avatar of 发明者量化-小小梦 发明者量化-小小梦
fokus pada Pesan pribadi
4
fokus pada
1271
Pengikut

Bagi para pemula dalam Perdagangan Kuantitatif di Dunia Kripto, silakan lihat ini - Membawa Anda Lebih Dekat ke Perdagangan Kuantitatif di Dunia Kripto (VI)

Dibuat di: 2021-06-04 10:08:48, diperbarui pada: 2024-12-04 21:14:15
comments   6
hits   2596

Bagi para pemula dalam Perdagangan Kuantitatif di Dunia Kripto, silakan lihat ini - Membawa Anda Lebih Dekat ke Perdagangan Kuantitatif di Dunia Kripto (VI)

Bagi para pemula dalam Perdagangan Kuantitatif di Dunia Kripto, silakan lihat ini - Membawa Anda Lebih Dekat ke Perdagangan Kuantitatif di Dunia Kripto (VI)

Pada artikel sebelumnya, kita bekerja sama untuk membuat strategi grid sederhana. Pada artikel ini, kita akan meningkatkan dan memperluas strategi ini menjadi strategi grid spot multivariasi dan menguji strategi ini dalam pertempuran sesungguhnya. Tujuannya bukanlah untuk menemukan “cawan suci”, tetapi untuk mengeksplorasi berbagai masalah dan solusi saat merancang strategi. Artikel ini akan menjelaskan beberapa pengalaman saya dalam merancang strategi ini. Konten artikel ini sedikit rumit dan memerlukan dasar-dasar pemrograman.

Desain berpikir berdasarkan kebutuhan strategis

Artikel ini, seperti artikel sebelumnya, masih membahas desain berdasarkan Inventor Quantization (FMZ.COM).

  • Berbagai macam varietas Terus terang saja, saya pikir strategi jaringan ini tidak hanyaBTC_USDT, juga bisa melakukanLTC_USDT/EOS_USDT/DOGE_USDT/ETC_USDT/ETH_USDT. Bagaimanapun, untuk pasangan perdagangan spot, semua produk yang ingin Anda perdagangkan dapat diperdagangkan secara grid pada saat yang sama.

Um~~Senang rasanya bisa menguasai pasar yang fluktuatif dengan beragam jenisnya. Persyaratannya terdengar sederhana, tetapi masalah muncul selama desain.

    1. Pertama, dapatkan informasi pasar berbagai varietas. Ini adalah masalah pertama yang harus dipecahkan. Setelah memeriksa dokumentasi API bursa, saya menemukan bahwa sebagian besar bursa menyediakan antarmuka informasi pasar agregat. Oke, gunakan antarmuka data pasar agregat untuk mendapatkan data.
    1. Masalah kedua yang dihadapi adalah aset akun. Karena kami ingin menerapkan strategi multivariasi, kami perlu mempertimbangkan pengelolaan aset terpisah untuk setiap transaksi. Dan untuk memperoleh data dan catatan semua aset sekaligus. Mengapa kita perlu mendapatkan data aset akun? Apakah kita perlu menyimpan catatan terpisah untuk setiap pasangan transaksi? Karena Anda perlu menilai aset yang tersedia saat melakukan pemesanan, apakah Anda perlu mendapatkannya sebelum membuat penilaian? Dan Anda perlu menghitung pendapatan. Apakah Anda juga perlu mencatat data aset akun awal terlebih dahulu, lalu memperoleh data aset akun berjalan dan membandingkannya dengan data awal untuk menghitung laba rugi? Untungnya, antarmuka akun aset bursa biasanya mengembalikan data aset semua mata uang. Kita hanya perlu memperolehnya sekali lalu memproses datanya.
    1. Desain parameter strategi. Desain parameter beberapa varietas sangat berbeda dari varietas tunggal, karena meskipun logika perdagangan setiap varietas sama, parameter selama perdagangan mungkin berbeda. Misalnya, dalam strategi grid, Anda mungkin ingin memperdagangkan 0,01 BTC setiap kali melakukan pasangan perdagangan BTC_USDT. Namun, jika Anda masih menggunakan parameter ini (memperdagangkan 0,01 koin) saat melakukan DOGE_USDT, itu jelas tidak tepat. Tentu saja, Anda dapat juga menanganinya sesuai dengan jumlah USDT. Namun, akan tetap ada masalah. Bagaimana jika Anda hanya ingin memperdagangkan 1000U dengan BTC_USDT dan 10U dengan DOGE_USDT? Permintaan tersebut tidak akan pernah terpenuhi. Beberapa siswa mungkin memikirkan pertanyaan ini dan kemudian berkata: “Saya dapat menetapkan beberapa kelompok parameter untuk mengendalikan parameter pasangan perdagangan yang berbeda secara terpisah.” Ini masih belum bisa memenuhi kebutuhan secara fleksibel. Berapa banyak kelompok parameter yang harus ditetapkan? Tiga set parameter ditetapkan. Bagaimana jika saya ingin memperdagangkan 4 jenis? Apakah mungkin untuk mengubah strategi dan menambahkan parameter… Oleh karena itu, ketika merancang parameter strategi multivariasi, kita harus mempertimbangkan sepenuhnya permintaan untuk parameter yang dibedakan. Salah satu solusinya adalah merancang parameter sebagai string biasa atau string JSON. Misalnya:
    ETHUSDT:100:0.002|LTCUSDT:20:0.1
    

    “|” memisahkan data setiap varietas, yang berartiETHUSDT:100:0.002Mengendalikan pasangan perdagangan ETH_USDT.LTCUSDT:20:0.1Mengendalikan pasangan perdagangan LTC_USDT. “|” di tengah berfungsi sebagai pemisah. ETHUSDT:100:0.002, di mana ETHUSDT menunjukkan pasangan perdagangan yang ingin Anda perdagangkan, 100 adalah jarak kisi, 0,002 adalah jumlah koin ETH yang diperdagangkan di setiap kisi, dan tanda “:” digunakan untuk memisahkan data ini (tentu saja, aturan parameter ini ditetapkan oleh perancang strategi). Anda dapat mendesainnya sesuai dengan kebutuhan Anda). Rangkaian ini berisi informasi parameter setiap produk yang ingin Anda perdagangkan. Analisis rangkaian ini dalam strategi dan tetapkan nilai tertentu pada variabel strategi untuk mengendalikan logika perdagangan setiap produk. Jadi bagaimana cara menguraikannya? Mari kita gunakan contoh di atas lagi.

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

    Bagi para pemula dalam Perdagangan Kuantitatif di Dunia Kripto, silakan lihat ini - Membawa Anda Lebih Dekat ke Perdagangan Kuantitatif di Dunia Kripto (VI)

    Anda dapat melihat bahwa parameter diurai dengan cara ini. Tentu saja, Anda juga dapat menggunakan string JSON secara langsung, yang lebih sederhana.

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

    Bagi para pemula dalam Perdagangan Kuantitatif di Dunia Kripto, silakan lihat ini - Membawa Anda Lebih Dekat ke Perdagangan Kuantitatif di Dunia Kripto (VI)

    1. Ketahanan data Terdapat pula perbedaan besar antara strategi yang dapat diterapkan secara praktis dan strategi pengajaran. Strategi pengajaran dalam artikel sebelumnya hanyalah uji coba awal dari logika dan desain strategi. Masih banyak lagi hal yang perlu dipertimbangkan dalam praktik yang sebenarnya. Selama perdagangan sesungguhnya, Anda dapat memulai dan menghentikan perdagangan sesungguhnya. Pada saat ini, semua data selama operasi waktu nyata akan hilang. Jadi bagaimana caranya agar disk sesungguhnya berhenti dan kemudian memulai ulang agar dapat terus berjalan pada kondisi sebelumnya? Di sini, perlu untuk menyimpan data kunci selama operasi waktu nyata sehingga data dapat dibaca dan dilanjutkan ketika sistem dihidupkan ulang. Dapat digunakan pada Platform Perdagangan Kuantitatif Inventor_G()Fungsi, atau menggunakan fungsi operasi databaseDBExec()Untuk mengetahui rinciannya, silakan merujuk pada dokumentasi API FMZ.

    Misalnya, kami merancang fungsi sapuan, 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()
    }
    
    1. Pembatasan pada keakuratan jumlah pesanan, keakuratan harga pesanan, jumlah pesanan minimum, jumlah pesanan minimum, dll.

    Sistem backtest tidak memberlakukan batasan ketat seperti itu pada kuantitas pesanan dan akurasi pesanan, tetapi dalam perdagangan nyata, setiap bursa mungkin memiliki standar ketat untuk harga pesanan dan kuantitas pesanan, dan standar ini untuk setiap pasangan perdagangan juga sangat ketat. Pembatasan tidak sama. Oleh karena itu, para pemula sering menguji sistem backtest dan melihat berbagai macam masalah saat memicu transaksi di pasar riil. Mereka juga tidak membaca pesan kesalahan dan mengalami berbagai macam fenomena aneh [dog head].

    Untuk banyak varietas, persyaratan ini lebih rumit. Untuk strategi satu produk, Anda dapat merancang parameter untuk menentukan informasi seperti akurasi. Namun, saat merancang strategi multiproduk, jelas bahwa menuliskan informasi ini ke dalam parameter akan membuat parameter tampak sangat besar.

    Saat ini, Anda perlu memeriksa dokumentasi API bursa untuk melihat apakah ada antarmuka dengan informasi terkait pasangan perdagangan dalam dokumentasi bursa. Jika antarmuka ini tersedia, Anda dapat merancang antarmuka akses otomatis dalam strategi untuk mendapatkan informasi seperti akurasi, dan mengonfigurasinya ke informasi pasangan perdagangan yang terlibat dalam transaksi (dalam istilah sederhana, akurasi secara otomatis diminta dari bursa, dan kemudian disesuaikan dengan parameter strategi). variabel).

    1. Adaptasi terhadap berbagai pertukaran Mengapa pertanyaan ini diletakkan di akhir? Karena solusi dari permasalahan yang kita bahas di atas akan memunculkan permasalahan terakhir ini, karena strategi kita berencana untuk menggunakan antarmuka pasar agregat, mengakses keakuratan pasangan perdagangan bursa dan adaptasi data lainnya, mengakses informasi akun dan memproses setiap pasangan perdagangan secara terpisah, dll. Solusi ini akan Ada perbedaan besar antara bursa. Ada perbedaan dalam panggilan antarmuka dan perbedaan dalam mekanisme. Untuk bursa spot, perbedaannya lebih kecil jika strategi grid ini diperluas menjadi versi berjangka. Perbedaan dalam mekanisme berbagai pertukaran bahkan lebih besar. Salah satu solusinya adalah merancang pustaka templat FMZ. Tulis dan rancang implementasi berbeda ini dalam pustaka kelas. Mengurangi keterkaitan antara strategi itu sendiri dan pertukaran. Kerugian melakukan ini adalah Anda perlu menulis pustaka templat dan menerapkannya secara khusus untuk setiap pertukaran dalam templat ini.

Mendesain perpustakaan templat

Berdasarkan analisis di atas, pustaka templat dirancang untuk mengurangi keterkaitan antara strategi dan mekanisme pertukaran serta antarmuka.

Kita dapat mendesain pustaka kelas templat ini seperti ini (beberapa kode dihilangkan):

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, tuliskan untuk implementasi pertukaran tertentu, misalnya, ambil disk simulasi FMZ WexApp sebagai contoh:

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

Maka menggunakan template ini dalam strateginya sangatlah 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)
    })
}

Strategi pasar riil

Sangat mudah untuk merancang dan menulis strategi berdasarkan templat di atas. Seluruh strategi terdiri dari sekitar 300+ baris, yang menerapkan strategi grid multivariasi spot mata uang digital.

Bagi para pemula dalam Perdagangan Kuantitatif di Dunia Kripto, silakan lihat ini - Membawa Anda Lebih Dekat ke Perdagangan Kuantitatif di Dunia Kripto (VI)

Bagi para pemula dalam Perdagangan Kuantitatif di Dunia Kripto, silakan lihat ini - Membawa Anda Lebih Dekat ke Perdagangan Kuantitatif di Dunia Kripto (VI)

Saat ini sedang merugiT_T, kode sumbernya tidak akan dirilis untuk saat ini.

Berikut ini beberapa kode registrasi. Jika Anda tertarik, Anda dapat mencobanya di wexApp:

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

Jumlahnya hanya sekitar 200 dolar AS, dan ketika mulai berjalan, ia menemui pasar besar yang berat sebelah dan perlahan pulih. Keuntungan terbesar dari grid spot adalah: “Anda bisa tidur nyenyak!” Stabilitasnya oke. Saya belum menyentuhnya sejak 27 Mei. Saya tidak berani mencoba jaringan berjangka untuk saat ini.