এফএমজেড কোয়ান্টের উপর ভিত্তি করে অর্ডার সিঙ্ক্রোনাইজেশন ম্যানেজমেন্ট সিস্টেমের নকশা (1)

লেখক:লিডিয়া, সৃষ্টিঃ ২০২২-১১-০৭ ১০ঃ২০:০১, আপডেটঃ ২০২৩-০৯-১৫ ২০ঃ৪৫ঃ২৩

img

এফএমজেড কোয়ান্টের উপর ভিত্তি করে অর্ডার সিঙ্ক্রোনাইজেশন ম্যানেজমেন্ট সিস্টেমের নকশা (1)

এফএমজেড লাইব্রেরির পূর্ববর্তী নিবন্ধগুলিতে, আমরা অর্ডার এবং অবস্থানের জন্য বেশ কয়েকটি ধরণের সিঙ্ক্রোনাইজেশন কৌশল ডিজাইন করেছি।

এগুলি অর্ডার এবং অবস্থানের সিঙ্ক্রোনাইজেশন অর্জনের জন্য একটি কৌশলতে রেফারেন্স অ্যাকাউন্ট এবং সিঙ্ক্রোনাইজড অ্যাকাউন্ট পরিচালনা করে। এবং আজ আমরা একটি ভিন্ন নকশা চেষ্টা করব, আমরা এফএমজেড কোয়ান্ট ট্রেডিং প্ল্যাটফর্মের শক্তিশালী বর্ধিত এপিআই ইন্টারফেসের উপর ভিত্তি করে একটি অর্ডার সিঙ্ক্রোনাইজেশন ম্যানেজমেন্ট সিস্টেম ডিজাইন করব।

ডিজাইন আইডিয়া

প্রথমত, আমাদের কিছু ভাল পরামর্শ এবং প্রয়োজন প্রয়োজন। উপরে দুটি পূর্ববর্তী আদেশ এবং অবস্থান সিঙ্ক্রোনাইজেশন কৌশল, যা বেশ কয়েকটি সুস্পষ্ট ত্রুটি আছে, যা আমরা একসাথে আলোচনা করব।

    1. সিঙ্ক্রোনাইজেশন কৌশল ব্যবহারকারীদের রিয়েল বট অবশ্যই রেফারেন্স অ্যাকাউন্টের এক্সচেঞ্জ এপিআই কী এবং সিঙ্ক্রোনাইজেশন অ্যাকাউন্টের এক্সচেঞ্জ এপিআই কী থাকতে হবে। এই সমস্যাটি ব্যবহারের পরিস্থিতিতে ঠিক আছে যেখানে অন্য এক্সচেঞ্জ অ্যাকাউন্টগুলি তার নিজের অ্যাকাউন্ট অনুসরণ করে। তবে রেফারেন্স অ্যাকাউন্ট এবং সিঙ্ক্রোনাইজড অ্যাকাউন্ট একই মালিক নয় এমন পরিস্থিতিতে এটি সমস্যাযুক্ত হতে পারে। কখনও কখনও সিঙ্ক্রোনাইজড অ্যাকাউন্টের মালিক সুরক্ষার কারণে নিজের এক্সচেঞ্জ অ্যাকাউন্টের এপিআই কী সরবরাহ করতে চায় না, তবে এপিআই কী সরবরাহ না করে অর্ডার লেনদেনগুলি কীভাবে সিঙ্ক্রোনাইজ করবেন?

    সমাধানঃ এফএমজেডের বর্ধিত এপিআই ইন্টারফেস ব্যবহার করে, সিঙ্ক্রোনাইজড অ্যাকাউন্টের মালিক (অর্ডার অনুসরণকারী) কেবল এফএমজেড কোয়ান্ট ট্রেডিং প্ল্যাটফর্মে একটি অ্যাকাউন্ট নিবন্ধন করতে হবে, তারপরে একটি কৌশল চালান (এই নিবন্ধে ডিজাইন করা সিস্টেমেঃOrder Synchronous Serverতারপর শুধু FMZ বর্ধিত API KEY প্রদান করুন (নোট করুন যে এটি এক্সচেঞ্জ অ্যাকাউন্টের API KEY নয়) এবং অর্ডার সিঙ্ক্রোনাস সার্ভার রিয়েল বট আইডি রেফারেন্স অ্যাকাউন্টের মালিককে (অর্ডার লিডার) । যখন রেফারেন্স অ্যাকাউন্টের মালিক (অর্ডার অনুসরণকারী) প্রকৃত বট (অর্ডার অনুসরণকারী)Order Synchronization Management System Class Library (Single Server)এই নিবন্ধে ডিজাইন করা সিস্টেমে) একটি সংকেত পাঠায়, সিঙ্ক্রোনাইজেশন অ্যাকাউন্টের মালিকের প্রকৃত বট ট্রেডিং সংকেতটি গ্রহণ করবে এবং স্বয়ংক্রিয়ভাবে পরবর্তী অর্ডারটি স্থাপন করবে।

    1. অনেক ডেভেলপারদের ভাল কৌশল আছে, কিন্তু তারা উপরে বর্ণিত 2 অতীত অর্ডার এবং অবস্থান সিঙ্ক্রোনাইজেশন কৌশল ব্যবহার করতে পারে না। কারণ তাদের এই সিঙ্ক্রোনাইজড কৌশলগুলির সাথে তাদের নিজস্ব কৌশলগুলিকে সংহত করতে হবে এবং কৌশলগুলিকে ব্যাপকভাবে পরিবর্তন করতে হতে পারে, যার জন্য অনেক কাজ এবং প্রচেষ্টা খরচ হবে। আপনার পরিপক্ক কৌশলগুলির কিছু সরাসরি অর্ডার সিঙ্ক্রোনাইজেশন ফাংশনে আপগ্রেড করার একটি ভাল উপায় আছে কি? সমাধানঃ আপনি একটি অর্ডার সিঙ্ক্রোনাইজেশন টেমপ্লেট ক্লাস লাইব্রেরি ডিজাইন করতে পারেনOrder Synchronization Management System Class Library (Single Server)এই নিবন্ধে ডিজাইন করা সিস্টেমে কৌশল), যাতে রেফারেন্স অ্যাকাউন্টের মালিক (অর্ডার-লিডার) এই টেমপ্লেট ক্লাস লাইব্রেরিটি সরাসরি তার নিজস্ব কৌশলতে অর্ডার এবং অবস্থান সিঙ্ক্রোনাইজেশনের ফাংশন অর্জনের জন্য এম্বেড করতে পারে।
    1. আরেকটা আসল বটকে কমিয়ে আনুন। সর্বশেষ ত্রুটি হল যে আপনি যদি 2 অতীত আদেশ ব্যবহার করেন, তবে উপরে বর্ণিত অবস্থানগুলি সিঙ্ক্রোনাইজেশন কৌশল। রেফারেন্স অ্যাকাউন্টের অবস্থানগুলি (অর্ডার নেতাদের জন্য অ্যাকাউন্ট) পর্যবেক্ষণ করতে একটি অতিরিক্ত বাস্তব বট খুলতে হবে। সমাধানঃ টেমপ্লেট ক্লাস লাইব্রেরি ব্যবহার করে রেফারেন্স অ্যাকাউন্ট কৌশলতে কার্যকারিতা এম্বেড করুন।

সুতরাং সিস্টেমটি ২টি অংশ নিয়ে গঠিত:

  1. অর্ডার সিঙ্ক্রোনাইজেশন ম্যানেজমেন্ট সিস্টেম ক্লাস লাইব্রেরি (একক সার্ভার)
  2. অর্ডার সিঙ্ক্রোনাইজেশন ম্যানেজমেন্ট সিস্টেম (সিঙ্ক্রোনস সার্ভার)

একবার আমরা আমাদের চাহিদা নির্ধারণ করলে, আসুন আমরা ডিজাইন শুরু করি!

ডিজাইন ১ঃ অর্ডার সিঙ্ক্রোনাইজেশন ম্যানেজমেন্ট সিস্টেম ক্লাস লাইব্রেরি (একক সার্ভার)

মনে রাখবেন যে এটি একটি কৌশল নয়। এটি এফএমজেডের একটি টেমপ্লেট ক্লাস লাইব্রেরি। একটি টেমপ্লেট ক্লাস লাইব্রেরির ধারণাটি এফএমজেড এপিআই ডকুমেন্টেশনে অনুসন্ধান করা যেতে পারে এবং আমরা এটি আবার পুনরাবৃত্তি করব না।

টেমপ্লেট ক্লাস লাইব্রেরির কোডঃ

// Global variables
var keyName_label = "label"
var keyName_robotId = "robotId"
var keyName_extendAccessKey = "extendAccessKey"
var keyName_extendSecretKey = "extendSecretKey"
var fmzExtendApis = parseConfigs([config1, config2, config3, config4, config5])
var mapInitRefPosAmount = {}

function parseConfigs(configs) {
    var arr = []
    _.each(configs, function(config) {
        if (config == "") {
            return 
        }
        var strArr = config.split(",")
        if (strArr.length != 4) {
            throw "configs error!"
        }
        var obj = {}
        obj[keyName_label] = strArr[0]
        obj[keyName_robotId] = strArr[1]
        obj[keyName_extendAccessKey] = strArr[2]
        obj[keyName_extendSecretKey] = strArr[3]
        arr.push(obj)
    })
    return arr 
}

function getPosAmount(pos, ct) {
    var longPosAmount = 0
    var shortPosAmount = 0
    _.each(pos, function(ele) {
        if (ele.ContractType == ct && ele.Type == PD_LONG) {
            longPosAmount = ele.Amount
        } else if (ele.ContractType == ct && ele.Type == PD_SHORT) {
            shortPosAmount = ele.Amount
        }
    })
    var timestamp = new Date().getTime()
    return {ts: timestamp, long: longPosAmount, short: shortPosAmount}
}

function sendCommandRobotMsg (robotId, accessKey, secretKey, msg) {
    // https://www.fmz.com/api/v1?access_key=xxx&secret_key=yyyy&method=CommandRobot&args=[186515,"ok12345"]
    var url = "https://www.fmz.com/api/v1?access_key=" + accessKey + "&secret_key=" + secretKey + "&method=CommandRobot&args=[" + robotId + ',"' + msg + '"]'
    Log(url)
    var ret = HttpQuery(url)
    return ret 
}

function follow(nowPosAmount, symbol, ct, type, delta) {
    var msg = ""
    var nowAmount = type == PD_LONG ? nowPosAmount.long : nowPosAmount.short
    if (delta > 0) {
        // open the position
        var tradeDirection = type == PD_LONG ? "buy" : "sell"
        // send signals
        msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)        
    } else if (delta < 0) {
        // close the position
        var tradeDirection = type == PD_LONG ? "closebuy" : "closesell"
        if (nowAmount <= 0) {
            Log("no positions found")
            return 
        }
        // send signals
        msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)
    } else {
        throw "error"
    }
    if (msg) {
        _.each(fmzExtendApis, function(extendApiConfig) {
            var ret = sendCommandRobotMsg(extendApiConfig[keyName_robotId], extendApiConfig[keyName_extendAccessKey], extendApiConfig[keyName_extendSecretKey], msg)
            Log("call the CommandRobot interface, ", "label:", extendApiConfig[keyName_label], ",  msg:", msg, ",  ret:", ret)
            Sleep(1000)
        })
    }
}

$.PosMonitor = function(exIndex, symbol, ct) {    
    var ts = new Date().getTime()
    var ex = exchanges[exIndex]
    // judge the type of ex
    var exName = ex.GetName()
    var isFutures = exName.includes("Futures_")
    var exType = isFutures ? "futures" : "spot"
    if (!isFutures) {
        throw "only future-following is supported"
    }

    if (exType == "futures") {
        // caching symbol ct
        var buffSymbol = ex.GetCurrency()
        var buffCt = ex.GetContractType()

        // switch to the corresponding contract pair, contract code
        ex.SetCurrency(symbol)
        if (!ex.SetContractType(ct)) {
            throw "SetContractType failed"
        }

        // monitor positions
        var keyInitRefPosAmount = "refPos-" + exIndex + "-" + symbol + "-" + ct    // refPos-exIndex-symbol-contractType
        var initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
        if (!initRefPosAmount) {
            // no initialization data, initialize it
            mapInitRefPosAmount[keyInitRefPosAmount] = getPosAmount(_C(ex.GetPosition), ct)
            initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
        }

        // monitor
        var nowRefPosAmount = getPosAmount(_C(ex.GetPosition), ct)
        // calculate the position changes
        var longPosDelta = nowRefPosAmount.long - initRefPosAmount.long
        var shortPosDelta = nowRefPosAmount.short - initRefPosAmount.short

        // detect changes
        if (!(longPosDelta == 0 && shortPosDelta == 0)) {
            // Perform long positions
            if (longPosDelta != 0) {
                Log(ex.GetName(), ex.GetLabel(), symbol, ct, "Perform long position-following, changes in volume:", longPosDelta)
                follow(nowRefPosAmount, symbol, ct, PD_LONG, longPosDelta)
            }
            // Perform short positions
            if (shortPosDelta != 0) {
                Log(ex.GetName(), ex.GetLabel(), symbol, ct, "Perform short position-following, changes in volume:", shortPosDelta)
                follow(nowRefPosAmount, symbol, ct, PD_SHORT, shortPosDelta)
            }

            // Update after performing the order-following operation
            mapInitRefPosAmount[keyInitRefPosAmount] = nowRefPosAmount
        }

        // restore symbol ct
        ex.SetCurrency(buffSymbol)
        ex.SetContractType(buffCt)
    } else if (exType == "spot") {
        // Spots
    }
}

$.getTbl = function() {
    var tbl = {
        "type" : "table", 
        "title" : "synchronization of data", 
        "cols" : [], 
        "rows" : []
    }
    // construct the table headers
    tbl.cols.push("monitor the account: refPos-exIndex-symbol-contractType")
    tbl.cols.push(`monitor the position: {"timestamp":xxx,"long positions":xxx,"short positions":xxx}`)
    _.each(fmzExtendApis, function(extendApiData, index) {
        tbl.cols.push(keyName_robotId + "-" + index)
    })
    
    // Write data in
    _.each(mapInitRefPosAmount, function(initRefPosAmount, key) {
        var arr = [key, JSON.stringify(initRefPosAmount)]
        _.each(fmzExtendApis, function(extendApiData) {
            arr.push(extendApiData[keyName_robotId])
        })
        tbl.rows.push(arr)
    })

    return tbl
}

// Example of the strategy call that references the template class library
function main() {
    // Clear all logs
    LogReset(1)

    // Switch to OKEX demo to test
    exchanges[0].IO("simulate", true)

    // Set the contract
    exchanges[0].SetCurrency("ETH_USDT")
    exchanges[0].SetContractType("swap")

    // Timed trading interval
    var tradeInterval = 1000 * 60 * 3        // Trade for every three minutes to observe the order-following signals
    var lastTradeTS = new Date().getTime()
    
    while (true) {
        // Other logic of the strategy...

        // Simulated trading triggers for testing
        var ts = new Date().getTime()
        if (ts - lastTradeTS > tradeInterval) {
            Log("Trade the simulation order-leading strategies, position changes", "#FF0000")
            exchanges[0].SetDirection("buy")
            exchanges[0].Buy(-1, 1)
            lastTradeTS = ts
        }

        // Interface functions that use templates
        $.PosMonitor(0, "ETH_USDT", "swap")    // Multiple monitors can be set up to monitor different exchange objects on the order-following strategy  
        var tbl = $.getTbl()
        
        // Display status bar
        LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
        Sleep(1000)
    }
}

নকশা খুব সহজ, ক্লাস লাইব্রেরি 2 কার্যকরী ফাংশন আছে. যখন FMZ প্ল্যাটফর্মে একটি প্রোগ্রাম্যাটিক ট্রেডিং কৌশল টেমপ্লেট ক্লাস লাইব্রেরি উল্লেখOrder Synchronization Management System Class Library (Single Server). তারপর কৌশল নিম্নলিখিত ফাংশন ব্যবহার করতে পারেন.

  • $.পোস্ট মনিটর এই ফাংশনটির উদ্দেশ্য হল কৌশলটিতে বিনিময় বস্তুর অবস্থানের পরিবর্তন পর্যবেক্ষণ করা এবং তারপর টেমপ্লেটের পরামিতিগুলিতে নির্ধারিত বাস্তব বট মার্কেটে ট্রেডিং সংকেত পাঠানোঃ অর্ডার সিঙ্ক্রোনাইজেশন ম্যানেজমেন্ট সিস্টেম ক্লাস লাইব্রেরি (একক সার্ভার) ।

  • $$$$ মনিটর করা সিঙ্ক্রোনাইজেশন ডেটাতে ফিরে যান।

ব্যবহারের উদাহরণ হলmainঅর্ডার সিঙ্ক্রোনাইজেশন ম্যানেজমেন্ট সিস্টেম ক্লাস লাইব্রেরির ফাংশন (একক সার্ভার):

// Example of the strategy call that references the template class library
function main() {
    // Clear all logs
    LogReset(1)

    // Switch to OKEX demo to test
    exchanges[0].IO("simulate", true)

    // Set the contract
    exchanges[0].SetCurrency("ETH_USDT")
    exchanges[0].SetContractType("swap")

    // Timed trading interval
    var tradeInterval = 1000 * 60 * 3        // Trade for every three minutes to observe the order-following signals
    var lastTradeTS = new Date().getTime()
    
    while (true) {
        // Other logic of the strategy...

        // Simulated trading triggers for testing
        var ts = new Date().getTime()
        if (ts - lastTradeTS > tradeInterval) {
            Log("Trade the simulation order-leading strategies, position changes", "#FF0000")
            exchanges[0].SetDirection("buy")
            exchanges[0].Buy(-1, 1)
            lastTradeTS = ts
        }

        // Interface functions by using templates
        $.PosMonitor(0, "ETH_USDT", "swap")    // Multiple monitors can be set up to monitor different exchange objects on the order-following strategy  
        var tbl = $.getTbl()
        
        // Display status bar
        LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
        Sleep(1000)
    }
}

একটি টেমপ্লেট ক্লাস লাইব্রেরি নিজেই একটি কৌশল বাস্তব বট তৈরি করতে পারে, যা সাধারণত টেমপ্লেট ক্লাস লাইব্রেরি পরীক্ষা করতে ব্যবহৃত হয়, যেমন টেমপ্লেট পরীক্ষা। আপনি বিবেচনা করতে পারেন যেmainএকটি টেমপ্লেটে ফাংশন হলmainআপনার নিজস্ব কৌশলগুলির একটির ফাংশন।

পরীক্ষার কোডটি OKEX ডেমো ব্যবহার করে পরীক্ষা করার জন্য লেখা হয়েছে, আপনাকে FMZ এ একটি রেফারেন্স অ্যাকাউন্ট (অর্ডার-লিডিং) হিসাবে OKEX ডেমো এপিআই কী কনফিগার করতে হবে, এবং এটি মূল ফাংশনে ডেমোতে স্যুইচ করতে শুরু করে। তারপরে ট্রেডিং জোড়াটি ETH_USDT এ সেট করুন এবং চুক্তিটি স্যুইপ করতে সেট করুন। তারপরে এটি একটি while লুপ প্রবেশ করে। লুপে, কৌশল লেনদেনের ট্রিগারিং সিমুলেট করার জন্য প্রতি 3 মিনিটে একটি অর্ডার স্থাপন করা হয়।$.PosMonitor(0, "ETH_USDT", "swap")এই ফাংশনের প্রথম প্যারামিটারটি 0 এ পাস করা হয়, যার অর্থ হ'ল এক্সচেঞ্জ অবজেক্ট এক্সচেঞ্জগুলি পর্যবেক্ষণ করা, ETH_USDT ট্রেডিং জুটি, সুপ চুক্তি পর্যবেক্ষণ করা। তারপরে এটি কল করবে$.getTbl()চার্ট তথ্য পেতে, ব্যবহার করেLogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")স্ট্যাটাস বারে প্রদর্শিত চার্ট ডেটা তৈরি করতে।

সুতরাং আমরা দেখতে পাচ্ছি যে আমরা কৌশল করতে পারেন একটি নির্দিষ্ট প্রজাতির অবস্থান নিরীক্ষণ করার ক্ষমতা আছে, এবং অবস্থান পরিবর্তন বার্তা পাঠাতে ব্যবহার করে$.PosMonitor(0, "ETH_USDT", "swap")যে কৌশলটি টেমপ্লেটটি উল্লেখ করে।

পরীক্ষার আগে, আমরা কৌশল পরামিতি নকশা ব্যাখ্যাOrder Synchronization Management System Class Library (Single Server). আমরা শুধু কিভাবে একটি টেমপ্লেট এর ইন্টারফেস ফাংশন ব্যবহার একটি অর্ডার নেতৃস্থানীয় ফাংশন আছে একটি কৌশল আপগ্রেড করার বিষয়ে কথা বলা হয়েছে. অবস্থান পরিবর্তন যখন পাঠানো সংকেত সম্পর্কে কি, এটা কে পাঠানো হবে? কে পাঠাবে এই প্রশ্নটি প্যারামিটার দ্বারা কনফিগার করা হয়Order Synchronization Management System Class Library (Single Server).

img

আমরা দেখতে পাচ্ছি যে 5 প্যারামিটার আছে, 5 টি পর্যন্ত ধাক্কা সমর্থন (এটি বৃদ্ধি প্রয়োজন হলে নিজেদের দ্বারা প্রসারিত করা যেতে পারে), ডিফল্ট প্যারামিটার খালি স্ট্রিং হয়, অর্থাৎ, প্রক্রিয়াজাত করা হয় না. কনফিগারেশন স্ট্রিং বিন্যাসঃ লেবেল,robotId,accessKey,secretKey

  • লেবেল একটি সিঙ্ক্রোনাইজ অ্যাকাউন্টের জন্য একটি লেবেল, এটি একটি অ্যাকাউন্টের জন্য একটি লেবেল সেট করতে ব্যবহৃত হয় যার নামটি ইচ্ছা অনুযায়ী সেট করা যেতে পারে।

  • robotId রোবট আইডি,Order Synchronous Serverসিঙ্ক্রোনিক অ্যাকাউন্টের মালিকের তৈরি আসল বট।

  • অ্যাক্সেস কী এফএমজেডের এক্সটেন্ডেড এপিআই অ্যাক্সেসকী

  • সিক্রেটকি এফএমজেডের এক্সটেন্ডেড এপিআই সিক্রেট কী

অর্ডার সিঙ্ক্রোনাইজেশন ম্যানেজমেন্ট সিস্টেমের অস্থায়ী কোড (সিঙ্ক্রোনস সার্ভার):

function main() {
    LogReset(1)
    while (true) {
        var cmd = GetCommand()
        if (cmd) {
            // cmd: ETH_USDT,swap,buy,1
            Log("cmd: ", cmd)
        }
        Sleep(1000)
    }
}

img

আমরা দেখতে পাচ্ছি যে সিঙ্ক্রোনাইজড অ্যাকাউন্টের মালিকের আসল বট এই বার্তাটি পেয়েছেঃETH_USDT,swap,buy,1.. তারপর এটি আমাদের ট্রেডিং জোড়া, চুক্তি কোড, ট্রেডিং নির্দেশাবলী, এবং তথ্য পরিমাণ উপর ভিত্তি করে পরবর্তী ধাপে আমাদের নিজস্ব স্বয়ংক্রিয় অর্ডার অনুসরণ করতে অনুমতি দেবে।

এখন পর্যন্ত,Order Synchronization Management System (Synchronous Server)এটি একটি অস্থায়ী কোড, আমরা পরবর্তী সংখ্যায় এর নকশা অন্বেষণ চালিয়ে যাব।


সম্পর্কিত

আরো