Skip to main content
Glama
dommy-i

paper-fx-mcp

by dommy-i
README.md
# Paper FX / Equity Multi-Source MCP Server

FX・株式の**ペーパートレード**を中核に、テクニカル分析・バックテスト・自動売買シミュレーション・経済ニュース・株価/指数 (日経平均含む)・企業財務・EDINET 開示・複合スコアリングまで一つの MCP に統合。

サーバーは2系統:

| エントリ | 売買先 | 用途 |
|---|---|---|
| `mcp_server.py` | ローカル SQLite の模擬ブローカー (価格は yfinance) | **推奨**。口座不要、完全無料 |
| `oanda_mcp_server.py` | OANDA REST API (デモ/本番) | 実ブローカーで運用する場合 |

どちらも同じツール体系・同じリスクガードを持ちます。

## ファイル構成

| ファイル | 役割 |
|---|---|
| `mcp_server.py` | ペーパー版 MCP エントリ。全ツールを登録 |
| `paper_broker.py` | SQLite 永続化の模擬ブローカー (SL/TP 自動決済・キルスイッチ) |
| `indicators.py` | テクニカル指標 (純Python) とスコアリングロジック |
| `backtest.py` | バックテスト・ウォークフォワード検証 ([backtesting.py](https://github.com/kernc/backtesting.py) ラッパー) |
| `simulator.py` | リアルタイム自動売買ループ (閾値ルール・判断ログ) |
| `run_sim.py` | シミュレータを MCP なしで常駐させるスタンドアロンランナー ([長期運用ガイド](docs/LONG_RUN.md)) |
| `news_feeds.py` | RSS ニュース取得 (API キー不要) |
| `dashboard.py` | 読み取り専用 Web ダッシュボード (stdlib のみ) |
| `oanda_mcp_server.py` | OANDA 版 MCP エントリ |
| `oanda_client.py` | OANDA REST API クライアント |
| `smoke_test.py` | 接続・認証情報の事前確認 (OANDA 版用) |
| `offline_test*.py` | yfinance をスタブしたオフラインテスト (ネットワーク不要) |
| `requirements.txt` | 依存 |
| `.env.example` | 環境変数テンプレ |

## セットアップ

> iPad(ブラウザのみ)で開発する場合は [docs/IPAD_DEV.md](docs/IPAD_DEV.md) を参照。Claude Code on the web / GitHub Codespaces / Browser use / Computer use のセットアップ済み。

```bash
pip install -r requirements.txt
```

環境変数はすべて任意 (`.env.example` 参照)。ニュース検索と EDINET を使う場合のみ:

```bash
export NEWSAPI_KEY="..."      # https://newsapi.org の無料枠
export EDINET_API_KEY="..."   # https://disclosure2.edinet-fsa.go.jp/
```

Claude Code 登録:
```bash
claude mcp add paper-fx -- python /絶対パス/mcp_server.py
```

動作確認 (ネットワーク不要):
```bash
python offline_test.py            # ブローカー + 指標
python offline_test_backtest.py   # バックテスト
python offline_test_simulator.py  # シミュレータ
python offline_test_dashboard.py  # ダッシュボード
python offline_test_runner.py     # 常駐ランナー
```

## 公開ツール一覧 (ペーパー版)

### 売買 (模擬)
- `get_price` — 通貨ペアの bid/ask (疑似スプレッド付き)
- `get_candles` — ローソク足 (OANDA 互換形式、ソースは yfinance)
- `get_account` — 残高・NAV・実現/評価損益・キルスイッチ状態
- `place_order` — 成行発注 (**SL 必須**、リスク%からサイズ自動計算)
- `close_position` — 指定銘柄の全決済
- `list_positions` — 建玉/決済履歴の一覧
- `kill_switch` / `reset_kill_switch` — 緊急停止 (状態は SQLite に永続化)
- `reset_account` — 全ポジション消去 (テスト用・破壊的)

### 株価・指数 (yfinance, 無料)
- `get_index` — 指数: `^N225` 日経 / `^TPX` TOPIX / `^GSPC` S&P / `^DJI` ダウ / `^IXIC` Nasdaq
- `get_stock_quote` — 銘柄株価: 日本株は `7203.T` (トヨタ) 形式、米株は `AAPL` 等
- `get_stock_history` — 過去 OHLC

### 財務・開示
- `get_financials` — PL/BS/CF (yfinance、日米両対応)
- `search_edinet` — 有報・四半期報告書・臨時報告書を日付検索

### ニュース
- `get_news` — NewsAPI 経由のキーワード検索 (`language='ja'` で日本語)
- `get_rss_news` — RSS ヘッドライン (Yahoo Finance / CNBC / MarketWatch / NHK 経済 / 日銀)。**API キー不要**、`RSS_FEEDS` 環境変数でフィード追加可

### 分析・スコアリング
- `technical_analysis` — FX も株も自動ルーティングで指標一式 + テクニカルスコア
- `composite_score` — テクニカル(自動) + ファンダ + ニュースを加重合成
- `build_dossier` — マルチタイムフレーム技術分析 + 財務 + ヘッドラインを1コールで収集

### バックテスト
- `backtest_strategy` — ライブと**同一のスコアロジック**を過去データで検証 (Sharpe・最大DD・勝率・PF と辛口の判定コメント)
- `walk_forward_test` — 期間分割して各区間を独立検証 (レジーム依存の検出)

### リアルタイムシミュレーション
- `sim_start` — 監視リストを定期スコアリングし閾値ルールで自動売買 (最短30秒間隔)
- `sim_stop` / `sim_status` / `sim_log` — 停止・状態確認・判断ログ (hold 含め全決定を SQLite に記録)

シミュレータの実行状態は MCP サーバーのプロセス内 (in-memory) なので、Claude Code のセッションを閉じると止まります。**数週間〜1ヶ月の連続運用には `run_sim.py`** を使ってください — MCP クライアント不要でシミュレータだけを常駐させるランナーで、発注は同じリスクガード経路を通ります:

```bash
python run_sim.py --watchlist USD_JPY EUR_USD --interval-seconds 300 --dashboard
```

systemd での常駐化・監視・1ヶ月後の評価方法は [docs/LONG_RUN.md](docs/LONG_RUN.md) を参照。常時稼働マシンがない場合に GCP 常時無料枠 (e2-micro) で動かす手順も同ドキュメントにあります。

## リスクガード

すべての発注 (手動ツール・シミュレータとも) は単一の `_risk_guarded_order` 経路を通り、迂回できません:

- **SL 必須** — `stop_loss_pips` なしでは発注不可
- **サイズ自動計算** — 残高 × `MAX_RISK_PER_TRADE_PCT` ÷ SL 距離
- **同時建玉上限** — `MAX_OPEN_POSITIONS` (デフォルト 3)
- **日次損失上限** — `MAX_DAILY_LOSS_PCT` (デフォルト 3%) 超過で**キルスイッチ自動発動**

## ダッシュボード

```bash
python dashboard.py            # http://localhost:8787
PORT=9000 python dashboard.py  # ポート変更
```

MCP サーバーと同じ SQLite を読み、残高/NAV・建玉・損益曲線・シミュレータ判断ログを5秒ごとに自動更新表示します。**表示専用**です — 状態変更はリスクガードのある MCP ツール経由のみ。バインドは 127.0.0.1 限定。

![dashboard](dashboard_live.png)

## スコアリングの考え方

`technical_score` は3コンポーネント (トレンド40% / モメンタム35% / 平均回帰25%) を -100〜+100 に正規化。これだけで戦略になるものではなく、ファンダとニュースは **Claude が `get_financials` と `get_news` の出力を読んで -100〜+100 の数値を作り、`composite_score` に渡す** ワークフローを想定しています。

平均回帰成分 (25%) があるため、**一方向に伸び切ったトレンドはスコアが頭打ちになり、急落局面では「売られすぎの反発期待」でスコアがプラスに振れることがあります**。順張り専用の指標ではない点に注意してください。

例: トヨタの判定
```
1. technical_analysis("7203.T", granularity="D")
   → テクニカルスコア取得
2. get_financials("7203.T")
   → Claude が「営業利益率改善・FCF黒字・負債健全」と読み、+60 とする
3. get_news("Toyota", language="en", max_results=10)
   → Claude が見出し10件読んで「中立〜やや好材料」と判断、+15
4. composite_score("7203.T", granularity="D",
                   fundamental_score=60, news_sentiment_score=15)
   → 加重合成スコア
5. backtest_strategy("7203.T", granularity="D", count=1000)
   → 同じスコアロジックが過去に通用したか確認
6. walk_forward_test("7203.T")
   → 特定レジームだけで機能する戦略でないか確認
```

## OANDA 版を使う場合

```bash
export OANDA_API_TOKEN="..."
export OANDA_ACCOUNT_ID="101-001-xxxxxxx-001"
export OANDA_ENVIRONMENT="practice"     # デフォルト practice

claude mcp add oanda -- python /絶対パス/oanda_mcp_server.py
python smoke_test.py                    # 登録前に接続確認
```

安全弁: `OANDA_ENVIRONMENT=live` の場合、`ALLOW_LIVE_TRADING=true` を明示しない限り**起動を拒否**します。OANDA 版のキルスイッチ状態はプロセス内メモリのみ (再起動で解除) です。

## 完全自動売買に進む前のチェックリスト

1. デモ/ペーパーで最低1ヶ月走らせる (手順: [docs/LONG_RUN.md](docs/LONG_RUN.md))
2. プロセス監視 (落ちたら通知)
3. ネット断/API障害時のフェイルセーフ確認
4. `backtest_strategy` と `walk_forward_test` で戦略を検証
5. 税務と申告の理解
6. 失っても生活に影響しない金額のみ

## 既知の限界

- **損益・サイジングはクォート通貨建て** — 「クォート通貨 ≒ 口座通貨」前提の近似。USD_JPY を JPY 口座で回す分には整合するが、EUR_USD 等ではリスク%計算がずれる
- ペーパー版の SL/TP 判定は**照会時 (get_account / list_positions / シミュレータの tick) にのみ**実行される。長時間アクセスがないと SL を飛び越えた価格で決済される
- スワップ/金利コストは未シミュレート。スプレッドは固定の疑似値 (`PAPER_SIMULATED_SPREAD_PIPS`)
- yfinance はレート制限あり (短時間に大量呼び出し禁止)
- NewsAPI 無料枠は1日100リクエスト、過去1ヶ月のみ
- EDINET は**書類リストの取得**まで。本文の取得・XBRL 解析は別途
- シミュレータの実行状態は in-memory (サーバー再起動で停止。判断ログは SQLite に残る)。長期連続運用は `run_sim.py` + systemd で ([docs/LONG_RUN.md](docs/LONG_RUN.md))
- スコアは「相対的にどちらに偏っているか」の指標であって、勝率や期待値の保証ではない

## 拡張ロードマップ

- EDINET 書類本文ダウンロードと XBRL パース
- TDnet 適時開示の取得
- 価格ストリーミング (`stream_prices` via OANDA stream API)
- 損益の口座通貨換算 (クロス円以外の正確なリスク計算)
- Discord/Slack 通知連携