diff --git a/AGENTS.md b/AGENTS.md index 8fe6360..232bc82 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -2,6 +2,9 @@ 株式 (日本株・米国株、現物) のスクリーニングと保有分析。**発注機能は持たない** (分析・提案のみ)。 TradingCopilot (仮想通貨) の兄弟プロジェクト ([ADR-0001](docs/adr/0001-separate-sibling-project.md))。 +両プロジェクトの機能差、意図的差分、共通化候補は +[`docs/sibling-project-comparison.md`](docs/sibling-project-comparison.md) を正とする。 +関連領域を変更するときは、同文書の比較表と更新契機を確認する。 **設計判断の理由・却下した代替・その時点の測定値は [`docs/adr/`](docs/adr/README.md) にある。** このファイルには結論とリンクだけを置く。判断を変えるときは新しい ADR を書いてから実装する diff --git a/README.md b/README.md index fd064a6..c3e43ee 100644 --- a/README.md +++ b/README.md @@ -7,6 +7,8 @@ 仮想通貨向けの兄弟プロジェクト TradingCopilot から指標エンジンを移植しているが、 コードは共有せずコピー流用している。 +両プロジェクトの機能差、意図的差分、共通化候補は +[`docs/sibling-project-comparison.md`](docs/sibling-project-comparison.md)を正とする。 ## 全体像 diff --git a/docs/adr/README.md b/docs/adr/README.md index 88f8950..0f500e5 100644 --- a/docs/adr/README.md +++ b/docs/adr/README.md @@ -40,6 +40,9 @@ ADR の役目。 なく、取り消しコストも低い。理由は `AGENTS.md` と `ruff.toml` に置いてある - **発注機能を持たないこと** — 規範としては最上位だが、代替を検討して落とした記録が無い。 隔離の理由は [ADR-0001](0001-separate-sibling-project.md) の結果節にある +- **StockCopilot と TradingCopilot の現行機能差** — 正は + [`docs/sibling-project-comparison.md`](../sibling-project-comparison.md)。 + 将来の設計判断ではなく、実装に合わせて更新する比較表として管理する - **ジャーナルの書式**([#19](https://github.com/Ries630/StockCopilot/issues/19)) — 正は `journal/README.md` にあり、ADR にすると二重管理になる diff --git a/docs/sibling-project-comparison.md b/docs/sibling-project-comparison.md new file mode 100644 index 0000000..4dcd7d7 --- /dev/null +++ b/docs/sibling-project-comparison.md @@ -0,0 +1,189 @@ +# StockCopilotとTradingCopilotの比較 + +StockCopilotとTradingCopilotは、同じ指標セットと候補抽出の考え方を持つ。 +しかし、StockCopilotは発注を禁止し、TradingCopilotは承認後の本番発注まで担う。 +似ている実装をそのまま共有すると、この安全境界まで結合する可能性がある。 + +この文書は、両プロジェクトの現行差分を一つの場所で管理し、意図しない乖離の発見と共通化の判断に使う。 +StockCopilotを基準に書くが、どちらかを上位の実装とはみなさない。 + +## 比較の基準 + +比較表の事実は、次の状態を基準に確認した。 + +| プロジェクト | 基準 | 確認日 | +|---|---|---| +| StockCopilot | `origin/main` の `f2a48ef3f0240ae69f002bd10cedfeefcfa0a2ea` | 2026-08-26 | +| TradingCopilot | ローカルチェックアウト。Gitメタデータなし | 2026-08-26 | + +TradingCopilotにはコミット基準がないため、同プロジェクトの記述は確認日時点のスナップショットである。 +将来Git管理を始めたら、確認日だけでなく基準コミットも記録する。 +TradingCopilotが非Gitの間、両プロジェクトの乖離をCIで自動検出することはできない。 +現在は関連変更時に本書の更新契機を照合し、Git管理の開始後に共通フィクスチャのCI化を検討する。 + +この公開文書には、実際の保有銘柄、数量、口座情報、注文内容、資格情報を記録しない。 +TradingCopilot側のパスは、同プロジェクトのルートからの相対パスで表す。 + +各比較表の現状記述は、ソースとプロジェクト指示から確認した事実である。 +「共通化候補の優先順位」と「再評価のサイン」は評価案であり、採用済みの設計判断ではない。 + +## 差分の分類 + +| 分類 | 意味 | 変更時の扱い | +|---|---|---| +| **意図的差分** | 対象市場や安全境界から必要になった違い | 一致させる前に設計判断として再評価する | +| **同期対象** | 実装は別でも、考え方や振る舞いを揃える領域 | 片側を変えたら反対側への適用要否を確認する | +| **共通化候補** | 純粋ロジックやテストデータとして共有を検討できる領域 | 結合範囲と障害時の影響を測ってから決める | +| **対象外** | 一方にだけ必要で、反対側へ持ち込まない領域 | 差が広がっても乖離とは扱わない | + +「同期対象」は「同じコードにする」という意味ではない。 +市場固有の制約を残したまま、入力条件、出力の意味、失敗時の扱いを揃える領域も含む。 + +## 目的と安全境界 + +| 項目 | StockCopilot | TradingCopilot | 分類 | +|---|---|---|---| +| 対象 | 日本株、米国株、ETFの現物 | 暗号資産の無期限先物 | 意図的差分 | +| 主な役割 | 候補スクリーニング、保有分析、売買判断の提案 | 固定シグナルの注文プラン生成、承認後の発注、複数会場の裁量分析 | 意図的差分 | +| 執行 | 発注コードと証券会社APIを持たず、人間が手動で執行する | `execute_orders.py`がdry-runと明示承認を経てGrvtへ発注する | 意図的差分 | +| 認証情報 | Slack Webhookだけを扱い、保有情報も公開リポジトリへ残さない | 取引APIの資格情報をローカル環境に持つ | 意図的差分 | +| リポジトリ | 公開Gitリポジトリ。PRとCIで変更を管理する | 現在はローカルの非Gitチェックアウト | 意図的差分 | + +StockCopilotの発注禁止は、TradingCopilotとの差を埋める対象ではない。 +この境界があるため、株式分析の変更から本番注文へ到達する経路が生まれない。 +分離とコピー流用を選んだ理由は[ADR-0001](adr/0001-separate-sibling-project.md)に記録されている。 + +## 分析の流れ + +| 項目 | StockCopilot | TradingCopilot | 分類 | +|---|---|---|---| +| 定期処理 | 夕方に株式候補と保有を分析し、中間表現JSON、HTML、Slack通知を生成する | 09:05 JSTに固定銘柄の日足シグナルを判定し、注文プランを生成する | 意図的差分 | +| 定期シグナル | スクリーニング結果を分析へ渡し、LLMが候補の採否を判断する | `morning_signal.py`がEMA200と20日ブレイクアウトを決定的に判定する | 意図的差分 | +| 裁量分析 | 候補分析と保有分析の二系統を持つ | `swing-check`が複数会場のポジションと前回シナリオを比較する | 同期対象 | +| スクリーニング | ウォッチリスト、探索ユニバース、保有除外から最大件数まで絞る | Hyperliquidの流動性条件を通った銘柄から最大3件まで絞り、建てられる会場を付ける | 同期対象 | +| 候補の採否 | `screen.py`は買いを決めず、`analyze.py`の分析を通す | `swing/screen.py`は買いを決めず、スイング分析を通す | 同期対象 | +| 候補なし | 正常な結果として扱う | 正常な結果として扱う | 同期対象 | +| 分析時間足 | 日足と週足 | Morning Briefは日足、スイング分析は1時間足、4時間足、日足 | 意図的差分 | +| 市場固有情報 | 決算日、銘柄種別、日本語名、市場別の確定足更新 | funding、板、会場、証拠金、TPとSL、未決済注文 | 対象外 | + +両者のスクリーナーは、直近の変動と20日レンジ突破をATR単位で測り、運用時に保有銘柄を除外する。 +ただし、StockCopilotは確定終値と市場別の更新状態を使い、TradingCopilotは24時間変動と暗号資産会場の流動性を使う。 +共通なのは候補抽出の考え方であり、現時点の入力条件まで同一ではない。 + +## データと状態 + +| 項目 | StockCopilot | TradingCopilot | 分類 | +|---|---|---|---| +| 価格データ | yfinanceから日本株と米国株を取得する | Grvt、Hyperliquid、Decibelなど対象会場から取得する | 意図的差分 | +| 確定足 | 市場時間、タイムゾーン、日足と週足の境界で形成中の足を除く | ローソク足の開始時刻と時間足の秒数で形成中の足を除く | 同期対象 | +| 保有状態 | Investmentの生成物とジャーナルの執行記録を合成する | 各会場のAPIからポジションと残高を取得する | 意図的差分 | +| 取得不能 | 市場単位で分析を停止し、現在の保有状態に前回分析を合流する | 取得不能会場を`degraded`として示し、建玉ゼロとは解釈しない | 同期対象 | +| 継続分析 | 市場別の確定足が更新された部分だけを再分析する | 前回ジャーナルのシナリオと現在のポジションを比較する | 意図的差分 | + +取得失敗を正常な空データと区別する点は揃っている。 +一方は市場単位、もう一方は会場単位なので、共通化するなら状態名ではなく「失敗を空とみなさない」という契約を共有する。 + +## 指標と判定 + +| 項目 | StockCopilot | TradingCopilot | 分類 | +|---|---|---|---| +| 指標セット | RSI、MACD、EMA、Bollinger Bands、ATR、Stoch RSI、OBV、ADX、20本と60本の高安 | スイング分析では同じ指標セット | 共通化候補 | +| 指標の実装 | [`lib/indicators.py`](../lib/indicators.py)の純粋なDataFrame計算 | `swing/_analyze.py`でAPI接続、整形、指標計算、表示を一つのスクリプトに持つ | 共通化候補 | +| 定期シグナル | `screen.py`の結果を分析へ渡し、外部参照は[実行モード](output-contract.md#実行モードと外部参照)に従い、定期実行では引かず、対話実行だけ使える | Morning BriefはEMA200、20日ブレイクアウト、ATRによる固定ルールを使う | 意図的差分 | +| リスク計算 | 判断を提案するが、注文サイズを計算しない | 残高リスク、同時保有数、注文上限、TPとSLを注文プランへ反映する | 対象外 | + +指標計算は、現在もっともコード共有に近い。 +StockCopilotの`compute()`とTradingCopilotの`ind()`は同じ出力項目と期間を持つが、TradingCopilot側ではAPI接続と表示処理から分離されていない。 +共有モジュールを先に作ると、StockCopilotから取引環境への依存が生じる可能性がある。 + +最初に共有するなら、計算結果のテストベクトルが適している。 +同じOHLCVを入力し、指標値、丸め規則、データ不足時の扱いが一致することを両プロジェクトで検証できる。 +純粋計算を分離できた時点で、共有パッケージの保守コストとコピー同期のコストを測り直す。 + +## 出力と通知 + +| 項目 | StockCopilot | TradingCopilot | 分類 | +|---|---|---|---| +| 機械可読出力 | レポート用JSONをJSON Schemaと業務規則で検証する | 注文プランJSONを`ORDER_PLAN_SPEC.md`と`execute_orders.py`で検証する | 同期対象 | +| 人間向け出力 | 自己完結HTMLとCLI表示 | Morning BriefのHTMLとCLI表示、スイング分析の対話出力 | 共通化候補 | +| Slack通知 | 毎日投稿し、資金が動く判断がある日だけメンションする | 注文、警告、実行失敗がある日だけ投稿する | 意図的差分 | +| 通知の経路 | Incoming WebhookをPythonコードから呼ぶ | Incoming WebhookをPythonコードから呼ぶ | 共通化候補 | + +両者とも、LLMが直接Slackへ投稿せず、決定的なコードが通知条件を判定する。 +ただし、StockCopilotは日次記録、TradingCopilotは発注と異常の通知なので、発火条件を共通化する対象にはしない。 +Webhook送信のタイムアウト、エラー処理、本文エスケープは共通化できるが、小さな重複を除くためにプロジェクト間の依存を増やす価値はまだ測れていない。 + +## 開発と運用 + +| 項目 | StockCopilot | TradingCopilot | 分類 | +|---|---|---|---| +| Python環境 | uvとPEP 723 | uvとPEP 723 | 同期対象 | +| 実行パス | プロジェクト相対パス | プロジェクト相対パス | 同期対象 | +| 指示ファイル | `AGENTS.md`を正とし、`CLAUDE.md`を橋渡しにする | `AGENTS.md`を正とし、`CLAUDE.md`を橋渡しにする | 同期対象 | +| スキル | `.agents/skills/`へ同封し、リポジトリと一緒に版管理する | 現在はユーザースコープのスキルからローカルファイルを呼ぶ | 共通化候補 | +| 自動テスト | ネットワークを使わないテスト群とGitHub Actionsを持つ | 注文のpost-only交差判定に絞ったローカルテストを持つ | 同期対象 | +| 設計判断 | `docs/adr/`でプロジェクト境界、データ、出力、通知などを記録する | `docs/adr/`で指示ファイルと実行パスの判断を記録する | 同期対象 | + +テスト件数を同じにする必要はない。 +TradingCopilotでは、注文プラン検証、dry-run、発注ガード、TPとSLの部分失敗、二重発注防止の回帰テストが損失リスクに直結する。 +StockCopilotでは、市場別の確定足、公開禁止情報、中間表現の契約が優先される。 + +## 共通化候補の優先順位 + +| 候補 | 推奨する共有単位 | 優先度 | 現時点の評価 | +|---|---|---|---| +| 指標エンジン | 共通OHLCVフィクスチャと期待値。次に純粋計算関数 | 高 | 同じ指標の静かな乖離を検出でき、安全境界を結合しない | +| スクリーニング原則 | ATR正規化、20日レンジ、候補なしを含む振る舞いのテスト表 | 高 | 市場固有のデータ取得と閾値は分けたまま同期できる | +| 確定足 | 時間を注入できる共通インターフェースと境界テストの観点 | 中 | 市場カレンダーと24時間市場で実装条件が違うため、関数共有は急がない | +| 取得失敗の扱い | 空データと取得不能を区別する契約 | 中 | 語彙を統一するより、誤って正常扱いしないことを揃える | +| Slack送信 | Webhook送信だけの小さなヘルパー | 低 | 通知ポリシーは異なり、現状の重複量では依存追加の効果が小さい | +| スキル配置 | `.agents/skills/`と`CLAUDE.md`橋渡しの構成 | 中 | TradingCopilotのGit管理を始めるときに版管理単位を揃えられる | +| JSON契約 | スキーマバージョン、検証、生成と消費の分離という設計パターン | 中 | レポートと注文では語彙も失敗時の影響も違うため、スキーマ自体は共有しない | + +共通化は、共有パッケージの作成だけを指さない。 +テストフィクスチャ、振る舞いの契約、ファイル配置の規約を共有する方が、実行時依存を増やさずに乖離を検出できる場合がある。 + +## 共通化しない領域 + +次の領域は、現在の安全境界を保つために共有対象から外す。 + +- StockCopilotの保有読み込みとTradingCopilotの会場別ポジション取得 +- StockCopilotのレポートスキーマとTradingCopilotの注文プランスキーマ +- TradingCopilotの認証、残高、注文、キャンセル、TP、SLの処理 +- 両プロジェクトの通知発火条件 +- 決算情報とfundingなど、資産クラスに固有の分析材料 + +これらに共通の抽象化を置いても、実装の安全性は揃わない。 +一方の変更が反対側の実行経路へ伝播するため、障害の影響範囲だけが広がる可能性がある。 + +## 再評価のサイン + +共通化の優先度は固定しない。 +次の変化が起きた時点で、対応する候補を再評価する。 + +| 変化 | 再評価する候補 | +|---|---| +| 片側だけで指標の修正や追加が発生した | 指標の共通フィクスチャと純粋計算関数 | +| ATR正規化や20日レンジの意味を片側で変更した | スクリーニングの振る舞いの契約 | +| 空データを取得不能と誤認する不具合が発生した | 取得結果の状態と失敗時の契約 | +| Webhookの再送、タイムアウト、エスケープを両側で直す必要が生じた | Slack送信ヘルパー | +| TradingCopilotがGit管理とCIを始めた | スキル配置、共通テスト、共有パッケージの配布方法 | +| 共通OHLCVで両実装の結果が一致しなくなった | コピー流用の継続可否と共有モジュール化 | + +## 更新契機 + +次のファイルや規範を変更するときは、関連する比較表と共通化候補を確認する。 + +| 領域 | StockCopilot | TradingCopilot | +|---|---|---| +| 指標 | `lib/indicators.py` | `swing/_analyze.py` | +| 確定足とデータ取得 | `lib/datasource.py` | `morning_signal.py`、`swing/_analyze.py` | +| スクリーニング | `screen.py`、`config/universe.py` | `swing/screen.py` | +| 状態の取得と継続分析 | `lib/holdings.py`、`lib/market_observation.py` | `swing/fetch_positions.py`、`swing/journal.md` | +| 機械可読契約 | `docs/report-contract.schema.json`、`lib/contract.py` | `docs/ORDER_PLAN_SPEC.md`、`execute_orders.py` | +| 通知 | `lib/verdicts.py`、`notify.py` | `morning_signal.py` | +| 指示とスキル | `AGENTS.md`、`.agents/skills/` | `AGENTS.md`、ユーザースコープの関連スキル | + +更新時は、変更した行だけでなく分類も見直す。 +「意図的差分」が不要になった場合や、共有パッケージを採用する場合は設計判断が変わる。 +特にプロジェクト間のモジュール共有へ移る場合は、新しいADRで[ADR-0001](adr/0001-separate-sibling-project.md)を置き換えてから実装する。