detect_patterns
Detect chart patterns in cryptocurrency candlesticks: double tops/bottoms, head and shoulders, triangles, wedges, flags, and pennants, covering both forming and completed patterns to support technical analysis.
Instructions
[Chart Patterns / Double Top / Head and Shoulders / Triangle] チャートパターン検出(chart patterns / double top / double bottom / head and shoulders / triangle / wedge / flag)。形成中+完成済みを統合検出。表示日時は tz(既定 Asia/Tokyo)で整形。
検出の意味論:
直近の一方向トレンド(上げ続け / 下げ続け)はパターンを構成しないため検出対象に入らない。「直近の値動きが結果に出ない」は多くの場合これであってデータ欠落ではない。実際に走査した範囲は meta.scan(content の「スキャン範囲」行)で確認すること。
ピボットの確定には前後 swingDepth 本が要るため、スキャン窓の両端 swingDepth 本はピボットにならない(swingDepth は時間足ごとに自動スケールする。例: 1hour の実効値は 3)。
limit はスキャン窓の本数であり、同時に「何が検出可能か」も決める。小さすぎる場合は data.warnings に limit_too_small_for_timeframe が載る(content 先頭にも警告行を出す)。
各検出器はパターンの大きさの下限をバー数で持つ。既定 limit(90)ではどの時間足・どの種別も到達可能だが、limit をこれより小さくすると特定の種別だけが静かに 0 件になることがある(下限の表は docs/tools.md の「limit の実効下限」)。
既定 limit(90)は形成中〜完成直後のパターンを見るための窓。過去のパターンの統計(data.statistics の成功率 / 平均リターン)や aftermath を調べるなら limit を上げる(上限 365)。summary / detailed の content 量はほぼ変わらず、増えるのは API 呼び出し回数。
検出が 0 件、または期待した種別が出ない理由を答えるときは view=debug を使う。候補ごとの棄却理由コードが candidates に載る(例: poor_trendline_fit / r2_below_threshold / neckline_above_pre_decline_high。コードの意味は docs/tools.md の「detect_patterns 詳細ガイド」)。
その理由を推測で説明しないこと。 「上昇局面だったので構造的に成立しない」のような一般的なテクニカル分析の知識からの説明は、もっともらしくてもツールの出力に基づいていない。debug の実出力(棄却理由コード、候補が 1 件も積まれていないという事実を含む)だけを根拠にする。
視覚確認: 結果の overlays を render_chart_svg に渡して描画可能。 描画結果は必ずビジュアルとしてレンダリングして表示すること。 チャット本文へのSVGコード直接出力は禁止。
構造化データ (data.patterns[*].range.start/end 等) は後方互換のため UTC ISO 文字列のまま。
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| tz | No | 表示日時のタイムゾーン(既定: Asia/Tokyo)。get_candles の tz と揃える。pattern の表示日時(期間 / 形成期間 / 文脈期間 / ブレイク確認 / 先行トレンド / pivot / スキャン範囲 / 検出パターン分布期間 / 構造図 等)に適用される。intraday(1day 未満の時間足)では日付だけでなく時刻(HH:mm)まで表示する(issue #200。24 本が同じ日付ラベルに潰れてどの足か特定できない問題への対応)。日足以上は暦日のみ。構造化データ(data.patterns[*].range.start/end 等)は後方互換のため UTC ISO 文字列のまま不変。空文字も Asia/Tokyo にフォールバック。 | Asia/Tokyo |
| pair | No | btc_jpy | |
| type | No | 1day | |
| view | No | view は content の量を制御します。量は summary < detailed < full の順で、full は常にそのツールの最重量です。view が structuredContent から**フィールドを削ることはありません**(その view でしか計算しないデータを足すツールはあり、その場合は当該 view の説明に明記しています)。content[0].text は LLM への唯一のチャネルなので、軽い view は「短い表示」ではなく「LLM が明細を受け取らない」を意味します。 **`実効パラメータ(入力値ではない):` 行は 4 view すべて(`debug` を含む)に出る。** 解決後の実効値と由来(`(auto)` / `(指定)`)で、構造化データは meta.effective_params。`swingDepth` / `minBarsBetweenSwings` / `tolerancePct` はスキーマ既定値が sentinel なので、**渡した値と行の値が食い違うことがある**(#182 / #184)。**位置は view で違う**(行頭ラベルが一意なので機械的な抽出には影響しない): `debug` はヘッダの直下、summary / detailed / full は次の 2 行の**下**(=ヘッダから 4 行目)。 summary / detailed / full では、ヘッダ直下に 2 行が出る(**別の量なので混同しないこと**): - `スキャン範囲: <先頭足> ~ <末尾足>(N本)` — 検出器に実際に渡した足のレンジ。1day 未満の時間足では時刻まで表示する。構造化データは meta.scan。 - `検出パターン分布期間: <最古 range.start> ~ <最新 range.end>(N日間)` — **検出されたパターンの分布**であってスキャン窓ではない(旧ラベル「検出対象期間」)。 さらに summary / detailed / full には `検出経路:` 行が 1 行出る(実効パラメータ行の次。**パターン 0 件のときは出ない**。`debug` はパターンを列挙しない view なので出さない)。`strict N 件 / relaxed フォールバック由来 M 件(relaxed_triple_x1.25×1, …)` の形で、relaxed 経路が拾い直した件数と段の内訳を申告する。**relaxed が 0 件でも `全 N 件とも strict(relaxed フォールバック由来は 0 件)` と明示する**——行が無いことを「relaxed なし」と読ませないため(値が無いのか content に出していないのかを呼び出し側が区別できない状態が #189 / #191 の直した欠陥)。構造化データは data.patterns[]._fallback。 **`検出内訳:` 行は 4 view すべて(`debug` を含む)に出る**(issue #200)。`検出 N件 → 重複統合 -M → [現在時点フィルタ -K →] ライフサイクル除外 -L → triple×H&S排他 -X → 出力 P件` の形で、globalDedup / requireCurrentInPattern(既定 false)/ ライフサイクル絞り込み(includeForming 等)/ triple×H&S の型間排他(issue #218。**減るのは triple_* だけ**)の4 段でどれだけ減ったかを申告する。`現在時点フィルタ` は 0 のとき区間ごと省くが、`重複統合` / `ライフサイクル除外` / `triple×H&S排他` は 0 でも省かない。構造化データは meta.reduction(`detected` = `dedupMerged + currentFiltered + lifecycleExcluded + tripleHsExcluded + output`)。 - summary: ヘッダ + 分類内訳 + 直近30日/90日件数 + 上記 2 行 + 実効パラメータ行 + 検出経路行 + 検出内訳行 + 検討パターン。個々のパターンの詳細は content に出ない(**どのパターンが relaxed 由来かも出ない**——届くのは検出経路行の件数だけ)。 - detailed(既定): 上位 5 件の詳細。6 件目以降は content に出ない。検出件数が 5 件以上のときは見出し `【検出パターン】` に `N / 全 M 件(K 件省略。全件は view=full)` の形で件数を申告する(並び順は confidence 単独ではなく status → confirmation → confidence → 直近性の優先順。ちょうど 5 件なら `省略なし` になる)。5 件未満では省略が構造的に起こり得ないため申告行自体を出さない。 relaxed 由来のパターンは見出し行の末尾に `[relaxed_triple_x1.25]` が付く(`data.patterns[]._fallback` と同じ値。印が無ければ strict 経路で拾えた)。structuredContent に usage_example を**足す**。 - full: 全件の詳細(double_top / double_bottom では山谷 3 点の pivot 行も出る)。relaxed 由来の印は detailed と同じ。本ツールの最重量。 - debug(**階梯外**): swings / candidates のみ。**検出パターンもスキャン範囲 / 検出パターン分布期間の 2 行も検出経路行も content に出ない**(実効パラメータ行と検出内訳行だけは出る——`accepted N件 → data.patterns M件` のような疑問が最も生じやすい view なので診断に要る)。出力を置換する view なので full の上位集合ではない。structuredContent に data.candidates を**足す**。 candidates は `patterns` で要求した種別(エイリアスは展開して照合)に**絞って**返す。`patterns` 未指定なら全種別。絞らないと cap(200件)を要求外の種別が食い潰し、要求した種別の棄却理由が押し出される。 **cap で押し出しが起きた場合は申告する**(issue #180)。`meta.debug.candidatesTotal` が絞り込み後の総数、`meta.debug.candidatesOmitted` が押し出された件数で、content には`【Candidates】 200 / 全 N 件(M 件省略)` の形で出る(押し出しが無ければ「省略なし」)。トリムは accepted を先に並べてから切るので**押し出しは棄却理由から始まる**。`candidates` に `accepted:false` が 1 件でも残っていれば accepted は全件収まっており、押し出されたのはすべて棄却理由(全 200 件が `accepted:true` のときだけ accepted も押し出されうる)。`swings` 側も同様に `swingsTotal` / `swingsOmitted` を返す(`swings` は先頭から残すので落ちるのは直近側)。 **棄却理由の集計は content 側で済ませてある(数え直さないこと。issue #191)。** `【Candidates】` の見出しの直後・候補の列挙より前に 3 段の集計ブロックが出る: `▼ 候補の内訳: 全 69 件 = accepted 7 件 + rejected 62 件(cap 省略なし=全候補の内訳)` `▼ 棄却理由の内訳(type 別 → reason 別。合計は上の rejected 62 件と一致する)` ` - triple_top 40 件: three_peaks_not_level 21 / valleys_missing 12 / valley_too_shallow 7` ` - triple_bottom 22 件: peak_too_shallow 15 / peaks_missing 7` 内訳は **type と reason の 2 軸**で数える(`rising_wedge:slopes_not_same_direction` と `falling_wedge:slopes_not_same_direction` を同じ行に潰さないため——同じ reason でも type が違えば意味が違う)。type 行の合計は上の rejected 件数と、行内の reason の合計はその type の件数と必ず一致する(多すぎる場合は残余に畳むが、畳んだ分も件数で残す)。 **その下に `▼ reason 横断合計` が 1 行出る**(type を畳んで reason だけで合算したもの。issue #193): `▼ reason 横断合計(type を跨いで reason だけで合算。…。合計は上の rejected 62 件と一致する)` ` - three_peaks_not_level 21 / peak_too_shallow 15 / valleys_missing 12 / valley_too_shallow 7 / peaks_missing 7` **横断合計を自分で足さないこと。** 「棄却理由を多い順に」を type 別行から手集計すると外れる(別のライブ実測: type 別の数値をそのまま横断合計として提示し、続いて`no_convergence(41) > slopes_not_same_direction(66)` という不等号が成立しない式を出力した)。`reason` が `type` を跨ぐ実行ほど外れやすいので、跨ぎが起きうる **type が 2 種別以上のときだけ**出す(1 種別なら type 行がそのまま横断合計なので出さない)。type 別の内訳を**置き換えるものではない**——同じ reason でも type ごとに意味が違いうる(`slopes_not_same_direction` は rising / falling で別の話)ので、**帰属は必ず type 別行で見る。** 上限(10 種)を超えた分は type 行と同じ `他 N 種 M` に畳み、cap 飽和時は type 別行と同じ `**全 N 件の内訳ではない**` が付く。 **cap で押し出しが起きているときは分母が「表示分」に変わる**: `▼ 候補の内訳: 表示 200 件 = accepted 7 件 + rejected 193 件(全 289 件のうち 89 件は cap で省略されており、**この集計に入っていない**)` となり、内訳の見出しにも「**全 289 件の内訳ではない**」が付く。この状態の内訳から母集団(全 289 件)の傾向を語らないこと——censored な内訳からの誤帰属は実際に起きている(#152 → #167)。全体の内訳が要るなら `patterns` で種別を絞って呼び直す。`meta.debug.candidatesTotal` の申告が無い呼び出しでは分母が `受け取った N 件` になり、省略の有無は不明として扱う。 `accepted:false` は候補生成の時点での棄却(例: `head_not_higher`。`includeInvalid` では拾えない)で、`status` を持たない。`accepted:true` は**検出器が候補を組み立てた**ことを示すだけで、`data.patterns` に残ったことは意味しない(形成中パスの成功エントリは `globalDedup` より前に積むため、重複除去で最終出力から消えることがある)。エントリが持つ `status` / `breakoutDirection` も**組み立てた時点の観測値**であって、その後 `status=invalid`/`expired` になったかどうかはcandidates からは分からない。それを見るには `data.patterns` 側を `includeInvalid=true` で見る(区別は includeInvalid の説明を参照)。 | detailed |
| limit | No | スキャン窓の本数。**直近 limit 本がそのまま検出器に渡る**(指標 warmup 分は含まない)。 スイング検出で窓の前後 swingDepth 本ずつがピボット候補から外れるため、時間足の既定 swingDepth に対して小さすぎると構造上ほぼ何も検出できない(日足の既定 swingDepth=6 では 23 本未満)。その場合は data.warnings に `limit_too_small_for_timeframe` を載せ、content 先頭にも警告行を出す。 逆に既定の 90 は「いま形成中〜完成直後のパターンを見る」ための窓なので、**過去のパターンの統計(data.statistics の成功率 / 平均リターン)や aftermath を調べる用途では上げる**(上限 365)。view=summary / detailed の content 量はほぼ変わらず、増えるのは API 呼び出し回数。 | |
| patterns | No | Patterns to detect. Recommended params (guideline): - double_top/double_bottom: leave swingDepth / tolerancePct / minBarsBetweenSwings unset — the timeframe-auto values ARE the recommendation. Passing 7 / 0.04 / 5 explicitly does not pin those numbers: they are the schema defaults and get replaced by the timeframe-auto values (see each param). - triple_top/triple_bottom: tolerancePct≈0.05 - triangle_*: tolerancePct≈0.06 - pennant: swingDepth≈5, minBarsBetweenSwings≈3 - The ≈ values above are absolute targets, NOT "looser than the default". Compare them with the timeframe-auto table in each parameter first: tolerancePct is already 0.05 on 1hour/4hour (≈0.05 is a no-op there) and already 0.06 on 15min/30min (≈0.05 TIGHTENS it), and swingDepth / minBarsBetweenSwings are already 5 / 3 on 4hour/8hour/12hour. - head_and_shoulders/inverse_head_and_shoulders: shoulder-level tolerance is tolerancePct (same "bigger = looser" meaning as other types); to loosen how much the head must stand out above/below the shoulders, use headProminencePct instead (opposite direction: bigger = stricter). Aliases: 'flag' → bull_flag + bear_flag, 'pennant' → bull/bear pennant, 'triangle' → asc/desc/sym. | |
| swingDepth | No | スイング検出の窓の深さ。ピボット(山 / 谷)と認めるのに前後何本ぶんの比較を要求するか。大きいほどピボットが減り、検出されるパターンも減る。窓の前後 swingDepth 本はピボット候補から外れるので limit の実効下限にも効く(limit の説明を参照)。 **未指定なら時間軸オート**: 1min/5min=2, 15min/30min/1hour=3, 4hour/8hour/12hour=5, 1day=6, 1week=7, 1month=8。 **⚠ 既定値 7 を明示的に渡しても時間軸オートに置換される**(7 は「未指定」の sentinel 扱い)。`swingDepth=7` は 1hour では 3、1day では 6 として実行される。指定した値をそのまま効かせたいなら 7 以外を渡すこと(6 や 8 はそのまま通る)。**深くしたい / 浅くしたいときは上の時間軸オート値と比べて選ぶ**(例: 1hour の auto は 3 なので、7 を渡すのは「深くする」ではなく「auto に戻す」)。 **#242 の経路ゲート(peak_after_last_pivot / trough_after_last_pivot)と再進入チェックも同じ swingDepth のピボット列で判定するため、深さを増やすと発火しにくくなる**(同じ値動きで swingDepth=3 では invalid、6 では完成済みになりうる。issue #251)。窓の終端 swingDepth 本の足はピボットになれないため、そこにある戻しは経路ゲートが見ない(同じ値動きでも limit で completed / invalid が変わりうる。issue #277)。 | |
| tolerancePct | No | 同水準判定の許容誤差。大きいほど判定が緩くなる。head_and_shoulders / inverse_head_and_shoulders では肩の左右差の許容誤差にのみ使う(ネックライン水平度は本パラメータに依存しない固定閾値。頭が肩よりどれだけ突出すべきかは headProminencePct が別に持つ。issue #149——旧実装はここに頭の突出要求も相乗りしており、肩では「大きいほど緩い」・頭では「大きいほど厳しい」が同じ値に同時にかかっていた)。 **未指定なら時間軸オート**: 1hour/4hour=0.05, 8hour/12hour=0.045, 15min/30min=0.06, 1week=0.035, 1month=0.03, その他=0.04。 **⚠ 既定値 0.04 を明示的に渡しても時間軸オートに置換される**(0.04 は「未指定」の sentinel 扱い)。1hour では `tolerancePct=0.04` が 0.05 として実行されるので、**0.04 → 0.05 に「緩めた」つもりの再検出は 1hour では何も緩んでいない**(前後とも実効 0.05)。指定した値をそのまま効かせたいなら 0.04 以外を渡し、**緩める / 締めるの判断は上の時間軸オート値との比較で行うこと**(1hour の auto は 0.05 なので、緩めるなら 0.055 以上。0.045 は auto より厳しい)。 | |
| includeForming | No | 形成中パターンを含める | |
| includeInvalid | No | 無効化済み(`status=invalid`)および期限切れ(`status=expired`)のパターンを含める。期限切れ = 第2構成点の確定から突破確認窓を過ぎてもネックラインを突破しなかった候補で、既定ではノイズになるため出力されない。 **`true` にしても拾えるのは、一度パターンとして成立してから無効化された `status=invalid` / `expired` のものだけ。** `head_not_higher` / `shoulders_not_near:both` 等、構造要件を満たさず**候補生成の時点で**落ちたものは `status` 自体を持たないため、`includeInvalid` では拾えない(見るには `view=debug` の `data.candidates` を使う。`accepted:false` の `reason` に理由が入る)。 | |
| includeCompleted | No | 完成済みパターンを含める | |
| headProminencePct | No | head_and_shoulders / inverse_head_and_shoulders 専用: 頭が両肩よりどれだけ突出していなければならないかの最小要求率。**tolerancePct とは向きが逆で、大きいほど判定が厳しくなる**(最小要求を引き上げるため)。緩めたい(=頭の突出要求を下げたい)ときは値を小さくする。 未指定時は本パラメータ専用の時間軸オート値(1min=0.0011, 5min=0.0024, 15min=0.0041, 30min=0.0058, 1hour=0.0083, 4hour=0.0163, 8hour=0.0231, 12hour=0.0283, 1day/1week/1month/その他=0.04)を使う。**この表は tolerancePct の時間軸オート表とは別物**(issue #198。1hour は tolerancePct では 0.05 だが本パラメータでは 0.0083 —— 両パラメータは意味の向きが逆なので同じ表を共有できない。旧実装は #198 以前、暫定的に tolerancePct の表を流用しており、1hour が 1day より頭の突出を 25% 厳しく要求する逆転が起きていた)。tolerancePct を明示的に変更しても本パラメータには影響しない(H&S の頭の判定は tolerancePct から完全に独立)。 | |
| currentRelevanceDays | No | ||
| minBarsBetweenSwings | No | ピボット(山 / 谷)どうしに要求する最小間隔(バー数)。大きいほど近接ピボットが排除され、検出されるパターンも減る。 **未指定なら時間軸オート**: 1min/5min=1, 15min/30min/1hour=2, 4hour/8hour/12hour=3, 1day=4, 1week=5, 1month=6(swingDepth と同じ表の別列。両者は必ず同じ時間軸オートから来る)。 **⚠ 既定値 5 を明示的に渡しても時間軸オートに置換される**(5 は「未指定」の sentinel 扱い)。`minBarsBetweenSwings=5` は 1hour では 2、1day では 4 として実行される。指定した値をそのまま効かせたいなら 5 以外を渡すこと(4 や 6 はそのまま通る)。**広げたい / 狭めたいときは上の時間軸オート値と比べて選ぶ**(例: 1hour の auto は 2 なので、5 を渡すのは「広げる」ではなく「auto に戻す」)。 | |
| requireCurrentInPattern | No |