Cryptocurrency spot hedging strategy design (1-2)

in #fmzlast year

Reset all data

28d9a96d308eecb849730.png

Sometimes it is necessary to delete all logs and clear the recorded data when the strategy starts. The you can design a strategy interface parameter isReset, and design the reset code in the initialization part of the strategy, for example:

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

Restore initial account data, update current account data
In order to judge the balance, the strategy needs to continuously record the initial account assets for comparison with the current one. The variable nowAccs is used to record the current account data, using the function we just designed updateAccs to get the account data of the current exchange. initAccs is used to record the initial account status (the number of coins, the number of denominated coins, etc. on exchanges A and B). For initAccs, use the _G() function to restore first (the _G function will record data persistently, and can return the recorded data again, see the API documentation for details: [link](https:// www.fmz.com/api#_gk-v)), if the query does not work, use the current account information to assign value and use the _G function to record.

Such as the following code:

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

Trading logic, main loop in main function
The code in the main loop is the process of each round of execution of the strategy logic, which is executed over and over again to form the main loop of the strategy. Let's take a look at the process of each execution of the program in the main loop.

Obtain market data and judge the validity of market data

      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 
      }

Here we can see that the concurrent function exchange.Go of the FMZ platform is used to create concurrent objects depthARoutine, depthBRoutine that call the GetDepth() interface. When these two concurrent objects are created, the GetDepth() interface is called immediately, and both requests for depth data are sent to the exchange.
Then call the wait() method of the depthARoutine, depthBRoutine objects to obtain the depth data.
After obtaining the depth data, it is necessary to check the depth data to determine its validity. In the case of abnormal data, the execution of the continue statement is triggered to re-execute the main loop.

Use the spread value parameter or the spread ratio 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
      }

In terms of parameters, we have made such a design: the parameters of FMZ can be show or hide based on a parameter, so we can make a parameter to decide whether to use price spread, or spread ratio.

5.png

A parameter diffAsPercentage has been added to the parameters of the strategy interface. The other two parameter settings to show or hide based on this parameter are:
hedgeDiffPrice@!diffAsPercentage, which is displayed when diffAsPercentage is false.
hedgeDiffPercentage@diffAsPercentage, which is displayed when diffAsPercentage is true.
After this design, we checked the diffAsPercentage parameter, which is the hedge trigger condition based on the price difference ratio. Without the diffAsPercentage parameter checked, the hedge is triggered by the price difference.

Determine the hedging trigger conditions

      if (depthA.Bids[0].Price - depthB.Asks[0].Price > targetDiffPrice && Math.min(depthA.Bids[0].Amount, depthB.Asks[0].Amount) >= minHedgeAmount) {          // A -> B market conditions are met            
          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("trigger A->B:", depthA.Bids[0].Price - depthB.Asks[0].Price, price, amount, nowAccs[1].Balance / price, nowAccs[0].Stocks)  // Tips
              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 market conditions are met
          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("trigger B->A:", depthB.Bids[0].Price - depthA.Asks[0].Price, price, amount, nowAccs[0].Balance / price, nowAccs[1].Stocks)  // Tips
              hedge(exA, exB, price, amount)
              cancelAll()
              lastKeepBalanceTS = 0
              isTrade = true 
          }            
      }

To be continued...

Coin Marketplace

STEEM 0.17
TRX 0.24
JST 0.034
BTC 96239.49
ETH 2782.12
SBD 0.67