価格データの空欄を直前の値で埋めたら、バックテストのエラーが消えた。プログラムとしては動いても、投資判断として正しくなったとは限らない。欠けている理由を調べずに補完すると、存在しない約定や、低すぎるリスクを作る可能性がある。
欠損処理の目的は、表を空欄なく埋めることではない。何を観測でき、何を観測できなかったかを正しく表すことだ。休場、売買なし、配信障害、取引停止を分けて扱うだけでも、検証結果の信頼性は変わる。
まず「あるはずの行」を定義する
一分足に空白があっても、その市場が休場なら価格がないのは正常だ。休日や昼休みを含む24時間の連続表を先に作ると、本来不要な時間帯まで欠損と判定してしまう。
取引所のカレンダー、セッション、タイムゾーン、短縮取引日を使って、観測が期待される区間を定義する。その上で行がないのか、行はあるが価格が空欄なのか、価格はあるが出来高がゼロなのかを分ける。見た目が似ていても原因と処理は違う。
売買がなかったことと配信が止まったこと
ある一分間に実際の取引がなければ、約定価格が新しく生まれないことは自然である。しかし取引があったのに受信できなかった場合、何が起きたかは手元のデータだけでは分からない。
気配データや別の公式・正規配信資料、システム稼働記録と突き合わせる。単に同じ価格が並んでいるだけでは「静かな市場」と「停止した配信」を区別できない。価格更新時刻や受信時刻、接続状態を価格と一緒に保存する意味はここにある。

直前値で埋めると何が仮定されるか
前方補完は、最後に観測した値を次の空欄へ引き継ぐ処理だ。評価用の参考価格を持ち回る目的では使える場合がある。しかし、その時間に同じ価格で売買できたことを意味しない。
例えば10時の価格100、10時1分と2分は欠損、10時3分は90だったとする。100、100、100、90と補完すれば、下落は最後の一分へ集中して見える。実際は途中で急落したのか、徐々に下がったのか、いったん上がったのか分からない。
線形補間は未来の値を使う
100と90の間を96.67、93.33でつなげば、滑らかな値下がりに見える。しかしその二つの値を計算するには、後から判明した90が必要だ。10時1分時点で利用可能だった価格ではない。
過去の図を見やすくする用途と、売買判断の入力を作る用途を分ける。将来の観測値を使った補間価格で損切りが成立したことにすれば、実際には利用できなかった価格を売買へ組み込むことになる。補間は数学的に滑らかでも、取引可能性を保証しない。

欠損をゼロ価格で埋めてはいけない
価格の空欄を数値ゼロに置き換えると、100から0への全損、次に90への復帰という、実際には観測されていない動きが生まれる。率の計算ではゼロ除算や無限大も発生する。
出来高ゼロは「その区間に売買数量がなかった」という有効な値になり得るが、価格ゼロは同じ意味ではない。列ごとの意味を理解せず、表全体へ一括でゼロ埋めを行うと、正常な数値と不明な数値が区別できなくなる。
リターンをゼロで埋めるのも別の仮定
欠けた価格から計算できなかったリターンをゼロにする処理も注意が必要だ。値動きがなかったことにすると、平均や標準偏差、連続損失、ドローダウンを変えてしまう。
後で判明した価格差をどの区間へ反映するのかも決めなければならない。欠損区間をゼロにし、再開日の変化まで削除すれば、損失そのものが消える可能性がある。エラーが出る行を落とすだけでは、最も重要な値動きを捨てる場合がある。
売買判定と時価評価でルールを分ける
保有資産の暫定評価には直前の参考値を使い、売買シグナルには一定以上古い価格を使わない、という設計は考えられる。二つの用途で同じ補完列を共有しないことがポイントだ。
価格の元時刻、現在時刻との差、補完の有無を別列へ残す。例えば二分以上古い価格なら新規売買を止めるといった条件を置く場合も、その二分は戦略ごとに検証すべき仮定であって万能な安全基準ではない。既存建玉の管理は別途必要になる。
停止中の損切りを架空の価格で成立させない
売買停止中は通常の連続取引ができない。停止前100、再開80というデータで95の損切りを置いていても、95で売れたとは限らない。補間して95を通過したことにすれば、停止のリスクを消してしまう。
取引再開の方法、注文の扱い、利用できる価格を確認し、分からない場合は実行価格の幅を持たせたストレスを行う。データの欠けた部分を都合のよい約定で埋めるより、損失が不確実であることを明示した方が判断に役立つ。
銘柄一覧から消えた企業を削除しない
現在の銘柄一覧だけで過去データを集めると、上場廃止や合併などで消えた企業が抜けることがある。取得できない銘柄を単に除外すれば、生き残った企業だけの成績になる可能性がある。
当時の投資可能集合を確認し、銘柄コード変更、合併対価、最終取引、上場廃止後の扱いを調べる。情報不足で評価できない場合も、対象件数と理由を残す。「データが取れなかったので除いた」という処理が、結果へどの程度影響するかを確認したい。
欠損率だけで品質を判断しない
欠損が全体の0.1%でも、すべて急落日の寄り付きに集中していれば、戦略へ大きく影響する。一方、取引対象外の時間に多くても、売買結果に関係しない場合がある。
時間帯、銘柄、出来高、値動きの大きさ、イベント日の別に欠損を集計する。欠損が相場と無関係に起きているとは限らない。高負荷時の配信障害など、最も危険な場面ほど記録が失われる場合があることを想定する。
「全部そろった行だけ残す」処理の副作用
百銘柄の表で一銘柄でも空欄のある時刻を削ると、多数の正常な観測も消える。逆に、全銘柄がそろった日だけを選ぶことで、流動性の高い静かな日へ偏る可能性もある。
戦略が本当に必要とする列を特定し、その列の欠損だけで判断する。二銘柄のペアなら両方の価格鮮度が必要だが、無関係な九十八銘柄まで条件に含める理由はない。データの結合方法が取引日を選んでしまわないようにする。
前方補完の長さに上限を置く
分析用途で直前値を引き継ぐ場合も、無制限に何日も持ち回らない。どのくらい古い値まで許すかを定義し、それを超えた区間は不明とする。価格が存在するように見える期間と、実際に更新された期間を分けられる。
pandas等のデータ処理道具は前方・後方補完を提供するが、その金融的な妥当性まで決めてくれるわけではない。時刻の並び、銘柄ごとのグループ、日跨ぎの可否を確認する。別銘柄の最後の価格を次銘柄の空欄へ引き継ぐような実装ミスも防ぎたい。
元データを残して処理を比較する
原本、欠損分類、補完後データ、売買に使ったデータを分けて保存する。欠損区間で新規取引をしない場合、直前値で評価する場合、不利な価格を仮定する場合などを比較し、結論が処理方法に依存していないかを調べる。
一つの補完ルールだけで利益が出るなら、その利益が相場の特徴ではなく処理の産物である可能性を疑う。除外した取引数、変わった約定数、最大損失の差を報告すれば、データ品質の影響を具体的な数字で説明できる。
値が入っていても正しいとは限らない
欠損チェックを通過した価格にも問題はあり得る。高値が安値より低い、終値が足の高値を超える、同じ時刻の行が重複する、取引所時刻が前の行より戻る、といった条件を別に調べる。ただし訂正約定やセッションの定義によって意味が変わるため、検出後は仕様と照合する。
異常値を見つけたら直ちに平均値へ置換するのではなく、原データと受信時刻を保存する。データ提供元の訂正が来た場合も、当時その価格を知っていたかと、現在正しい履歴として何が分かるかを区別する。過去の検証を後からきれいにするだけでは、本番時の判断を再現できない。
保有銘柄の価格が欠けても負担は消えない
二銘柄を50%ずつ保有し、片方の価格が欠損したとする。その銘柄を集計から落として残りを100%へ再配分すると、実際には売れていない資産を売却した扱いになる。ポートフォリオの構成と評価の不確実性を同時に変えてしまう。
保有数量は維持し、評価に使った価格の時刻や暫定性を表示する。新規注文を止めるか、リバランスを延期するかは別の運用規則にする。欠損のために取引できなかった日も、現金やポジションを持ち続けた結果として成績へ残す。
感度分析では都合の悪い結果も残す
補完なし、期限付きの前値補完、該当日の新規売買停止という複数条件を比較し、どれで順位が変わるかを見る。最も高い収益になる処理だけを採用すれば、欠損処理もパラメータ最適化の一部になる。
特に利益の大部分が欠損直後の数回に集中しているなら、その約定が当時実現できたかを個別確認する。全体の欠損率が低いという説明では、その少数の取引の妥当性を代替できない。
空欄は失敗ではなく重要な情報
監査結果には、元の観測数、欠損数、補完数、売買を停止した回数を併記する。補完後の行数だけでは、どれほど観測値へ手を加えたかが分からない。原因別の件数を残せば、相場の特性と配信システムの品質を混ぜずに改善の優先順位を付けられる。
観測できなかった区間を不明として残すことは、分析の放棄ではない。不確実性を見える状態に保ち、取引可能性と評価の限界を区別するための手順である。
バックテストの品質は、行数の多さや空欄の少なさだけでは決まらない。いつ、何を知り、その情報で何ができたかを再現できることが重要だ。欠損を埋める前に、その空白が市場の沈黙なのか、観測側の問題なのかを問うところから始めたい。
参考:pandasの欠損データ処理資料、データ整列・補完の基本機能。補完方法の説明と、売買に使える価格の判断は別の問題。


コメント