Die dauerhafte Gitterstrategie ist eine sehr beliebte klassische Strategie der Plattform. Im Vergleich zu den Inhaltsnetzen kann man nicht mit Münzen arbeiten, sondern mit einem höheren Hebel. Da die Quantifizierung der Inhalte nicht direkt auf der Plattform des Erfinders durchgeführt werden kann, was die Auswahl der Währungen und die Optimierung der Parameter beeinträchtigt, wird in diesem Artikel der vollständige Python-Rückmessungsprozess beschrieben, der alle Aspekte umfasst: Datenerfassung, Rückmessungsrahmen, Messfunktionen, Parameteroptimierung, die Sie selbst im juypter Notebook ausprobieren können.
Generell genügt es mit K-Liniendaten, um die Präzision zu gewährleisten, je kleiner die K-Linienzyklen, desto besser, aber um die Nachprüfungszeit und die Datenmenge auszubalancieren, wird in diesem Artikel mit 5min die Daten der letzten zwei Jahre nachgeprüft, wobei die endgültige Datenmenge 20 W-Linien übersteigt. Die Währung wählt DYDX.
import requests
from datetime import date,datetime
import time
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import requests, zipfile, io
%matplotlib inline
def GetKlines(symbol='BTC',start='2020-8-10',end='2021-8-10',period='1h'):
Klines = []
start_time = int(time.mktime(datetime.strptime(start, "%Y-%m-%d").timetuple()))*1000
end_time = int(time.mktime(datetime.strptime(end, "%Y-%m-%d").timetuple()))*1000
while start_time < end_time:
res = requests.get('https://fapi.binance.com/fapi/v1/klines?symbol=%sUSDT&interval=%s&startTime=%s&limit=1000'%(symbol,period,start_time))
res_list = res.json()
Klines += res_list
start_time = res_list[-1][0]
return pd.DataFrame(Klines,columns=['time','open','high','low','close','amount','end_time','volume','count','buy_amount','buy_volume','null']).astype('float')
df = GetKlines(symbol='DYDX',start='2022-1-1',end='2023-12-7',period='5m')
df = df.drop_duplicates()
Der Test setzte fort, die bisher üblichen Rahmenbedingungen für USDT-Festvertrags-Multiwährungen zu wählen, die einfach zu bedienen sind.
class Exchange:
def __init__(self, trade_symbols, fee=0.0004, initial_balance=10000):
self.initial_balance = initial_balance #初始的资产
self.fee = fee
self.trade_symbols = trade_symbols
self.account = {'USDT':{'realised_profit':0, 'unrealised_profit':0, 'total':initial_balance, 'fee':0}}
for symbol in trade_symbols:
self.account[symbol] = {'amount':0, 'hold_price':0, 'value':0, 'price':0, 'realised_profit':0,'unrealised_profit':0,'fee':0}
def Trade(self, symbol, direction, price, amount):
cover_amount = 0 if direction*self.account[symbol]['amount'] >=0 else min(abs(self.account[symbol]['amount']), amount)
open_amount = amount - cover_amount
self.account['USDT']['realised_profit'] -= price*amount*self.fee #扣除手续费
self.account['USDT']['fee'] += price*amount*self.fee
self.account[symbol]['fee'] += price*amount*self.fee
if cover_amount > 0: #先平仓
self.account['USDT']['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount #利润
self.account[symbol]['realised_profit'] += -direction*(price - self.account[symbol]['hold_price'])*cover_amount
self.account[symbol]['amount'] -= -direction*cover_amount
self.account[symbol]['hold_price'] = 0 if self.account[symbol]['amount'] == 0 else self.account[symbol]['hold_price']
if open_amount > 0:
total_cost = self.account[symbol]['hold_price']*direction*self.account[symbol]['amount'] + price*open_amount
total_amount = direction*self.account[symbol]['amount']+open_amount
self.account[symbol]['hold_price'] = total_cost/total_amount
self.account[symbol]['amount'] += direction*open_amount
def Buy(self, symbol, price, amount):
self.Trade(symbol, 1, price, amount)
def Sell(self, symbol, price, amount):
self.Trade(symbol, -1, price, amount)
def Update(self, close_price): #对资产进行更新
self.account['USDT']['unrealised_profit'] = 0
for symbol in self.trade_symbols:
self.account[symbol]['unrealised_profit'] = (close_price[symbol] - self.account[symbol]['hold_price'])*self.account[symbol]['amount']
self.account[symbol]['price'] = close_price[symbol]
self.account[symbol]['value'] = abs(self.account[symbol]['amount'])*close_price[symbol]
self.account['USDT']['unrealised_profit'] += self.account[symbol]['unrealised_profit']
self.account['USDT']['total'] = round(self.account['USDT']['realised_profit'] + self.initial_balance + self.account['USDT']['unrealised_profit'],6)
Die Grillstrategie ist sehr einfach: Verkauf, Kauf und Rückgang. Sie beinhaltet drei Parameter: Anfangspreis, Gitterintervall, Transaktionswert. Der Markt für DYDX ist sehr schwankend.
symbol = 'DYDX'
value = 100
pct = 0.01
def Grid(fee=0.0002, value=100, pct=0.01, init = df.close[0]):
e = Exchange([symbol], fee=0.0002, initial_balance=10000)
init_price = init
res_list = [] #用于储存中间结果
for row in df.iterrows():
kline = row[1] #这样会测一根K线只会产生一个买单或一个卖单,不是特别精确
buy_price = (value / pct - value) / ((value / pct) / init_price + e.account[symbol]['amount']) #买单价格,由于是挂单成交,也是最终的撮合价格
sell_price = (value / pct + value) / ((value / pct) / init_price + e.account[symbol]['amount'])
if kline.low < buy_price: #K线最低价低于当前挂单价,买单成交
e.Buy(symbol,buy_price,value/buy_price)
if kline.high > sell_price:
e.Sell(symbol,sell_price,value/sell_price)
e.Update({symbol:kline.close})
res_list.append([kline.time, kline.close, e.account[symbol]['amount'], e.account['USDT']['total']-e.initial_balance,e.account['USDT']['fee'] ])
res = pd.DataFrame(data=res_list, columns=['time','price','amount','profit', 'fee'])
res.index = pd.to_datetime(res.time,unit='ms')
return res
Die Einstellung des Anfangspreises beeinflusst die anfängliche Haltung der Strategie, die soeben wiederholte Standard-Anfängspreis ist der anfängliche Preis bei der Einführung, d.h. nicht gehalten bei der Einführung. Und wir wissen, dass die Netzstrategie alle Gewinne bei der Anfänglichkeit der Preisrückkehr erzielt, so dass die Erträge erheblich erhöht werden, wenn die Strategie bei der Einführung eine richtige Vorhersage über die Zukunft des Marktes hat. Setzen Sie hier den Anfangspreis auf 3U wiederholen.
Die Strategie ist jedoch, dass der Startpreis auf 3 U festgelegt wird, und die Strategie besteht darin, eine große Anzahl von Leerbeständen zu halten, die von Anfang an leer sind, und in diesem Fall direkt die Leerbestände von 17.000 U halten, was auch ein größeres Risiko für die Kunden darstellt.
Die Gridspanne bestimmt die Entfernung der Aufschlüsse. Offensichtlich ist es so, dass je kleiner der Abstand, desto häufiger werden die Transaktionen, je geringer der Profit für eine einzelne Rechnung und desto höher die Bearbeitungsgebühren. Es ist jedoch erwähnenswert, dass die Gridspanne kleiner wird und der Gridswert unverändert bleibt.
Da die Rückmessung 5mK-Daten enthält und nur einmal auf einer K-Leitung getätigt wird. Dies ist offensichtlich unrealistisch, insbesondere wenn die Volatilität der digitalen Währung sehr hoch ist und ein kleinerer Abstand im Rückmessungseinsatz zu einem echten Abstand viele Transaktionen verpasst. Nur ein größerer Abstand hat einen Referenzwert.
for p in [0.0005, 0.001 ,0.002 ,0.005, 0.01, 0.02, 0.05]:
res = Grid( fee=0.0002, value=value*p/0.01, pct=p, init =3)
print(p, round(min(res['profit']),0), round(res['profit'][-1],0), round(res['fee'][-1],0))
0.0005 -8378.0 144.0 237.0
0.001 -9323.0 1031.0 465.0
0.002 -9306.0 3606.0 738.0
0.005 -9267.0 9457.0 781.0
0.01 -9228.0 13375.0 550.0
0.02 -9183.0 15212.0 309.0
0.05 -9037.0 16263.0 131.0
Wie bereits erwähnt, sollte ein Netzintervall von 1% des Gesamtkapitals und 1% des Netzes für die meisten Märkte geeignet sein, solange es keinen schnellen Rückgang gibt. In diesem Fall löste ein Rückgang von fast 90% in DYDX auch einen Aufbruch aus.
Der Rücklaufpreis ist der Anfangspreis, die Differenz zwischen dem aktuellen Preis und dem anfänglichen Preis und die Gridgröße bestimmen, wie viele Positionen gehalten werden sollen. Wenn der Rücklaufpreis höher als der aktuelle Preis gesetzt ist, wird die Gridstrategie mehr tun, was wiederum leer ist. Der Standard-Rücklaufpreis ist der Preis, zu dem die Strategie gestartet wurde.
Bei der Eröffnung der Strategie wird der Rückgangspreis auf das 1.6-fache des Startpreises gesetzt, so dass die Netzstrategie als Mehrposition beginnt, wenn der Preis von 1.6 Mal auf den aktuellen Preis sinkt und den durch diesen Teil des Unterschieds verursachten Unterschied hält. Wenn der spätere Preis den Rückgangspreis / 1.6 übersteigt, wird der Anfangspreis neu eingestellt, so dass immer mindestens 60% des Unterschieds für den Mehrbetrag verwendet werden.
Natürlich kann man diesen Prozentsatz größer setzen, wenn man optimistischer ist, und die letztendlichen Gewinne werden entsprechend erhöht. Natürlich erhöht dieser Ansatz auch das Risikogewicht, wenn der Markt fällt.
NansegWarum kann fmz nicht direkt die Netzpolitik zurückverfolgen?