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

Penulis:Mimpi kecil, Dicipta: 2023-06-27 13:37:01, Dikemas kini: 2023-09-18 19:34:23

img

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

Dalam merancang beberapa strategi trend, penunjuk pengiraan sering memerlukan jumlah yang mencukupi K-Line Bar; bergantung pada API platform FMZ:exchange.GetRecords()Dan jumlah data yang diberikan oleh fungsi.exchange.GetRecords()Ini adalah pembungkusan untuk antara muka K pertukaran. Tidak ada pertanyaan bertaburan dalam reka bentuk antara muka API pertukaran mata wang kripto awal, dan antara muka K pertukaran hanya disediakan untuk jumlah data yang terhad, jadi beberapa pembangun tidak dapat memenuhi keperluan pengiraan penunjuk parameter yang lebih besar.

Antara muka K-Line untuk API Kontrak Binance menyokong pertanyaan bertaburan, maka artikel ini akan mengajar anda bagaimana untuk melaksanakan pertanyaan bertaburan dengan menggunakan API K-Line Binance sebagai contoh dan menentukan jumlah Bar untuk mendapatkan perpustakaan templat platform FMZ.

Antara muka K-Line Binance

img

Pertama, lihat dokumentasi API pertukaran untuk melihat parameter yang spesifik untuk antara muka. Kita dapat melihat bahawa panggilan antara muka K-line ini memerlukan jenis, kitaran K-line, jangkauan data (masa permulaan, akhir), bilangan bahagian halaman, dan sebagainya.

Oleh kerana keperluan reka bentuk kami adalah untuk menyoal sejumlah data K-line, contohnya untuk menyoal K-line 1 jam, dari masa kini ke masa lalu, dengan jumlah 5000 Bar. Jadi anda hanya memanggil satu permintaan API pertukaran yang jelas tidak akan mendapatkan data yang anda mahukan.

Kemudian kita membahagikan pertanyaan, memproses segmen dari masa kini ke masa sejarah. Kita tahu bahawa kitaran data K-line yang diperlukan adalah baik untuk mengira permulaan dan pengakhiran setiap segmen. Hanya gunakan segmen ke arah masa sejarah untuk membuat pertanyaan sehingga jumlah Bar yang mencukupi.

Reka bentuk Templat Data Sejarah K-Line untuk Javascript

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

/**
 * desc: $.GetRecordsByLength 是该模板类库的接口函数,该函数用于获取指定K线长度的K线数据
 * @param {Object} e - 交易所对象
 * @param {Int} period - K线周期,秒数为单位
 * @param {Int} length - 指定获取的K线数据的长度,具体和交易所接口限制有关
 * @returns {Array<Object>} - K线数据
 */

Reka bentuk$.GetRecordsByLengthFungsi ini biasanya memerlukan garis K yang panjang untuk mengira penunjuk pada awal pelaksanaan strategi. Setelah fungsi ini dijalankan, data yang cukup panjang diambil, dan data baris K baru hanya perlu diperbaharui. Tidak perlu lagi memanggil fungsi ini untuk mendapatkan data baris K yang sangat panjang, yang menyebabkan panggilan antara muka yang tidak diperlukan.

Oleh itu, kita juga perlu merancang antara muka untuk mengemas kini data susulan:$.UpdataRecords(e, records, period)

/**
 * desc: $.UpdataRecords 是该模板类库的接口函数,该函数用于更新K线数据
 * @param {Object} e - 交易所对象
 * @param {Array<Object>} records - 需要更新的K线数据源
 * @param {Int} period - K线周期,需要和records参数传入的K线数据周期一致
 * @returns {Bool}  - 是否更新成功
 */

Kemudian, fungsi antara muka akan diimplementasikan.

/**
 * desc: $.GetRecordsByLength 是该模板类库的接口函数,该函数用于获取指定K线长度的K线数据
 * @param {Object} e - 交易所对象
 * @param {Int} period - K线周期,秒数为单位
 * @param {Int} length - 指定获取的K线数据的长度,具体和交易所接口限制有关
 * @returns {Array<Object>} - K线数据
 */
$.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 币安期货交易所获取K线数据函数的具体实现
 * @param {Object} e - 交易所对象
 * @param {Int} period - K线周期,秒数为单位
 * @param {Int} length - 指定获取的K线数据的长度,具体和交易所接口限制有关
 * @returns {Array<Object>} - K线数据
 */
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 -> 分钟; h -> 小时; d -> 天; w -> 周; M -> 月
    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 最大值: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
        // startTime 与 endTime 之间最多只可以相差200天
        // limit 最大值: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) {
        // 计算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
        }

        // 超出交易所可查询范围,查询不到数据时
        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 是该模板类库的接口函数,该函数用于更新K线数据
 * @param {Object} e - 交易所对象
 * @param {Array<Object>} records - 需要更新的K线数据源
 * @param {Int} period - K线周期,需要和records参数传入的K线数据周期一致
 * @returns {Bool}  - 是否更新成功
 */
$.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) {
            // 添加新Bar
            records.push(r[i])
            // 更新上一个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) {
            // 更新Bar
            records[records.length - 1] = r[i]
        }
    }
    return true
}

Dalam templat ini, kami hanya menggunakan sokongan untuk antarmuka K-Line Kontrak Binance, iaitugetRecordsForFuturesBinanceFungsi ini juga boleh meluaskan antara muka K-Line yang menyokong pertukaran mata wang kripto lain.

Percubaan

Seperti yang dapat dilihat, kod untuk melaksanakan fungsi ini tidak banyak dalam templat, mungkin kurang daripada 200 baris. Selepas kod templat ditulis, ujian adalah sangat banyak. Dan untuk mendapatkan data seperti itu, kita juga memerlukan ujian yang paling ketat mungkin.

Ujian ini memerlukan salinan templat "K-line History Data Template" dan "Draw Line Library" ini ke dalam perpustakaan dasar anda sendiri (dalam bahasa Inggeris).Dataran StrategyKemudian, kami membuat dasar baru untuk memilih dua templat ini:

img

img

img

Kami menggunakan "Layanan Gambar" kerana kami perlu melukis dan melihat data K-line yang kami perolehi.

function main() {
	LogReset(1)
	var testPeriod = PERIOD_M5
    Log("当前测试的交易所:", exchange.GetName())

    // 如果是期货则需要设置合约
    exchange.SetContractType("swap")

    // 使用$.GetRecordsByLength获取指定长度的K线数据
    var r = $.GetRecordsByLength(exchange, testPeriod, 8000)
    Log(r)

    // 使用画图测试,方便观察
    $.PlotRecords(r, "k")

    // 检测数据
    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++) {
            // 检查重复Bar
            if (i != j && r[i].Time == r[j].Time) {
                Log(r[i].Time, i, r[j].Time, j)
                throw "有重复Bar"
            }
        }
        
        // 检查Bar连续性
        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不连续"
            }            
        }
    }
    Log("检测通过")

    Log("$.GetRecordsByLength函数返回的数据长度:", r.length)

    // 更新数据
    while (true) {
        $.UpdataRecords(exchange, r, testPeriod)
        LogStatus(_D(), "r.length:", r.length)
        $.PlotRecords(r, "k")
        Sleep(5000)
    }
}

Di sini kita menggunakanvar testPeriod = PERIOD_M5Setup 5 minit K garis kitaran, tentukan untuk mendapatkan 8000 bar.var r = $.GetRecordsByLength(exchange, testPeriod, 8000)Data K-line panjang yang dikembalikan oleh antara muka diuji dengan gambar:

    // 使用画图测试,方便观察
    $.PlotRecords(r, "k")

Di sini, kita boleh melihat data K-line yang panjang:

    // 检测数据
    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++) {
            // 检查重复Bar
            if (i != j && r[i].Time == r[j].Time) {
                Log(r[i].Time, i, r[j].Time, j)
                throw "有重复Bar"
            }
        }
        
        // 检查Bar连续性
        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不连续"
            }            
        }
    }
    Log("检测通过")

1. Periksa sama ada terdapat pengulangan dalam baris KBar. 2, periksa keseragaman garis KBar (apakah selang masa Bar berdekatan sama)

Selepas pemeriksaan ini berlalu, memeriksa antara muka untuk mengemas kini K-line$.UpdataRecords(exchange, r, testPeriod)Adakah ia normal:

    // 更新数据
    while (true) {
        $.UpdataRecords(exchange, r, testPeriod)
        LogStatus(_D(), "r.length:", r.length)
        $.PlotRecords(r, "k")
        Sleep(5000)
    }

Kod ini akan terus mengeluarkan baris K pada carta dasar semasa berjalan pada cakera sebenar, dengan ini kita memeriksa sama ada pembaruan dan penambahan data Bar baris K adalah normal.

img

img

Dengan menggunakan K-Line untuk mendapatkan hari, setup untuk mendapatkan 8000 root (dengan mengetahui bahawa tidak ada data pasaran sebelum 8000 hari), seperti ini:

img

Di sini, kita melihat garis hari hanya 1309 root, berbanding dengan data di carta bursa:

img

img

Dan anda boleh lihat bahawa data juga sesuai.

END

Alamat templat:"Pengundian halaman versi JavaScript untuk query K-Line Template Data Sejarah"Alamat templat:"Layanan Kelas Gambar".

Templat, kod strategi di atas hanya digunakan untuk pengajaran, pembelajaran dan penggunaan. Sila mengoptimumkan atau mengubahnya mengikut keperluan anda.


Lebih lanjut