Deskpricer について
Deskpricerは、個人のトレーディングデスク向けのローカルなオプション価格サービスです。HTTPまたはMCP経由で欧州型・米国型の株式オプションを分析でき、Excelの数式とも連携します。
主な機能
- 01オプション価格とGreeksの計算
- 02インプライド・ボラティリティの算出
- 03オプション損益の要因分析
- 04複数レッグのポートフォリオGreeks集計
- 05XMLを標準出力し、JSONにも対応
活用シーン
- 01Excelでオプション価格とGreeksを取得
- 02市場価格からボラティリティを推定
- 03保有期間中の損益を要因別に分析
- 04複数レッグのオプションリスクを集計
MCP 対応
MCP サーバーは `price_option`、`implied_volatility`、`pnl_attribution`、`portfolio_greeks` ツールを提供し、HTTP APIと同じ価格計算エンジンを使用します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
DeskPricer v3.5.0
バニラのヨーロピアンおよびアメリカン株式オプション向けのローカル HTTP プライシングマイクロサービスです。Excel の WEBSERVICE と FILTERXML による連携を想定しており、VBA は不要で、サービス内部から Bloomberg ターミナルを呼び出すこともありません。
設計意図: DeskPricer は、個人のデスクでのプライシングとオプション分析を目的としたローカル専用ツールです。公開サービスやサーバー型サービスとして実行・提供することは想定していません。localhost へのバインド、認証なし、TLS なし、レート制限なし、XML を既定とするなど、すべての設計上の選択はこの方針に基づいています。
AI エージェントでの使用(MCP)
DeskPricer は MCP サーバーとして利用できます。Cursor、Claude Desktop、または MCP 対応のエージェントに追加してください。
pip install deskpricer
PyPI で公開されています:https://pypi.org/project/deskpricer/
Cursor — ~/.cursor/mcp.json に追加します。
{
"mcpServers": {
"deskpricer": {
"command": "deskpricer-mcp",
"args": []
}
}
}
Claude Desktop — claude_desktop_config.json に追加します。
{
"mcpServers": {
"deskpricer": {
"command": "deskpricer-mcp"
}
}
}
deskpricer-mcp が PATH にない場合は、仮想環境内の実行ファイルへのフルパスを指定してください。
ツール:price_option、implied_volatility、pnl_attribution、portfolio_greeks — HTTP API と同じプライシングエンジンを使用します。
セットアップ、規約、プロンプトの例については、docs/mcp_quickstart.md を参照してください。
クイックスタート
クリーンなクローンから、5 分以内にプライシング呼び出しを実行できます。
# 1. Install
python -m venv .venv
.venv\Scripts\activate
pip install -e ".[dev]"
# 2. Run
python -m deskpricer.main
# 3. Test with curl
curl "http://127.0.0.1:8765/v1/greeks?s=100&k=105&t=0.25&r=0.05&q=0.02&b=0.0&v=0.20&type=call&style=european"
# 4. Test with Excel (copy into a cell)
# =FILTERXML(WEBSERVICE("http://127.0.0.1:8765/v1/greeks?s=100&k=105&t=0.25&r=0.05&q=0.02&b=0.0&v=0.20&type=call&style=european"),"//outputs/price")
curl 呼び出しで期待される出力(XML):
<?xml version="1.0" encoding="UTF-8"?>
<greeks>
<meta>
<service_version>3.5.0</service_version>
<quantlib_version>1.42.1</quantlib_version>
<engine>analytic</engine>
<valuation_date>2026-06-10</valuation_date>
</meta>
<inputs>
<s>100.0</s>
<k>105.0</k>
<t>0.25</t>
<r>0.05</r>
<q>0.02</q>
<b>0.0</b>
<v>0.2</v>
<type>call</type>
<style>european</style>
</inputs>
<outputs>
<price>2.288743</price>
<delta>0.356244</delta>
<gamma>0.037206</gamma>
<vega>0.185519</vega>
<theta>-0.033315</theta>
<rho>0.083111</rho>
<charm>-0.001241</charm>
</outputs>
</greeks>
JSON を使用するには、Accept: application/json を送信するか、?format=json を追加してください。
デモ用ワークブックを試す
すぐに実行できるサンプルとして、sample/DeskPricer_Bitcoin_Demo.xlsx を開いてください。次の 3 つのシートが含まれています。
| シート | 内容 |
|---|---|
| Greeks | Bitcoin のヨーロピアンコール — スポット価格 $75K、権利行使価格 $100K、満期 3M、ボラティリティ 50% |
| ImpliedVol | 市場価格 $3,398.71 から約 68.3% のインプライドボラティリティを逆算 |
| PnL Attribution | スポット価格が $75K → $80K、ボラティリティが 50% → 55% に上昇した場合の PnL を分解 |
各シートには、実際の WEBSERVICE と FILTERXML の数式があらかじめ入力されています。DeskPricer を起動するだけで、セルに値が自動的に表示されます。
機能
- 単一オプションまたは複数レッグのポートフォリオのプライシングとグリークス
- インプライドボラティリティソルバー(QuantLib 経由の Brent 法)
- PnL 帰属分析 — オプションの PnL をデルタ、ガンマ、ベガ、シータ、ロー、バンナ、ボルガ、残差に分解
- 既定では XML — Excel の
WEBSERVICEとFILTERXMLですぐに利用可能。Accept: application/jsonで JSON も使用できます - localhost 専用 —
127.0.0.1にバインドし、ネットワークに公開されません
規約
| グリーク | 単位/規約 |
|---|---|
delta | 絶対値(∂V/∂S) |
gamma | 絶対値(∂²V/∂S²) |
vega | ボラティリティ 1% ポイントあたり |
theta | 暦日あたり(ACT/365)。一般的なロングオプションでは負になります(時間価値の減衰)。符号は Bloomberg DM と逆で、Bloomberg ではシータを正の減衰として表示します。 |
rho | 金利 1% ポイントあたり(無リスク金利のみ。配当利回りや借株コストに対するローは含みません) |
charm | 暦日あたり(∂delta/∂t) |
借株コスト(b):年率換算した株式の借株コスト(小数)を任意で指定できます。実効キャリーコストは r − q − b です。省略または 0.0 の場合は、3.4.0 より前の動作と同じです。
満期までの時間(t):ACT/365 に基づく年数で指定します。内部では暦日数(round(t * 365))に変換され、最低 1 日に設定された後、選択したカレンダー(既定では hong_kong)に従って次の営業日に繰り延べられます。シータとチャームは営業日ではなく暦日あたりで計算されます。
PnL 帰属分析:calendar_days は、保有期間中に実際に経過した暦日数を表します。theta_pnl = theta × calendar_days_elapsed です。評価日を両方とも省略した場合、calendar_days は既定で 1 になります。複数日の保有期間を正確に計算するには、日付を明示してください。
インストール方法
スタンドアロン実行ファイル(推奨)
Releases ページから DeskPricer_v3.exe をダウンロードして、次のように実行します。
.\DeskPricer_v3.exe
サービスはポート 8765 で起動します。別のポートを使用するには、次のようにします。
.\DeskPricer_v3.exe --port 9000
ソースからのインストール
python -m venv .venv
.venv\Scripts\activate
pip install -e ".[dev]"
python -m deskpricer.main
Excel ユーザーガイド
サービスの状態
価格を取得する前に、サービスが実行中であることを確認してください。
| セル | 数式 |
|---|---|
| 状態 | =IFERROR(FILTERXML(WEBSERVICE("http://127.0.0.1:8765/v1/health"),"//status"),"DOWN") |
期待される出力: UP
例 1:単一オプションの価格とグリークス
シートに次の項目があるとします。
| 列 | ラベル | 値の例 |
|---|---|---|
| C | スポット価格 | 100 |
| K | 権利行使価格 | 105 |
| T | 満期までの期間(年) | 0.25 |
| R | 無リスク金利 | 0.05 |
| Q | 配当利回り | 0.02 |
| B | 借入コスト(省略可、デフォルトは 0.0) | 0.0 |
| V | ボラティリティ | 0.20 |
| TYPE | オプションタイプ | call |
| STYLE | スタイル | european |
ステップ 1 — ヘルパーセル(例:H2)に URL を作成します:
="http://127.0.0.1:8765/v1/greeks?s="&C2&"&k="&K2&"&t="&T2&"&r="&R2&"&q="&Q2&"&b="&B2&"&v="&V2&"&type="&TYPE2&"&style="&STYLE2
ステップ 2 — 生の XML を取得します(例:I2):
=WEBSERVICE(H2)
ステップ 3 — 値を個別のセルに抽出します:
| 出力 | 数式 |
|---|---|
| 価格 | =VALUE(FILTERXML(I2,"//outputs/price")) |
| デルタ | =VALUE(FILTERXML(I2,"//outputs/delta")) |
| ガンマ | =VALUE(FILTERXML(I2,"//outputs/gamma")) |
| ベガ | =VALUE(FILTERXML(I2,"//outputs/vega")) |
| シータ | =VALUE(FILTERXML(I2,"//outputs/theta")) |
| ロー | =VALUE(FILTERXML(I2,"//outputs/rho")) |
| チャーム | =VALUE(FILTERXML(I2,"//outputs/charm")) |
上記の例で期待される出力:
| グリーク | 値 |
|---|---|
| 価格 | 2.288743 |
| デルタ | 0.356244 |
| ガンマ | 0.037206 |
| ベガ | 0.185519 |
| シータ | -0.033315 |
| ロー | 0.083111 |
| チャーム | -0.001241 |
ヒント: 各
FILTERXMLをIFERROR(...,"ERR")で囲むと、1 行のエラーでシート全体が壊れるのを防げます。
例 2:市場価格からインプライド・ボラティリティを逆算する
同じオプションの市場仲値が 6.50 であり、インプライド・ボラティリティを求めたいとします。
ステップ 1 — URL を作成します(例:H2):
="http://127.0.0.1:8765/v1/impliedvol?s="&C2&"&k="&K2&"&t="&T2&"&r="&R2&"&q="&Q2&"&b="&B2&"&price=6.50&type="&TYPE2&"&style="&STYLE2
ステップ 2 — インプライド・ボラティリティを抽出します:
=VALUE(FILTERXML(WEBSERVICE(H2),"//outputs/implied_vol"))
期待される出力: 0.417484(約 41.7 % のボラティリティ)
例 3:損益のアトリビューション
昨日(t-1)にポジションがあり、今日の損益を説明したいとします。
次のように仮定します。
| 項目 | t-1 の値 | t の値 |
|---|---|---|
| スポット価格 | 100 | 102 |
| 時間 | 0.25 | 0.2466 |
| ボラティリティ | 0.20 | 0.22 |
| 金利 | 0.05 | 0.05 |
| 配当 | 0.02 | 0.02 |
| 借入 | 0.0 | 0.0 |
| 数量 | 10 | — |
ステップ 1 — URL を作成します:
="http://127.0.0.1:8765/v1/pnl_attribution?s_t_minus_1=100&s_t=102&k=105&t_t_minus_1=0.25&t_t=0.2466&r_t_minus_1=0.05&r_t=0.05&q_t_minus_1=0.02&q_t=0.02&b_t_minus_1=0.0&b_t=0.0&v_t_minus_1=0.2&v_t=0.22&type=call&style=european&qty=10&cross_greeks=true"
ステップ 2 — アトリビューションの内訳を抽出します:
| 内訳 | 数式 |
|---|---|
| 実現損益 | =VALUE(FILTERXML(WEBSERVICE(H2),"//outputs/actual_pnl")) |
| デルタ損益 | =VALUE(FILTERXML(WEBSERVICE(H2),"//outputs/delta_pnl")) |
| ガンマ損益 | =VALUE(FILTERXML(WEBSERVICE(H2),"//outputs/gamma_pnl")) |
| ベガ損益 | =VALUE(FILTERXML(WEBSERVICE(H2),"//outputs/vega_pnl")) |
| シータ損益 | =VALUE(FILTERXML(WEBSERVICE(H2),"//outputs/theta_pnl")) |
| ロー損益 | =VALUE(FILTERXML(WEBSERVICE(H2),"//outputs/rho_pnl")) |
| バンナ損益 | =VALUE(FILTERXML(WEBSERVICE(H2),"//outputs/vanna_pnl")) |
| ボルガ損益 | =VALUE(FILTERXML(WEBSERVICE(H2),"//outputs/volga_pnl")) |
| 残差 | =VALUE(FILTERXML(WEBSERVICE(H2),"//outputs/residual_pnl")) |
期待される出力:
| 内訳 | 値 |
|---|---|
| price_t_minus_1 | 2.288743 |
| price_t | 3.448862 |
| 実現損益 | 11.601 |
| デルタ損益 | 7.125 |
| ガンマ損益 | 0.744 |
| ベガ損益 | 3.710 |
| シータ損益 | -0.333 |
| ロー損益 | 0.0 |
| バンナ損益 | 0.343 |
| ボルガ損益 | 0.031 |
| 説明済み損益 | 11.621 |
| 残差 | -0.020 |
residual_pnlは、高次の効果と t-1 と t の間のモデル差を捉えます。バンナとボルガの寄与を含めるには、cross_greeks=trueを有効にしてください。
例 4:ポートフォリオ/一括グリークス
ブック単位で集計するには、Power Query または小規模な VBA ヘルパーを使って POST /v1/portfolio/greeks エンドポイントを呼び出してください。このエンドポイントは、複数のレッグを含む JSON 本文を受け取り、レッグごとのグリークスと集計グリークスを返します。
リクエスト/レスポンスのスキーマ全体については、docs/api.md を参照してください。
グリークスの規約
| グリークス | 単位 | 備考 |
|---|---|---|
| Delta | 絶対値 | 現物価格が 1 ドル動くごと |
| Gamma | 絶対値 | 現物価格が 1 ドル動くごと |
| Vega | ボラティリティ 1 ポイントあたり | つまり、10 進数表記のボラティリティ × 100 |
| Theta | 暦日 1 日あたり | 暦日が 1 日経過した場合の将来損益(1 暦日後の再評価額 − 今日の価格)。価値が減少するロングオプションではマイナスになります。 |
| Rho | 金利 1% ポイントあたり | つまり、10 進数表記の金利 × 100 |
| Charm | 暦日 1 日あたり | ∂delta/∂t(t − 1/365 時点のデルタ − 今日のデルタ)。ロングコールではマイナスになります。デルタは満期に向けて低下します。 |
ログの場所と構造化ログ
- ログのパス:
DESKPRICER_LOG_DIR環境変数を設定すると、デフォルトのパス(Windows ではC:\ProgramData\DeskPricer\logs、それ以外では~/.local/share/deskpricer/logs)を上書きします。 - 形式:Python 標準ライブラリの
loggingモジュールを、カスタム JSON フォーマッターおよびRotatingFileHandler(10 MB ごとにローテーション、バックアップ 5 個)とともに使用します。以前の手書きのopen()方式に代わるものです。 - パスの変更:
$env:DESKPRICER_LOG_DIR = "C:\MyLogs" python -m deskpricer.main
トラブルシューティング
QuantLib のインストールに失敗する
QuantLib の pip install が失敗する場合は、C++ コンパイラーと CMake がインストールされていることを確認するか、ビルド済みのホイールを使用してください。詳しい手順については、docs/operator_guide.md を参照してください。
ゼロ DTE での注意点
QuantLib の計算が破綻しないよう、t=0 は暦日 1 日に切り上げられます。そのため、純粋な本質的価値ではなく、小さな時間価値プレミアムが加算されます。これは意図的な動作です。
エンジンとスタイルの不一致
style=european→engine=analyticのみstyle=american→engine=binomial_crrまたはbinomial_jrのみ
XML と JSON
Excel にはデフォルトで XML が返されます。JSON を使用するには、Accept: application/json または ?format=json を送信してください。
エラーコード
| コード | 意味 |
|---|---|
INVALID_INPUT | ビジネスルールまたはスキーマの検証に失敗しました |
UNSUPPORTED_COMBINATION | エンジンとスタイルが一致しません |
PRICING_FAILURE | 予期しない内部エラーです(トレースバックは公開されません) |
制限事項
- FD エンジンなし — ヨーロピアンオプションと経済的に同等なアメリカンオプションには閉形式の BSM を使用し、それ以外のアメリカンオプションには二項 CRR/JR を使用します。
- プロセスプールによる QuantLib の並行実行 — デフォルトのワーカー数は
min(4, cpu_count())(DESKPRICER_WORKERS)です。ポートフォリオの各レッグは、リクエストごとに 1 回のワーカー呼び出しでまとめて処理されます。 - バンプ範囲に上限あり —
bump_spot_rel≤ 0.1、bump_vol_abs≤ 0.01、bump_rate_abs≤ 0.01。 - データベースや永続化機能なし — すべての状態はリクエストごとにメモリ内に保持されます。
- 認証、TLS、レート制限なし — 設計上、ローカルでのみ使用します。
テストの実行
pytest tests -v
設計上の決定事項
ローカル専用の設計
DeskPricer は、公開 API ではなく個人用デスクトップツールとして構築されています。意図的に機能を省いている理由は次のとおりです。
- 認証/認可なし — サービスに接続できるのは
127.0.0.1のみです。 - TLS/HTTPS なし — ローカルのループバック通信は、設計上暗号化されません。
- レート制限なし — スロットリングは行いません。並行リクエストは、単一の QuantLib グローバル状態で順次処理するのではなく、プロセスプールで処理します。
- Swagger/Redoc なし — 攻撃対象領域を減らすため、本番ビルドでは OpenAPI ドキュメントを非表示にします。
- デフォルトは XML — Excel の
WEBSERVICE関数はAccept: application/jsonを送信しません。
これらの機能が必要な場合、DeskPricer は適切なツールではありません。適切な API ゲートウェイ、またはフル機能のプライシングプラットフォームを使用してください。
QuantLib がプロセスプールで実行される理由
QuantLib の Python バインディングは、プロセス内で共有される単一の Settings.instance() オブジェクトに依存しています。すべてのリクエストを asyncio.Lock で順次処理するのではなく、DeskPricer は QuantLib の処理を ProcessPoolExecutor にディスパッチします。各ワーカープロセスは独立した設定を持つため、並行するエージェントや Excel からの呼び出しを、評価日を破損させずに並列で価格計算できます。プールサイズのデフォルトは min(4, cpu_count()) で、DESKPRICER_WORKERS から設定できます。
ヨーロピアンオプションと経済的に同等なアメリカンオプションは QuantLib を完全に迂回し、純粋な Python による BSM 実装(bsm_fast)を使用します。この実装は QuantLib と照合し、小数点以下 6 桁まで一致することを検証済みです。
PnL アトリビューションで多数のクエリパラメーターを指定した GET を使用する理由
Excel の WEBSERVICE 関数は HTTP GET のみをサポートしています。このサービスの主なユーザーは Excel のため、GET /v1/pnl_attribution エンドポイントは WEBSERVICE との互換性を特に考慮して設計されています。よりすっきりした JSON 本文を必要とするプログラムクライアントは、現時点では POST /v1/portfolio/greeks を使用できます。PnL アトリビューション用の POST の代替手段は、将来のリリースで追加される可能性があります。
プロジェクト構成
DeskPricer/
├── pyproject.toml
├── README.md
├── src/deskpricer/ # FastAPI app + pricing core
│ ├── app.py # Thin composition root
│ ├── routers/ # APIRouter modules
│ ├── services/ # Pricing orchestration + QL lock
│ ├── pricing/ # QuantLib pricing engines
│ ├── schemas.py # Pydantic models
│ ├── responses.py # XML/JSON serializers
│ ├── errors.py # Custom exceptions
│ ├── logging_config.py # Structured JSON logging
│ └── main.py # Uvicorn entrypoint
├── tests/ # pytest + hypothesis
├── tests/fixtures/ # Regression baseline JSONs
├── scripts/ # Build + fixture generation
├── sample/ # Demo Excel workbook
└── docs/ # API ref + operator guide
ライセンス
MIT
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。