Mengajarkan Anda untuk menulis strategi -- transplantasi strategi MyLanguage (Advanced)

Penulis:Lydia, Dibuat: 2022-12-26 18:56:00, Diperbarui: 2023-09-20 09:46:34

img

Ajarkan Anda untuk menulis strategi transplantasi strategi MyLanguage (Advanced)

Dalam artikel sebelumnyaMengajarkan Anda untuk menulis strategi -- menanam strategi MyLanguage, strategi MyLanguage sederhana telah diuji untuk transplantasi. Jika itu adalah MyLanguage yang lebih kompleks, bagaimana bisa ditransplantasikan ke dalam strategi bahasa JavaScript?

Mari kita lihat strategi yang akan ditransplantasikan terlebih dahulu:

(*backtest
start: 2019-05-01 00:00:00
end: 2019-11-12 00:00:00
period: 1d
exchanges: [{"eid":"Futures_OKCoin","currency":"BTC_USD"}]
args: [["SlideTick",10,126961],["ContractType","quarter",126961]]
*)

N1:=10;
N2:=21;
AP:=(HIGH+LOW+CLOSE)/3;
ESA:=EMA(AP,N1);
D:=EMA(ABS(AP-ESA),N1);
CI:=(AP-ESA)/(0.015*D);
TCI:=EMA(CI,N2);
WT1:TCI;
WT2:SMA(WT1,4,1);
AA:=CROSS(WT1,WT2);
BB:=CROSSDOWN(WT1,WT2);
REF(AA,1),BPK;
REF(BB,1),SPK;

Peraturan(* backtest... *)Pada awal strategi MyLanguage adalah kode konfigurasi untuk pengaturan backtesting. Untuk memudahkan perbandingan, konfigurasi backtesting terpadu ditetapkan. Strategi ini juga acak, yang tidak terlalu kompleks (lebih kompleks daripada yang ada dalam artikel sebelumnya). Ini adalah strategi representatif. Untuk menanamkan strategi MyLanguage, Anda harus melihat seluruh strategi terlebih dahulu. Kode strategi ringkas, dan Anda dapat memiliki pemahaman tertentu tentang keseluruhan strategi. Untuk strategi ini, kami telah melihat bahwa beberapa fungsi indikatorEMA, SMAtelah digunakan:

Bangun roda dulu

  • EMA Fungsi indikator, ada fungsi perpustakaan indikator siap pakai yang tersedia langsung di platform FMZ saat menulis strategi dalam bahasa JavaScript. yaitu:TA.MA.

  • SMA Apa yang harus kita lakukan adalahSMAindikator, yang kami temukan di perpustakaan TA FMZ tidak mendukung fungsi indikator SMA, dan ada perbedaan antara indikator SMA di perpustakaan talib dan yang di MyLanguage.

img

Seperti yang kita lihat, bagian parameter memiliki parameter bobot selain parameter periode.

Fungsi indikator SMA di perpustakaan talib dalam dokumentasi FMZ API dijelaskan sebagai berikut:

img

Hal ini dapat dilihat bahwatalib.SMAadalah indikator rata-rata bergerak sederhana. Dengan cara ini, kita hanya dapat menerapkan SMA sendiri. Sebagai pengembang yang menggunakan bahasa JavsScript untuk menulis strategi, ini juga merupakan salah satu keterampilan yang diperlukan. Lagi pula, jika tidak ada roda siap pakai, program masih perlu dijalankan, hanya membangun satu.

Untuk mengatakan kebenaran, tidak banyak penelitian tentang indikator dan sebagainya. umumnya, orang mencari informasi jika mereka tidak mengerti. untuk SMA untuk menemukan ini:

img

Tampaknya proses algoritma dari teori ini cukup dapat diandalkan, dan implementasinya adalah sebagai berikut:

function SMA (arr, n, m) {
    var sma = []
    var currSMA = null
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] && !isNaN(arr[i])) {
            if (!currSMA) {
                currSMA = arr[i]
                sma.push(currSMA)
                continue
            }  

            // [M*C2+(N-M)*S1]/N
            currSMA = (m * arr[i] + (n - m) * currSMA) / n
            sma.push(currSMA)
        } else {
            sma.push(NaN)
        }
    }  

    return sma
}

Tulis bagian penuh

Kerangka kerja strategi menggunakan kerangka kerja yang sama seperti dalam artikelMengajarkan Anda untuk menulis strategi -- menanam strategi MyLanguagedan terutama diisi dalam dua bagian:

Pertama, lakukan pengolahan data ticker dan perhitungan indeks.

img

Mari kita ambil bagian ini dari MyLanguage satu kalimat pada suatu waktu, fungsi demi fungsi:

    1. AP:=(HIGH+LOW+CLOSE)/3;

Hal ini dapat dipahami bahwa harga tertinggi, harga terendah dan harga penutupan dari setiap BAR dalam data baris K harus ditambahkan dan kemudian dibagi dengan 3 untuk menghitung nilai rata-rata, dan kemudian disimpan sebagai array, yang sesuai dengan setiap BAR satu per satu. Ini dapat diproses sebagai berikut:

function CalcAP (r) {   // AP:=(HIGH+LOW+CLOSE)/3;
    var arrAP = []      // Declare an empty array

    for (var i = 0; i < r.length; i++) {      // r is the incoming K-line data, which is an array, use for to traverse this array.
        v = (r[i].High + r[i].Low + r[i].Close) / 3      // Calculate the average value.
        arrAP.push(v)                                    // Add to the end of the arrAP array, the end is the first when arrAP is empty.
    }  

    return arrAP     // Returns this average array, i.e., the AP calculated in the MyLanguage 
}

Fungsi ini dapat dipanggil dalam fungsi OnTick loop utama, misalnya:

// Calculation of indicators
// AP
var ap = CalcAP(records)
    1. Setelah perhitungan AP selesai, lanjutkan untuk menghitungESA:=EMA(AP,N1);:

Di sini, kita akan menggunakan data AP yang dihitung pada langkah sebelumnya untuk menghitung ESA. sebenarnya, ESA adalah eksponensial moving average dari AP, yaitu indikator EMA. jadi kita akan menggunakan AP sebagai data dan N1 sebagai parameter indikator EMA untuk menghitung indikator EMA.

function CalcESA (ap, n1) {   // ESA:=EMA(AP,N1);
    if (ap.length <= n1) {    // If the AP length is less than the indicator parameter, valid data cannot be calculated. At this time, let the function return false.
        return false
    }  

    return TA.EMA(ap, n1)
}
    1. D:=EMA(ABS(AP-ESA),N1);

Menggunakan perhitunganAP, ESAuntuk menghitung dataDAku tidak tahu. Komentar kode di sini dapat dibaca untuk beberapa tips tentang cara menghitung indikator.

function CalcD (ap, esa, n1) {    // D:=EMA(ABS(AP-ESA),N1);
    var arrABS_APminusESA = []
    if (ap.length != esa.length) {
        throw "ap.length != esa.length"
    }  

    for (var i = 0; i < ap.length; i++) {
        // When calculating the value of the indicator, it is necessary to determine the validity of the data, because the first few EMA calculations may be the beginning of the array of data is NaN, or null.
        // So it must be judged that the data involved in the calculation are all valid values to proceed, and if there are any invalid values, they are filled with NaN to arrABS_APminusESA.
        // The data thus calculated, each position corresponds to the previous data one by one, without misalignment.
        if (ap[i] && esa[i] && !isNaN(ap[i]) && !isNaN(esa[i])) {
            v = Math.abs(ap[i] - esa[i])     // According to ABS(AP-ESA), the specific value is calculated and put into the arrABS_APminusESA array.
            arrABS_APminusESA.push(v)
        } else {
            arrABS_APminusESA.push(NaN)
        }
    }  

    if (arrABS_APminusESA.length <= n1) {
        return false
    }  

    return TA.EMA(arrABS_APminusESA, n1)    // Calculate the EMA indicator of the array arrABS_APminusESA and get the data D (array structure).
}
    1. CI:=(AP-ESA)/(0.015*D);Metode perhitungan mirip dengan langkah 1, dan kode dirilis langsung.
function CalcCI (ap, esa, d) {    // CI:=(AP-ESA)/(0.015*D);
    var arrCI = []
    if (ap.length != esa.length || ap.length != d.length) {
        throw "ap.length != esa.length || ap.length != d.length"
    }
    for (var i = 0; i < ap.length; i++) {
        if (ap[i] && esa[i] && d[i] && !isNaN(ap[i]) && !isNaN(esa[i]) && !isNaN(d[i])) {
            v = (ap[i] - esa[i]) / (0.015 * d[i])
            arrCI.push(v)
        } else {
            arrCI.push(NaN)
        }
    }  

    if (arrCI.length == 0) {
        return false
    }  

    return arrCI
}
  • TCI:=EMA(CI,N2); Hanya menghitung indikator EMA untuk array CI.
function CalcTCI (ci, n2) {   // TCI:=EMA(CI,N2);
    if (ci.length <= n2) {
        return false
    }  

    return TA.EMA(ci, n2)
}
  • WT2:SMA(WT1,4,1);

Pada langkah terakhir ini, fungsi SMA dari roda yang kita bangun sebelumnya digunakan.

function CalcWT2 (wt1) {    // WT2:SMA(WT1,4,1);
    if (wt1.length <= 4) {
        return false 
    }  

    return SMA(wt1, 4, 1)   // The SMA indicator for wt1 is calculated by using our own implementation of the SMA function.
}

Translating sinyal perdagangan sangat sederhana.

AA:=CROSS(WT1,WT2);
BB:=CROSSDOWN(WT1,WT2);
REF(AA,1),BPK;
REF(BB,1),SPK;

Setelah membaca kode-kode MyLanguage ini, kita dapat melihat bahwa Golden Cross dan Bearish Crossover dari WT1 dan WT2 digunakan sebagai kondisi pembukaan. Menggunakan backtest strategi MyLanguage secara langsung, kita mengamati bahwa:

img

Hal ini dapat dilihat dari pengamatan operasi sebenarnya dari strategi MyLanguage bahwa ketika sinyal terdeteksi di posisi pembukaan, itu sebenarnya untuk mendeteksi apakah posisi BAR di titik pembukaan menghitung 2 BAR ke depan adalah Golden Cross.

img img

Kode pengisian bagian deteksi sinyal dapat ditulis sebagai berikut:

if ((_State == IDLE || _State == SHORT) && wt1[wt1.length - 4] < wt2[wt2.length - 4] && wt1[wt1.length - 3] > wt2[wt2.length - 3]) {
    if (_State == IDLE) {
        _State = OPENLONG
        Log("OPENLONG")    // test
    }
    if (_State == SHORT) {
        _State = COVERSHORT
        Log("COVERSHORT")  // test
    }
    isOK = false  
}

if ((_State == IDLE || _State == LONG) && wt1[wt1.length - 4] > wt2[wt2.length - 4] && wt1[wt1.length - 3] < wt2[wt2.length - 3]) {
    if (_State == IDLE) {
        _State = OPENSHORT
        Log("OPENSHORT")  // test
    }
    if (_State == LONG) {
        _State = COVERLONG
        Log("COVERLONG")  // test
    }
    isOK = false   
}

Di sini Anda dapat berpikir tentang mengapa instruksi SPK dan BPK dari MyLanguage dapat diterapkan dengan kode di atas.

Backtest

Konfigurasi backtest:

img

Backtest di MyLanguage:

img

Backtest dalam versi JavaScript:

img img

Kode pada awal fungsi OnTick digunakan untuk membuat backtesting lebih cepat. Ini digunakan untuk menjalankan strategi berdasarkan model Bar. Jika Anda tertarik, Anda dapat menganalisisnya secara rinci.

function OnTick(){
    // The ticker processing part of the driving strategy.
    var records = _C(exchange.GetRecords)
    if (records[records.length - 1].Time == preTime) {
        if (isOK) {
            Sleep(500)
            return 
        }
    } else {
        preTime = records[records.length - 1].Time
    }
    ...
    ..
    .

Kode strategi pengajaran lengkap:https://www.fmz.com/strategy/174457

Terima kasih sudah membaca.


Lebih banyak