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

Neulinge im quantitativen Handel in Kryptowährungskreisen, schauen Sie sich bitte dies an - So kommen Sie dem quantitativen Handel in Kryptowährungskreisen näher (V)

Erstellt in: 2021-05-28 09:50:12, aktualisiert am: 2023-09-21 21:06:08
comments   14
hits   2533

Neulinge im quantitativen Handel in Kryptowährungskreisen, schauen Sie sich bitte dies an - So kommen Sie dem quantitativen Handel in Kryptowährungskreisen näher (V)

Neulinge im quantitativen Handel in Kryptowährungskreisen, schauen Sie sich bitte dies an - So kommen Sie dem quantitativen Handel in Kryptowährungskreisen näher (V)

Im vorherigen Artikel haben wir die Handelslogikanalyse einer einfachen Rasterstrategie erläutert. In diesem Artikel werden wir den Entwurf dieser Lehrstrategie weiter vervollständigen.

  • Analyse der Transaktionslogik Im vorherigen Artikel haben wir erwähnt, dass die Transaktionsaktion ausgelöst werden kann, solange wir jede Gitterlinie des Rasters durchlaufen und feststellen, ob der aktuelle Preis über oder unter der Gitterlinie liegt. Aber in Wirklichkeit gibt es noch viele logische Details. Neulinge, die das Schreiben von Strategien nicht verstehen, haben oft die falsche Vorstellung, dass „die Logik sehr einfach ist und der Code nur wenige Zeilen umfassen sollte, aber beim tatsächlichen Schreiben gibt es immer noch viele Details.”

Das erste Detail, das wir berücksichtigen müssen, ist das Design des unendlichen Gitters. Denken Sie daran, dass wir im letzten Artikel eine Funktion zum Generieren der anfänglichen Rasterdatenstruktur entworfen habencreateNetWas? Diese Funktion erzeugt eine Gitterdatenstruktur mit einer endlichen Anzahl von Gitterlinien. Was passiert nun, wenn der Preis während der Ausführung der Strategie die Grenzen dieser Rasterdatenstruktur überschreitet (über die obere Rasterlinie mit dem höchsten Preis und die untere Rasterlinie mit dem niedrigsten Preis hinaus)? Daher müssen wir zunächst der Rasterdatenstruktur einen Erweiterungsmechanismus hinzufügen.

Beginnen Sie mit dem Schreiben der Hauptfunktion der Strategie. Dabei handelt es sich um den Code, der die Ausführung der Strategie startet.

  var diff = 50                                 // 全局变量,网格间距,可以设计成参数,方便讲解,我们把这个参数写死在代码里。
  function main() {
      // 实盘开始运行后,从这里开始执行策略代码
      var ticker = _C(exchange.GetTicker)       // 获取市场最新的行情数据ticker,ticker这个数据的结构参看FMZ API文档:https://www.fmz.com/api#ticker
      var net = createNet(ticker.Last, diff)    // 我们上篇设计的初始构造网格数据结构的函数,这里构造一个网格数据结构net

      while (true) {                            // 然后程序逻辑就进入了这个while死循环,策略执行到此将不停的循环执行这里{}符号之内的代码
          ticker = _C(exchange.GetTicker)       // 死循环代码部分的第一行,获取最新的行情数据,更新给ticker变量
          // 检查网格范围
          while (ticker.Last >= net[net.length - 1].price) {
              net.push({
                  buy : false,
                  sell : false,
                  price : net[net.length - 1].price + diff,
              })
          }
          while (ticker.Last <= net[0].price) {
              var price = net[0].price - diff
              if (price <= 0) {
                  break
              }
              net.unshift({
                  buy : false,
                  sell : false,
                  price : price,
              })
          }

          // 还有其它代码...
      }
  }

Der Code, der die Rasterdatenstruktur erweiterbar macht, ist dieser (Auszug aus dem obigen Code):

        // 检查网格范围
        while (ticker.Last >= net[net.length - 1].price) {   // 如果价格超过网格最高价格的网格线
            net.push({                                       // 就在网格最高价格的网格线之后加入一个新的网格线
                buy : false,                                 // 初始化卖出标记
                sell : false,                                // 初始化买入标记
                price : net[net.length - 1].price + diff,    // 在之前最高价格的基础上再加一个网格间距
            })
        }
        while (ticker.Last <= net[0].price) {                // 如果价格低于网格最低价格的网格线
            var price = net[0].price - diff                  // 区别于向上添加,要注意向下添加新网格线的价格不能小于等于0,所以这里要判断
            if (price <= 0) {                                // 小于等于0就不添加了,跳出这层循环
                break
            }
            net.unshift({                                    // 就在网格最低价格的网格线之前添加一个新的网格线
                buy : false,
                sell : false,
                price : price,
            })
        }

Im nächsten Schritt muss überlegt werden, wie die Transaktionsauslösung im Detail umgesetzt werden kann.

  var diff = 50
  var amount = 0.002       // 增加一个全局变量,也可以设计成参数,当然为了简便讲解,我们也写死在策略代码,
                           // 这个参数控制每次网格线上触发交易时的交易量
  function main() {
      var ticker = _C(exchange.GetTicker)
      var net = createNet(ticker.Last, diff)
      var preTicker = ticker       // 在主循环(死循环)开始前,设置一个变量,记录上一次的行情数据
      while (true) {
          ticker = _C(exchange.GetTicker)
          // 检查网格范围
          while (ticker.Last >= net[net.length - 1].price) {
              net.push({
                  buy : false,
                  sell : false,
                  price : net[net.length - 1].price + diff,
              })
          }
          while (ticker.Last <= net[0].price) {
              var price = net[0].price - diff
              if (price <= 0) {
                  break
              }
              net.unshift({
                  buy : false,
                  sell : false,
                  price : price,
              })
          }  

          // 检索网格
          for (var i = 0 ; i < net.length ; i++) {     // 遍历网格数据结构中的所有网格线
              var p = net[i]
              if (preTicker.Last < p.price && ticker.Last > p.price) {         // 上穿,卖出,当前节点已经交易过不论SELL BUY ,都不再交易
                  if (i != 0) {
                      var downP = net[i - 1]
                      if (downP.buy) {
                          exchange.Sell(-1, amount, ticker)
                          downP.buy = false 
                          p.sell = false 
                          continue
                      }
                  }
                  if (!p.sell && !p.buy) {
                      exchange.Sell(-1, amount, ticker)
                      p.sell = true
                  }
              } else if (preTicker.Last > p.price && ticker.Last < p.price) {  // 下穿,买入
                  if (i != net.length - 1) {
                      var upP = net[i + 1]
                      if (upP.sell) {
                          exchange.Buy(-1, amount * ticker.Last, ticker)
                          upP.sell = false 
                          p.buy = false 
                          continue
                      }
                  }
                  if (!p.buy && !p.sell) {
                      exchange.Buy(-1, amount * ticker.Last, ticker)
                      p.buy = true 
                  } 
              }
          }
          preTicker = ticker    // 把当前的行情数据记录在preTicker中,在下一次循环中,作为“上一次”行情数据和最新的对比,判断上穿下穿
          Sleep(500)
      }
  }  

Sie können sehen:

  • Bedingung für das Überschreiten der Gitterlinie:preTicker.Last < p.price && ticker.Last > p.price
  • Bedingung für das Überschreiten der Gitterlinie:preTicker.Last > p.price && ticker.Last < p.price

Darüber haben wir im vorherigen Artikel gesprochen:

Neulinge im quantitativen Handel in Kryptowährungskreisen, schauen Sie sich bitte dies an - So kommen Sie dem quantitativen Handel in Kryptowährungskreisen näher (V)

Das Überkreuzen nach oben oder unten ist nur der erste Schritt bei der Ermittlung, ob ein Handel platziert werden kann. Dazu ist auch die Ermittlung der Markierungen in den Gitternetzliniendaten erforderlich.

Wenn es sich um eine Aufwärtskreuzung handelt, wird der Preis als niedriger als die aktuelle Gitterlinie und die Kaufmarke auf der nächsten Gitterlinie beurteilt. Wenn der Wert der Kaufmarke wahr ist, bedeutet dies, dass die vorherige Gitterlinie gekauft wurde, und die vorherige Gitterlinie wird zurückgesetzt. Die Kaufmarke der Wurzel ist falsch und die Verkaufsmarke der aktuellen Gitterlinie wird auf falsch zurückgesetzt.

Nach der Beurteilung der vorherigen Bedingung, wenn sie nicht ausgelöst wird, fahren Sie mit der Beurteilung fort. Wenn die Kauf-/Verkaufsmarkierungen auf der aktuellen Gitterlinie beide falsch sind, bedeutet dies, dass die aktuelle Gitterlinie gehandelt werden kann. Da es sich um eine Aufwärtskreuzung handelt, Führen Sie hier den Verkaufsvorgang aus. Markieren Sie nach der Ausführung das aktuelle Verkaufsflag der Gitterlinie als wahr.

Die Logik für den Umgang mit Unterführungen ist dieselbe (das müssen Neulinge selbst überlegen).

Umfassendes Strategie-Backtesting

Um einige Backtesting-Daten anzuzeigen, wird eine Funktion geschriebenshowTblZeigen Sie die Daten an.

function showTbl(arr) {
    var tbl = {
        type : "table", 
        title : "网格",
        cols : ["网格信息"],
        rows : []
    }
    var arrReverse = arr.slice(0).reverse()
    _.each(arrReverse, function(ele) {
        var color = ""
        if (ele.buy) {
            color = "#FF0000"
        } else if (ele.sell) {
            color = "#00FF00"
        }
        tbl.rows.push([JSON.stringify(ele) + color])
    })
    LogStatus(_D(), "\n`" + JSON.stringify(tbl) + "`", "\n 账户信息:", exchange.GetAccount())
}

Vollständiger Strategiecode:

/*backtest
start: 2021-04-01 22:00:00
end: 2021-05-22 00:00:00
period: 1d
basePeriod: 1m
exchanges: [{"eid":"OKEX","currency":"ETH_USDT","balance":100000}]
*/

var diff = 50
var amount = 0.002
function createNet(begin, diff) {
    var oneSideNums = 10
    var up = []
    var down = []
    for (var i = 0 ; i < oneSideNums ; i++) {
        var upObj = {
            buy : false,
            sell : false, 
            price : begin + diff / 2 + i * diff,
        }
        up.push(upObj)

        var j = (oneSideNums - 1) - i
        var downObj = {
            buy : false,
            sell : false,
            price : begin - diff / 2 - j * diff,
        }
        if (downObj.price <= 0) {  // 价格不能小于等于0 
            continue
        }
        down.push(downObj)
    }

    return down.concat(up)
}

function showTbl(arr) {
    var tbl = {
        type : "table", 
        title : "网格",
        cols : ["网格信息"],
        rows : []
    }
    var arrReverse = arr.slice(0).reverse()
    _.each(arrReverse, function(ele) {
        var color = ""
        if (ele.buy) {
            color = "#FF0000"
        } else if (ele.sell) {
            color = "#00FF00"
        }
        tbl.rows.push([JSON.stringify(ele) + color])
    })
    LogStatus(_D(), "\n`" + JSON.stringify(tbl) + "`", "\n 账户信息:", exchange.GetAccount())
}

function main() {
    var ticker = _C(exchange.GetTicker)
    var net = createNet(ticker.Last, diff)
    var preTicker = ticker 
    while (true) {
        ticker = _C(exchange.GetTicker)
        // 检查网格范围
        while (ticker.Last >= net[net.length - 1].price) {
            net.push({
                buy : false,
                sell : false,
                price : net[net.length - 1].price + diff,
            })
        }
        while (ticker.Last <= net[0].price) {
            var price = net[0].price - diff
            if (price <= 0) {
                break
            }
            net.unshift({
                buy : false,
                sell : false,
                price : price,
            })
        }

        // 检索网格
        for (var i = 0 ; i < net.length ; i++) {
            var p = net[i]
            if (preTicker.Last < p.price && ticker.Last > p.price) {         // 上穿,卖出,当前节点已经交易过不论SELL BUY ,都不再交易
                if (i != 0) {
                    var downP = net[i - 1]
                    if (downP.buy) {
                        exchange.Sell(-1, amount, ticker)
                        downP.buy = false 
                        p.sell = false 
                        continue
                    }
                }
                if (!p.sell && !p.buy) {
                    exchange.Sell(-1, amount, ticker)
                    p.sell = true
                }
            } else if (preTicker.Last > p.price && ticker.Last < p.price) {  // 下穿,买入
                if (i != net.length - 1) {
                    var upP = net[i + 1]
                    if (upP.sell) {
                        exchange.Buy(-1, amount * ticker.Last, ticker)
                        upP.sell = false 
                        p.buy = false 
                        continue
                    }
                }
                if (!p.buy && !p.sell) {
                    exchange.Buy(-1, amount * ticker.Last, ticker)
                    p.buy = true 
                } 
            }
        }

        showTbl(net)
        preTicker = ticker 
        Sleep(500)
    }
}

Strategie-Backtesting:

Neulinge im quantitativen Handel in Kryptowährungskreisen, schauen Sie sich bitte dies an - So kommen Sie dem quantitativen Handel in Kryptowährungskreisen näher (V)

Neulinge im quantitativen Handel in Kryptowährungskreisen, schauen Sie sich bitte dies an - So kommen Sie dem quantitativen Handel in Kryptowährungskreisen näher (V)

Neulinge im quantitativen Handel in Kryptowährungskreisen, schauen Sie sich bitte dies an - So kommen Sie dem quantitativen Handel in Kryptowährungskreisen näher (V)

Es ist ersichtlich, dass die Merkmale der Netzstrategie darin bestehen, dass es in einem Trendmarkt zu großen schwebenden Verlusten kommt und die Renditen nur in einem volatilen Markt wieder ansteigen. Daher ist die Netzstrategie nicht risikofrei. Die Spotstrategie kann immer noch aufrechterhalten werden, aber die Netzstrategie mit Terminkontrakten ist riskanter und erfordert konservative Einstellungen der Netzparameter.