संसाधन लोड हो रहा है... लोड करना...

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

लेखक:FMZ~Lydia, बनाया गयाः 2022-11-07 10:20:01, अद्यतन किया गयाः 2023-09-15 20:45:23

img

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

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

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

डिजाइन विचार

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

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

    समाधान: FMZ के विस्तारित एपीआई इंटरफ़ेस का उपयोग करके, सिंक्रनाइज़ किए गए खाते (ऑर्डर फॉलोअर) के मालिक को केवल FMZ क्वांट ट्रेडिंग प्लेटफॉर्म पर एक खाता पंजीकृत करने की आवश्यकता है, फिर एक रणनीति चलाएं (इस लेख में डिज़ाइन की गई प्रणाली मेंःOrder Synchronous ServerReal Bot में रणनीति). फिर बस 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 पिछले आदेशों का उपयोग करते हैं, तो स्थिति सिंक्रनाइज़ेशन रणनीति ऊपर वर्णित है। संदर्भ खाते की स्थिति की निगरानी के लिए एक अतिरिक्त वास्तविक बॉट खोलना आवश्यक है (ऑर्डर नेताओं के लिए खाता) । समाधान: संदर्भ खाता रणनीति में कार्यक्षमता एम्बेड करने के लिए टेम्पलेट वर्ग पुस्तकालय का उपयोग करें.

तो इस प्रणाली में 2 भाग होते हैंः

  1. ऑर्डर सिंक्रनाइज़ेशन प्रबंधन प्रणाली वर्ग पुस्तकालय (एकल सर्वर)
  2. ऑर्डर सिंक्रनाइज़ेशन प्रबंधन प्रणाली (सिंक्रोनस सर्वर)

एक बार जब हम अपनी आवश्यकताओं को परिभाषित कर लेते हैं, तो चलिए डिजाइन करना शुरू करते हैं!

डिजाइन 1: ऑर्डर सिंक्रनाइज़ेशन प्रबंधन प्रणाली वर्ग पुस्तकालय (एकल सर्वर)

ध्यान दें कि यह एक रणनीति नहीं है. यह FMZ का एक टेम्पलेट क्लास लाइब्रेरी है. एक टेम्पलेट क्लास लाइब्रेरी की अवधारणा को FMZ एपीआई प्रलेखन में खोजा जा सकता है और हम इसे फिर से नहीं दोहराएंगे.

टेम्पलेट वर्ग पुस्तकालय कोडः

// 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 कार्यात्मक कार्य हैं। जब एफएमजेड प्लेटफॉर्म पर एक प्रोग्रामेटिक ट्रेडिंग रणनीति टेम्पलेट क्लास लाइब्रेरी का संदर्भ देती है।Order Synchronization Management System Class Library (Single Server). तो रणनीति निम्नलिखित कार्यों का उपयोग कर सकते हैं.

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

  • $.getTbl मॉनिटर किए गए सिंक्रनाइज़ेशन डेटा पर लौटें.

उपयोग का उदाहरण है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 पर सेट करें और कॉन्ट्रैक्ट को स्वैप करने के लिए सेट करें। फिर यह एक जबकि लूप में प्रवेश करता है। लूप में, रणनीति लेनदेन के ट्रिगरिंग का अनुकरण करने के लिए हर 3 मिनट में एक ऑर्डर रखा जाता है।$.PosMonitor(0, "ETH_USDT", "swap")जबकि लूप में बुलाया जाता है, इस फ़ंक्शन का पहला पैरामीटर 0 पर पारित किया जाता है, जिसका अर्थ है कि thes एक्सचेंज ऑब्जेक्ट एक्सचेंजों की निगरानी करना[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 धक्का (यह अपने आप को विस्तारित किया जा सकता है अगर यह वृद्धि की जरूरत है), डिफ़ॉल्ट पैरामीटर खाली स्ट्रिंग्स हैं, यानी, संसाधित नहीं. विन्यास स्ट्रिंग प्रारूपः label,robotId,accessKey,secretKey

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

  • robotId रोबोट आईडी,Order Synchronous Serverवास्तविक बॉट सिंक्रोनस खाते के मालिक द्वारा बनाया गया।

  • accessKey एफएमजेड की विस्तारित एपीआई अभिगम कुंजी

  • गुप्त कुंजी एफएमजेड का विस्तारित एपीआई गुप्त कुंजी

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

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)अस्थायी कोड है, हम अगले अंक में इसके डिजाइन का अन्वेषण करना जारी रखेंगे।


संबंधित

अधिक