Simon
|
ba52edc2d6
|
feat(signal): M8.1 交易信号引擎(规则 + signal_event 落库 + /api/signals)
- SignalRules(买入 rank 阈值/趋势 MA/动量 + 卖出区间/破位警示)+ SignalEvent
(BUY/WATCH/SELL,score/price/trigger_reason 可解释)+ SignalResult/Meta
- quant/signal.generate_signals:与选股同一评分引擎取全市场 rank,按规则分类输出
- signal_snapshot/signal_event 表(migration d8e0b2f3c4d5,MySQL 已应用)+ Repo
- SignalService + POST /api/signals(同步+落库)、GET 详情/列表
- tests/test_signals.py(引擎分类/排序/破位不 BUY、service、API 提交读回);全量 pytest 通过
|
2026-09-09 00:35:37 +08:00 |
|
Simon
|
ef09d5b419
|
feat(quant): M7.3 研究行情口径显式化(默认不复权 none,可切 qfq)
- DailyBarRepository.get_range_many / stream_range_many_columns 增加 adjust 参数
(默认 'none')→ SQL 层过滤口径,消除 stock_daily 混 source/adjust 污染因子的风险
- ResearchSpec / SelectionQuery 增加 price_adjustment(none|qfq),随 config_snapshot
落库可溯源;ResearchService._load_daily 与 SelectionService 装配按口径取数
- tests/test_price_adjustment.py:repo 读取按 adjust 过滤(none/qfq 各自命中)、
spec 默认与字段记录;全量 pytest 通过
|
2026-09-09 00:32:55 +08:00 |
|
Simon
|
4fa2bb748e
|
feat(composite): M7.2b 因子组合落库 + /api/composites CRUD
- factor_composite 表(migration c3e9a0d1f4b5,MySQL 已应用;name 唯一)
- CompositeDefinition/Component 实体 + CompositeRepository Protocol + SQLAlchemy 实现
- /api/composites:POST(注册表自动填充组件 direction;未注册因子 400)、GET 列表/详情、DELETE
- tests/test_composites_api.py(repo CRUD/同名拒绝/删除、API 方向填充/404/400);全量 pytest 通过
|
2026-09-09 00:30:37 +08:00 |
|
Simon
|
273aee2772
|
refactor(quant): M7.2a Composite Engine 模块化(quant/composite.py)
- cross_sectional_zscore / composite_score / build_factor_panels 从 local_engine 迁入
quant/composite.py;新增统一入口 build_score_panel(daily, factor_specs)
- local_engine re-export 保持旧引用兼容;selection/engine 的评分面板构建均指向
composite —— 选股与回测的复合分实现收敛于一处
- 回归:quant/eval/research/selection 一致性/qlib 引擎测试全过;全量 pytest 通过
|
2026-09-09 00:29:23 +08:00 |
|
Simon
|
8f47b5b603
|
feat(factor): M7.1 因子定义入库 + /api/factors 读库(目录契约源)
- factor_definition 表(migration b7f2a5e81c33,MySQL 已应用):name 主键 + 元数据
(formula/brief/frequency/lookback/direction/requires JSON/version)+ FactorDefinition
entity(from_registry_def 由代码注册表构造)
- FactorRepository Protocol + SQLAlchemy 实现(幂等 upsert/list/get)
- /api/factors 改读 DB;目录为空自动 seed 注册表(幂等)—— 保留自定义因子登记能力
(计算仍须代码注册,引用未注册因子照常 FactorError,防伪因子)
- tests/test_factor_catalog.py(repo 幂等/roundtrip/registry seed、API seed+字段齐全);
test_api 的 client fixture 补 tmp sqlite session(factors 读库);全量 pytest 通过
|
2026-09-09 00:28:16 +08:00 |
|
Simon
|
0ab9038570
|
feat(web): M6.5 股票筛选页(/selection)—— 评分/条件双模式 + 当前/历史选股
- app/selection/page.tsx:因子评分(多因子+权重+TopN)与条件模式(结构化条件行
编辑:static.*/因子/close>ma60/ROE 等,AND 语义);as_of 留空=最近交易日;
结果表(rank/symbol/score/因子值/入选理由)+ 最近选股记录点击回看
- lib/types.ts:SelectionQuery/Condition/Candidate/Result/Meta/Run DTO
- app-shell 导航加入「股票筛选」;rail 脚注与 Dashboard 文案 SQLite→MySQL(M-DB 收尾)
- 端到端验证:真实 MySQL 上 POST /api/selections 返回候选并落库可读回;
/selection 页面 200;后端全量 pytest + 前端 tsc --noEmit 通过
|
2026-09-09 00:25:27 +08:00 |
|
Simon
|
0d3e123de3
|
feat(selection): M6.4 回测与选股共用评分引擎(v2 §25 一致性锁定)
- quant/selection.score_panel_for_factors:复合分面板构建收敛为共享函数;
LocalEngine.run_backtest 与 SelectionEngine.run_score_selection 均调它 ——
消除「回测一套评分、选股另一套」的隐患
- tests/test_selection_backtest_consistency.py:对回测每个调仓日验证
SelectionService.select(as_of=d, top_n) 候选 == 该日回测实际持仓(月调仓多时点),
排序方向一致性亦验证;全量 pytest 通过
|
2026-09-09 00:22:08 +08:00 |
|
Simon
|
c60dc78c88
|
feat(selection): M6.3 选股结果落库 + /api/selections(快照 + 逐候选行)
- domain/repositories/selection.py + SelectionMeta:选股 Repository Protocol
- models/selection.py + migration a6c91d4e7f20:selection_snapshot(查询/统计快照)+
selection_result(逐候选:rank/score/factor_values/filter_status/reason JSON)
- repositories/selection_impl.py:save/get/list_recent(读回重建 SelectionResult)
- api/selections.py:POST /api/selections(同步执行+落库,返回 selection_id+result)、
GET /{id}、GET 列表(as_of/method 过滤);deps 装配 SelectionService/Repo
- config._build_mysql_url:仅编码破坏 URL 结构的字符(修 Alembic configparser 遇 %21 崩)
- 迁移已在 MySQL 应用(alembic head a6c91d4e7f20);tests/test_selections_api.py 4 例
提交→读回一致/404/列表过滤/condition;全量 pytest 通过
|
2026-09-09 00:20:42 +08:00 |
|
Simon
|
75c5472c31
|
feat(selection): M6.2 条件选股(method=condition + 财务可见性防护)
- quant/selection.run_condition_selection:结构化条件 AND 求值 —— 字段域
static.*(行业/市场…)、技术列与派生量(close/volume/ma20/ma60)、已注册因子
(momentum_60 等)、fundamental.*(announce_date<=as_of 的最新已公告财务值);
条件支持 value 字面量与 ref 字段比较(如 close > ma60);结果带 filter_status/reason
- SelectionQuery 校验调整:condition 模式为纯过滤(不再强制 top_n/top_pct)
- FinancialRepository 新增 list_announced_many(批量防未来函数读取)+ SQLAlchemy 实现;
SelectionService 注入 financial_repo 并按 announce_date 取每股最新一版
- tests/test_selection_condition.py:8 例(行业 in/ne、动量>0、close>ma60 ref、阈值、
ROE 过滤且未来公告不可见、缺财务 repo 报错、更早 as_of 排除);全量 pytest 通过
|
2026-09-09 00:16:45 +08:00 |
|
Simon
|
25a1d9531a
|
feat(selection): M6.1 Universe 选股范围执行器(规则化 + symbols 白名单 + 历史日语义)
- quant/universe.py:filter_stocks 从 quant/service 迁出并集中(ST/上市天数/退市过滤),
as_of 当前/历史日语义由 delist/list_date 保证;exclude_suspended 依赖停牌表未建模,
由上层显式标注(选股结果 unimplemented)
- research.UniverseSpec 增加 symbols 白名单(非空时仅白名单内参与,再叠加其余过滤)
- quant/service re-export filter_stocks(外部引用不变);SelectionService 已共用
- tests/test_universe.py:6 例覆盖当前/历史日、ST、上市天数、退市、白名单;全量 pytest 通过
|
2026-09-09 00:13:28 +08:00 |
|
Simon
|
f3586adb25
|
feat(selection): M6.0 选股契约与评分引擎(SelectionQuery/Result + select(as_of))
- domain/entities/selection.py:SelectionQuery(universe+method+factors+top_n/top_pct/
min_score+as_of+预热)与 SelectionResult/Candidate/Statistics(v2 §14.2/§21.1 DTO);
ConditionSpec 字段就位供 M6.2 条件选股
- quant/selection.py:Selection Engine method=score —— 复合分(zscore×权重×方向)
→ TopN/Top% 截断;observation_date=<=as_of 最近交易日(防未来函数,v2 §9);
候选带 factor_values 与 selection_reason(可解释)
- application/services/selection_service.py:选股用例(universe 过滤 → 装配 → 引擎)
- quant/service.py:抽取公共 load_daily_df 供研究/选股共用(行为不变)
- tests/test_selection.py:11 例 —— TopN/排序/理由、as_of 防未来函数、ST/上市天数/
退市过滤、top_pct/min_score、空数据与查询校验;全量 pytest 通过
|
2026-09-09 00:12:28 +08:00 |
|
Simon
|
697ffc767b
|
docs: DEV_PLAN_v2 以选股系统为下一阶段主线(用户定调)
- 新路线:M6 选股系统(Universe 选股范围 + Selection Engine A 条件/B 评分 +
selection_result/snapshot 落库 + /api/selections + 回测共用引擎 + Web 选股页)
→ M7 因子层落地(原 M6 内容后移为支撑)→ M8 Signal/Portfolio/Strategy/Agent/模型选股
- 选股 MVP 复用现有数据与 9 因子/composite_score,不阻塞于因子入库
- 明确历史/当前 as_of 一致性、selection_reason 可解释、未来函数防护与范围控制
|
2026-09-09 00:06:31 +08:00 |
|
Simon
|
0ffd574f30
|
docs: 下阶段开发计划(架构 v2 落地 M6-M8)+ MySQL 迁移文档同步
- docs/DEV_PLAN_v2.md:基于 ARCHITECTURE_v2 与 M0-M5 现状的下一阶段计划
(M-DB 迁移收尾 → M6 因子定义入库/复合因子/口径修复 → M7 Selection/Signal/
Portfolio 引擎分层 → M8 Strategy 平台化/Web 做实/Agent 工具补齐;含本机 Redis
127.0.0.1:6379 的接入触发点与执行顺序)
- ROADMAP.md:登记 M-DB 里程碑并指向 DEV_PLAN_v2
- USAGE.md / README.md:数据库描述由 SQLite 更新为 MySQL(config.yaml database.mysql)
|
2026-09-08 23:58:51 +08:00 |
|
Simon
|
6c2f198261
|
feat(db): SQLite 全量迁移至 MySQL(config.yaml 配置化 + 迁移脚本 + 一致性校验)
- config.yaml database.mysql:host/port/db/user/charset 明文可提交;密码经 password_env
引用 .env 的 MYSQL_PASSWORD(AGENT.md §33 密钥不进 git)
- config.py _build_mysql_url:URL 优先级 DATABASE_URL env > database.mysql 段 > sqlite 兜底
- pyproject 引入 pymysql>=1.1
- tests/conftest.py 强制每进程 /tmp SQLite(测试绝不触 MySQL 开发库);test_config 覆盖
mysql 组装/密码可选/sqlite 兜底分支
- scripts/migrate_sqlite_to_mysql.py:sqlite→mysql 一次性迁移工具(keyset 分页 + chunk
多值 INSERT + 攒批 commit + 幂等续传 + 低配 MySQL 节流 --throttle-sec + --verify-only
行数与抽样一致性校验);已用于 data/quant.db 约 1605 万行迁移并经校验一致
|
2026-09-08 23:58:48 +08:00 |
|
Simon
|
a3fabf9ae9
|
docs: 新增架构文档 v2(ARCHITECTURE_v2)
|
2026-09-08 21:48:23 +08:00 |
|
Simon
|
db520d0430
|
build(web): Noto Sans SC 本地自托管,移除 Google Fonts 在线依赖
- 经 3128 代理下载可变字体(400-700)101 个 unicode-range 子集到 public/fonts
- app/fonts.css 生成本地 @font-face 表,globals.css 改用 @import './fonts.css'
- 页面运行期不再请求 fonts.googleapis.com / fonts.gstatic.com
|
2026-09-08 21:48:23 +08:00 |
|
Simon
|
24f98e90c6
|
feat(web): 按 ui-ux-pro-max 设计系统重构前端(侧边导航 + 组件库 + 图标 + 可视化)
- 设计令牌与组件体系:语义色/间距/圆角/状态 + Card/Metric/Pill/Btn/Field/Empty/Skeleton/Progress 等
- 桌面左侧导航 + 窄屏抽屉(usePathname 高亮、ESC/遮罩关闭);修复抽屉/遮罩占据网格把 main 挤到第二行的问题
- 自绘内联 SVG 图标集替代 emoji;图标/表格/按钮等交互态齐全,空态/加载/错误/禁用态补齐
- 因子研究分层柱状、因子组合与回测净值/回撤双图 + 月度收益热力表、实验页任务状态徽标
- LineChart 主题化并按需引入 echarts(回测/组合首载 JS 448k→281k);next.config 放行局域网 dev 来源
|
2026-09-08 21:48:20 +08:00 |
|
Simon
|
442999f701
|
feat(data): 财务/日线同步增量 + 新浪「两边一致」校验兜底 + 逐只进度
- financial 默认增量:按 A 股披露节奏判断已最新并跳过;--full 强制全量重拉
- Tushare fina_indicator 增加报告期窗口与 100 条/请求自动分页(修复老报告期静默截断)
- 新浪兜底收紧为校验兜底:两源重叠历史一致才导入缺失键,行标记 source=sina;
财务可比字段取 eps/销售毛利率(ROE 两端口径不同不作依据),日线只比较最近重叠交易日
- CLI 输出逐只进度与导入内容描述(来源/行数/报告期与公告区间),失败股票留待重跑
- financial_indicator 增 source 列(迁移 d3f6c9a21b04);新增一致性/分页/服务测试
|
2026-09-08 21:48:09 +08:00 |
|
Simon
|
a77d3c13c3
|
feat(web): 因子研究升级 + 因子组合页
- 因子元数据增加 brief 使用简介(后端 FactorDef + /api/factors 返回,9 个内置因子补齐文案)
- 因子研究页:
· 时间默认「今日 ~ 近 6 个月」
· 因子多选,逐个跑 IC/RankIC Job 并分卡展示报告
· 目录显示使用简介,行点击展开公式/方向/用法详解
· 新增计分规则说明与「去因子组合」入口
- 因子组合页 /factors/compose:多因子勾选+权重、组合得分规则说明(z-score×权重求和→TopN),
可配 topN/调仓/区间/ST,一键回测 Job → 净值/回撤/月度/未建模标注
- 回测页时间默认同样近 6 月
- 验证:tsc + next build 通过;组合回测(momentum_60×1.5 + volatility_60×1.0)Job 成功归档
EXP-330CAAAE(-13.51%,交易 20);后端 factors/research/api 相关测试通过 / ruff clean
|
2026-09-07 21:36:16 +08:00 |
|
Simon
|
1cf7c84897
|
fix(web): 因子研究/回测改走异步 Job(修复全市场研究长请求被代理中断 500)
- 根因:全市场因子测试同步执行约 47s,经 Next 同源代理转发时长请求被 socket 中断(前端日志:Failed to proxy .../api/factor-tests [socket hang up])
- factors/backtest 页改为 POST /api/jobs 提交 → 轮询 GET /api/jobs/{id} → 取内嵌结果(AGENT §19 异步化)
- 新增 lib/jobs.ts(submitJob / waitJob,超时 10 分钟),运行中显示 Job 号
- 端到端验证:全市场 momentum_60 测试 JOB-93479087 → success(IC -0.0598,样本 323 日)+ Experiment 归档
- tsc + next build 通过;同步接口保留(适合小样本/脚本调用)
|
2026-09-07 20:38:56 +08:00 |
|
Simon
|
55b684fbe1
|
feat(scripts): dev.sh 前后端一键 start/stop/restart/status/logs
- 启动后端 uvicorn(:8000, --reload, 0.0.0.0) + 前端 next dev(:3000),setsid 独立进程组
- 停止按 pidfile + 监听端口双定位,整进程组清理(无子进程残留,实测残留 0)
- 端口探测 ss 优先(lsof 在该环境对 socket 不可靠)
- status/logs/restart;支持 API_PORT/WEB_PORT/BACKEND_API_URL 覆盖
- 日志落 logs/,pid 落 .run/(均已 gitignore);USAGE §5 增加用法
|
2026-09-07 20:13:39 +08:00 |
|
Simon
|
195f5d41f4
|
perf(backend): 内存优化三项——全市场研究不再占满 8G
1) 数据装配流式+列裁剪:Repository 新增 stream_range_many_columns(只 SELECT
所需列、SQL 侧转 REAL、yield_per 分批),引擎按 required_columns 取数
(LocalEngine 仅 close+因子字段),消除 ORM/Decimal 全量物化;
2) 研究 Job 独立子进程执行(job.mode=subprocess):python -m app.cli.run_job
在子进程内设 RLIMIT_AS 上限,OOM 归档 failed 而非拖垮 API worker;
子进程异常退出由父进程补记 failed;并发上限 2;
3) 服务启动清理:残留 queued/running Job 标记 failed(防永久 running)。
实测同款全市场回测:uvicorn worker RSS 稳定 ~220MB,任务峰值内存由 4.1GB+
降至 ~470MB,24s 完成并归档(此前 43s 未完成即 OOM)。
新增/更新测试 96 passed,ruff 干净。
|
2026-09-06 22:12:44 +08:00 |
|
Simon
|
02e42184be
|
test+fix: 新浪 jsonp 稳健解析(容忍注释/括号包裹/尾部杂字符);Job API 测试改 tmp 种子库
- 真实响应含 /*...*/ 注释与 var data=([...]); 前缀 → _extract_jsonp 取首 '[' 至末 ']'
- 新浪真实网络冒烟通过:财务 100 期(含披露日)+ 日K 最近窗口(source=sina/adjust=qfq)
- TestJobsApi / experiments 用例改为 monkeypatch SessionLocal → tmp 种子库(5 股×300 日),
与真实全市场库(779 万行)解耦,全量稳定 <1min
- pytest 全量 141 passed / ruff clean
|
2026-09-06 21:34:29 +08:00 |
|
Simon
|
56254172b3
|
feat(data): Tushare 限速退避 + 新浪兜底(财务 getFinanceReport2022 / 日K 前复权),source+adjust 口径标记
- TushareProvider:频率超限按指数退避重试(不再一次 200/min 即中断),最长等待 30s
- SinaProvider 重构(参考 cc-cursor 公开接口实现):
· 新增财务通道 CompanyFinanceService.getFinanceReport2022(source=gjzb) → FinancialIndicator
(report_date / announce_date=publish_date),与 Tushare fina_indicator schema 一致
· 日 K 保留 jsonp(前复权),统一 UA + 重试
· 不支持方法仍抛 DataSourceNotSupported(复权因子/交易日历/基础信息)
- FailoverProvider 现在可对 daily 与 financial 兜底(CLI _failover_provider 接 SinaProvider)
- DailyBar + stock_daily 表新增 source/adjust 列:新浪兜底行标记 sina/qfq,
Tushare 恢复后 --resume 按同键覆盖回不复权 → 两源格式一致且可追溯
- 迁移 91c4e27a03fb 已生成;执行需在全市场同步结束后:uv run alembic upgrade head
- 测试 34+ 项(新浪财务解析/格式一致/限速退避等)通过
|
2026-09-06 20:52:13 +08:00 |
|
Simon
|
e2741a0236
|
feat(cli): daily --resume 对已最新股票直接跳过并明示增量结果
- 增量基准改为「本地全局最新交易日」:股票本地已含该日期 → 跳过,不再发空区间 API 请求(此前 end=今天 在周末/盘前会多调一次返回 0 根,观感像非增量)
- 汇总输出区分写入量与跳过数:…写入 N 根;增量跳过(已最新)M 只(本地最新 YYYY-MM-DD)
- smoke:600519.SH(已到 2026-09-04)→ 即时返回『跳过 1 只』,无 API 空调用
|
2026-09-06 20:43:49 +08:00 |
|
Simon
|
778c4beb07
|
perf(data): Repository 批量 upsert —— 批次一次性查重 + 批量插入/更新
- 原实现逐行 select→insert/update,是全市场同步耗时主因
- 改为:组合键 row-constructor IN 一次查重 → 新行 add_all 批量插入、已有行就地更新
- 批内重复键(数据源偶发)以最后出现者为准覆盖,保持原语义
- 测试:repository/domain/factors/eval/engine/qlib/provider/migrations 等 67 项通过(tmp 库);
依赖真实 quant.db 的 API/Job 测试在全市场同步结束后补跑
|
2026-09-06 20:40:01 +08:00 |
|
Simon
|
b78852f01b
|
fix: 前端同源代理 /api → 后端(任意 IP 访问不再 NetworkError)+ SQLite 写锁等待
- 根因①:页面硬编码 http://127.0.0.1:8000/api,从 192.168.1.160:3000 访问时浏览器请求自身/跨域失败
- 根因②(500):全市场数据同步(长写事务)持有 SQLite 锁导致读接口 database is locked
- 前端:next.config.ts rewrites /api/* → http://127.0.0.1:8000/api(BACKEND_API_URL 可覆盖);
lib/api.ts 默认相对 /api 同源(NEXT_PUBLIC_API_BASE 保留为直连覆盖项);.env.local.example 说明两种方式
- 后端:CORS 开发期 allow_origins=["*"](无凭据,上线前收紧);SQLite engine busy_timeout=30s
- USAGE FAQ 同步;验证:192.168.1.160:3000/api/health 与 /api/factors 经代理 200,CORS 头 access-control-allow-origin: *
|
2026-09-06 19:00:49 +08:00 |
|
Simon
|
fc12ba89ad
|
docs(USAGE): 更新至 QlibEngine v1 / Parquet 导出后的最新状态
- 适用版本 HEAD、技术栈(pyarrow/pyqlib/LightGBM)
- 新增 §6.1 双引擎说明(LocalEngine 默认 / QlibEngine v1 切换与 float32 差异)
- 补 export 命令、API 端点(health/stocks/{symbol})、引擎与 Parquet 相关 FAQ
- 测试计数与覆盖清单更新(86 passed)
- 限制与说明同步(QlibEngine init 幂等、Alpha158+LightGBM 仍为 TODO)
|
2026-09-06 18:23:37 +08:00 |
|
Simon
|
bbb5c1ea52
|
feat(cli): sync export — 日线按年导出 Parquet(data/parquet/stock_daily/<year>.parquet)
- 对应 ROADMAP §1.4「历史时序大数据转 Parquet」;pyarrow 随 qlib 依赖已可用
- 用法:uv run python -m app.cli.sync export [--years 2023,2024]
- 实测:9680 行 → 2023/2024 两个 parquet(data/parquet 已被 gitignore)
- ruff clean / pytest 86 passed
|
2026-09-06 18:21:55 +08:00 |
|
Simon
|
b8f67f99ae
|
feat(quant): QlibEngine v1 — 本地行情落盘 QlibDataset → D.features 读取 → 因子回测
- qlib_adapter/provider.py:SQLite 行情按 qlib 0.9.8 二进制格式落盘(起始索引头 + 逐日 float32、instruments 3 列、小写 instrument、晚上市 offset)
- qlib_adapter/dataset.py:qlib.init 幂等({'day': uri})+ D.features 读取 close 面板
- qlib_adapter/engine.py:QlibEngine(QuantEngine)v1 —— Qlib 数据管线回测与 LocalEngine 同记账规则(无未来函数/成本/涨跌停标注),factor_test 复用共享实现;Alpha158+LightGBM 为 TODO
- 真实 20 股验证:qlib 落盘 142 文件→读取→回测(-12.81%,Local 对照 -12.97%,差异为 qlib float32 存储)
- tests/test_qlib_engine.py 5 项(格式/roundtrip/晚上市 offset/回测/因子测试)→ pytest 86 passed / ruff clean
|
2026-09-06 18:20:28 +08:00 |
|
Simon
|
880f4c50fe
|
docs: Qlib 安装可用性验证报告 + 基线验证脚本
- pyqlib(0.9.8.dev32 源码安装)验证:import / 数据落盘 / storage 底层读回 / Alpha158 / LGBModel 均通过(scripts/qlib_verify.py 可重复)
- 记录格式要点:小写 instrument、instruments 3 列、provider_uri 需 {'day': path} 字典
- 如实记录未打通项:D.features→训练→回测高层链路仍待 QlibEngine 实现(建议按官方 dump 规则落盘)
- 项目回归保持 81 passed / ruff clean
|
2026-09-06 18:02:22 +08:00 |
|
Simon
|
c5349bf9da
|
docs(env): .env.example 说明 LLM 仅需 API Key(URL/模型见 config.yaml agent.llm)
|
2026-09-06 17:57:36 +08:00 |
|
Simon
|
01d818e12a
|
docs: 使用说明 docs/USAGE.md;LLM URL/模型名配置移到 config.yaml(.env 仅 Key)
- config.yaml 新增 agent.llm:base_url / model 明文配置(默认百炼兼容端点 qwen-plus),api_key 只从 .env 的 LLM_API_KEY 读取;LLM_BASE_URL / LLM_MODEL 仍可经 .env 覆盖
- .env.example 注释同步;core.config 读取逻辑 env > yaml > 默认
- docs/USAGE.md:安装/配置/数据同步/启动/研究 API 与 Job/Experiment/Agent/测试门禁/已知限制/FAQ
- README 增加使用说明入口
- 新增 config LLM 测试 2 项(yaml 默认 + env 覆盖)→ pytest 81 passed / ruff clean
|
2026-09-06 17:57:15 +08:00 |
|
Simon
|
8f8b6d274f
|
feat: 解决 aarch64 上 Qlib 安装(源码 git 固化依赖)并记录下载代理规则
- backend/pyproject.toml + uv.lock: pyqlib 以 git+https 固定 commit 79633dd 注册为核心依赖,
替代无法在 Linux aarch64 安装的 PyPI wheel(ROADMAP §2 旧备注)
- engine.py: 更正占位说明(Qlib 现已可安装,工作流实现待 Phase 2 补齐)
- AGENT.md §0: 网络下载困难时使用 HTTP 代理 192.168.1.160:3128
- README / ROADMAP: 同步 Qlib 安装方式与代理说明
|
2026-09-06 17:45:01 +08:00 |
|
Simon
|
d9be75a98f
|
feat: Phase 5 — AI Research Agent(受控工具白名单 + LLM 编排 + API)
- agent/tools.py:Tool 元数据(JSON Schema)+ 白名单调用(异常转可读反馈,不中断对话)
- agent/tools_impl.py:6 个受控工具 search_stocks / get_market_data / test_factor / run_backtest / get_experiment / compare_experiments —— 全部只读经 Job/Experiment 链路,研究自动归档;无 shell/任意执行/写删数据能力
- agent/llm.py:LLMClient 抽象 + OpenAI 兼容客户端(LLM_API_KEY/LLM_BASE_URL/LLM_MODEL 走 .env,未配置给出引导提示)+ 研究纪律 system prompt(反过拟合/样本外/成本)
- agent/service.py:编排循环(tool/final JSON 决策 → 执行 → 回喂 → 结论),轮次上限兜底,未知工具拒绝
- /api/agent/chat;httpx 移至主依赖;Job 默认工厂抽取(api/agent/executor 复用)
- 测试 6 项(白名单无 shell、完整研究循环产出、未知工具拒绝、轮次兜底),全量 79 passed / ruff clean
|
2026-09-06 17:22:05 +08:00 |
|
Simon
|
0ea229d766
|
feat: Phase 4 — Experiment 自动归档 + 异步 Job(状态机 / SSE / 一键复跑)
- 数据表:job / experiment(spec/result JSON 存档、code_version),Alembic 迁移 53113c80257f
- Job:queued→running→(success|failed) 状态机,BackgroundTasks 本地执行 + 失败兜底标记;结果与 Experiment 关联
- Experiment:每次研究成功自动归档(含 git commit 与收益摘要),支持一键复跑(同 spec 重建 Job)
- API:POST /api/jobs、GET /api/jobs/{id}(内嵌结果)、SSE /api/jobs/{id}/events、/api/experiments 列表/详情/rerun
- 前端:新增「实验」页(列表 / 详情 / 复跑 + Job 轮询);导航更新
- 端到端验证:真实 20 股 job 提交→后台执行→success→EXP 归档(-12.41%);executor 成功/失败路径单测
- 测试 73 passed(新增 5 项 Job/Experiment)/ ruff clean / 前端 tsc + build 通过
|
2026-09-06 17:18:46 +08:00 |
|
Simon
|
92627f5b6b
|
feat: Phase 3 Web — 业务 API(stocks/factors/backtests)+ Next.js 前端
- 后端业务 API:GET /api/stocks(搜索/分页)、GET /api/factors(因子目录)、POST /api/factor-tests 与 /api/backtests(Research Spec 驱动同步执行)、GET /api/backtests/last;Annotated 依赖注入 + CORS(dev)
- Repository 批量查询 get_range_many(研究装配一次查询,避免逐只拉取)
- 前端 frontend/web:Next.js 15(TS) + ECharts —— 总览 / 股票池 / 因子研究(IC·RankIC·分层展示) / 回测(净值·回撤·月度·持仓·未建模标注)
- 前端只消费业务 API 与标准化 BacktestResult,无 Qlib/SQL 概念泄漏
- 真实数据:同步 20 只权重股 2023-2024 日线(9680 根)支撑截面研究
- 验证:API 集成测试 8 项(DTO 校验/装配/引擎/标准结果,内存 repo 全链路)+ 全量 pytest 68 passed;前端 tsc + next build 通过;无头浏览器端到端(factors/backtest 页面渲染后端数据)
- ruff clean
|
2026-09-06 17:14:33 +08:00 |
|
Simon
|
e9f59d3cf8
|
feat(backend): Phase 2 研究引擎 — ResearchSpec / 因子 / 评估 / 低频回测 / 引擎抽象
- domain:ResearchSpec(universe/factors/selection/rebalance/costs 校验)+ 标准化 BacktestResult / FactorTestReport
- 因子引擎:注册表 + 元数据,内置 9 个行情因子(momentum/volatility/量比/乖离/反转),支持自定义注册;只用行情字段规避未来函数
- 评估:横截面 IC / RankIC(rank+pearson 免 scipy)/ ICIR / 分层收益
- 回测:TopK 等权低频,无未来函数记账(t 收盘成交、自 t+1 计收益),成本/涨跌停/停牌约束,未建模项显式写入 unimplemented(AGENT §24)
- 引擎抽象 QuantEngine + LocalEngine(pandas 默认实现);qlib_adapter 桥接占位 —— pyqlib 无 aarch64+cp312 wheel(ROADMAP 已备注)
- 真实链路冒烟:600519 2024 月度动量回测闭环产出标准结果
- 测试 60 passed / ruff clean
|
2026-09-06 17:08:00 +08:00 |
|
Simon
|
2da234220a
|
feat(backend): Phase 1 数据层 — Domain / Provider / Failover 审计 + 持久化 + 同步 CLI
- domain:市场数据实体(Stock / 交易日历 / 日线 / 复权 / 财务含 announce_date)+ Repository 与 MarketDataProvider Protocol
- 数据源:TushareProvider(归一化、重试、鉴权错误归类)、SinaProvider(备用,明确前复权口径与能力边界)、FailoverProvider + SyncLog 审计(禁止静默切换)
- 持久化:SQLAlchemy 2.x Models + Repository 实现(按业务键幂等 upsert、as_of_date 防未来函数过滤)+ Alembic 迁移
- CLI:uv run python -m app.cli.sync {basic|calendar|daily|financial|verify},支持 --resume 断点续传
- 真实 Tushare 验证:stock 5556 / 交易日历 366 / daily+factor 242 / 财务 55;sync_log 审计完整
- 测试:38 passed(domain / provider / failover / repository / 未来函数 / 迁移),ruff clean
|
2026-09-06 16:59:28 +08:00 |
|
Simon
|
7a89d97c0b
|
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)无溢出
|
2026-09-06 16:27:16 +08:00 |
|
Simon
|
2a52ee5e83
|
feat(backend): 搭建 FastAPI 分层骨架 — 配置加载 / 健康检查 / SQLAlchemy+Alembic 就位
- uv 工程(Python 3.12,pyproject + uv.lock,dev: pytest/ruff)
- 分层包结构:api / application / domain / infrastructure / quant(qlib_adapter) / agent / core
- app.core.config:加载根 config.yaml + .env,sqlite 相对路径解析到项目根 data/
- SQLAlchemy Base + Session 工厂(Infrastructure 层,业务走 Repository)
- Alembic 迁移环境就位(env.py 复用应用配置,render_as_batch 兼容 SQLite)
- GET /api/health + pytest 冒烟 6 项通过 / ruff clean / uvicorn 启动验证
|
2026-09-06 16:09:10 +08:00 |
|
Simon
|
8eb3b4ac2a
|
chore: 项目初始化 — 工程文档、配置与目录骨架
- AGENT.md / docs/ARCHITECTURE.md 约束与架构文档入库(README 覆盖远端模板)
- 根级配置:.gitignore / .env.example / config.yaml(密钥只走 .env,不入库)
- 目录占位:data(parquet/qlib/raw/normalized) / experiments / docker / frontend/web / scripts
|
2026-09-06 16:09:07 +08:00 |
|