Mengajarkan Anda untuk merancang perpustakaan kelas template untuk mendapatkan data K-line dari panjang yang ditentukan

Penulis:Lydia, Dibuat: 2023-06-29 17:27:59, Diperbarui: 2023-09-18 19:33:33

img

Mengajarkan Anda untuk merancang perpustakaan kelas template untuk mendapatkan data K-line dari panjang yang ditentukan

Ketika merancang strategi tren, seringkali perlu memiliki jumlah batang garis K yang cukup untuk perhitungan indikator.exchange.GetRecords()Pada awal desain API pertukaran cryptocurrency, tidak ada dukungan untuk paginasi di antarmuka K-line, dan antarmuka K-line exchange hanya menyediakan sejumlah data terbatas. Akibatnya, beberapa pengembang tidak dapat memenuhi persyaratan untuk menghitung indikator dengan nilai parameter yang lebih besar.

Antarmuka K-line dari API kontrak Binance mendukung paginasi. Dalam artikel ini, kami akan menggunakan antarmuka API Binance K-line sebagai contoh untuk mengajarkan Anda cara menerapkan paginasi dan menentukan jumlah bar untuk diambil menggunakan perpustakaan template platform FMZ.

Antarmuka K-line dari Binance

Data garis K

Waktu pembukaan setiap K-line diGET /dapi/v1/klinestitik akhir dapat dianggap sebagai ID unik.

Berat permintaan tergantung pada nilai parameter LIMIT.

img

Parameter:

img

Pertama, kita perlu merujuk ke dokumentasi API exchanges untuk memahami parameter spesifik antarmuka K-line. kita dapat melihat bahwa ketika memanggil titik akhir K-line ini, kita perlu menentukan jenis, periode K-line, rentang data (waktu awal dan akhir), dan jumlah halaman, dll.

Karena persyaratan desain kami adalah untuk menanyakan sejumlah data K-line tertentu, misalnya, untuk menanyakan data K-line 1 jam, 5000 bar data K-line 1 jam dari saat ini ke masa lalu, jelas bahwa melakukan panggilan API tunggal ke pertukaran tidak akan mengambil data yang diinginkan.

Untuk mencapai hal ini, kita dapat menerapkan pagination dan membagi query menjadi segmen dari saat ini menuju momen historis tertentu. Karena kita tahu periode data K-line yang diinginkan, kita dapat dengan mudah menghitung waktu awal dan akhir untuk setiap segmen. Kita kemudian dapat menanyakan setiap segmen secara berurutan menuju momen historis sampai kita mendapatkan cukup batang. Pendekatan terdengar sederhana, jadi mari kita lanjutkan dan terapkan!

Desain Versi JavaScript dari query berpaginasi K-line template data historis

Fungsi antarmuka untuk template desain:$.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
 */

Desain fungsi$.GetRecordsByLength, yang biasanya digunakan pada tahap awal pelaksanaan strategi untuk menghitung indikator berdasarkan periode panjang data K-line. Setelah fungsi ini dieksekusi dan data yang cukup diperoleh, hanya data K-line baru yang perlu diperbarui. Tidak perlu memanggil fungsi ini lagi untuk mengambil data K-line yang terlalu panjang, karena akan menghasilkan panggilan API yang tidak perlu.

Oleh karena itu, juga perlu merancang antarmuka untuk pembaruan 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 selanjutnya adalah menerapkan fungsi antarmuka 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, kami hanya menerapkan dukungan untuk Binance kontrak berjangka K-line antarmuka, yaitu,getRecordsForFuturesBinanceIni juga dapat diperluas untuk mendukung antarmuka K-line dari pertukaran cryptocurrency lainnya.

Sesi Uji

Seperti yang Anda lihat, kode untuk menerapkan fungsionalitas ini dalam template tidak luas, total kurang dari 200 baris. Setelah menulis kode template, pengujian sangat penting dan tidak boleh diabaikan.

Untuk mengujinya, Anda perlu menyalin kedua JavaScript Versi Pagination Query K-Line Template Data historis dan Plot Library template ke perpustakaan strategi Anda (yang dapat ditemukan diStrategy SquareKemudian, buatlah strategi baru dan pilih dua templat ini.

img

img

Plot Library digunakan, karena kita perlu menggambar data K-line yang diperoleh untuk pengamatan.

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 menggunakan garisvar testPeriod = PERIOD_M5untuk mengatur periode K-line 5 menit dan menentukan untuk mengambil 8000 bar. kemudian kita dapat melakukan tes plot pada data K-line panjang dikembalikan olehvar r = $.GetRecordsByLength(exchange, testPeriod, 8000) interface.

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

Tes berikutnya untuk data garis panjang K 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 apakah ada duplikat bar dalam data K-line.
  2. Periksa koherensi data garis K (apakah perbedaan timestamp antara batang berdekatan sama).

Setelah melewati pemeriksaan ini, periksa apakah antarmuka yang digunakan untuk memperbarui data K-line,$.UpdateRecords(exchange, r, testPeriod), berfungsi dengan baik.

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

Kode ini akan terus menghasilkan data K-line pada grafik strategi selama perdagangan langsung, memungkinkan kita untuk memeriksa apakah pembaruan dan penambahan data K-line berfungsi dengan benar.

img

img

Menggunakan data K-line harian, kami mengaturnya untuk mengambil 8000 bar (mengetahui bahwa tidak ada data pasar yang tersedia untuk 8000 hari yang lalu).

img

Mengingat hanya ada 1309 K-line harian, bandingkan data pada grafik pertukaran:

img

img

Anda dapat melihat bahwa data juga cocok.

Penghentian

Alamat templat:Versi JavaScript dari Pagination Query K-Line Template Data SejarahAlamat templat:Plot Library

Templat dan kode strategi di atas hanya untuk penggunaan pengajaran dan pembelajaran, silahkan dioptimalkan dan dimodifikasi sesuai dengan kebutuhan khusus perdagangan langsung.


Berkaitan

Lebih banyak