Reka bentuk Sistem Pengurusan Sinkron berdasarkan Perintah FMZ (1)

Penulis:Ninabadass, Dicipta: 2022-04-06 15:08:26, Dikemas kini: 2022-04-24 18:00:51

Reka bentuk Sistem Pengurusan Sinkron berdasarkan Perintah FMZ (1)

Dalam artikel sebelumnya di FMZ Digest, kami telah merancang beberapa urutan dan kedudukan strategi synchronous.

Reka bentuk ini mengambil akaun rujukan dan akaun sinkron ke dalam strategi yang sama untuk diuruskan untuk merealisasikan penyegerakan pesanan dan kedudukan. hari ini, kita boleh mencuba reka bentuk yang berbeza; berdasarkan antara muka API lanjutan FMZ yang kuat, di sini kita merancang sistem pengurusan sinkron pesanan.

Pemikiran Reka Bentuk

Pertama sekali, kita memerlukan beberapa cadangan dan keperluan yang baik. Dua strategi penyelarasan pesanan dan kedudukan sebelumnya di atas mempunyai beberapa kelemahan yang jelas. Mari kita bincangkannya bersama:

  • 1.Pengguna yang melaksanakan penyegerakan bot strategi mesti mempunyai API KEY platform akaun rujukan dan API KEY akaun penyegerakan. Untuk senario penggunaan, masalahnya adalah: tidak mengapa untuk akaun platform lain anda mengikuti salah satu akaun anda sendiri. Tetapi ia boleh menjadi masalah untuk senario di mana akaun rujukan dan akaun penyegerakan tidak mempunyai pemilik yang sama. Pemilik akaun penyegerakan kadang-kadang tidak mahu memberikan KEY API akaun platformnya kerana pertimbangan keselamatan. Tetapi bagaimana untuk meletakkan pesanan untuk berdagang secara serentak tanpa memberikan KEY API?

    Penyelesaian: Menggunakan FMZ diperluaskan API, pemilik akaun penyelarasan (pemelihara pesanan) hanya perlu mendaftar platform perdagangan FMZ Quant, dan kemudian menjalankan strategi (dalam sistem yang direka dalam artikel ini:Order Synchronous Management System (Synchronous Server)Kemudian, KEY API diperluaskan FMZ (catat bahawa ia bukan KEY API akaun platform) dan ID bot sistem pengurusan penyegerakan pesanan (Synchronous Server) akan diberikan kepada pemilik akaun rujukan (pemilik pesanan). Apabila bot pemilik akaun rujukan (pemilik pesanan) (Order Synchronous Management System Library (Single Server)dalam sistem yang direka dalam artikel) menghantar isyarat, bot pemilik akaun penyegerakan akan menerima isyarat dagangan.

  • 2.Banyak pemaju mempunyai strategi yang lebih baik dan tidak dapat menggunakan dua strategi penyegerakan urutan dan kedudukan sebelumnya yang diterangkan di atas. Kerana itu perlu menggabungkan strategi mereka sendiri dengan strategi penyegerakan ini, dan strategi mereka mungkin perlu diubahsuai, yang memakan masa dan tenaga. Adakah ada cara yang baik untuk meningkatkan beberapa strategi matang anda secara langsung kepada yang mempunyai fungsi penyegerakan pesanan?

    Penyelesaian: Anda boleh merancang perpustakaan templat order synchronous (yangOrder Synchronous Management System Library (Single Server)strategi dalam sistem yang direka dalam artikel), supaya pemilik akaun rujukan (pemilik pesanan) boleh memasukkan perpustakaan templat ini secara langsung ke dalam strategi sendiri untuk mencapai urutan dan penyegerakan kedudukan.

  • 3.Kurangkan bot tambahan Kelemahan terakhir adalah bahawa jika anda menggunakan dua perintah sebelumnya dan strategi penyegerakan kedudukan yang diterangkan di atas, adalah perlu untuk membuka kedudukan tambahan akaun rujukan ( akaun dengan pesanan) untuk pemantauan bot. Penyelesaian: Gunakan perpustakaan templat untuk menyematkan fungsi ke dalam strategi akaun rujukan.

Oleh itu, sistem ini terdiri daripada dua bahagian: 1.perpustakaan sistem pengurusan sinkron pesanan (Single Server) 2.Sistem pengurusan pesanan serentak (Synchronous Server)

Setelah kita memastikan tuntutan kita, mari kita mula merancang!

Reka bentuk 1: Memesan Perpustakaan Sistem Pengurusan Sinkron (Perkhidmatan Tunggal)

Perhatikan bahawa di sini ia bukan strategi, tetapi perpustakaan templat FMZ, yang boleh dicari dalam dokumentasi FMZ API dan kita tidak akan membincangkan di sini.

Kod templat:

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

Reka bentuknya sangat mudah, perpustakaan mempunyai 2 fungsi.Order Synchronous Management System Library (Single Server)Perpustakaan kelas templat. Strategi ini kemudian boleh menggunakan fungsi berikut.

  • $. PosMonitor Kesan fungsi ini adalah untuk memantau perubahan kedudukan objek pertukaran dalam strategi, dan kemudian menghantar isyarat perdagangan ke bot yang ditetapkan dalam parameter templat: perpustakaan sistem pengurusan sinkron pesanan (Single Server).
  • $.getTbl Fungsi ini mengembalikan data sinkronis yang dipantau.

Contoh penggunaan adalah dimainfungsi dalam perpustakaan sistem pengurusan sinkronis pesanan (Single Server):

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

Perpustakaan templat itu sendiri juga boleh membuat bot strategi, yang biasanya digunakan untuk menguji perpustakaan templat. Sebagai contoh, ujian untuk templat ini.mainFungsi dalam templat adalahmainfungsi salah satu strategi anda sendiri.

Kod ujian ditulis untuk menggunakan bot simulasi OKEX untuk menguji, dan API KEY bot simulasi OKEX perlu dikonfigurasi di FMZ sebagai akaun rujukan (dengan pesanan), dan fungsi utama mula beralih ke bot simulasi. Kemudian atur pasangan dagangan ke ETH_USDT, dan atur kontrak untuk menukar. Kemudian masukkan gelung sementara. Dalam gelung, pesanan diletakkan setiap 3 minit untuk mensimulasikan pencetus perdagangan strategi.$.PosMonitor(0, "ETH_USDT", "swap")dipanggil dalam gelung sementara, dan parameter pertama fungsi dipanggil adalah 0, yang bermaksud untuk memantau pertukaran objek pertukaran[0], pasangan perdagangan ETH_USDT, dan kontrak swap. Kemudian panggil$.getTbl()untuk mendapatkan maklumat carta, dan menggunakanLogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")untuk membuat data carta yang dipaparkan pada bar status.

Jadi anda lihat, selagi$.PosMonitor(0, "ETH_USDT", "swap")digunakan dalam strategi yang memanggil templat, strategi boleh mempunyai fungsi memantau kedudukan simbol tertentu dan mendorong mesej perubahan kedudukan.

Sebelum ujian, jelaskan reka bentuk parameterOrder Synchronous Management System Library (Single Server)strategi: Saya hanya bercakap tentang bagaimana untuk menggunakan fungsi antara muka templat untuk membuat peningkatan strategi dengan fungsi membawa pesanan. jadi siapa isyarat yang dihantar apabila kedudukan berubah? Persoalan kepada siapa untuk menghantar adalah dikonfigurasikan oleh parameterorder synchronous management system library (Single Server).

img

Anda boleh melihat lima parameter, yang boleh menyokong maksimum lima push (jika anda perlu meningkatkan nombor push, anda boleh memanjangkannya sendiri); lalai parameter adalah rentetan kosong, iaitu tidak diproses.

  • label Label akaun selaras, digunakan untuk melabelkan akaun; nama label boleh ditetapkan secara rawak.

  • robotId ID bot; ID bot daripadaorder synchronous management system (Synchronous Server)yang dicipta oleh pemilik akaun sinkron.

  • aksesKey AccessKey FMZ diperluaskan API.

  • RahsiaKey Kunci rahsia FMZ diperluaskan API.

Kemudian, kita boleh menjalankan ujian yang mudah.

Perintah Perpustakaan Sistem Pengurusan Sinkron (Perkhidmatan Tunggal) operasi bot:

img

Bot Sistem Pengurusan Sinkron Perintah (Sinkron Pelayan) menerima isyarat: Perintah Sistem Pengurusan Sinkron (Synchronous Server) kini belum sepenuhnya direka oleh kita, dan kita boleh menggunakan kod yang mudah untuk mewujudkannya, tanpa perdagangan, hanya isyarat cetak:

Perintah Sistem Pengurusan Sinkron (Sinkron Pelayan) kod sementara:

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

img

Seperti yang anda lihat, bot pemilik akaun sinkron menerima mesej:ETH_USDT,swap,buy,1. Oleh itu, dalam langkah seterusnya, kita boleh mengawasi pesanan secara automatik, mengikut pasangan dagangan, kod kontrak, arah dagangan dan jumlah.

Pada masa ini,order synchronous management system (Synchronous Server)adalah hanya kod sementara, dan kita boleh membincangkan lebih lanjut reka bentuknya dalam artikel seterusnya.


Lebih lanjut