Mengajar anda untuk merancang perpustakaan kelas templat untuk mendapatkan data K-garis panjang tertentu

Penulis:Lydia, Dicipta: 2023-06-29 17:27:59, Dikemas kini: 2023-09-18 19:33:33

img

Mengajar anda untuk merancang perpustakaan kelas templat untuk mendapatkan data K-garis panjang tertentu

Apabila merancang strategi trend, sering kali perlu mempunyai bilangan bar K-line yang mencukupi untuk mengira penunjuk.exchange.GetRecords()fungsi dalam API platform FMZ, yang merupakan bungkus untuk antara muka K-line pertukaran. Dalam reka bentuk awal API pertukaran mata wang kripto, tidak ada sokongan untuk paginasi dalam antara muka K-line, dan antara muka K-line pertukaran hanya menyediakan sejumlah data yang terhad. Akibatnya, beberapa pemaju tidak dapat memenuhi keperluan untuk mengira penunjuk dengan nilai parameter yang lebih besar.

Antara muka K-line API kontrak Binance menyokong paginasi. Dalam artikel ini, kami akan menggunakan antara muka API K-line Binance sebagai contoh untuk mengajar anda cara melaksanakan paginasi dan menentukan bilangan bar untuk diambil menggunakan perpustakaan templat platform FMZ.

Antara muka K-line Binance

Data garis K

Waktu pembukaan setiap K-garis dalamGET /dapi/v1/klinesTitik akhir boleh dianggap sebagai ID unik.

Berat permintaan bergantung kepada nilai parameter LIMIT.

img

Parameter:

img

Pertama, kita perlu merujuk kepada dokumentasi API pertukaran untuk memahami parameter khusus antara muka K-line. Kita dapat melihat bahawa ketika memanggil titik akhir K-line ini, kita perlu menentukan jenis, tempoh K-line, julat data (waktu permulaan dan akhir), dan bilangan halaman, dll.

Oleh kerana keperluan reka bentuk kami adalah untuk menyoal sejumlah data K-line tertentu, sebagai contoh, untuk menyoal data K-line 1 jam, 5000 bar data K-line 1 jam dari masa kini ke masa lalu, jelas bahawa membuat panggilan API tunggal ke pertukaran tidak akan mendapatkan data yang dikehendaki.

Untuk mencapai ini, kita boleh melaksanakan pagination dan membahagikan pertanyaan ke dalam segmen dari masa kini ke masa sejarah tertentu. Oleh kerana kita tahu tempoh data K-line yang dikehendaki, kita boleh dengan mudah mengira masa permulaan dan akhir untuk setiap segmen. Kita kemudian boleh menanyakan setiap segmen secara berurutan ke arah masa sejarah sehingga kita mendapatkan bar yang cukup. Pendekatan terdengar mudah, jadi mari kita teruskan dan pelaksanaannya!

Reka bentuk Versi JavaScript query bertaburan K-line templat data sejarah

Fungsi antara muka untuk templat reka bentuk:$.GetRecordsByLength(e, period, length).

/**
 * desc: $.GetRecordsByLength is the interface function of this template library, this function is used to get the K-line data of the specified K-line length
 * @param {Object} e - exchange object
 * @param {Int} period - K-line period, in seconds
 * @param {Int} length - Specify the length of the acquired K-line data, which is related to the exchange interface limits
 * @returns {Array<Object>} - K-line data
 */

Reka bentuk fungsi$.GetRecordsByLength, yang biasanya digunakan pada peringkat awal pelaksanaan strategi untuk mengira penunjuk berdasarkan data K-line yang panjang. Setelah fungsi ini dijalankan dan data yang mencukupi diperoleh, hanya data K-line baru yang perlu dikemas kini. Tidak perlu memanggil fungsi ini lagi untuk mendapatkan data K-line yang terlalu panjang, kerana akan mengakibatkan panggilan API yang tidak perlu.

Oleh itu, ia juga perlu untuk merancang antara muka untuk kemas kini data berikutnya:$.UpdataRecords(e, records, period).

/**
 * desc: $.UpdataRecords is the interface function of this template library, this function is used to update the K-line data.
 * @param {Object} e - exchange object
 * @param {Array<Object>} records - K-line data sources that need to be updated
 * @param {Int} period - K-line period, needs to be the same as the K-line data period passed in the records parameter
 * @returns {Bool}  - Whether the update was successful
 */

Langkah seterusnya adalah untuk melaksanakan fungsi antara muka ini.

/**
 * desc: $.GetRecordsByLength is the interface function of this template library, this function is used to get the K-line data of the specified K-line length
 * @param {Object} e - exchange object
 * @param {Int} period - K-line period, in seconds
 * @param {Int} length - Specify the length of the acquired K-line data, which is related to the exchange interface limits
 * @returns {Array<Object>} - K-line data
 */
$.GetRecordsByLength = function(e, period, length) {
    if (!Number.isInteger(period) || !Number.isInteger(length)) {
        throw "params error!"
    }

    var exchangeName = e.GetName()
    if (exchangeName == "Futures_Binance") {
        return getRecordsForFuturesBinance(e, period, length)
    } else {
        throw "not support!"
    }
}

/**
 * desc: getRecordsForFuturesBinance, the specific implementation of the function to get K-line data for Binance Futures Exchange
 * @param {Object} e - exchange object
 * @param {Int} period - K-line period, in seconds
 * @param {Int} length - Specify the length of the acquired K-line data, which is related to the exchange interface limits
 * @returns {Array<Object>} - K-line data
 */
function getRecordsForFuturesBinance(e, period, length) {
    var contractType = e.GetContractType()
    var currency = e.GetCurrency()
    var strPeriod = String(period)

    var symbols = currency.split("_")
    var baseCurrency = ""
    var quoteCurrency = ""
    if (symbols.length == 2) {
        baseCurrency = symbols[0]
        quoteCurrency = symbols[1]
    } else {
        throw "currency error!"
    }

    var realCt = e.SetContractType(contractType)["instrument"]
    if (!realCt) {
        throw "realCt error"
    }
    
    // m -> minute; h -> hour; d -> day; w -> week; M -> month
    var periodMap = {}
    periodMap[(60).toString()] = "1m"
    periodMap[(60 * 3).toString()] = "3m"
    periodMap[(60 * 5).toString()] = "5m"
    periodMap[(60 * 15).toString()] = "15m"
    periodMap[(60 * 30).toString()] = "30m"
    periodMap[(60 * 60).toString()] = "1h"
    periodMap[(60 * 60 * 2).toString()] = "2h"
    periodMap[(60 * 60 * 4).toString()] = "4h"
    periodMap[(60 * 60 * 6).toString()] = "6h"
    periodMap[(60 * 60 * 8).toString()] = "8h"
    periodMap[(60 * 60 * 12).toString()] = "12h"
    periodMap[(60 * 60 * 24).toString()] = "1d"
    periodMap[(60 * 60 * 24 * 3).toString()] = "3d"
    periodMap[(60 * 60 * 24 * 7).toString()] = "1w"
    periodMap[(60 * 60 * 24 * 30).toString()] = "1M"
    
    var records = []
    var url = ""
    if (quoteCurrency == "USDT") {
        // GET https://fapi.binance.com  /fapi/v1/klines  symbol , interval , startTime , endTime , limit 
        // limit maximum value:1500

        url = "https://fapi.binance.com/fapi/v1/klines"
    } else if (quoteCurrency == "USD") {
        // GET https://dapi.binance.com  /dapi/v1/klines  symbol , interval , startTime , endTime , limit
        // The difference between startTime and endTime can be up to 200 days.
        // limit maximum value:1500

        url = "https://dapi.binance.com/dapi/v1/klines"
    } else {
        throw "not support!"
    }

    var maxLimit = 1500
    var interval = periodMap[strPeriod]
    if (typeof(interval) !== "string") {
        throw "period error!"
    }

    var symbol = realCt
    var currentTS = new Date().getTime()

    while (true) {
        // Calculate limit
        var limit = Math.min(maxLimit, length - records.length)
        var barPeriodMillis = period * 1000
        var rangeMillis = barPeriodMillis * limit
        var twoHundredDaysMillis = 200 * 60 * 60 * 24 * 1000
        
        if (rangeMillis > twoHundredDaysMillis) {
            limit = Math.floor(twoHundredDaysMillis / barPeriodMillis)
            rangeMillis = barPeriodMillis * limit
        }

        var query = `symbol=${symbol}&interval=${interval}&endTime=${currentTS}&limit=${limit}`
        var retHttpQuery = HttpQuery(url + "?" + query)
        
        var ret = null 
        try {
            ret = JSON.parse(retHttpQuery)
        } catch(e) {
            Log(e)
        }
        
        if (!ret || !Array.isArray(ret)) {
            return null
        }

        // When the data cannot be searched because it is beyond the searchable range of the exchange
        if (ret.length == 0 || currentTS <= 0) {
            break
        }

        for (var i = ret.length - 1; i >= 0; i--) {
            var ele = ret[i]
            var bar = {
                Time : parseInt(ele[0]),
                Open : parseFloat(ele[1]),
                High : parseFloat(ele[2]),
                Low : parseFloat(ele[3]), 
                Close : parseFloat(ele[4]),
                Volume : parseFloat(ele[5])
            }

            records.unshift(bar)
        }

        if (records.length >= length) {
            break
        }

        currentTS -= rangeMillis
        Sleep(1000)
    }

    return records
}

/**
 * desc: $.UpdataRecords is the interface function of this template library, this function is used to update the K-line data.
 * @param {Object} e - exchange object
 * @param {Array<Object>} records - K-line data sources that need to be updated
 * @param {Int} period - K-line period, needs to be the same as the K-line data period passed in the records parameter
 * @returns {Bool}  - Whether the update was successful
 */
$.UpdataRecords = function(e, records, period) {
    var r = e.GetRecords(period)
    if (!r) {
        return false 
    }

    for (var i = 0; i < r.length; i++) {
        if (r[i].Time > records[records.length - 1].Time) {
            // Add a new Bar
            records.push(r[i])
            // Update the previous Bar
            if (records.length - 2 >= 0 && i - 1 >= 0 && records[records.length - 2].Time == r[i - 1].Time) {
                records[records.length - 2] = r[i - 1]
            }            
        } else if (r[i].Time == records[records.length - 1].Time) {
            // Update Bar
            records[records.length - 1] = r[i]
        }
    }
    return true
}

Dalam templat, kita hanya melaksanakan sokongan untuk kontrak niaga hadapan Binance antara muka K-garis, iaitu,getRecordsForFuturesBinanceIa juga boleh diperluaskan untuk menyokong antara muka K-line pertukaran cryptocurrency lain.

Sesi Ujian

Seperti yang anda lihat, kod untuk melaksanakan fungsi ini dalam templat tidak luas, berjumlah kurang daripada 200 baris. Selepas menulis kod templat, ujian adalah penting dan tidak boleh diabaikan.

Untuk mengujinya, anda perlu menyalin kedua-dua JavaScript Versi Pagination Query K-Line Template Data Sejarah dan Plot Library templat ke perpustakaan strategi anda (yang boleh didapati diStrategy SquareKemudian, buat strategi baru dan pilih dua templat ini.

img

img

Plot Library digunakan, kerana kita perlu menarik data K-line yang diperoleh untuk pemerhatian.

function main() {
	LogReset(1)
	var testPeriod = PERIOD_M5
    Log("Current exchanges tested:", exchange.GetName())

    // If futures, you need to set up a contract
    exchange.SetContractType("swap")

    // Get K-line data of specified length using $.GetRecordsByLength
    var r = $.GetRecordsByLength(exchange, testPeriod, 8000)
    Log(r)

    // Use the Plot test for easy observation
    $.PlotRecords(r, "k")

    // Test data
    var diffTime = r[1].Time - r[0].Time 
    Log("diffTime:", diffTime, " ms")
    for (var i = 0; i < r.length; i++) {
        for (var j = 0; j < r.length; j++) {
            // Check the repeat bar
            if (i != j && r[i].Time == r[j].Time) {
                Log(r[i].Time, i, r[j].Time, j)
                throw "With duplicate Bar"
            }
        }
        
        // Check Bar continuity
        if (i < r.length - 1) {            
            if (r[i + 1].Time - r[i].Time != diffTime) {
                Log("i:", i, ", diff:", r[i + 1].Time - r[i].Time, ", r[i].Time:", r[i].Time, ", r[i + 1].Time:", r[i + 1].Time)
                throw "Bar discontinuity"
            }            
        }
    }
    Log("Test passed")

    Log("The length of the data returned by the $.GetRecordsByLength function:", r.length)

    // Update data
    while (true) {
        $.UpdataRecords(exchange, r, testPeriod)
        LogStatus(_D(), "r.length:", r.length)
        $.PlotRecords(r, "k")
        Sleep(5000)
    }
}

Di sini, kita gunakan garisvar testPeriod = PERIOD_M5untuk menetapkan tempoh K-garis 5 minit dan tentukan untuk mendapatkan 8000 bar. kemudian kita boleh melakukan ujian plot pada data K-garis panjang dikembalikan olehvar r = $.GetRecordsByLength(exchange, testPeriod, 8000) interface.

    // Use the plot test for easy observation
    $.PlotRecords(r, "k")

Ujian seterusnya untuk data garis K panjang adalah:

    // Test data
    var diffTime = r[1].Time - r[0].Time 
    Log("diffTime:", diffTime, " ms")
    for (var i = 0; i < r.length; i++) {
        for (var j = 0; j < r.length; j++) {
            // Check the repeat Bar
            if (i != j && r[i].Time == r[j].Time) {
                Log(r[i].Time, i, r[j].Time, j)
                throw "With duplicate Bar"
            }
        }
        
        // Check Bar continuity
        if (i < r.length - 1) {            
            if (r[i + 1].Time - r[i].Time != diffTime) {
                Log("i:", i, ", diff:", r[i + 1].Time - r[i].Time, ", r[i].Time:", r[i].Time, ", r[i + 1].Time:", r[i + 1].Time)
                throw "Bar discontinuity"
            }            
        }
    }
    Log("Test passed")
  1. Periksa jika terdapat sebarang bar duplikat dalam data K-line.
  2. Periksa kesesuaian data garis K (apakah perbezaan cap masa antara bar bersebelahan sama).

Selepas lulus pemeriksaan ini, mengesahkan sama ada antara muka yang digunakan untuk mengemas kini data K-garis,$.UpdateRecords(exchange, r, testPeriod), berfungsi dengan betul.

    // Update data
    while (true) {
        $.UpdataRecords(exchange, r, testPeriod)
        LogStatus(_D(), "r.length:", r.length)
        $.PlotRecords(r, "k")
        Sleep(5000)
    }

Kod ini akan terus mengeluarkan data K-line pada carta strategi semasa perdagangan langsung, yang membolehkan kita memeriksa sama ada kemas kini dan penambahan data K-line berfungsi dengan betul.

img

img

Menggunakan data K-line harian, kami menetapkannya untuk mendapatkan 8000 bar (mengetahui bahawa tidak ada data pasaran yang tersedia untuk 8000 hari yang lalu).

img

Memandangkan terdapat hanya 1309 K-line harian, bandingkan data pada carta pertukaran:

img

img

Anda boleh lihat bahawa data juga sepadan.

END

Alamat templat:Versi Javascript Permintaan Paginasi Templat Data Bersejarah K-LineAlamat templat:Plot Library

Templat dan kod strategi di atas hanya untuk penggunaan pengajaran dan pembelajaran, sila optimumkan dan ubahsuai mengikut keperluan khusus perdagangan langsung.


Berkaitan

Lebih lanjut