3
Подписаться
1444
Подписчики

Подробное объяснение оптимизации параметров стратегии сетки бессрочных контрактов

Создано: 2023-12-08 17:00:38, Обновлено: 2023-12-14 17:07:42
comments   1
hits   2866

Подробное объяснение оптимизации параметров стратегии сетки бессрочных контрактов

Стратегия вечной сетки — популярная классическая стратегия на платформе. По сравнению со спотовой сеткой, нет необходимости держать монеты и можно добавить кредитное плечо, что гораздо удобнее, чем спотовая сетка. Однако, поскольку невозможно провести обратное тестирование непосредственно на Inventor Quantitative Platform, это не способствует скринингу валют и определению оптимизации параметров. В этой статье будет представлен полный процесс обратного тестирования Python, включая сбор данных, фреймворк обратного тестирования, функцию обратного тестирования, оптимизацию параметров, и т. д. Вы можете попробовать сделать это самостоятельно в блокноте Juypter.

Сбор данных

Обычно данных K-line достаточно. Для точности, чем меньше период K-line, тем лучше. Однако время бэктеста и объем данных должны быть сбалансированы. В этой статье для бэктестинга используются 5-минутные данные за последние два года . Конечный объем данных превышает 200 000 строк. Выберите DYDX. Конечно, конкретную валюту и период K-line можно выбрать в соответствии с вашими собственными интересами.

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

Фреймворк бэктестинга

В бэктесте по-прежнему используется ранее широко применяемая структура, поддерживающая несколько валют бессрочных контрактов USDT, которая проста и удобна в использовании.

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)

Функция бэктестинга сетки

Принцип стратегии сетки очень прост: продавайте, когда цена растет, и покупайте, когда цена падает. Он включает три конкретных параметра: начальную цену, шаг сетки и стоимость транзакции. Рыночные колебания DYDX очень велики. Он упал с начальных 8.6U до 1U и снова вырос до 3U на недавнем бычьем рынке. Начальная цена стратегии по умолчанию составляет 8.6U, что очень неблагоприятно для сети стратегия, но бэктест параметров по умолчанию Общая прибыль за два года составила 9200U, и в какой-то момент был убыток в размере 7500U. Подробное объяснение оптимизации параметров стратегии сетки бессрочных контрактов

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

Подробное объяснение оптимизации параметров стратегии сетки бессрочных контрактов

Влияние начальной цены

Установка начальной цены влияет на начальную позицию стратегии. Начальная цена по умолчанию для бэктеста сейчас — это начальная цена при запуске, то есть при запуске позиция не удерживается. Мы знаем, что стратегия сетки принесет всю прибыль, когда цена вернется к исходному уровню, поэтому, если стратегия сможет правильно предсказать будущее рынка при запуске, она значительно увеличит прибыль. Здесь мы устанавливаем начальную цену 3U, а затем проводим бэктест. Итоговая максимальная просадка составила 9200U, а итоговая прибыль — 13372U. Окончательная стратегия не удерживает позиции. Эта прибыль — вся прибыль от волатильности, а разница между прибылью параметров по умолчанию и этой прибылью — убыток позиции, вызванный неточным суждением о конечной цене.

Однако если начальная цена установлена ​​на уровне 3U, стратегия будет идти в шорт в начале и удерживать большое количество коротких позиций. В этом примере напрямую удерживается короткая позиция в 17 000 U, поэтому она сталкивается с большими рисками.

Подробное объяснение оптимизации параметров стратегии сетки бессрочных контрактов

Настройки интервала сетки

Шаг сетки определяет расстояние между отложенными ордерами. Очевидно, что чем меньше интервал, тем чаще транзакции, тем ниже прибыль от одной транзакции и тем выше комиссия за обработку. Но стоит отметить, что когда шаг сетки становится меньше, а значение сетки остается неизменным, общая позиция будет увеличиваться при изменении цены, а возникающие риски будут совершенно другими. Поэтому для бэк-тестирования эффекта шага сетки необходимо преобразовать значение сетки.

Поскольку при бэктесте используются данные линии 5mK, а на линии K выполняется только одна транзакция. Это, очевидно, не соответствует действительности, особенно с учетом того, что волатильность цифровых валют очень велика. Меньший интервал пропустит много транзакций при бэктестинге по сравнению с реальной торговлей. Только больший интервал будет иметь референтное значение. При использовании этого механизма обратного тестирования выводы не являются точными. По результатам бэктестинга данных потока ордеров на уровне тиков оптимальный шаг сетки должен составлять 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

Стоимость транзакции в сети

Как упоминалось ранее, когда волатильность одинакова, чем больше удерживаемая стоимость, тем выше метод пропорционального риска. Однако, пока это не быстрое падение, 1% от общего объема средств в сочетании с 1% от интервала сетки должен быть в состоянии справиться с большинством рыночных условий. В этом примере DYDX падение почти на 90% также привело к маржин-коллу. Но учтите, что DYDX в основном падает. Когда он падает, стратегия сетки идет в лонг и максимальное падение составляет 100%. Однако предела на рост нет, а риск гораздо выше. Поэтому стратегия сетки рекомендует пользователям выбирать валюты, которые, по их мнению, имеют потенциал, и открывать только длинные позиции.

Переменная регрессия Цена

Цена регрессии — это начальная цена. Разница между текущей ценой и начальной ценой, а также размер сетки определяют, какую позицию следует удерживать. Если цена регрессии установлена ​​выше текущей цены, стратегия сетки будет длинной, и наоборот. Цена регрессии по умолчанию — это цена, с которой была запущена стратегия. Чтобы снизить риск, рекомендуется использовать сетку только для лонгов. Естественная идея заключается в том, можно ли изменить цену регрессии так, чтобы даже если цена вырастет, вы все равно могли удерживать длинные позиции без необходимости их корректировки. сам. Если взять в качестве примера рынок BTC, то в этом году он вырос с 15 000 в начале года до 43 000 к концу года. Если вы начнете использовать стратегию сетки с начала года, цена возврата по умолчанию составит 15 000, и вы будете совершать как длинные, так и короткие сделки. Конкретные возвраты показаны на рисунке ниже. Вы будете терять деньги на всем пути, поскольку BTC поднимается. Даже если режим «только лонг» настроен неправильно, цена может быстро превысить лимит без удержания позиции. Подробное объяснение оптимизации параметров стратегии сетки бессрочных контрактов

Во-первых, когда стратегия запускается, цена регрессии устанавливается в 1,6 раза больше цены на момент запуска. Таким образом, стратегия сетки будет считать цену падающей от 1,6 раза до текущей цены и начнет удерживать лонг позиция, вызванная этой частью разницы в цене. Если последующая цена превышает Когда цена возврата равна /1.6, начальная цена сбрасывается, так что не менее 60% разницы всегда доступно для длинных позиций. Результаты бэктестинга следующие: Подробное объяснение оптимизации параметров стратегии сетки бессрочных контрактов

Конечно, если вы более оптимистично настроены относительно рынка, вы можете установить это соотношение на большее значение, и конечная прибыль соответственно увеличится. Конечно, если рынок падает, эта настройка также увеличит риск удержания позиций.