Mengajarkan Anda untuk menulis strategi -- menanam strategi MyLanguage

Penulis:Lydia, Dibuat: 2022-12-26 15:23:08, Diperbarui: 2023-09-13 19:44:28

img

Ajarkan Anda menulis strategi menanamkan strategi MyLanguage

Baru-baru ini, ketika berbicara tentang strategi dengan teman-teman saya, saya belajar bahwa banyak strategi yang ditulis dalam MyLanguage menderita fleksibilitas. Dalam banyak kasus, perlu menggunakan periode K-line standar yang tidak disediakan oleh sistem. Misalnya, persyaratan maksimum adalah menggunakan K-line selama 4 jam. Masalah ini telah diselesaikan dalam sebuah artikel. Jika Anda tertarik, silakan lihat:TautanNamun, dalam strategi MyLanguage, karena fitur enkapsulasi tinggi dari MyLanguage, tidak fleksibel untuk memproses data sendiri. Pada saat ini, perlu untuk mentransplantasikan ide strategi ke bahasa lain.

Ini sangat sederhana untuk transplantasi strategi tren. kita dapat menggunakan kode contoh untuk mengisi bagian perhitungan data dari kode yang mendorong strategi, dan mengisi kondisi pemicu sinyal perdagangan.

Kode sampel yang dapat digunakan kembali:

Ambil strategi untuk OKX berjangka sebagai contoh.

// 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)
    }
}

Contoh: Transplantasi strategi EMA ganda

MyLanguage backtest:

img

Kode strategi MyLanguage:

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

Transplantasi ke Strategi JavaScript

Pertama, isi bagian akuisisi ticker dan perhitungan indikator untuk kode sampel yang dapat digunakan kembali:

// 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]

Seperti yang Anda lihat, strategi EMA ganda sangat sederhana. pertama, mendapatkan data K-linerecords, dan kemudian gunakan fungsi EMATA.MAdariTA function libraryuntuk menghitung EMA 5 hari dan EMA 15 hari (seperti yang dapat kita lihat di antarmuka backtest, periode K-line diatur ke K-line harian, jadiTA.MA(records, 5)adalah untuk menghitung EMA 5 hari,TA.MA(records, 15)adalah untuk menghitung EMA 15 hari). Kemudian mendapatkan titik penutupma5_curr(nilai indikator), titik ketiga terakhirma5_pre(nilai indikator) dari data indikatorma5, dan sama untukma15Kemudian kita dapat menggunakan data indikator ini untuk menilai Golden Cross dan Bearish Crossover, seperti yang ditunjukkan pada gambar:

img

Setiap kali keadaan seperti itu terbentuk, itu pasti Golden Cross atau Bearish Crossover.

Kemudian bagian menilai sinyal dapat ditulis sebagai berikut:

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
}

Dengan cara ini, transplantasi tidak apa-apa. Backtesting strategi JavaScript Konfigurasi backtesting:

img

Hasil pengujian balik:

img

Backtesting dari MyLanguage

img

Dengan cara ini, jika Anda ingin terus menambahkan fungsi interaktif, pemrosesan data (seperti sintesis K-line), dan tampilan grafik yang disesuaikan ke strategi, Anda dapat mencapai ini.

Jika Anda tertarik, silakan coba.


Berkaitan

Lebih banyak