avatar of 发明者量化-小小梦 发明者量化-小小梦
fokus pada mesej peribadi
4
fokus pada
1271
Pengikut

Ajar anda untuk mereka bentuk perpustakaan templat untuk mendapatkan data K-line dengan panjang yang ditentukan

Dicipta dalam: 2023-06-27 13:37:01, dikemas kini pada: 2023-09-18 19:34:23
comments   0
hits   1285

Ajar anda untuk mereka bentuk perpustakaan templat untuk mendapatkan data K-line dengan panjang yang ditentukan

Ajar anda untuk mereka bentuk perpustakaan templat untuk mendapatkan data K-line dengan panjang yang ditentukan

Apabila mereka bentuk beberapa strategi aliran, pengiraan penunjuk selalunya memerlukan bilangan bar garis K yang mencukupi. Bergantung pada API platform FMZ:exchange.GetRecords()Jumlah data yang diberikan oleh fungsi, danexchange.GetRecords()Ia adalah enkapsulasi antara muka talian K pertukaran. Dalam reka bentuk awal antara muka API pertukaran mata wang kripto, tiada pertanyaan paging, dan antara muka K-line pertukaran hanya menyediakan jumlah data yang terhad, jadi keperluan sesetengah pembangun untuk pengiraan penunjuk dengan parameter yang lebih besar tidak dapat dipenuhi.

Antara muka K-line API kontrak Binance menyokong pertanyaan bernombor Artikel ini mengambil antara muka API K-line Binance sebagai contoh untuk mengajar anda cara melaksanakan pertanyaan bernombor dan menentukan perpustakaan templat platform FMZ untuk mendapatkan bilangan Bar.

Antara muka Binance K-line

Ajar anda untuk mereka bentuk perpustakaan templat untuk mendapatkan data K-line dengan panjang yang ditentukan

Mula-mula, anda perlu membaca dokumentasi API pertukaran untuk melihat parameter khusus antara muka. Kita dapat melihat bahawa apabila memanggil antara muka K-line ini, adalah perlu untuk menentukan produk, tempoh K-line, julat data (masa mula dan tamat), bilangan halaman, dsb.

Memandangkan keperluan reka bentuk kami adalah untuk menanyakan bilangan data garis K yang ditentukan, contohnya, untuk menanyakan baris K 1 jam, tolak dari masa semasa ke masa lalu, bilangannya ialah 5,000 bar. Dengan cara ini, anda jelas tidak boleh mendapatkan data yang anda inginkan dengan memanggil pertanyaan antara muka API pertukaran sekali sahaja.

Kemudian kami akan membuat pertanyaan dalam halaman, memproses dalam segmen dari saat semasa ke saat tertentu dalam sejarah. Selagi kita mengetahui tempoh data K-line yang diperlukan, adalah mudah untuk mengira masa mula dan tamat setiap segmen. Hanya bertanya ke arah detik bersejarah mengikut urutan sehingga anda menemui bar yang mencukupi. Ideanya kelihatan mudah, bukan?

Reka bentuk “Templat data sejarah K-line pertanyaan versi JavaScript”

Fungsi antara muka templat reka bentuk:$.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 digunakan pada peringkat awal operasi strategi apabila garis K yang panjang diperlukan untuk mengira penunjuk. Selepas fungsi ini dilaksanakan, ia memperoleh data yang cukup panjang, dan kemudian ia hanya perlu mengemas kini data K-line baharu. Tidak perlu memanggil fungsi ini untuk mendapatkan data talian K yang sangat panjang, yang akan menyebabkan panggilan antara muka yang tidak perlu.

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

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

Langkah seterusnya ialah melaksanakan fungsi antara muka ini.

/**
 * 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, kami hanya melaksanakan sokongan antara muka K-line kontrak Binance, iaitu,getRecordsForFuturesBinanceBerfungsi, ia juga boleh dikembangkan untuk menyokong antara muka K-line bagi pertukaran mata wang kripto lain.

Menguji

Anda dapat melihat bahawa tidak banyak kod dalam templat untuk melaksanakan fungsi ini, mungkin kurang daripada 200 baris. Selepas kod templat ditulis, ujian amat diperlukan. Dan untuk pemerolehan data sedemikian, kami juga perlu mengujinya seketat mungkin.

Ujian ini memerlukan menyalin “versi JavaScript templat data sejarah baris K pertanyaan halaman” dan templat “pustaka lukisan garis” ini ke pustaka strategi anda sendiri (dalamDataran Strategiboleh dicari dalam ). Kemudian kami mencipta strategi baharu dan menyemak dua templat ini:

Ajar anda untuk mereka bentuk perpustakaan templat untuk mendapatkan data K-line dengan panjang yang ditentukan

Ajar anda untuk mereka bentuk perpustakaan templat untuk mendapatkan data K-line dengan panjang yang ditentukan

Ajar anda untuk mereka bentuk perpustakaan templat untuk mendapatkan data K-line dengan panjang yang ditentukan

“Perpustakaan lukisan garisan” digunakan kerana kita perlu melukis data garis K yang diperolehi untuk pemerhatian.

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 gunakanvar testPeriod = PERIOD_M5Ayat ini menetapkan tempoh K-line kepada 5 minit dan menentukan untuk mendapatkan 8000 bar. Kemudian untukvar r = $.GetRecordsByLength(exchange, testPeriod, 8000)Antara muka mengembalikan data garis K yang panjang untuk ujian lukisan:

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

Seterusnya, kami akan menguji data K-line yang sangat panjang ini:

    // 检测数据
    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. Semak sama ada terdapat sebarang pendua dalam Bar K-line.
  2. Semak kesinambungan Bar K-line (sama ada perbezaan cap masa Bar bersebelahan adalah sama)

Selepas semakan ini diluluskan, semak antara muka yang digunakan untuk mengemas kini baris K$.UpdataRecords(exchange, r, testPeriod)Biasa:

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

Kod ini akan terus mengeluarkan K-line pada carta strategi apabila ia berjalan dalam dagangan sebenar, supaya kami boleh menyemak sama ada data Bar K-line dikemas kini dan ditambah seperti biasa.

Ajar anda untuk mereka bentuk perpustakaan templat untuk mendapatkan data K-line dengan panjang yang ditentukan

Ajar anda untuk mereka bentuk perpustakaan templat untuk mendapatkan data K-line dengan panjang yang ditentukan

Gunakan fungsi pemerolehan K-line harian dan tetapkan pemerolehan kepada 8,000 (mengetahui bahawa tiada data pasaran sebelum 8,000 hari), dan lakukan ujian kekerasan seperti ini:

Ajar anda untuk mereka bentuk perpustakaan templat untuk mendapatkan data K-line dengan panjang yang ditentukan

Terdapat hanya 1309 talian harian, berbanding dengan data pada carta pertukaran:

Ajar anda untuk mereka bentuk perpustakaan templat untuk mendapatkan data K-line dengan panjang yang ditentukan

Ajar anda untuk mereka bentuk perpustakaan templat untuk mendapatkan data K-line dengan panjang yang ditentukan

Anda dapat melihat bahawa data adalah konsisten.

END

Alamat templat:「Templat data sejarah K-line versi JavaScript pertanyaan berhalaman」 Alamat templat:Perpustakaan lukisan garisan

Templat dan kod strategi di atas hanya untuk tujuan pengajaran dan pembelajaran Sila optimumkan dan ubah suai mengikut keperluan sebenar anda.