Simon
|
861a4051ca
|
feat(job): D2 全市场选股 Job 化(kind=selection 异步)
- Job kind=selection:executor 分支用 SelectionService(spec=SelectionQuery),结果
落 result_json、自动归档 Experiment(summary:as_of + 选出 N);/api/jobs 与
/api/experiments 的 result 解码支持 SelectionResult
- POST /api/selections/jobs:提交 SelectionQuery 为异步 Job(BackgroundTasks/subprocess)
- Web 选股页新增「异步(全市场)」按钮:提交 Job → waitJob 轮询结果(解决同步 60s+)
- tests/test_selection_job.py:executor 执行归档(SelectionResult/Experiment kind)、
API 提交→轮询→结果与实验列表;全量 pytest + tsc 通过
|
2026-09-09 07:43:35 +08:00 |
|
Simon
|
7c268e43df
|
feat(job): D1 Job 阶段上报(v3 §23)+ 列表/取消端点
- ResearchService.run_backtest/run_factor_test 支持 on_stage 回调(data_loading →
factor_calculation/backtesting → analysis);job_executor 经独立短会话把 stage 写库
(子进程模式同样走 DB),收尾回读最后阶段避免覆盖
- /api/jobs:GET 列表(kind/limit)、POST /{id}/cancel(queued/running → CANCELLED +
终止子进程 terminate_active;父进程兜底已跳过 CANCELLED)
- SSE /jobs/{id}/events 现会携带 stage
- tests/test_job_stages.py:成功 job 终态 stage=analysis;executor 取消 queued/幂等/
已完成不可取消;API 列表+终态不可取消+404;全量 pytest 通过
|
2026-09-09 07:37:25 +08:00 |
|
Simon
|
0d05bfd187
|
feat(factor): C1 因子相关性分析(横截面 Spearman 矩阵 + API)
- evaluation.factor_correlation_report:多因子共同日期 ∩ 后逐日横截面 Spearman 相关
取均值 → FactorCorrelationReport(冗余剔除前置,v3 §12 Correlation→Redundancy)
- ResearchService.run_factor_correlation + POST /api/factor-correlations
(universe/factors/period;与其它研究同装配口径)
- tests/test_factor_correlation.py:矩阵对角=1/近线性±相关符号/对称/无共同日期补零、
API 冒烟;全量 pytest 通过
|
2026-09-09 07:31:49 +08:00 |
|
Simon
|
9cc4bfccac
|
feat(universe): B1-1 指数历史成分(index_weight)+ Universe 按 as_of 成分过滤
- index_weight 表(migration f5e0d1c2b3a4,MySQL 已应用;index_code+date+symbol 唯一)
+ IndexWeight 实体 + IndexConstituentRepository(members_at:取 <=as_of 最近一期快照,
Survivorship-free / 无未来成分;latest_date)
- UniverseSpec.index_code + universe.filter_stocks members 交集 + resolve_members;
Research/Selection/Signal/Replay 服务注入 index repo(历史成分过滤,选股/回测共用)
- tests/test_index_universe.py:快照历史成分(成分变更不入早期结果)、幂等、
空快照期空集、index_code 过滤下 as_of 一致性;全量 pytest 通过
|
2026-09-09 07:27:13 +08:00 |
|
Simon
|
37510c1b89
|
feat(replay): M9-6 Bar Replay 线性重放(as_of 逐日仅用当时数据)
- domain/entities/replay.py:ReplayDay{top/events/counts}/ReplayResult 时间线
- ReplayService:universe.symbols 白名单必填(≤40)且重放交易日 ≤90(防全市场长任务);
每个交易日以 <=as_of 数据经同一 signal/score 引擎生成帧
- POST /api/replays(边界校验)→ 时间线;供前端 Bar Replay 控件(v3 §20.6 阶段二)
- tests/test_replays.py:重放帧 == 回测 selection_history 逐调仓日一致;范围约束;
后段暴涨股不泄漏进早段帧(未来函数);API 400/200;全量 pytest 通过
|
2026-09-09 07:18:36 +08:00 |
|
Simon
|
995ed08548
|
feat(chart): M9-1 Chart DTO + Chart Service + Chart API(v3 §20)
- domain/entities/chart.py:ChartResult/OHLC/Volume/Series/EventMarker/ChartMetadata
(adjust_mode + execution_price_basis 口径元数据)+ SelectionHit
- application/services/chart_service.py:个股 K线/量/MA 指标;显示层 qfq/hfq 折算
(基于主口径 none 行情 × adjust_factor,绝回写研究数据);回测个股视图把实际成交
转 fills 标记并在显示口径不同时做坐标换算(v3 §20.3/§20.5)
- by-symbol 历史查询:SignalRepository/SelectionRepository.list_by_symbol(含溯源 id)
- api/charts.py:/stocks/{symbol}/chart|signals|selections、/backtests/{id}/stocks/{symbol}/chart
|trades|positions
- tests/test_charts.py(指标/qfq-hfq 折算断言/回测 fills/API 集成+404);全量 pytest 通过
|
2026-09-09 07:09:52 +08:00 |
|
Simon
|
9d25d466e5
|
feat(strategy): M8.3 策略模型 + /api/strategies(命名配置资产,可展开为 ResearchSpec)
- StrategyDefinition:universe/factors/selection/rebalance/costs/portfolio +
price_adjustment(除 period 外完整策略定义);to_research_spec(period) 展开为标准 Spec
- strategy 表(migration e1f2a3b4c5d6,MySQL 已应用;name 唯一)+ StrategyRepository
- /api/strategies:POST/GET/DELETE + POST /{id}/expand(period+initial_capital → ResearchSpec)
- tests/test_strategies.py(repo CRUD/同名/expand、API CRUD/400/404);全量 pytest 通过
|
2026-09-09 00:38:09 +08:00 |
|
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
|
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
|
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
|
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
|
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
|
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
|
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
|
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 |
|