docs: 新增开发路线图与架构 / 数据流水可视化图

- docs/ROADMAP.md:M0-M5 里程碑与 Phase 1-5 开发计划(含验收口径与硬约束自查)
- docs/diagrams/qlib-architecture.html:系统架构图(Web→API→Service→Domain→存储,Qlib Adapter 与数据源支线)
- docs/diagrams/qlib-dataflow.html:数据流水图(Tushare/Sina→落地→特征→研究→实验→消费)
- 均按 archify showcase 校验交付,1440×900 ~ 2048×1320(light/dark)无溢出
This commit is contained in:
Simon
2026-09-06 16:27:16 +08:00
parent 2a52ee5e83
commit 7a89d97c0b
6 changed files with 28081 additions and 0 deletions
File diff suppressed because it is too large Load Diff
+65
View File
@@ -0,0 +1,65 @@
{
"schema_version": 1,
"diagram_type": "architecture",
"meta": {
"title": "A股量化研究平台 · 系统架构",
"quality_profile": "showcase",
"viewBox": [1360, 660],
"views": [
{ "id": "main-chain", "label": "主研究链", "focus": ["web-ui", "api", "services", "domain", "sqlite", "parquet"], "note": "从 Web UI 经 Research Specification 到持久化的业务主链。" },
{ "id": "quant-path", "label": "量化引擎链路", "focus": ["services", "qlib-adapter", "qlib"], "note": "Qlib 只经 Adapter 被调用,业务层不直接 import qlib。" },
{ "id": "source-path", "label": "数据源链路", "focus": ["tushare", "sina", "services"], "note": "Tushare 首选,新浪仅作缺失兜底与交叉验证。" }
]
},
"components": [
{ "id": "web-ui", "type": "frontend", "label": "Web UI", "sublabel": "Next.js · ECharts", "pos": [460, 16], "size": [320, 64] },
{ "id": "api", "type": "backend", "label": "FastAPI API", "sublabel": "Pydantic DTO · REST / SSE", "pos": [460, 118], "size": [320, 64] },
{ "id": "services", "type": "backend", "label": "Application Services", "sublabel": "数据 / 因子 / 策略 / 回测 / 实验", "pos": [400, 232], "size": [440, 108] },
{ "id": "domain", "type": "backend", "label": "Domain · Repository", "sublabel": "实体 + Protocol(禁 SQL)", "pos": [460, 392], "size": [320, 80] },
{ "id": "agent", "type": "backend", "label": "Agent Service", "sublabel": "AI 助手 · 受控 Tool", "pos": [30, 40], "size": [240, 62] },
{ "id": "tushare", "type": "external", "label": "Tushare", "sublabel": "日线 / 财务 / 日历(首选)", "pos": [30, 232], "size": [240, 64] },
{ "id": "sina", "type": "external", "label": "新浪财经", "sublabel": "兜底 / 交叉验证(备用)", "pos": [30, 390], "size": [240, 64] },
{ "id": "qlib-adapter", "type": "backend", "label": "Quant · Qlib Adapter", "sublabel": "Dataset / 训练 / 回测封装", "pos": [1010, 232], "size": [290, 72] },
{ "id": "qlib", "type": "external", "label": "Qlib 引擎", "sublabel": "LightGBM / 回测(不改源码)", "pos": [1010, 400], "size": [290, 68] },
{ "id": "sqlite", "type": "database", "label": "SQLite", "sublabel": "元数据 / 实验 / Job", "pos": [330, 532], "size": [240, 64] },
{ "id": "parquet", "type": "database", "label": "Parquet · Qlib Dataset", "sublabel": "行情 / 财务 / 特征", "pos": [750, 532], "size": [260, 64] }
],
"connections": [
{ "id": "req-rest", "from": "web-ui", "to": "api", "label": "REST / SSE", "labelAt": [620, 94] },
{ "id": "to-spec", "from": "api", "to": "services", "label": "Research Specification", "variant": "emphasis", "labelAt": [620, 196] },
{ "id": "to-domain", "from": "services", "to": "domain", "label": "Repository Protocol · 编排", "labelAt": [620, 366] },
{ "id": "domain-sqlite", "from": "domain", "to": "sqlite", "label": "元数据 / 实验", "fromSide": "bottom", "toSide": "top" },
{ "id": "domain-parquet", "from": "domain", "to": "parquet", "label": "时序 / 特征", "fromSide": "bottom", "toSide": "top" },
{ "id": "fetch-tushare", "from": "tushare", "to": "services", "label": "行情 / 财务(首选)", "variant": "emphasis", "labelAt": [250, 318] },
{ "id": "fallback-sina", "from": "sina", "to": "services", "label": "兜底(缺失)", "variant": "dashed" },
{ "id": "to-adapter", "from": "services", "to": "qlib-adapter", "label": "因子 / 回测 Job", "variant": "emphasis" },
{ "id": "adapter-qlib", "from": "qlib-adapter", "to": "qlib", "label": "Dataset / 训练 / 回测", "fromSide": "bottom", "toSide": "top", "labelAt": [1155, 318] },
{ "id": "agent-tools", "from": "agent", "to": "services", "label": "受控 Tool(Phase 5)", "variant": "dashed" }
],
"cards": [
{
"dot": "emerald",
"title": "主研究链",
"items": [
"Web UI → API(Research Specification DTO)→ 服务编排 → Repository → SQLite / Parquet",
"Qlib 仅经 Qlib Adapter 调用,业务层不直接 import qlib"
]
},
{
"dot": "violet",
"title": "数据源与边界纪律",
"items": [
"Tushare 首选,新浪兜底须经统一 Provider 并记录来源,禁止静默切换",
"业务层禁 SQL / Session 直连;Agent 仅走受控 Tool(Phase 5)"
]
},
{
"dot": "amber",
"title": "异步与可复现",
"items": [
"因子 / 训练 / 回测为异步 Job:queued → running → success / failed / cancelled",
"所有研究落 Experiment,含数据与代码版本,可一键复跑"
]
}
]
}
File diff suppressed because it is too large Load Diff
+373
View File
@@ -0,0 +1,373 @@
{
"schema_version": 1,
"diagram_type": "dataflow",
"meta": {
"title": "A股量化研究平台 · 数据流水",
"quality_profile": "showcase",
"viewBox": [
1300,
693
],
"views": [
{
"id": "main-path",
"label": "主研究数据流",
"focus": [
"tushare",
"provider",
"parquet",
"dataset",
"factor",
"backtest",
"experiment",
"api",
"web"
],
"note": "行情从 Tushare 一路流转到可复现的实验与可视化。"
},
{
"id": "future-free",
"label": "防未来函数口径",
"focus": [
"provider",
"sqlite",
"parquet",
"dataset"
],
"note": "财务数据按 announce_date 控制可见性,查询一律带 as_of_date。"
},
{
"id": "agent-path",
"label": "AI 研究助手消费",
"focus": [
"experiment",
"api",
"web"
],
"note": "结果经 API 提供给 Web UI;AI Agent(Phase 5)仅经受控 Tool 经 API 消费研究数据。"
}
]
},
"stages": [
{
"label": "数据接入"
},
{
"label": "数据落地"
},
{
"label": "特征构建"
},
{
"label": "研究计算"
},
{
"label": "回测 · 实验 · 消费"
}
],
"nodes": [
{
"id": "tushare",
"type": "external",
"label": "Tushare",
"sublabel": "日线 / 财务 / 交易日历",
"tag": "首选",
"stage": 0,
"row": 0,
"height": 36,
"yOffset": -2
},
{
"id": "provider",
"type": "backend",
"label": "Data Provider",
"sublabel": "归一化 / 校验 / 审计",
"tag": "MarketDataProvider",
"stage": 0,
"row": 2,
"width": 130,
"height": 36,
"yOffset": -2
},
{
"id": "sina",
"type": "external",
"label": "新浪财经",
"sublabel": "缺失兜底 / 交叉验证",
"tag": "备用",
"stage": 0,
"row": 4,
"height": 36,
"yOffset": -2
},
{
"id": "sqlite",
"type": "database",
"label": "SQLite",
"sublabel": "股票 / 日历 / 因子定义 / Job",
"tag": "业务库",
"stage": 1,
"row": 0,
"height": 36,
"yOffset": -2
},
{
"id": "parquet",
"type": "database",
"label": "Parquet",
"sublabel": "历史行情 / 复权 / 财务时序",
"tag": "时序库",
"stage": 1,
"row": 2,
"height": 36,
"yOffset": -2
},
{
"id": "dataset",
"type": "database",
"label": "Qlib Dataset",
"sublabel": "data/qlib 特征集",
"tag": "研究数据",
"stage": 2,
"row": 2,
"height": 36,
"yOffset": -2
},
{
"id": "factor",
"type": "backend",
"label": "因子研究",
"sublabel": "Alpha158 / 自定义因子",
"tag": "IC · 分层测试",
"stage": 3,
"row": 0,
"height": 36,
"yOffset": -2
},
{
"id": "model",
"type": "backend",
"label": "模型训练",
"sublabel": "LightGBM",
"tag": "预测信号",
"stage": 3,
"row": 2,
"height": 36,
"yOffset": -2
},
{
"id": "backtest",
"type": "backend",
"label": "选股回测",
"sublabel": "调仓 / 成本 / 涨跌停 / 停牌",
"tag": "低频策略",
"stage": 4,
"row": 0,
"height": 36,
"yOffset": -2
},
{
"id": "experiment",
"type": "database",
"label": "Experiment",
"sublabel": "参数 / 结果 / 数据与代码版本",
"tag": "可复现",
"stage": 4,
"row": 1,
"height": 36,
"yOffset": -2
},
{
"id": "api",
"type": "backend",
"label": "FastAPI API",
"sublabel": "业务 API(Pydantic DTO)",
"tag": "REST / SSE",
"stage": 4,
"row": 3,
"height": 36,
"yOffset": -2
},
{
"id": "web",
"type": "frontend",
"label": "Web UI",
"sublabel": "Next.js · ECharts",
"tag": "结果可视化",
"stage": 4,
"row": 4,
"height": 36,
"yOffset": -2
}
],
"flows": [
{
"id": "raw-tushare",
"from": "tushare",
"to": "provider",
"label": "行情 / 财务 raw",
"variant": "emphasis"
},
{
"id": "raw-sina",
"from": "sina",
"to": "provider",
"label": "兜底 raw",
"variant": "dashed"
},
{
"id": "to-sqlite",
"from": "provider",
"to": "sqlite",
"label": "股票 / 日历 / 元数据",
"labelAt": [
212,
256
]
},
{
"id": "to-parquet",
"from": "provider",
"to": "parquet",
"label": "行情 / 财务时序",
"route": "straight",
"labelAt": [
212,
426
]
},
{
"id": "calendar-to-dataset",
"from": "sqlite",
"to": "dataset",
"label": "交易日历 / 股票池",
"labelAt": [
422.5,
276
]
},
{
"id": "series-to-dataset",
"from": "parquet",
"to": "dataset",
"label": "行情特征输入",
"route": "straight",
"labelAt": [
452,
426
]
},
{
"id": "dataset-to-factor",
"from": "dataset",
"to": "factor",
"label": "特征矩阵",
"variant": "emphasis",
"labelAt": [
637.5,
268
]
},
{
"id": "dataset-to-model",
"from": "dataset",
"to": "model",
"label": "训练 / 预测特征",
"route": "straight",
"labelAt": [
610,
426
]
},
{
"id": "factor-signal",
"from": "factor",
"to": "backtest",
"label": "因子信号"
},
{
"id": "model-signal",
"from": "model",
"to": "backtest",
"label": "预测信号",
"labelAt": [
852.5,
298
]
},
{
"id": "factor-archive",
"from": "factor",
"to": "experiment",
"label": "因子测试归档",
"fromSide": "top",
"toSide": "right",
"via": [
[
745,
98
],
[
1060,
98
],
[
1060,
258
]
],
"labelAt": [
1060,
176
]
},
{
"id": "backtest-archive",
"from": "backtest",
"to": "experiment",
"label": "回测结果归档",
"variant": "emphasis"
},
{
"id": "query-result",
"from": "experiment",
"to": "api",
"label": "结果查询 DTO"
},
{
"id": "to-web",
"from": "api",
"to": "web",
"label": "REST / SSE"
}
],
"cards": [
{
"dot": "emerald",
"title": "主研究数据流",
"items": [
"Tushare → Data Provider(归一化 / 校验 / 审计)→ SQLite 与 Parquet 分流",
"Qlib Dataset 汇总日历与行情 → 因子 / 模型 → 回测 → Experiment 全量归档",
"每条拉取记录 source / 行数 / 时间,来源可追溯"
]
},
{
"dot": "violet",
"title": "防未来函数口径",
"items": [
"财务数据区分 report_date / announce_date,仅 announce_date 后可见",
"研究查询一律带 as_of_date,禁止未来成分 / 行业 / 财务数据",
"新浪仅作缺失兜底与交叉验证,禁止静默切换"
]
},
{
"dot": "amber",
"title": "结果消费",
"items": [
"Experiment → FastAPI API → Web UI(REST / SSE)可视化",
"AI Agent(Phase 5)仅经受控 Tool 经 API 读取研究数据与实验",
"历史实验含数据与代码版本,可一键复跑"
]
}
]
}