各トランザクションとK線バックテストの欠陥に基づく高周波バックテストシステム

作者: リン・ハーン優しさ, 作成日: 2020-06-16 10:30:19, 更新日: 2023-11-01 20:26:21

img

私が書いたときビナンス・フューチャーズ・マルチ通貨・ヘッジ戦略に関する研究,私はバックテストエンジンもリリースしました. 最初のレポートは,戦略の有効性を検証した1時間のKラインバックテストに基づいていました. しかし,実際のオープンソース戦略の睡眠時間は1秒で,かなり高周波の戦略です.明らかに,毎時間のKラインバックテストを使用して正確な結果が得られません. その後,分レベルKラインのバックテストの結果が追加され,バックテスト収益は大幅に改善されました. しかし,秒レベルの場合,どのパラメータを使用すべきかを決定することはまだ不可能であり,戦略全体の理解はあまり明確ではありません. 主な理由は,Kラインに基づくバックテストの重要な欠点です.

K線バックテストに基づく問題

まず,歴史的なK線とは何か.K線データには4つの価格,高,オープン,低,閉,最初の2つのと間隔の音量が含まれています.ほとんどの量子化プラットフォームとフレームワークはK線バックテストに基づいています.FMZプラットフォームは,ティックレベルバックテストも提供しています.K線バックテストのスピードは非常に高速で,ほとんどの場合,非常に少ない問題がありますが,特にバックテストのマルチ多様性戦略と高周波戦略など,非常に深刻な欠陥もあります.正しい結論を出すことはほぼ不可能です.

第"は時間の問題である.K線データの最高価格と最低価格の時刻は与えられていないし,考慮する必要もないが,最も重要な開閉価格は開閉時間ではない.あまり人気のない取引品種でさえ,10秒以上取引しないことが多い.そして,マルチバリエーション戦略をバックテストするとき,開閉価格と閉閉閉価格が同じであると仮定することが多い.これは閉閉価格のバックテストにも基づいている.

2つの品種の仲介をバックテストするために,分数レベルK線を使用することを想像してください. その間の差は通常,10元 (またはドル) です. 10:01時に,契約Aの閉値が100,契約Bは112,差は12元です. したがって,戦略はヘッジを開始します. ある時点で,価格差が戻り,戦略は2元のリターン利益を得ました.

しかし,実際の状況は, 10:00:45 に契約 A が 100 元の取引を行った場合,その後に取引はなく,契約 B は 10:00:58 に 112 元の取引をした場合, 10:01:00 に両価格も存在しない場合である.この時点で市場価格は何で,ヘッジオペレーションはどのくらい得ることができるのか?私は知りません.可能な状況の一つは: 10:00:58 に,契約 A の待機中の注文価格の 買 1 売 1 101.9102.1戦略の最適化に 大きな誤りをもたらすでしょう

2つ目はマッチメイキング問題です.実際のマッチメイキングは価格優先度と時間優先度です.もし購入者が"販売"価格を超えると,通常は直接"販売"価格で取引します.そうでなければ,待機中のオーダーブックに入力して待機します.Kラインデータには明らかに"購入"と"販売"価格がありません.詳細価格マッチングのレベルをシミュレートすることは不可能です.

最後に,戦略そのものの市場への影響です.少額の資金のバックテストである場合,影響は大きくありません. しかし,取引量が大きい場合,それは市場に影響を及ぼします. 大量の注文をすると価格の滑りが大きくなるだけでなく,長い注文を実行した場合,この種のアクションは実際に購入した他のトレーダーの注文を捕獲します. この効果は定量化できません. 高周波取引は小さな資金しか受け入れられないことを経験からしか言えません.

リアルタイムの深さとティックに基づくバックテスト

リアルレベルのバックテストを提供し,実際の歴史的データを得ることができます.20 layer depth priceリアルタイムで2階Ticks, Each Individual TransactionFMZはこれらの機能に基づいて リアルタイムトランザクション再生機能を作りました

この種のバックテストデータ量は非常に大きく,バックテスト速度も非常に遅いため,通常は2日間しかバックテストできない.比較的高い頻度または時間的な戦略では,実際の市場レベルのバックテストが必要である.FMZが収集した取引ペアと取引時間は非常に長くないが,依然として7000億以上の歴史的データがある.

現在のマッチメイキングメカニズムは,購入オーダーがSell 1より大きい場合,金額を見ることなくすぐに完全にマッチされ,Sell 1より小さい場合は,マッチキューに入って待機するということです.このようなバックテストメカニズムはKラインバックテストの最初の2つの問題を解決しますが,最後の問題を解決することはできません.データ量が大きすぎるため,バックテストの速度と時間範囲は制限されています.

img

注文ごとに取引流量に基づくバックテストメカニズム

価格深さは偽の深さでもあり得ます しかし,ある種のデータがあります. それは市場の実際の取引意欲です.Each Individual Transactionこの記事では,オーダーフローに基づいた高周波バックテストシステムを提案し,実際の市場レベルのバックテストデータの量を大幅に削減し,ある程度は取引量の市場への影響をシミュレートします.

過去5日間の取引をダウンロードしました (ダウンロードアドレス:https://www.fmz.com/upload/asset/1ff487b007e1a848ead.csv2万3000件の取引データがあります.まず,データの構成を見てみましょう.

[['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'],

データとは2次元のリストで,時間順に並べられています. 具体的な意味は以下のとおりです:品種名,取引価格,取引タイムスタンプ,取引量,それが販売注文のアクティブ取引であるかどうか. 買取と販売側があり,各取引には買い手と売り手が含まれます. 買い手は市場である場合.Maker売り手はアクティブですTaker最新のデータはTrue.

まず,取引の方向性により,市場における"1買"と"1売"について,かなり正確に推測することができます.もしアクティブセールオーダーであれば,現時点の"1買"価格は取引価格であり,アクティブセールオーダーであれば",1売"価格は取引価格になります.新しい取引があった場合,すべての価格が更新され,更新されます.更新や更新がない場合,最後の結果は保持されます.上記のデータの最後の瞬間を導入することは簡単です.

注文流量に応じて,次の方法でマッチすることができます: 購入注文を例として,価格price注文量はamount1 を買って売る.bidそしてaskもし,priceより低いaskそしてbid判断されるのはmaker取引価格が,取引価格より低かまたは等しいすべての取引が,取引価格が,取引価格よりも低かまたは等しいすべての取引が,取引価格が,取引価格より低かまたは等しいすべての取引が,取引価格より低かまたは等しいすべての取引が,取引価格より低かまたは等しいすべての取引が,取引価格より低かまたは等しいすべての取引が,取引価格より低かまたは等しいすべての取引が,取引価格より低かまたは等しいすべての取引が,取引価格より低かpriceこの順序にマッチされます (もしprice未満または等しいbid取引価格より低い注文は,取引の優先順位が与えられていない.priceこの順番に一致します.)

配当価格はprice取引の総額である.Each Individual Transactionオーダーが完全に完了するか,オーダーがキャンセルされるまでask評価されています.takerその後に,オーダーが存在している間,すべての取引は,取引価格がpriceこの注文と一致し,マッチ価格は取引価格ですEach Individual Transaction.............makerそしてtaker高周波戦略では,この差を考慮する必要があります. 取引先は,取引先の取引額を削減し,取引先の取引額を削減します.

順序が一致している場合は,takerまず,我々は待機中の注文の量を考慮していない,いくつかのデータがある場合でも,直接取引も価格の深さを変更した判断,市場に影響を与える.

新しい注文のマッチングに基づいて,それは,歴史上の既存の注文をあなたの注文に置き換えることに等しい.いかなる場合でも,それは市場自身の取引量の限界を超えてはならないし,最終利益は市場が生み出す最大利益を超えてはならない.マッチングメカニズムの一部は,注文の量にも影響し,それが戦略の収益に影響を与え,戦略の能力を定量的に反映する.資金の量が倍になり,利益が倍になると,伝統的なバックテストはありません.

注文の購入価格がBuy 1に等しい場合,購入価格がBuy 1に一致する確率は依然としてあるため,この種の状況はここで考慮されません.

対応コード

交換オブジェクトは,基本的には変化せず,最初の引入を参照することができます.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

いくつかの詳細を注意してください:

  • 新しい取引が起こると,まず注文をマッチし,次に最新の価格に従って注文します.

  • 各注文には2つの属性があります. メーカーメーカーの優先順位マッチング優先順位,例えば購入注文の場合,購入価格が1より小さい場合,maker購入価格が1より大きい場合は,Priority matching, priority価格が購入価格に等しいか否かを決定し,メーカーは取引手数料を決定します.

  • についてmakerそしてpriority価格が購入価格より高ければ,残ったボリュームは,市場容量を上回る価格です.maker.

  • 戦略interval市場が遅れている可能性があります.

ネットワーク戦略のバックテスト

予想された結果を達成できるかどうか確認するために,最も古典的なグリッド戦略の1つをバックテストしましょう. 戦略の原則は,価格が1%上昇するたびに,我々は特定の価値のショートオーダー (逆に,我々はロングオーダー) を保持し,購入オーダーと販売オーダーを事前に計算することです.Grid('XTZ', 100, 0.3, 1000, maker_fee=-0.00002, taker_fee=0.0003)パラメータは: 取引ペア,価格は,保持値から1%の偏差,待機注文密度は0.3%です, 睡眠間隔ms,未定の注文料と実行された注文料.

XTZの市場価格は 5日間にショック状態で 電力網には非常に適しています

img

まず,異なる保有ポジションが利益収益に与える影響をバックテストします.従来のバックテストメカニズムによってバックテストされた収益は,保有ポジションの増加に比例して確実に増加します.

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'])

合計4つのグループがバックテストされ,保有ポジションの値は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と10000のポジション価値の相対的収益の比較である:

img

また,待機中の注文密度,睡眠時間,取引手数料など,バックテスト収益に対する異なるパラメータの影響をバックテストすることもできます. නිද眠時間を例として100msに変更し,睡眠時間を1000msに比較して利益の返済を見ることができます.バックテスト結果は以下のとおりです:

{'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}

戦略は,注文のセットのみを送信するため,収益が少し増加した,いくつかの注文は,変更する時間がないため,変動する価格を実行することはできません,睡眠時間の削減は,この問題を解決します.これはまた,複数のセットの注文を配置するためのグリッド戦略の重要性を示しています.

結論から言うと

この記事では,オーダーフローに基づく新しいバックテストシステムを革新的に提案しており,待機中のオーダー,実行中のオーダー,部分実行されたオーダー,遅延などマッチング状況を部分的にシミュレートすることができ,戦略資金の金額の収益への影響を部分的に反映しています.高周波およびヘジング戦略では,重要な基準値を持っています.高精度バックテストは戦略パラメータ最適化の方向性を示しています.また,長い間検証されています.さらに,バックテストに必要なデータの量はよく制御されており,バックテスト速度も非常に速いです.


関連性

もっと