রিসোর্স লোড হচ্ছে... লোডিং...

ডিজিটাল মুদ্রা জোড়া ট্রেডিং কৌশল এবং FMZ প্ল্যাটফর্মের সর্বশেষতম API এর সোর্স কোডের ভূমিকা

লেখক:এফএমজেড-লিডিয়া, তৈরিঃ ২০২৪-০৭-১১ 14:57:15, আপডেটঃ ২০২৪-০৭-১২ 15:55:53

img

প্রিফেস

পূর্ববর্তী প্রবন্ধে জোড়া ট্রেডিং এর নীতি এবং ব্যাকটেস্টিং চালু করা হয়েছে,https://www.fmz.com/bbs-topic/10459. এখানে এফএমজেড প্ল্যাটফর্মের উপর ভিত্তি করে একটি ব্যবহারিক সোর্স কোড রয়েছে। কৌশলটি সহজ এবং পরিষ্কার, শিক্ষানবিশদের শেখার জন্য উপযুক্ত। এফএমজেড প্ল্যাটফর্ম সম্প্রতি মাল্টি-ট্রেডিং জোড়া কৌশলগুলির জন্য আরও বন্ধুত্বপূর্ণ হতে কিছু এপিআই আপগ্রেড করেছে। এই নিবন্ধটি এই কৌশলটির জাভাস্ক্রিপ্ট উত্স কোডটি বিশদভাবে পরিচয় করিয়ে দেবে। যদিও কৌশল কোডটি মাত্র একশো লাইন, এটি একটি সম্পূর্ণ কৌশল জন্য প্রয়োজনীয় সমস্ত দিক ধারণ করে। নির্দিষ্ট এপিআইটি এপিআই নথিতে দেখা যাবে, যা খুব বিস্তারিত। কৌশল পাবলিক ঠিকানাঃhttps://www.fmz.com/strategy/456143সরাসরি কপি করা যায়।

এফএমজেড প্ল্যাটফর্ম ব্যবহার

আপনি যদি এফএমজেড প্ল্যাটফর্মের সাথে পরিচিত না হন, তাহলে আমি আপনাকে এই টিউটোরিয়ালটি পড়ার পরামর্শ দিচ্ছিঃhttps://www.fmz.com/bbs-topic/4145এটি প্ল্যাটফর্মের মৌলিক ফাংশনগুলি বিস্তারিতভাবে পরিচয় করিয়ে দেয়, পাশাপাশি কীভাবে একটি রোবটকে স্ক্র্যাচ থেকে স্থাপন করা যায়।

কৌশলগত কাঠামো

নিম্নলিখিতটি একটি সহজ কৌশল কাঠামো। প্রধান ফাংশনটি এন্ট্রি পয়েন্ট। অসীম লুপটি নিশ্চিত করে যে কৌশলটি অবিচ্ছিন্নভাবে কার্যকর করা হয় এবং অ্যাক্সেস ফ্রিকোয়েন্সি বিনিময় সীমা অতিক্রম করা থেকে বিরত রাখতে একটি ছোট ঘুমের সময় যোগ করা হয়।

function main(){
    while(true){
        //strategy content
        Sleep(Interval * 1000) //Sleep
    }
}

রেকর্ড ঐতিহাসিক তথ্য

রোবটটি বিভিন্ন কারণে বারবার পুনরায় চালু হবে, যেমন ত্রুটি, পরামিতি আপডেট, কৌশল আপডেট ইত্যাদি, এবং পরবর্তী স্টার্টআপের জন্য কিছু ডেটা সংরক্ষণ করা দরকার। এখানে রিটার্ন গণনা করার জন্য প্রাথমিক ইক্যুইটি কীভাবে সংরক্ষণ করা যায় তার একটি প্রদর্শন রয়েছে। _G() ফাংশন বিভিন্ন ডেটা সঞ্চয় করতে পারে। _G(কি, মান) মানের মান সংরক্ষণ করতে পারে এবং এটি _G(কি দিয়ে কল করতে পারে, যেখানে কী একটি স্ট্রিং।

let init_eq = 0 //defining initial equity
if(!_G('init_eq')){  //If there is no storage, _G('init_eq') returns null.
    init_eq = total_eq
    _G('init_eq', total_eq) //Since there is no storage, the initial equity is the current equity and is stored here
}else{
    init_eq = _G('init_eq') //If stored, read the value of the initial equity
}

কৌশল ত্রুটি সহনশীলতা

এপিআই এর মাধ্যমে অবস্থান এবং বাজার অবস্থার মতো ডেটা পাওয়ার সময়, বিভিন্ন কারণে ত্রুটি ফিরে আসতে পারে। সরাসরি ডেটা কল করার ফলে ত্রুটির কারণে কৌশলটি বন্ধ হয়ে যাবে, তাই একটি ত্রুটি-সহনশীল প্রক্রিয়া প্রয়োজন। _C() ফাংশনটি একটি ত্রুটির পরে স্বয়ংক্রিয়ভাবে পুনরায় চেষ্টা করবে যতক্ষণ না সঠিক ডেটা ফিরে আসে। অথবা ফিরে আসার পরে ডেটা উপলব্ধ কিনা তা পরীক্ষা করুন।

let pos = _C(exchange.GetPosition, pair)

let ticker_A = exchange.GetTicker(pair_a)
let ticker_B = exchange.GetTicker(pair_b)
if(!ticker_A || !ticker_B){
    continue //If the data is not available, exit the loop.
}

মাল্টি মুদ্রা সামঞ্জস্যপূর্ণ এপিআই

GetPosition, GetTicker, এবং GetRecords এর মতো ফাংশনগুলি এক্সচেঞ্জ-বাউন্ড ট্রেডিং জোড়া সেট না করেই সংশ্লিষ্ট ডেটা পেতে একটি ট্রেডিং জোড়া প্যারামিটার যুক্ত করতে পারে, যা একাধিক ট্রেডিং জোড়া কৌশলগুলির সামঞ্জস্যতাকে ব্যাপকভাবে সহজ করে তোলে। নির্দিষ্ট আপগ্রেড সামগ্রীর জন্য, নিবন্ধটি দেখুনঃhttps://www.fmz.com/bbs-topic/10456. অবশ্যই, এটি সমর্থন করার জন্য সর্বশেষ ডকার প্রয়োজন. যদি আপনার ডকার খুব পুরানো হয়, আপনি আপগ্রেড করতে হবে.

কৌশল পরামিতি

  • Pair_A: ট্রেডিং জোড়া A যা ট্রেডিংয়ের জন্য জোড়া করা দরকার। আপনাকে ট্রেডিং জোড়াটি নিজেরাই বেছে নিতে হবে। আপনি পূর্ববর্তী নিবন্ধে ভূমিকা এবং ব্যাকটেস্টিং উল্লেখ করতে পারেন।
  • Pair_B: ট্রেডিং জোড়া B যা জোড়া করা প্রয়োজন।
  • উদ্ধৃতিঃ ফিউচার এক্সচেঞ্জের মার্জিন মুদ্রা, সাধারণত ইউএসডিটি।
  • Pct: পজিশন যোগ করার জন্য বিচ্যুতি কত, বিস্তারিত জানার জন্য কৌশল নীতি সম্পর্কিত নিবন্ধটি দেখুন, হ্যান্ডলিং ফি এবং স্লিপিংয়ের কারণে এটি খুব ছোট করা উচিত নয়।
  • Trade_Value: গ্রিডের আকার থেকে প্রতিটি বিচ্যুতির জন্য পজিশন যোগ করার ট্রেডিং মান।
  • Ice_Value: লেনদেনের মান যদি খুব বড় হয়, তাহলে আপনি একটি অবস্থান খোলার জন্য আইসবার্গের কমিশন মান ব্যবহার করতে পারেন। সাধারণভাবে, এটি লেনদেনের মানের সাথে একই মান সেট করা যেতে পারে।
  • Max_Value: একটি একক মুদ্রার সর্বাধিক ধারণ, খুব বেশি পজিশন রাখার ঝুঁকি এড়ানোর জন্য।
  • N: গড় মূল্য অনুপাত গণনা করার জন্য ব্যবহৃত পরামিতি, ইউনিটটি ঘন্টা, উদাহরণস্বরূপ, 100 100 ঘন্টা গড় প্রতিনিধিত্ব করে।
  • অন্তরালঃ কৌশলটির প্রতিটি চক্রের মধ্যে ঘুমের সময়।

সম্পূর্ণ কৌশল নোট

যদি আপনি এখনও বুঝতে না পারেন, আপনি FMZ এর API ডকুমেন্টেশন, ডিবাগিং সরঞ্জাম এবং বাজারে সাধারণত ব্যবহৃত এআই ডায়লগ সরঞ্জামগুলি ব্যবহার করে আপনার প্রশ্নগুলি সমাধান করতে পারেন।

function GetPosition(pair){
    let pos = _C(exchange.GetPosition, pair)
    if(pos.length == 0){ //Returns null to indicate no position
        return {amount:0, price:0, profit:0}
    }else if(pos.length > 1){ //The strategy should be set to unidirectional position mode
        throw 'Bidirectional positions are not supported'
    }else{ //For convenience, long positions are positive and short positions are negative
        return {amount:pos[0].Type == 0 ? pos[0].Amount : -pos[0].Amount, price:pos[0].Price, profit:pos[0].Profit}
    }
}

function GetRatio(){
    let kline_A = exchange.GetRecords(Pair_A+"_"+Quote+".swap", 60*60, N) //Hourly K-line
    let kline_B = exchange.GetRecords(Pair_B+"_"+Quote+".swap", 60*60, N)
    let total = 0
    for(let i= Math.min(kline_A.length,kline_B.length)-1; i >= 0; i--){ //Calculate in reverse to avoid the K-line being too short.
        total += kline_A[i].Close / kline_B[i].Close
    }
    return total / Math.min(kline_A.length,kline_B.length)
}

function GetAccount(){
    let account = _C(exchange.GetAccount)
    let total_eq = 0
    if(exchange.GetName == 'Futures_OKCoin'){ //Since the API here is not compatible, only OKX Futures Exchange obtains the total equity currently.
        total_eq = account.Info.data[0].totalEq //The equity information of other exchanges is also included. You can look for it yourself in the exchange API documentation.
    }else{
        total_eq = account.Balance //Temporary use of available balances on other exchanges will cause errors in calculating returns, but will not affect the use of strategies.
    }
    let init_eq = 0
    if(!_G('init_eq')){
        init_eq = total_eq
        _G('init_eq', total_eq)
    }else{
        init_eq = _G('init_eq')
    }
    LogProfit(total_eq - init_eq)
    return total_eq
}

function main(){
    var precision = exchange.GetMarkets() //Get the precision here
    var last_get_ratio_time = Date.now()
    var ratio = GetRatio()
    var total_eq = GetAccount()
    while(true){
        let start_loop_time = Date.now()
        if(Date.now() - last_get_ratio_time > 10*60*1000){ //Update the average price and account information every 10 minutes
            ratio = GetRatio()
            total_eq = GetAccount()
            last_get_ratio_time = Date.now()
        }
        let pair_a = Pair_A+"_"+Quote+".swap" //The trading pair is set as BTC_USDT.swap
        let pair_b = Pair_B+"_"+Quote+".swap"
        let CtVal_a = "CtVal" in precision[pair_a] ? precision[pair_a].CtVal : 1 //Some exchanges use sheets to represent quantity, such as one sheet represents 0.01 coin, so you need to convert.
        let CtVal_b = "CtVal" in precision[pair_b] ? precision[pair_b].CtVal : 1 //No need to include this field
        let position_A = GetPosition(pair_a)
        let position_B = GetPosition(pair_b)
        let ticker_A = exchange.GetTicker(pair_a)
        let ticker_B = exchange.GetTicker(pair_b)
        if(!ticker_A || !ticker_B){ //If the returned data is abnormal, jump out of this loop
            continue
        }
        let diff = (ticker_A.Last / ticker_B.Last - ratio) / ratio //Calculate the ratio of deviation
        let aim_value = - Trade_Value * diff / Pct //Target holding position
        let id_A = null
        let id_B = null
        //The following is the specific logic of opening a position
        if( -aim_value + position_A.amount*CtVal_a*ticker_A.Last > Trade_Value && position_A.amount*CtVal_a*ticker_A.Last > -Max_Value){
            id_A = exchange.CreateOrder(pair_a, "sell", ticker_A.Buy, _N(Ice_Value / (ticker_A.Buy * CtVal_a), precision[pair_a].AmountPrecision))
        }
        if( -aim_value - position_B.amount*CtVal_b*ticker_B.Last > Trade_Value && position_B.amount*CtVal_b*ticker_B.Last < Max_Value){
            id_B = exchange.CreateOrder(pair_b, "buy", ticker_B.Sell, _N(Ice_Value / (ticker_B.Sell * CtVal_b), precision[pair_b].AmountPrecision))
        }
        if( aim_value - position_A.amount*CtVal_a*ticker_A.Last > Trade_Value && position_A.amount*CtVal_a*ticker_A.Last < Max_Value){
            id_A = exchange.CreateOrder(pair_a, "buy", ticker_A.Sell, _N(Ice_Value / (ticker_A.Sell * CtVal_a), precision[pair_a].AmountPrecision))
        }
        if( aim_value + position_B.amount*CtVal_b*ticker_B.Last > Trade_Value &&  position_B.amount*CtVal_b*ticker_B.Last > -Max_Value){
            id_B = exchange.CreateOrder(pair_b, "sell", ticker_B.Buy, _N(Ice_Value / (ticker_B.Buy * CtVal_b), precision[pair_b].AmountPrecision))
        }
        if(id_A){
            exchange.CancelOrder(id_A) //Cancel directly here
        }
        if(id_B){
            exchange.CancelOrder(id_B)
        }
        let table = {
            type: "table",
            title: "trading Information",
            cols: ["initial equity", "current equity", Pair_A+"position", Pair_B+"position", Pair_A+"holding price", Pair_B+"holding price", Pair_A+"profits", Pair_B+"profits", Pair_A+"price", Pair_B+"price", "current price comparison", "average price comparison", "deviation from average price", "loop delay"],
            rows: [[_N(_G('init_eq'),2), _N(total_eq,2), _N(position_A.amount*CtVal_a*ticker_A.Last, 1), _N(position_B.amount*CtVal_b*ticker_B.Last,1),
                _N(position_A.price, precision[pair_a].PircePrecision), _N(position_B.price, precision[pair_b].PircePrecision),
                _N(position_A.profit, 1), _N(position_B.profit, 1), ticker_A.Last, ticker_B.Last,
                _N(ticker_A.Last / ticker_B.Last,6), _N(ratio, 6), _N(diff, 4), (Date.now() - start_loop_time)+"ms"
            ]]
        }
        LogStatus("`" + JSON.stringify(table) + "`") //This function will display a table containing the above information on the robot page.
        Sleep(Interval * 1000) //Sleep time in ms
    }
}

আরো