Les ressources ont été chargées... Je charge...

La main qui vous apprend à écrire des stratégies -- transférer une stratégie dans ma langue.

Auteur:L'inventeur de la quantification - un petit rêve, Créé: 2019-10-21 14:59:12, Mis à jour: 2023-10-17 21:22:56

img

La main qui vous apprend à écrire des stratégies et qui vous transplante une stratégie dans votre langue

Récemment, en discutant avec des amis sur les stratégies, j'ai découvert qu'il y avait beaucoup de problèmes de flexibilité avec les stratégies de rédaction de my language. Dans de nombreux cas, il est nécessaire d'utiliser des cycles de lignes K standard fournis par des non-systèmes, par exemple, le plus souvent demandé est d'utiliser des lignes K de 4 heures. Ce problème a été résolu dans un article.Les liensMais le problème avec les stratégies my est que les données ne peuvent pas être traitées de manière flexible par les stratégies my, car elles sont hautement condensées.

Pour le portage de la stratégie de tendance, il est très simple d'utiliser un code d'exemple pour remplir une partie du code de calcul des données qui conduit à la stratégie, remplissant les conditions de déclenchement du signal de transaction.

Code de l'exemple réutilisable:

Les stratégies utilisées pour les contrats à terme sur l'OKEX sont des exemples.

// 全局变量
var IDLE = 0
var LONG = 1
var SHORT = 2
var OPENLONG = 3
var OPENSHORT = 4
var COVERLONG = 5
var COVERSHORT = 6  

var BREAK = 9
var SHOCK = 10  

var _State = IDLE
var Amount = 0                 // 记录持仓数量
var TradeInterval = 500        // 轮询间隔
var PriceTick = 1              // 价格一跳
var Symbol = "this_week"  

function OnTick(){
    // 驱动策略的行情处理部分
    // 待填充...
     
    // 交易信号触发处理部分
    // 待填充...  

    // 执行交易逻辑
    var pos = null
    var price = null
    var currBar = records[records.length - 1]
    if(_State == OPENLONG){
        pos = GetPosition(PD_LONG)
        // 判断是不是 满足状态,如果满足 修改状态
        if(pos[1] >= Amount){
            _State = LONG
            Amount = pos[1]   // 更新实际量
            return
        }
        price = currBar.Close - (currBar.Close % PriceTick) + PriceTick * 2
        Trade(OPENLONG, price, Amount - pos[1], pos, PriceTick)                // (Type, Price, Amount, CurrPos, PriceTick)
    }  

    if(_State == OPENSHORT){
        pos = GetPosition(PD_SHORT)
        if(pos[1] >= Amount){
            _State = SHORT
            Amount = pos[1]   // 更新实际量
            return
        }
        price = currBar.Close - (currBar.Close % PriceTick) - PriceTick * 2
        Trade(OPENSHORT, price, Amount - pos[1], pos, PriceTick)
    }  

    if(_State == COVERLONG){
        pos = GetPosition(PD_LONG)
        if(pos[1] == 0){
            _State = IDLE
            return
        }
        price = currBar.Close - (currBar.Close % PriceTick) - PriceTick * 2
        Trade(COVERLONG, price, pos[1], pos, PriceTick)
    }
    
    if(_State == COVERSHORT){
        pos = GetPosition(PD_SHORT)
        if(pos[1] == 0){
            _State = IDLE
            return
        }
        price = currBar.Close - (currBar.Close % PriceTick) + PriceTick * 2
        Trade(COVERSHORT, price, pos[1], pos, PriceTick)
    }
}  

// 交易逻辑部分
function GetPosition(posType) {
    var positions = _C(exchange.GetPosition)
    var count = 0
    for(var j = 0; j < positions.length; j++){
        if(positions[j].ContractType == Symbol){
            count++
        }
    }  

    if(count > 1){
        throw "positions error:" + JSON.stringify(positions)
    }  

    for (var i = 0; i < positions.length; i++) {
        if (positions[i].ContractType == Symbol && positions[i].Type === posType) {
            return [positions[i].Price, positions[i].Amount];
        }
    }
    Sleep(TradeInterval);
    return [0, 0];
}  

function CancelPendingOrders() {
    while (true) {
        var orders = _C(exchange.GetOrders)
        for (var i = 0; i < orders.length; i++) {
            exchange.CancelOrder(orders[i].Id);
            Sleep(TradeInterval);
        }
        if (orders.length === 0) {
            break;
        }
    }
}  

function Trade(Type, Price, Amount, CurrPos, OnePriceTick){    // 处理交易
    if(Type == OPENLONG || Type == OPENSHORT){                 // 处理开仓
        exchange.SetDirection(Type == OPENLONG ? "buy" : "sell")
        var pfnOpen = Type == OPENLONG ? exchange.Buy : exchange.Sell
        var idOpen = pfnOpen(Price, Amount, CurrPos, OnePriceTick, Type)
        Sleep(TradeInterval)
        if(idOpen) {
            exchange.CancelOrder(idOpen)
        } else {
            CancelPendingOrders()
        }
    } else if(Type == COVERLONG || Type == COVERSHORT){        // 处理平仓
        exchange.SetDirection(Type == COVERLONG ? "closebuy" : "closesell")
        var pfnCover = Type == COVERLONG ? exchange.Sell : exchange.Buy
        var idCover = pfnCover(Price, Amount, CurrPos, OnePriceTick, Type)
        Sleep(TradeInterval)
        if(idCover){
            exchange.CancelOrder(idCover)
        } else {
            CancelPendingOrders()
        }
    } else {
        throw "Type error:" + Type
    }
}  

function main() { 
    // 设置合约
    exchange.SetContractType(Symbol)  

    while(1){
        OnTick()
        Sleep(1000)
    }
}

Exemple: le transfert de la stratégie à double équilibre

Il y a aussi des gens qui ont été victimes de violences.img

Le code stratégique de la langue Ma:

MA5^^MA(C,5);
MA15^^MA(C,15);
CROSSUP(MA5,MA15),BPK;
CROSSDOWN(MA5,MA15),SPK;

Porte à la stratégie JavaScript

Tout d'abord, remplissez la section d'accès au marché et de calcul des indicateurs pour le code de l'exemple réutilisable:

// 驱动策略的行情处理部分
var records = _C(exchange.GetRecords)  

if (records.length < 15) {
    return 
}  

var ma5 = TA.MA(records, 5)
var ma15 = TA.MA(records, 15)
var ma5_pre = ma5[ma5.length - 3]
var ma15_pre = ma15[ma15.length - 3]
var ma5_curr = ma5[ma5.length - 2]
var ma15_curr = ma15[ma15.length - 2]

Vous pouvez voir que la stratégie de la double ligne droite est très simple, il suffit d'obtenir les données de la ligne K.recordset utilisezTA函数库La fonction homogène deTA.MAOn peut calculer la ligne moyenne de 5 jours, la ligne moyenne de 15 jours (vous pouvez voir sur l'interface de retouche que la période de la ligne K est définie par la ligne K du jour, doncTA.MA(records, 5)Les chiffres sont calculés sur la moyenne de cinq jours.TA.MA(records, 15)Il y a aussi des gens qui ont été victimes de violences. et puis obtenirma5Le deuxième point négatif de l'indicateurma5_curr(valeur de l'indicateur), le troisième point du compteurma5_preLe nombre de personnes atteintes de cette maladie est en hausse.ma15Les données de l'indicateur sont analogues. On peut ensuite utiliser ces données pour juger de la fourchette morte, comme le montre le graphique:imgIl y a une sorte de "forc à mort" qui se forme dès qu'il y a un tel état.

La partie qui juge le signal peut être écrite comme suit:

if(_State == IDLE && ma5_pre < ma15_pre && ma5_curr > ma15_curr){     
    _State = OPENLONG
    Amount = 1
}  

if(_State == IDLE && ma5_pre > ma15_pre && ma5_curr < ma15_curr){     
    _State = OPENSHORT
    Amount = 1
}  

if(_State == LONG && ma5_pre > ma15_pre && ma5_curr < ma15_curr){     
    _State = COVERLONG
    Amount = 1
}  

if(_State == SHORT && ma5_pre < ma15_pre && ma5_curr > ma15_curr){     
    _State = COVERSHORT
    Amount = 1
}

Il y a un problème avec le transfert de sang, et il est normal de le refaire: Réévaluation de la stratégie JavaScript Les paramètres de détection:img

回测结果:
![img](/upload/asset/16baa65d35e034e06a58.png) 

Mon langage est en train de changerimg

On peut voir les résultats de la retouche essentiellement les mêmes, ce qui est possible si l'on souhaite continuer à ajouter des fonctionnalités d'interaction pour les stratégies, ajouter du traitement de données (par exemple la synthèse de lignes K), ajouter des graphiques graphiques personnalisés.

Les élèves intéressés peuvent essayer.


Relationnée

Plus de

Le petitEn apprentissage