10. プロセスデータ (proc.*) と動的バックテスト (設計仕様)
この章では、qteasy における プロセス データの定義とアクセス方法、バックテスト中の 静的ブランチ と 動的ブランチの選択、およびそれらの間の一貫性規則について説明し、実装および拡張の際の参考にします。使用レベルの説明については、「戦略によるデータの宣言と使用方法」および API ドキュメントと合わせて読んでください。
10.1. 1. 背景与目标
1.1 プロセスデータの意味
一部の戦略は、バックテストまたはライブ取引実行パスによって変化するデータに依存する必要があります。次に例を示します。
現在/過去のポジション、利用可能な現金。
過去の約定数量、約定価格、取引コスト。
ポジションや価格から導き出される時価や総資産など。
このようなデータは、バックテストの開始前に一度に事前生成することはできません。これは実行時にBacktester (バックテスト) または Trader (ライブ取引) によってのみ維持でき、「現在表示されているスコープ」に従ってシグナル生成の各ステップで戦略に提供されます。これを総称して プロセス データと呼びます。
1.2 設計の目的
統合されたエントリ ポイント: 静的な履歴データと同様に、プロセス データは
Strategy.get_data()経由で取得されるため、学習曲線が短縮されます。先読みなし: ステップ k の信号を生成するとき、ストラテジーはステップ k の実行結果を確認できません。完了したステップの履歴のみを使用できます。
バックテスト/ライブの一貫性: バックテストとライブ取引の両方で、同じ戦略セットと同じ
get_data('proc.xxx')呼び出しパターンを使用できます。プロセス データが必要な場合は、動的実行パスに従いますが、それ以外の場合は、結果に関して元の静的パスとの一貫性を保つことができます。
10.2. 2. 过程数据的统一定义(proc.*)
2.1 命名と公開方法
すべてのプロセス データは、
proc.<field_name>(proc.own_cashやproc.trade_recordsなど) の形式でストラテジーに公開されます。プロセス データは、戦略の
__init__のdata_typesを介して宣言する必要はありません**。これは、Backtester / Trader によって実行時に挿入され、ストラテジーは必要に応じてrealize()のget_data('proc.xxx', ...)を呼び出すだけで済みます。
2.2 実装された組み込みフィールド
現在のバージョンに実装され、戦略で使用できるプロセス データ フィールドには次のものがあります。
カテゴリ |
フィールド名 |
意味 |
|---|---|---|
アカウントのスカラー |
|
現在のステップの開始時点での口座内の現金の合計 |
|
現在のステップの開始時に注文に利用できる現金 |
|
|
現在のステップ開始時の総資産市場価値 (ポジション評価 + 現金) |
|
位置ベクトル |
|
現在のステップ開始時の各商品の合計ポジション数量 |
|
現在のステップの開始時の各商品の販売可能数量 |
|
|
現在のステップ開始時の各商品のポジション市場価格 (内部価格とポジションから計算) |
|
実行結果 |
|
各ステップにおける各商品の実際の約定数量 (買いの場合はプラス、売りの場合はマイナス) |
|
各ステップにおける各商品の取引コスト |
|
|
各ステップにおける各商品の約定価格 |
バックテストおよびライブ取引における上記フィールドの時間セマンティクスと可視性の制約については、セクション 4 を参照してください。
2.3 将来拡張可能なフィールド (オプション)
設計によってさらに拡張できるフィールドには、proc.realized_pnl、proc.unrealized_pnl、proc.last_trade_price、proc.last_trade_volume などがあります。詳細については、実装とドキュメントを参照してください。
10.3. 3. 访问接口:Strategy.get_data() 与 proc.*
3.1 静的データ (proc. プレフィックスなし)
単一ソース:
self.get_data('close_E_d');複数のソース:self.get_data('close_E_d', 'high_E_d')。静的データは、
lag/windowパラメータをサポートしません。指定した場合、英語のValueErrorが生成されます。
3.2 プロセスデータ(proc.プレフィックス)
呼び出しの例:
self.get_data('proc.own_cash'): 現在のステップまでの現金シリーズ。self.get_data('proc.own_cash', lag=0): 最新のステップでの現金価値。self.get_data('proc.own_cash', lag='1d'): 1 日を時間ごとに振り返るステップに相当します。self.get_data('proc.own_cash', window='5d'): 過去 5 日間のウィンドウ スライス。
制約:
1 回の呼び出しで許可されるのは 1 つのみ
proc.*フィールドです。複数のフィールドが使用されている場合、または同じ呼び出し内で静的データが混在している場合は、英語のValueErrorが発生します。lagとwindowを同時に指定することはできません。lagは整数 (ステップ) または文字列 (例:'1d'、'8h')、windowは文字列 (例:'5d'、'8h') です。
戻り値: 常に
np.ndarray;形状とデータ型は API ドキュメントに従います。
10.4. 4. 回测分支选择与过程数据协作
4.1 静的ブランチと動的ブランチ
静的分岐 (
_backtest_static_operator): すべてのタイム ステップに対してrun_strategiesを 1 回呼び出してすべての信号を生成し、backtest_batch_stepsなどの Numba ベクトル化関数を使用してバックテストを完了します。プロセスデータに依存しない戦略に適しています。動的分岐 (
_backtest_dynamic_operator): 時間ステップごとにループします。各ステップでシグナルを生成→解析して約定をシミュレート→ポジションとキャッシュを更新し、次のステップに進みます。プロセス データは Backtester によって維持され、各ステップの前に Operator に注入されるため、戦略はget_data('proc.xxx')を介してアクセスできます。
実行前に、Backtester は Operator.check_dynamic_data() を介してどの分岐を取るかを決定します。
4.2 check_dynamic_data()の判定ロジック(現在の実装)
次のいずれかに該当する場合は、True を返し、動的分岐を実行します。
op_type == 'stepwise': Operator は明示的にステップワイズ モードに設定されています。
ストラテジーのソース コードで proc. を使用する*:
_strategies_use_proc_data()は、各ストラテジーのrealize()のソース コードに'proc.'または"proc."が含まれているかどうかを確認します。そうであれば、プロセスデータに依存していると考えられます。
したがって、実現()でget_data('proc.xxx')が呼び出されている限り、宣言なしで自動的に動的分岐を実行します。プロセスデータには、proc.* を介してのみアクセスできます。 DataType を介した宣言はサポートされなくなりました (従来の op_* タイプは削除されました)。
4.3 先読み保証なし
戦略がステップ k でシグナルを生成すると、次のようになります。
口座/ポジション データ (例:
own_cashes、own_amounts) は、最大でインデックス[0..k](つまり、現在のステップの開始時の状態) まで表示されます。取引関連データ (例:
trade_records、trade_cost) は、このステップでまだ発生していない取引を除く として、最大で[0..k-1]まで表示されます。
実装では、Operator の
_current_signal_indexと Strategy の_get_process_data_single()が上記の範囲でスライスされます。 Backtester は、各ステップで信号を生成する前にインデックスを更新し、先読みを行わないようにします。
4.4 BacktesterとOperatorの注入関係
Backtester (動的ブランチ):
_backtest_dynamic_operatorエントリ ポイントで、own_cashes、available_cashes、own_amounts_array、available_amounts_array、trade_records_array、trade_cost_array、trade_price_array、trade_price_dataなどを_process_data_sourcesとして Operator に追加し、_process_time_indexをop_signal_indexに合わせたタイムラインに設定します。Operator:
run_strategy(step_index)では、stg.generate()を呼び出す前に、Strategy が「現在表示されている」プロセス データをスライスするために、group_timing_tableとgroup_merge_typeに基づいて_current_signal_indexを計算して更新します。
4.5 ライブ取引におけるプロセスデータ (Trader)
operator.check_dynamic_data() が True の場合、Trader は _run_strategy() で次の処理を実行します。
当座預金の現金、ポジション、利用可能な数量、現在の価格などを シングルステップ
_process_data_sourcesおよび_process_time_indexに組み立てます (単一のライブ取引実行は 1 ステップとして扱われます)。このステップ内で、ストラテジーは
get_data('proc.own_cash')などを呼び出して、現在の口座/ポジションのビューを取得できます。このステップ内の取引履歴は空であり、「このステップではまだ取引が行われていない」というセマンティクスと一致します。
10.5. 5. 动态/静态路径一致性约定
戦略が プロセス データを使用しない場合、静的ブランチを選択する必要があります。他の理由で動的ブランチを選択する場合、バックテストの結果は、(同じ構成とデータの下で) 静的ブランチと数値的にまったく同じになるはずです。
戦略がデータを使用する場合、動的ブランチを通過する必要があります。そうしないと、
_process_data_sourcesが挿入されず、RuntimeError がトリガーされます。テスト規約:
StaticSignalStg(純粋に静的) とProcAwareButStaticLogicStg(proc を呼び出すがシグナルには使用しない) を使用して、同じ構成の下でバックテストを行い、own_cashes、own_amounts_array、trade_records_arrayなどの数値の一貫性を主張します。tests/test_process_data_api.pyのグループ B を参照してください。
10.6. 6. 测试与文档索引
専用テスト:
tests/test_process_data_api.pyグループ A: 純粋に静的な戦略 / proc.* を使用した戦略の下での
check_dynamic_data()の動作。グループ B: 静的戦略と「プロシージャを呼び出すが論理的に同等」戦略の間の配列の一貫性をバックテストします。
グループ C: 静的マルチソースの
get_dataエラー動作、ラグ/ウィンドウ、proc 単一フィールド、および混合呼び出しの拒否。グループ D:
proc.trade_recordsの先読み検証なし。グループ E: プロセス データに基づく実際の動的戦略パスの正確さ。
プロジェクト メモリ:
.cursor/rules/process-data-and-dynamic-backtest.mdc(実装と規約の概要)。戦略データの概要: 戦略がデータを宣言および使用する方法; バックテストのエントリ ポイントとモード: バックテスト、ライブ取引、最適化。