SECTION 9 / 多 Agent 蜂群协作
V.AGI
@ Agora
[ 团队 ]
- 吴彦熙
- 陈霖
- 符修信
- 张圣颜
> 提交时间:2026/9/24 02:33:26
[ 项目介绍 ]
项目名称:V·AGI — 本地优先的 AI 驱动金融分析与资产配置平台
开发团队:Hackathon 团队(Ethan · Gary · Liz · FXX)
核心特点:零第三方依赖(Python 标准库 + 原生 JavaScript)、本地单进程架构(127.0.0.1 only)、数据版本可追溯(SHA-256 快照归档)
一、外部 API 接入(重点)
1.1 Yahoo Finance 调整收盘价(多资产组合数据源)
端点:https://query2.finance.yahoo.com/v8/finance/chart/{symbol}
认证:无需 API Key
参数:interval=1d, range=max
口径:Adjusted Close(包含分红、拆股、资本利得分配调整)
1.2 DeepSeek Chat API(可选 AI 文字分析)
端点:https://api.deepseek.com/chat/completions
认证:Bearer Token(用户在浏览器端配置,密钥存于 sessionStorage)
默认模型:deepseek-flash
安全措施:密钥仅存 sessionStorage,后端拒绝保存包含 apiKey/api_key/secret/token/password 字段的案例,仅发送配比、金额、计算摘要和来源,不发送原始价格数组
1.3 NewsData.io API(可选资讯扫描)
端点:https://newsdata.io/api/1/news
参数:apikey, q(关键词), language=zh, category=business
二、底层运行逻辑
2.1 本地单进程架构
服务启动流程:
用户双击 gary/启动平台.command → 执行 python3 server.py --port 0 --open → ThreadingHTTPServer 绑定 127.0.0.1:<自动端口> → 打开浏览器访问 http://127.0.0.1:<port>/
关键设计:
- 单进程:Python HTTP 服务同时承担静态文件和 API 职责,避免跨进程通信
- 仅回环绑定:ThreadingHTTPServer(("127.0.0.1", port)),不接受外部网络连接
- 自动端口选择:--port 0 时自动分配空闲端口,避免端口冲突
- 无外部依赖:仅用 Python 标准库(http.server、urllib、json、threading)
安全校验:Host 校验(请求 Host 头必须为 127.0.0.1:<port> 或 localhost:<port>)、Origin 校验(有 Origin 头时必须匹配本机地址集合)、跨站点阻断(Sec-Fetch-Site: cross-site 请求被拒绝)、路径穿越防护(静态文件服务检查 resolve 后路径仍在 root 内)
2.2 数据获取与缓存流程
首次请求流程:
浏览器 GET /api/case-context?asset=oil&days=60 → backend/market.py 检查缓存 → 缓存不存在或超时 → _download() 从 FRED 下载 CSV → parse_history(raw) 校验数据格式 → 校验通过 → SHA-256 哈希 → 归档到 data/snapshots/<sha256>.csv + .json → 保存到 data/cache/brent.csv + metadata.json → calibrate() 校准 GBM 参数 → run_backtest() 执行回测 → 返回 JSON(market, calibration, source, backtest)
缓存刷新失败流程:
缓存超时 (> 6h) → 尝试从 FRED 重新下载 → 下载失败(网络错误/超时/数据异常)→ 检查缓存是否通过校验 → 是:返回旧缓存(mode: "validated_cache", refreshFailed: true, cacheAgeHours: X)→ 否:返回 503 SOURCE_UNAVAILABLE
关键原则:永不信任缓存(每次读取都重新校验 SHA-256 和数据有效性)、失败降级(刷新失败时使用通过校验的旧缓存)、明确标注(缓存陈旧度、刷新失败状态、抓取时间均在报告中保存)
2.3 GBM 校准与蒙特卡洛模拟
GBM 模型:S(t+1) = S(t) × exp[(μ − σ²/2)/252 + σZ/√252]
其中 S(t) 为 t 时刻价格,μ 为年化算术漂移,σ 为年化波动率,Z 为标准正态随机数,252 为交易日常数
参数估计(backend/market.py::calibrate):
提取最近 252 个有效观测步 → 计算对数收益 returns = [log(sample[i][1] / sample[i-1][1]) for i in range(1, 253)] → 年化波动率 σ = stdev(returns, ddof=1) × √252 → 年化漂移 μ = 252 × mean(returns) + 0.5 × σ²
蒙特卡洛模拟(js/prediction-engine.js):
使用 seedrandom 库实现固定种子可复现,默认 3000 条路径,输出中位数、50%/90% 期末区间(25%~75%, 5%~95%)、下行 10% 日末触达率、显著变动概率、零漂移对照(相同波动率,μ=0)
2.4 历史回测机制
回测原理:评估区间最近 1260 个有效观测步,预测窗口 horizon 个交易日(例如 60 天),训练窗口每次预测前使用前 252 个收益校准
评估指标:
1. 区间覆盖率:实际价格落在预测区间的比例(90% 区间理想值约 90%,50% 区间理想值约 50%)
2. 中位数 MAPE:MAPE = mean(|median_forecast - actual| / actual)
3. 方向 Brier 分数:Brier = mean((P_up - actual_up)²),越低越好,0 为完美预测,0.25 为随机猜测水平
零漂移基线对照:使用相同历史波动率但 μ=0,判断主模型是否优于"无趋势"假设
实际回测结果(60 交易日,2026-09-09 快照):
窗口数 21,主模型 90% 覆盖率 80.95%/MAPE 18.24%/Brier 0.29867,基线 90% 覆盖率 80.95%/MAPE 14.53%/Brier 0.24826,结论:主模型当前落后于零漂移基线
2.5 多资产组合计算流程
协方差估计(js/portfolio-engine.js):
1. 找到所有资产的共同交易日(至少 252 个)
2. 提取对数收益
3. 计算协方差矩阵(样本协方差,ddof=1,年化)
4. Cholesky 分解(用于生成相关随机数)
相关 GBM 模拟:生成相关的标准正态随机数(Z = L × 独立标准正态向量)→ 更新每个资产价格 → 计算组合终值
关键约束:不支持负仓位/借款/杠杆,固定持有不再平衡,现金无息,所有资产行情须与组合币种一致,未计入费用/税费/滑点/跨币种影响
2.6 案例版本化系统
版本关系数据结构:
{
"report": {
"lineage": {
"projectId": "proj_portfolio_20260920_xyz",
"versionId": "ver_20260920_123456_abc",
"versionNumber": 3,
"parentVersionId": "ver_20260920_120000_def"
},
"changes": ["总资金从 50000 调整为 100000", "期限从 30 天延长至 60 天"]
}
}
版本生成流程:
用户点击"修改金额" → 前端读取当前版本配置(GET /api/cases/:id)→ 表单预填 → 用户修改 → 核对变化 → 用户确认重新分析 → 重新运行数据获取/模拟/验证 → 生成新报告(parentVersionId = 当前版本ID)→ POST /api/cases → 后端分配 versionNumber(父版本号 + 1)→ 校验父版本存在且同项目 → 追加保存到 data/cases/<新案例ID>.json
并发保护:backend/storage.py 使用 threading.Lock 保护文件写入,同一 ID 幂等保存
---
## 三、技术架构总结
分层架构:
浏览器 SPA(引擎层:prediction-engine.js + portfolio-engine.js + hedging-engine.js + enterprise-engine.js + workflow-engine.js,UI 层:dashboard.js + simulator.js + director-projects.js + case-amount-editor.js + portfolio-editor.js + hedging-page-v2.js,基础设施层:api-adapter.js + deepseek-cli
[ 项目图集 ]