Reka bentuk strategi Martingale untuk niaga hadapan cryptocurrency

Penulis:Lydia, Dicipta: 2022-08-04 15:41:45, Dikemas kini: 2023-09-21 21:10:49

img

Reka bentuk strategi Martingale untuk niaga hadapan cryptocurrency

Baru-baru ini, terdapat banyak strategi Martingale yang dibincangkan dalam kumpulan rasmi FMZ, dan tidak banyak strategi Martingale kontrak mata wang kripto di platform. Oleh itu, saya mengambil peluang ini untuk merancang strategi Martingale yang mudah untuk niaga hadapan mata wang kripto. Mengapa ia dipanggil strategi Martingale? Kerana risiko berpotensi strategi Martin memang tidak kecil, ia tidak direka dengan tepat mengikut strategi Martin. Walau bagaimanapun, jenis strategi ini masih mempunyai banyak risiko, dan tetapan parameter strategi jenis Martin sangat berkaitan dengan risiko, dan risiko tidak boleh diabaikan.

Artikel ini terutamanya menerangkan dan belajar dari reka bentuk strategi jenis Martin.

Mendapatkan ekuiti keseluruhan

Jumlah ekuiti sering digunakan ketika merancang strategi niaga hadapan mata wang kripto. Ini kerana pulangan harus dikira, terutamanya apabila anda perlu mengira pulangan terapung. Oleh kerana kedudukan didiami dengan margin, pesanan yang menunggu juga diduduki. Pada masa ini, antara muka APIexchange.GetAccount()Pertukaran niaga hadapan mata wang kripto kebanyakan menyediakan data ekuiti keseluruhan, tetapi atribut ini tidak dikemas secara seragam di FMZ.

Jadi kita merancang fungsi untuk mendapatkan data ini mengikut pertukaran yang berbeza:

// OKEX V5 obtain total equity
function getTotalEquity_OKEX_V5() {
    var totalEquity = null 
    var ret = exchange.IO("api", "GET", "/api/v5/account/balance", "ccy=USDT")
    if (ret) {
        try {
            totalEquity = parseFloat(ret.data[0].details[0].eq)
        } catch(e) {
            Log("failed to obtain the total equity of the account!")
            return null
        }
    }
    return totalEquity
}

// Binance futures
function getTotalEquity_Binance() {
    var totalEquity = null 
    var ret = exchange.GetAccount()
    if (ret) {
        try {
            totalEquity = parseFloat(ret.Info.totalWalletBalance)
        } catch(e) {
            Log("failed to obtain the total equity of the account!")
            return null
        }
    }
    return totalEquity
}

PeraturantotalEquityKemudian kita menulis fungsi sebagai entri panggilan, dan memanggil fungsi yang sepadan mengikut nama bursa.

function getTotalEquity() {
    var exName = exchange.GetName()
    if (exName == "Futures_OKCoin") {
        return getTotalEquity_OKEX_V5()
    } else if (exName == "Futures_Binance") {
        return getTotalEquity_Binance()
    } else {
        throw "This exchange is not supported"
    }
}

Merancang beberapa fungsi tambahan

Sebelum merancang fungsi utama dan logik utama, kita perlu melakukan beberapa persiapan dan merancang beberapa fungsi tambahan.

  • Batalkan semua pesanan yang sedang menunggu

    function cancelAll() {
        while (1) {
            var orders = _C(exchange.GetOrders)
            if (orders.length == 0) {
                break
            }
            for (var i = 0 ; i < orders.length ; i++) {
                exchange.CancelOrder(orders[i].Id, orders[i])
                Sleep(500)
            }
            Sleep(500)
        }
    }
    

    Fungsi ini biasa bagi mereka yang sering membaca kod contoh strategi pada kotak strategi FMZ, dan banyak strategi telah menggunakan reka bentuk yang sama. Fungsi ini adalah untuk mendapatkan senarai pesanan yang sedang menunggu, dan kemudian membatalkannya satu demi satu.

  • Operasi penempatan bagi niaga hadapan

    function trade(distance, price, amount) {
        var tradeFunc = null 
        if (distance == "buy") {
            tradeFunc = exchange.Buy
        } else if (distance == "sell") {
            tradeFunc = exchange.Sell
        } else if (distance == "closebuy") {
            tradeFunc = exchange.Sell
        } else {
            tradeFunc = exchange.Buy
        }
        exchange.SetDirection(distance)
        return tradeFunc(price, amount)
    }
    
    function openLong(price, amount) {
        return trade("buy", price, amount)
    }
    
    function openShort(price, amount) {
        return trade("sell", price, amount)
    }
    
    function coverLong(price, amount) {
        return trade("closebuy", price, amount)
    }
    
    function coverShort(price, amount) {
        return trade("closesell", price, amount)
    }
    

    Terdapat empat arah untuk perdagangan niaga hadapan: openLong, openShort, coverLong andcoverShort. Jadi kami merancang empat fungsi pesanan yang sepadan dengan operasi ini. Jika anda hanya mempertimbangkan pesanan, maka terdapat beberapa faktor yang diperlukan: arah, harga pesanan dan jumlah pesanan. Jadi kami juga merancang fungsi bernama:tradeuntuk mengendalikan operasi apabiladistance, price, amountditentukan. Panggilan fungsi untuk openLong, openShort, coverLong dan coverShort akhirnya diselesaikan olehtradefungsi, iaitu, meletakkan pesanan di bursa niaga hadapan berdasarkan jarak, harga, dan kuantiti yang ditetapkan.

Fungsi utama

Idea strategi ini sangat mudah, ambil harga semasa sebagai asas, dan tempatkan pesanan jual (pendek) dan beli (panjang) pada jarak tertentu ke atas atau ke bawah.

  • Kerja awal Kerana pesanan yang menunggu, kita perlukan dua pembolehubah global untuk merakam ID pesanan.

    var buyOrderId = null
    var sellOrderId = null
    

    Kemudian parameter antara muka strategi direka untuk menggunakan pilihan bot simulasi OKEX_V5, jadi beberapa pemprosesan perlu dilakukan dalam kod:

    var exName = exchange.GetName()    
    // Switch OKEX V5 simulated bot
    if (isSimulate && exName == "Futures_OKCoin") {
        exchange.IO("simulate", true)
    }
    

    Terdapat juga pilihan untuk menetapkan semula semua maklumat dalam parameter antara muka, jadi harus ada pemprosesan yang sepadan dalam kod:

    if (isReset) {
        _G(null)
        LogReset(1)
        LogProfitReset()
        LogVacuum()
        Log("reset all data", "#FF0000")
    }
    

    Kami hanya menjalankan kontrak kekal, jadi tulisan ditetapkan di sini dan ditetapkan untuk kekal sahaja.

    exchange.SetContractType("swap")
    

    Kemudian kita juga perlu mempertimbangkan ketepatan harga pesanan dan jumlah pesanan. Jika ketepatan tidak ditetapkan dengan betul, ketepatan akan hilang semasa proses pengiraan strategi. Jika data mempunyai sebilangan besar tempat perpuluhan, mudah menyebabkan pesanan ditolak oleh antara muka pertukaran.

    exchange.SetPrecision(pricePrecision, amountPrecision)
    Log("set precision", pricePrecision, amountPrecision)
    

    Pemulihan data mudah dengan reka bentuk

    if (totalEq == -1 && !IsVirtual()) {
        var recoverTotalEq = _G("totalEq")
        if (!recoverTotalEq) {
            var currTotalEq = getTotalEquity()
            if (currTotalEq) {
                totalEq = currTotalEq
                _G("totalEq", currTotalEq)
            } else {
                throw "failed to obtain initial equity"
            }
        } else {
            totalEq = recoverTotalEq
        }
    }
    

    Jika anda ingin menentukan jumlah ekuiti awal akaun apabila strategi berjalan, anda boleh menetapkan parametertotalEqJika parameter ini ditetapkan kepada -1, strategi akan membaca data ekuiti total yang disimpan. Jika tidak ada data ekuiti total yang disimpan, ekuiti total yang dibaca semasa digunakan sebagai ekuiti total awal strategi yang sedang berjalan. Selepas itu, peningkatan ekuiti total menunjukkan keuntungan, dan penurunan ekuiti total menunjukkan kerugian. Jika data ekuiti total dibaca, strategi akan terus berjalan dengan data ini.

  • Logik utama Selepas kerja awal dilakukan, akhirnya kita datang ke bahagian logik utama strategi. untuk kemudahan penjelasan, saya menulis arahan terus pada kod komen.

      while (1) {                                  // The main logic of the strategy is designed as an infinite loop
          var ticker = _C(exchange.GetTicker)      // Read the current market information first, mainly using the latest transaction price
          var pos = _C(exchange.GetPosition)       // Read current position data
          if (pos.length > 1) {                    // Judging the position data, because of the logic of this strategy, it is unlikely that long and short positions will appear at the same time, so if there are long and short positions at the same time, an error will be thrown
              Log(pos)
              throw "Simultaneous long and short positions"                  // Throw an error to stop the strategy
          }
          //Depends on status
          if (pos.length == 0) {                    // Make different operations according to the position status, when there is no position, pos.length == 0 
              // If you have not held a position, count the profit once
              if (!IsVirtual()) {
                  var currTotalEq = getTotalEquity()
                  if (currTotalEq) {
                      LogProfit(currTotalEq - totalEq, "current total equity:", currTotalEq)
                  }
              }
    
              buyOrderId = openLong(ticker.Last - targetProfit, amount)       // Open a buy order for a long position
              sellOrderId = openShort(ticker.Last + targetProfit, amount)     // Open a short sell order
          } else if (pos[0].Type == PD_LONG) {   // For long positions, the position and quantity of pending orders are different
              var n = 1
              var price = ticker.Last
              buyOrderId = openLong(price - targetProfit * n, amount)
              sellOrderId = coverLong(pos[0].Price + targetProfit, pos[0].Amount)
          } else if (pos[0].Type == PD_SHORT) {   // For short positions, the position and quantity of pending orders are different
              var n = 1
              var price = ticker.Last
              buyOrderId = coverShort(pos[0].Price - targetProfit, pos[0].Amount)
              sellOrderId = openShort(price + targetProfit * n, amount)
          }
    
          if (!sellOrderId || !buyOrderId) {   // If one side of the pending order fails, cancel all pending orders and start over
              cancelAll()
              buyOrderId = null 
              sellOrderId = null
              continue
          } 
    
          while (1) {  // The pending order is completed, start monitoring the order
              var isFindBuyId = false 
              var isFindSellId = false
              var orders = _C(exchange.GetOrders)
              for (var i = 0 ; i < orders.length ; i++) {
                  if (buyOrderId == orders[i].Id) {
                      isFindBuyId = true 
                  }
                  if (sellOrderId == orders[i].Id) {
                      isFindSellId = true 
                  }               
              }
              if (!isFindSellId && !isFindBuyId) {    // Detected that both buy and sell orders have been filled
                  cancelAll()
                  break
              } else if (!isFindBuyId) {   // Detected buy order closing
                  Log("buy order closing")
                  cancelAll()
                  break
              } else if (!isFindSellId) {  // Detected sell order closing
                  Log("sell order closing")
                  cancelAll()
                  break
              }
              LogStatus(_D())
              Sleep(3000)
          }
          Sleep(500)
      }
    

Seluruh logik dan reka bentuk dijelaskan.

Ujian semula

Biarkan strategi melalui pasaran 19 Mei.

img

img

Ia boleh dilihat bahawa strategi Martingale masih mempunyai risiko tertentu.

Bot sebenar boleh dijalankan dengan bot simulasi OKEX V5

Alamat strategi:https://www.fmz.com/strategy/294957

Strategi digunakan terutamanya untuk belajar, dan wang sebenar harus digunakan dengan berhati-hati~!


Berkaitan

Lebih lanjut