Martingale strategy design for cryptocurrency futures (2)

in fmz •  last year 

There is also an option to reset all information in the interface parameters, so there should be corresponding processing in the code:

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

We only run perpetual contracts, so the writing is fixed here and set to perpetual only.

exchange.SetContractType("swap")

Then we also need to consider the accuracy of the order price and the order amount. If the accuracy is not set properly, the accuracy will be lost during the strategy calculation process. If the data has a large number of decimal places, it is easy to cause the order to be rejected by the exchange interface.

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

Simple data recovery by design

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

If you want to specify the initial total equity of the account when the strategy is running, you can set the parameter totalEq. If this parameter is set to -1, the strategy will read the stored total equity data. If there is no stored total equity data, the current read total equity is used as the initial total equity of the strategy running progress. After that, an increase in total equity indicates a profit, and a decrease in total equity indicates a loss. If the total equity data is read, the strategy will continue to run with this data.

main logic
After the initial work is done, finally we came to the main logic part of the strategy. For the convenience of explanation, I wrote the instructions directly on the code comments.

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

The whole logic and design are explained.

Backtesting
Let the strategy go through a May 19 market.

28e76ca5f23fd8d30bbd8.png

2.png

It can be seen that the Martingale strategy still has certain risks.

The real bot can be run with the OKEX V5 simulation bot

Strategy address: https://www.fmz.com/strategy/294957

Strategies are mainly used for learning, and real money should be used with caution~!

From: https://blog.mathquant.com/2022/08/05/martingale-strategy-design-for-cryptocurrency-futures.html

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!