「負けたのは、わたしの翻訳」。そう書いて閉じたとき、たぶん、ほっとしていた。
たぶん、というのは、それが分かったのが次の動画を半分まで訳したころだったから。
Abstract
- 出典: Pro Trading School「Learn Every ICT Concept in 17 Minutes」
- 対象: OANDA practice / USDJPY / M5(bid・ask)の固定抽出から集約した完全な15分足と、NY17:00境界の日足。データ・期間・約定モデル・バイアス・サイズ・コストは、前回の検証と完全に同一
- やったこと: 17分の動画が語る同名のオーダーブロックを、安値を割って戻す動き → 構造転換 → 隙間 → ゾーンへの戻り、という複合の機械ルールへ翻訳して検証。あわせて、前回訳した40分側の検出ゾーン、および流通している実装の出力と、指している場所が重なるかを測定
- 結果: 事前に決めた主判定(決済後残高のリターンがプラス、かつ固定5区間中3区間以上で実現損益がプラス)は不成立
- 非対象: 二つの翻訳の優劣判定、流通実装を正解基準とすること、出典者・原手法の評価、EURUSDや他期間への一般化、実注文の約定再現、実運用の可否
| 指標 | 主版 |
|---|---|
| 検出ゾーン | 321 |
| トレード数 | 194 |
| リターン | -23.132819% |
| 最大ドローダウン(決済後残高) | -27.832202% |
| プロフィットファクター | 0.793311 |
| 勝率 | 38.659794% |
| プラスの固定区間 | 2 / 5 |

1. Introduction — 正しい版
再生リストに残していた動画を開く。17分。同じ名前を、別の人が話している。
40分のほうを訳したときは、余白を埋めるのに時間がかかった。今度は短い。要約みたいなものだろうし、たぶんすぐ終わる。
訳し比べれば、自分の翻訳のどこがズレていたか分かるはずだった。
そう思って、書き取りを始めた。
2. Method — 同じ名前の下で
2.1 最初の違いは、細部じゃなかった
17分のほうは、有効なオーダーブロックの条件を並べていく。その一番目に、こうある。
there must be an imbalance also known as a gap or inefficiency
隙間がなければならない。ローソクとローソクのあいだに、価格が通らなかった空白があること。
……40分のほうには、この条件がなかった。
もう一度、前に書いた凍結表を開いて確かめる。陰線。窓の中の最安値。高値の上抜けで有効化。隙間の話は、どこにも出てこない。
説明の順番が違うとか、言い方が違うとか、そういうことだと思っていた。条件そのものが違う。
隙間を機械の条件にする。三本並べて、後ろの足の安値が、前の足の高値より高いこと。等号は入れない。
2.2 探しても、ない
入る場所の話になる。ゾーンまで戻ってきて、そこで跳ね返されたら入る、と言っている。
具体的な価格は、言わない。
ゾーンの50%。半分まで引きつけて入る、というのを、どこかで読んだ。オーダーブロックの入り方として、当たり前みたいに書いてあった。
探す。ない。
戻して聞き直す。この人は、半分とも、中心とも、言っていない。
どこかで見た数字だから、どこかにはあると思っていた。ここには、ない。どこから来たのかも分からない。
分からないものは置けないので、捨てる。ゾーンの境界に指値を置く。戻ってきて最初に触るところ。
2.3 順番は、自分で組んだ
もうひとつ、決めることがあった。
安値を割ってから戻す動き——だましのブレイクの話は、動画の前半のセクションにある。構造転換のほうは、後半のオーダーブロックの条件として出てくる。
この二つが「まず安値を狩って、それから構造が変わって、そこにできたオーダーブロック」という一続きの流れとして説明されているわけではない。並んでいるだけ。
つなげたのは、わたし。
安値を割って終値で戻す。そこから12本以内に構造が変わる。そのあいだに隙間がある。その区間の最後の陰線を、オーダーブロックにする。
この順番は、17分の中にはない。
2.4 凍結
隙間を判定しているのは、ここ(ict_ob.py):
for center in range(first_center, mss_index):
before = frame.iloc[center - 1]
after = frame.iloc[center + 1]
if side == "long":
if float(after["bid_low"]) > float(before["bid_high"]):
return True
40分のほうの検出器には、これに当たる関数がない。
| 項目 | 固定条件 |
|---|---|
| データ・期間・区間・バイアス・サイズ・コスト | 前回の検証と完全に同一 |
| 検出 | 安値を割って終値で戻す → 12本以内に構造転換 → その区間に隙間が1本以上 → 区間内の最後のbid陰線をオーダーブロックとする(買い側。売りは鏡像) |
| ゾーン | オーダーブロック足の全レンジ(ヒゲ込み) |
| エントリー | ゾーン境界への指値(買いはbid_high)。50%中点は不採用。構造転換を確認した足の次から有効 |
| 損切り / 利確 | 買い: オーダーブロック足のbid_lowそのもの / 確定済み直近スイング高値(遡り400本)。売りは鏡像 |
| 約定・ゾーン運用 | 前回と同一(bid判定系列、方向別quote、同一足はSL優先、待機ゾーン1・置換式、強制手仕舞いなし) |
| 調整 | 結果を見て条件を変えない |
同じにできるところは、全部同じにした。違うのは検出の条件と、狙う場所の定義だけ。

図1. 条件ごとの絞り込み。安値を割って戻した3,455回のうち、12本以内に構造が変わったのが768回。そこから隙間なしで259回、反対色の足が見つからずに184回が落ちる。残った325のうち、構造転換を確認した足の時点でバイアスが揃わない4回を見送り、321ゾーンが残る。
走らせる。
3. Results — 重ならない
3.1 数字
入力のhashを固定値と照合する。一致。二回走らせて、結果のhashも一致。
| 指標 | 結果 |
|---|---|
| 検出ゾーン | 321 |
| トレード数 | 194 |
| 最終残高 | 768,671.812円 |
| リターン | -23.132819% |
| 勝率 | 38.659794% |
| 最大ドローダウン(決済後残高) | -27.832202% |
| プロフィットファクター | 0.793311 |
| 平均実現R | -0.124158 |
| プラスの固定区間 | 2 / 5 |
| 主判定 | 不成立 |
-23.13%。プラスは五つのうち二つ。主判定は、不成立。
同じ結論だ。
3.2 途中の形が違う
前に走らせたほうと、並べてみる。
| 40分の翻訳 | 17分の翻訳 | |
|---|---|---|
| 検出ゾーン | 1,121 | 321 |
| 決済 | 534 | 194 |
| 勝率 | 11.235955% | 38.659794% |
| 決済理由 | SL 470 / 窓開きSL 4 / TP 60 | SL 116 / 窓開きSL 3 / TP 75 |
決済の回数は3分の1近くまで減っている。なのに、利確に届いた回数だけ増えている。60回が、75回。
結論は同じところに着いたのに、途中がぜんぜん違う。
どちらが正しい翻訳なのか、と一瞬考えて、その問いの立て方が変だと気づく。
3.3 固定した5区間
| 区間 | 取引数 | 実現損益 |
|---|---|---|
| 1 | 19 | -115,976円 |
| 2 | 49 | +15,212円 |
| 3 | 54 | +71,596円 |
| 4 | 37 | -97,484円 |
| 5 | 35 | -104,676円 |

図2. 920暦日窓を開始日から184日ずつ5区間に固定分割。プラスは区間2と3。区間ごとの標本は19〜54本で、傾きの理由までは、ここからは言えない。
プラスは区間2と3。事前に決めた「3区間以上」には届かない。観測は、そこまで。
3.4 同じ場所を指しているか
先に、重なりの数え方を決めておく。
価格の範囲が交わっていて、有効だった時間も交わっているとき、その二つは重なったことにする。買いと売りが一致しているかは問わない。約定まで行かなかったゾーンも、全部数に入れる。
40分の翻訳が見つけた1,121のうち、17分の翻訳と重なったのは、46。
17分の翻訳が見つけた321のうち、40分の翻訳と重なったのは、45。
4%と、14%。

図3. 三つの定義を二つずつ突き合わせ、それぞれが自分の検出ゾーンのうちどれだけ相手と重なったかを示す。母数が違うので、同じ組でも向きによって割合が変わる。流通実装の27件は期間中の全検出数ではなく、関数を通したあとに残った行(Appendix E)。
3.5 ゼロ
もうひとつ、突き合わせる先がある。
オーダーブロックを検出するライブラリが公開されていて、そこそこ使われている。デフォルトのまま、同じ15分足を通す。
40分の翻訳とは、15。
17分の翻訳とは、0。
一件も重ならない。
数える手が、止まった。
4. Discussion — 答え合わせ
4.1 母集団が違う
0という数字を見たあとで、そのライブラリが何を返しているのかを確かめた。
返ってきた27件は、期間中に見つけた全部じゃない。一度検出したあと、反対側へ抜けたものを消して、最後に残った行だった。
スイングの取り方も違う。デフォルトは前後50本を見る。真ん中の足がスイングかどうかを、後ろの50本まで見てから決める。全部終わったあとで振り返って貼るラベルで、その時刻に手元で使える判定ではない。
だから0%は、このライブラリが間違っていることを示さない。示せるようにできていない。
4.2 答え合わせ
答え合わせをしにいったつもりだった。
相手は、全部見終わってから貼るラベルだった。
4.3 名前
三つ並んでいる。
40分の人が話したものを、わたしが訳したもの。17分の人が話したものを、わたしが訳したもの。誰かが実装して公開しているもの。
全部、オーダーブロックという同じ名前で呼ばれている。そして、ほとんど同じ場所を指していない。
「負けたのは、わたしの翻訳」と書いたとき、少しほっとしていた。
あれは、引き受けられたからじゃなかった。正しい版がどこかにあると、まだ思っていたからだ。自分のがズレているなら、ズレていない本物がどこかにあるはずで、それを見つければいい。そういう場所を、外に探していた。
名前は、そこにあるものを保証しない。
1,121と321を、重ねてみる。
重なっていたのは、46だけだった。次は、そこを見に行く。
Appendix — 再現条件と技術的な境界
A. 入力と同一性
前回の検証と同じ固定入力を使う。
| 項目 | 値 |
|---|---|
| source / environment | oanda_rest_v20 / practice |
| instrument / granularity / price | USD_JPY / M5 / BA、complete=1のみ |
| 固定抽出範囲 | [2024-01-01T22:00:00Z, 2026-07-14T10:05:00Z) |
| M5行数 | 188,981 |
| M5抽出SHA-256 | f6d0e1cd1bd50ec11f7f3f0bd34e31b61a39970a687f3c5ac83682ae2ea1d512 |
| complete M15 / 不完全bucket | 62,957 / 61 |
| 採用した日足 / 不採用 | 656 / 1 |
| 取引窓 | ET [2024-01-06, 2026-07-14) の920暦日、5区間×184日 |
日足バイアス、スイングの確定遅れ(前後2本・2本あとに確定)、ポジションサイズ(初期残高100万円、リスク1%、証拠金率4%)、コスト(手数料0、通常スリッページ0、スワップ0)は前回と同一。ただし手数料等を0にしても無コストではない——買いはask、売りはbidで約定させているため、bid/ask差は入力価格の側にコストとして含まれている。完全再計算には同一の非公開SQLiteが必要で、行単位データは同梱しない。
B. 翻訳した条件(買い側。売りは鏡像)
- 安値の狩り:
bid_lowが確定済み直近スイング安値を下回り、かつbid_closeがその水準より上で終わること - 構造転換: 上記の足から12本以内に、
bid_closeが直前に確定していたスイング高値を上抜けること。超えたら破棄 - 隙間: 上記の区間内に、
bid_low[t+1] > bid_high[t-1]を満たす三本並びが1本以上あること(厳密不等号)。なければ破棄 - オーダーブロック: 安値の狩り以降・構造転換の確認足より前にある、最後のbid陰線。なければ破棄
- ゾーン: そのローソクの
[bid_low, bid_high](ヒゲ込みの全レンジ) - エントリー: ゾーン境界(買いは
bid_high)への指値。構造転換を確認した足の次の足から有効 - 損切り: オーダーブロック足の
bid_lowそのもの(売りはask_highそのもの) - 利確: 確定済みスイング高値のうち、エントリー価格より上にあるものの直近(売りはエントリー価格より下にある直近スイング安値)。探索範囲はエントリー足を含まない直前400本の完全15分足。条件を満たす水準がなければ見送り
- 同一足の扱い: 指値が足の途中で成立した場合、その足での利確は無効とし、次の足から有効にする。損切りは悲観側として、成立した足から判定する。始値の時点ですでに指値条件を満たしていた場合だけ、その足の利確も有効とする
- 「安値の狩り → 構造転換 → 隙間 → 戻り」という一続きの構成は、出典の中で結合して語られているものではなく、本検証が組んだ順序である
C. 検出とゾーンの内訳
- 検出: 安値の狩り 3,455(うち新しい狩りへ置き換え 2,056) → 12本以内に構造転換せず 631 / 構造転換 768 → 隙間なし 259 → 反対色の足が見つからず 184(買い側で陰線なし 118 / 売り側で陽線なし 66) → 残り 325 のうち、構造転換を確認した足の時点でバイアスが条件と揃わず見送り 4 → ゾーン 321
- ゾーンの方向: 買い 210 / 売り 111
- ゾーンのその後: 有効化 321 → 消費 270(利確水準が見つからず見送り 4 / 証拠金上限で見送り 72 / 約定 194)、無効化 5、置き換え 46
- 決済の方向: 買い 109 / 売り 85(ゾーンの方向とは母数が異なる。約定まで進んだものだけの内訳)
- 決済理由: SL 116 / 窓開きSL 3 / TP 75
D. 重なりの定義と全組合せ
- 価格は閉区間、有効時間は半開区間。両方が交差したときだけ重なったとする
- 買い・売りの一致は要求しない(事前に凍結していないため、方向一致率を後から主指標にしない)
- 約定まで行かなかったゾーン、利確水準なしで見送ったゾーン、即座に置き換えられたゾーンも、すべて母集団に含める
- 消費・無効化の足内時刻はOHLCから復元できないため、双方に同じ規則を当て、その足の終わりまで有効として扱う
| 組合せ | 左の重複 / 総数 | 割合 | 右の重複 / 総数 | 割合 |
|---|---|---|---|---|
| 40分の翻訳 → 17分の翻訳 | 46 / 1,121 | 4.103479% | 45 / 321 | 14.018692% |
| 40分の翻訳 → 流通実装 | 15 / 1,121 | 1.338091% | 10 / 27 | 37.037037% |
| 17分の翻訳 → 流通実装 | 0 / 321 | 0% | 0 / 27 | 0% |
左右で件数が違うのは、一つのゾーンが相手側の二つと重なる組があるため。重複ペアはそれぞれ46 / 15 / 0。
E. 流通実装の詳細と制約
smartmoneyconcepts==0.0.27、パラメータはデフォルトのまま(swing_length=50等を明示指定していない)- 同じ完全15分足のbid OHLCVを入力。約定と損益は計算していない(ゾーンの比較のみ)
- オーダーブロック: raw 27行、記事窓内27(買い 23 / 売り 4)。うち反対側へ抜けたもの 2、データ終端まで残ったもの 25
- 流動性: raw 156行、記事窓内155(買い 77 / 売り 78)。関数出力の監査だけに使い、重なり率には含めない
- この27件は期間中の全検出数ではなく、関数を通したあとに残った行である
- デフォルトのスイング判定は前後50本の中央窓を使う。全標本を見たあとの回顧的なラベルであり、その時点で利用可能な非先読みの検出時刻ではない
- したがって、この比較は「流通している実装の最終出力との突き合わせ」であって、正解との照合ではない
F. 指標の定義と限界
- リターン:
最終残高 ÷ 1,000,000 − 1。最大DDは初期残高と各取引の決済後残高から算出し、保有中の時価評価を含まない - PF: 総利益 ÷ 総損失の絶対値。実現R: 方向別の単位あたり損益 ÷ 初期リスク
- 主判定は決済194件(30件以上)を前提に判定した
- 15分足のOHLCから足の中の価格経路は復元できない。同一足でSL優先とするのは悲観側の仮定
- ここから言えないこと: 二つの翻訳の優劣、流通実装を正解基準とすること、「オーダーブロック一般の一致率」、原手法や出典者の評価、実運用可能性、EURUSDや他期間への一般化
G. 再現コードと確認
- 再現コード: GitHub
- 参照結果の再計算:
python chapters/season2/ch04_ict_order_blocks/compare.py --db "$SOURCE_DB" --repeat 2(検出・約定・比較まで二度実行し、結果hashの一致を要求) - 独立検証: 同chapterの
verify.py。集計のみのrow-freeモードと、トレード明細から主要値を再計算する完全モード - 条件・version・hashは
results/reference/ch04_ict_order_blocks/manifest.jsonに固定。テストは全135件PASS
この固定条件とデータ仕様に基づく検証です。データ仕様の変更・欠損・修正などで結果は変わりえます。投資助言ではなく、売買判断はご自身の責任で。
