Perdagangan kuantitatif dalam lingkaran mata wang adalah sesuatu yang baru - membawa anda lebih dekat kepada kuantitatif dalam lingkaran mata wang.

Penulis:Mimpi kecil, Dicipta: 2021-06-04 10:08:48, Dikemas kini: 2023-09-21 21:01:06

img

Perdagangan kuantitatif lingkaran mata wang yang baru muncul untuk membawa anda lebih dekat ke lingkaran mata wang.

Dalam artikel sebelum ini, kami telah membuat strategi grid yang mudah, dan dalam artikel ini kami telah meningkatkan dan mengembangkan strategi ini menjadi strategi grid yang tersedia dalam pelbagai jenis, dan menguji strategi ini. Tujuan kami bukan untuk mencari "cawan suci", tetapi untuk membincangkan pelbagai isu dan penyelesaian dalam reka bentuk strategi dari reka bentuk strategi. Artikel ini akan menerangkan beberapa pengalaman saya dalam reka bentuk strategi ini, kandungan ini agak rumit dan memerlukan asas tertentu untuk penulisan program.

Berfikir reka bentuk berdasarkan keperluan strategik

Artikel ini, seperti artikel sebelumnya, masih berdasarkan kuantiti pencipta.FMZ.COMDi sini anda boleh melihat beberapa gambar yang menarik.

  • Pelbagai jenis Saya mahu strategi grid ini bukan hanya untuk melakukanBTC_USDTBoleh buat.LTC_USDT/EOS_USDT/DOGE_USDT/ETC_USDT/ETH_USDTWalau bagaimanapun, pasangan yang berdagang dengan mata wang tunai dan jenis yang ingin berlari juga berdagang dengan jaring.

    "Mengambil gambar pelbagai jenis pergolakan, rasanya bagus. Permintaan terdengar mudah, tetapi masalah datang semasa mereka merancang.

    • 1. mula-mula mendapatkan pelbagai jenis pasaran. Ini adalah masalah pertama yang perlu diselesaikan. Selepas melihat dokumen API bursa, saya mendapati bahawa bursa biasa menawarkan antara muka pasaran yang dikumpulkan. OK, gunakan antara muka pasaran agregat untuk mendapatkan data.

    • 2. Masalah kedua yang dihadapi ialah aset akaun. Oleh kerana ia adalah strategi yang pelbagai, anda perlu mempertimbangkan setiap urus niaga untuk pengurusan aset secara berasingan. Dan anda perlu mendapatkan semua data aset sekaligus. Mengapa anda perlu mendapatkan data aset akaun? Kerana anda perlu menilai aset yang ada semasa membuat pesanan, atau anda perlu mendapatkan dan menilai semula? Atau anda perlu mengira keuntungan, atau anda perlu mencatat data aset akaun awal, dan kemudian mendapatkan data aset akaun semasa dan mengira keuntungan dan kerugian berbanding awal? Untungnya, antara muka akaun aset di bursa juga biasanya mengembalikan semua data aset mata wang, yang hanya perlu kita dapatkan sekali dan kemudian memproses data.

    • 3., Reka bentuk parameter strategi... Reka bentuk parameter pelbagai jenis dan reka bentuk parameter satu jenis lebih berbeza, kerana logik perdagangan pelbagai jenis walaupun sama, tetapi mungkin parameter ketika berdagang adalah berbeza... Sebagai contoh, strategi grid, mungkin melakukan BTC_USDT perdagangan pasangan apabila berharap 0.01 BTC setiap dagangan, tetapi apabila melakukan DOGE_USDT jika masih parameter ini ((perdagangan 0.01 syiling) jelas tidak sesuai, sudah tentu anda juga boleh memproses dengan jumlah USDT... Mungkin rakan-rakan akan berfikir tentang perkara ini dan kemudian berkata: Saya boleh menetapkan beberapa set parameter yang berbeza untuk mengawal pasangan transaksi yang berbeza. Adakah masih boleh menjadi fleksibel untuk memenuhi keperluan, dengan beberapa set parameter yang baik? Set tiga set parameter, bagaimana jika saya mahu membuat empat jenis? Oleh itu, apabila merancang parameter untuk pelbagai strategi, perlu mempertimbangkan sepenuhnya keperluan parameter pembezaan ini. Satu penyelesaian adalah dengan merancang parameter sebagai rentetan biasa atau rentetan JSON. Contohnya:

      ETHUSDT:100:0.002|LTCUSDT:20:0.1
      

      Di sini, pembahagian yang lebih besar adalah data untuk setiap jenis, yang bermaksud:ETHUSDT:100:0.002Di samping itu, mereka juga mempunyai hak untuk mengundi.LTCUSDT:20:0.1Ia adalah pasangan yang mengawal transaksi LTC_USDT.ETHUSDT:100:0.002, di mana ETHUSDT menunjukkan apa pasangan dagangan yang akan anda lakukan, 100 adalah jarak grid, 0.002 adalah jumlah koin ETH yang diperdagangkan pada setiap grid, dan oh: julukan adalah pembahagian data ini ((Sudah tentu, peraturan parameter ini dibuat oleh pereka strategi, apa sahaja yang anda reka mengikut keperluan anda). String-string ini mengandungi maklumat parameter untuk setiap varieti yang akan anda lakukan. Dalam strategi, anda perlu menganalisis strings ini, memberi nilai kepada variabel yang digunakan untuk mengawal logik urus niaga untuk setiap varieti.

      function main() {
          var net = []  // 记录的网格参数,具体运行到网格交易逻辑时,使用这里面的数据
          var params = "ETHUSDT:100:0.002|LTCUSDT:20:0.1"
          var arrPair = params.split("|")
          _.each(arrPair, function(pair) {
              var arr = pair.split(":")
              var symbol = arr[0]              // 交易对名称
              var diff = parseFloat(arr[1])    // 网格间距
              var amount = parseFloat(arr[2])  // 网格下单量
              net.push({symbol : symbol, diff : diff, amount : amount})
          })
          Log("网格参数数据:", net)
      }
      

      img

      Dengan cara ini, parameter akan diselesaikan, tetapi anda juga boleh menggunakan tali JSON secara langsung, yang lebih mudah.

      function main() {        
          var params = '[{"symbol":"ETHUSDT","diff":100,"amount":0.002},{"symbol":"LTCUSDT","diff":20,"amount":0.1}]'
          var net = JSON.parse(params)  // 记录的网格参数,具体运行到网格交易逻辑时,使用这里面的数据        
          _.each(net, function(pair) {
              Log("交易对:", pair.symbol, pair)
          })
      }
      

      img

    • 4. Pengekalan data Strategi yang boleh digunakan dalam peperangan sebenar dan strategi pengajaran juga berbeza, strategi pengajaran yang disebutkan di atas hanya ujian awal strategi logik, reka bentuk, lebih banyak masalah yang perlu dipertimbangkan semasa peperangan sebenar. Pada masa sebenar, mungkin membuka, menghentikan cakera sebenar. Di sini anda perlu menyimpan data penting semasa disket berjalan secara berterusan, supaya data ini boleh dibaca pada permulaan semula dan terus berjalan. Ia boleh digunakan pada platform perdagangan kuantiti pencipta_G()Fungsi, atau menggunakan fungsi operasi pangkalan dataDBExec()Untuk maklumat lebih lanjut, anda boleh rujuk dokumentasi API FMZ.

      Sebagai contoh, kita merancang satu fungsi sweep tail, menggunakan_G()Fungsi menyimpan data grid.

      var net = null 
      function main() {  // 策略主函数
          // 首先读取储存的net
          net = _G("net")
          
          // ...
      }
      
      function onExit() {
          _G("net", net)
          Log("执行扫尾处理,保存数据", "#FF0000")
      }
      
      function onexit() {    // 平台系统定义的退出扫尾函数,在点击实盘停止时触发执行
          onExit()
      }
      
      function onerror() {   // 平台系统定义的异常退出函数,在程序发生异常时触发执行
          onExit()
      }
      
    • 5. Pengekangan seperti ketepatan jumlah pesanan, ketepatan harga pesanan, kuantiti pesanan minimum, jumlah pesanan minimum

      Sistem retest tidak mempunyai batasan yang ketat terhadap jumlah pesanan, ketepatan pesanan, dan lain-lain, tetapi pada masa nyata, setiap bursa boleh mempunyai piawaian yang ketat untuk harga pesanan, jumlah pesanan, dan setiap pasangan dagangan tidak sama.

      Dalam kes pelbagai jenis, keperluan ini lebih rumit. Dalam strategi tunggal jenis, anda boleh merancang parameter untuk menentukan maklumat seperti ketepatan, tetapi apabila anda merancang strategi pelbagai jenis, jelas bahawa maklumat ini ditulis dalam parameter yang kelihatan sangat rumit.

      Pada masa ini, anda perlu melihat dokumen API bursa untuk melihat sama ada terdapat antara muka perdagangan untuk maklumat yang berkaitan. Jika terdapat antara muka ini, anda boleh merancang maklumat seperti ketepatan capaian antara muka akses automatik dalam dasar, dan mengkonfigurasi apa yang tepat untuk permintaan capaian automatik kepada bursa dan kemudian disesuaikan dengan pembolehubah yang berkaitan dengan parameter dasar.

    • 6. Sesuai dengan bursa yang berbeza Mengapa kita meletakkan soalan ini di akhir? Oleh kerana penyelesaian masalah yang telah kita bincangkan di atas akan membawa kepada masalah terakhir ini, kerana strategi kami merancang untuk menggunakan antara muka pasaran agregat, mengakses pertukaran untuk menyesuaikan data dan ketepatan perdagangan, mengakses maklumat akaun secara berasingan untuk memproses setiap transaksi dan sebagainya. Terdapat perbezaan dalam panggilan antara muka, perbezaan dalam mekanisme. Perbezaan agak kecil untuk bursa tunai jika strategi grid ini meluas ke versi masa hadapan. Perbezaan lebih besar dalam mekanisme bursa yang berbeza. Satu penyelesaian adalah merancang perpustakaan templat FMZ. Menerbitkan reka bentuk dalam perpustakaan kelas untuk melaksanakan perbezaan ini. Mengurangkan strategi itu sendiri dan pemasangan bursa. Kelemahan untuk melakukan ini adalah bahawa anda perlu menulis perpustakaan kelas templat, dan di dalam templat ini, perbezaan untuk setiap bursa akan dilaksanakan secara khusus.

Reka bentuk perpustakaan templat

Berdasarkan analisis di atas, perancangan perpustakaan template digunakan untuk mengurangkan kesesuaian antara strategi dan mekanisme pertukaran, antara muka.

Kami boleh merancang perpustakaan kelas templat seperti ini (sebahagian kod telah dihapuskan):

function createBaseEx(e, funcConfigure) {
    var self = {}
    self.e = e 
    
    self.funcConfigure = funcConfigure
    self.name = e.GetName()
    self.type = self.name.includes("Futures_") ? "Futures" : "Spot"
    self.label = e.GetLabel()
    
    // 需要实现的接口
    self.interfaceGetTickers = null   // 创建异步获取聚合行情数据线程的函数
    self.interfaceGetAcc = null       // 创建异步获取账户数据线程的函数
    self.interfaceGetPos = null       // 获取持仓
    self.interfaceTrade = null        // 创建并发下单
    self.waitTickers = null           // 等待并发行情数据 
    self.waitAcc = null               // 等待账户并发数据
    self.waitTrade = null             // 等待下单并发数据
    self.calcAmount = null            // 根据交易对精度等数据计算下单量
    self.init = null                  // 初始化工作,获取精度等数据
    
    // 执行配置函数,给对象配置
    funcConfigure(self)

    // 检测configList约定的接口是否都实现
    _.each(configList, function(funcName) {
        if (!self[funcName]) {
            throw "接口" + funcName + "未实现"
        }
    })
    
    return self
}

$.createBaseEx = createBaseEx
$.getConfigureFunc = function(exName) {
    dicRegister = {
        "Futures_OKCoin" : funcConfigure_Futures_OKCoin,    // OK期货的实现
        "Huobi" : funcConfigure_Huobi,
        "Futures_Binance" : funcConfigure_Futures_Binance,
        "Binance" : funcConfigure_Binance,
        "WexApp" : funcConfigure_WexApp,                    // wexApp的实现
    }
    return dicRegister
}

Dalam templat, penulisan untuk pertukaran tertentu dapat dilaksanakan, contohnya dengan WexApp, alat analog FMZ:

function funcConfigure_WexApp(self) {
    var formatSymbol = function(originalSymbol) {
        // BTC_USDT
        var arr = originalSymbol.split("_")
        var baseCurrency = arr[0]
        var quoteCurrency = arr[1]
        return [originalSymbol, baseCurrency, quoteCurrency]
    }

    self.interfaceGetTickers = function interfaceGetTickers() {
        self.routineGetTicker = HttpQuery_Go("https://api.wex.app/api/v1/public/tickers")
    }

    self.waitTickers = function waitTickers() {
        var ret = []
        var arr = JSON.parse(self.routineGetTicker.wait()).data
        _.each(arr, function(ele) {
            ret.push({
                bid1: parseFloat(ele.buy), 
                bid1Vol: parseFloat(-1),
                ask1: parseFloat(ele.sell), 
                ask1Vol: parseFloat(-1),
                symbol: formatSymbol(ele.market)[0],
                type: "Spot", 
                originalSymbol: ele.market
            })
        })
        return ret 
    }

    self.interfaceGetAcc = function interfaceGetAcc(symbol, updateTS) {
        if (self.updateAccsTS != updateTS) {
            self.routineGetAcc = self.e.Go("GetAccount")
        }
    }

    self.waitAcc = function waitAcc(symbol, updateTS) {
        var arr = formatSymbol(symbol)
        var ret = null 
        if (self.updateAccsTS != updateTS) {
            ret = self.routineGetAcc.wait().Info
            self.bufferGetAccRet = ret 
        } else {
            ret = self.bufferGetAccRet
        }
        if (!ret) {
            return null 
        }        
        var acc = {symbol: symbol, Stocks: 0, FrozenStocks: 0, Balance: 0, FrozenBalance: 0, originalInfo: ret}
        _.each(ret.exchange, function(ele) {
            if (ele.currency == arr[1]) {
                // baseCurrency
                acc.Stocks = parseFloat(ele.free)
                acc.FrozenStocks = parseFloat(ele.frozen)
            } else if (ele.currency == arr[2]) {
                // quoteCurrency
                acc.Balance = parseFloat(ele.free)
                acc.FrozenBalance = parseFloat(ele.frozen)
            }
        })
        return acc
    }

    self.interfaceGetPos = function interfaceGetPos(symbol, price, initSpAcc, nowSpAcc) {
        var symbolInfo = self.getSymbolInfo(symbol)
        var sumInitStocks = initSpAcc.Stocks + initSpAcc.FrozenStocks
        var sumNowStocks = nowSpAcc.Stocks + nowSpAcc.FrozenStocks
        var diffStocks = _N(sumNowStocks - sumInitStocks, symbolInfo.amountPrecision)
        if (Math.abs(diffStocks) < symbolInfo.min / price) {
            return []
        }
        return [{symbol: symbol, amount: diffStocks, price: null, originalInfo: {}}]
    }

    self.interfaceTrade = function interfaceTrade(symbol, type, price, amount) {
        var tradeType = ""
        if (type == self.OPEN_LONG || type == self.COVER_SHORT) {
            tradeType = "bid"
        } else {
            tradeType = "ask"
        }
        var params = {
            "market": symbol,
            "side": tradeType,
            "amount": String(amount),
            "price" : String(-1),
            "type" : "market"
        }
        self.routineTrade = self.e.Go("IO", "api", "POST", "/api/v1/private/order", self.encodeParams(params))
    }

    self.waitTrade = function waitTrade() {
        return self.routineTrade.wait()
    }

    self.calcAmount = function calcAmount(symbol, type, price, amount) {
        // 获取交易对信息
        var symbolInfo = self.getSymbolInfo(symbol)
        if (!symbol) {
            throw symbol + ",交易对信息查询不到"
        }
        var tradeAmount = null 
        var equalAmount = null  // 记录币数
        if (type == self.OPEN_LONG || type == self.COVER_SHORT) {
            tradeAmount = _N(amount * price, parseFloat(symbolInfo.pricePrecision))
            // 检查最小交易量
            if (tradeAmount < symbolInfo.min) {
                Log(self.name, " tradeAmount:", tradeAmount, "小于", symbolInfo.min)
                return false 
            }
            equalAmount = tradeAmount / price
        } else {
            tradeAmount = _N(amount, parseFloat(symbolInfo.amountPrecision))
            // 检查最小交易量
            if (tradeAmount < symbolInfo.min / price) {
                Log(self.name, " tradeAmount:", tradeAmount, "小于", symbolInfo.min / price)
                return false 
            }
            equalAmount = tradeAmount
        }
        return [tradeAmount, equalAmount]
    }

    self.init = function init() {   // 自动处理精度等条件的函数
        var ret = JSON.parse(HttpQuery("https://api.wex.app/api/v1/public/markets"))
        _.each(ret.data, function(symbolInfo) {
            self.symbolsInfo.push({
                symbol: symbolInfo.pair,
                amountPrecision: parseFloat(symbolInfo.basePrecision),
                pricePrecision: parseFloat(symbolInfo.quotePrecision),
                multiplier: 1,
                min: parseFloat(symbolInfo.minQty),
                originalInfo: symbolInfo
            })
        })        
    }
}

Kemudian, menggunakan templat ini dalam strategi adalah mudah:

function main() {
    var fuExName = exchange.GetName()
    var fuConfigureFunc = $.getConfigureFunc()[fuExName]
    var ex = $.createBaseEx(exchange, fuConfigureFunc)

    var arrTestSymbol = ["LTC_USDT", "ETH_USDT", "EOS_USDT"]
    var ts = new Date().getTime()
    
    // 测试获取行情
    ex.goGetTickers()
    var tickers = ex.getTickers()
    Log("tickers:", tickers)
    
    // 测试获取账户信息
    ex.goGetAcc(symbol, ts)
    
    _.each(arrTestSymbol, function(symbol) {        
        _.each(tickers, function(ticker) {
            if (symbol == ticker.originalSymbol) {
                // 打印行情数据
                Log(symbol, ticker)
            }
        })

        // 打印资产数据
        var acc = ex.getAcc(symbol, ts)
        Log("acc:", acc.symbol, acc)
    })
}

Rancangan sebenar

Strategi penulisan berdasarkan templat di atas adalah mudah, keseluruhan strategi kira-kira 300+ baris, mewujudkan strategi grid pelbagai mata wang digital.

img

img

Kini, kita sedang kehilangan wang.T_TJika anda tidak mempunyai akses kepada laman web ini, anda tidak boleh mengakses laman web ini.

Jika anda berminat, anda boleh memasang WexApp dan bermain dengan beberapa kod pendaftaran:

购买地址: https://www.fmz.com/m/s/284507
注册码: 
adc7a2e0a2cfde542e3ace405d216731
f5db29d05f57266165ce92dc18fd0a30
1735dca92794943ddaf277828ee04c27
0281ea107935015491cda2b372a0997d
1d0d8ef1ea0ea1415eeee40404ed09cc

Dengan lebih daripada 200 U, hanya berlari, anda akan menemui satu kumpulan besar, perlahan-lahan berdarah. Stabiliti juga berkumpul, tidak bergerak sejak 27 Mei dan grid niaga hadapan belum berani mencuba sementara.


Berkaitan

Lebih lanjut

Kuantiti KecilTerima kasih, Quantify, lampu bercahaya di jalan raya.

Sembilan MatahariMeng Wei Wu!

Makhluk orbitTerima kasih.

Mimpi kecilTerima kasih atas sokongan anda!

Mimpi kecilTerima kasih atas sokongan anda!