avatar of 发明者量化-小小梦 发明者量化-小小梦
konzentrieren Sie sich auf Private Nachricht
4
konzentrieren Sie sich auf
1271
Anhänger

Martingale-Strategie-Design für Kryptowährungs-Futures

Erstellt in: 2021-07-02 14:35:34, aktualisiert am: 2023-09-21 21:09:56
comments   22
hits   6170

Martingale-Strategie-Design für Kryptowährungs-Futures

Martingale-Strategie-Design für Kryptowährungs-Futures

In letzter Zeit gab es in der offiziellen FMZ-Gruppe viele Diskussionen über Martingale-Strategien, aber es gibt nicht viele Martingale-Strategien für digitale Währungsverträge auf der Plattform. Daher habe ich diese Gelegenheit genutzt, um eine einfache Martingale-Strategie für Kryptowährungs-Futures zu entwickeln. Warum wird sie als Martin-ähnliche Strategie bezeichnet? Weil die potenziellen Risiken der Martin-Strategie in der Tat nicht gering sind, sodass sie nicht vollständig nach der Martin-Strategie konzipiert ist. Allerdings birgt diese Art von Strategie immer noch erhebliche Risiken, und die Parametereinstellungen der Martingale-Strategie hängen eng mit den Risiken zusammen und dürfen nicht ignoriert werden.

In diesem Artikel wird hauptsächlich das Design von Strategien vom Typ Martin erläutert und daraus gelernt. Die Strategieidee selbst ist sehr klar. Als Benutzer von FMZ berücksichtigen wir das Strategiedesign mehr.

Gesamtes Eigenkapital erhalten

Bei der Entwicklung von Futures-Strategien für digitale Währungen werden häufig Gesamtkapitaldaten verwendet. Denn eine Renditeberechnung ist notwendig, insbesondere wenn variable Renditen berechnet werden müssen. Da offene Positionen eine Marge beanspruchen, beanspruchen auch ausstehende Aufträge eine Marge. Rufen Sie zu diesem Zeitpunkt die API-Schnittstelle der FMZ-Plattform aufexchange.GetAccount()Ermittelt werden die verfügbaren Vermögenswerte und die durch ausstehende Aufträge eingefrorenen Vermögenswerte. Tatsächlich stellen die meisten Terminbörsen für digitale Währungen Daten zum Gesamtkapital bereit, FMZ erfasst dieses Attribut jedoch nicht einheitlich.

Daher entwickeln wir Funktionen zum Abrufen dieser Daten entsprechend den verschiedenen Austauschmethoden:

// OKEX V5 获取总权益
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("获取账户总权益失败!")
            return null
        }
    }
    return totalEquity
}

// 币安期货
function getTotalEquity_Binance() {
    var totalEquity = null 
    var ret = exchange.GetAccount()
    if (ret) {
        try {
            totalEquity = parseFloat(ret.Info.totalWalletBalance)
        } catch(e) {
            Log("获取账户总权益失败!")
            return null
        }
    }
    return totalEquity
}

Im CodetotalEquityDies ist das gesamte Eigenkapital, das wir benötigen. Anschließend schreiben wir eine Funktion als aufrufenden Eintrag und rufen die entsprechende Funktion entsprechend dem Austauschnamen auf.

function getTotalEquity() {
    var exName = exchange.GetName()
    if (exName == "Futures_OKCoin") {
        return getTotalEquity_OKEX_V5()
    } else if (exName == "Futures_Binance") {
        return getTotalEquity_Binance()
    } else {
        throw "不支持该交易所"
    }
}

Entwerfen Sie einige Hilfsfunktionen

Vor dem Entwerfen der Hauptfunktion und Hauptlogik. Hier müssen wir noch einige Vorbereitungen treffen und einige Zusatzfunktionen konzipieren.

  • Alle aktuell ausstehenden Bestellungen stornieren
  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)
      }
  }

Ich glaube, dass diejenigen, die sich häufig die Beispielcodes für Strategien auf dem FMZ-Strategieplatz ansehen, mit dieser Funktion sehr vertraut sind. Viele Strategien haben ähnliche Designs verwendet. Seine Funktion besteht darin, die aktuelle Liste der ausstehenden Aufträge abzurufen und diese dann einzeln zu stornieren.

  • Futures-Auftragsvorgang
  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)
  }

Beim Futures-Handel gibt es vier Richtungen: Öffnen einer Long-Position (openLong), Öffnen einer Short-Position (openShort), Schließen einer Long-Position (coverLong) und Schließen einer Short-Position (coverShort). Daher haben wir vier Ordnungsfunktionen entworfen, die diesen Operationen entsprechen. Wenn Sie nur eine Bestellung aufgeben möchten, sind mehrere Faktoren erforderlich: Richtung, Bestellpreis und Bestellmenge. Deshalb haben wir auch ein Programm mit dem Namen entwickelt:tradeDie zu handhabende Funktion方向(distance)下单价格(price)下单量(amount)Alle Abläufe sind übersichtlich. Die Funktionsaufrufe zum Öffnen einer Long-Position (openLong), Öffnen einer Short-Position (openShort), Schließen einer Long-Position (coverLong) und Schließen einer Short-Position (coverShort) werden letztendlich ausgeführt vontradeDie Funktion führt die eigentliche Aufgabe aus, nämlich eine Order an der Terminbörse entsprechend der festgelegten Richtung, des festgelegten Preises und der festgelegten Menge zu platzieren.

Hauptfunktion

Die Strategie ist sehr einfach. Verwenden Sie den aktuellen Preis als Basislinie und platzieren Sie Verkaufsaufträge (Short) und Kaufaufträge (Long) in einem bestimmten Abstand über und unter dem aktuellen Preis. Sobald eine Seite ausgeführt ist, werden alle verbleibenden Aufträge storniert, und dann wird ein neuer Schlussauftrag in einem bestimmten Abstand basierend auf dem Positionspreis platziert, und ein Erhöhungsauftrag wird zum aktualisierten aktuellen Preis platziert, aber der Erhöhungsauftrag wird nicht die doppelte Bestellmenge.

  • Erste Arbeiten Da wir Bestellungen aufgeben müssen, benötigen wir zwei globale Variablen zum Aufzeichnen der Bestell-IDs.
  var buyOrderId = null
  var sellOrderId = null

Anschließend wird die Option zur Verwendung der OKEX_V5-Simulationsdiskette in den Schnittstellenparametern der Strategie vorgesehen, sodass im Code einige Verarbeitungsschritte durchgeführt werden müssen:

  var exName = exchange.GetName()    
  // 切换OKEX V5模拟盘
  if (isSimulate && exName == "Futures_OKCoin") {
      exchange.IO("simulate", true)
  }

Da die Schnittstellenparameter auch eine Möglichkeit zum Zurücksetzen aller Informationen beinhalten, sollte der Code auch eine entsprechende Verarbeitung beinhalten:

  if (isReset) {
      _G(null)
      LogReset(1)
      LogProfitReset()
      LogVacuum()
      Log("重置所有数据", "#FF0000")
  }

Wir führen nur unbefristete Verträge aus, daher ist es hier fest codiert und nur auf unbefristete Verträge eingestellt.

  exchange.SetContractType("swap")

Dann müssen wir auch die Genauigkeit der Bestellpreise und Bestellmengen berücksichtigen. Wenn die Genauigkeit nicht richtig eingestellt ist, geht die Genauigkeit während des Strategieberechnungsprozesses verloren. Wenn die Daten viele Dezimalstellen haben, kann die Bestellung leicht von der Vermittlungsstelle abgelehnt.

  exchange.SetPrecision(pricePrecision, amountPrecision)
  Log("设置精度", pricePrecision, amountPrecision)

Einfache Datenwiederherstellungsfunktion

  if (totalEq == -1 && !IsVirtual()) {
      var recoverTotalEq = _G("totalEq")
      if (!recoverTotalEq) {
          var currTotalEq = getTotalEquity()
          if (currTotalEq) {
              totalEq = currTotalEq
              _G("totalEq", currTotalEq)
          } else {
              throw "获取初始权益失败"
          }
      } else {
          totalEq = recoverTotalEq
      }
  }

Wenn Sie das anfängliche Gesamtkapital des Kontos bei Ausführung der Strategie angeben möchten, können Sie den ParametertotalEqWenn dieser Parameter auf -1 gesetzt ist, liest die Strategie die gespeicherten Gesamtkapitaldaten. Wenn keine gespeicherten Gesamtkapitaldaten vorhanden sind, wird das aktuell gelesene Gesamtkapital als anfängliches Gesamtkapital des Strategieverlaufs verwendet. Wenn das Gesamtkapital Wenn Ihr Eigenkapital steigt, bedeutet dies: Wenn Sie Geld verdienen, Ihr gesamtes Eigenkapital jedoch geringer ist, bedeutet dies, dass Sie Geld verloren haben. Wenn Daten zum Gesamteigenkapital gelesen werden, fahren Sie mit dem Betrieb unter Verwendung dieser Daten fort.

  • Hauptlogik Nachdem die anfängliche Arbeit erledigt war, kamen wir endlich zur Hauptlogik der Strategie. Der Einfachheit halber habe ich die Erklärung direkt in die Codekommentare geschrieben.
    while (1) {                                  // 策略主要逻辑设计为一个死循环
        var ticker = _C(exchange.GetTicker)      // 首先读取当前行情信息,主要用到最新成交价
        var pos = _C(exchange.GetPosition)       // 读取当前持仓数据
        if (pos.length > 1) {                    // 判断持仓数据,由于这个策略的逻辑,是不太可能同时出现多空持仓的,所以发现同时出现多空持仓就抛出错误
            Log(pos)
            throw "同时有多空持仓"                  // 抛出错误,让策略停止
        }
        // 根据状态而定
        if (pos.length == 0) {                    // 根据持仓状态做出不同操作,pos.length == 0是当没有持仓时
            // 未持仓了,统计一次收益
            if (!IsVirtual()) {
                var currTotalEq = getTotalEquity()
                if (currTotalEq) {
                    LogProfit(currTotalEq - totalEq, "当前总权益:", currTotalEq)
                }
            }

            buyOrderId = openLong(ticker.Last - targetProfit, amount)       // 挂开多仓的买单
            sellOrderId = openShort(ticker.Last + targetProfit, amount)     // 挂开空仓的卖单
        } else if (pos[0].Type == PD_LONG) {   // 有多头持仓,挂单位置、数量有所不同
            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) {   // 有空头持仓,挂单位置、数量有所不同
            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) {   // 如果有一边挂单失败就取消所有挂单,重来
            cancelAll()
            buyOrderId = null 
            sellOrderId = null
            continue
        } 

        while (1) {  // 挂单完成,开始监控订单
            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) {    // 检测到买卖单都成交了
                cancelAll()
                break
            } else if (!isFindBuyId) {   // 检测到买单成交
                Log("买单成交")
                cancelAll()
                break
            } else if (!isFindSellId) {  // 检测到卖单成交
                Log("卖单成交")
                cancelAll()
                break
            }
            LogStatus(_D())
            Sleep(3000)
        }
        Sleep(500)
    }

Die gesamte Logik und das Design wurden erklärt.

Backtesting

Lassen Sie die Strategie die Marktsituation am 19. Mai erleben.

Martingale-Strategie-Design für Kryptowährungs-Futures

Martingale-Strategie-Design für Kryptowährungs-Futures

Man erkennt, dass die Martingale-Strategie dennoch gewisse Risiken birgt.

Sie können die OKEX V5-Demo für echtes Trading ausprobieren.

Martingale-Strategie-Design für Kryptowährungs-Futures

Strategieadresse: https://www.fmz.com/strategy/294957

Strategien dienen hauptsächlich zum Lernen. Gehen Sie beim Umgang mit echtem Geld also mit Vorsicht vor ~!