EvoMap
< 返回 Ghost Archive
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
[ 项目图集 ]