金融数据分析服务器

MCP Finance Server 是一个集成了实时市场数据、基本面分析、筛选器分析和期权分析的工具,特别适用于Wheel策略工作流,提供稳定、可靠且易于LLM查询的金融数据服务。

  • by douglashiga
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 douglashiga/MCP-Finance-Server

使用说明

MCP金融服务器

MCP服务器,用于市场数据、基本面、筛选器分析、期权分析和Wheel策略工作流。

该项目结合了:

  • 盈透证券(实时市场连接)
  • 雅虎财经(广泛报道基本面/历史)
  • 本地ELT管道(用于可靠LLM查询的规范化+缓存表)

面向LLM的分析的默认市场是 sweden.

核心目标

  • 稳定、LLM友好的工具,具有明确的默认值和可预测的响应包络。
  • 首先从本地数据库进行可靠的缓存分析,并控制回退。
  • 快速回答实际交易问题(筛选器、期权、轮盘)。
  • 从原始摄取到精心策划的分析表的清晰数据沿袭。

为什么这台服务器与其他服务器相比

  • IBKR实时+雅虎+本地策划缓存(不仅直接读取雅虎API)。
  • 轮式优先工具集(放置选择、容量、分配流、覆盖呼叫继续)。
  • 带有greeks的选项+IV和筛查的选项指标快照。
  • 事件风险建模侧重于车轮碰撞窗口。
  • 具有确定性串行作业和MCP友好发现工具的本地管道。

端到端示例1(车轮定位选择)

  1. get_wheel_put_candidates(symbol='Nordea', market='sweden', delta_min=0.25, delta_max=0.35, dte_min=4, dte_max=10)
  2. analyze_wheel_put_risk(symbol='Nordea', pct_below_spot=5.0, target_dte=7)
  3. get_wheel_contract_capacity(symbol='Nordea', capital_sek=200000, market='sweden')

端到端示例2(事件风险窗口)

  1. get_wheel_event_risk_window(ticker='NDA-SE.ST', market='sweden', days_ahead=14)
  2. get_corporate_events(ticker='NDA-SE.ST', market='sweden')
  3. get_monetary_policy_events(market='sweden')

建筑

MCP-Finance-Server/
├── mcp_server.py                    # MCP tool registry and entrypoint
├── services/
│   ├── market_service.py            # Price lookup and symbol resolution
│   ├── option_service.py            # IB option chain + greeks
│   ├── option_screener_service.py   # Cached option metrics queries
│   ├── screener_service.py          # Stock screener + rankings
│   ├── classification_service.py    # Sector/subsector/core business/earnings
│   ├── wheel_service.py             # Wheel analytics (puts, calls, risk, stress)
│   └── job_service.py               # ELT job controls
├── dataloader/
│   ├── models.py                    # SQLAlchemy models
│   ├── seed.py                      # DB seed + default jobs
│   ├── scheduler.py                 # Cron-like job runner
│   └── scripts/                     # Extract/transform/curation scripts
└── README.md

数据模型亮点

MCP工具使用的关键标准化/策划表:

  • stocks, realtime_prices, historical_prices
  • fundamentals, dividends
  • stock_metrics, market_movers
  • option_metrics
  • option_iv_snapshots (来自期权指标的IV历史快照)
  • exchanges, market_indices
  • sector_taxonomy, industry_taxonomy, subindustry_taxonomy
  • stock_classification_snapshots, company_profiles
  • raw_earnings_events, earnings_events
  • raw_market_events, market_events
  • stock_intelligence_snapshots (新闻/持有者/推荐/声明的本地缓存)

MCP工具组

市场与基本面

  • get_stock_price(symbol, exchange=None, currency='USD')
  • get_historical_data(symbol, duration='1 D', bar_size='1 hour', exchange=None, currency='USD')
  • get_historical_data_cached(symbol, period='1y', interval='1d')
  • search_symbol(query)
  • get_fundamentals(symbol)
  • get_dividends(symbol)
  • get_dividend_history(symbol, period='2y')
  • get_company_info(symbol)
  • get_financial_statements(symbol)
  • get_comprehensive_stock_info(symbol)
  • get_exchange_info(symbol)
  • yahoo_search(query)

笔记:

  • get_stock_price, get_historical_data, search_symbol, get_option_chain,以及 get_option_greeks 是DB优先(管道支持的快照)。
  • 账户/投资组合端点和摄入作业仍然需要IB实时连接。

IB账户和投资组合

  • get_account_summary(masked=True)
  • 资源: finance://account/summary (默认情况下被屏蔽)
  • 资源: finance://portfolio/positions

股票筛选器

  • get_stock_screener(market='sweden', sector=None, sort_by='perf_1d', limit=50)
  • get_top_gainers(market='sweden', period='1D', limit=10)
  • get_top_losers(market='sweden', period='1D', limit=10)
  • get_most_active_stocks(market='sweden', period='1D', limit=10)
  • get_top_dividend_payers(market='sweden', sector=None, limit=10)
  • get_technical_signals(market='sweden', signal_type='oversold', limit=20)
  • get_highest_rsi(market='sweden', limit=10)
  • get_lowest_rsi(market='sweden', limit=10)
  • get_fundamental_rankings(market='sweden', metric='market_cap', limit=10, sector=None)

分类和收益

  • get_companies_by_sector(market='sweden', sector=None, industry=None, subindustry=None, limit=50)
  • get_company_core_business(symbol)
  • get_earnings_events(symbol=None, market='sweden', upcoming_only=False, limit=20)

选项(缓存+实时)

  • get_option_chain(symbol)
  • get_option_greeks(symbol, last_trade_date, strike, right)
  • get_option_screener(symbol=None, expiry=None, right=None, min_delta=None, max_delta=None, min_iv=None, max_iv=None, has_liquidity=True, limit=50)
  • get_option_chain_snapshot(symbol, expiry=None)
  • get_options_data(symbol, expiration_date=None)

市场情报(本地缓存)

  • get_news(symbol, limit=10)
  • get_institutional_holders(symbol, limit=50)
  • get_analyst_recommendations(symbol, limit=50)
  • get_technical_analysis(symbol, period='1y')
  • get_sector_performance(symbols)

车轮策略工具

  • get_wheel_put_candidates(symbol, market='sweden', delta_min=0.25, delta_max=0.35, dte_min=4, dte_max=10, limit=5, require_liquidity=True)
  • get_wheel_put_annualized_return(symbol, market='sweden', target_dte=7)
  • get_wheel_contract_capacity(symbol, capital_sek, market='sweden', strike=None, margin_requirement_pct=1.0, cash_buffer_pct=0.0, target_dte=7)
  • analyze_wheel_put_risk(symbol, market='sweden', pct_below_spot=5.0, target_dte=7)
  • get_wheel_assignment_plan(symbol, assignment_strike, premium_received, market='sweden')
  • get_wheel_covered_call_candidates(symbol, average_cost, market='sweden', delta_min=0.25, delta_max=0.35, dte_min=4, dte_max=21, min_upside_pct=1.0, limit=5)
  • compare_wheel_premiums(symbol_a, symbol_b, market='sweden', delta_min=0.25, delta_max=0.35, dte_min=4, dte_max=10)
  • evaluate_wheel_iv(symbol, market='sweden', lookback_days=90, high_iv_threshold_percentile=70.0, target_dte=7)
  • simulate_wheel_drawdown(symbol, strike, premium_received, drop_percent=10.0, market='sweden')
  • compare_wheel_start_timing(symbol, market='sweden', wait_drop_percent=3.0, delta_min=0.25, delta_max=0.35, dte_min=4, dte_max=10)
  • build_wheel_multi_stock_plan(capital_sek, symbols=None, market='sweden', delta_min=0.25, delta_max=0.35, dte_min=4, dte_max=10, margin_requirement_pct=1.0, cash_buffer_pct=0.10)
  • stress_test_wheel_portfolio(capital_sek, sector_drop_percent=20.0, symbols=None, market='sweden', delta_min=0.25, delta_max=0.35, dte_min=4, dte_max=10)

活动日历工具

  • get_event_calendar(market='sweden', category=None, event_type=None, ticker=None, start_date=None, end_date=None, min_volatility_impact='low', limit=50)
  • get_corporate_events(market='sweden', ticker=None, start_date=None, end_date=None, min_volatility_impact='low', limit=50)
  • get_macro_events(market='sweden', start_date=None, end_date=None, min_volatility_impact='low', limit=50)
  • get_monetary_policy_events(market='sweden', start_date=None, end_date=None, min_volatility_impact='low', limit=50)
  • get_geopolitical_events(market='sweden', start_date=None, end_date=None, min_volatility_impact='low', limit=50)
  • get_market_structure_events(market='sweden', start_date=None, end_date=None, min_volatility_impact='low', limit=50)
  • get_wheel_event_risk_window(ticker, market='sweden', days_ahead=14, limit=100)

本地缓存数据库工具

  • get_earnings_history(symbol, limit=10)
  • get_earnings_calendar(symbol)
  • query_local_stocks(country=None, sector=None)
  • query_local_fundamentals(symbol)

工作和管道管理

  • list_jobs()
  • get_job_logs(job_name, limit=5)
  • trigger_job(job_name)
  • toggle_job(job_name, active)
  • get_job_status()
  • run_pipeline_health_check()

能力发现

  • get_market_capabilities()
    • 返回分组功能(methods + examples)因此,法学硕士可以用具体行动回答“你能做什么?”。
  • describe_tool(tool_name)
    • 返回一个工具的参数模式(类型/默认值)、Pydantic JSON模式(如果可用)、docstring摘要和示例。
  • help_tool(tool_name)
    • 别名为 describe_tool,适用于要求 help.
  • get_server_health()
    • 返回相当于的健康有效载荷 /health.
  • get_server_metrics(output_format='json'|'prometheus')
    • 返回等效于的度量有效载荷 /metrics.

健康和指标资源

  • 资源: finance://status
  • 资源: finance://health
  • 资源: finance://metrics

LLM服务设计规则

在添加/更新工具时使用这些规则,以便其他代理可以依赖稳定的行为。

  1. 比起大型工具,更喜欢特定意图的工具。
  2. 保持安全默认值(market='sweden',低风险 limit,有界的窗户)。
  3. 钳制限制并规范已知枚举样式字段。
  4. 返回显式 criteria 和 empty_reason 对于零结果查询。
  5. 空结果不是系统错误(success=true, data=[]).
  6. 包含 as_of_date 或 as_of_datetime 当数据基于快照时。
  7. 不要伪造不可用的后端数据;返回不确定性或数据状态不足。
  8. 保持响应密钥稳定;避免破坏重命名。
  9. 尽可能保持表模式稳定;在查询/服务层进化。
  10. 使用API密钥和严格的脚本路径验证来保护管理端点。

代理指令(MCP友好)

将另一个AI代理连接到此服务器时,请使用以下指令:

  1. 先打个电话 get_market_capabilities() 用于意图路由。
  2. 对于未知工具,请致电 describe_tool(tool_name) 在执行之前。
  3. 与广泛的查询相比,更喜欢特定意图的工具。
  4. 始终使用明确的市场默认值(market='sweden')除非用户覆盖。
  5. 尊重不确定性:如果后端没有数据,则返回不足的数据响应。
  6. 切勿推断时间戳;使用 meta.asof 从工具响应。
  7. 在仅雅虎模式下(IB_ENABLED=false),避免使用IB工具,转而使用本地/Yahoo工具。
  8. 对于敏感信息,请保留 get_account_summary(masked=True) 除非用户在可信环境中明确提出其他请求。
  9. 如果工具返回 validation_error,修复输入,然后使用更正的参数重试一次。
  10. 如果电源开路(circuit_open),在冷却之前避免重复重试。

事件建模规则

在中使用统一事件 market_events 根据这份最低合同:

  • 识别: event_id, event_type, category, subtype
  • 时间: event_datetime_utc, timezone, market, is_market_hours, is_pre_market, is_after_market
  • 范围: ticker, sector, country, region, affected_markets
  • 影响: expected_volatility_impact, systemic_risk_level, is_recurring, confidence_score
  • 具体数据: expected_eps, previous_eps, expected_revenue, previous_value, forecast_value, actual_value

支持的类别:

  • corporate
  • macro
  • monetary_policy
  • geopolitical
  • market_structure

稳定响应包络

首选形状:

{
  "success": true,
  "data": {},
  "error": {
    "code": null,
    "message": null,
    "details": null
  },
  "meta": {
    "source": "ibkr|yahoo|local_db|pipeline|system|...",
    "asof": "2026-02-13T12:34:56.000000+00:00",
    "cache_ttl": null,
    "request_id": "uuid",
    "default_market": "sweden",
    "market_timezone": "Europe/Stockholm"
  }
}

笔记:

  • 信封在 mcp_server.py (tool_endpoint 装饰师)。
  • 现有服务特定密钥(count, criteria等等)被保存。

车轮分析公式

用于 wheel_service.py 并通过MCP工具暴露:

  • 卖出期回报率(%)= (premium / strike) * 100
  • 年化回报率(%)= period_return * (365 / DTE)
  • 每份合同的现金担保资本= strike * 100
  • 容量= floor((capital * (1-cash_buffer_pct)) / (strike * 100 * margin_requirement_pct))
  • 盈亏平衡(空头)= strike - premium
  • 分配概率代理= abs(delta)
  • 到期时的提款情况= max(0, break_even - final_price)

笔记:

  • abs(delta) 是一个代理,而不是一个真正的概率模型。
  • 时间比较工具返回具有显式不确定性(无预测)的情景分析。

数据管道作业(关键)

主要工作岗位 dataloader/seed.py 包括:

  • 原始摄取:雅虎价格/基本面、IBKR价格、IBKR工具、期权指标。
  • 标准化:价格、基本面、分类分类法、公司简介。
  • 策划:收益活动。
  • 分析:股票指标、市场推动者、期权IV快照、事件日历。
  • 情报缓存:新闻、机构持有人、分析师建议、财务报表快照。
  • 加载器:股票列表、参考数据、股息、历史价格、指数表现。
  • 验证:管道健康检查。

种子行为(python -m dataloader.seed):

  • 默认作业的同步:创建缺失的作业并更新现有作业(description/script/cron/timeout/tables),而不重复行。
  • 默认情况下,首次加载完全运行,并且始终以串行方式运行(没有并行作业执行)。
  • 加载顺序是基于相位的,以最大限度地提高鲁棒性:
    • MASTER:参考/股票代码/原始+转换/历史/股息/收益/分类。
    • IB:IBKR提取器/选项(仍然是串行的,可以跳过)。
    • COMPUTE:指标/推动者/事件/情报快照。
  • 第一个加载数据集包括:
    • 历史价格(5年),
    • 股息(5年),
    • 收益(10年)+管理,
    • 分类规范化+公司简介丰富,
    • 股票指标+市场推动者,
    • 标准化事件日历生成。
    • 市场情报快照。
  • 内置回退:如果筛选器基线保持为空,它将重试历史负载+指标/移动器。
  • 可选标志:
    • --skip-first-load:仅初始化DB+同步作业。
    • --skip-ib:在首次加载时跳过IB相关步骤。
    • --warmup:已弃用别名(首次加载已为默认)。

快速开始

5分钟入职培训(即插即用)

pip install -e .
python -m dataloader.seed --skip-ib
IB_ENABLED=false mcp-finance

然后将您的MCP客户端指向此服务器(以下示例)。

码头工人

docker compose up -d
docker compose --profile init run seed

本地

pip install -e .
python -m dataloader.seed
mcp-finance
python -m dataloader.app

运行时配置文件

  • Yahoo-only:
    • IB_ENABLED=false
    • 启动时没有IB连接尝试。
    • IB工具返回结构化 ib_disabled 错误。
  • IBKR + Yahoo:
    • IB_ENABLED=true (默认)
    • 需要IB网关/TWS连接和市场数据权限。

环境变量(参考)

  • IB_ENABLED:
    • true|false (默认值 true)
  • MCP_TRANSPORT:
    • sse|stdio (默认值 sse)
  • MCP_HOST:
    • 默认 0.0.0.0
  • MCP_PORT:
    • 默认 8000
  • DEFAULT_MARKET:
    • 默认 sweden
  • DEFAULT_MARKET_TIMEZONE:
    • 默认 Europe/Stockholm
  • MCP_TOOL_ALLOWLIST:
    • 逗号分隔的工具名称;如果设置,则只有列出的工具可调用
  • CIRCUIT_BREAKER_FAILURE_THRESHOLD:
    • 默认 4
  • CIRCUIT_BREAKER_COOLDOWN_SECONDS:
    • 默认 45

MCP客户端配置示例

克劳德桌面

{
  "mcpServers": {
    "finance": {
      "command": "mcp-finance",
      "env": {
        "IB_ENABLED": "false",
        "DEFAULT_MARKET": "sweden",
        "DEFAULT_MARKET_TIMEZONE": "Europe/Stockholm"
      }
    }
  }
}

光标

{
  "mcp": {
    "servers": {
      "finance": {
        "command": "mcp-finance",
        "args": [],
        "env": {
          "IB_ENABLED": "true",
          "MCP_TRANSPORT": "stdio"
        }
      }
    }
  }
}

帆板运动

{
  "mcpServers": [
    {
      "name": "finance",
      "command": "mcp-finance",
      "env": {
        "IB_ENABLED": "false"
      }
    }
  ]
}

最小Python代理

import os
import subprocess

env = os.environ.copy()
env["IB_ENABLED"] = "false"
proc = subprocess.Popen(["mcp-finance"], env=env)
print("MCP Finance server PID:", proc.pid)

安全说明

  • 集 DATALOADER_API_KEY 用于管理API端点。
  • 保持 DATALOADER_ALLOW_INSECURE=true 仅限于地方发展。
  • 配置CORS DATALOADER_ALLOWED_ORIGINS.
  • 可选工具满列表:set MCP_TOOL_ALLOWLIST=get_market_capabilities,describe_tool,....
  • 默认情况下,帐户摘要被屏蔽(get_account_summary(masked=true)).
  • 如果通过网络传输运行MCP(MCP_TRANSPORT=sse),保持主机/防火墙受限,并在MCP客户端网关上使用API/身份验证控件。

威胁模型(此服务器不执行的操作)

  • 不下订单。
  • 不修改位置。
  • 不提交交易。
  • 不转移资金。
  • 不提供有保证的预测。

按设计只读:仅分析、筛选、事件、账户检查和管道控制。

可观察性和操作性

  • get_server_health() 和资源 finance://health
  • get_server_metrics(output_format='json'|'prometheus') 和资源 finance://metrics
  • 每次工具调用的结构化JSON日志(request_id、工具、来源、延迟、成功)
  • 带冷却功能的断路器(IBKR/Yahoo/本地组)
  • 内置工具级指标:调用/失败/平均延迟/源代码故障
  • 通过IB连接运行时快照暴露的速率限制器指标

代码质量和发布

  • pre-commit 已配置挂钩(ruff, black, isort, mypy)
  • GitHub操作CI(.github/workflows/ci.yml)运行皮棉、类型检查和测试
  • 推荐释放流程:
    • 碰撞 version 在 pyproject.toml
    • 创建git标签(vX.Y.Z)
    • 更新更新日志/发行说明

操作说明

  • 如果筛选器返回空,请运行:
    • Historical Prices Loader
    • Calculate Stock Metrics
    • Update Market Movers
  • 如果Wheel IV分析报告历史记录不足,则运行选项度量作业,并 Snapshot Option IV 持续了好几天。
  • 如果期权数量稀少,请确保IB市场数据权限和期权订阅处于活动状态。
  • 对于宏观/货币/地缘政治事件,保持 dataloader/data/manual_events.json 并运行 Load Event Calendar.
  • 要刷新本地新闻/持有者/推荐/声明缓存,请运行 Load Market Intelligence.
  • 为了避免重复的手动运行,后端和前端都可以防止同一作业的并发触发器:
    • 后端返回 "Job '<name>' is already queued/running" 当存在开放运行时,
    • 前端在请求执行过程中禁用运行按钮。
  • 调度器执行模型现在是一个单一的工作队列:
    • 所有cron/手动触发器都已排队 status='queued',
    • 全球一次只有一个作业运行,
    • 已对同一作业进行重复数据消除 queued/running.
    • 在调度器启动时,孤儿 queued/running 跑步会自动恢复到 failed.
  • Jobs UI使用应用内通知/祝酒和确认模式(无浏览器 alert() 流量)。

故障排除

  • 指标种子过程中出错,如 operands could not be broadcast together with shapes (29,) (30,):
    • 通过使用稳健的返回序列来固定(pct_change)在波动率计算中,而不是脆性阵列切片。
    • 确保你遵守承诺 4d0292f 或更新。
  • 如果种子因本地缺失deps而失败,请先安装项目依赖关系:
    • pip install -e .

许可证

麻省理工学院