avatar of 发明者量化-小小梦 发明者量化-小小梦
Suivre Messages privés
4
Suivre
1271
Abonnés

Je vous apprends à écrire des stratégies étape par étape - transplantez ma stratégie linguistique

Créé le: 2019-10-21 14:59:12, Mis à jour le: 2024-12-17 20:37:18
comments   1
hits   2733

Je vous apprends à écrire des stratégies étape par étape - transplantez ma stratégie linguistique

Je vous apprends à écrire des stratégies étape par étape - transplantez ma stratégie linguistique

Alors que je discutais récemment de stratégies avec mes amis, j’ai appris que de nombreuses personnes qui utilisent mon langage pour écrire des stratégies souffrent du problème de flexibilité. Dans de nombreux cas, il est nécessaire d’utiliser une période K-line standard qui n’est pas fournie par le système. Par exemple, l’exigence la plus fréquemment demandée est d’utiliser une ligne K de 4 heures. Ce problème a été résolu dans un article. Si cela vous intéresse, vous pouvez d’abord y jeter un œil :Lien. Cependant, dans la stratégie de mon langage, en raison de la nature hautement encapsulée du langage, ce problème ne peut pas traiter les données de manière flexible par lui-même. À l’heure actuelle, il est nécessaire de transplanter la pensée stratégique dans d’autres langages.

Il est très simple de transplanter des stratégies de tendance. Nous pouvons utiliser un exemple de code pour remplir la partie calcul des données de la stratégie de pilotage et remplir les conditions de déclenchement du signal de trading.

Exemple de code réutilisable :

Prenons comme exemple la stratégie utilisée pour les contrats à terme OKEX.

// 全局变量
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 : Transplantation de la stratégie de la double moyenne mobile

Backtest du langage Mai : Je vous apprends à écrire des stratégies étape par étape - transplantez ma stratégie linguistique

Code de stratégie de la langue Mai :

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

Stratégie de migration vers JavaScript

Tout d’abord, remplissez les parties acquisition de marché et calcul d’indicateur dans l’exemple de code 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]

Comme vous pouvez le constater, la stratégie de la double moyenne mobile est très simple. Il suffit d’obtenir d’abord les données de la ligne K.records, puis utilisezTA函数库Fonction de moyenne mobileTA.MACalculez la moyenne mobile sur 5 jours et la moyenne mobile sur 15 jours (vous pouvez voir sur l’interface de backtest que la période de la ligne K est définie sur la ligne K quotidienne, doncTA.MA(records, 5)La moyenne mobile sur 5 jours est calculée.TA.MA(records, 15)(Moyenne mobile sur 15 jours). Alors, prendsma5L’avant-dernier point des données de l’indicateurma5_curr(Valeur indicatrice), du troisième au dernier pointma5_pre(Valeur indicatrice),ma15Il en va de même pour les données des indicateurs. Vous pouvez ensuite utiliser ces données indicatrices pour juger la croix dorée et la croix morte, comme indiqué dans la figure : Je vous apprends à écrire des stratégies étape par étape - transplantez ma stratégie linguistique Tant qu’un tel état est formé, c’est une croix d’or confirmée ou une croix morte.

La partie jugement du signal peut alors s’écrire 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
}

Cela signifie que la greffe est OK et que vous pouvez revenir en arrière et la tester : Stratégies de backtesting JavaScript Configuration du backtest : Je vous apprends à écrire des stratégies étape par étape - transplantez ma stratégie linguistique

回测结果:
![Je vous apprends à écrire des stratégies étape par étape - transplantez ma stratégie linguistique](/upload/asset/16baa65d35e034e06a58.png) 

Backtesting de mon langage Je vous apprends à écrire des stratégies étape par étape - transplantez ma stratégie linguistique

On peut voir que les résultats des backtests sont fondamentalement les mêmes, donc si vous souhaitez continuer à ajouter des fonctions interactives à la stratégie, ajouter un traitement de données (comme la synthèse K-line) et ajouter un dessin et un affichage de graphiques personnalisés, vous pouvez le faire il.

Les étudiants intéressés peuvent l’essayer.