Nに数えるもの・数えないもの
試行回数Nは、「コードを何回動かしたか」ではありません。同じデータから、結果を見て比べた候補がいくつあったかです。 同じ設定でバグを直して3回動かしても、比べた候補が1つならNは1です。逆に、最適化ツールを1回動かしただけでも、中で400通りを比べて最良を選んだならNは400増えます。
- 移動平均の組み合わせを3組比べた:20/50、20/60、30/50 を比べて良いものを選ぶなら、Nに3を加える。
- 損切り3種類×利確4種類のグリッド:12通りを比べるので、Nに12を加える。グリッドの中は掛け算で数える。
- 結果を見て曜日フィルタを足し、もう一度評価した:新しい試行。試した曜日の数だけ加える。
- データの欠損や週末の位置を確認した:候補を選んでいないので、原則としてN外。
迷ったときの判断基準は1つだけです。「この数字を見て、候補を選ぶか。ルール・期間・物差しを変えるか」。選ぶ、または変えるなら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行の役割は次のとおりです。
- 対象:通貨ペア・時間足・期間・候補の数。期間を書くのは、どのデータを「使った」かを残すため。探索期間だけのつもりで検証期間まで読み込んでいないかも、ここで気づけます。
- 企画書との一致:この実行が、事前に書いた計画のどの手順に当たるか。計画にない実行なら、ここが空欄になります。空欄のまま実行しないことが、この行の目的です。
- Nの更新:現在のNと、この実行の後のNを書く。結果が良くても悪くても、ここに書いた数は変えません。
Aさんの手順を再現したときの宣言を、このテンプレートで2つ示します。
対象: USDJPY 15分足 2005-01-01〜2016-12-31 57,600バリエーション
企画書との一致: §3.4 手順2(グリッド探索、スプレッド0・シグナル足の終値で約定、総pips最大・100トレード以上)
この実行で N_A は 0 → 57,600 になる対象: 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は同じだけ増えます。 数え方を結果から切り離すことが、宣言の一番の働きです。
計画にない実行をしたくなったら
検証を進めると、計画になかった実行をしたくなる場面が必ず来ます。「参考までに別の通貨ペアでも」「念のため2年前から」。 そのときは、宣言の「企画書との一致」が空欄になることを合図に、いったん止めます。そして計画書に追記してから実行します。追記には日付と、結果を見る前か後かを書きます。
- 結果を見る前の変更:このコースでは、結果を見る前に「Aさんも探索期間を2005〜2016年とし、2017〜2022年を使い回しの対象にする」と計画を改訂しました。当初の案ではAさんが一度も見ていないデータが残らなかったためで、改訂の日付と理由を計画書に残しています。
- 結果を見た後の変更:結果を見てから「負けが多いからこの曜日を外そう」「少し期間をずらしてみよう」と条件を変えるのは、すべて新しい試行(Nの加算)です。結果を見てから変えたのか、見る前に変えたのかを日付付きで記録します。
- 別の通貨ペアへの展開:「参考までに」追加しません。転写は、ルールを固定したまま比較対象との差だけを見る手順を先に決めてから行います(第16回)。
研究ログの書き方
宣言が「実行の前」の記録なら、研究ログは検証全体の記録です。トレード日誌の回では、日々のトレード記録とは別のシートに、手法を検証するときだけ研究ログを付けると書きました。 トレード記録と研究記録を分けておけば、日誌を重くせずに、過去に何通り試したかを失わずに済みます。ここでは、そのシートに何を書くかを具体的にします。
| 項目 | 書くこと | 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のままです。ログに「前」と書いてあるから、後で誰が読んでもそう判断できます。
却下した案こそ残す
研究ログで最も抜けやすいのは、採用しなかった案です。Aさんの台帳には「貪欲フィルタ25通り(基準:総pips)→ どれも不採用」という行があります。 何も採用しなかった実行でも、25通りを比べたことに変わりはありませんし、この「不採用」を見たことが、次に物差しをPFへ替える判断につながりました(第3回)。 もしこの行を消していたら、台帳のNは25少なくなるだけでなく、「物差しを替えた」という分かれ道そのものが記録から消えます。
コードで検証するなら、Nを先に書き換える
Pythonなどで検証する場合は、スクリプトの先頭で累計Nを更新し、画面とログファイルの両方に出してから計算に入ると、宣言を書き忘れにくくなります。次は、その最小の形です(読まなくても本文は理解できます)。
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-24 | B | 事前登録ルール1通り(探索期間 2005〜2016年) | 0 → 1 |
| 2026-09-24 | A | グリッド57,600通り(2005〜2016年、コスト0・終値約定、総pips最大・100トレード以上) | 0 → 57,600 |
| 2026-09-24 | A | 貪欲フィルタ25通り(基準:総pips)→ どれも不採用 | 57,600 → 57,625 |
| 2026-09-24 | A | 基準をPFに替えて貪欲フィルタ25通り → 金曜除外・5月除外・RSI>55 | 57,625 → 57,650 |
| 2026-09-24 | A | 2017〜2022年を使い回し、IS上位12案から検証成績が最良の案に乗り換え(3位案) | 57,650 → 57,662 |
台帳には、行の外にもう1つの記録があります。記述統計(選択なし・N外)として計算したものの一覧です:Bさんの近傍8通り、比較対象C1〜C3、Bさんのルールの転写(EURJPY・GBPJPY)、Aさんの利益の分解、月×曜日のマス集計、ドローダウンの再標本化、置換検定、ランダムウォーク、ウォークフォワード。 これらは第10回以降の材料ですが、どれも「見て何かを選んではいない」ことを、計算した時点で書き残しています。
第3回で数えた「実質N」との対応
第3回では、Aさんの開発を分かれ道の図に描き、段ごとに選択肢の数を数えました。その表と、この台帳は1行ずつ対応しています。
- 段①(対象と期間):台帳に行がない。Aさんがチャートを眺めて決めたもので、何通り比べたかの記録が残っていないため。だから台帳の57,662は下限です。
- 段②(グリッド):台帳の2行目(0 → 57,600)。
- 段③(総pips基準のフィルタ):3行目(57,600 → 57,625)。
- 段④⑤(物差しをPFに替えてもう一度):4行目(57,625 → 57,650)。
- 段⑥(検証データで乗り換え):5行目(57,650 → 57,662)。
第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つも出てこないなら、記録がないと考える。
- 物差しは最初から決まっていたか:総pips、PF、Sharpe、勝率のどれで選んだか。途中で替えたか。
- 検証用のデータを何回見たか:「後半で確認した」なら、確認して直したことは何回あるか(第7回)。
- コストと約定の前提:スプレッド、滑り、どの価格で約定させたか(第9回)。
- 日付の付いた事前の記録があるか:ルールを公開した日より後の成績と、前の成績を分けて見せてもらえるか。
この質問に答えられない報告は、嘘とは限りません。ただ、答えられない限り、その成績は「Nが分からない=大きいかもしれない」成績として読みます。 公開される成績は、試した人の中でうまくいった人のものだけが表に出る、という偏りも持っています(第4回の型7)。 最も確かな確認は、作った人がルールを公開した日より後の期間、つまり作った人が見ていない期間の成績です。他人の成績を読む質問は、修了回で10項目にまとめます(第19回)。
よくある間違い
「良い結果が出てから、Nを数える」
結果を見た後に数えると、悪かった実行ほど「設定ミスだった」「参考の実行だった」と外されます。Nは実行する前に更新し、結果によって変えません。 数える時点が結果の後にある限り、数え方そのものが結果に合わせた選択になります。
「記述統計だから、何を見てもN外」
近傍や年別の成績を見るだけならN外です。しかし、それを見て損切りの位置を変えたり、悪い年を除外したりすれば、その時点で新しい試行です。 Bさんが近傍8通りをN外にできたのは、「見るだけで、ルールは変えない」と事前に決め、そのとおりにしたからです。
「Nは覚えておけばよい」
数週間の検証で試した案を、正確に覚えている人はいません。記憶に残るのは、良かった案とその直前の数回です。 過去の検証を振り返ってNを復元するときも、分からない部分は少なく見積もらず、「少なくともN」として多めに扱います。
「失敗した検証はログから消して、きれいにしておく」
失敗した検証の行を消すと、Nが減るだけでなく、「なぜ次にその方向へ進んだか」という分かれ道の記録も消えます。ログは成果の一覧ではなく、判断の履歴です。却下した案と却下理由こそ残します。
実戦課題
今検証している(またはこれから検証する)ルールについて、次の順に記録の仕組みを作ってください。
- 研究ログのシートを作る:日付・仮説ID・データ・時刻規約・期間・N(現在値 → 新値)・結果の前か後か・採否と理由、の8列です。トレード日誌とは別のシートにします。
- 今までのNを復元する:これまでに比べた通貨ペア・期間・パラメータ・フィルタ・物差しを思い出せる限り書き出し、合計を「少なくともN」として1行目に書きます。第3回の実戦課題で描いた分かれ道の図があれば、それを使います。
- 次の実行の前に宣言を書く:対象・計画との一致・Nの更新の3行を書いてから実行します。計画との一致が書けなければ、実行せずに計画を追記します。
- N外にする確認を先に決める:近傍や年別の成績など、「見るだけでルールは変えない」確認を、実行前に列挙しておきます。
- 報告の冒頭にNを書く:成績を人に見せるときは、最初の行にNと、どのNを使ったか(累計か、その選択の分か)を書きます。
やるべきこと/やるべきでないこと
| やるべきこと | やるべきでないこと |
|---|---|
| 実行前に宣言を書き、Nを更新してから実行する | 良い結果が出てからNを数える |
| 期間・通貨ペア・方向・時間足・物差しの選択もNに数える | パラメータの組み合わせだけを数える |
| 却下した案と却下理由を研究ログに残す | 採用した案だけを記録し、失敗した検証を消す |
| 変更のたびに「結果の前か後か」と日付を書く | いつ決めたかを書かずに仕様を書き換える |
| 「見るだけ」の確認を事前に決め、見た後でルールを変えたらN+1にする | 記述統計だからと、見た結果でルールを直してもN外にする |
| 計画にない実行は、計画に追記してから行う | 「参考までに」別の通貨ペアや期間を試す |
| 報告の冒頭にNと、どのNを使ったかを書く | 最良案の勝率とPFだけを示す |
チェックリスト
次の回に進む前に、以下が自分の言葉で説明できるか確認してください。
- Nは実行回数ではなく、結果を見て比べた候補の数であること
- Nに入れるかどうかを「この数字を見て、何かを選ぶか」で判断すること
- 記述統計でも、見た後でルールを変えればN+1になること
- 実行前の宣言の3行(対象・計画との一致・Nの更新)と、それを結果の前に書く理由
- 研究ログの「結果の前か後か」の列が、仕様の修正と新しい試行を分けること
- Aさんの台帳 57,600 → 57,625 → 57,650 → 57,662 の各行が何だったか、57,662が下限である理由
- AさんのN=57,600(下限)とBさんのN=1の違いが、なぜ評価に直結するか
ミニテスト
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が分からない=大きいかもしれない」成績として読み、作った人が見ていない期間の成績で確かめます。