Sie lernen, Strategien zu schreiben -- transplantieren Sie eine MyLanguage-Strategie

Schriftsteller:Lydia., Erstellt: 2022-12-26 15:23:08, aktualisiert: 2023-09-13 19:44:28

img

Sie lernen Strategien zu schreiben eine MyLanguage-Strategie zu transplantieren

Vor kurzem, als ich mit meinen Freunden über Strategien sprach, erfuhr ich, dass viele Strategien, die in MyLanguage geschrieben wurden, an Flexibilität leiden. In vielen Fällen ist es notwendig, die Standard-K-Linie-Periode zu verwenden, die vom System nicht bereitgestellt wird. Zum Beispiel ist die maximale Anforderung, die K-Linie für 4 Stunden zu verwenden. Dieses Problem wurde in einem Artikel gelöst. Wenn Sie interessiert sind, schauen Sie sich bitte an:VerknüpfungIn der MyLanguage-Strategie ist es jedoch aufgrund der hohen Verkapselungsfunktion von MyLanguage nicht flexibel, Daten alleine zu verarbeiten.

Es ist sehr einfach für die Trendstrategie Transplantation. wir können einen Beispielcode verwenden, um den Datenberechnungsteil des Codes, der die Strategie antreibt, auszufüllen und die Handelssignal-Triggerbedingungen auszufüllen.

Wiederverwendbarer Mustercode:

Nehmen wir zum Beispiel die Strategie für OKX-Futures.

// Global variables
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                 // Record the number of positions
var TradeInterval = 500        // Polling intervals
var PriceTick = 1              // Price per jump
var Symbol = "this_week"  

function OnTick(){
    // Ticker processing part of the driving strategy
    // To be filled...
     
    // Trading signal trigger processing section
    // To be filled...  

    // Execution of trading logic
    var pos = null
    var price = null
    var currBar = records[records.length - 1]
    if(_State == OPENLONG){
        pos = GetPosition(PD_LONG)
        // Determine whether the state is satisfied, and if so, modify the state.
        if(pos[1] >= Amount){
            _State = LONG
            Amount = pos[1]   // Update the actual volume.
            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]   // Update the actual volume.
            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)
    }
}  

// Trading logic section
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){    // Processing transactions
    if(Type == OPENLONG || Type == OPENSHORT){                 // Processing of opening positions
        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){        // Processing of closing positions
        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() { 
    // Set up the contract
    exchange.SetContractType(Symbol)  

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

Beispiel: Transplantation einer doppelten EMA-Strategie

MyLanguage Backtest:

img

MyLanguage-Strategiecode:

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

Transplantieren auf JavaScript-Strategie

Zunächst müssen die Teile für die Tickeraufnahme und die Indikatorberechnung für den wiederverwendbaren Mustercode ausgefüllt werden:

// The ticker processing part of the driving strategy
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]

Wie Sie sehen können, ist die doppelte EMA-Strategie sehr einfach.records, und dann die Funktion EMA verwendenTA.MAvonTA function libraryUm die 5-tägige EMA und die 15-tägige EMA zu berechnen (wie wir in der Backtest-Schnittstelle sehen können, ist die K-Linienperiode auf die tägliche K-Line gesetzt, alsoTA.MA(records, 5)ist die Berechnung der 5-tägigen EMA,TA.MA(records, 15)Der 15-Tage-EMA wird berechnet). Dann kriegen Sie den vorletzten Punktma5_curr(Indikatorwert), der letzte dritte Punktma5_pre(Indikatorwert) der Indikatordatenma5, und dasselbe für diema15Dann können wir diese Indikatordaten verwenden, um das Goldene Kreuz und den Bearish Crossover zu beurteilen, wie in der Abbildung gezeigt:

img

Wann immer ein solcher Zustand entsteht, ist es ein bestimmtes Goldenes Kreuz oder ein Bärenkreuz.

Dann kann der Teil der Beurteilung des Signals wie folgt geschrieben werden:

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
}

Auf diese Weise ist die Transplantation in Ordnung. Backtesting der JavaScript-Strategie Konfiguration der Rückprüfung:

img

Rückprüfungsergebnis:

img

Backtesting von MyLanguage

img

Wenn Sie weiterhin interaktive Funktionen, Datenverarbeitung (z. B. K-Liniensynthese) und maßgeschneiderte Diagrammdarstellung der Strategie hinzufügen möchten, können Sie dies erreichen.

Wenn Sie interessiert sind, versuchen Sie es bitte.


Verwandt

Mehr