Desain sistem manajemen pesanan sinkronisasi berdasarkan kuantifikasi FMZ (1)

Penulis:Mimpi kecil, Dibuat: 2022-02-14 19:46:30, Diperbarui: 2023-09-15 20:44:11

img

Desain sistem manajemen pesanan sinkronisasi berdasarkan kuantifikasi FMZ (1)

Dalam artikel-artikel sebelumnya di FMZ, kami telah merancang beberapa strategi sinkronisasi pesanan dan penyimpanan.

Ini adalah menempatkan akun referensi dan akun sinkronisasi dalam satu strategi untuk mengelola pemenuhan pesanan, sinkronisasi penyimpanan. Hari ini kita akan mencoba desain yang sedikit berbeda, berdasarkan antarmuka API ekstensi yang kuat dari platform perdagangan kuantitatif FMZ, kita akan merancang sistem manajemen sinkronisasi pesanan.

Pikiran Desain

Pertama, kita perlu beberapa saran yang baik, kebutuhan, dan beberapa titik nyeri yang jelas dari dua pesanan jangka panjang dan strategi sinkronisasi saham di atas, mari kita bahas:

  • 1. Implementor dari strategi simultan real-time harus memiliki API KEY dari akun acuan, API KEY dari akun simultan. Masalahnya dengan skenario penggunaan adalah: tidak masalah jika akun Anda mengikuti akun Anda sendiri. Tetapi itu akan menjadi masalah untuk skenario akun referensi dan akun sinkronisasi bukan pemilik. Pemilik akun sinkronisasi kadang-kadang tidak mau memberikan KEY API akun mereka sendiri karena alasan keamanan. Tetapi bagaimana cara menyinkronkan transaksi tanpa menyediakan KEY API?

    Solusi: Dengan menggunakan antarmuka API ekstensi FMZ, pemilik akun sinkronisasi (pengikut) hanya perlu mendaftar ke platform perdagangan kuantitatif FMZ dan kemudian menjalankan salah satu kebijakan (dalam sistem yang dirancang untuk artikel ini):订单同步管理系统(Synchronous Server)Kebijakan Disk) ; kemudian FMZ extension API KEY (catatan, bukan API KEY dari akun bursa) ; order synchronous server (Synchronous Server) dapat memberikan ID Disk kepada pemilik akun referensi (band). Ketika referensi pemilik akun (bandwidth) di dalam sistem yang dirancang untuk订单同步管理系统类库(Single Server)Jika Anda mengirim sinyal, akun yang disinkronkan akan menerima sinyal transaksi dan kemudian melakukan pemesanan secara otomatis.

  • 2. Banyak pengembang yang memiliki strategi yang lebih baik dan tidak dapat menggunakan dua order masa depan yang dijelaskan di atas, yaitu strategi sinkronisasi penyimpanan. Karena itu perlu menggabungkan strategi mereka dengan strategi sinkronisasi ini, dan mungkin strategi tersebut perlu diubah secara besar-besaran dan sulit. Apakah ada cara yang baik untuk meningkatkan beberapa strategi mereka yang sudah mapan secara langsung ke sinkronisasi order? Solusi: Anda dapat merancang perpustakaan template sinkronisasi pesanan (dalam sistem yang dirancang untuk artikel ini)订单同步管理系统类库(Single Server)Kebijakan), yang memungkinkan pemilik akun referensi (bandwidth) untuk langsung mengintegrasikan template ke dalam kebijakan mereka sendiri untuk mencapai fungsi order, penyimpanan dan sinkronisasi.

  • 3. Mengurangi satu piringan ekstra. Titik nyeri terakhir adalah bahwa jika Anda menggunakan dua pesanan berjangka yang dijelaskan di atas, maka Anda perlu membuka tambahan akun pemegang yang memiliki referensi pemantauan fisik. Solusi: Menggunakan perpustakaan template untuk menyematkan fitur ke dalam kebijakan akun referensi.

Jadi sistem ini terdiri dari dua bagian: 1, Kelas Sistem Manajemen Sinkronisasi Pemesanan (Single Server) 2, Sistem Manajemen Pemesanan Sinkron (Synchronous Server)

Jika Anda memiliki kebutuhan yang jelas, maka mulailah mendesain.

Desain 1: Kelas Perpustakaan Sistem Manajemen Sinkronisasi Pemesanan (Single Server)

Perhatikan bahwa ini bukan sebuah strategi. Ini adalah sebuah database template untuk FMZ. Konsep tentang database template dapat dicari di dokumen FMZ API, yang tidak akan dibahas di sini.

Kode Kelas Template:

// 全局变量
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) {
        // 开仓
        var tradeDirection = type == PD_LONG ? "buy" : "sell"
        // 发送信号
        msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)        
    } else if (delta < 0) {
        // 平仓
        var tradeDirection = type == PD_LONG ? "closebuy" : "closesell"
        if (nowAmount <= 0) {
            Log("未检测到持仓")
            return 
        }
        // 发送信号
        msg = symbol + "," + ct + "," + tradeDirection + "," + Math.abs(delta)
    } else {
        throw "错误"
    }
    if (msg) {
        _.each(fmzExtendApis, function(extendApiConfig) {
            var ret = sendCommandRobotMsg(extendApiConfig[keyName_robotId], extendApiConfig[keyName_extendAccessKey], extendApiConfig[keyName_extendSecretKey], msg)
            Log("调用CommandRobot接口,", "label:", extendApiConfig[keyName_label], ", msg:", msg, ", ret:", ret)
            Sleep(1000)
        })
    }
}

$.PosMonitor = function(exIndex, symbol, ct) {    
    var ts = new Date().getTime()
    var ex = exchanges[exIndex]
    // 判断ex类型
    var exName = ex.GetName()
    var isFutures = exName.includes("Futures_")
    var exType = isFutures ? "futures" : "spot"
    if (!isFutures) {
        throw "仅支持期货跟单"
    }

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

        // 切换到对应的交易对、合约代码
        ex.SetCurrency(symbol)
        if (!ex.SetContractType(ct)) {
            throw "SetContractType failed"
        }

        // 监控持仓
        var keyInitRefPosAmount = "refPos-" + exIndex + "-" + symbol + "-" + ct    // refPos-exIndex-symbol-contractType
        var initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
        if (!initRefPosAmount) {
            // 没有初始化数据,初始化          
            mapInitRefPosAmount[keyInitRefPosAmount] = getPosAmount(_C(ex.GetPosition), ct)
            initRefPosAmount = mapInitRefPosAmount[keyInitRefPosAmount]
        }

        // 监控
        var nowRefPosAmount = getPosAmount(_C(ex.GetPosition), ct)
        // 计算仓位变动
        var longPosDelta = nowRefPosAmount.long - initRefPosAmount.long
        var shortPosDelta = nowRefPosAmount.short - initRefPosAmount.short

        // 检测变动
        if (!(longPosDelta == 0 && shortPosDelta == 0)) {
            // 执行多头动作
            if (longPosDelta != 0) {
                Log(ex.GetName(), ex.GetLabel(), symbol, ct, "执行多头跟单,变动量:", longPosDelta)
                follow(nowRefPosAmount, symbol, ct, PD_LONG, longPosDelta)
            }
            // 执行空头动作
            if (shortPosDelta != 0) {
                Log(ex.GetName(), ex.GetLabel(), symbol, ct, "执行空头跟单,变动量:", shortPosDelta)
                follow(nowRefPosAmount, symbol, ct, PD_SHORT, shortPosDelta)
            }

            // 执行跟单操作后,更新
            mapInitRefPosAmount[keyInitRefPosAmount] = nowRefPosAmount
        }

        // 恢复 symbol ct
        ex.SetCurrency(buffSymbol)
        ex.SetContractType(buffCt)
    } else if (exType == "spot") {
        // 现货
    }
}

$.getTbl = function() {
    var tbl = {
        "type" : "table", 
        "title" : "同步数据", 
        "cols" : [], 
        "rows" : []
    }
    // 构造表头
    tbl.cols.push("监控账户:refPos-exIndex-symbol-contractType")
    tbl.cols.push(`监控持仓:{"时间戳":xxx,"多头持仓量":xxx,"空头持仓量":xxx}`)
    _.each(fmzExtendApis, function(extendApiData, index) {
        tbl.cols.push(keyName_robotId + "-" + index)
    })
    
    // 写入数据
    _.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
}

// 引用该模板类库的策略调用范例
function main() {
    // 清除所有日志
    LogReset(1)

    // 切换到OKEX 模拟盘测试
    exchanges[0].IO("simulate", true)

    // 设置合约
    exchanges[0].SetCurrency("ETH_USDT")
    exchanges[0].SetContractType("swap")

    // 定时交易时间间隔
    var tradeInterval = 1000 * 60 * 3        // 三分钟交易一次,用于观察跟单信号
    var lastTradeTS = new Date().getTime()
    
    while (true) {
        // 策略其它逻辑...

        // 用于测试的模拟交易触发
        var ts = new Date().getTime()
        if (ts - lastTradeTS > tradeInterval) {
            Log("模拟带单策略发生交易,持仓变化", "#FF0000")
            exchanges[0].SetDirection("buy")
            exchanges[0].Buy(-1, 1)
            lastTradeTS = ts
        }

        // 使用模板的接口函数
        $.PosMonitor(0, "ETH_USDT", "swap")    // 可以设置多个监控,监控带单策略上的不同的exchange对象  
        var tbl = $.getTbl()
        
        // 显示状态栏
        LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
        Sleep(1000)
    }
}

Perpustakaan ini memiliki dua fungsi fungsi yang sangat sederhana.订单同步管理系统类库(Single Server)Setelah template class library. Kebijakan ini dapat dilakukan dengan menggunakan fungsi berikut.

  • $ PosMonitor Fungsi ini berfungsi untuk memantau perubahan kepemilikan objek bursa dalam kebijakan, dan kemudian mengirim sinyal perdagangan ke piringan nyata yang ditetapkan dalam template: Order Synchronous Management System (Single Server).

  • $.getTbl Data sinkronisasi yang dipantau kembali.

Contoh penggunaan adalah: Template Kelas Sistem Manajemen Sinkronisasi Pesenan (Single Server)mainFungsi:

// 引用该模板类库的策略调用范例
function main() {
    // 清除所有日志
    LogReset(1)

    // 切换到OKEX 模拟盘测试
    exchanges[0].IO("simulate", true)

    // 设置合约
    exchanges[0].SetCurrency("ETH_USDT")
    exchanges[0].SetContractType("swap")

    // 定时交易时间间隔
    var tradeInterval = 1000 * 60 * 3        // 三分钟交易一次,用于观察跟单信号
    var lastTradeTS = new Date().getTime()
    
    while (true) {
        // 策略其它逻辑...

        // 用于测试的模拟交易触发
        var ts = new Date().getTime()
        if (ts - lastTradeTS > tradeInterval) {
            Log("模拟带单策略发生交易,持仓变化", "#FF0000")
            exchanges[0].SetDirection("buy")
            exchanges[0].Buy(-1, 1)
            lastTradeTS = ts
        }

        // 使用模板的接口函数
        $.PosMonitor(0, "ETH_USDT", "swap")    // 可以设置多个监控,监控带单策略上的不同的exchange对象  
        var tbl = $.getTbl()
        
        // 显示状态栏
        LogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")
        Sleep(1000)
    }
}

Sebuah template sendiri juga dapat membuat policy disk, yang biasanya digunakan untuk menguji template. Misalnya, Anda dapat memahami apa yang dimaksud dengan template.mainFungsi adalah strategi Anda sendiri.mainFungsi tersebut.

Kode pengujian ditulis untuk pengujian menggunakan OKEX analog disk, yang membutuhkan konfigurasi API KEY dari OKEX analog disk pada FMZ sebagai akun referensi (band), mulai beralih ke analog disk di fungsi utama. Kemudian atur pasangan transaksi menjadi ETH_USDT, lalu atur kontrak menjadi permanen (swap). Kemudian masuk ke dalam loop sementara.$.PosMonitor(0, "ETH_USDT", "swap")Fungsi ini disebut dengan parameter pertama 0 yang berarti monitor exchanges[0] yang memantau obyek pertukaran, pasangan transaksi ETH_USDT, dan kontrak swap.$.getTbl()Mendapatkan informasi grafik, menggunakannyaLogStatus(_D(), "\n" + "`" + JSON.stringify(tbl) + "`")Buat data grafik ditampilkan pada status bar.

Jadi Anda lihat, hanya jika Anda menggunakan strategi yang mengutip template.$.PosMonitor(0, "ETH_USDT", "swap")Dengan cara ini, strategi dapat memiliki fungsi untuk memantau jenis saham yang berbeda dan memindahkan saham untuk memajukan pesan.

Tuliskan sebelum Anda melakukan tes.订单同步管理系统类库(Single Server)Desain Parameter Strategi: Kami baru saja membahas bagaimana menggunakan fungsi antarmuka template untuk membuat kebijakan ditingkatkan dengan fitur bandwidth. Jadi, siapa yang akan menerima sinyal yang dikirim saat saham berubah? Pertanyaan siapa yang mengirimnya adalah pertanyaan dari orang yang mengirimnya.订单同步管理系统类库(Single Server)Untuk mengkonfigurasikan parameter tersebut.

img

Anda dapat melihat bahwa ada 5 parameter, yang mendukung maksimal 5 push (menambah perlu dapat diperluas sendiri), parameter default adalah string kosong, yaitu tidak diproses. Format string konfigurasi: label, robotId, accessKey, secretKey

  • label Tag akun sinkronisasi, digunakan untuk menandai akun tertentu, nama dapat disetel sesuka hati.

  • robotId Disk ID, dibuat oleh pemilik akun sinkronisasi订单同步管理系统(Synchronous Server)ID dari hardisk tersebut.

  • aksesKey AccessKey untuk ekstensi API FMZ

  • SecretKey SecretKey untuk ekstensi API FMZ

Setelah itu, kita bisa melakukan tes sederhana.

Perangkat lunak ini dapat digunakan untuk mengunduh file dari komputer Anda, dan untuk mengunduh file dari komputer Anda.

img

Sistem manajemen pesanan sinkron (Synchronous Server) menerima sinyal: Sistem Manajemen Pemesanan Sinkron (Synchronous Server) saat ini belum kami desain, kami mengimplementasikannya dengan kode sederhana, tidak melakukan transaksi, hanya mencetak sinyal:

Sistem Manajemen Pemesanan Sinkron (Synchronous Server) kode sementara:

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

img

Anda dapat melihat bahwa pengguna akun sinkronisasi menerima pesan di hard drive:ETH_USDT,swap,buy,1Saya tidak tahu. Dengan demikian, langkah selanjutnya adalah melakukan pelacakan otomatis berdasarkan pasangan transaksi, kode kontrak, arah transaksi, jumlah transaksi yang ada dalam informasi tersebut.

Saat ini订单同步管理系统(Synchronous Server)Ini hanya kode sementara, dan kami akan terus membahas desainnya di edisi berikutnya.


Berkaitan

Lebih banyak

Mingxi1005Untuk implementasi daftar, Anda perlu dua hard drive, satu adalah hard drive perpustakaan kelas, dan satu adalah hard drive sistem manajemen pesanan.

Mingxi1005Menggunakan tutorial, menunjukkan kesalahan konfigurasi

AllahParameter mana yang harus diubah dalam daftar mundur?

AllahApakah Anda bisa mengkoneksikan dua hardisk, satu untuk mengirim sinyal dan satu untuk menerima sinyal, dan keduanya bisa digunakan bersama-sama?

Mimpi kecilAnda mungkin tidak mengerti artikel ini, buku kelas ini adalah alat yang dapat ditanamkan langsung di baris kebijakan pengguna, dan kemudian kebijakan ini memiliki fungsi band, akan mengirim pesan ke akun yang sudah diatur, dan bot akan menerima pesan tersebut. "Saya tidak tahu apa yang akan terjadi", katanya.

Mimpi kecilAnda dapat melihat artikel ini, informasi konfigurasi: label, disk ID, accesskey, secretkey.

Mingxi1005Kesalahan configs error!, di dalam direktori sistem manajemen sinkronisasi pesanan (Single Server), mengisi disk pengirim dan 2 KEY, dan kemudian mengutip direktori sistem manajemen sinkronisasi pesanan (Single Server) di dalam direktori (Single Server), memberikan kesalahan, kesalahan configs error!

Mingxi1005Kesalahan configs error!

Mimpi kecilUntuk melihat informasi yang salah.

Mimpi kecil"Kami tidak bisa menghindarinya", katanya.

Mimpi kecilKode terbuka, Anda dapat mengubahnya sesuai kebutuhan Anda, dan itu bisa dilakukan.