3
フォロー
1444
フォロワー

取引ごとの高頻度バックテストシステムとKラインバックテストの欠陥

作成日:: 2020-06-04 16:48:02, 更新日:: 2024-12-10 20:32:01
comments   7
hits   5112

取引ごとの高頻度バックテストシステムとKラインバックテストの欠陥

私はここにいますBinance ショートオーバー上昇、ロングオーバー下落のマルチ通貨ヘッジ戦略バックテストエンジンも同時にリリースされました。最初のレポートでは、1 時間の K ライン バックテストに基づいて戦略の有効性が検証されました。しかし、公開戦略の実際の休眠時間は1秒であり、非常に高頻度の戦略であるため、1時間ごとのKラインでバックテストを行っても正確な結果を得ることは明らかに不可能です。後から追加分単位のバックテストその結果、バックテストの利益は大幅に増加しましたが、第2レベルの状況でどのようなパラメータを使用すべきかを判断することはまだ不可能であり、戦略全体の理解はあまり明確ではありません。主な理由は、K ライン ベースのバックテストの重大な欠点です。

Kラインバックテストの問題

まず、歴史的Kラインとは何でしょうか? K ラインのデータには、始値の高値と終値の安値、2 つの開始時刻、および範囲取引量の 4 つの価格が含まれます。ほとんどの定量プラットフォームとフレームワークは K ライン バックテストに基づいており、FMZ 定量プラットフォームはティック レベルのバックテストも提供します。 K ライン バックテストは非常に高速で、ほとんどの場合問題はありませんが、非常に重大な欠陥もあり、特に多品種戦略や高頻度戦略をバックテストする場合は、正しい結論を導き出すことがほぼ不可能です。

まず、時間の問題です。Kラインデータの最高値と最低値の時間は示されていないため、考慮する必要はありません。しかし、最も重要な始値と終値は、始値と終値から始まるわけではありません。閉店時間です。あまり人気のない取引商品でも、10 秒以上取引が行われないことがよくあります。マルチ商品戦略をバックテストする場合、多くの場合、始値と終値は同時であると想定します。これは、終値のバックテストの基準でもあります。

分線を使って2種類の裁定取引をバックテストするとします。通常、価格差は10元です。10:01に、契約Aの終値は100、契約Bの終値は112で、価格は12元の差。そのため、戦略はヘッジを開始します。この時点で、価格差が戻り、戦略は2元の利益を獲得しました。

実際の状況は、10:00:45に契約Aが100元の取引を生成し、その後取引がなかった可能性があります。10:00:58に契約Bが112元の取引を生成しました。10:01に、両方の価格が存在しないのですが、現時点での市場価格はいくらで、ヘッジすることでどれだけの価格差が得られるのでしょうか?知る方法はありません。考えられるシナリオの 1 つは、10:00:58 に契約 A の売買価格が 101.9 ~ 102.1 であり、2 元の価格差がまったくないというものです。これは、戦略の最適化に大きな誤解を招きます。

2つ目の課題はマッチングです。本当のマッチングでは価格と時間が優先されます。買い手が売り価格を上回った場合、取引は通常、売り価格で直接完了します。それ以外の場合は、注文簿に登録されて待機します。 K ライン データには当然、買値と売値がないため、詳細レベルでのマッチングをシミュレートすることは不可能です。

最後に、戦略自体が市場に与える影響があります。小資本のバックテストであれば、影響は大きくありません。しかし、取引量が大きな割合を占める場合には、市場に影響を与えることになるでしょう。取引が即時実行されると価格のスリップが大きくなるだけでなく、買い注文がバックテストを通じて実行されると、元々購入を希望していた他のトレーダーの取引を実際に先取りし、バタフライ効果が価格に影響を与えることになります。市場。この影響は定量化できず、経験上、高頻度取引は小額の資金しか対応できないとしか言​​えません。

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

FMZはリアルタイムバックテストを提供し、実際の履歴20レベルの深さ、リアルタイムの2番目のレベルのティック、トランザクションごとのデータを取得でき、これに基づいて、リアルタイム再生機能。バックテストデータの量は非常に大きく、速度は非常に遅く、通常は 2 日だけです。比較的高頻度の戦略や厳密な時間判断が必要な戦略の場合、リアルタイムのバックテストが必要になります。 FMZ によって収集されるトランザクション ペアと期間は長くありませんが、履歴データは 700 億件以上あります。現在のマッチングの仕組みでは、買い注文が売り注文より大きい場合は、数量を考慮せずにすぐに完全にマッチングされ、売り注文より小さい場合は、マッチング キューに入ります。このようなバックテストのメカニズムは、K ライン バックテストの最初の 2 つの問題を解決しますが、最後の問題はまだ解決できません。また、データ量が非常に多いため、バックテストの速度と時間範囲が制限されます。

取引ごとの高頻度バックテストシステムとKラインバックテストの欠陥

取引注文フローに基づくバックテストメカニズム

K ラインの情報が少なすぎて、深度が間違っている可能性がありますが、市場の真の取引意図を反映し、最も信頼できる取引履歴、つまり取引ごとの取引を反映するデータが 1 つあります。この記事では、注文フローに基づいた高頻度バックテスト システムを提案します。これにより、リアルタイム バックテストのデータ量が大幅に削減され、取引量が市場に与える影響をある程度シミュレートできます。

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

データはトランザクション時間順に並べられた 2 次元リストです。具体的な意味は、商品名、取引価格、取引タイムスタンプ、取引数量、アクティブな売り注文取引であるかどうかです。買い手と売り手がいて、各取引には買い手と売り手が含まれます。買い手がマーケット メーカーで売り手がテイカーの場合、最後のデータは True になります。

まず、取引の方向に基づいて、市場での買い価格と売り価格をかなり正確に推測することができます。アクティブな売り注文の場合、この時点での買い価格は取引価格です。アクティブな買い注文の場合、売値は取引価格です。新しい取引があれば新しい見積りが更新されます。更新されない場合は、以前の結果が保持されます。上記のデータの最終時点では、購入価格は 2.903、販売価格は 2.904 であったと簡単に推測できます。

注文フローに応じて、マッチングは次のように行われます。買い注文を例にとると、価格は price、注文数量は amount、買い注文と売り注文はそれぞれ bid と ask です。価格が売り注文より低く、買い注文より高い場合、まずメイカーと判断され、最初に取引とマッチングされます。その後、注文の存続時間内に、取引価格が売り注文より低いか等しいすべての取引がこの注文は、価格が売り値より低い場合、取引価格は買い値より高くなります。買い値が売り値と同じか等しい場合、最初に取引することはできません。すべての注文この注文と一致するのは、その価格よりも低い取引価格の注文のみです。一致する価格は価格であり、取引量は注文が完全に実行されるかキャンセルされるまでの各取引の取引量です。価格が売り注文より高い場合はテイカーとみなされます。その後、注文の存続時間内に取引価格が価格以下のすべての取引がこの注文とマッチングされ、マッチング価格は取引の取引価格となります。メイカーとテイカーを区別する理由は、取引所が基本的に注文を奨励し、取引手数料を優遇するからです。高頻度取引戦略では、この区別を考慮する必要があります。

このタイプのマッチングの問題は簡単にわかります。注文がテイカーの場合、実際の状況は、新しい注文が一致するのを待つのではなく、すぐに実行できることです。まず、保留中の注文の量を考慮していませんでした。データがあったとしても、取引を直接判断すると深さが変わり、市場に影響を与えます。新規注文に基づくマッチングは、履歴にある実際の注文を自分の注文に置き換えることと同じです。いずれの場合も、市場自体の取引量の制限を超えることはなく、最終利益は市場が生み出す最大利益を超えることはありません。一部のマッチングメカニズムは注文の取引量にも影響し、それが戦略のリターンにも影響し、戦略の能力を定量的に反映します。資金の額が 2 倍になると利益が 2 倍になるという従来のバックテストは行われません。

細かい点がいくつかあります。注文の買い価格が買い1価格と等しい場合、実際には買い1価格で一致する可能性がまだあります。保留中の注文の優先順位と取引の確率など比較的複雑なのでここでは考慮しません。

一致するコード

取引所オブジェクトは、基本的に変更されていない最初の導入を参照できます。メイカーとテイカーの手数料の差額のみが追加され、バックテストの速度が最適化されます。以下では主にマッチングコードを紹介します。

    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. 新規取引があった場合、まず注文をマッチングさせてから、最新の価格に基づいて注文をする必要があります。
  • 2. 各注文には2つの属性があります。メーカー(メーカーであるかどうか)、優先度(マッチングの優先度)。買い注文を例にとると、買い価格が売り価格よりも低い場合はメーカーとしてマークされ、買い注文価格が買い注文価格より大きい場合、買い注文としてマークされます。優先マッチング、優先順位は価格が入札価格と等しいかどうかを決定し、メーカーが手数料を決定します。
  • 3. 注文のメイカーと優先順位が更新されます。例えば、市場価格を上回る大口の買い注文が出され、ビッド価格を上回る価格が出た場合には、残りの取引量がメイカーとなります。
  • 4. 戦略の間隔は必要であり、市場の遅延を表すことができます。

グリッド戦略のバックテスト

ついに、実際のバックテスト段階に到達しました。最も古典的なグリッド戦略の 1 つをバックテストして、期待どおりの結果が得られるかを確認します。この戦略の原則は、価格が 1% 上昇するたびに、一定の値のショート オーダーを保持し (またはその逆でロング オーダーを保持)、買い注文と売り注文を計算して、事前に発注することです。コードは公開されていません。すべてのコードをカプセル化するGrid('XTZ',100,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)この関数のパラメータは、取引ペア、保有値の 1% の価格偏差、注文密度 0.3%、スリープ間隔 (ミリ秒)、注文作成手数料、注文受取手数料です。

過去 5 日間、XTZ 市場は不安定な局面にあり、これはグリッドにとって非常に適しています。 /アップロード/アセット/1e235fa08ed9dce82a3.png

まず、さまざまなポジション サイズがリターンに与える影響をバックテストします。従来のバックテスト メカニズムによって測定されるリターンは、ポジションの増加に比例して確実に増加します。

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、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 の値で比較したものです。 取引ごとの高頻度バックテストシステムとKラインバックテストの欠陥

また、注文密度、休眠時間、手数料など、さまざまなパラメータがバックテストのリターンに与える影響をバックテストすることもできます。スリープ時間を例にとり、それを 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}

利益はわずかに増加しました。これは、この戦略では注文を 1 セットだけ行うためです。一部の注文は、時間内に変更できないため、変動する価格から利益を得ることができません。休止時間の短縮により、この問題は改善されました。これは、グリッド戦略で複数の注文グループを配置することの重要性も示しています。

要約する

この論文では、注文フローに基づいた新しいバックテストシステムを革新的に提案しています。このシステムは、保留中の注文、注文の取得、部分的な取引、遅延などのマッチング状況を部分的にシミュレートし、戦略資金がリターンに与える影響を部分的に反映することができます。ヘッジ戦略の基準値、および高精度のバックテストにより戦略パラメータを最適化する方向性が示されます。長期にわたる実際の取引を通じても検証されています。また、バックテストに必要なデータ量も適切に制御され、バックテストの速度も非常に高速です。