
я здесьBinance короткая перерастающая длинная перепадающая мультивалютная стратегия хеджированияВ то же время был выпущен и движок для бэктестинга. Первый отчет подтвердил эффективность стратегии на основе часового бэктестинга K-линии. Однако фактическое время бездействия публичной стратегии составляет 1 с, что является очень высокочастотной стратегией. Очевидно, что невозможно получить точные результаты путем бэктестинга с почасовой K-линией. Позже добавленоТестирование минутной линииВ результате прибыль по бэктестингу значительно возросла, но по-прежнему невозможно определить, какие параметры следует использовать в ситуации второго уровня, да и понимание всей стратегии не очень ясное. Основная причина — существенный недостаток бэктестинга на основе K-линии.
Прежде всего, что такое историческая К-линия? Данные K-линии включают четыре цены: максимальную цену открытия и минимальную цену закрытия, два времени начала и диапазон объема торговли. Большинство количественных платформ и фреймворков основаны на бэктестинге K-line, а количественная платформа FMZ также обеспечивает бэктестинг на уровне тиков. Бэктестинг K-line очень быстрый и в большинстве случаев не вызывает никаких проблем, но у него также есть очень серьезные недостатки, особенно при бэктестинге многовариантных стратегий и высокочастотных стратегий: практически невозможно сделать правильные выводы.
Первая проблема — это вопрос времени. Время самых высоких и самых низких цен данных K-line не указано, поэтому нет необходимости его учитывать. Но самые важные цены открытия и закрытия не начинаются с открытия и время закрытия. Даже для менее популярных торговых продуктов часто нет торговли дольше десяти секунд. Когда мы тестируем многопродуктовые стратегии, мы часто предполагаем, что их цены открытия и закрытия являются одновременными. Это также является основой для тестирования цены закрытия.
Представьте себе использование минутной линии для бэктестинга арбитража двух разновидностей. Разница в их ценах обычно составляет 10 юаней. Теперь выясняется, что в 10:01 цена закрытия контракта A составляет 100, а цена закрытия контракта B — 112. Разница в цене составляет 12 юаней. Поэтому стратегия начинает хеджирование. В этот момент разница в цене вернулась, и стратегия заработала прибыль в размере 2 юаней.
Фактическая ситуация может быть такой, что в 10:00:45 контракт A сгенерировал транзакцию на 100 юаней, и после этого транзакций не было. В 10:00:58 контракт B сгенерировал транзакцию на 112 юаней. В 10:01, обе цены не существуют, какова рыночная цена в данный момент и какую разницу в цене можно получить с помощью хеджирования? Нет возможности узнать это. Один из возможных сценариев: в 10:00:58 цена спроса и предложения по контракту А составляет 101,9–102,1, а разницы в цене в 2 юаня нет вообще. Это в значительной степени собьет с толку оптимизацию нашей стратегии.
Вторая проблема — соответствие. Настоящее соответствие ставит во главу угла цену и время. Если покупатель превышает цену предложения, транзакция, как правило, будет завершена напрямую по цене предложения. В противном случае она войдет в книгу заявок и будет ждать. Данные K-line, очевидно, не содержат цены покупки и продажи, и смоделировать соответствие на детальном уровне невозможно.
Наконец, есть влияние самой стратегии на рынок. Если это небольшой бэктест капитала, влияние не будет значительным. Но если объем торговли составит большую долю, это окажет влияние на рынок. Не только проскальзывание цены будет большим, когда транзакция выполняется немедленно, но и если ваш ордер на покупку выполняется через бэктестинг, он фактически вытеснит транзакции других трейдеров, которые изначально хотели купить, и эффект бабочки окажет влияние на рынок. Это влияние невозможно оценить количественно, и на основе опыта мы можем лишь сказать, что высокочастотная торговля может работать только с небольшими фондами.
FMZ обеспечивает бэктестинг в реальном времени, который позволяет получить реальную историческую глубину в 20 уровней, тик второго уровня в реальном времени, данные по каждой транзакции и другие данные.Функция воспроизведения в реальном времени. Объем данных бэктестинга чрезвычайно велик, а скорость очень низкая, обычно всего два дня. Для относительно высокочастотных стратегий или стратегий, требующих строгой оценки времени, необходимо тестирование в реальном времени. Пары транзакций и временные периоды, собираемые FMZ, невелики, но имеется более 70 миллиардов исторических данных. Текущий механизм сопоставления заключается в том, что если ордер на покупку больше ордера на продажу, он будет полностью сопоставлен немедленно, без учета объема; если он меньше ордера на продажу, он попадет в очередь сопоставления. Такой механизм бэктестинга решает первые две проблемы бэктестинга K-line, но он все еще не может решить последнюю проблему. А поскольку объем данных очень велик, скорость и временной диапазон бэктестинга ограничены.

Информации о K-line слишком мало, и глубина может быть ложной, но есть один вид данных, который отражает истинное намерение рынка относительно транзакций и отражает наиболее достоверную историю транзакций, то есть транзакцию за транзакцией. В этой статье будет предложена система высокочастотного бэктестинга, основанная на потоке ордеров, которая значительно сократит объем данных для бэктестинга в реальном времени и в определенной степени смоделирует влияние объема торгов на рынок.
Я загрузил записи транзакций бессрочного контракта Binance XTZ за последние 5 дней (адрес загрузки: https://www.fmz.com/upload/asset/1ff487b007e1a848ead.csv). Поскольку это не очень популярный продукт, в нем 213 000 транзакций. Всего. Данные, давайте сначала посмотрим на состав данных:
[['XTZ', 1590981301905, 2.905, 0.4, 'False\n'],
['XTZ', 1590981303044, 2.903, 3.6, 'True\n'],
['XTZ', 1590981303309, 2.903, 3.7, 'True\n'],
['XTZ', 1590981303738, 2.903, 238.1, 'True\n'],
['XTZ', 1590981303892, 2.904, 0.1, 'False\n'],
['XTZ', 1590981305250, 2.904, 0.1, 'False\n'],
['XTZ', 1590981305643, 2.903, 197.3, 'True\n'],
Данные представляют собой двумерный список, отсортированный по времени транзакции. Конкретные значения: название продукта, цена транзакции, временная метка транзакции, объем транзакции и является ли транзакция активным ордером на продажу. Есть покупатели и продавцы, и каждая транзакция включает покупателя и продавца. Если покупатель — маркет-мейкер, а продавец — тейкер, последние данные — True.
Во-первых, на основе направления транзакции можно довольно точно вывести цены покупки и продажи на рынке. Если это активный ордер на продажу, то цена покупки в это время является ценой транзакции. Если это активный ордер на покупку, то цена продажи — цена транзакции. Если есть новая транзакция, новая котировка будет обновлена. Если не обновлена, предыдущий результат будет сохранен. Легко сделать вывод, что в последний момент приведенных выше данных цена покупки составляла 2,903, а цена продажи — 2,904.
Согласно потоку ордеров, сопоставление может быть выполнено следующим образом: если взять в качестве примера ордер на покупку, то цена — это цена, объем ордера — это сумма, а ордера на покупку и продажу — это бид и аск соответственно. Если цена ниже, чем аск и выше, чем бид, то сначала определяется, что это мейкер и может быть сопоставлен с заказом первым. Затем, в течение времени существования заказа, все транзакции с ценой транзакции ниже или равная цене будет сопоставлена с этим ордером (если цена ниже, чем аск, ордер будет сопоставлен с бидом). Если цена бида равна или выше, чем цена бида, ордер не может быть продан первым . Все ордера с ценой транзакции ниже цены предложения будут сопоставлены с этим ордером. Цена сопоставления — это цена предложения, а объем транзакции — это объем транзакции каждой транзакции до тех пор, пока ордер не будет полностью выполнен или отменен. Если цена выше, чем ask, он считается тейкером. После этого все транзакции с ценой транзакции ниже или равной цене в течение времени существования ордера будут сопоставлены с этим ордером, и сопоставленная цена будет цена сделки по сделке. Различие между мейкерами и тейкерами заключается в том, что биржи в основном поощряют размещение заказов и предлагают льготные комиссии за транзакции. Для высокочастотных стратегий это различие необходимо учитывать.
Легко увидеть проблему с этим типом сопоставления. Если заказ является заказом тейкера, то фактическая ситуация такова, что он может быть выполнен немедленно, а не ждать новых заказов, чтобы сопоставить его. Во-первых, мы не учитывали объем отложенных ордеров. Даже если бы были данные, прямая оценка транзакции изменила бы глубину и повлияла бы на рынок. Матчинг на основе новых ордеров эквивалентен замене реальных ордеров в истории на ваши ордера. В любом случае, он не превысит лимит собственного объема торговли рынка, а итоговая прибыль не превысит максимальную прибыль, генерируемую рынком. Некоторые механизмы сопоставления также влияют на объем транзакций заказов, что, в свою очередь, влияет на доходность стратегии и количественно отражает ее пропускную способность. Традиционного бэк-теста, при котором прибыль удваивается при удвоении суммы средств, не будет.
Есть некоторые мелкие детали. Если цена покупки ордера равна цене покупки одного, на самом деле все еще есть определенная вероятность, что он будет сопоставлен по цене покупки одного. Необходимо учитывать приоритет отложенного ордера и вероятность транзакции и т.д. Это относительно сложно и не будет здесь рассматриваться.
Объекты обмена могут ссылаться на введение в начале, которое в основном не изменилось. Добавляется только разница между комиссиями мейкера и тейкера, а также оптимизируется скорость бэктестинга. Далее будет представлен в основном соответствующий код.
symbol = 'XTZ'
loop_time = 0
intervel = 1000 #策略的休眠时间为1000ms
init_price = data[0][2] #初始价格
e = Exchange([symbol],initial_balance=1000000,maker_fee=maker_fee,taker_fee=taker_fee,log='') #初始化交易所
depth = {'ask':data[0][2], 'bid':data[0][2]} #深度
order = {'buy':{'price':0,'amount':0,'maker':False,'priority':False,'id':0},
'sell':{'price':0,'amount':0,'maker':False,'priority':False,'id':0}} #订单
for tick in data:
price = int(tick[2]/tick_sizes[symbol])*tick_sizes[symbol] #成交价格
trade_amount = tick[3] #成交数量
time_stamp = tick[1] #成交时间戳
if tick[4] == 'False\n':
depth['ask'] = price
else:
depth['bid'] = price
if depth['bid'] < order['buy']['price']:
order['buy']['priority'] = True
if depth['ask'] > order['sell']['price']:
order['sell']['priority'] = True
if price > order['buy']['price']:
order['buy']['maker'] = True
if price < order['sell']['price']:
order['sell']['maker'] = True
#订单网络延时也可以作为撮合条件之一,这里没考虑
cond1 = order['buy']['priority'] and order['buy']['price'] >= price and order['buy']['amount'] > 0
cond2 = not order['buy']['priority'] and order['buy']['price'] > price and order['buy']['amount'] > 0
cond3 = order['sell']['priority'] and order['sell']['price'] <= price and order['sell']['amount'] > 0
cond4 = not order['sell']['priority'] and order['sell']['price'] < price and order['sell']['amount'] > 0
if cond1 or cond2:
buy_price = order['buy']['price'] if order['buy']['maker'] else price
e.Buy(symbol, buy_price, min(order['buy']['amount'],trade_amount), order['buy']['id'], order['buy']['maker'])
order['buy']['amount'] -= min(order['buy']['amount'],trade_amount)
e.Update(time_stamp,[symbol],{symbol:price})
if cond3 or cond4:
sell_price = order['sell']['price'] if order['sell']['maker'] else price
e.Sell(symbol, sell_price, min(order['sell']['amount'],trade_amount), order['sell']['id'], order['sell']['maker'])
order['sell']['amount'] -= min(order['sell']['amount'],trade_amount)
e.Update(time_stamp,[symbol],{symbol:price})
if time_stamp - loop_time > intervel:
order = get_order(e,depth,order) #交易逻辑,这里未给出
loop_time += int((time_stamp - loop_time)/intervel)*intervel
Несколько деталей, на которые следует обратить внимание:
Наконец, мы достигли фактической стадии бэктестинга. Мы проведем бэктест одной из самых классических стратегий сетки, чтобы увидеть, достигает ли она ожидаемых результатов. Принцип стратегии заключается в том, что каждый раз, когда цена растет на 1%, мы держим короткий ордер определенного значения (или наоборот, держим длинный ордер), рассчитываем ордера на покупку и продажу и заранее выставляем их. Код не будет опубликован. Инкапсулируйте весь код вGrid('XTZ',100,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)В функции используются следующие параметры: торговая пара, отклонение цены 1% от удерживаемой стоимости, плотность ордеров 0,3%, интервал сна в мс, комиссия создателя ордера и комиссия принимающего ордер.
В последние пять дней рынок XTZ находился в нестабильной фазе, что очень подходит для энергосистемы. 
Сначала мы тестируем на исторических данных влияние различных размеров позиций на доходность. Доходность, измеренная традиционным механизмом тестирования на исторических данных, определенно увеличится пропорционально увеличению позиций.
e1 = Grid('XTZ',100,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
print(e1.account['USDT'])
e2 = Grid('XTZ',1000,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
print(e2.account['USDT'])
e3 = Grid('XTZ',10000,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
print(e3.account['USDT'])
e4 = Grid('XTZ',100000,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
print(e4.account['USDT'])
Всего было протестировано четыре группы со значениями удержания 100, 1000, 10000 и 100000 соответственно, а общее время тестирования составило 1,3 с. Результаты следующие:
{'realised_profit': 28.470993031132966, 'margin': 0.7982662957624465, 'unrealised_profit': 0.0104554474048441, 'total': 10000028.481448, 'leverage': 0.0, 'fee': -0.3430967859046398, 'maker_fee': -0.36980249726699727, 'taker_fee': 0.026705711362357405}
{'realised_profit': 275.63148945320177, 'margin': 14.346335829979132, 'unrealised_profit': 4.4382117331794045e-14, 'total': 10000275.631489, 'leverage': 0.0, 'fee': -3.3102045933457784, 'maker_fee': -3.5800688964477048, 'taker_fee': 0.2698643031019274}
{'realised_profit': 2693.8701498889504, 'margin': 67.70120400534114, 'unrealised_profit': 0.5735269329348516, 'total': 10002694.443677, 'leverage': 0.0001, 'fee': -33.984021415250744, 'maker_fee': -34.879233866850974, 'taker_fee': 0.8952124516001403}
{'realised_profit': 22610.231198585603, 'margin': 983.3853688758861, 'unrealised_profit': -20.529965947304365, 'total': 10022589.701233, 'leverage': 0.002, 'fee': -200.87094000385412, 'maker_fee': -261.5849078470078, 'taker_fee': 60.71396784315319}
Видно, что итоговая реализованная прибыль составила 28,4%, 27,5%, 26,9% и 22,6% от стоимости позиции соответственно. Это также соответствует фактической ситуации. Чем больше стоимость позиции, чем больше стоимость отложенного ордера, тем больше вероятность того, что частичная транзакция будет совершена, а окончательная реализованная прибыль будет меньше по сравнению с объем отложенного ордера. На следующем рисунке сравнивается относительная доходность активов стоимостью 100 и 10 000 соответственно:

Мы также можем провести бэктестинг влияния различных параметров на результаты бэктестинга, таких как плотность заказов, время бездействия, комиссии за обработку и т. д. Возьмем в качестве примера время сна, изменим его на 100 мс и сравним со временем сна 1000 мс, чтобы увидеть преимущества. Результаты бэктестинга следующие:
{'realised_profit': 29.079440803790423, 'margin': 0.7982662957624695, 'unrealised_profit': 0.0104554474048441, 'total': 10000029.089896, 'leverage': 0.0, 'fee': -0.3703702128662524, 'maker_fee': -0.37938946377435134, 'taker_fee': 0.009019250908098965}
Прибыль немного увеличилась. Это потому, что стратегия размещает только один набор ордеров. Некоторые ордера не могут выиграть от колеблющихся цен, потому что их нельзя изменить вовремя. Сокращение времени покоя улучшило эту проблему. Это также иллюстрирует важность размещения нескольких групп заказов в сеточной стратегии.
В этой статье инновационно предлагается новая система бэктестинга, основанная на потоке ордеров, которая может частично имитировать условия соответствия отложенных ордеров, принятия ордеров, частичных транзакций, задержек и т. д., а также частично отражать влияние стратегических фондов на доходность. Она имеет важные ссылки ценность для стратегий хеджирования, а высокоточное бэктестирование указывает направление для оптимизации параметров стратегии. Это также было проверено в ходе долгосрочной реальной торговли. Он также лучше контролирует объем данных, необходимых для бэктестинга, а скорость бэктестинга также очень высокая.