Оптимизация параметров стратегии сетки длительного контракта

Автор:Трава, Создано: 2023-12-08 17:00:38, Обновлено: 2023-12-14 17:07:42

img

Устойчивая сетка является популярной классической стратегией платформы. В отличие от насущной сетки, она не использует монет, но может быть использована с использованием рычагов. Однако, поскольку не может быть прямого количественного повторного измерения на платформе изобретателя, что неблагоприятно для фильтрации монет и определения параметров оптимизации, в этой статье будет представлен полный процесс повторного измерения Python, включающий в себя все аспекты сбора данных, повторного измерения рамок, измерения функций, оптимизации параметров и т. Д., которые можно попробовать самостоятельно в ноутбуке juypter.

Сбор данных

В целом достаточно использовать K-линейные данные, для точности, чем меньше циклов K-линий, тем лучше, но сбалансировать время повторного анализа и объем данных, в этом статье используется 5min для повторного анализа данных последних двух лет, и в конечном итоге объем данных превышает 20 W-линий, валюта выбирает DYDX;; конечно, конкретные валюты и циклы K-линий могут быть выбраны в зависимости от ваших интересов.

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.img

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

img

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

Установка начальной цены влияет на начальную цену стратегии, только что повторенная по умолчанию начальная цена - это начальная цена при запуске, т.е. нет цены при запуске. А мы знаем, что сетевая стратегия будет извлекать все прибыли при начальном возврате цены, поэтому если стратегия будет иметь правильное предвзятое отношение к будущему развитию рынка при запуске, то значительно повысится прибыль. Здесь установка начальной цены на 3U повторяем.

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

img

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

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

Поскольку регенерирование использует 5 мК линейные данные, и только один раз транзакции на K-линии. Это явно не соответствует реальности, особенно в цифровых валютах волатильность очень велика, меньшие интервалы в регенерировании упускают много сделок по сравнению с реальными, и только увеличение интервала имеет значение для ссылки. При таком механизме регенерирования выводы не точные.

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% также вызвало взрыв.

Переменная цена возврата

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

При первом запуске стратегии цена возврата устанавливается на 1.6 раза превышающую цену запуска, так что сетевая стратегия начинает держать большую позицию, вызванную этой части разницы, когда цена падает в 1.6 раза до текущей цены. Если позднее цена превышает цену возврата/1.6, то пересчитывается первоначальная цена, таким образом, всегда сохраняя не менее 60% разницы для использования большего.img

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


Больше

ЭЭСИПочему fmz не может напрямую отслеживать политику сетки?