Когда я писалИсследование стратегии хеджирования в нескольких валютах на фьючерсах Binance, Я также выпустил движок обратного теста. И первый отчет был основан на одночасовом обратном тесте K-линии, который подтвердил эффективность стратегии. Но время сна фактической стратегии с открытым исходным кодом составляет
Прежде всего, что такое историческая линия K? Данные K-линии содержат четыре цены: высокая, открытая, низкая, близкая, первые два
Первое - это вопрос времени. Время наивысшей цены и самой низкой цены данных K-линии не указано и не нужно учитывать, но самые важные цены открытия и закрытия - это не время открытия и закрытия. Даже менее популярные торговые варианты часто не торгуют более десяти секунд, и когда мы проверяем многовариантную стратегию, мы часто предполагаем, что их цена открытия и цена закрытия одинаковы, что также основано на обратном тестировании цены закрытия.
Представьте, что вы используете линию минутового уровня K для обратного тестирования арбитража двух сортов. Разница между ними обычно составляет 10 юаней ((или долларов). Теперь, в 10:01, цена закрытия контракта А составляет 100, контракт В - 112, а разница составляет 12 юаней. Таким образом, стратегия начинает хеджироваться. В определенный момент разница в цене возвращается, и стратегия получает прибыль в размере 2 юаней.
но фактическая ситуация может быть такая, что в 10:00:45, контракт А произвел транзакцию в 100 юаней, после чего не было никакой транзакции, контракт В имел транзакцию в 112 юаней в 10:00:58, в 10:01:00 Обе цены не существуют. Какая рыночная цена в это время, и сколько может получить хеджирующая операция? Я не могу знать. Одна из возможных ситуаций: в 10:00:58, цена 101.9
до102.1
Это сильно обманет нашу стратегию оптимизации.
Второй - это проблема сопоставления. Реальный сопоставление - это приоритет цены и приоритет времени. Если покупатель превышает цену
Последний - это влияние самой стратегии на рынок. Если это бэкстест небольших сумм средств, влияние не большое. Но если объем транзакций большой, то это повлияет на рынок. Не только ценовой сдвиг будет большим, когда вы размещаете большой объем ордера, если вы покупаете длинный ордер, выполненный, этот вид действия на самом деле захватить заказы других трейдеров, которые изначально хотели купить, эффект
FMZ обеспечивает реальный уровень backtest, который может получить реальные исторические20 layer depth price
, в режиме реального времени второго уровняTicks
, Each Individual Transaction
На основе этих функций FMZ создал функцию воспроизведения транзакций в реальном времени.
Такой объем данных обратного теста очень большой, а скорость обратного теста также очень медленная, обычно можно проводить обратный тест только в течение двух дней. Для относительно высокочастотных или критических по времени стратегий необходим реальный обратный тест на уровне рынка.
В настоящее время механизм соответствия заключается в том, что если заказ на покупку больше
В K-линии слишком мало информации, и глубина цены также может быть фальшивой глубиной, но есть тип данных, которые являются реальной готовностью рынка к транзакциям, которая отражает самую реальную историю транзакций, то естьEach Individual Transaction
В этой статье будет предложена высокочастотная система обратного теста, основанная на потоке заказов, которая значительно уменьшит объем данных обратного теста на реальном рынке и в определенной степени смоделирует влияние объема торговли на рынок.
Я загрузил транзакцию последних 5 дней Binance XTZ вечный контракт (адрес загрузки:https://www.fmz.com/upload/asset/1ff487b007e1a848ead.csv), как не популярный сорт, он имеет в общей сложности 213000 данных о транзакциях, сначала давайте посмотрим на состав данных:
[['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'],
Данные представляют собой двумерный список, сортированный в хронологическом порядке. Конкретные значения следующие: название сорта, цена сделки, временная марка сделки, количество сделки, является ли это активной сделкой с продажным заказом. Существуют стороны покупки и продажи, и каждая сделка включает в себя покупателя и продавца. Если покупатель является рынкомMaker
и продавец является активнымTaker
, последние данныеTrue
.
Во-первых, в зависимости от направления сделки вы можете достаточно точно спекулировать на
Согласно потоку заказов, он может быть сопоставлен следующим образом: возьмите заказ на покупку в качестве примера, ценаprice
, количество заказа:amount
, то купить и продать 1 в это времяbid
иask
соответственно.price
нижеask
и вышеbid
, то он оценивается какmaker
первое, и приоритет может быть совпадает, чтобы сделать сделку, то все сделки с ценой сделки ниже или равнаprice
время существования заказа будет совпадать с этим заказом (еслиprice
меньше или равноbid
, не приоритетность данной сделки.price
совпадают с этим порядком.)
Соответствующая цена:price
, а объем - объем транзакцийEach Individual Transaction
, пока заказ не будет полностью завершен или пока заказ не будет отменен.ask
, оно оценивается какtaker
После этого, в течение времени, когда ордер существует, все сделки с ценой транзакции ниже или равнаprice
совпадают с этим заказом, и цена совпадения - это цена сделкиEach Individual Transaction
Различие междуmaker
иtaker
Для высокочастотных стратегий необходимо учитывать эту разницу.
Это легко увидеть проблему с этим типом соответствия.taker
, фактическая ситуация заключается в том, что он может быть выполнен немедленно, а не ждать, пока новый заказ будет совпадать с ним. Во-первых, мы не рассматривали объем ожидающих заказов, даже если есть некоторые данные, непосредственно судить сделка также изменила глубину цены, влияя на рынок.
На основе сопоставления новых заказов, это эквивалентно замене существующих заказов в истории на ваши заказы. В любом случае, он не будет превышать предел собственного объема торговли рынка, и конечная прибыль не может превышать максимальную прибыль, генерируемую рынком. Часть механизма сопоставления также влияет на объем заказов, который, в свою очередь, влияет на доход стратегии, количественно отражая потенциал стратегии. Не будет традиционного бэкстеста, когда сумма средств удваивается и прибыль удваивается.
Есть еще некоторые мелкие детали. Если цена покупки заказа равна
Объекты обмена могут относиться к введению в начале, в основном неизменным, только добавляя разницу междуmaker
иtaker
В следующем разделе в основном будет представлен код совпадения.
symbol = 'XTZ'
loop_time = 0
intervel = 1000 # The sleep time of the strategy is 1000ms
init_price = data[0][2] # Initial price
e = Exchange([symbol],initial_balance=1000000,maker_fee=maker_fee,taker_fee=taker_fee,log='') # Initialize the exchange
depth = {'ask':data[0][2], 'bid':data[0][2]} # depth
order = {'buy':{'price':0,'amount':0,'maker':False,'priority':False,'id':0},
'sell':{'price':0,'amount':0,'maker':False,'priority':False,'id':0}} # order
for tick in data:
price = int(tick[2]/tick_sizes[symbol])*tick_sizes[symbol] # executed price
trade_amount = tick[3] # executed volume
time_stamp = tick[1] # executed timestamp
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
# Order network delay can also be used as one of the matching conditions, not considered here
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) # Trading logic, not given here
loop_time += int((time_stamp - loop_time)/intervel)*intervel
Некоторые детали:
Когда происходит новая сделка, мы должны сначала сопоставить заказ, а затем разместить заказ по последней цене.
Каждый заказ имеет два атрибута: makermaker
, а когда цена покупки больше Priority matching
, priority
определяет, равна ли цена покупке или нет, а производитель определяет комиссию за транзакцию.
Вmaker
иpriority
Если большая покупка была размещена и превышает рыночную емкость.maker
.
Стратегияinterval
Это может означать задержку на рынке.
Наконец, это фактический этап обратного теста. Давайте проверим одну из самых классических стратегий сетки здесь, чтобы увидеть, можем ли мы достичь ожидаемых результатов. Принцип стратегии заключается в том, что каждый раз, когда цена повышается на 1%, мы держим короткий заказ определенного значения (наоборот, мы держим длинный заказ), рассчитываем заказ покупки и продажи заранее. Я не покажу вам исходный код.Grid('XTZ', 100, 0.3, 1000, maker_fee=-0.00002, taker_fee=0.0003)
функция, параметры: торговая пара, цена отклоняется от стоимости хранения на 1%, плотность ожидаемых заказов составляет 0,3%, интервал снаms
, отсроченные сборы за заказы и сборы за исполненные заказы.
Рыночная цена 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, 100 000, а общее время обратных тестов составило 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 мс и сравним время сна с 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}
Это также иллюстрирует важность сетевой стратегии для размещения нескольких наборов заказов.
Эта статья инновационно предлагает новую систему обратного теста, основанную на потоке заказов, которая может частично моделировать ситуацию совпадения ожидаемых заказов, исполняемых заказов, частично выполненных заказов, задержек и т. д., и частично отражает влияние суммы стратегии средств на доходы. Для высокочастотных и хеджирующих стратегий, У нее есть важное справочное значение. Высокоточный обратный тест указывает направление для оптимизации параметров стратегии. Он также проверен в течение длительного времени. Кроме того, количество данных, необходимых для обратного теста, хорошо контролируется, и скорость обратного теста также очень быстра.