Reka bentuk strategi lindung nilai tunai mata wang digital ((1)

Penulis:Mimpi kecil, Dicipta: 2021-07-19 17:38:24, Dikemas kini: 2023-09-20 10:35:16

img

Reka bentuk strategi lindung nilai tunai mata wang digital ((1)

Untuk pemula dalam merancang strategi, strategi lindung nilai adalah strategi latihan yang sangat baik. Artikel ini mewujudkan strategi lindung nilai tunai mata wang digital yang mudah tetapi boleh digunakan, dengan harapan dapat memberi pengalaman reka bentuk kepada pemula.

Merancang beberapa fungsi, parameter antara muka dasar mengikut keperluan dasar

Pertama, untuk menjelaskan bahawa strategi yang akan direka adalah strategi hedging mata wang digital, kami merancang hedging yang paling mudah, hanya antara dua bursa mata wang yang menjual dengan harga yang lebih tinggi dan membeli dengan harga yang lebih rendah untuk mendapatkan perbezaan. Apabila semua pertukaran yang lebih tinggi adalah mata wang (kerana semua mata wang yang lebih tinggi telah dijual) dan semua bursa yang lebih rendah adalah mata wang (kerana semua mata wang yang lebih rendah telah dibeli sebagai mata wang) tidak dapat dihalang.

Harga, kuantiti, dan pertukaran mempunyai had ketepatan semasa melakukan peruntukan peruntukan dan terdapat juga had jumlah peruntukan minimum. Selain daripada had minimum, strategi di luar had minimum dalam melakukan peruntukan peruntukan juga mempertimbangkan jumlah peruntukan yang paling besar dalam satu peruntukan, jika jumlah peruntukan terlalu besar, tidak akan ada jumlah pesanan yang mencukupi. Juga perlu dipertimbangkan bagaimana menukar kadar pertukaran jika dua mata wang yang diperdagangkan berbeza.

Mengikut pertimbangan ini, strategi ini memerlukan beberapa parameter:

  • Harga perpaduan:hedgeDiffPrice, Apabila perbezaan melebihi nilai ini, operasi lindung nilai akan dipicu.
  • Kewangan minimum:minHedgeAmount, jumlah unit minimum yang boleh dilindungi (jumlah syiling) ⇒
  • Maksimum tunggakan:maxHedgeAmount, jumlah maksimum yang dikurangkan dalam satu hedging (angka mata wang) ‖.
  • A: Kecekapan harga:pricePrecisionA, A adalah harga yang tepat untuk pesanan di bursa (digit kecil).
  • Perincian ketepatan:amountPrecisionAPerincian kuantiti yang lebih rendah daripada bursa A.
  • Harga B:pricePrecisionB, Kecekapan harga pesanan di bursa B (angka kecil) ⇒
  • Perincian perincian:amountPrecisionBPeringkat B adalah satu-satunya yang mempunyai ketepatan yang lebih rendah.
  • Nilai pertukaran A:rateA, pertukaran mata wang objek bursa pertama yang ditambahkan, tidak ditukar oleh lalai 1.
  • Nilai pertukaran B:rateB, penukaran nilai tukar objek bursa kedua yang ditambah, tidak ditukaran 1 secara lalai.

Strategi hedging memerlukan bilangan mata wang kedua-dua akaun sentiasa tidak berubah (iaitu tidak memegang mana-mana kedudukan arah, kekal netral), jadi strategi ini memerlukan logik keseimbangan yang sentiasa mengesan keseimbangan. Apabila mengesan keseimbangan, kita tidak dapat mengelakkan data aset dari kedua-dua bursa. Kita perlu menulis fungsi untuk menggunakannya.

  • kemas kiniAccs
    function updateAccs(arrEx) {
        var ret = []
        for (var i = 0 ; i < arrEx.length ; i++) {
            var acc = arrEx[i].GetAccount()
            if (!acc) {
                return null
            }
            ret.push(acc)
        }
        return ret 
    }
    

Jika tidak ada pesanan yang diselesaikan selepas pesanan tersebut, kita perlu membatalkannya dengan tepat pada masanya, tidak boleh membiarkan pesanan itu tetap tergantung. Operasi ini perlu diuruskan baik dalam modul imbangan atau dalam logik lindung nilai, jadi kita juga perlu merancang fungsi pencabutan pesanan sepenuhnya.

  • BatalkanSemua
    function cancelAll() {
        _.each(exchanges, function(ex) {
            while (true) {
                var orders = _C(ex.GetOrders)
                if (orders.length == 0) {
                    break
                }
                for (var i = 0 ; i < orders.length ; i++) {
                    ex.CancelOrder(orders[i].Id, orders[i])
                    Sleep(500)
                }
            }
        })
    }
    

Dalam jumlah syiling yang seimbang, kita perlu mencari harga yang terkumpul kepada jumlah syiling tertentu dalam data kedalaman, jadi kita memerlukan fungsi seperti ini untuk memprosesnya.

  • mendapatkanDepthPrice
    function getDepthPrice(depth, side, amount) {
        var arr = depth[side]
        var sum = 0
        var price = null
        for (var i = 0 ; i < arr.length ; i++) {
            var ele = arr[i]
            sum += ele.Amount
            if (sum >= amount) {
                price = ele.Price
                break
            }
        }
        return price
    }
    

Kemudian, kita perlu merancang dan menulis operasi pesanan bawah yang khusus untuk lindungan, yang perlu direka sebagai pesanan bersama:

  • perisai
    function hedge(buyEx, sellEx, price, amount) {
        var buyRoutine = buyEx.Go("Buy", price, amount)
        var sellRoutine = sellEx.Go("Sell", price, amount)
        Sleep(500)
        buyRoutine.wait()
        sellRoutine.wait()
    }
    

Akhirnya, kita akan selesaikan reka bentuk fungsi keseimbangan, fungsi keseimbangan agak rumit.

  • simpanBalance
    function keepBalance(initAccs, nowAccs, depths) {
        var initSumStocks = 0
        var nowSumStocks = 0 
        _.each(initAccs, function(acc) {
            initSumStocks += acc.Stocks + acc.FrozenStocks
        })
        _.each(nowAccs, function(acc) {
            nowSumStocks += acc.Stocks + acc.FrozenStocks
        })
      
        var diff = nowSumStocks - initSumStocks
        // 计算币差
        if (Math.abs(diff) > minHedgeAmount && initAccs.length == nowAccs.length && nowAccs.length == depths.length) {
            var index = -1
            var available = []
            var side = diff > 0 ? "Bids" : "Asks"
            for (var i = 0 ; i < nowAccs.length ; i++) {
                var price = getDepthPrice(depths[i], side, Math.abs(diff))
                if (side == "Bids" && nowAccs[i].Stocks > Math.abs(diff)) {
                    available.push(i)
                } else if (price && nowAccs[i].Balance / price > Math.abs(diff)) {
                    available.push(i)
                }
            }
            for (var i = 0 ; i < available.length ; i++) {
                if (index == -1) {
                    index = available[i]
                } else {
                    var priceIndex = getDepthPrice(depths[index], side, Math.abs(diff))
                    var priceI = getDepthPrice(depths[available[i]], side, Math.abs(diff))
                    if (side == "Bids" && priceIndex && priceI && priceI > priceIndex) {
                        index = available[i]
                    } else if (priceIndex && priceI && priceI < priceIndex) {
                        index = available[i]
                    }
                }
            }
            if (index == -1) {
                Log("无法平衡")            
            } else {
                // 平衡下单
                var price = getDepthPrice(depths[index], side, Math.abs(diff))
                if (price) {
                    var tradeFunc = side == "Bids" ? exchanges[index].Sell : exchanges[index].Buy
                    tradeFunc(price, Math.abs(diff))
                } else {
                    Log("价格无效", price)
                }
            }        
            return false
        } else if (!(initAccs.length == nowAccs.length && nowAccs.length == depths.length)) {
            Log("错误:", "initAccs.length:", initAccs.length, "nowAccs.length:", nowAccs.length, "depths.length:", depths.length)
            return true 
        } else {
            return true 
        }
    }
    

Fungsi-fungsi ini telah direka mengikut keperluan dasar dan berikut adalah fungsi utama untuk memulakan reka bentuk dasar.

Reka bentuk fungsi utama strategi

Strategi di FMZ adalah daripadamainFungsi bermula pada.mainPada bahagian permulaan fungsi, kita perlu melakukan beberapa kerja inisialisasi strategi.

  • Nama objek bursa Oleh kerana banyak operasi dalam strategi digunakan untuk objek bursa, seperti mendapatkan pasaran, meletakkan pesanan, dan sebagainya. Oleh itu, menggunakan nama yang lebih panjang setiap kali akan menjadi masalah, tip kecil adalah menggunakan nama yang mudah sebagai gantinya, sebagai contoh:

    var exA = exchanges[0]
    var exB = exchanges[1]
    

    Dengan cara ini, anda akan berasa selesa untuk menulis kod di belakang.

  • Perancangan mengenai kadar pertukaran dan ketepatan

      // 精度,汇率设置
      if (rateA != 1) {
          // 设置汇率A
          exA.SetRate(rateA)
          Log("交易所A设置汇率:", rateA, "#FF0000")
      }
      if (rateB != 1) {
          // 设置汇率B
          exB.SetRate(rateB)
          Log("交易所B设置汇率:", rateB, "#FF0000")
      }
      exA.SetPrecision(pricePrecisionA, amountPrecisionA)
      exB.SetPrecision(pricePrecisionB, amountPrecisionB)
    

    Jika parameter pertukaranrateArateBTerdapat tetapan untuk 1 ((default adalah 1), iaiturateA != 1ataurateB != 1Tidak akan mencetuskan, jadi tidak akan menetapkan penukaran mata wang.

  • Set semula semua data

    img

    Kadang-kadang, anda perlu memadamkan semua log atau catatan kosong semasa memulakan dasar. Anda boleh membuat parameter antara muka dasar.isReset, dan kemudian merancang semula bahagian kod yang dimulakan dalam dasar, seperti:

      if (isReset) {   // 当isReset为真时重置数据
          _G(null)
          LogReset(1)
          LogProfitReset()
          LogVacuum()
          Log("重置所有数据", "#FF0000")
      }
    
  • Memulihkan data akaun awal, mengemas kini data akaun semasa Untuk menilai keseimbangan, strategi memerlukan rekod yang berterusan mengenai keadaan aset akaun awal yang digunakan berbanding dengan keadaan semasa.nowAccsIni adalah pemboleh ubah yang digunakan untuk merakam data akaun semasa menggunakan fungsi yang baru kita bina.updateAccsUntuk mendapatkan data akaun bagi bursa semasa.initAccsIa digunakan untuk merakam keadaan akaun awal (data seperti jumlah mata wang, jumlah mata wang yang ditagih oleh Bursa A dan Bursa B);initAccsPenggunaan pertama_G()Fungsi pemulihan ((_G) berfungsi untuk menyimpan data secara kekal dan dapat mengembalikan data yang disimpan, lihat dokumentasi API:Pautan), jika permintaan tidak dapat diisi, gunakan maklumat akaun semasa untuk memberi dan menggunakan_GFungsi rekod.

    Contohnya, kod berikut:

      var nowAccs = _C(updateAccs, exchanges)
      var initAccs = _G("initAccs")
      if (!initAccs) {
          initAccs = nowAccs
          _G("initAccs", initAccs)
      }
    

Logik urus niaga, putaran utama dalam fungsi utama

Kod dalam gelung utama adalah proses yang dijalankan oleh logik dasar setiap pusingan, dan pelaksanaan berulang berulang membentuk gelung utama; mari kita lihat proses yang dijalankan oleh program dalam gelung utama setiap kali.

  • Mengambil data pasaran dan menilai keberkesanan data pasaran

          var ts = new Date().getTime()
          var depthARoutine = exA.Go("GetDepth")
          var depthBRoutine = exB.Go("GetDepth")
          var depthA = depthARoutine.wait()
          var depthB = depthBRoutine.wait()
          if (!depthA || !depthB || depthA.Asks.length == 0 || depthA.Bids.length == 0 || depthB.Asks.length == 0 || depthB.Bids.length == 0) {
              Sleep(500)
              continue 
          }
    

    Di sini anda boleh melihat fungsi yang menggunakan platform FMZ.exchange.Go, membuat panggilanGetDepth()Objek serentak antara mukadepthARoutinedepthBRoutine│ Apabila kedua-dua objek yang sama dibuat, panggilGetDepth()Antara muka juga berlaku dengan serta-merta, di mana kedua-dua permintaan untuk mendapatkan data mendalam dihantar ke bursa masa lalu. Kemudian panggildepthARoutinedepthBRoutineobjekwait()Cara untuk mendapatkan data mendalam.
    Selepas mendapatkan data mendalam, data mendalam perlu diperiksa untuk menilai keberkesanannya.continuePerkataan yang dilakukan semula dalam lingkaran utama.

  • Penggunaan价差值Apakah parameternya?差价比例Parameter?

          var targetDiffPrice = hedgeDiffPrice
          if (diffAsPercentage) {
              targetDiffPrice = (depthA.Bids[0].Price + depthB.Asks[0].Price + depthB.Bids[0].Price + depthA.Asks[0].Price) / 4 * hedgeDiffPercentage
          }
    

    Dalam parameter, kita telah membuat reka bentuk seperti ini. Parameter FMZ boleh berdasarkan pada parameter.TunjukkanatauBerlindungJadi kita boleh buat satu parameter untuk menentukan apakah yang digunakan.价格差atau差价比例

    img

    Tambah satu parameter pada parameter antara muka strategidiffAsPercentage❖ Dua lagi parameter yang berdasarkan parameter ini boleh dilihat atau disembunyikan adalah:hedgeDiffPrice@!diffAsPercentageApabiladiffAsPercentageUntuk memaparkan parameter ini.hedgeDiffPercentage@diffAsPercentageApabiladiffAsPercentageMenunjukkan parameter tersebut adalah benar. Selepas kita merancangnya, kita pilih.diffAsPercentageParameter, iaitu sebagai syarat pencetus lindung nilai mengikut nisbah perbezaan harga; tidak dipilihdiffAsPercentageParameter adalah perbezaan harga sebagai syarat pencetus lindung nilai.

  • Menentukan syarat pemicu lindung nilai

          if (depthA.Bids[0].Price - depthB.Asks[0].Price > targetDiffPrice && Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount) >= minHedgeAmount) {          // A -> B 盘口条件满足            
              var price = (depthA.Bids[0].Price + depthB.Asks[0].Price) / 2
              var amount = Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount)
              if (nowAccs[0].Stocks > minHedgeAmount && nowAccs[1].Balance / price > minHedgeAmount) {
                  amount = Math.min(amount, nowAccs[0].Stocks, nowAccs[1].Balance / price, maxHedgeAmount)
                  Log("触发A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, price, amount, nowAccs[1].Balance / price, nowAccs[0].Stocks)  // 提示信息
                  hedge(exB, exA, price, amount)
                  cancelAll()
                  lastKeepBalanceTS = 0
                  isTrade = true 
              }            
          } else if (depthB.Bids[0].Price - depthA.Asks[0].Price > targetDiffPrice && Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount) >= minHedgeAmount) {   // B -> A 盘口条件满足
              var price = (depthB.Bids[0].Price + depthA.Asks[0].Price) / 2
              var amount = Math.min(depthB.Bids[0].Amount, depthA.Asks[0].Amount)
              if (nowAccs[1].Stocks > minHedgeAmount && nowAccs[0].Balance / price > minHedgeAmount) {
                  amount = Math.min(amount, nowAccs[1].Stocks, nowAccs[0].Balance / price, maxHedgeAmount)
                  Log("触发B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, price, amount, nowAccs[0].Balance / price, nowAccs[1].Stocks)  // 提示信息
                  hedge(exA, exB, price, amount)
                  cancelAll()
                  lastKeepBalanceTS = 0
                  isTrade = true 
              }            
          }
    

    Di samping itu, ia juga boleh menyebabkan pencemaran udara. 1, pertama memenuhi perbezaan lindung nilai, dan hanya boleh dilindung nilai apabila perbezaan dalam ledangan memenuhi parameter perbezaan yang ditetapkan. 2, margin yang boleh diperdagangkan harus memenuhi margin minimum yang ditetapkan dalam parameter, kerana jumlah minimum yang mungkin dibatasi oleh pelbagai bursa berbeza, maka mengambil yang terkecil dari kedua-dua. 3. Aset di bursa yang menjual operasi cukup untuk dijual dan aset di bursa yang membeli operasi cukup untuk dibeli. Apabila syarat-syarat ini dipenuhi, fungsi lindung nilai dijalankan untuk melakukan lindung nilai. Sebelum fungsi utama, kita mengisytiharkan satu pembolehubah terlebih dahulu.isTradeUntuk menandakan sama ada terdapat lindung nilai, jika lindung nilai dipicu, anda menetapkan pembolehubah ini sebagaitrue.dan menetapkan semula pembolehubah globallastKeepBalanceTSUntuk 0 ((lastKeepBalanceTS digunakan untuk menandakan tetingkap masa operasi imbangan terakhir, yang ditetapkan kepada 0 akan mencetuskan operasi imbangan dengan segera), dan kemudian membatalkan semua senarai tanggungan.

  • Operasi keseimbangan

          if (ts - lastKeepBalanceTS > keepBalanceCyc * 1000) {
              nowAccs = _C(updateAccs, exchanges)
              var isBalance = keepBalance(initAccs, nowAccs, [depthA, depthB])
              cancelAll()
              if (isBalance) {
                  lastKeepBalanceTS = ts
                  if (isTrade) {
                      var nowBalance = _.reduce(nowAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
                      var initBalance = _.reduce(initAccs, function(sumBalance, acc) {return sumBalance + acc.Balance}, 0)
                      LogProfit(nowBalance - initBalance, nowBalance, initBalance, nowAccs)
                      isTrade = false 
                  }                
              }            
          }
    

    Fungsi imbangan akan dijalankan secara berkala, tetapi jika operasi lindung nilai telah dicetuskan,lastKeepBalanceTSOperasi imbangan yang diset semula ke 0 akan segera dicetuskan. Hasil akan dikira selepas imbangan berjaya.

  • Maklumat status

          LogStatus(_D(), "A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, " B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, " targetDiffPrice:", targetDiffPrice, "\n", 
              "当前A,Stocks:", nowAccs[0].Stocks, "FrozenStocks:", nowAccs[0].FrozenStocks, "Balance:", nowAccs[0].Balance, "FrozenBalance", nowAccs[0].FrozenBalance, "\n", 
              "当前B,Stocks:", nowAccs[1].Stocks, "FrozenStocks:", nowAccs[1].FrozenStocks, "Balance:", nowAccs[1].Balance, "FrozenBalance", nowAccs[1].FrozenBalance, "\n", 
              "初始A,Stocks:", initAccs[0].Stocks, "FrozenStocks:", initAccs[0].FrozenStocks, "Balance:", initAccs[0].Balance, "FrozenBalance", initAccs[0].FrozenBalance, "\n", 
              "初始B,Stocks:", initAccs[1].Stocks, "FrozenStocks:", initAccs[1].FrozenStocks, "Balance:", initAccs[1].Balance, "FrozenBalance", initAccs[1].FrozenBalance)
    

    Bar status tidak mempunyai reka bentuk yang sangat rumit, menunjukkan masa semasa, menunjukkan perbezaan antara bursa A ke bursa B dan perbezaan antara bursa B ke bursa A. Menunjukkan perbezaan sasaran lindung nilai semasa. Menunjukkan data aset akaun bursa A, data aset akaun pertukaran B.

Pengurusan untuk pasangan transaksi dalam mata wang yang berbeza

Pada parameter, kita merancang parameter untuk menukar nilai pertukaran, dan pada permulaan strategi, kita akan membuat parameter untuk menukar nilai pertukaran.mainDi bahagian operasi awal fungsi, kita juga merancang penukaran nilai tukar.SetRateFungsi penukaran kadar pertukaran perlu dilaksanakan terlebih dahulu. Kerana fungsi ini mempengaruhi dua peringkat:

  • Semua data pasaran, data pesanan, dan data simpanan akan ditukar harga.
  • Pertukaran mata wang dalam aset akaun. Sebagai contoh, pasangan dagangan semasaBTC_USDTHarga dalam satu unitUSDTIa juga boleh digunakan sebagai mata wang dalam aset akaun.USDTJika saya mahu menukar nilai kepada CNY, atur dalam kod.exchange.SetRate(6.8)Hanya perluexchangeSemua data yang diperoleh oleh fungsi di bawah objek bursa ini ditukar kepada CNY. Dan jika anda mempunyai mata wang yang sama, anda akan mendapat wang yang sama.SetRatePenghantaran fungsiKadar pertukaran mata wang semasa kepada mata wang sasaran

Rancangan lengkap:Strategi lindung nilai semasa untuk mata wang yang berlainan


Berkaitan

Lebih lanjut

Squirrels - Pengembara Besar di Ukrainehebat.