Nに数えるもの・数えないもの

試行回数Nは、「コードを何回動かしたか」ではありません。同じデータから、結果を見て比べた候補がいくつあったかです。 同じ設定でバグを直して3回動かしても、比べた候補が1つならNは1です。逆に、最適化ツールを1回動かしただけでも、中で400通りを比べて最良を選んだならNは400増えます。

迷ったときの判断基準は1つだけです。「この数字を見て、候補を選ぶか。ルール・期間・物差しを変えるか」。選ぶ、または変えるならNに入れます。 記事やレポートに載せなかった失敗案も、頭の中で「これはないな」と却下した調整も、データを見たうえで捨てたなら試行です。

Nに数える基準:計算の種類ではなく「その数字を見て何かを選んだか」で決まる データで計算した数字を見た その数字を見て、候補を選んだか? (ルール・期間・通貨・時間足・物差しの変更も「選ぶ」に含む) [はい] Nに数える! 比べた候補の数をすべてNに加算 例:グリッド57,600、フィルタ25、乗り換え12 [いいえ] 記述統計(N外) 欠損値の確認・比較対象の計算・近傍確認 ※ 見た後でルールを変えたら即Nに加算
Nに入るかどうかは、計算の種類ではなく「その数字を見て何かを選んだか」で決まる

このコースの検証で、実際にどう分けたかを表にします。右の列の「N外」は、選ぶためではなく、仮説の性質を確かめるために計算した数字です。

やったこと扱い理由
Aさんのグリッド57,600通り(総pips最大を選ぶ)Nに数える(+57,600)全候補の成績を比べて1つを選んだ
Aさんが負けた日を見て試したフィルタ25通り(どれも不採用)Nに数える(+25)採用しなかったが、比べて捨てた。その結果を見て次の行動(物差しの変更)が決まった
Aさんが検証期間でIS上位12案を見比べ、3位案に乗り換えNに数える(+12)検証データの成績を見て選んだ
Bさんの近傍8通り(レンジ終了・シグナル窓・損切り・決済をずらす)N外事前登録で「記述統計として確認するだけ」と決め、ルールを変えなかった
比較対象C1〜C3、置換検定、ドローダウンの再標本化N外ルールを選ぶためではなく、選んだルールを試すための検査
データの欠損・週末ギャップの確認N外成績を見ていない
ウォークフォワードで窓の長さを4通り試すN外(ただし条件付き)手順の検査として並べるだけならN外。4通りの中から結果の良い窓を選んで使えば、その時点で選択になる(第15回)

「N外」は「何をしてもよい」という意味ではありません。Bさんの事前登録書には「近傍の結果を見てルールを変えたら、その時点で N+1 として記録する」と書いてあります(第6回)。 記述統計は、見るだけならNを増やしませんが、見た後の行動しだいでNに変わる数字です。数え方に迷ったら、多く数えるほうを選びます。少なく数えた誤りは後から見つけにくく、多く数えた誤りは成績を控えめに読むだけで済むからです。

実行前のスコープ宣言

Nは、実行した瞬間に増えます。そして一度見た結果は、見なかったことにできません。 結果を見た後でNを数えようとすると、良い結果なら「これは確認のための実行だった」、悪い結果なら「設定を間違えていたから数えない」と、都合のよい理由がいくらでも付きます。 そこで、実行する前に、何を何通り試すか、それが計画のどこに当たるか、Nがいくつからいくつになるかを書いてから実行します。これを実行前のスコープ宣言と呼びます。

このコースの検証では、実行のたびに次の3行を書きました(企画書の実行前チェック)。

実行前の宣言(テンプレート)
対象: USDJPY 15分足 <期間> <バリエーション数>
企画書との一致: §3.x の該当箇所
この実行で N_A(またはN_B)は <現在値> → <新値> になる

3行の役割は次のとおりです。

Aさんの手順を再現したときの宣言を、このテンプレートで2つ示します。

実行前の宣言(Aさんのグリッド探索)
対象: USDJPY 15分足 2005-01-01〜2016-12-31 57,600バリエーション
企画書との一致: §3.4 手順2(グリッド探索、スプレッド0・シグナル足の終値で約定、総pips最大・100トレード以上)
この実行で N_A は 0 → 57,600 になる
実行前の宣言(Aさんの検証データの使い回し)
対象: USDJPY 15分足 2017-01-01〜2022-12-31 12バリエーション(IS上位12案)
企画書との一致: §3.4 手順4(検証成績を順に見て、最良の案に乗り換える)
この実行で N_A は 57,650 → 57,662 になる

2つ目の宣言は、成績を1つも見る前に「12案を見比べるのでNは12増える」と書いています。後で3位案が選ばれたか、1位案のままだったかに関係なく、Nは同じだけ増えます。 数え方を結果から切り離すことが、宣言の一番の働きです。

正しい順番 結果を見る前(ここで数を決める) 結果を見た後 ① 宣言を書く 対象・計画との一致 ② Nを更新 現在値 → 新値 ③ 実行 ④ 結果を見る ⑤ 採否と理由 却下案も記録 ここから先は取り消せない よくある順番 実行 結果を見る 良ければ記録 Nは後から数える (悪かった実行は数えられにくい)
Nの更新は、結果を見る線の手前で終わらせる。後から数えると、悪かった実行ほど数から漏れる

計画にない実行をしたくなったら

検証を進めると、計画になかった実行をしたくなる場面が必ず来ます。「参考までに別の通貨ペアでも」「念のため2年前から」。 そのときは、宣言の「企画書との一致」が空欄になることを合図に、いったん止めます。そして計画書に追記してから実行します。追記には日付と、結果を見る前か後かを書きます。

研究ログの書き方

宣言が「実行の前」の記録なら、研究ログは検証全体の記録です。トレード日誌の回では、日々のトレード記録とは別のシートに、手法を検証するときだけ研究ログを付けると書きました。 トレード記録と研究記録を分けておけば、日誌を重くせずに、過去に何通り試したかを失わずに済みます。ここでは、そのシートに何を書くかを具体的にします。

項目書くことBさんの例
日付その記録を書いた日。結果を見る前の決定か、後の決定かを判断する根拠になる2026-09-24
仮説ID仮説ごとの番号。同じアイデアを直したら、新しい番号を振るか枝番を付けるB-01(東京レンジ→ロンドン序盤ブレイク)
データデータの提供元、通貨ペア、時間足の作り方、欠損の扱いmarket_data.duckdb、USDJPY 1分足から15分足を作成、欠損のある日は見送り
時刻規約どの時刻で記録されたデータか、日足の区切り、夏時間の処理JST、日足の境界は 06:00 JST。ロンドン時刻は夏時間を処理して変換
期間この記録で使ったデータの期間と、その期間の役割(探索・検証・最終テスト)探索 2005-01-01〜2016-12-31
N(累計)実行前の宣言で書いた「現在値 → 新値」0 → 1
結果の前か後か決定や変更を、結果を見る前にしたのか、後にしたのか前(事前登録)
採否と理由採用・保留・棄却と、その根拠。却下した案と却下理由も書く探索期間は判定しない(最終テストで判定)

特に大事なのが、「結果の前か後か」の列です。同じ変更でも、結果を見る前なら仕様の修正、結果を見た後なら新しい試行です。 Bさんは、データを確認した段階で「保有している時間帯や決済の足に欠損がある日も見送る」というルールを追加しました。これは成績を見る前の決定だったので、Nは1のままです。ログに「前」と書いてあるから、後で誰が読んでもそう判断できます。

Bさんの研究ログ記入例(仮説ID: B-01):行ごとに「結果の前か後か」を記録する 日付 内容・操作 前/後 N 採否・理由 2026-09-24 事前登録(ルール1通り固定) 合格ライン5項目を事前に明記 結果の前 0 → 1 登録完了(仮説固定) 2026-09-24 データ確認(欠損日の見送り追加) 異常値排除の事前ルール化 結果の前 1のまま ルール変更なし(データ前処理) 2026-09-25 近傍8通りを確認(記述統計) 最良点への乗り換えは行わない 結果の後 N外 (1) 台地を確認、ルール維持 2026-09-26 最終テスト開封(1回のみ) 全指標を一括算出 結果の後 1(完了) 保留(2項目が不合格) ※ 「結果を見る前にNを確定した」ログがあるからこそ、第三者が検証の正当性を100%信用できる
Bさんの研究ログ。行ごとに「結果の前か後か」を書くと、Nが増えなかった理由を後から誰でも確かめられる

却下した案こそ残す

研究ログで最も抜けやすいのは、採用しなかった案です。Aさんの台帳には「貪欲フィルタ25通り(基準:総pips)→ どれも不採用」という行があります。 何も採用しなかった実行でも、25通りを比べたことに変わりはありませんし、この「不採用」を見たことが、次に物差しをPFへ替える判断につながりました(第3回)。 もしこの行を消していたら、台帳のNは25少なくなるだけでなく、「物差しを替えた」という分かれ道そのものが記録から消えます。

コードで検証するなら、Nを先に書き換える

Pythonなどで検証する場合は、スクリプトの先頭で累計Nを更新し、画面とログファイルの両方に出してから計算に入ると、宣言を書き忘れにくくなります。次は、その最小の形です(読まなくても本文は理解できます)。

Python
import csv, datetime

N_BEFORE = 57_650   # 台帳の現在値(前回の実行の後の値)
PLANNED  = 12       # この実行で見比べる候補の数
N_AFTER  = N_BEFORE + PLANNED

# 結果を計算する前に、宣言をログへ追記する
with open("trial_ledger.csv", "a", newline="", encoding="utf-8") as f:
    csv.writer(f).writerow([
        datetime.date.today().isoformat(), "A",
        "2017-2022 IS上位12案の検証成績を比較(企画書 §3.4 手順4)",
        N_BEFORE, N_AFTER,
    ])
print(f"この実行で N_A は {N_BEFORE:,} → {N_AFTER:,} になる")

# ここから検証期間の成績を計算する

要点は、ログへの追記が計算より前にあることです。計算が途中で失敗しても、結果が悪くても、行は残ります。 試行回数を成績の評価にどう反映するか(DSR)は第14回で、その数理は上級コースで扱います。

AさんとBさんのNを並べる

このコースの検証で、実際に付けた試行台帳をそのまま載せます。行は実行した順で、Nの列は実行前の宣言に書いた「現在値 → 新値」です。

日付台帳内容N
2026-09-24B事前登録ルール1通り(探索期間 2005〜2016年)0 → 1
2026-09-24Aグリッド57,600通り(2005〜2016年、コスト0・終値約定、総pips最大・100トレード以上)0 → 57,600
2026-09-24A貪欲フィルタ25通り(基準:総pips)→ どれも不採用57,600 → 57,625
2026-09-24A基準をPFに替えて貪欲フィルタ25通り → 金曜除外・5月除外・RSI>5557,625 → 57,650
2026-09-24A2017〜2022年を使い回し、IS上位12案から検証成績が最良の案に乗り換え(3位案)57,650 → 57,662

台帳には、行の外にもう1つの記録があります。記述統計(選択なし・N外)として計算したものの一覧です:Bさんの近傍8通り、比較対象C1〜C3、Bさんのルールの転写(EURJPY・GBPJPY)、Aさんの利益の分解、月×曜日のマス集計、ドローダウンの再標本化、置換検定、ランダムウォーク、ウォークフォワード。 これらは第10回以降の材料ですが、どれも「見て何かを選んではいない」ことを、計算した時点で書き残しています。

台帳ごとの試行回数Nの推移:Aさんは57,662へ爆発、Bさんは1を維持 57,600 (グリッド) Aさん N = 57,662回 事前登録 N=1 Bさん N = 1(不動) 対象・期間選択 グリッド探索 総pipsフィルタ PFフィルタ 検証乗り換え ※ Aさんの最初の「対象・期間の選択」は記録すらなく、57,662回はあくまで確認できた下限値にすぎない
Aさんの台帳は実行のたびに増え、Bさんの台帳は事前登録の1から動かない。Aさんの最初の点(対象と期間の選択)は記録がなく、57,662は下限

第3回で数えた「実質N」との対応

第3回では、Aさんの開発を分かれ道の図に描き、段ごとに選択肢の数を数えました。その表と、この台帳は1行ずつ対応しています。

第3回の表は「分析するための数え方」、この台帳は「その場で付ける記録」です。記録を付けていたから分析ができ、記録のない段①は分析しても数えられませんでした。 Nを正しく数えられるかどうかは、計算の腕ではなく、実行のたびに書いたかどうかで決まります。

台帳を分ける理由と、どのNを使うか

このコースでは、AさんとBさんの2人の台帳を分けています。2人は別々の開発者として、それぞれの手順で選んだという設定だからです。 実務で同じ人が同じデータでAさんとBさんの両方をやったなら、台帳は1つにまとめます。同じデータを何度も見ていることに変わりはないからです。 企画書では「N_AとN_Bは別の台帳で管理し、両方ともレポートの冒頭に書く」と決めました。どちらか一方だけを載せると、読み手は検証者がほかに何を見ていたかを知ることができません。

2人の「やったこと/結果」

記録のやり方報告に書いたN結果
Aさん本人は記録を付けず、最良の1通りの成績だけを報告(台帳は検証者が再現のために付けた)書いていない(本人の感覚は1)台帳ではN=57,600〜57,662(下限)。探索期間の好成績は、何通りから選んだかを添えて初めて読める
Bさんデータを見る前に1通りを登録し、変更と確認をすべて「前/後」付きでログに残した1成績をそのまま読める。探索期間は平均 −0.14 pipsとほぼゼロで、その答えもそのまま受け取れる

他人の成績を見るときに聞くこと

台帳を付ける習慣は、他人の成績を読むときにも役に立ちます。EAの販売ページ、SNSの検証報告、書籍のルール。そこに載っているのは、たいていAさんの報告と同じ「最良の1通り」です。 載っていないのは台帳です。だから、成績の数字を読む前に、台帳にあたる情報を質問します。

  1. 何通り試して、この1つを選んだか:パラメータの組み合わせだけでなく、通貨ペア・時間足・期間・方向の選択も含めて。
  2. 却下した案は何か:うまくいかなかった設定、外した通貨ペア、採用しなかったフィルタ。1つも出てこないなら、記録がないと考える。
  3. 物差しは最初から決まっていたか:総pips、PF、Sharpe、勝率のどれで選んだか。途中で替えたか。
  4. 検証用のデータを何回見たか:「後半で確認した」なら、確認して直したことは何回あるか(第7回)。
  5. コストと約定の前提:スプレッド、滑り、どの価格で約定させたか(第9回)。
  6. 日付の付いた事前の記録があるか:ルールを公開した日より後の成績と、前の成績を分けて見せてもらえるか。

この質問に答えられない報告は、嘘とは限りません。ただ、答えられない限り、その成績は「Nが分からない=大きいかもしれない」成績として読みます。 公開される成績は、試した人の中でうまくいった人のものだけが表に出る、という偏りも持っています(第4回の型7)。 最も確かな確認は、作った人がルールを公開した日より後の期間、つまり作った人が見ていない期間の成績です。他人の成績を読む質問は、修了回で10項目にまとめます(第19回)。

よくある間違い

「良い結果が出てから、Nを数える」

結果を見た後に数えると、悪かった実行ほど「設定ミスだった」「参考の実行だった」と外されます。Nは実行する前に更新し、結果によって変えません。 数える時点が結果の後にある限り、数え方そのものが結果に合わせた選択になります。

「記述統計だから、何を見てもN外」

近傍や年別の成績を見るだけならN外です。しかし、それを見て損切りの位置を変えたり、悪い年を除外したりすれば、その時点で新しい試行です。 Bさんが近傍8通りをN外にできたのは、「見るだけで、ルールは変えない」と事前に決め、そのとおりにしたからです。

「Nは覚えておけばよい」

数週間の検証で試した案を、正確に覚えている人はいません。記憶に残るのは、良かった案とその直前の数回です。 過去の検証を振り返ってNを復元するときも、分からない部分は少なく見積もらず、「少なくともN」として多めに扱います。

「失敗した検証はログから消して、きれいにしておく」

失敗した検証の行を消すと、Nが減るだけでなく、「なぜ次にその方向へ進んだか」という分かれ道の記録も消えます。ログは成果の一覧ではなく、判断の履歴です。却下した案と却下理由こそ残します。

実戦課題

今検証している(またはこれから検証する)ルールについて、次の順に記録の仕組みを作ってください。

  1. 研究ログのシートを作る:日付・仮説ID・データ・時刻規約・期間・N(現在値 → 新値)・結果の前か後か・採否と理由、の8列です。トレード日誌とは別のシートにします。
  2. 今までのNを復元する:これまでに比べた通貨ペア・期間・パラメータ・フィルタ・物差しを思い出せる限り書き出し、合計を「少なくともN」として1行目に書きます。第3回の実戦課題で描いた分かれ道の図があれば、それを使います。
  3. 次の実行の前に宣言を書く:対象・計画との一致・Nの更新の3行を書いてから実行します。計画との一致が書けなければ、実行せずに計画を追記します。
  4. N外にする確認を先に決める:近傍や年別の成績など、「見るだけでルールは変えない」確認を、実行前に列挙しておきます。
  5. 報告の冒頭にNを書く:成績を人に見せるときは、最初の行にNと、どのNを使ったか(累計か、その選択の分か)を書きます。

やるべきこと/やるべきでないこと

やるべきことやるべきでないこと
実行前に宣言を書き、Nを更新してから実行する良い結果が出てからNを数える
期間・通貨ペア・方向・時間足・物差しの選択もNに数えるパラメータの組み合わせだけを数える
却下した案と却下理由を研究ログに残す採用した案だけを記録し、失敗した検証を消す
変更のたびに「結果の前か後か」と日付を書くいつ決めたかを書かずに仕様を書き換える
「見るだけ」の確認を事前に決め、見た後でルールを変えたらN+1にする記述統計だからと、見た結果でルールを直してもN外にする
計画にない実行は、計画に追記してから行う「参考までに」別の通貨ペアや期間を試す
報告の冒頭にNと、どのNを使ったかを書く最良案の勝率とPFだけを示す

チェックリスト

次の回に進む前に、以下が自分の言葉で説明できるか確認してください。

ミニテスト

4問で確認します。不正解なら別の選択肢を選び直せます。正解すると解説が表示されます。

Q1. Bさんは、事前登録書に書いたとおり、近傍8通り(レンジの終了時刻やシグナル窓をずらしたもの)の成績を確認し、ルールは変えませんでした。N_B はどうなりますか?

Nに入るかどうかは「その数字を見て何かを選んだか」で決まります。見るだけならN外ですが、記述統計として確認したこと自体は、「前/後」の印を付けてログに残します。

Q2. 実行前の宣言で、Nの更新を「結果を見る前」に書く一番の理由は?

結果を見た後に数えると、悪かった実行ほど「参考だった」「設定ミスだった」と外されがちです。Aさんの検証データの使い回しでも、12案を見比べる前に「57,650 → 57,662」と書いたので、どの案が選ばれても数は同じでした。

Q3. Aさんは総pipsを基準にフィルタ25通りを試しましたが、どれも採用しませんでした。台帳の正しい書き方は?

比べて捨てた25通りも試行です。しかも「不採用」を見たことで、Aさんは物差しをPFに替えてもう25通り試しました。この行を消すと、Nが減るだけでなく、その分かれ道の記録も消えます。

Q4. EAの販売ページに、1通りのルールの勝率・PF・損益曲線だけが載っています。最初に確かめるべきことは?

Aさんの報告も、1通りの立派な成績(PF 1.83、勝率59.5%)だけでした。台帳にあたる情報が分からない限り、その成績は「Nが分からない=大きいかもしれない」成績として読み、作った人が見ていない期間の成績で確かめます。