claude_dev
|
e91b103f7a
|
docs(data): Phase2 归档旧回填/import链+15m灌库链(VPS schtask实证线头死)
VPS schtasks /query: 调用这些脚本的 schtask 全已禁用(baostock_day1/2,
xtdata-build, index-hist, bs-daily-increment 等),且不被8个活跃wrapper引用。
活跃白名单(保留): bs_eod/xt_eod/sina_index_eod/akshare_static_download/
index_const_hist_download/merge_constituent/migrate_constituent/parse_csindex_announce
- _archive/backfill_legacy/: 31个(旧回填import链+旧baostock下载+禁用wrapper+Mac .sh链)
- _archive/backfill_15m/: 7个(15min灌库链+hardening测试,backfill已完成)
- 关键实证: index_const_hist_download 被 index_monthly_wrapper(活跃)调用→保留不归档
- 无残留import(fetch_with_fallback是sanguo_data函数非fallback模块)
|
2026-07-29 11:56:44 +08:00 |
|
claude_dev
|
c3e53fbef3
|
docs(data): 归档数据层验证产物 + 数据层总览README
- scripts/data_platform/_archive/legacy/: 归档20个独立探针/诊断/旧降级脚本(零引用验证)
- docs/archive/data/: 归档17个数据相关旧设计/plan/report(保留fusion spec作深读)
- docs/data-platform/README.md: 数据层单一权威记录(8节:架构/布局/源/管线/铁律/API/缺口/待办)
- 删除 _mootdx_depth_result.txt
- Phase2待办: 15m灌库链+旧回填import链(有测试/wrapper依赖,VPS schtask确认后归档)
|
2026-07-29 10:11:38 +08:00 |
|
claude_dev
|
1cc9126abb
|
feat(portfolio): get_limit_status_batch 回测涨跌停/停牌批量接口
修 filter_limitup/limitdown/paused 回测失效(get_current_tick 无 last_price/paused
字段→恒不过滤→03/02 回测算出假收益)。
get_limit_status_batch(codes, date) → {code: {is_limit_up,is_limit_down,is_paused}|None}:
- dbbardata 无 high_limit 列 → high_limit=round(prev_close×(1+幅度),2) 精确算
(pctChg 阈值高价股边界失真故不用); 窗口 ROW_NUMBER 取 T+T-1 两根日线。
- 幅度板块感知: 主板10/创业·科创20/北交30 + 历史 ST5%(valuation_baostock.isST)。
- 停牌=当日 volume==0; 方案A(返回判断好的状态); 缺失股 None。
Mac TDD 6 用例(涨停/跌停/停牌/创业板20%/正常/缺失)全绿; 45 回归通过。
策略层 filter 接入归策略 session(替 get_current_tick 逐只)。
|
2026-07-29 09:10:20 +08:00 |
|
claude_dev
|
d2cd8fa945
|
feat(portfolio): get_security_info_batch + get_value_metrics_batch 批量接口
策略层提速第三轮(filters 通病 + 策略01):
- get_security_info_batch: 2 条 SQL(symbol IN chunk + GROUP BY sym,exc 拿
min/max; constituent_unified 拿 name)替 N×2 逐只。filters.py filter_st_stock/
filter_new_stock 自动探测批量(hasattr + isinstance dict 回退逐只, 向后兼容)。
三策略 ST/次新过滤通病: 万次查询压成 2 条。
- get_value_metrics_batch: ThreadPool 并发逐只委托 lpp.get_value_metrics
(多期 ROE/FCF/流动比率逻辑不变, 只并发)。策略01 价值精选提速。
- 接口3 get_ticks_batch 不做: 实证 get_current_tick 无 last_price/paused 字段
→ 回测涨跌停/停牌 filter 恒不过滤(死代码), 批量化无意义; 真问题是回测
涨跌停检测失效(策略层另修)。
Mac TDD parity 测试全绿(batch==逐只); 93 回归通过。
|
2026-07-29 08:23:21 +08:00 |
|
claude_dev
|
32dbcb8958
|
feat(portfolio): P2/P3 策略层向量化 + fundamentals批量提速解锁长回测
P2 行情向量化(get_price→get_closes_panel,口径实证 max_abs_diff=0.0 零偏差):
- momentum_timing: _cal_rps/_select_stocks/_cal_buy_sign 三处向量化
- small_cap: _cal_momentum_score 用 close.min/max 代理 low/high(方案A)
P3 fundamentals 批量(small_cap _pick_stocks 加 fields=[market_cap,eps],
对接数据session f416a17 get_fundamentals_df 按需短路):
- 02 000985 全市场 5128只 ~19min卡死 → 195s 跑通解锁
验收: 72单测全过; VPS 03短回测+138%(口径与get_price一致diff=0)/
02全市场-11%(2024Q1小盘股灾期合理)/01沪深300可跑
|
2026-07-29 07:49:35 +08:00 |
|
claude_dev
|
f416a17b6d
|
feat(portfolio): get_fundamentals_df 批量提速(fields= 按需短路 + ThreadPool 并发)
策略02 _pick_stocks 对 5128 只按 market_cap+eps 排序, 旧实现逐只读 4 表(valuation+
income+balance+financial_abstract)+算 calc_roic, 首仓全 cache miss 卡死。
优化(就地, 策略代码零改动, fields=None 向后兼容):
- fields= 参数: 只读请求字段依赖的源表(策略02 只要 market_cap+eps → 跳 balance/
financial_abstract/roic, 省一半 parquet 读)
- ThreadPool 并发逐只(>64 只; 本地文件 I/O 非 baostock 网络, 不触不并发铁律)
- _build_fundamental_row 加 need= 守卫读取(lpp + unified 两层)
Mac TDD 4 测试(子集/短路/回归/并发保序)全绿, 124 回归通过。
注: 策略02 要拿满提速需在其 get_fundamentals_df 调用加 fields=[market_cap,eps](策略层, 归策略session)
|
2026-07-28 23:31:13 +08:00 |
|
claude_dev
|
e7f9426bcd
|
feat(data): get_closes_panel 生产化(qfq 前复权 + UNION ALL 340x 提速 + chunk) + 000938 行情
G5-P1 接口生产化(本地已建 c8f26be 但未部署 VPS — 策略 session 报缺失的根因):
- fq 参数(raw/qfq/前复权, 默认 raw 向后兼容): 批量前复权用单次 WHERE code IN (...) 查
bs_adjust_factor + merge_asof 向量化 asof, 对齐聚宽默认前复权(RPS/均线/动量跨期必需)。
- 性能修复: 原 (symbol=? AND exchange=?) OR 大链打不动复合索引 -> SQLite 全表扫(5只10.6s);
改 UNION ALL per symbol 走 (sym,exc,interval,datetime) 索引 SEEK(5只0.03s, 340x)。
- chunk=400 抗大体量(参数<999 版本安全); interval/start/end regex 校验字面量注入。
- 部署 VPS。实测 5128只(000985) raw 68s / qfq 33s(逐只会卡死); 200只 qfq 0.9s。
qfq 与 get_price(fq=qfq) max_diff=0.00; 22 测试 0 回归。
P2 000938: sina_index_eod CODES 加 000938 -> 腾讯灌 1591 行点位(1395~2884, 非基金净值);
腾讯对该码停 2023-02-17(数据源限, 非代码问题)。
解锁: 策略02(000985 5128只选股) + 策略03 长期回测; 策略层 pandas 向量化(P2)归策略 session。
|
2026-07-28 23:03:32 +08:00 |
|
claude_dev
|
de04a8904b
|
feat(portfolio): 移植3聚宽策略到BulletTrade + 8bug修正 + 数据缺口文档
三策略(聚宽py2→BulletTrade 0.9.2,BrokerFacade注入跨版本兼容):
- momentum_timing 动量择时(牛熊分界+行业RPS+均线,切回10中证行业指数)
- value_selection 价值精选(6条基本面过滤,切回沪深300)
- small_cap 小市值(去IC对冲,切回000985中证全指)
框架:
- runner_backtest 加 --strategy 分发(原硬编码all_weather)
- provider 加 get_value_metrics(价值精选6条基本面,NOTICE_DATE治前视偏差)
- 72单测全过(21+27+24)
修8个回测实测发现的真bug:
- 01第⑥条EPS绝对值0.08~0.5与①大盘矛盾→6条交集恒空致全程空仓,按注释本意改净利润同比8~50%
- 03原帖calRPS取数区间错(get_price start=end只取1天)→涨跌幅恒0 RPS失效;date.today()取真实今天非回测日
- 02 universe 000985不在constituent_unified→候选池空
VPS实测(短区间验证逻辑,非长期表现): 01价值+23%/03行业轮动+48%/02选出20只小盘
数据缺口(详见docs/research/joinquant_strategies/SUMMARY.md + data_gaps_fix_plan.md):
- 三表"1/3损坏"误报已撤回(全扫5530文件/表0损坏,沪深95%+健康,仅北交所920xxx空,不做北交所)
- 真实缺口: 行业成份股(G1已补)/000985(G2已补)/IC期货(02对冲去掉)/provider批量接口(G5待做,解锁长回测)
|
2026-07-28 22:20:49 +08:00 |
|
claude_dev
|
e4f6416765
|
feat(data): 行业指数治偏差 content HTML 解析(was_removed 8->99)
parse_csindex_announce 加 parse_content_adjustments: 公告无 PDF/xlsx 附件时 fallback
解析 HTML content 嵌入文字表格(1208 公告 2009 中证行业调整名单, 10 行业各一表)。共享
_extract_section_records 给 PDF/content 两路, 非破坏(1000/2000 PDF 路径不变; 实测 000852
was_removed=672 / 000905=1303 等宽基未变)。process_notice 附件空时 fallback content;
SHARED_NOTICES_BY_INDEX 补 1208->全 10 行业(csindex API indexCode 漏绑 000936)。
结果: constituent_unified 行业指数 was_removed 8->99(000928-937 全 >0)。
局限: 仅覆盖 2009 那次 + 零星 2016-2022 临时调整; 2010-2025 半年度定期调整 csindex 公告
系统无完整存档, 需 wind/choice/官网另补(本脚本范围外)。
|
2026-07-28 22:15:19 +08:00 |
|
claude_dev
|
66a2c9e9ce
|
feat(data): 中证指数日线点位修股票/指数同名碰撞 + 行业治偏差 section 名校正/增量接线
行情(修碰撞): 新 sina_index_eod.py 拉 14 中证指数日线点位(000016/300/852/905/985/000928-937)
入 dbbardata exchange=SSE, 与 SZSE 同名股票分离(provider .XSHG→SSE 零改动命中)。sina 主源 +
腾讯兜底 5 个 sina 停 2016 的(000929/930/936/937/985); 东财两端点持续封 VPS。schtask sanguo-idx-eod
18:30 增量(busy_timeout 60s 防 bs_eod 撞锁)。策略03 行业 mavg30 不再读个股股价。
治偏差(行业): INDEX_SECTION_MAP section 名校正(中证800能源->中证能源等, 1208 公告 content 实证);
index_monthly_wrapper STEP0b 接进 --indices 000928-937 月度增量(闭合 G1+G2 一次性未接增量缺口)。
注: 宽基治偏差(000852/000905/000016 等)早已完成(prior b237c2d); 行业指数 csindex 无 PDF 调整
公告(数据埋 HTML content), was_removed 仍~0, content 解析待专项。
|
2026-07-28 21:54:46 +08:00 |
|
claude_dev
|
c8f26bef80
|
feat(portfolio): LocalUnifiedProvider 批量行情接口 get_closes_panel (G5-Phase1)
单条 dbbardata 参数化查询 (symbol,exchange) OR + pivot 返宽表, 替代 N 次 get_price, 为策略向量化提速铺路。raw close 口径一致, 缺失 NaN 列, symbol-exchange 配对防歧义。22 tests 含 batch-vs-逐只回归。本文件另含 get_value_metrics 透传(策略移植)。
|
2026-07-28 20:36:11 +08:00 |
|
claude_dev
|
853d35197e
|
feat(data): 补 000985 中证全指 + 中证800十行业成份股入 constituent_unified (G1+G2)
治幸存者偏差全集: 000985=5128 全市场(解锁策略02小市值全市场池) + 000928~000937 中证800十行业 24~196只(解锁策略03行业轮动)。复用+泛化 000852/932000 csindex 公告回溯流程, 不动硬编码路径。9 宽基无回归, was_removed 治偏差填齐, 全表 14402 行/20 指数。
|
2026-07-28 20:36:11 +08:00 |
|
claude_dev
|
670498ab01
|
fix(data): akshare 三表下载鲁棒性 — 原子写 + --repair (G4)
write_parquet_and_marker 改原子写(tmp→os.replace→marker) kill 不产残缺 parquet; 新增 --repair 只重取 missing/empty/corrupt 忽略 marker(周度补漏不必等财报季 --force 全量); is_parquet_healthy 辅助。top_holders 修复无回归, 106 tests。
|
2026-07-28 20:36:11 +08:00 |
|
claude_dev
|
f94a145587
|
fix(data): bs_eod 卡死根治 — per-stock commit + baostock 超时包装 + 周期 relogin
根因(py-spy dump + netstat CLOSE_WAIT 实证): baostock 服务端关长连接→CLOSE_WAIT, send_msg 静默阻塞不抛异常, socket.setdefaulttimeout 不被 baostock 自己 socket 遵守, relogin 只在 error_code≠0 救不了; 一把大事务全程持 WAL 锁阻断全库。修复: per-stock commit 去大事务 + _with_timeout 线程超时包 fetch_k 打破静默 hang + 周期 relogin 每500主动刷连接。VPS --limit 3 验证 11s 不 hang。
|
2026-07-28 20:36:11 +08:00 |
|
claude_dev
|
955c05357a
|
fix(data): ak-stock top_holders KeyError 'sdltgd' 根治(_safe 捕 KeyError+匹配sdltgd,跳北交所920/83/87/43)
|
2026-07-27 21:08:53 +08:00 |
|
claude_dev
|
8b2693423a
|
feat(data): xt_eod 扩展补全北交所 920xxx 日线(exc_of+universe+import容错,复用×100 normalize)
- exc_of: 920 -> BJSE (3 位前缀优先于 2 位 SSE/SZSE 判断, 防 sym[:2]='92' 落 SZSE)
- universe: 沪深ETF/基金 ∪ 北交所920xxx (从 constituent_unified 932000 取, baostock 不覆盖)
- import xtquant 容错 (mac xd=None 可单测 exc_of, main() 开头 return 2)
- --full-bj: 北交所 backfill start=20240101 (默认 LOOKBACK=30 与 ETF 同窗)
- 复用 normalize_daily_dt + ×100 volume 口径, 不动已有 ETF 写入路径
Tests: tests/data_platform/test_xt_eod_bj.py 14 cases RED -> GREEN (3 位前缀 critical + ETF/沪深/深市 覆盖)
|
2026-07-27 20:56:16 +08:00 |
|
claude_dev
|
11f383a8e2
|
fix(data): akshare top_holders Length mismatch bug 根治
bug 根因 (实证 akshare 1.18.x stock_gdfx_em.py:418):
报告期未披露 (如 sz002673 的 20260630 在 2026-07-26 还未发) 时,
东财 PageSDLTGD 接口返 sdltgd=[], akshare pd.DataFrame([])+reset_index()
得 1 列 df, 然后 columns=[12 列] 抛
ValueError('Length mismatch: Expected axis has 1 elements, new values have 12')
这是确定性无数据 (非瞬时故障), 但 call_ak_with_retry 当网络错重试 3 次
(14s 退避) + 噪声 ERROR 日志, 浪费时间且消耗断路器配额。
修复:
新增 _safe_top_10_em 包装 ak.stock_gdfx_free_top_10_em: 子串匹配
'Length mismatch' (pandas 错误信息稳定) → 返空 df 带 8 列 schema
(TOP_HOLDERS_COLUMNS), 不抛; 其他 ValueError/ConnectionError 透传重试。
fetch_top_holders_one_period 改调此包装。
验证:
- Mac: sz002673/20260630 从 ~14s (3 重试) 降到 0.04s, 返 0×8 空 df
- 有效期 sz002673/20251231, sh600519/20250930 正常返 10×8 数据
- 9/9 新单测通过 (tests/data_platform/test_top_holders_parse.py)
|
2026-07-26 11:54:19 +08:00 |
|
claude_dev
|
b06af336c3
|
fix(data): bs_eod 15min datetime 格式 bug 根治 + --no-daily 选项
bug 根因(2026-07-25): baostock 15min 实测 date='2026-07-21'(带 -),
time='20260721094500000'(17 位 YYYYMMDDHHMMSSmmm)。原代码假设 date 纯数字 +
time[:6] 取年月, 产乱 datetime 致 dbbardata 15min 全市场停 2026-07-17(8 天
没正确累积), 日线正常(7-24)。
修复:
- 提纯函数 _build_15m_dt(date_series, time_series): date 直连 + 从 17 位 time
第 8-12 位提取 HHMM, 产出 'YYYY-MM-DD HH:MM:00' (符合 GLOB 清理模式)
- upsert_15m 调用 _build_15m_dt 替代内联拼接
- 新增 --no-daily 选项(只跑 15min, 用于重灌快), 与 --no-15m 对称
- TDD: 8 case 覆盖(09:45/14:30/15:00/13:00/跨日/多行混合/GLOB 格式)
- conftest.py 修补 sibling import 在 pytest 下可用
|
2026-07-25 21:14:12 +08:00 |
|
claude_dev
|
e807bed09c
|
fix(portfolio): all_weather 小盘池码 + fq 口径 + stop_loss 日志
- all_weather:
- s_stocks 399101.XSHE → 000852.XSHG(中证1000)。旧码在 constituent_unified
无数据,分支C(小盘轮动)完全 dead(S_mean 恒 0)= 业绩差主因。
- stop_loss -8% logger.debug → info(原 INFO 不可见,无法验收该分支)。
- big/bm/small 阈值验证用放宽(适配年报口径+中证1000,最终业务决策再说):
small roe>0.15&roa>0.10 → roe>0.05&roa>0.02(原 roa>0.10 命中仅~5%)。
- runner_backtest: build_broker_facade_inner 注入 set_option 委托 bullet_trade
settings + initialize 顺序改(先注入 broker 再 initialize)。修 fq 口径不一致
(engine fq_mode=none raw vs get_current_data fq=pre)致大盘市价保护价<当前价不成交。
修后 all_weather 2022-2024 全量验证(726交易日,max-pool 50):
总收益 0.82%→15.48%,夏普 -0.16→+0.04,回撤 -27%→-23%。
全分支跑通:月度调仓36 / 分支A无敌行情2月 / 分支C小盘活了(末日全仓小盘) /
stop_loss -8% 触发111次。
|
2026-07-24 11:27:25 +08:00 |
|
claude_dev
|
0ef0cadaff
|
fix(portfolio): provider 基本面前视偏差修复 + ETF paused + roic 接入
- local_parquet_provider: 新增 _latest_published_annual(NOTICE_DATE<=date +
年报口径),替旧 _latest_row_before(REPORT_DATE)。修复两个 bug:
1) 前视偏差:旧按报告期过滤会用未披露年报(如 3/31 取上年报,4 月才披露);
2) 周期错配:income/balance 各自取最新致 NP(年)÷权益(季)垃圾值。
income/balance 统一走该 helper → 同报告期 + 无前视。
另:roic 接 calc_roic,_num(v==v)排 NaN 修 g() 对 NaN truthy 问题。
- local_unified_provider: get_price 缺失字段 paused 补 False / high·low_limit
按 close±10% 估,修 bool(NaN)=True 被 bullet_trade get_current_data 误判
停牌致 _process_orders cancel 所有 ETF 订单(0 交易)。
实证:roe/roa 跨时点一致(p50 从 0.016/0.064 不一致 → 0.074/0.070/0.065)。
|
2026-07-24 11:26:56 +08:00 |
|
claude_dev
|
e7465c342f
|
feat(data): 中证1000/2000 定期更新 schtask + schtask 路径坑修复
sanguo-index 增强: index_monthly_wrapper 加 STEP0 parse_csindex_announce
(治偏差全集, 月度16号自动刷新 constituent_unified)
register_akshare_schtasks 修 PowerShell schtasks /tr 反斜杠路径丢前缀坑:
$ws 变量在双引号被原生命令解析吃掉 -> Arguments 存成 \xxx.ps1 ->
schtasks /run 返回成功但 wrapper 静默不跑从不写日志。改全路径硬编码 + --%。
ak-* 5 schtask 路径全坏已批量修(register_akshare 旧版"已部署Ready"是假成功)。
诊断: Get-ScheduledTask 中文Win报 0x80070057 无用, 改 schtasks /query /xml
看 Arguments 才发现丢前缀。
schtask 全链路验证 STEP0-3 exit=0, constituent_unified
000852=1672(was_removed=672) / 932000=2684(684) 治偏差保持。
|
2026-07-24 00:20:36 +08:00 |
|
claude_dev
|
d5582fd6f2
|
fix(migrate): deep glob 排除 *_announce_union.parquet(不同 schema)
deep union 段 glob '*_union.parquet' 误匹配 000852_announce_union.parquet/
932000_announce_union.parquet, 它们无 in_current/was_removed 列(用 adjust_type)
-> KeyError 崩溃。显式 skip _announce_union.parquet 文件。
VPS 验证通过:
- 000852: 1672 rows (in_current=1000, was_removed=672)
- 932000: 2684 rows (in_current=2000, was_removed=684)
- 000300/000905/000016/399001 行数不变(回归 OK)
|
2026-07-23 23:50:03 +08:00 |
|
claude_dev
|
b237c2d7e7
|
fix(data): 中证1000/2000 历史成份股补全(parse+migrate 聚合)
parse_csindex_announce.py 3 处修复:
- 932000 launch xlsx header 定位"证券代码"列(原 row[0]=指数代码 bug, distinct=1)
- 000852 列表搜索用 indexCode payload 精准拉(28 -> 96 公告, 回溯到 2016)
- akshare current snapshot header 定位"成分券代码"列(原 iloc[0]=日期 bug, current=0)
migrate_constituent.py:
- 加 _read_announce_union_aggregated(): 000852/932000 用 announce_union 全集
替换原 snapshot-only 路径, was_removed 治幸存者偏差
- 缺 announce_union 时回退旧 snapshot 逻辑(向后兼容)
TDD: tests/portfolio/test_migrate_announce_union.py 7 测全过(5 unit + 2 integration)
Mac 产出验证:
- 000852: distinct 1220 -> 1672, was_removed 0 -> 672
- 932000: distinct 1 -> 2684(launch 修复), was_removed 0 -> 684
|
2026-07-23 23:45:55 +08:00 |
|
claude_dev
|
114a69e997
|
fix(data): dbbardata 日线双行根治(统一纯日期+helper,留ROWID max去重)
根因: dbbardata UNIQUE(symbol,exchange,interval,datetime) 按字符串字面比较,
多写入路径混用 'YYYY-MM-DD' 与 'YYYY-MM-DD 00:00:00' -> 同一交易日双行,
INSERT OR REPLACE 不去重 -> 回测交易日翻倍/pivot duplicate/信号异常。
方案A (统一纯日期, 详见 Main Agent 诊断):
- 新增 scripts/data_platform/dbbardata_utils.py: normalize_daily_dt(s)
取前 10 字符, None/短串安全
- 4 个日线写入脚本写入前调 helper:
- bs_eod.py (sanguo-bs-eod 个股日线 baostock)
- migrate_daily_baostock.py (历史迁移)
- xt_eod.py (sanguo-xt-eod ETF/基金 xtata)
- import_vnpy_daily_fast.py (NAS 日线 parquet 导入, 加防御)
- TDD: tests/data_platform/test_dbbardata_utils.py 9 cases 全过
- 回归: tests/data_platform + tests/portfolio 199 passed 12 skipped
peewee DateTimeField formats 含 '%Y-%m-%d' (阶段0 VPS 实测确认),
读纯日期不崩, 方案A 前提成立。
15min 干净, 不动 (分钟必须带时分)。只改日线 interval='d'。
数据层根治, 不在 provider 适配兜底 (用户铁律)。
|
2026-07-23 12:18:41 +08:00 |
|
claude_dev
|
4c2af8ff00
|
fix(data): verify_akshare_e2e 修正事件类路径(data/static/<type> 非 events/)
akshare_static_download 全类型(含 per-date 龙虎榜/大宗/两融/解禁 + per-period 预告/快报)
都落 data/static/<type>/, 非 data/events/; 合并为单一 static 检查(13 类型)
|
2026-07-23 09:06:00 +08:00 |
|
claude_dev
|
28d1606947
|
feat(data): akshare 低频 5 schtask wrapper+register+verify(spec §14.5 A+B/C)
5 wrapper(ak_eod daily19:00估值+财务摘要/ak_quarter财报季三表+预告快报/
ak_events daily19:30龙虎榜+大宗+两融+解禁 per-date当日/ak_stock weekly周六
北向+股本+十大股东/index_monthly 16号成份股3源+migrate+merge)+register_akshare
_schtasks(/m APR,MAY,SEP,NOV财报季)+verify_akshare_e2e; 均unset proxy+夜间避封IP
|
2026-07-23 09:04:01 +08:00 |
|
claude_dev
|
48c67d05d2
|
fix(data): 成份股 merge/migrate pipeline 可重跑(idempotent, 读 bs_index_constituent_old)
|
2026-07-23 09:04:00 +08:00 |
|
claude_dev
|
ae3a768091
|
docs(data): akshare 低频 schtask plan(spec §14.5 A+B+C)
spec §14.5 akshare/index 低频 schtask 部署 plan, 待 compact 后新 session 执行:
- A 三表/估值增量(sanguo-ak-eod 日频 + ak-quarter 季频, --force 全量夜间慢跑)
- B 成份股月度(sanguo-index, 改 merge_constituent 可重跑 DROP/REPLACE + 3源wrapper + TDD)
- C 事件类 7 种(ak-events per-date 日频 + ak-stock per-stock 周频)
实测现状: static 停 7/22 18:25(provider依赖) / events 全空(从未采集) /
constituent_unified 7110 静态 / 旧 schtask 全无(方案A stop_all 清了)
关键约束: akshare marker symbol级→三表/估值必须--force更新 / per-stock全量慢+东财限流→夜间 /
merge_constituent RENAME不可重跑→改幂等
plan 自包含(fresh agent 可执行), 关联 memory akshare-low-freq-plan
|
2026-07-23 08:49:56 +08:00 |
|
claude_dev
|
41cc6d13bf
|
feat(portfolio): LocalUnifiedProvider spec §6 使用层落地 + VPS E2E(Task6)
spec §6 使用层 provider — 读方案A 权威数据层, 零 online, 治幸存者偏差:
- get_price: dbbardata('d') raw + bs_adjust_factor 前复权(asof, qfq[t]=raw[t]*factor[t])
- get_index_stocks/get_constituent: constituent_unified 并集治偏差(300=940含被踢, 无date时点)
- get_fundamentals_df: baostock pe/pb/ps/pcf + akshare 市值 + 三表委托 LocalParquetProvider
- 辅助: trade_days/security_info/current_tick/split_dividend/all_securities
VPS E2E 实证修复(Mac fixture 盲区):
- dbbardata datetime 混合格式("2024-09-26" vs "2024-09-26 00:00:00")
→ pd.to_datetime format='mixed' + SQL substr(datetime,1,10) 比日期(字符串比漏边界)
- 补 TestMixedDatetimeFormat 单测覆盖
验证: VPS 真数据 E2E 全通过(600519在市raw/qfq复权/000005退市治偏差/510300ETF/
fundamentals市值+pe+eps全字段/辅助方法); Mac 37单测+149回归绿
交付: 使用说明 docs/portfolio_local_unified_provider.md(其他 session 直用)+
plan+probe+E2E 脚本
|
2026-07-23 08:25:44 +08:00 |
|
claude_dev
|
b89eb0f941
|
feat(portfolio): 接线 LocalUnifiedProvider 到 runner(Task5)
|
2026-07-23 08:13:32 +08:00 |
|
claude_dev
|
9243f86773
|
feat(portfolio): LocalUnifiedProvider 辅助方法(Task4)
|
2026-07-23 08:12:34 +08:00 |
|
claude_dev
|
011c9d4ddb
|
feat(portfolio): LocalUnifiedProvider fundamentals baostock估值+akshare市值(Task3)
|
2026-07-23 08:11:35 +08:00 |
|
claude_dev
|
b46a0c26c8
|
feat(portfolio): LocalUnifiedProvider 成份股并集治偏差(Task2)
|
2026-07-23 08:07:37 +08:00 |
|
claude_dev
|
4b4dca2f44
|
feat(portfolio): LocalUnifiedProvider get_price+前复权(Task1)
|
2026-07-23 08:06:45 +08:00 |
|
claude_dev
|
e12c66acd5
|
feat(portfolio): LocalUnifiedProvider 代码转换+复权因子(Task0)
|
2026-07-23 08:05:09 +08:00 |
|
claude_dev
|
c2a89d01a4
|
feat(data): 方案A 数据层落地(spec §14)— DB唯一表+治幸存者偏差+权威源
spec §14 方案A 数据层迁移完成 + E2E 验证(read_db_daily: 在市/退市治偏差/ETF 全OK):
- dbbardata('d') 1826万含退市(治回测幸存者偏差, INSERT OR REPLACE staging迁移, WHERE OHLC NOT NULL+COALESCE)
- constituent_unified 7110行/9指数(300/500/50 baostock全集 + 深证4指 akshare cni union + 中证1000/2000 snapshot)
- pe/pb 不进DB -> valuation_baostock/<year>.parquet 按年宽表(2003-2026)
- 废弃 daily_baostock_full/bs_index_constituent(rename _old 保留); 旧4 schtask disabled
- 新 schtask sanguo-bs-eod 18:05(baostock个股日线+15min+拆pe/pb DAILY_LIMIT 48000) + sanguo-xt-eod 18:40(ETF/基金xtata)
- 权威源: baostock个股日线+估值+15min+复权+300/500/50 / xtata ETF+基金+当天实时 / akshare三表+事件+深证中证成份股
- 全程备份+staging+_old保留可回滚; 脚本 audit/probe/migrate/merge/cleanup/fix_config/verify/bs_eod/xt_eod/wrapper/register_schtasks
- 待办(spec §6 使用层): LocalParquetProvider 接 constituent_unified+valuation_baostock + 实时拼接
|
2026-07-23 07:20:34 +08:00 |
|
claude_dev
|
b270faf4b9
|
feat(portfolio): 本地数据 provider 层(baostock/local_parquet)
- BaostockProvider: 读 VPS daily_baostock_full(本地,不调online,守 provider-local-data-only 铁律)
- LocalParquetProvider: 读 parquet 兜底,回测117交易日0.4s/月出JSON
- all_weather 策略 + runner_backtest 适配
- 数据源融合使用层(单 Provider 内部路由,见 data-fusion spec §6)
|
2026-07-22 10:35:23 +08:00 |
|
claude_dev
|
774170ec05
|
feat(data): 数据源融合 P0 补全 + 每日增量脚本
采集层(多源各下):
- baostock: 日线全字段全量(baostock_daily_fullmarket) + 15min全市场 + 静态(基础/复权/分红/季频/三表) + 成份股
- akshare: 静态(估值/龙虎榜/大宗/融资融券/北向/指数成分/行业/股本/解禁/业绩预告)
- xtdata(miniQMT): build_daily_from_xtdata + daily_update_xtdata
数据补全 P0:
- ETF全市场: universe 扩展 沪深A股∪ETF∪基金(7414), dividend_type='front' 前复权
- 历史成份股(治幸存者偏差): index_const_hist_download 深证/国证 adjust_cni 4指数 + 中证1000/2000快照 + 新浪交叉校验
- 退市K线: baostock_delisted_download + import_delisted_to_db(实证 Day1 fetch_all_stocks 已含退市)
灌库:
- import_baostock_to_db: daily_baostock_full(5537股/1826万行,18字段)+ bs_index_constituent + bs_adjust_factor
- INSERT OR REPLACE 幂等, WAL+busy_timeout, dbbardata 不碰
每日增量 #7(用户决策A: VPS直跑):
- daily_update_static: login探针防黑名单graceful skip + LOOKBACK7 + query_stock_basic含退市 + INSERT OR REPLACE + QUERY_COUNT守48000/天
设计文档: spec(13节三层融合) + P0 plan + 数据gap设计
|
2026-07-22 10:34:22 +08:00 |
|
claude_dev
|
c4042a50d1
|
fix(portfolio): routes_portfolio 本地/SSH 自动检测(VPS后端405修复)
VPS 后端(schtasks sanguo-api → run_web.py)独立部署,之前没同步 routes_portfolio
致前端调 /api/v1/portfolio/backtest 报 405 Method Not Allowed。
- routes_portfolio 加本地/SSH 自动检测:os.path.isdir(_VPS_WORKDIR) 判定
(VPS 有 C:\sanguo_vnpy_v2 → 本地直接 subprocess 跑 runner;Mac 无 → SSH 到 VPS)
避免 VPS 后端 SSH 自连外网 IP 绕路,无需 env 配置同源两端自适应
- VPS 端同步 routes_portfolio.py + app.py 注册 portfolio_router + 重启 schtasks
- 验证:POST /api/v1/portfolio/backtest 从 405 → 401(路由注册成功,verify_token 生效)
|
2026-07-19 08:18:53 +08:00 |
|
claude_dev
|
f074a6b420
|
fix(portfolio): provider download加threading超时防御+Layer1链路闭环
xtdata.download_financial_data 阻塞无超时,休市/服务不响应卡死整个回测
(实证:周六休市HS300全成分首次download卡死,已缓存股票0.5s)。
包threading+join(120s)超时跳过读缓存(数据不全但回测不卡死)。
Layer1 MVP链路完整闭环:runner→BulletTrade engine→AllWeather策略→miniQMT→JSON
(7.49%收益/37交易日/选股5只ETF/净值37点/指标total_return+sharpe+max_drawdown全有)。
休市致股票财务空走ETF兜底,策略数值无意义但链路100%通;周一download恢复走真实选股。
|
2026-07-18 22:31:58 +08:00 |
|
claude_dev
|
b38ac3efd1
|
fix(portfolio): 前端回测MVP链路5处bug(VPS同步/routes命令/max-pool/filter/日期)
Layer1-3 链路验证发现并修复:
1. VPS runner_backtest旧版(tar同步,修 from bullet_trade.core import BacktestEngine ImportError)
2. routes shlex.quote对Windows路径产POSIX单引号cmd不认 -> 手动拼远端命令
3. routes 'set X=Y &&' 尾空格进value致bullet_trade provider名匹配失败 -> 删set(runner自带setdefault)
4. 加 --max-pool 参数(默认前端30)避免HS300+中小综指1258只基本面下载超时
5. filter_st/filter_new对全成分逐只 -> max_pool slice提前到filter前;
_coerce_datetime加YYYYMMDD解析(原fromisoformat不认miniQMT日期格式)
|
2026-07-18 22:16:08 +08:00 |
|
claude_dev
|
96b1924fd5
|
feat: 实盘模拟(live) + 组合回测MVP(portfolio)
[live] 实盘模拟 vnpy+miniQMT 直连(supervisor 轮询, 前后端):
- sanguo_live: LiveTradingEngine + AShareCtaTemplate(定寸/禁做空) + runner_supervisor(DB驱动) + persistence(4表WAL)
- sanguo_api/routes_live: 9路由(create/start/stop/positions/trades/account/status)
- frontend live: New/List/Monitor + api/live.ts; config/live.yaml
[portfolio] 组合回测 MVP(BulletTrade, 链路代码完成待验证):
- runner_backtest 加 JSON 入口(--json, BacktestEngine 顶层 import)
- sanguo_api/routes_portfolio: POST /portfolio/backtest SSH 触发 VPS 跑
- frontend PortfolioBacktest.vue + api/portfolio.ts: 表单+结果+净值曲线
- 路由/菜单注册(/backtest/portfolio 组合回测)
- 已知: MVP 链路未端到端验证, agent 改至中途被停; 待 Mac 起服务联调
|
2026-07-18 20:04:16 +08:00 |
|
claude_dev
|
a68cf4905e
|
feat(portfolio): sanguo_portfolio 组合策略框架(BulletTrade+miniQMT,不用jqdatasdk)
把聚宽"全天候轮动"(post48819)搬到 BulletTrade。融合=pip+扩展点注入
(SanguoMiniQmtProvider 继承 MiniQMTProvider 只 override get_fundamentals,
set_data_provider 公开 API 注入, BulletTrade 源码 0 改动)。
- providers: SanguoMiniQmtProvider 补 get_fundamentals(PershareIndex+自算PE/PS/PB/PCF/市值/ROIC)
- strategies/all_weather: 4选股函数+大小盘轮动+ETF兜底+涨停止损(聚宽风格翻译)
- factors(估值/ROIC自算) + filters(ST/涨跌停/次新/停牌)
- 88/88 测试 Mac+VPS 双过; VPS 回测 pipeline 跑通(修9bug:Capital单位/日期格式/百分数口径/11字段alias)
- 实盘 runner_live+runbook 就绪等交易日; DEFAULT_DATA_PROVIDER=miniqmt env 不装 jqdatasdk
- 文档: sanguo_portfolio_plan / portfolio_backtest_result / portfolio_live_runbook
|
2026-07-18 19:08:18 +08:00 |
|
claude_dev
|
723e42ab36
|
feat(frontend): 回测页加K线周期选择器(日线/5m/15m)
New.vue 加K线周期radio(日线d/5m/15m,默认d),backtest.ts CtaSubmit加interval字段。
提交body传interval(后端已支持5m/15m回测)。默认d向后兼容。
|
2026-07-18 18:47:33 +08:00 |
|
claude_dev
|
ee27313644
|
feat(data): 全市场5m/15m下载+灌库+每日增量链
xtdata逐只下载(非批量download_history_data2,后者5201只触发xtquant死锁),
先5m后15m(15m依赖5m),看get bars判成败(ret=None正常非失败)。
download_15m_xtdata.py + relaunch_15m_wrapper.ps1(auto-restart兜底segfault)。
import_vnpy_minute_fast.py灌库(INSERT OR REPLACE,interval存5m/15m,8028万行)。
_run_daily.ps1加5m/15m增量段(每天16:30)。validate_import.py校验。
全市场5201只,5m 6020万/15m 2007万bar,2025-07-17~2026-07-17。
|
2026-07-18 18:45:24 +08:00 |
|
claude_dev
|
43b6a58ba7
|
feat(backtest): 支持5m/15m周期回测(ashare适配绕vnpy Interval enum)
ashare_engine override load_data: 5m/15m 直查 dbbardata 转 BarData(MINUTE),
绕过 vnpy Interval enum 限制(原生只认 d/1h/1m)。cta_engine +interval 参数,
5m/15m 映射 MINUTE 过父类校验。api(schema/routes)+orchestrator 透传 interval。
顺带修 cta_engine DB路径污染(yaml NAS路径在Win VPS误解析→改读vt_setting.json)。
测试: 15m 600519一年 3888bars total_return-0.22 sharpe-2.04; 5m 11664bars; 日线未回归(237bars)。
|
2026-07-18 18:45:24 +08:00 |
|
claude_dev
|
d6162d1928
|
fix(factor): 因子任务持久化到 backtest_results.db(type=factor)
此前 FactorReport 无 id,_on_done 不存 DB → 因子任务不进任务列表、重启丢失
(用户:历史任务列表看不到因子分析)。_on_done 现对 FactorReport 调
_persist_factor 存 backtest_stats(type=factor, strategy=因子名, symbol=标的池,
statistics={ic_summary, report_paths})。FactorReport 加 symbols/start/end 字段。
|
2026-07-17 17:06:57 +08:00 |
|
claude_dev
|
f4cf35a7d1
|
fix(history): optimize 任务查看跳 optimize-result 页(此前跳 CTA result 致指标全空)
Dashboard/History 的 open() 只区分 factor,optimize 任务也跳 /backtest/result/,
但优化任务无单一 metrics/equity → 指标卡片全显示 —。改为按 type 分流到
/backtest/optimize-result/(同 Progress.vue 已有逻辑)。
|
2026-07-17 16:48:12 +08:00 |
|
claude_dev
|
f465756499
|
fix(optimize): 不再为每个 combo 存独立记录,避免污染历史任务列表
cta_optimizer 每跑一个 combo 就 save_result 存一条 type=optimize 记录
(statistics 是单 combo stats,无 combos key)。每次优化额外产生 N 条子记录,
历史任务列表全是这些,点开后 optimization-results endpoint 查 combos 找不到
→ 空页面。实证 142 条 optimize 里 137 条是这种空子记录(12/12 匹配主任务 combo)。
combo 结果只在内存聚合,由 aggregate 主任务统一存 {combos:[...]}。
|
2026-07-17 16:01:01 +08:00 |
|
claude_dev
|
4f0e3162b3
|
fix(optimize): 策略切换时按策略参数自动填网格,避免 grid 不匹配
Optimize.vue 硬编码默认 grid 为 fast_window/slow_window(DoubleMa 参数),
切换策略不更新。选 DualThrust/AtrRsi 等策略时 grid 仍是 fast/slow_window,
参数对该策略无效 → 所有组合跑出完全相同结果(实证 opt_235fa738 DualThrust
24 组合 total_return 全=-0.0023, distinct=1/24)。
加 watch(form.strategy):切换时拉 /strategy/{name}/params,按 parameters+
defaults 以默认值为中心生成网格,保证参数名匹配策略。历史无效优化无法挽回。
|
2026-07-17 15:33:03 +08:00 |
|