Desain Sistem Manajemen Sinkronisasi Pesenan Berdasarkan FMZ Quant (1)

Penulis:Lydia, Dibuat: 2022-11-07 10:20:01, Diperbarui: 2023-09-15 20:45:23

img

Desain Sistem Manajemen Sinkronisasi Pesenan Berdasarkan FMZ Quant (1)

Dalam artikel sebelumnya di perpustakaan FMZs, kami telah merancang beberapa jenis strategi sinkronisasi untuk urutan dan posisi.

Ini mengelola akun referensi dan akun yang disinkronkan dalam satu strategi untuk mencapai sinkronisasi pesanan dan posisi. dan hari ini kita akan mencoba desain yang berbeda, kita akan merancang sistem manajemen sinkronisasi pesanan berdasarkan antarmuka API diperpanjang yang kuat dari FMZ Quant Trading Platform.

Ide Desain

Pertama, kita perlu beberapa saran yang baik dan kebutuhan. dua urutan sebelumnya dan posisi strategi sinkronisasi di atas, yang memiliki beberapa kelemahan yang jelas, yang akan kita bahas bersama-sama.

    1. Pengguna strategi sinkronisasi real bot harus memiliki exchange API KEY dari akun referensi, dan exchange API KEY dari akun sinkronisasi. Masalah ini baik-baik saja untuk situasi penggunaan di mana akun pertukaran lain mengikuti akunnya sendiri. Namun, dapat mengganggu untuk situasi di mana akun referensi dan akun sinkronisasi bukan pemilik yang sama. Kadang-kadang pemilik akun yang disinkronkan tidak ingin memberikan KEY API akun pertukaran sendiri karena alasan keamanan, tetapi bagaimana untuk menyinkronkan transaksi pesanan tanpa memberikan KEY API?

    Solusi: Menggunakan antarmuka API FMZ yang diperluas, pemilik akun yang disinkronkan (pengikut pesanan) hanya perlu mendaftarkan akun di Platform Perdagangan Kuantum FMZ, kemudian menjalankan strategi (dalam sistem yang dirancang dalam artikel ini:Order Synchronous ServerStrategi di Real Bot). Kemudian cukup berikan FMZ diperpanjang API KEY (catat bahwa itu bukan API KEY dari akun pertukaran) dan Order Synchronous Server real bot ID untuk pemilik akun referensi (order leader). Ketika pemilik akun referensi (pengikut pesanan) bot nyata (Order Synchronization Management System Class Library (Single Server)dalam sistem yang dirancang dalam artikel ini) mengirimkan sinyal, pemilik akun sinkronisasi bot nyata akan menerima sinyal perdagangan dan menempatkan pesanan berikutnya secara otomatis.

    1. Banyak pengembang memiliki strategi yang baik, tetapi mereka tidak dapat menggunakan 2 strategi sinkronisasi urutan dan posisi masa lalu yang dijelaskan di atas. Karena mereka perlu mengintegrasikan strategi mereka sendiri dengan strategi yang disinkronkan ini, dan strategi mungkin perlu diubah secara drastis, yang akan membutuhkan banyak pekerjaan dan usaha. Apakah ada cara yang baik untuk meningkatkan beberapa strategi matang Anda langsung ke fungsi sinkronisasi urutan? Solusi: Anda dapat mendesain perpustakaan kelas template sinkronisasi order (theOrder Synchronization Management System Class Library (Single Server)strategi dalam sistem yang dirancang dalam artikel ini), sehingga pemilik akun referensi (order-leader) dapat menanamkan perpustakaan kelas templat ini ke dalam strategi sendiri secara langsung untuk mencapai fungsi sinkronisasi urutan dan posisi.
    1. Mengurangi tambahan bot nyata. Kelemahan terakhir adalah bahwa jika Anda menggunakan 2 pesanan sebelumnya, strategi sinkronisasi posisi yang dijelaskan di atas. Solusi: Gunakan perpustakaan kelas template untuk menyematkan fungsionalitas dalam strategi akun referensi.

Jadi sistem terdiri dari 2 bagian:

  1. Perpustakaan kelas sistem manajemen sinkronisasi pesanan (Single Server)
  2. Sistem manajemen sinkronisasi pesanan (Synchronous Server)

Setelah kita menentukan kebutuhan kita, mari kita mulai mendesain!

Desain 1: Perpustakaan kelas sistem manajemen sinkronisasi pesanan (Single Server)

Perhatikan bahwa ini bukan strategi. Ini adalah perpustakaan kelas template FMZ. Konsep perpustakaan kelas template dapat dicari dalam dokumentasi API FMZ dan kami tidak akan mengulanginya lagi.

Kode perpustakaan kelas templat:

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

Desainnya sangat sederhana, perpustakaan kelas memiliki 2 fungsi.Order Synchronization Management System Class Library (Single Server)Kemudian strategi dapat menggunakan fungsi berikut.

  • $. PosMonitor Tujuan dari fungsi ini adalah untuk memantau perubahan posisi objek pertukaran dalam strategi dan kemudian mengirim sinyal perdagangan ke pasar bot nyata yang ditetapkan dalam parameter templat: Perpustakaan kelas Sistem Manajemen Sinkronisasi Pesenan (Single Server).

  • $.getTbl Kembali ke data sinkronisasi yang dipantau.

Contoh penggunaan adalah dalammainfungsi template Perpustakaan Kelas Sistem Manajemen Sinkronisasi Pesenan (Single Server):

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

Perpustakaan kelas template juga dapat membuat strategi real bot sendiri, yang biasanya digunakan untuk menguji perpustakaan kelas template, seperti pengujian template.mainfungsi dalam template adalahmainfungsi dari salah satu strategi Anda sendiri.

Kode uji ditulis dengan menggunakan OKEX demo untuk menguji, Anda perlu mengkonfigurasi OKEX demo API KEY pada FMZ sebagai akun referensi (order-leading), dan mulai beralih ke demo dalam fungsi utama. Kemudian atur pasangan perdagangan ke ETH_USDT dan atur kontrak untuk swap. Kemudian memasuki loop sementara. Dalam loop, sebuah order ditempatkan setiap 3 menit untuk mensimulasikan pemicu transaksi strategi.$.PosMonitor(0, "ETH_USDT", "swap")disebut dalam loop sementara, parameter pertama dari fungsi ini dilewatkan ke 0, yang berarti untuk memantau pertukaran objek pertukaran[0], memantau pasangan perdagangan ETH_USDT, kontrak swap.$.getTbl()untuk mendapatkan informasi grafik, menggunakanLogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")untuk membuat data grafik ditampilkan pada bilah status.

Jadi kita dapat melihat bahwa kita dapat membuat strategi memiliki kemampuan untuk memantau posisi spesies tertentu, dan perubahan posisi untuk mengirim pesan dengan menggunakan$.PosMonitor(0, "ETH_USDT", "swap")Dalam strategi yang mengacu pada template.

Sebelum pengujian, kami akan menjelaskan desain parameter strategi dariOrder Synchronization Management System Class Library (Single Server)Aku tidak tahu. Kami baru saja berbicara tentang bagaimana menggunakan fungsi antarmuka templat untuk meningkatkan strategi untuk memiliki fungsi order-leading. Pertanyaan siapa yang akan dikirim dikonfigurasi oleh parameter dariOrder Synchronization Management System Class Library (Single Server).

img

Kita dapat melihat bahwa ada 5 parameter, mendukung hingga 5 dorongan (itu dapat diperluas sendiri jika perlu peningkatan), parameter default adalah string kosong, yaitu, tidak diproses.

  • label Sebuah label untuk akun sinkronisasi, digunakan untuk mengatur label untuk akun dengan nama yang dapat diatur sesuka hati.

  • robotId Robot ID, ID dariOrder Synchronous Serverbot nyata yang dibuat oleh pemilik akun sinkron.

  • aksesKey Akses API diperluasKey FMZ

  • RahasiaKey Rahasia API diperluasKey FMZ

Kode sementara Sistem Manajemen Sinkronisasi Pesenan (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

Kita bisa melihat bahwa bot asli pemilik akun yang disinkronkan menerima pesan:ETH_USDT,swap,buy,1Aku tidak tahu. Kemudian itu akan memungkinkan kita untuk membuat kami sendiri otomatis order-mengikuti di langkah berikutnya berdasarkan trading pasangan, kode kontrak, arah perdagangan, dan jumlah dalam informasi.

Sejauh ini,Order Synchronization Management System (Synchronous Server)adalah kode sementara, kita akan terus mengeksplorasi desainnya dalam edisi berikutnya.


Berkaitan

Lebih banyak