FXの自動売買を作りたくて、AI(Claude)に検証を手伝ってもらいました。
結果から言うと、3日間で50セル以上を検定して、採用ゼロです。実弾も1円も入れていません。
でも、この記事で書きたいのは「勝てませんでした」という話ではありません。面白かったのは、AIが最初に持ち出してきた**「合格線」の作り方**のほうでした。バックテストの結果が良いことと、その手法が本物であることは、まったく別の問題だという話です。
コードと数字を全部載せます。落とし方に興味がある人向けです。
何を検定したのか
| 対象 | セル数 | 内訳 |
|---|---|---|
| 市販FX本の手法(Amazon売れ筋10冊) | 30 | 10手法 × H1/H4/D1 |
| TradingViewの人気スクリプト 第1弾 | 20 | 10指標 × H1/D1 |
| TradingViewの人気スクリプト 第2弾 | 22 | 12指標 × H1/D1 |
| デイトレ機構6本 | 12 | 6手法 × 成行/指値 |
| 総当たりグリッド | 6,597 | テクニカル9 × オシレータ5 × TP/SL4 × ナンピン3 × 7銘柄 × 2足 |
| その他(TSMOM、ゴトー日、ナンピン、スキャル、独自15本ほか) | 30+ |
データは13銘柄(USDJPY / EURJPY / GBPJPY / EURUSD / GBPUSD / AUDUSD / XAUUSD / NZDUSD / USDCAD / USDCHF / EURGBP / AUDJPY / CADJPY)。H1は2.8年(各約17,100本、金のみ約13,700本)、D1は15年(金は20年)。総当たりとデイトレ検定はこのうち6〜7銘柄・より短い窓を使っています。
出口は原則すべての手法で共通に固定しました。SL = 1.5 × ATR14 / TP = 2.5 × ATR14 / 最大100本保有 / 決済までは新規を建てない。パラメータ探索は一切しません。指標のパラメータも公開ソースの既定値のまま。例外はタートルズだけで、10本ドンチャンの逆側と2Nのネイティブ出口を使っています(出口が手法の一部なので外せない)。
評価は E(R)(1回の損切額を1としたときの1トレードあたり期待値)で統一しました。pips のままだとクロス円とドルストレートを混ぜられないからです。
コストは実測の往復スプレッド(1.1〜2.1 pips、スリッページ0.5込み)を毎トレードから引いています。
合格線(4つの関門)
ここが本題です。バックテストで E(R) がプラスになった手法は、実際いくつもありました。それを全部落とすための関門が4つあります。
関門1: 事前登録
計算する前に、合格条件と自分の予測を書いてファイルに保存する。
(事前登録ファイルの現物は、3回ぶんの全文と訂正の追記まで含めて、この記事から外して別にまとめています。ここでは形だけ書きます。計算前にファイルへ書くのは4つ。探索空間のセル数、ヌルの作り方、合格の条件、そして自分の予測です。第2弾では探索空間を21セルと書きました。)
(このセル数は数え間違いで、V11もH1のみなので実際は20セルでした。事前登録の本文は書き換えず、「計算後の追記」として別に訂正を書いてヌルもbest-of-20で回しています。封をした文章を後から直さないのが大事なところなので、間違いも含めてそのまま残します。)
地味ですが、これが一番効きました。結果を見てから「n=234 だけど銘柄分散はいいから採用」みたいな後付けができなくなります。
副産物として、自分の予測がどれくらい当たるかの記録も残ります。私たちの場合、H1全滅は3回連続で当たりましたが、「ラウンドナンバーは効くはず」「荒れた日ほどブレイクは素直に走るはず」といった機構の予測は軒並み外れました。予測が外れた記録があると、次に自信満々で立てた仮説を疑えるようになります。
関門2: best-of-N ヌル(ブロックシャッフル)
20セル試して1位が +0.05 だったとして、それは偶然ではないと言えるのか。
答えは「同じ探索を、構造を壊したデータで何十回もやってみる」です。日足なら10本、H1なら20本のブロック単位で時系列をシャッフルします。ブロックにするのはボラティリティのクラスタリング(荒い日は荒い日で固まる)を保存するためです。ブロックの境界では価格を繋ぎ直します。これをやらないと境界ごとに巨大な人工ギャップが生まれて、まったく別の(そしてずっと弱い)ヌルになります。
(この手順を実装したコード一式は、この記事から外して別にまとめています。やっていることは単純で、並べ替えたデータに対して探索を丸ごと1回やり直し、その中の1位だけを記録します。それを30回繰り返して分布を作ります。)
ポイントは、1手法のp値ではなく「探索全体の1位」の分布を作ることです。20個試して1位を選ぶという行為そのものを、ヌルの側でも再現します。
実際の数字:
| 検定 | 実データの1位 | まぐれの1位の分布 | 判定 |
|---|---|---|---|
| 市販本10手法 30セル | タートルズD1 +0.119 | 中央値 +0.103 / 90%点 +0.150 | 63パーセンタイル ✗ |
| TradingView 第1弾 20セル | QQE D1 +0.108 | 中央値 +0.057 / 90%点 +0.078 / 最大 +0.095 | 100パーセンタイル ○ |
| TradingView 第2弾 20セル | Gaussian Filter D1 +0.047 | 中央値 +0.036 / 90%点 +0.084 / 最大 +0.108 | 63パーセンタイル ✗ |
タートルズの +0.119 は、単独で見れば立派な数字です。でも「30セル探して1位」という文脈では、構造のないデータからでも半分以上の確率で出てくる大きさでした。
ちなみに第2弾でまぐれの1位が第1弾より高くなっているのは、機械学習系(kNN、Lorentzian分類)はシャッフルされたデータからも「学習」してしまうからです。探索空間に学習器を入れると、まぐれの上限が上がります。これも実測して初めて気づきました。
関門3: 入場を1本ずらす
シグナルを検出した足の値段で入場していると、偽のエッジが出ます。実装ミスとして分かりやすいものは潰したつもりでも、微妙なものは残ります。
なので候補が出たら、必ず入場を1本遅らせて同じ計算をします。
第2弾の1位、Gaussian Filter D1 の場合:
元 +0.047
1本遅れ +0.009 ← ほぼ消えた
2本遅れ +0.016
さらに「ガウス加重」に意味があるのかを見るために、単純移動平均の傾き反転でも同じことをやりました。
Gauss(20) +0.047 SMA(20) -0.009 EMA(10) +0.053 EMA(30) -0.012
Gauss(10) +0.025 Gauss(30) +0.057 Gauss(50) -0.007
隣の設定に移すと符号がばらつきます。「短いMAの傾き反転」という族が ±0.05 の帯の中で揺れているだけに見え、ガウス関数に固有の効果は見えませんでした。
関門4: 一度も見ていない銘柄に当てる
これが一番高い授業料でした。
TradingView第1弾の QQE(14,5) D1 は、7銘柄で以下の成績でした。
- E(R) +0.108、6/7銘柄プラス、n=805
- best-of-20 のヌル分布を30回中30回とも上回る(100パーセンタイル)
- 1銘柄抜きすべてプラス(+0.09〜+0.12)
- 期間を4分割して全部プラス(+0.199 / +0.065 / +0.052 / +0.230)
- コスト2倍でも +0.099
事前登録した関門を全部通っています。3日間で最も強い「合格」でした。
そこで、一度も見ていない6通貨(NZDUSD / USDCAD / USDCHF / EURGBP / AUDJPY / CADJPY)を新しく取得して、ルールを一切変えずに当てました。合格線はデータを取得する前に書きました。
QQE D1 E(R) -0.019 プラス 2/6 p=0.45 ✗
MAリボン D1 E(R) -0.072 プラス 0/6 p=0.88 ✗
(通貨別 QQE: NZDUSD +0.076 / USDCAD +0.023 / USDCHF -0.019 / EURGBP -0.117 / AUDJPY -0.029 / CADJPY -0.054)
両方落ちました。
意味するところは明快です。7銘柄のD1で見えていたものは、ドル絡み主要通貨+金のこの15年に固有の性質であって、通貨一般の構造ではなかった。ドル高と円安、そして金の長期上昇(20年で約7倍)という一方向の相場が乗っていただけでした。
そして教訓のほうが重要です。
同じデータ内の best-of-N ヌルは「探索の偶然」を除けるが、「そのデータ固有の性質」は除けない。除けるのは、別の銘柄か別の期間だけ。
第2弾では最初からこれを合格線に組み込んで、13銘柄を「既知7」と「新6」に分けて両グループでプラスを要求しました。結果、D1の10セルのうち6セルが「既知7はプラス、新6はマイナス」という同じ型を示しました。両グループでプラスだったのは2セルだけです。
落ちたものの棚
数字だけ並べます。すべて実測コスト込みの E(R) です。
時間軸で決まっていた
市販本の10手法を同じ銘柄・同じコストで3つの時間軸に当てると、こうなりました。
H1 プラス 0/10
H4 プラス 2/10
D1 プラス 7/10
手法の中身ではなく時間軸で決まっています。別に測った「持続性の取り分」(同じ2.8年・同じトレール・コスト前で、実データとブロックシャッフルの差)も D1 +0.116R / H1 +0.011R と一桁違いました。コストは同じ pips なので、H1は構造的に負ける側です。
ただしこの +0.116R は「D1なら勝てる」という意味ではありません。コストを引いた実額ではD1も全銘柄マイナスで、超過がプラスなのはシャッフルのほうがもっと負けるからです。D1はゼロのすぐ上、H1はゼロより下、というのが正確な言い方になります。
TradingView系は第1弾・第2弾あわせて H1 22本すべてマイナス(−0.037〜−0.106)。デイトレ機構12セルも全部マイナスで、1位が −0.027。3日間の H1 検定セルは50本を超えて、プラスはゼロでした。
新6通貨のH1が既知7より一段悪い(−0.095〜−0.137 対 −0.023〜−0.079)のも、スプレッドが太い分そのままです。H1の負けは、ほぼ費用で説明できます。
人気の機械学習系が、H1で下から数えたほうが早い位置に来た
Lorentzian分類 (jdehorty) H1 -0.097 D1 -0.011
kNN k=63 (capissimo) H1 -0.085 D1 +0.007
事前登録で「ML系はH1で最悪の族になる」と予測して、おおむね当たりました(単セルの最下位は Williams VixFix と MACD MTF なので、厳密には「族として下位」です)。理由も単純で、この2つは「4本先の終値の符号」を学習します。H1の4本先はほぼコイン投げで、しかも往復びんたを食らう帯です。学習対象そのものが情報を持っていない。
ナンピンは勝率を上げて期待値を上げない
5回まで追加・合計0.5ロット・1回の損切上限を決めた仕様で回しました。
勝率 82%
1回あたり期待値 -¥940
資金曲線 → 破産
コイン投げで方向を決めた場合 -¥867 ← ほぼ同じ
方向に情報がないので、コイン投げと変わりません。総当たりのうち取引数40以上に絞った5,283通りでも、ナンピン0回/1回/2回の E(R) の中央値は −0.047 / −0.042 / −0.043 でした。
ここで私たち自身がバグを踏みました。最初の計算では +¥240万という素晴らしい結果が出たんです。原因は、同じ足の中で「安値で買い増して、高値で利確する」という順序を許していたこと。実際には1本の足の中でどちらが先に来たかは分かりません。直したら −¥830万 になりました。
自分でこれを踏んで以来、ナンピン系のバックテスト結果を見るときは「1本の足の中で、追加と決済のどちらが先に来たと仮定しているか」を必ず確認するようになりました。
スキャルピングは算数で閉じる
「7pips利確・5pips損切を1日10回」という案を検討しました。
M15の実測で、無情報のときの勝率は 41.6% です(50%ではありません。利確幅のほうが広いので、先に損切に当たる確率のほうが高い)。コスト後の損益分岐に必要な勝率は銘柄によって 51〜59%。つまり無情報から10ポイント以上の改善が要ります。3日間で測った方向情報の上限は +0.02R でした。届きません。
その他
TSMOM 14年(月次168回) シャープ +0.31 vs シャッフル90%点 +0.62 ✗
ゴトー日(仲値ドル円ロング) 置換検定 p=0.869 ✗(コスト前から負け)
月末WMRフィックス -0.18 pips, p=0.36 ✗
ラウンドナンバー(Osler) H1では観測されず(グロスでもマイナス)
指値で0.3ATR引きつけ 6手法すべてで成行より 0.05〜0.09R 悪い
ボラフィルタ(高ボラ日だけ) 予測と逆。高ボラ日ほどブレイクの方向情報が劣化
タートルズの40年 2006-12 +0.206 → 2013-18 +0.183 → 2019-22 +0.065 → 2023-26 -0.113
最後のタートルズの減衰は、適応的市場仮説(Adaptive Markets Hypothesis)の教科書どおりの実例が1つ出た、という話です。期間の区切りは4つしかないので有意性は主張できません。向きだけを見ています。
3日間で残ったもの
採用 0件。実弾 0円。
まだデモで前向き検証している候補が1つだけありますが、判定は年末で、それまでは書きません。判定前の候補を「見つけました」と書くのは、この記事でやってきた話と矛盾するので。
代わりに残ったのは、こういう帳簿です。
封印データの帳簿
使用済み 金 D1 2022-2026 / FX D1 全期間(13銘柄)/ 新6通貨 H1 2.8年
未開封 H1 2026-03-01〜2026-09-01 (候補の判定用。1回だけ開ける)
未見のデータは有限の資源です。1回使ったら、そのデータで「一度も見ていない」とはもう言えません。だから帳簿をつけて、何をいつ消費したかを記録します。
まとめ
3日間で学んだことを1つに絞るなら、これです。
バックテストの数字は、それ自体では何の証拠でもない。証拠になるのは「その数字が、構造のないデータからは出てこない」という比較だけ。
そして比較する相手は、次の4つを全部くぐらせたものである必要があります。
- 事前登録 — 合格線と自分の予測を、計算前に書く
- best-of-N ヌル — 1手法のp値ではなく、探索全体の1位の分布と比べる
- 入場ずらし — 1本遅らせて残るか
- 未見の銘柄・期間 — 同じデータ内のヌルでは、データ固有の性質は絶対に除けない
4番目を最初からやっていれば、QQEに費やした時間は要らなかったはずです。でも、実際に「100パーセンタイルで合格したものが隣の6通貨で 2/6 になる」のを自分の目で見るのは、教科書で読むのとはだいぶ違う体験でした。
AIに手伝ってもらって一番良かったのは、手が速いことより、合格線を先に書けと言い続けることのほうだったかもしれません。人間は結果を見てから基準を動かします。私も動かそうとして、事前登録ファイルを見せられて止まりました。
測ってほしいことがあれば
手元で再現できるものなら、実際に動かして数字で返します。コメントに環境と再現手順を書いてもらえると早いです。結果がどちらに転んでも、そのまま出します。
検証はPython(numpy)で実装。指標はTradingViewの公開ソースの中核ロジックを同じ式で再実装しています。閉源(invite-only)のスクリプトは式が読めないので検定対象外にしました。
本記事は検証手順の記録であり、特定の手法・銘柄・業者の売買を推奨するものではありません。投資判断はご自身の責任でお願いします。