3
Seguir
1444
Seguidores

Explicación detallada de la optimización de los parámetros de la estrategia de red de contratos perpetuos

Creado el: 2023-12-08 17:00:38, Actualizado el: 2023-12-14 17:07:42
comments   1
hits   2862

Explicación detallada de la optimización de los parámetros de la estrategia de red de contratos perpetuos

La estrategia de cuadrícula perpetua es una estrategia clásica popular en la plataforma. En comparación con la red al contado, no es necesario mantener monedas y se puede agregar apalancamiento, lo que es mucho más conveniente que la red al contado. Sin embargo, dado que es imposible realizar pruebas retrospectivas directamente en la plataforma cuantitativa Inventor, no es propicio para seleccionar monedas y determinar la optimización de parámetros. Este artículo presentará el proceso completo de pruebas retrospectivas de Python, incluida la recopilación de datos, el marco de pruebas retrospectivas, la función de pruebas retrospectivas, la optimización de parámetros, etc. Puedes probarlo tú mismo en Jupiter Notebook.

Recopilación de datos

En general, los datos de la línea K son suficientes. Por el bien de la precisión, cuanto menor sea el período de la línea K, mejor. Sin embargo, el tiempo de prueba retrospectiva y el volumen de datos deben estar equilibrados. Este artículo utiliza datos de 5 minutos de los últimos dos años para realizar pruebas retrospectivas. El volumen de datos final supera las 200.000 filas. Elija DYDX. Por supuesto, la moneda específica y el período de la línea K se pueden seleccionar de acuerdo con sus propios intereses.

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()

Marco de trabajo de pruebas retrospectivas

El backtest continúa utilizando el marco comúnmente usado anteriormente que admite múltiples monedas de contratos perpetuos de USDT, que es simple y fácil de usar.

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)

Función de prueba retrospectiva de la red

El principio de la estrategia de cuadrícula es muy simple: vender cuando el precio sube y comprar cuando baja. Implica tres parámetros específicos: precio inicial, espaciado de la cuadrícula y valor de la transacción. Las fluctuaciones del mercado de DYDX son muy grandes. Ha caído de los 8,6 U iniciales a 1 U, y ha vuelto a subir a 3 U en el mercado alcista reciente. El precio inicial predeterminado de la estrategia es 8,6 U, lo que es muy desfavorable para la red. estrategia, pero el parámetro predeterminado backtest La ganancia total en dos años fue 9200U, y hubo una pérdida de 7500U en un momento. Explicación detallada de la optimización de los parámetros de la estrategia de red de contratos perpetuos

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

Explicación detallada de la optimización de los parámetros de la estrategia de red de contratos perpetuos

El impacto del precio inicial

La configuración del precio inicial afecta la posición inicial de la estrategia. El precio inicial predeterminado del backtest actual es el precio inicial al inicio, es decir, no se mantiene ninguna posición al inicio. Sabemos que la estrategia de red obtendrá todas las ganancias cuando el precio regrese al nivel inicial, por lo que si la estrategia puede predecir correctamente el mercado futuro cuando se lance, aumentará significativamente las ganancias. Aquí establecemos el precio inicial en 3U y luego realizamos una prueba retrospectiva. La caída máxima final fue 9200U y la ganancia final fue 13372U. La estrategia final no mantiene posiciones. Esta ganancia es toda la ganancia por volatilidad, y la diferencia entre la ganancia de los parámetros predeterminados y esta ganancia es la pérdida de posición causada por un cálculo incorrecto del precio final.

Sin embargo, si el precio inicial se establece en 3U, la estrategia se pondrá en corto al principio y mantendrá una gran cantidad de posiciones cortas. En este ejemplo, se mantiene directamente una posición corta de 17.000 U, por lo que enfrenta mayores riesgos.

Explicación detallada de la optimización de los parámetros de la estrategia de red de contratos perpetuos

Configuración del espaciado de la cuadrícula

El espaciado de la cuadrícula determina la distancia entre las órdenes pendientes. Obviamente, cuanto menor sea el espaciado, más frecuentes serán las transacciones, menor será la ganancia de una sola transacción y mayor será la tarifa de procesamiento. Pero vale la pena señalar que cuando el espaciado de la cuadrícula se hace más pequeño y el valor de la cuadrícula permanece sin cambios, la posición total aumentará cuando cambie el precio y los riesgos a los que se enfrenta son completamente diferentes. Por lo tanto, para probar retrospectivamente el efecto del espaciado de la cuadrícula, es necesario convertir el valor de la cuadrícula.

Dado que el backtest utiliza datos de línea de 5mK y solo se realiza una transacción en una línea K. Obviamente, esto no se corresponde con la realidad, especialmente porque la volatilidad de las monedas digitales es muy grande. Un espaciado más pequeño hará que se pierdan muchas transacciones en las pruebas retrospectivas en comparación con las transacciones reales. Solo un espaciado más grande tendrá valor de referencia. Bajo este mecanismo de backtesting las conclusiones extraídas no son precisas. A través de pruebas retrospectivas de datos de flujo de órdenes a nivel de tick, el espaciado óptimo de la cuadrícula debería ser 0,005-0,01.

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

Valor de transacción de la red

Como se mencionó anteriormente, cuando la volatilidad es la misma, cuanto mayor sea el valor mantenido, mayor será el método proporcional al riesgo. Sin embargo, siempre que no se trate de una caída rápida, el 1% de los fondos totales combinados con el 1% del espaciado de la cuadrícula Debería poder hacer frente a la mayoría de las condiciones del mercado. En este ejemplo de DYDX, una caída de casi el 90% también desencadenó una llamada de margen. Pero tenga en cuenta que DYDX suele caer. Cuando cae, la estrategia de la red es larga y la caída máxima es del 100 %. Sin embargo, no hay límite para el aumento y el riesgo es mucho mayor. Por lo tanto, la estrategia de cuadrícula recomienda que los usuarios elijan monedas que crean que tienen potencial y solo operen en largo.

Precio de regresión variable

El precio de regresión es el precio inicial. La diferencia entre el precio actual y el precio inicial y el tamaño de la cuadrícula determinan cuánta posición se debe mantener. Si el precio de regresión se establece más alto que el precio actual, la estrategia de cuadrícula irá en largo y viceversa. El precio de regresión predeterminado es el precio en el que se inició la estrategia. Para reducir el riesgo, se recomienda utilizar una cuadrícula de posiciones largas únicamente. Una idea natural es si es posible cambiar el precio de regresión de modo que, incluso si el precio sube, aún se puedan mantener posiciones largas sin tener que ajustarlas. tú mismo. Tomando como ejemplo el mercado de BTC este año, pasó de 15.000 a principios de año a 43.000 a finales de año. Si comienza a ejecutar la estrategia de cuadrícula desde principios de año, el precio de retorno predeterminado es de 15 000 y realiza operaciones tanto largas como cortas. Los retornos específicos se muestran en la siguiente figura. Perderá dinero en todo momento, ya que BTC se eleva. Incluso si el modo de solo largo plazo no está configurado correctamente, el precio puede exceder rápidamente el límite sin mantener una posición. Explicación detallada de la optimización de los parámetros de la estrategia de red de contratos perpetuos

En primer lugar, cuando se inicia la estrategia, el precio de regresión se establece en 1,6 veces el precio en el momento de la puesta en marcha. De esta manera, la estrategia de cuadrícula considerará que el precio cae de 1,6 veces al precio actual y comenzará a mantener la posición larga. Posición causada por esta parte de la diferencia de precio. Si el precio posterior supera el precio de retorno /1.6, se restablece el precio inicial, de modo que al menos el 60% de la diferencia siempre esté disponible para posiciones largas. Los resultados del backtest son los siguientes: Explicación detallada de la optimización de los parámetros de la estrategia de red de contratos perpetuos

Por supuesto, si eres más optimista sobre el mercado, puedes establecer este ratio en un valor mayor y el beneficio final aumentará en consecuencia. Por supuesto, si el mercado cae, esta configuración también aumentará el riesgo de mantener posiciones.