एफएमजेड आधारित ऑर्डर सिंक्रोनस मैनेजमेंट सिस्टम डिजाइन (1)

लेखक:निनाबादास, बनाया गयाः 2022-04-06 15:08:26, अद्यतन किया गयाः 2022-04-24 18:00:51

एफएमजेड आधारित ऑर्डर सिंक्रोनस मैनेजमेंट सिस्टम डिजाइन (1)

एफएमजेड डाइजेस्ट पर पिछले लेखों में, हमने कई क्रम और स्थिति सिंक्रोनस रणनीतियों को डिजाइन किया है।

इन डिजाइनों में संदर्भ खाते और सिंक्रोनस खाते को एक ही रणनीति में लिया जाता है ताकि आदेशों और पदों के सिंक्रनाइज़ेशन को महसूस करने के लिए प्रबंधित किया जा सके। आज, हम एक अलग डिजाइन की कोशिश कर सकते हैं; एफएमजेड के शक्तिशाली विस्तारित एपीआई इंटरफ़ेस के आधार पर, यहां हम एक ऑर्डर सिंक्रोनस प्रबंधन प्रणाली डिजाइन करते हैं।

डिजाइन सोच

सबसे पहले, हमें कुछ अच्छे सुझावों और आवश्यकताओं की आवश्यकता है। उपरोक्त दो पिछले आदेशों और पदों के सिंक्रनाइज़ेशन रणनीतियों में कई स्पष्ट नुकसान हैं। आइए उन पर एक साथ चर्चा करेंः

  • 1. रणनीति बॉट सिंक्रनाइज़ेशन को लागू करने वाले उपयोगकर्ताओं के पास संदर्भ खाता प्लेटफॉर्म की एपीआई कुंजी और सिंक्रनाइज़ेशन खाते की एपीआई कुंजी होनी चाहिए। उपयोग के परिदृश्य के लिए, समस्या यह हैः आपके अन्य प्लेटफ़ॉर्म खातों के लिए आपके अपने खातों में से एक का पालन करना ठीक है। लेकिन यह उस परिदृश्य के लिए कष्टप्रद हो सकता है जहां संदर्भ खाते और सिंक्रनाइज़ेशन खाते का एक ही मालिक नहीं है। सिंक्रनाइज़ेशन खाते का मालिक कभी-कभी सुरक्षा कारणों से अपने प्लेटफ़ॉर्म खाते की एपीआई कुंजी प्रदान करने के इच्छुक नहीं होता है। लेकिन एपीआई कुंजी प्रदान किए बिना सिंक्रनाइज़ेशन ट्रेडिंग के लिए ऑर्डर कैसे करें?

    समाधान: एफएमजेड विस्तारित एपीआई का उपयोग करें, सिंक्रनाइज़ेशन खाते के मालिक (ऑर्डर पर्यवेक्षक) को केवल एफएमजेड क्वांट ट्रेडिंग प्लेटफॉर्म को पंजीकृत करने की आवश्यकता है, और फिर एक रणनीति चलाएं (इस लेख में डिज़ाइन की गई प्रणाली मेंःOrder Synchronous Management System (Synchronous Server)फिर, एफएमजेड की विस्तारित एपीआई कुंजी (ध्यान दें कि यह प्लेटफ़ॉर्म खाते की एपीआई कुंजी नहीं है) और ऑर्डर सिंक्रनाइज़ेशन प्रबंधन प्रणाली (एकीकृत सर्वर) की बॉट आईडी संदर्भ खाते के मालिक (ऑर्डर स्वामी) को प्रदान की जाएगी। जब संदर्भ खाते के मालिक (ऑर्डर के मालिक) का बॉट (Order Synchronous Management System Library (Single Server)इस लेख में डिजाइन की गई प्रणाली में) एक संकेत भेजता है, सिंक्रनाइज़ेशन खाते के मालिक का बॉट ट्रेडिंग संकेत प्राप्त करेगा। आदेश स्वचालित रूप से बाद में रखा जाएगा।

  • 2. कई डेवलपर्स के पास बेहतर रणनीतियाँ हैं और ऊपर वर्णित दो पिछले आदेश और स्थिति सिंक्रनाइज़ेशन रणनीतियों का उपयोग नहीं कर सकते हैं। क्योंकि इसके लिए इन सिंक्रनाइज़ेशन रणनीतियों के साथ अपनी रणनीतियों को मर्ज करने की आवश्यकता है, और उनकी रणनीतियों को काफी संशोधित करने की आवश्यकता हो सकती है, जो समय लेने वाली और श्रम-गहन है। क्या आपके कुछ परिपक्व रणनीतियों को सीधे ऑर्डर सिंक्रनाइज़ेशन फ़ंक्शन वाले लोगों के लिए अपग्रेड करने का एक अच्छा तरीका है?

    समाधान: आप एक आदेश सिंक्रोनस टेम्पलेट लाइब्रेरी डिजाइन कर सकते हैंOrder Synchronous Management System Library (Single Server)लेख में डिजाइन की गई प्रणाली में रणनीति), ताकि संदर्भ खाते के मालिक (ऑर्डर के मालिक) सीधे इस टेम्पलेट लाइब्रेरी को अपनी रणनीति में क्रम और स्थिति सिंक्रनाइज़ेशन प्राप्त करने के लिए सम्मिलित कर सकें।

  • 3.एक अतिरिक्त बॉट को कम करें अंतिम दोष यह है कि यदि आप ऊपर वर्णित दो पूर्ववर्ती आदेशों और स्थिति सिंक्रनाइज़ेशन रणनीतियों का उपयोग करते हैं, तो बॉट निगरानी के लिए संदर्भ खाते (आदेशों के साथ खाता) की एक अतिरिक्त स्थिति खोलना आवश्यक है। समाधान: फ़ंक्शन को संदर्भ खाता रणनीति में एम्बेड करने के लिए टेम्पलेट लाइब्रेरी का प्रयोग करें.

अतः इस प्रणाली में दो भाग होते हैंः 1.ऑर्डर सिंक्रोनस मैनेजमेंट सिस्टम लाइब्रेरी (एकल सर्वर) 2.ऑर्डर सिंक्रोनस मैनेजमेंट सिस्टम (सिंक्रोनस सर्वर)

एक बार जब हम अपनी मांगों को सुनिश्चित कर लेते हैं, तो चलिए डिजाइन करना शुरू करते हैं!

डिजाइन 1: ऑर्डर सिंक्रोनस मैनेजमेंट सिस्टम लाइब्रेरी (एकल सर्वर)

ध्यान दें कि यहाँ यह एक रणनीति नहीं है, लेकिन एक FMZ टेम्पलेट पुस्तकालय है, जो FMZ एपीआई प्रलेखन में खोज किया जा सकता है और हम यहाँ चर्चा नहीं करेंगे।

टेम्पलेट कोडः

// Global variable
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 position
        var tradeDirection = type == PD_LONG ? "buy" : "sell"
        // Send signal
        msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)        
    } else if (delta < 0) {
        // Open position 
        var tradeDirection = type == PD_LONG ? "closebuy" : "closesell"
        if (nowAmount <= 0) {
            Log("No position detected")
            return 
        }
        // Send signal 
        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 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 support futures order supervising"
    }

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

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

        // Monitor position 
        var keyInitRefPosAmount = "refPos-" + exIndex + "-" + symbol + "-" + ct    // refPos-exIndex-symbol-contractType
        var initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
        if (!initRefPosAmount) {
            // The data is not initialized; initialize it          
            mapInitRefPosAmount[keyInitRefPosAmount] = getPosAmount(_C(ex.GetPosition), ct)
            initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
        }

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

        // Detect changes 
        if (!(longPosDelta == 0 && shortPosDelta == 0)) {
            // Execute long position action 
            if (longPosDelta != 0) {
                Log(ex.GetName(), ex.GetLabel(), symbol, ct, "Execute long position order supervision, change volume:", longPosDelta)
                follow(nowRefPosAmount, symbol, ct, PD_LONG, longPosDelta)
            }
            // Execute short position action 
            if (shortPosDelta != 0) {
                Log(ex.GetName(), ex.GetLabel(), symbol, ct, "Execute short position order supervision, change volume:", shortPosDelta)
                follow(nowRefPosAmount, symbol, ct, PD_SHORT, shortPosDelta)
            }

            // After executing the order supervision operation, update  
            mapInitRefPosAmount[keyInitRefPosAmount] = nowRefPosAmount
        }

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

$.getTbl = function() {
    var tbl = {
        "type" : "table", 
        "title" : "Synchrodata", 
        "cols" : [], 
        "rows" : []
    }
    // Construct the table title 
    tbl.cols.push("Monitoring account:refPos-exIndex-symbol-contractType")
    tbl.cols.push(`Mintoring position:{"timestamp":xxx,"long position volume":xxx,"short position volume":xxx}`)
    _.each(fmzExtendApis, function(extendApiData, index) {
        tbl.cols.push(keyName_robotId + "-" + index)
    })
    
    // Write in the data 
    _.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
}

// Invocation example of the strategy in the template
function main() {
    // Clear all logs
    LogReset(1)

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

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

    // Timed trading time interval
    var tradeInterval = 1000 * 60 * 3        // trade every three minutes, to observe the order supervising signal  
    var lastTradeTS = new Date().getTime()
    
    while (true) {
        // Other logic of the strategy...

        // Used to test the simulated trade trigger  
        var ts = new Date().getTime()
        if (ts - lastTradeTS > tradeInterval) {
            Log("Simulated strategy with orders has trades, and positions changed", "#FF0000")
            exchanges[0].SetDirection("buy")
            exchanges[0].Buy(-1, 1)
            lastTradeTS = ts
        }

        // Call the interface function in the template 
        $.PosMonitor(0, "ETH_USDT", "swap")    // You can set multiple monitors, to minitor different exchange objects in the strategy with orders
        var tbl = $.getTbl()
        
        // Display the status bar 
        LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
        Sleep(1000)
    }
}

डिजाइन बहुत सरल है, पुस्तकालय 2 कार्य है. जब एक कार्यक्रम व्यापार मंच पर एफएमजेड रणनीति कॉलOrder Synchronous Management System Library (Single Server)टेम्पलेट क्लास लाइब्रेरी. यह रणनीति तब निम्नलिखित कार्यों का उपयोग कर सकती है.

  • $.पोस मॉनिटर इस फ़ंक्शन का प्रभाव रणनीति में विनिमय वस्तुओं की स्थिति परिवर्तन की निगरानी करना है, और फिर टेम्पलेट के मापदंडों में सेट बॉट को ट्रेडिंग सिग्नल भेजना हैः ऑर्डर सिंक्रोनस मैनेजमेंट सिस्टम लाइब्रेरी (एकल सर्वर) ।
  • $.getTbl यह फ़ंक्शन मॉनिटर किए गए सिंक्रोनस डेटा को लौटाता है।

उपयोग का उदाहरण हैmainऑर्डर सिंक्रोनस मैनेजमेंट सिस्टम लाइब्रेरी (एकल सर्वर) में फ़ंक्शनः

// Invocation example of the strategy in the template 
function main() {
    // Clear all logs 
    LogReset(1)

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

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

    // Timed trading time interval
    var tradeInterval = 1000 * 60 * 3        // trade every three minutes, to observe the order supervising signal  
    var lastTradeTS = new Date().getTime()
    
    while (true) {
        // Other logic of the strateg...

        // Used to test the simulated trade trigger  
        var ts = new Date().getTime()
        var ts = new Date().getTime()
        if (ts - lastTradeTS > tradeInterval) {
            Log("Simulated strategy with orders has trades, and positions changed", "#FF0000")
            exchanges[0].SetDirection("buy")
            exchanges[0].Buy(-1, 1)
            lastTradeTS = ts
        }

        // Use the interface function of the template 
        $.PosMonitor(0, "ETH_USDT", "swap")    // You can set multiple monitors to monitor different exchange objects on an strategy with orders
        var tbl = $.getTbl()
        
        // Display the status bar
        LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
        Sleep(1000)
    }
}

एक टेम्पलेट लाइब्रेरी स्वयं एक रणनीति बॉट भी बना सकती है, जिसका उपयोग आमतौर पर टेम्पलेट लाइब्रेरी का परीक्षण करने के लिए किया जाता है. उदाहरण के लिए इस टेम्पलेट के लिए एक परीक्षण. आप समझ सकते हैं किmainटेम्पलेट में फ़ंक्शन हैmainअपनी एक रणनीति का कार्य।

परीक्षण कोड को परीक्षण के लिए ओकेएक्स सिमुलेटेड बॉट का उपयोग करने के लिए लिखा गया है, और ओकेएक्स सिमुलेटेड बॉट की एपीआई कुंजी को एफएमजेड पर एक संदर्भ खाते (ऑर्डर के साथ) के रूप में कॉन्फ़िगर करने की आवश्यकता है, और मुख्य फ़ंक्शन सिमुलेटेड बॉट पर स्विच करना शुरू कर देता है। फिर ट्रेडिंग जोड़ी को ETH_USDT पर सेट करें, और कॉन्ट्रैक्ट को स्वैप करने के लिए सेट करें। फिर एक जबकि लूप दर्ज करें। लूप में, रणनीति ट्रेडों के ट्रिगर का अनुकरण करने के लिए हर 3 मिनट में एक ऑर्डर रखा जाता है।$.PosMonitor(0, "ETH_USDT", "swap")जबकि लूप में बुलाया जाता है, और बुलाया फ़ंक्शन का पहला पैरामीटर 0 है, जिसका अर्थ है एक्सचेंज ऑब्जेक्ट एक्सचेंजों[0], ट्रेडिंग जोड़ी ETH_USDT, और स्वैप अनुबंध की निगरानी करना। फिर कॉल करें$.getTbl()चार्ट की जानकारी प्राप्त करने के लिए, और उपयोगLogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")स्थिति पट्टी पर प्रदर्शित चार्ट डेटा बनाने के लिए।

तो आप देखते हैं, जब तक$.PosMonitor(0, "ETH_USDT", "swap")टेम्पलेट को कॉल करने वाली रणनीति में प्रयोग किया जाता है, रणनीति का कार्य एक निश्चित प्रतीक की स्थिति की निगरानी करना और स्थिति परिवर्तन संदेश को आगे बढ़ाना हो सकता है।

परीक्षण से पहले, पैरामीटर डिजाइन का वर्णन करेंOrder Synchronous Management System Library (Single Server)रणनीति: मैं सिर्फ आदेश ले जाने के एक समारोह के साथ एक रणनीति उन्नयन बनाने के लिए टेम्पलेट के इंटरफेस समारोह का उपयोग करने के बारे में बात की. तो कौन संकेत भेजा जाता है जब स्थिति बदल जाती है? किसके लिए भेजने का प्रश्न पैरामीटर द्वारा कॉन्फ़िगर किया जाता हैorder synchronous management system library (Single Server).

img

आप पांच मापदंडों को देख सकते हैं, जो अधिकतम पांच धक्का का समर्थन कर सकते हैं (यदि आपको धक्का संख्या बढ़ाने की आवश्यकता है, तो आप इसे स्वयं बढ़ा सकते हैं); मापदंडों का डिफ़ॉल्ट एक खाली स्ट्रिंग है, अर्थात् संसाधित नहीं है। विन्यस्त स्ट्रिंग प्रारूप मेंः लेबल, robotId, accessKey, secretKey

  • लेबल सिंक्रोनस खाते का लेबल, जिसका उपयोग किसी खाते को लेबल करने के लिए किया जाता है; लेबल का नाम यादृच्छिक रूप से सेट किया जा सकता है।

  • robotId बॉट आईडी; बॉट आईडीorder synchronous management system (Synchronous Server)सिंक्रोनस खाते के मालिक द्वारा बनाया गया।

  • accessKey एफएमजेड विस्तारित एपीआई की एक्सेसकी।

  • गुप्त कुंजी FMZ विस्तारित एपीआई की गुप्त कुंजी।

फिर, हम एक सरल परीक्षण कर सकते हैं।

ऑर्डर सिंक्रोनस मैनेजमेंट सिस्टम लाइब्रेरी (एकल सर्वर) बॉट ऑपरेशनः

img

ऑर्डर सिंक्रोनस मैनेजमेंट सिस्टम (सिंक्रोनस सर्वर) बॉट ने संकेत प्राप्त कियाः ऑर्डर सिंक्रोनस मैनेजमेंट सिस्टम (सिंक्रोनस सर्वर) अब हमारे द्वारा पूरी तरह से डिजाइन नहीं किया गया है, और हम एक सरल कोड का उपयोग कर सकते हैं इसे महसूस करने के लिए, व्यापार के बिना, केवल प्रिंट सिग्नलः

ऑर्डर सिंक्रोनस मैनेजमेंट सिस्टम (सिंक्रोनस सर्वर) अस्थायी कोडः

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 synchronous management system (Synchronous Server)केवल अस्थायी कोड है, और हम इसके डिजाइन पर आगे चर्चा कर सकते हैं अगले लेख में।


अधिक