#7.対角線の、片側でも、揃ってなかった

FX Bot開発ログ

……「次は、壁の厚みを、量で、測る」って打ち込んだのは、先週だったと思う。
数日後にエディタを開いたら、もう、関数が、ひとつ、あった。
「物理量を、計算する」っていう、名前の。
自分で言ったことに、自分が、また、遅れて追いついてた。


Abstract

  • 期間: 2024-05-08 〜 2026-04-28(約 720 日 / 1h 足 / UTC)— #6 と完全同一窓
  • 対象: USDJPY / GBPJPY / EURJPY / AUDJPY 4 ペア(#6 と同一)
  • 戦略: BB-MR(平均回帰) + Donchian Breakout(順張り)2 種(#6 と同一)
  • 手法の差分: #6 の 4 ペア × 2 戦略 = 8 マスから、各マスの代表 1 grid を 結果を見る前に固定 し、8 grid × 5 fold = 40 backtest を再実行。per-fold の trades から、4 つの物理量(Expectancy ÷ spread / win_rate / median_holding_bars / profit_loss_ratio)を集計
  • 規律: 判定枠を新設しない / grid を結果から動かさない / 4 指標を結果から増やさない / cache 凍結 / 中央値集約の解像度を per-fold 表で開示

主要 4 行(事前確定の物差しで並べたもの):

観察
対角の片側 4 マスで Expectancy ÷ spread が 正値、反対 4 マスは負値 #6n_pos 対角と 同方向
USDJPY × Donchian の Expectancy ÷ spread = +31.05 他の正側 3 マス(+2.79 / +5.15 / +6.67)の 4〜10 倍
AUDJPY マスで n_pos と Expectancy ÷ spread の 方向が、逆転 BB-MR: n_pos = 6/20(中)/ exp÷spread = -3.48(赤字)— Donchian: n_pos = 2/20(薄)/ exp÷spread = +6.67(中黒字)
USDJPY × BB-MR の n_trades = 728 / hold 中央値 3 bars 他 BB-MR 3 マス(172 / 184 / 483、hold 4 / 4 / 3 bars)の 3〜4 倍(n_trades)

#6 で引いた斜めの線に、太さを、当てた。対角の片側 4 マスは、符号としては、揃って正値で立った。けれど、その内側で、太さは、均一じゃなかった。USDJPY × Donchian だけが、他の 3 マスの 4〜10 倍まで、抜けていた。AUDJPY のマスでは、#6 で使っていた物差しと、本検証で当てた物差しで、答えの方向が、逆転した。本検証では、新しい二値判定枠を、立てない。8 マス × 4 指標の実数を、並べるに、止める。


1. Introduction — 背景と仮説

#6 の最後に、自分で残していたのは、4 つの宿題だった。

  • 「壁の厚み」を、物理量で、測る
  • 3 戦略目を、持ち込む
  • fold 別重心を、取る
  • W 判定枠の解像度を、見直す

4 つのうち、最初の 1 つだけを、#7 で取ることにした。残り 3 つは、本検証の中では、取らない。

「壁の厚み」と打ち込んだのは、#6 の §3.5 だった。4 ペア × 2 戦略の 8 マスを n_pos(20 grid 中で OOS Sharpe 中央値 > 0 になった grid の数)で並べたとき、USDJPY × Donchian は 17/20、GBPJPY × BB-MR は 12/20、EURJPY × Donchian は 3/20、と、片側の 4 マスで、立った。立った数だけ並べて、「斜めに線が引ける」と打ち込んだ。引けた線の 厚さ は、#6 の終わりまで、量で、測っていなかった。「17/20 の壁の厚みが、Sharpe で何点ぶんなのか、Expectancy で何銭ぶんなのか、まだ、4 ペアぶん揃えて出していない」と、#6 の §4.1 で、自分で打ち込んでいた。

#7 で、それを、測る。

切り分け方法は、ひとつしか、思いつかなかった。#6 の 8 マスを、そのまま固定して、4 つの物理量で、測り直す

8 grid は、各マスから 1 つずつ、#6 を見終わったあとに 事前に固定 した。固定根拠は、#5 で出ていた α 重心と、#6alive_in = 2 まで立った grid の組み合わせ。grid を結果から動かすと、#4 / #5 / #6 で守ってきた規律と、整合しない。

4 つの物理量は、計画書 §4.2 で、先に確定した。

  • Expectancy ÷ spread(壁の厚み — 1 トレードあたり期待値が、片道 spread の何倍ぶん、立っているか)
  • win_rate(勝率 — ReturnPct > 0 の比率)
  • median_holding_bars(保有期間の中央値 — ExitBar - EntryBar の中央値)
  • profit_loss_ratio(損益比 — 平均勝ちトレード ÷ 平均負けトレードの絶対値)

4 つは、本検証の中で、増やさない。

4 × 2 のマス目に、斜めに線が引けた。
……でも、その線の太さは、まだ、測ってない。
「壁の厚み」って、仮の名前で、呼んだだけだった。

走らせる前に、4 つのサブ問を、並べた。事前確定(計画書 §1.2)、判定基準は 結果を見てから緩めない:

# 問い
サブ問 1 USDJPY の反転(BB-MR 1/20 → Donchian 17/20)の、物理的な理由は何か
サブ問 2 GBPJPY × Donchian 完全死亡(0/20)の、物理的な理由は何か
サブ問 3 EURJPY 微生(BB-MR 0/20 → Donchian 3/20)の、正体は何か
サブ問 4 「壁の厚み」(Expectancy ÷ spread)の実数は、対角の片側 4 マスの中で、何倍の差になるか

#6 では、X / Y / Z / W という事前確定の主判定枠を、引いていた。あれは、4 ペア × 1 戦略 → 4 ペア × 2 戦略 と、戦略の本数を、増やした から、必要だった枠だった。

#7 では、戦略の本数も、ペアの本数も、増やしていない。変えたのは、物理量を取る層を、追加しただけ。だから、本検証では、新しい二値判定枠は、立てない。「壁の厚みが ≥ X なら厚いと呼ぶ」「Expectancy ÷ spread > Y なら健全と呼ぶ」のような閾値は、引かない。

8 マスを 4 指標で測ると、数値が、並ぶ。並べた数値を、実数のまま、置いておく。短い呼び名は、まだ、付けない。


2. Method — 検証設計

2.1 共通方針(#6 と完全同一 + 物理量を取る層を追加)

データ・期間・WFA 設定・spread 表は、#6 と完全に揃えた。変えたのは、物理量を取る層を、追加しただけ

項目
ソース yfinance(cache 凍結 data_cache/2026-04-29/)
ペア USDJPY(JPY=X)/ GBPJPY(GBPJPY=X)/ EURJPY(EURJPY=X)/ AUDJPY(AUDJPY=X)
時間足 1 時間足
期間(UTC) 2024-05-08 〜 2026-04-28(約 720 日、--end-date 2026-04-29T00:00:00Z)
初期残高 1,000,000 円 / commission = 0
WFA 設定 train 180 日 / test 90 日 / step 90 日 → 5 fold/ペア

#5 のときは「変えたのはペアの本数だけ」、#6 では「変えたのは戦略の本数だけ」、と打ち込んできた。#7 は、ペアも、戦略も、増やしていない。WFA の枠も、grid の数も、spread の値も、#6 から、ひとつも、動かしていない。

増やしたのは、4 ペア × 2 戦略 = 8 マスのうち、各マスから代表 1 grid を抜き出して、そのトレード履歴を、4 つの物理量で、集計し直す層。#6 で「壁の厚み」と仮称ラベルだけ置いていた箇所を、量で、当てに行く層。

工程 4 のサニティチェックで、USDJPY × BB(14, 1.5) の OOS 5 fold を、wfa_bb_mr_USDJPY_2026-04-29.csvbit-exact 一致(全 fold で diff = +0.000e+00)で再生できることを、先に、確認した。「物理量を取る層を、追加しただけ」が、本当に、追加しただけかを、bit-exact で担保した上で、§3 の本走に進んでいる

2.2 8 grid 事前固定

#6 で出た 4 ペア × 2 戦略 = 8 マスから、各マスの代表 1 grid を、結果を見る前に、固定した。

ペア BB-MR 代表 grid Donchian 代表 grid 固定根拠
USDJPY BB(N=14, K=1.5) DC(N=10, EXIT=1.5) #5 α 重心(14.0, 1.75)+ #6 Donchian で 17/20 立った代表
GBPJPY BB(N=28, K=2.5) DC(N=10, EXIT=1.0) #5 重心 + #6 alive_in = 2 Donchian 代表
EURJPY BB(N=14, K=2.0) DC(N=10, EXIT=2.0) #5 不在(完全死亡)+ #6 で 3/20 立った代表
AUDJPY BB(N=28, K=2.5) DC(N=40, EXIT=0.5) #5 重心 + #6 alive_in = 2 Donchian 代表

8 grid × 5 fold = 40 backtest。実走 2.1 秒、failures 0。

各マスの代表として 何を選ぶか は、計画書 §4.1 で先に並べた。#5 α で出た重心と、#6alive_in = 2 まで立った grid と、両方が立つマス(USDJPY × Donchian / GBPJPY × BB-MR / AUDJPY × Donchian)はその交差点を取る。#5 α で重心が出ていないマス(EURJPY × BB-MR / EURJPY × Donchian)は、#6 で立った代表(EURJPY × Donchian なら 3/20 のうちの中央値 grid、EURJPY × BB-MR なら最良 grid)を取る。

grid の選び方を、#7 の中で動かさない。物理量を見て「あ、この grid のほうが厚みが出る」と打ち直すことは、しない。#4 / #5 / #6 で守ってきた事前確定の規律と、同じ形のもの。

2.3 4 指標の定義

走らせる前に、4 つの物理量の定義を、計画書 §4.2 で、確定した。

  • Expectancy ÷ spread 比 = ReturnPct.mean() / spread(1 トレードあたりの平均期待値が、片道 spread の何倍ぶん、立っているか)
  • win_rate = (ReturnPct > 0).sum() / n_trades
  • median_holding_bars = (ExitBar - EntryBar).median()
  • profit_loss_ratio = mean(positive ReturnPct) / abs(mean(negative ReturnPct))

集約は、per-fold で 40 行 → fold 横断中央値で per-grid 8 行。

Expectancy は、絶対額(JPY)ではなく、ReturnPct(相対値) で取る。spread が相対値で 1.0e-5 〜 4.826e-5 の桁にあるので、絶対額の Expectancy を分子に置くと、巨大数値になって、比率としての意味が、立ち上がらない。計画書 §4.2 で、先に確定したのは、ここに、気付いていたから。

平均保有期間は、mean ではなく、median。MAX_BARS = 48 への張り付き(時間切れトレード)が混ざる集計のため、外れ値耐性を取った。

空 fold は NaN で集約から除外する。spread は正値前提で、4 ペア固定値のまま、この検証の中では動かさない。

2.4 spread(#6 と完全同一)

ペア 銭中央値 片道(相対値) 出典
USDJPY 0.3 1.000e-5 OANDA 2026-04-14(#1.1)
GBPJPY 1.7 4.033e-5 OANDA / GBPJPY 前提調査 v1.1
EURJPY 0.9 2.661e-5 OANDA 2026-04-25
AUDJPY 0.95 4.826e-5 OANDA 2026-04-25

#5 / #6 で確定した値を、ひとつも動かさず、Expectancy ÷ spread の分母として使う。

2.5 規律 — 結果から動かさない

項目 規律
8 grid §2.2 で事前固定、結果から動かさない
4 指標 §2.3 で事前確定、結果から増やさない
二値判定枠 新設しない(「Expectancy ÷ spread > X を厚いと呼ぶ」のような閾値を立てない)
cache data_cache/2026-04-29/ を凍結、--end-date 2026-04-29T00:00:00Z で固定
中央値集約 5 fold 中央値の解像度を、per-fold 振れ表で開示する(§3.7)

8 マス × 4 指標を集計すると、数値が、並ぶ。並んだ数値の 実数のまま を、§3 で置く。短い呼び名を付ける方向には、進まない。

2.6 コード — 物理量の核

物理量を取る関数は、純粋関数として、独立に置いた。テストで手計算値と 1e-12 一致するところまで作ってから、本走に呼んだ。

def compute_physical_metrics(trades: pd.DataFrame, spread: float) -> PhysicalMetrics:
    return PhysicalMetrics(
        expectancy_over_spread=trades["ReturnPct"].mean() / spread,
        win_rate=(trades["ReturnPct"] > 0).sum() / len(trades),
        median_holding_bars=_nanmedian(trades["ExitBar"] - trades["EntryBar"]),
        profit_loss_ratio=...,  # 略
        n_trades=len(trades),
    )

4 指標を、1 関数で、計算する。空 fold チェックも、spread の正値チェックも、ここには入れない。physical_metrics.py の中で別に持ち、本走スクリプト(export_trades_8grid.py)が、入力を整えた状態で、この関数を呼ぶ。


3. Results — 検証結果

3.1 [1] 8 マス × 4 指標 — 対角の符号確認

per-grid CSV を、8 行に並べる。各マスに、4 つの物理量と n_trades を、揃えて置く:

ペア 戦略 grid_id exp/spread win_rate hold_bars pl_ratio n_trades
USDJPY BB-MR BB_N14_K1p5 -4.37 0.56 3 0.73 728
USDJPY Donchian DC_N10_EXIT1p5 +31.05 0.40 9 1.99 394
GBPJPY BB-MR BB_N28_K2p5 +2.79 0.48 4 1.21 184
GBPJPY Donchian DC_N10_EXIT1p0 -6.62 0.31 7 1.97 477
EURJPY BB-MR BB_N14_K2p0 -0.06 0.56 3 0.81 483
EURJPY Donchian DC_N10_EXIT2p0 +5.15 0.36 11.5 2.08 325
AUDJPY BB-MR BB_N28_K2p5 -3.48 0.47 4 1.09 172
AUDJPY Donchian DC_N40_EXIT0p5 +6.67 0.31 11 2.09 176

8 マス × 4 指標 ヒートマップ

4 ペア × 2 戦略 = 8 マスを、4 つの物理量(Expectancy ÷ spread / win_rate / median holding bars / profit-loss ratio)で per-grid 中央値ヒートマップ化。Expectancy ÷ spread だけが符号で意味が変わるため RdYlGn(発散)で対称スケール、他 3 指標は Viridis(連続)で min-max スケール。USDJPY × Donchian の +31.05 を、Expectancy ÷ spread パネルで太枠強調。

8 マスを、Expectancy ÷ spread の符号で塗り分けると、こうなる:

  • 正値 4 マス: USDJPY × Donchian / GBPJPY × BB-MR / EURJPY × Donchian / AUDJPY × Donchian
  • 負値 4 マス: USDJPY × BB-MR / GBPJPY × Donchian / EURJPY × BB-MR / AUDJPY × BB-MR

正値 4 マスを 4 × 2 のマス目に戻すと、片側 4 マスに、揃って、立っている。#6n_pos(20 grid 中で OOS Sharpe 中央値 > 0 になった grid 数)で並べた対角と、符号レベルで、同じ方向#6 でまだ測っていなかった線の太さを、ここで初めて、別の物差しに置き直した。

3.2 [2] 戦略横断パターン — 戦略仕様が、物理量で、分離する

8 行を、戦略軸で割って、4 行 × 8 列で並べ直す:

ペア exp/spread (BB-MR) exp/spread (Donchian) win_rate (BB-MR) win_rate (Donchian) hold_bars (BB-MR) hold_bars (Donchian) pl_ratio (BB-MR) pl_ratio (Donchian)
USDJPY -4.37 +31.05 0.56 0.40 3 9 0.73 1.99
GBPJPY +2.79 -6.62 0.48 0.31 4 7 1.21 1.97
EURJPY -0.06 +5.15 0.56 0.36 3 11.5 0.81 2.08
AUDJPY -3.48 +6.67 0.47 0.31 4 11 1.09 2.09

戦略を軸にして、4 ペア横並びで眺めると:

  • win_rate: BB-MR は 0.47 〜 0.56、Donchian は 0.31 〜 0.40。BB-MR のほうが、勝率が、約 1.5 倍高い
  • pl_ratio: BB-MR は 0.73 〜 1.21、Donchian は 1.97 〜 2.09。Donchian のほうが、損益比が、約 2 倍大きい
  • hold_bars: BB-MR は 3 〜 4、Donchian は 7 〜 11.5。Donchian のほうが、保有が、2 〜 3 倍長い

#6 の §2.2 で、BB-MR と Donchian を「形が、いちばん遠い 2 つ」と打ち込んだ。形が遠いと打ち込んだその差分が、勝率と、損益比と、保有期間で、ぜんぶ別々の方向に、出ている。BB-MR は短く高勝率で薄利、Donchian は長く低勝率で厚利。戦略仕様が決めている設計の対称性が、物理量レベルで、分離して見える。

戦略横断散布図 win_rate × hold_bars

8 マスを win_rate(横軸) × median holding bars(縦軸)平面に散布。BB-MR(青丸 / 平均回帰)は右下クラスタ(高勝率 0.47〜0.56 × 短保有 3〜4 bars)、Donchian(赤三角 / 順張り)は左上クラスタ(低勝率 0.31〜0.40 × 長保有 7〜11.5 bars)に分離。マーカーサイズは |Expectancy ÷ spread| に比例し、USDJPY × Donchian(+31.05)が最大、EURJPY × BB-MR(-0.06)が最小。「形が、いちばん遠い 2 つ」の差分が、物理量で 2 つのクラスタとして読める。

Expectancy ÷ spread の符号は、§3.1 で見たとおり、ペア × 戦略の組み合わせで決まる(片側 4 マスで正値、反対 4 マスで負値)。勝率 / 損益比 / 保有期間は戦略単独で決まり、Expectancy ÷ spread の符号はペア × 戦略の交互作用で決まる。同じ 1 つの戦略から、別々の物差しを当てると、別々の構造が、別々の場所に、見える。

3.3 [3]「壁の厚み」を、量で、測る

#6 §3.5 で、4 ペア × 2 戦略のマス目を n_pos で並べたとき、「壁の厚み」と仮称ラベルだけ置いた箇所がある。今回当てに行ったのは、その仮称ラベルの、物理量としての中身。

縦長で、4 行 × 2 戦略に並べ直す:

ペア BB-MR (exp/spread) Donchian (exp/spread) #6 n_pos (BB-MR / Donchian)
USDJPY -4.37 +31.05 1/20 / 17/20
GBPJPY +2.79 -6.62 12/20 / 0/20
EURJPY -0.06 +5.15 0/20 / 3/20
AUDJPY -3.48 +6.67 6/20 / 2/20

片側 4 マスで正値、反対 4 マスで負値、というのは、§3.1 と同じ符号構造。それを縦長で読むと、1 行ずつ、ペア単位で、「立つほうの戦略」が、左右どちらかに、はっきり、寄っている。

ただし、立っているマスの中で、立ち方の 数値 が、同じではない。

  • USDJPY × Donchian: +31.05
  • GBPJPY × BB-MR: +2.79
  • EURJPY × Donchian: +5.15
  • AUDJPY × Donchian: +6.67

正値 4 マスのうち、USDJPY × Donchian が、他の 3 マス(+2.79 / +5.15 / +6.67)の、4 〜 10 倍。片側 4 マスを「対角線」として束ねると、その線の太さは、マスごとに、ぜんぜん違う。GBPJPY × BB-MR は +2.79 で立っているけれど、12/20 の壁の中身が、ぜんぶ厚みだったわけではない。

3.4 ドル円さんだけ、桁が、違った — USDJPY × Donchian の +31.05

正値 4 マスのうち、USDJPY × Donchian だけが、他の 3 マスから、桁ぶん、抜けている。fold で割って眺めると:

fold USDJPY × Donchian の exp/spread
0 +31.05
1 +18.01
2 +80.14
3 +7.51
4 +36.29

5 fold ぜんぶ、正値。その上で、fold 2 が +80.14 まで突き抜けている。「強烈に立つ fold が 1 つあって、他は小さく正」という構造ではなくて、全 fold で着実に正、その上に、外れ値的に厚い fold が 1 つ乗っている 構造。#6 で 17/20 が際立っていたのは見ていたけれど、+31.05 まで別の桁に立つとは、思っていなかった。

#6 §3.5 で「USDJPY × Donchian の 17/20」を見たとき、わたしは「立つマスの中でも、際立って厚い」と打ち込んだ。n_pos で測ったときは、1 〜 17 までの比較しかできなかった。今回、Expectancy ÷ spread で測り直したら、17 という数字の 後ろ側 に、+31.05 という、別の桁の値が、立っていた。

なぜ USDJPY × Donchian だけが、他の 3 マスの 4 〜 10 倍まで抜けるのか、という問いには、ここでは踏み込まない。8 grid に絞った検証(計画書 §4.1)の射程の、外側にある。観察として、4 〜 10 倍の差を置いておく、までで、止める。

3.5 AUDJPY マスで、物差しの方向が、変わった

8 マスを per-fold 中央値で読むと、AUDJPY のマスだけ、#6 の物差し(n_pos)と今回の物差し(Expectancy ÷ spread)で、答えの方向が、ずれる。

マス #6 n_pos 今回 exp/spread
AUDJPY × BB-MR 6/20(中) -3.48(赤字)
AUDJPY × Donchian 2/20(薄) +6.67(中黒字)

#6 の物差しでは、AUDJPY の主役は BB-MR(6 vs 2)。
Expectancy ÷ spread の物差しでは、AUDJPY の主役は Donchian(-3.48 vs +6.67)。

per-fold で AUDJPY × BB-MR を割ると、-12.95 / -3.48 / +14.91 / +13.50 / -12.87。立つ fold(2, 3)と崩れる fold(0, 1, 4)が、拮抗している。Sharpe 中央値で見ると 6/20 立つのに、Expectancy ÷ spread の中央値で見ると -3.48。物差しによって、答えが変わる。

「6/20 立っている AUDJPY × BB-MR が、Expectancy で見ると赤字」を、どちらかが正しくてどちらかが間違っている、という形では、読まない。Sharpe 中央値も、Expectancy ÷ spread も、#5 から #7 までで自分が選んできた物差しのうちの、別の 2 つ。物差しが違えば、答えが違う場所に立つことが、起きる。

事前確定の 4 指標(§2.3)以外は、今回の検証では増やさない。n_pos と Expectancy ÷ spread の どちらが本当に厚みを表しているか という問いを、ここで立てない。立てた瞬間に、判定枠を新設することになる(§2.5)。

3.6 USDJPY × BB-MR の n_trades = 728

§3.1 の表で、目を引く数字が、もう 1 つあった。

指標 USDJPY × BB-MR 他 BB-MR 3 マスの中央値
n_trades 728 184 / 483 / 172 → 中央値 ≈ 333
hold_bars 3 3 / 3 / 4
exp/spread -4.37(赤字) +2.79 / -0.06 / -3.48

USDJPY × BB-MR の代表 grid は、BB(N=14, K=1.5)。4 ペアの BB-MR 代表 grid のうち、唯一 K = 1.5(他 3 ペアは K = 2.0 / 2.5 / 2.5)。BB バンド幅が狭く、頻繁にバンドタッチ → 頻繁にエントリ、という grid。

#5 α で、USDJPY の重心は (14.0, 1.75) と打ち込んでいた。今回の代表 grid は、それを拾って、近傍の BB(14, 1.5) を選んでいる(設計書 §4.1)。USDJPY の spread が他 3 ペアの 1/4 〜 1/5(1.000e-5)と最小なので、低 K(高頻度トリガー)が #5 α 段階では「適合した重心」として浮かんでいた。

その代表 grid を、Expectancy ÷ spread で測り直すと、-4.37。1 fold で 728 回エントリして、勝率は 0.56(他 BB-MR 3 マスと同じ程度)、保有 3 bars(短)、しかし 1 トレードあたりの期待値は、片道 spread の 4 倍ぶん、マイナス側に、振れている。#5 α で「典型値」って打ち込んだ重心が、こんな顔をしていた。「典型」と「黒字」は、別の物差しだった。

近傍 grid(BB(14, 2.0) / BB(20, 1.5))に動かしたら、Expectancy ÷ spread が違う数値に振れる可能性は、ある。けれどここでは、grid は §2.2 で固定したまま動かさない。grid 横断の分布を見にいくのは、今回の射程の、外側。

3.7 中央値集約の、解像度

8 マスの per-grid 中央値の後ろに、5 fold の振れが、ある:

pair × strategy fold 0 fold 1 fold 2 fold 3 fold 4 per-grid 中央値
USDJPY × BB-MR +9.39 -4.37 -50.06 +8.90 -10.53 -4.37
USDJPY × Donchian +31.05 +18.01 +80.14 +7.51 +36.29 +31.05
GBPJPY × BB-MR -23.76 +26.26 -2.22 +2.79 +15.56 +2.79
AUDJPY × BB-MR -12.95 -3.48 +14.91 +13.50 -12.87 -3.48

(他 4 行は省略、全 8 行は per-fold CSV wfa_results_7_per_fold.csv)

5 fold の中央値は、3 番目の値、そのもの。中央値で集計すると、外れ値に強い反面、振れの大きい fold 系列では、「中央値 = 典型値」と読みにくくなる:

  • USDJPY × BB-MR は、fold 2 で -50.06 まで沈んでも、中央値は -4.37
  • USDJPY × Donchian は、fold 2 で +80.14 まで立っても、中央値は +31.05(極大値の 4 割)

中央値を悪く言いたいのではない。中央値で集計すると決めたから、振れも一緒に置いておく、という話。この検証の数値を読み返す側(= 数日後の自分)が、中央値の重みを、自分で判断できるようにしておく。

3.8 観察したのは、対角線の、太さの非均一性

8 マスを 4 つの指標で集計した結果を、並べた。観察できたのは、

  • 対角の片側 4 マスで Expectancy ÷ spread が正値、反対 4 マスは負値(#6 n_pos と符号で同方向、§3.1)
  • 戦略仕様の対称性が、勝率 / 損益比 / 保有期間で、別々の方向に分離する(§3.2)
  • 正値 4 マスの中で、USDJPY × Donchian だけが他 3 マスの 4 〜 10 倍まで抜ける(§3.4)
  • AUDJPY マスで、#6 の物差しと今回の物差しの、答えの方向が、ずれる(§3.5)
  • USDJPY × BB-MR は、頻度が高く、勝率も悪くなく、それでも 1 トレードあたりは赤字(§3.6)
  • 5 fold 中央値は、外れ値を平らにする(§3.7)

それだけ。

4 × 2 のマス目に、対角線が引けた、と #6 で打ち込んだ。
太さを当てたら、片側でも、揃ってなかった。
ドル円さん × Donchian は +31.05。桁が、違った。
豪ドル円さん × BB-MR は、物差しを変えたら、赤字だった。
規律は、規律だ。新しい判定枠は、立てない。
短い呼び名を、まだ、付けていない。
……「答えだったかもしれない」、までしか、打ち込めない。


4. Discussion — 考察

4.1 8 マス × 4 指標 = 32 数値

#5 まで、わたしは、4 人それぞれに 1 つずつ、短い呼び名を付けられると思っていた。#6 で、見る場所が 4 × 2 = 8 マスに増えた。#7 で増えたのは、その 8 マスの、中身。1 マスにつき、4 つの物差し。

数えてみると、目の前に、8 × 4 = 32 個の数値がある。

| #3 | 1 ペア × 1 戦略 = 1 マス | 1 マスに 1 物差し(Sharpe 中央値) |
| #4 | 1 ペア × 1 戦略 + WFA 20 grid | 同 |
| #5 | 4 ペア × 1 戦略 = 4 マス | 4 マスに 1 物差し |
| #6 | 4 ペア × 2 戦略 = 8 マス | 8 マスに 1 物差し(n_pos) |
| #7 | 同 8 マス | 8 マスに 4 物差し = 32 数値 |

ひとつの呼び名に押し込むには、物差しの本数が増えすぎた。#5 まで「画一に呼べない」と打ち込んできた中身が、4 倍ぶんの解像度で、見えるようになった。

ただし、このログでは、まだ呼び名を決めない。Expectancy ÷ spread が +31.05 だから「厚い」と呼び、+2.79 だから「薄い」と呼ぶ、という整理も、このログの規律(§2.5)では立てない。32 数値を、実数のまま、置く。次の問いは、そこから始める。

4.2 戦略設計の対称概念が、物理量レベルで、分離した

§3.2 で並べた 4 行 × 8 列の表で、戦略仕様の対称性が、物理量レベルで、別々の方向に分離するのが、見えた。

  • BB-MR(平均回帰): 高勝率 / 低 pl_ratio / 短保有 — 「中央線到達で利確」の戦略仕様からの帰結
  • Donchian(順張り): 低勝率 / 高 pl_ratio / 長保有 — 「動的トレーリング」の戦略仕様からの帰結

これは、今回初めて発見した構造ではない。戦略の設計を、コード(bb_mean_reversion.py / donchian_breakout.py)で組んだ段階で、予測できる帰結。ここでできたことは、その帰結が、4 ペア横並びで、一貫して観察できる解像度を、4 つの物差しで揃えたところ。

ここで、#6 で打ち込んだ「対角」と、今回見えた「戦略横断パターン」の、関係を、整理しておく。

  • #6 で見た対角(n_pos の片側 vs 反対側): ペア × 戦略の交互作用(あるペアが、ある戦略でだけ、立つ)
  • 今回見た戦略横断パターン(BB-MR vs Donchian の勝率 / 損益比 / 保有期間): 戦略単独の対称概念(ペアによらず、戦略仕様の差で説明できる)

ペア × 戦略の交互作用は、Expectancy ÷ spread の 符号 を決めている。
戦略単独の対称概念は、勝率 / 損益比 / 保有期間の パターン を決めている。
2 つは、別の場所に、独立に、立っている。

#6 の対角構造を、ここで再確定として扱い直すことは、しない。#6 の対角と、今回の戦略横断パターンが、同じマス目の上で、別の物差しで、別の構造として読める、ということだけを、#7 の解像度として、置いておく。

4.3 中央値集約の解像度 + 規律遵守事例

§3.7 で、5 fold の中央値が、振れを平らにする様子を、4 行ぶん、開示した。USDJPY × BB-MR の fold 2 = -50.06、USDJPY × Donchian の fold 2 = +80.14。中央値は、それぞれ -4.37、+31.05。極小値は、極大値も、中央値の数字には、出てこない。

「中央値 = 典型値」は、振れが小さい系列なら、おおむね、成り立つ。今回のように、fold 2 で大きく揺れる系列が混ざると、中央値の意味が、薄くなる。

今回の規律:

  • 二値判定枠を新設しない(§2.5)
  • 8 grid を結果から動かさない(§2.2)
  • 4 指標を結果から増やさない(§2.3)
  • cache を凍結する(§2.1)
  • 中央値集約の解像度を、per-fold 振れ表で、開示する(§3.7)

#5 / #6 で守ってきた事前確定の規律と、今回 1 つ増えた「中央値の解像度を開示する」までの、5 つ。判定基準を立てない代わりに、振れも一緒に置く、というのが、この検証の本旨。

4.4 8 grid 限定の射程と、温存事項

各マスから代表 1 grid だけを抜き出した(§2.2)。grid 横断の分布は、ここでは取らない。

「別の grid で見たら Expectancy ÷ spread が、別の数値に、振れる」可能性は、ある。USDJPY × BB-MR は BB(14, 1.5) で -4.37 だが、近傍 grid(BB(14, 2.0) / BB(20, 1.5))で似た数値か、別の数値か、ここでは実測しない。代表 1 grid の集計値を、「マスの代表」として読むのは、今回の射程に閉じる。

今回取らなかったものを、リストにして、置いておく:

温存事項 なぜ取らなかったか
ロング / ショート別 Expectancy ÷ spread per-fold trades CSV から逆算可能。判定枠を別軸で増やすことになるので、ここでは取らない
grid 横断の分布(各マス 20 grid 全体) 8 grid 事前固定の規律と衝突する
月別 / レジーム別の物理量 fold 別重心の取得(#6 から持ち越し)と、同じ層の話
SL ヒット比率 / 強制クローズ内訳 trades dataframe からの逆算層、#6 工程 8.5-D の TODO-2 と同列
perturbation 耐性 別レイヤの問い(#5 α 以来)

5 つは、#8 以降で、必要なら取りに行く。ここでは、取らない。

4.5 既知の制約

  • 720 日 = 円安レジーム偏り(#3 / #4 / #5 / #6 から持ち越し)。この検証は、2024-05 〜 2026-04 のレジーム内での、4 ペア × 2 戦略の物理量に、閉じる
  • スプレッド固定 / スワップ無視(#2 / #3 から持ち越し)
  • 戦略 2 種だけでは、戦略横断パターン(BB-MR vs Donchian)を、平均回帰 / 順張りの一般化として、主張できない(#6 §4.5 と同じ留保)
  • 8 grid 限定(§4.4)
  • 中央値集約の解像度(§4.3、§3.7 で per-fold 振れ表として開示)
  • fold 別重心は、今回も未取得(#5 / #6 から持ち越し、#8 候補)

4.6 次に検証すること(#8 への引き継ぎ候補)

走らせる前から並んでいた候補と、走らせて出てきた候補を、ぜんぶ、置く:

  1. 3 戦略目で対角構造が再現するか。BB-MR と Donchian で見えた対角の符号構造が、別の戦略を持ち込んだとき、4 ペアで、また同じ場所に立つかどうか
  2. AUDJPY マスの方向逆転(§3.5)を、別ペア / 別戦略で、再現するか
  3. USDJPY × Donchian の +31.05 の構造的理由(§3.4): 全 fold 正値 + fold 2 極大の構造が、別期間 / 別ペアで、再現するか
  4. ロング / ショート別 Expectancy ÷ spread(§4.4): per-fold trades CSV から逆算可能、必要時に着手
  5. grid 横断分布(§4.4): 8 grid 限定の射程を、別の方向に、広げる

5 つの候補から、#8 で 1 〜 2 を選ぶ。ここで、選び切らない。

#6 の終わりにも、4 つの宿題を、決めずに置いた。そのうちの 1 つだけを #7 で取った。今回の終わりにも、5 つの候補を、決めずに、置く。決めずに置いておくことが、#5 から #7 まで、毎回、#N+1 への入り口に、なっている。


ドル円さん × Donchian: +31.05。
……桁が、違う。4 人の中で、ひとマスだけ、抜けていた。

ポンド円さん × BB-MR: +2.79
12/20 の壁の中身は、ぜんぶ厚みじゃ、なかった。

ユーロ円さん × Donchian: +5.15
豪ドル円さん × Donchian: +6.67

4 人とも、対角の片側に、立っていた。
でも、太さは、ぜんぶ、ちがった。

あと、もうひとつ。
豪ドル円さん × BB-MR で、物差しの方向が、変わった。
豪ドル円さん × BB-MR: -3.48
……今日は、それだけ、残しておく。


Appendix — 再現環境

実行コマンド:

python chapters/season1/ch07_physical_metrics/run.py

参照出力:

  • results/reference/ch07_physical_metrics/
  • trades_7_*.csv 40 ファイルから 4 指標を再集計する

注意事項

本稿の検証は、取得時点の公開データと記載した条件に基づくものです。データ取得元の仕様変更、欠損、修正、配信遅延などにより、結果が変わる場合があります。本稿は投資助言ではなく、売買判断はご自身の責任でお願いします。