In diesem Artikel haben wir diese Strategie aufgestockt und in eine vielfältige, realisierte Netzstrategie ausgeweitet. Wir wollten nicht einen Heiligen Becher finden, sondern aus der Strategieentwicklung die verschiedenen Probleme und Lösungsansätze des Entwurfs zu erörtern. In diesem Artikel werde ich einige meiner Erfahrungen mit der Entwicklung dieser Strategie erklären.
Wie der vorherige Artikel, basiert dieses auch auf der Quantifizierung der Erfinder.FMZ.COMIch bin ein großer Liebhaber des Designs.
Vielfalt
Ich möchte Ihnen sagen, dass diese Netz-Strategie nicht nurBTC_USDT
Ich kann es auch.LTC_USDT
/EOS_USDT
/DOGE_USDT
/ETC_USDT
/ETH_USDT
In der Tat handelt es sich um ein Bargeldpaar, bei dem die Rassen, die laufen wollen, gleichzeitig Netshandel betreiben.
Ich habe mich in meinem Leben mit der Art und Weise beschäftigt, wie ich mich mit der Art und Weise, wie ich mich fühle, beschäftige. Die Anforderung klingt einfach, aber es ist Zeit, das Problem zu lösen.
1. Zuerst die Beschaffung von mehreren Arten von Märkten. Das ist das erste Problem, das ich lösen muss. Nach einem Blick in die API-Dokumentation der Börse habe ich festgestellt, dass die allgemeinen Börsen eine aggregierte Markt-Interface anbieten. OK, dann nutze die Aggregator-Markt-Interface, um Daten zu erhalten.
2. Das zweite Problem, das auftaucht, ist das Kontovermögen. Da es sich um eine vielfältige Strategie handelt, müssen alle Transaktionen separat verwaltet werden. Wenn Sie eine Anfrage stellen, müssen Sie die verfügbaren Vermögenswerte beurteilen, oder müssen Sie sie erst einmal einholen? Oder müssen Sie die Gewinne berechnen, oder müssen Sie zunächst eine ursprüngliche Kontovermögensdaten aufzeichnen und dann die aktuellen Kontovermögensdaten erhalten und den Gewinn und Verlust mit dem ursprünglichen Vergleich berechnen? Die Anlagekonto-Schnittstelle der Börse liefert normalerweise auch Anlagedaten in allen Währungen, die wir nur einmal abrufen und dann verarbeiten können.
3. Strategieparameter-Design. Die Parameter-Design von mehreren Sorten und die Parameter-Design von einer einzigen Sorte unterscheiden sich stark, da die Handelslogik der verschiedenen Sorten zwar identisch ist, aber die Parameter beim Handel möglicherweise unterschiedlich sind. Zum Beispiel die Gitterstrategie, bei der BTC_USDT-Trade kann man 0,01 BTC pro Handel erwarten, aber wenn man DOGE_USDT macht, ist es offensichtlich nicht geeignet, wenn man diesen Parameter ((Transaktionen von 0,01 Münzen) verwendet. Vielleicht werden auch andere Schüler darüber nachdenken und dann sagen: Ich kann mehrere Parametergruppen einstellen, um die verschiedenen Transaktionspaare getrennt zu steuern. Wenn ich die drei Parameter setzen würde, was wäre, wenn ich vier verschiedene Sorten machen würde? Die Notwendigkeit dieser Differentiationsparameter sollte daher bei der Gestaltung von Parametern für die Multivariate-Politik berücksichtigt werden. Eine Lösung ist die Gestaltung von Parametern in normalen Strings oder JSON-Strings. Zum Beispiel:
ETHUSDT:100:0.002|LTCUSDT:20:0.1
Das ist die Daten für jede Sorte, was bedeutet:ETHUSDT:100:0.002
Die Bank ist die einzige, die das ETH-USDT-Paar kontrolliert.LTCUSDT:20:0.1
Die "LTC_USDT"-Traditionspaare werden von den "LTC_USDT"-Traditionspaaren gesteuert.ETHUSDT:100:0.002
Die ETHUSDT gibt an, welche Paare du tätigen wirst, 100 ist die Gitterintervalle, 0.002 ist die Anzahl der ETH-Münzen, die pro Gittertransaktion getätigt wurden, und die Spitznamen sind die Splitter dieser Daten. (Natürlich werden diese Parameterregeln von den Strategie-Designern festgelegt, und Sie können alles entwerfen, was Sie möchten.)
Diese Strings enthalten die Parameterinformationen für die verschiedenen Varianten, die Sie tun müssen, und werden in der Strategie analysiert, um die Variablen der Strategie anzugeben, die zur Steuerung der Transaktionslogik der verschiedenen Varianten verwendet werden. Wie wird das analysiert? Oder verwenden Sie das Beispiel oben.
function main() {
var net = [] // 记录的网格参数,具体运行到网格交易逻辑时,使用这里面的数据
var params = "ETHUSDT:100:0.002|LTCUSDT:20:0.1"
var arrPair = params.split("|")
_.each(arrPair, function(pair) {
var arr = pair.split(":")
var symbol = arr[0] // 交易对名称
var diff = parseFloat(arr[1]) // 网格间距
var amount = parseFloat(arr[2]) // 网格下单量
net.push({symbol : symbol, diff : diff, amount : amount})
})
Log("网格参数数据:", net)
}
Das ist eine einfache Methode, um die Parameter zu analysieren, aber natürlich können Sie auch direkt mit einer JSON-String arbeiten.
function main() {
var params = '[{"symbol":"ETHUSDT","diff":100,"amount":0.002},{"symbol":"LTCUSDT","diff":20,"amount":0.1}]'
var net = JSON.parse(params) // 记录的网格参数,具体运行到网格交易逻辑时,使用这里面的数据
_.each(net, function(pair) {
Log("交易对:", pair.symbol, pair)
})
}
4. Datenverstärkung
Es gibt einen großen Unterschied zwischen der Praxis und der Lehrstrategie. Die vorhergehende Lehrstrategie ist lediglich ein Ersttest der Logik und des Designs der Strategie.
Dabei müssen die kritischen Daten beim Betrieb der Festplatte dauerhaft gespeichert werden, um diese Daten beim Neustart lesen und weiterlaufen zu können.
Es gibt eine Reihe von Möglichkeiten, wie Sie diese Methode nutzen können, wenn Sie sich für eine Quantitative Handelsplattform entscheiden._G()
Funktionen, oder mit Datenbank-OperationsfunktionenDBExec()
Die Funktionsweise der FMZ-API ist in der Dokumentation aufgeführt.
Zum Beispiel haben wir eine Schleudern-Funktion entwickelt._G()
Funktionen, die Daten des Gitterplatzes speichern.
var net = null
function main() { // 策略主函数
// 首先读取储存的net
net = _G("net")
// ...
}
function onExit() {
_G("net", net)
Log("执行扫尾处理,保存数据", "#FF0000")
}
function onexit() { // 平台系统定义的退出扫尾函数,在点击实盘停止时触发执行
onExit()
}
function onerror() { // 平台系统定义的异常退出函数,在程序发生异常时触发执行
onExit()
}
5. Einschränkungen in Bezug auf die Präzision der Bestellmenge, die Präzision der Bestellpreise, die Mindestbestellmenge und den Mindestbestellbetrag
Das Retest-System hat keine so strengen Einschränkungen für die Anzahl der Einheiten, die Präzision der Einheiten usw., aber in Echtzeit können die verschiedenen Börsen strenge Standards für den Preis und die Anzahl der Einheiten haben, und diese Einschränkungen sind für verschiedene Transaktionspaare nicht gleich. Daher gibt es oft neue Tests im Retest-System.
Bei einer mehrsprachigen Strategie kann man einen Parameter entwerfen, um Informationen wie Präzision anzugeben, aber wenn man eine mehrsprachige Strategie entwirft, erscheint diese Information offensichtlich sehr parametrisch.
In diesem Fall ist es notwendig, die API-Dokumentation der Börse zu überprüfen, um zu sehen, ob es in der Börsendokumentation eine Schnittstelle für die entsprechenden Informationen gibt. Wenn diese Schnittstellen vorhanden sind, können Sie in der Strategie Informationen wie die Präzision des automatischen Zugriffs auf die Schnittstelle entwerfen, die auf die Informationen der an der Transaktion beteiligten Schnittstellen konfiguriert werden ("einfach gesagt, was genau ist, wird automatisch an die Börse angefordert, und dann an die Variablen angepasst, die für die Strategieparameter relevant sind").
6. Anpassung an verschiedene Börsen Warum sollte man diese Frage zuletzt stellen? Da die oben beschriebenen Lösungsansätze dieses letzte Problem verursachen, weil unsere Strategie die Verwendung von Aggregatmarkt-Interfaces, die Datenausstattung, die Präzision der Transaktionen auf den Börsen, die individuelle Abwicklung der einzelnen Transaktionen auf den Kontoinformationen, usw. anbietet, kann es von Börse zu Börse sehr unterschiedlich sein. Es gibt Unterschiede in den Anrufen der Schnittstellen, Unterschiede in den Mechanismen. Für die Börse sind die Unterschiede noch kleiner, wenn diese Netzstrategie auf eine Version der Futures erweitert wird. Die Unterschiede in den verschiedenen Börsenmechanismen sind größer. Eine Lösung ist die Entwicklung einer FMZ-Template-Klassebücherei. Der Nachteil dabei ist, dass man eine Template-Klasse-Datei schreiben muss, die für jede einzelne Börse unterschiedlich realisiert wird.
Auf der Grundlage der oben genannten Analyse wurde eine Template-Library entworfen, um die Konvergenz zwischen Strategien und Börsenmechanismen und -interfaces zu reduzieren.
Wir können die Template-Klasse so gestalten (Teilcode ausgelassen):
function createBaseEx(e, funcConfigure) {
var self = {}
self.e = e
self.funcConfigure = funcConfigure
self.name = e.GetName()
self.type = self.name.includes("Futures_") ? "Futures" : "Spot"
self.label = e.GetLabel()
// 需要实现的接口
self.interfaceGetTickers = null // 创建异步获取聚合行情数据线程的函数
self.interfaceGetAcc = null // 创建异步获取账户数据线程的函数
self.interfaceGetPos = null // 获取持仓
self.interfaceTrade = null // 创建并发下单
self.waitTickers = null // 等待并发行情数据
self.waitAcc = null // 等待账户并发数据
self.waitTrade = null // 等待下单并发数据
self.calcAmount = null // 根据交易对精度等数据计算下单量
self.init = null // 初始化工作,获取精度等数据
// 执行配置函数,给对象配置
funcConfigure(self)
// 检测configList约定的接口是否都实现
_.each(configList, function(funcName) {
if (!self[funcName]) {
throw "接口" + funcName + "未实现"
}
})
return self
}
$.createBaseEx = createBaseEx
$.getConfigureFunc = function(exName) {
dicRegister = {
"Futures_OKCoin" : funcConfigure_Futures_OKCoin, // OK期货的实现
"Huobi" : funcConfigure_Huobi,
"Futures_Binance" : funcConfigure_Futures_Binance,
"Binance" : funcConfigure_Binance,
"WexApp" : funcConfigure_WexApp, // wexApp的实现
}
return dicRegister
}
In der Vorlage werden spezifische Börsen geschrieben, z. B. mit der FMZ-Analogplattform WexApp:
function funcConfigure_WexApp(self) {
var formatSymbol = function(originalSymbol) {
// BTC_USDT
var arr = originalSymbol.split("_")
var baseCurrency = arr[0]
var quoteCurrency = arr[1]
return [originalSymbol, baseCurrency, quoteCurrency]
}
self.interfaceGetTickers = function interfaceGetTickers() {
self.routineGetTicker = HttpQuery_Go("https://api.wex.app/api/v1/public/tickers")
}
self.waitTickers = function waitTickers() {
var ret = []
var arr = JSON.parse(self.routineGetTicker.wait()).data
_.each(arr, function(ele) {
ret.push({
bid1: parseFloat(ele.buy),
bid1Vol: parseFloat(-1),
ask1: parseFloat(ele.sell),
ask1Vol: parseFloat(-1),
symbol: formatSymbol(ele.market)[0],
type: "Spot",
originalSymbol: ele.market
})
})
return ret
}
self.interfaceGetAcc = function interfaceGetAcc(symbol, updateTS) {
if (self.updateAccsTS != updateTS) {
self.routineGetAcc = self.e.Go("GetAccount")
}
}
self.waitAcc = function waitAcc(symbol, updateTS) {
var arr = formatSymbol(symbol)
var ret = null
if (self.updateAccsTS != updateTS) {
ret = self.routineGetAcc.wait().Info
self.bufferGetAccRet = ret
} else {
ret = self.bufferGetAccRet
}
if (!ret) {
return null
}
var acc = {symbol: symbol, Stocks: 0, FrozenStocks: 0, Balance: 0, FrozenBalance: 0, originalInfo: ret}
_.each(ret.exchange, function(ele) {
if (ele.currency == arr[1]) {
// baseCurrency
acc.Stocks = parseFloat(ele.free)
acc.FrozenStocks = parseFloat(ele.frozen)
} else if (ele.currency == arr[2]) {
// quoteCurrency
acc.Balance = parseFloat(ele.free)
acc.FrozenBalance = parseFloat(ele.frozen)
}
})
return acc
}
self.interfaceGetPos = function interfaceGetPos(symbol, price, initSpAcc, nowSpAcc) {
var symbolInfo = self.getSymbolInfo(symbol)
var sumInitStocks = initSpAcc.Stocks + initSpAcc.FrozenStocks
var sumNowStocks = nowSpAcc.Stocks + nowSpAcc.FrozenStocks
var diffStocks = _N(sumNowStocks - sumInitStocks, symbolInfo.amountPrecision)
if (Math.abs(diffStocks) < symbolInfo.min / price) {
return []
}
return [{symbol: symbol, amount: diffStocks, price: null, originalInfo: {}}]
}
self.interfaceTrade = function interfaceTrade(symbol, type, price, amount) {
var tradeType = ""
if (type == self.OPEN_LONG || type == self.COVER_SHORT) {
tradeType = "bid"
} else {
tradeType = "ask"
}
var params = {
"market": symbol,
"side": tradeType,
"amount": String(amount),
"price" : String(-1),
"type" : "market"
}
self.routineTrade = self.e.Go("IO", "api", "POST", "/api/v1/private/order", self.encodeParams(params))
}
self.waitTrade = function waitTrade() {
return self.routineTrade.wait()
}
self.calcAmount = function calcAmount(symbol, type, price, amount) {
// 获取交易对信息
var symbolInfo = self.getSymbolInfo(symbol)
if (!symbol) {
throw symbol + ",交易对信息查询不到"
}
var tradeAmount = null
var equalAmount = null // 记录币数
if (type == self.OPEN_LONG || type == self.COVER_SHORT) {
tradeAmount = _N(amount * price, parseFloat(symbolInfo.pricePrecision))
// 检查最小交易量
if (tradeAmount < symbolInfo.min) {
Log(self.name, " tradeAmount:", tradeAmount, "小于", symbolInfo.min)
return false
}
equalAmount = tradeAmount / price
} else {
tradeAmount = _N(amount, parseFloat(symbolInfo.amountPrecision))
// 检查最小交易量
if (tradeAmount < symbolInfo.min / price) {
Log(self.name, " tradeAmount:", tradeAmount, "小于", symbolInfo.min / price)
return false
}
equalAmount = tradeAmount
}
return [tradeAmount, equalAmount]
}
self.init = function init() { // 自动处理精度等条件的函数
var ret = JSON.parse(HttpQuery("https://api.wex.app/api/v1/public/markets"))
_.each(ret.data, function(symbolInfo) {
self.symbolsInfo.push({
symbol: symbolInfo.pair,
amountPrecision: parseFloat(symbolInfo.basePrecision),
pricePrecision: parseFloat(symbolInfo.quotePrecision),
multiplier: 1,
min: parseFloat(symbolInfo.minQty),
originalInfo: symbolInfo
})
})
}
}
Die Strategie ist dann einfach, diese Vorlage zu verwenden:
function main() {
var fuExName = exchange.GetName()
var fuConfigureFunc = $.getConfigureFunc()[fuExName]
var ex = $.createBaseEx(exchange, fuConfigureFunc)
var arrTestSymbol = ["LTC_USDT", "ETH_USDT", "EOS_USDT"]
var ts = new Date().getTime()
// 测试获取行情
ex.goGetTickers()
var tickers = ex.getTickers()
Log("tickers:", tickers)
// 测试获取账户信息
ex.goGetAcc(symbol, ts)
_.each(arrTestSymbol, function(symbol) {
_.each(tickers, function(ticker) {
if (symbol == ticker.originalSymbol) {
// 打印行情数据
Log(symbol, ticker)
}
})
// 打印资产数据
var acc = ex.getAcc(symbol, ts)
Log("acc:", acc.symbol, acc)
})
}
Die Strategie basierend auf den oben genannten Vorlagen ist sehr einfach zu schreiben, die ganze Strategie umfasst etwa 300+ Zeilen und realisiert eine vielfältige Gitterstrategie für digitale Währungen.
Das ist ein Verlust.T_T
Der Quellcode ist vorübergehend nicht verfügbar.
Wenn Sie ein paar Registrierungscodes senden möchten, können Sie die WexApp anschließen und spielen:
购买地址: https://www.fmz.com/m/s/284507
注册码:
adc7a2e0a2cfde542e3ace405d216731
f5db29d05f57266165ce92dc18fd0a30
1735dca92794943ddaf277828ee04c27
0281ea107935015491cda2b372a0997d
1d0d8ef1ea0ea1415eeee40404ed09cc
Wenn man über 200 U läuft, trifft man auf eine große einseitige Bewegung, die langsam blutet. Die Stabilität hat sich wieder zusammengeschlossen, sie ist seit dem 27. Mai nicht mehr bewegt worden, und das Futures-Gitter hat sich vorerst nicht getraut, es zu versuchen.
Kleine Kürbische QuantisierungDank der Dammen, die Quantifizierung.
Neun SonnenIch bin nicht derjenige, der das sagt.
Orbitale TiereDanke.
Die Erfinder quantifizieren - Kleine TräumeDanke für die Unterstützung!
Die Erfinder quantifizieren - Kleine TräumeDanke für die Unterstützung!