4
ফোকাস
1271
অনুসারী

নির্দিষ্ট দৈর্ঘ্যের কে-লাইন ডেটা পেতে কীভাবে একটি টেমপ্লেট ক্লাস লাইব্রেরি ডিজাইন করতে হয় তা শেখান

তৈরি: 2023-06-27 13:37:01, আপডেট করা হয়েছে: 2023-09-18 19:34:23
comments   0
hits   1285

নির্দিষ্ট দৈর্ঘ্যের কে-লাইন ডেটা পেতে কীভাবে একটি টেমপ্লেট ক্লাস লাইব্রেরি ডিজাইন করতে হয় তা শেখান

নির্দিষ্ট দৈর্ঘ্যের কে-লাইন ডেটা পেতে কীভাবে একটি টেমপ্লেট ক্লাস লাইব্রেরি ডিজাইন করতে হয় তা শেখান

কিছু ট্রেন্ড কৌশল ডিজাইন করার সময়, সূচক গণনা করার জন্য প্রায়শই পর্যাপ্ত সংখ্যক K-লাইন বারের প্রয়োজন হয়। FMZ প্ল্যাটফর্ম API এর উপর নির্ভর করে:exchange.GetRecords()ফাংশন দ্বারা প্রদত্ত ডেটার পরিমাণ, যখনexchange.GetRecords()এটি এক্সচেঞ্জের কে-লাইন ইন্টারফেসের এনক্যাপসুলেশন। ক্রিপ্টোকারেন্সি এক্সচেঞ্জের প্রারম্ভিক API ইন্টারফেস ডিজাইনে, এক্সচেঞ্জের কে-লাইন ইন্টারফেসগুলি কেবলমাত্র সীমিত পরিমাণে ডেটা প্রদান করে, তাই কিছু বিকাশকারী বৃহৎ পরামিতিগুলির সাথে সূচকগুলির গণনার চাহিদা পূরণ করতে অক্ষম ছিল৷

Binance কন্ট্রাক্ট API-এর কে-লাইন ইন্টারফেস পেজিং ক্যোয়ারী সমর্থন করে, তাই এই নিবন্ধটি Binance K-line API ইন্টারফেসটিকে একটি উদাহরণ হিসাবে গ্রহণ করবে যাতে আপনি কীভাবে একটি পেজিং কোয়েরি বাস্তবায়ন করতে হয় এবং FMZ প্ল্যাটফর্ম টেমপ্লেট ক্লাস লাইব্রেরি নির্দিষ্ট করতে পারেন বার

Binance এর কে-লাইন ইন্টারফেস

নির্দিষ্ট দৈর্ঘ্যের কে-লাইন ডেটা পেতে কীভাবে একটি টেমপ্লেট ক্লাস লাইব্রেরি ডিজাইন করতে হয় তা শেখান

প্রথমে, ইন্টারফেসের নির্দিষ্ট পরামিতি দেখতে আপনাকে এক্সচেঞ্জ API ডকুমেন্টেশন পড়তে হবে। আমরা দেখতে পাচ্ছি যে এই কে-লাইন ইন্টারফেসটিতে কল করার সময়, আপনাকে বৈচিত্র্য, কে-লাইন চক্র, ডেটা পরিসীমা (শুরু এবং শেষের সময়), পেজিংয়ের সংখ্যা ইত্যাদি উল্লেখ করতে হবে।

যেহেতু আমাদের ডিজাইনের প্রয়োজনীয়তা হল একটি নির্দিষ্ট সংখ্যক কে-লাইন ডেটা জিজ্ঞাসা করা, উদাহরণস্বরূপ, 1-ঘণ্টার কে-লাইন অনুসন্ধান করার জন্য, এটিকে বর্তমান সময় থেকে অতীতের সময়ে ঠেলে দিন এবং সংখ্যাটি হল 5,000 বার৷ এইভাবে, যদি আপনি শুধুমাত্র একবার এক্সচেঞ্জ API ইন্টারফেস ক্যোয়ারী কল করেন, আপনি স্পষ্টতই আপনার পছন্দসই ডেটা পাবেন না।

তারপর আমরা পৃষ্ঠাগুলিতে অনুসন্ধান করব এবং বর্তমান মুহূর্ত থেকে ইতিহাসের একটি নির্দিষ্ট মুহুর্ত পর্যন্ত ধাপে ধাপে এটি প্রক্রিয়া করব। আমরা ইতিমধ্যেই আমাদের প্রয়োজনীয় কে-লাইন ডেটার সময়কাল জানি, তাই আমরা সহজেই প্রতিটি সেগমেন্টের শুরু এবং শেষের সময় গণনা করতে পারি। যতক্ষণ না আপনি পর্যাপ্ত সংখ্যক বার খুঁজে না পান সেগমেন্টে ঐতিহাসিক মুহুর্তের দিক থেকে শুধু অনুসন্ধান করুন। যদি ধারণাটি সহজ মনে হয়, তাহলে আসুন এটি বাস্তবায়ন করি!

“জাভাস্ক্রিপ্ট সংস্করণ পেজিং কোয়েরি কে-লাইন ঐতিহাসিক ডেটা টেমপ্লেট” ডিজাইন করুন

ডিজাইন টেমপ্লেট ইন্টারফেস ফাংশন:$.GetRecordsByLength(e, period, length)

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

নকশা$.GetRecordsByLengthএই ফাংশনের স্বাভাবিক ব্যবহারের দৃশ্য হল যে কৌশল অপারেশনের প্রাথমিক পর্যায়ে, সূচকটি গণনা করার জন্য একটি দীর্ঘ কে-লাইন প্রয়োজন। এই ফাংশনটি কার্যকর করার পরে, পর্যাপ্ত দীর্ঘ ডেটা প্রাপ্ত হয় এবং তারপর শুধুমাত্র নতুন কে-লাইন ডেটা আপডেট করতে হবে। অতি-দীর্ঘ কে-লাইন ডেটা পেতে এই ফাংশনটি কল করার প্রয়োজন নেই, যা অপ্রয়োজনীয় ইন্টারফেস কলের কারণ হবে।

অতএব, পরবর্তী ডেটা আপডেটের জন্য আমাদের একটি ইন্টারফেস ডিজাইন করতে হবে:$.UpdataRecords(e, records, period)

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

পরবর্তী ধাপ হল এই ইন্টারফেস ফাংশনগুলি বাস্তবায়ন করা।

/**
 * 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
}

টেমপ্লেটে, আমরা শুধুমাত্র Binance চুক্তি কে-লাইন ইন্টারফেসের জন্য সমর্থন বাস্তবায়ন করি, অর্থাৎgetRecordsForFuturesBinanceঅন্যান্য ক্রিপ্টোকারেন্সি এক্সচেঞ্জের কে-লাইন ইন্টারফেসকে সমর্থন করার জন্যও ফাংশনটি বাড়ানো যেতে পারে।

টেস্ট সেশন

এটি দেখা যায় যে টেমপ্লেটে এই ফাংশনগুলি বাস্তবায়নের জন্য খুব বেশি কোড নেই, সম্ভবত 200 লাইনের কম। টেমপ্লেট কোড লেখার পরে, পরীক্ষা একেবারে অপরিহার্য। এবং এই ধরনের ডেটা অধিগ্রহণের জন্য, আমাদের যতটা সম্ভব কঠোরভাবে পরীক্ষা করতে হবে।

পরীক্ষা করার জন্য, আপনাকে “পেজিং কে-লাইন ঐতিহাসিক ডেটা টেমপ্লেটের জাভাস্ক্রিপ্ট সংস্করণ” এবং “লাইন ড্রয়িং ক্লাস লাইব্রেরি” টেমপ্লেট উভয়ই কপি করতে হবে আপনার নিজস্ব কৌশল লাইব্রেরিতে (কৌশল প্লাজাপাওয়া যাবে)। তারপরে আমরা একটি নতুন কৌশল তৈরি করি এবং এই দুটি টেমপ্লেট পরীক্ষা করি:

নির্দিষ্ট দৈর্ঘ্যের কে-লাইন ডেটা পেতে কীভাবে একটি টেমপ্লেট ক্লাস লাইব্রেরি ডিজাইন করতে হয় তা শেখান

নির্দিষ্ট দৈর্ঘ্যের কে-লাইন ডেটা পেতে কীভাবে একটি টেমপ্লেট ক্লাস লাইব্রেরি ডিজাইন করতে হয় তা শেখান

নির্দিষ্ট দৈর্ঘ্যের কে-লাইন ডেটা পেতে কীভাবে একটি টেমপ্লেট ক্লাস লাইব্রেরি ডিজাইন করতে হয় তা শেখান

আমরা “লাইন ড্রয়িং লাইব্রেরি” ব্যবহার করি কারণ আমাদের পর্যবেক্ষণের জন্য প্রাপ্ত কে-লাইন ডেটা আঁকতে হবে।

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)
    }
}

এখানে আমরা ব্যবহার করিvar testPeriod = PERIOD_M5এই বাক্যে, 5-মিনিটের কে-লাইন চক্র সেট করুন এবং 8,000 বার পাওয়ার জন্য নির্দিষ্ট করুন। তারপর জন্যvar r = $.GetRecordsByLength(exchange, testPeriod, 8000)ইন্টারফেস দ্বারা প্রত্যাবর্তিত খুব দীর্ঘ কে-লাইন ডেটা অঙ্কন পরীক্ষার জন্য ব্যবহৃত হয়:

    // 使用画图测试,方便观察
    $.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("检测通过")
  1. কে-লাইন বারে ডুপ্লিকেট আছে কিনা তা পরীক্ষা করুন।
  2. কে-লাইন বারের ধারাবাহিকতা পরীক্ষা করুন (সংলগ্ন বারের টাইমস্ট্যাম্পের পার্থক্য সমান কিনা)

এই চেকগুলি পাস করার পরে, K লাইন আপডেট করতে ব্যবহৃত ইন্টারফেসটি পরীক্ষা করুন$.UpdataRecords(exchange, r, testPeriod)এটা কি স্বাভাবিক:

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

এই কোডটি রিয়েল ট্রেডিং চলাকালীন স্ট্র্যাটেজি চার্টে ক্রমাগত K-লাইন আউটপুট করবে, যাতে আমরা পরীক্ষা করতে পারি যে K-লাইন বার ডেটা আপডেট করা হয়েছে এবং স্বাভাবিকভাবে যোগ করা হয়েছে কিনা।

নির্দিষ্ট দৈর্ঘ্যের কে-লাইন ডেটা পেতে কীভাবে একটি টেমপ্লেট ক্লাস লাইব্রেরি ডিজাইন করতে হয় তা শেখান

নির্দিষ্ট দৈর্ঘ্যের কে-লাইন ডেটা পেতে কীভাবে একটি টেমপ্লেট ক্লাস লাইব্রেরি ডিজাইন করতে হয় তা শেখান

দৈনিক কে-লাইন অধিগ্রহণ পদ্ধতি ব্যবহার করুন এবং এটিকে 8,000 লাইন পেতে সেট করুন (8,000 দিনের আগে কোনও বাজারের ডেটা নেই তা জেনে), এবং এইভাবে একটি হিংসাত্মক পরীক্ষা করুন:

নির্দিষ্ট দৈর্ঘ্যের কে-লাইন ডেটা পেতে কীভাবে একটি টেমপ্লেট ক্লাস লাইব্রেরি ডিজাইন করতে হয় তা শেখান

দৈনিক লাইনটি শুধুমাত্র 1309, এক্সচেঞ্জ চার্টে ডেটা তুলনা করুন:

নির্দিষ্ট দৈর্ঘ্যের কে-লাইন ডেটা পেতে কীভাবে একটি টেমপ্লেট ক্লাস লাইব্রেরি ডিজাইন করতে হয় তা শেখান

নির্দিষ্ট দৈর্ঘ্যের কে-লাইন ডেটা পেতে কীভাবে একটি টেমপ্লেট ক্লাস লাইব্রেরি ডিজাইন করতে হয় তা শেখান

এটি দেখা যায় যে ডেটাও সামঞ্জস্যপূর্ণ।

END

টেমপ্লেট ঠিকানা:“জাভাস্ক্রিপ্ট সংস্করণ পেজিং কোয়েরি কে-লাইন ঐতিহাসিক ডেটা টেমপ্লেট” টেমপ্লেট ঠিকানা:“লাইন ড্রয়িং লাইব্রেরি”

উপরের টেমপ্লেট এবং কৌশল কোডগুলি শুধুমাত্র শিক্ষা এবং শেখার জন্য ব্যবহার করা হয় অনুগ্রহ করে আপনার প্রয়োজন অনুযায়ী প্রকৃত ট্রেডিং অপ্টিমাইজ করুন এবং পরিবর্তন করুন।