Simon Lin
cf58477fb7
fix: 历史日期调用时跳过实时请求及快照写入,明确说明实时数据已略去,不输出由其生成的金额或方向信号。可选缓存先按分析日截断,… ( #121 )
2026-10-26 07:10:23 +08:00
Simon Lin
e3981af1e4
chore: release v0.5.21
v0.5.21
2026-10-11 21:38:16 +08:00
Simon Lin
df0b63bdcf
fix: 批量入库只认新浪 2020-03-13 那一批;三表工具拒收空日期,重试也补空日期
...
- 别的日期多期共用同一入库时间(逾期公司一次补发几期)照旧等入库时间放行,不按截止日提前露出。
- curr_date 传空字符串时三张表工具直接要求重传(数据层收到空日期会整段不筛)。
- 缺数据重试对 curr_date 为 None / 空字符串的旧任务也按任务分析日补上。
2026-10-11 21:38:16 +08:00
Simon Lin
763e43f855
fix: 识别新浪 2020-03-13 批量入库时间;升级前的缺数据重试补上 curr_date
...
- 同一入库时间被 3 期及以上共用视为批量入库:仍可放行,但不算原始入库时间,这些期按法定
截止日判断。原来茅台 2019 年前三季的报表要到 2020-03-14 才放行(复核发现)。
- 公告日不晚于报告期的当作没有(上市前数据有写成报告期当天的)。
- 重试升级前记下、没有 curr_date 的财报调用时按任务分析日补上,结果仍记到原任务。
2026-10-11 21:26:49 +08:00
Simon Lin
067300364e
fix: 财报公布判断加入入库时间,逾期披露不再提前露出;三表工具 curr_date 必填
...
- 已公布 = 公告日早于分析日,或入库时间(北京时间)早于分析日当天;两个日期都晚于
报告期一年以上(原始日期已被改写丢失)时才按法定截止日判断。原来「截止日或公告日」
会让逾期披露的公司(300630 的 2023 年报 2024-07-05 才发)截止日一过就露出来。
- get_balance_sheet / get_cashflow / get_income_statement 的 curr_date 改为必填,提示词写明要传。
- 回看越早取的期数越多;按报告期从新到旧排序;同名科目不再互相覆盖;没有报告日列时不返回未筛的数据。
- 更正 start_analysis 生产者数量的注释(4 个,历史记录只清空)。
2026-10-11 21:07:28 +08:00
Simon Lin
fa3e25bb08
fix(dataflows): 财报按法定披露截止日或公告日判断是否已公布,防止回看时提前看到未公布财报
...
#117 修好新浪财报新结构后,按分析日筛选仍只比报告期:分析日 07-15 会拿到
8 月才公布的半年报。现在要求法定披露截止日已过(严格晚于),或新浪给的公告日
不晚于分析日。较早报告期的公告日是次年同期再刊出的日期,只作放行条件、
不作排除条件,也不放进返回表里。
2026-10-11 20:37:31 +08:00
Simon Lin
05209a17a0
Merge pull request #120 from ontheway06/fix/web-custom-model-id
2026-10-11 20:28:50 +08:00
Simon Lin
a3d1ee7b29
Merge pull request #117 from ontheway06/fix/sina-financial-report-structure
2026-10-11 20:28:50 +08:00
Simon Lin
ef1b180121
docs: README 表格标签列不换行,避免被挤成竖排
2026-10-10 21:33:04 +08:00
Simon Lin
30dd79e141
docs: 删除 README 求职段落
2026-10-10 20:44:52 +08:00
Simon Lin
7fc142e5a6
docs: 求职 → 看机会 · Open to Opportunities,中英双语统一作者表述
2026-10-07 14:40:40 +13:00
ontheway06
a4a69c4486
fix(web): 模型校验移到 start_analysis 的唯一消费点
...
上一个提交只在侧栏「开始分析」按钮里拦了「模型 ID 没填」,但 `start_analysis` 有
5 个生产者——侧栏「开始分析」、侧栏「未完成任务」续跑、历史记录、报告页「重新分析」、
错误页「继续未完成任务」。走其余任一条路径校验都被绕过,请求带着空模型发了出去:
Error code: 400 - The supported API model names are deepseek-flash,
deepseek-v4-pro, but you passed .
复现:深模型选「Custom model ID」且留空(`deep_model_idx: 3`),从「未完成任务」
续跑 → 请求里的 model 是空串。
改动:
- 校验移到 `web/app.py` 取出 `start_analysis` 之后、起线程之前——那是唯一的消费点,
5 条路径都要过这里。
- `_validate_model_selection()` → `validate_model_selection(config=None)`:传入真正
要发出去的 config 就校验最终值;不传则退回读 session_state,供侧栏按钮做即时反馈。
两处调用同一个函数,没有重复逻辑。
- `_build_config()` 改为只算一次并复用(此前内联在 `run_analysis_in_thread(...)` 里),
校验的就是即将发出去的那份配置。
测试:`tests/test_web_model_selection.py` 增至 14 项,新增「显式 config 校验」用例,
以及一条结构性回归——断言 app.py 在取出 start_analysis 之后、起线程之前调用校验,
防止以后有人把这道关卡挪回按钮里。
全量测试:525 passed, 14 skipped。
2026-10-05 17:03:04 +08:00
ontheway06
0f3341269a
fix(web): 「Custom model ID」不再被当成模型名发给 API
...
`MODEL_OPTIONS` 里每个供应商都带一条哨兵项 `("Custom model ID", "custom")`,含义是
"自己填模型 ID"。CLI 会就此追问输入(`cli/utils.py::_select_model`),Web 侧栏却把
这个字符串直接当成模型名用了,于是用户拿到的是一句和界面对不上号的错误:
Error code: 400 - The supported API model names are deepseek-flash,
deepseek-v4-pro, but you passed custom.
复现路径:供应商选 DeepSeek → 深模型下拉停在 index 3(正是那条哨兵)→ 开始分析。
改动:
- `_resolve_model_value()`:选中哨兵就渲染文本输入框、用它填的 ID,补上 CLI 已有的
那一步。输入框复用 `custom_quick_model` / `custom_deep_model`——这两个键本来就在
配置持久化清单里(`_save_llm_config` / `_load_saved_llm_config`),所以填过的 ID
会跟着一起记住。
- `_validate_model_selection()`:开始分析前拦住"模型 ID 没填",在侧栏直接给出可读
提示,而不是让它变成服务端一句 400——模型配置在折叠面板里,用户看不到任何反馈。
测试:新增 `tests/test_web_model_selection.py`(9 项),含一条遍历全部供应商、断言
任何哨兵值都不能原样流过的回归用例,以及事故现场(deepseek deep index 3)的定点用例。
全量测试:520 passed, 14 skipped。
2026-10-05 16:57:22 +08:00
ontheway06
4c186c56f9
fix(dataflows): 适配新浪财报接口的新返回结构
...
新浪已把财经报表结果从 result.data.<fzb|lrb|llb>(行列表)改为
result.data.report_list{报告期: {..., data: [{item_title, item_value}]}}。
旧解析只认前者,遇到新结构时返回空 DataFrame,三个取数函数于是返回
"No ... data found" 这样的正常字符串而非异常——上游 Agent 无法区分
"真的没有财报"和"解析失败",会把"该股没有财报"当成事实写进报告。
- 同时兼容新旧两种结构,上游再改版也不会退化成空表
- 新增 tests/test_sina_financial_report_shape.py 覆盖新结构、旧结构、
三个报表函数,以及未知结构的降级行为
实测 600519(curr_date=2026-09-30):资产负债表 48 → 9927 字符,
利润表 51 → 6251 字符,现金流量表 44 → 6339 字符。
全量测试:515 passed, 14 skipped。
Refs #116
2026-10-05 16:12:28 +08:00
Simon Lin
b0594a4f2b
docs: add concise open-to-work notice
2026-09-25 17:50:18 +08:00
Simon Lin
d393981690
fix: bound external calls for v0.5.20
v0.5.20
2026-09-21 08:29:51 +08:00
Simon Lin
7747b6ddf8
fix: harden LLM resilience for v0.5.19
v0.5.19
2026-09-21 06:49:48 +08:00
Simon Lin
dd35ce2cdb
Merge pull request #100 from k176060444-lgtm/fix/llm-resilience
...
fix(llm): prevent hangs via timeout retry and streaming keep-alive
2026-09-20 21:05:01 +08:00
Simon Lin
38f5178aa9
Merge pull request #112 from FelixWang119/feat/glm-catalog-5.3
...
feat(glm): 模型表补充 GLM-5.3 / 5.3-Flash / 5.2
2026-09-20 20:56:23 +08:00
Simon Lin
926de6e630
chore: release v0.5.18 — 缺失数据追踪 / 端点统一 / 辩论去重(4 PR + 1 issue)
...
合并 #107(缺失数据追踪与重试,langgraph 抬到 >=1.0)、#111(同花顺 pandas 3.x
取空、百度风控 403 被谎报成「无概念板块」)、#109(辩论历史去重与滚动压缩)、
#103(DeepSeek V4 输出预算挂 capabilities),并修 #113(CLI 与客户端兜底连到
不同站点,glm / qwen 统一到国内站)。
两处不向后兼容:langgraph 最低版本、glm/qwen 默认端点。
全量 422 passed / 14 skipped。
v0.5.18
2026-09-20 15:58:29 +08:00
k176060444-lgtm
9782a1f576
fix(llm): prevent hangs via timeout retry and streaming keep-alive
...
DeepSeek V4 thinking models emit long reasoning chains that can trip the
OpenCode Go gateway's ~3min idle timeout (TauricResearch/TradingAgents#1204 ),
leaving the process hung. Combined with transient 5xx / read-timeouts from
unstable LLM backends, a single node failure aborts the whole run.
- forward llm_timeout so a hung request can't stall the graph silently
- retry 5xx AND read-timeouts at the app layer with exponential backoff
(previously only 5xx was retried; a read-timeout crashed the graph)
- raise llm_timeout 120->150 and llm_max_retries 2->3
- enable streaming on opencode-go to keep the socket alive past the idle timeout
- capture reasoning_content on the streaming path so the DeepSeek round-trip
on the next turn doesn't fail
2026-09-20 15:28:13 +08:00
Simon Lin
922db59ae5
fix(llm): CLI 与客户端兜底连到不同站点(#113)
...
同一批 provider 的 base URL 写在两处,v0.2.4 引入时就没对齐:
provider CLI(cli/utils.py) 客户端兜底(openai_client.py)
glm open.bigmodel.cn(国内) api.z.ai(海外)
qwen dashscope.aliyuncs.com(国内) dashscope-intl(国际)
两站都能用同一个 key 且返回同一份模型列表,所以不报错——只是从 CLI 跑走国内站、
从 Web 跑走海外站(侧栏 Base URL 默认留空时用兜底值),报告里也看不出来。
其余 provider(xai / deepseek / openrouter / ollama)两处一直是一致的。
统一到国内站,判据:这是 A 股特化 fork,README 中英文都让用户去
open.bigmodel.cn 申请 key,用户主体在国内。海外用户不受影响——国内站同样可用,
需要指定端点可用 backend_url / 侧栏 Base URL 显式覆盖。
新增 tests/test_provider_endpoint_consistency.py 钉住两处一致,以及 glm/qwen
不得回到海外站——此前这两个值零测试覆盖,所以分裂了三个版本没人发现。
比对范围用显式的 _MUST_AGREE 集合并断言「恰好相等」:只断言交集非空的话,
某一侧漏写一个 provider 会让它悄悄退出比对而测试照样绿,那正是要防的失效模式。
issue 由 @FelixWang119 提出,含精确行号与两站实测对比。
2026-09-20 15:28:09 +08:00
Simon Lin
ec78d700f4
Merge pull request #109
2026-09-20 15:23:38 +08:00
Simon Lin
ace9efaff1
chore: 合并提交不带 CHANGELOG,撤回一处无关的注释转义
...
本仓的 PR 合并提交不碰 CHANGELOG / pyproject 的 version / CLAUDE.md,这三处
由发版时单独一个 `chore: release vX.Y.Z` 提交统一改,tests/test_version_consistency.py
钉住三者同步(#93 / #94 / #96 / #101 四个合并提交均如此)。
#107 把条目写进了已发布的 `## [0.5.16]` 段——0.5.16 和 0.5.17 都已发布,这批功能
会随下一版出去,写在旧版本段里会让人以为装 0.5.16 就有 langgraph>=1.0 的要求。
内容一字未改地存档,随 v0.5.18 进 CHANGELOG。
#103 顺带把注释里的 `^deepseek-v\d` 转义成了 `\\d`(Python 注释不做转义,读者会
看到两个字面反斜杠),与该 PR 主题无关,还原。
pyproject 的 langgraph>=1.0 是 #107 的真实依赖变更(wrap_tool_call 自 LangGraph 1.0
起提供,实测 0.6.11 没有),保留;version 仍为 0.5.17 未动。
2026-09-20 15:11:14 +08:00
Simon Lin
e58b94f2a2
Merge pull request #111
2026-09-20 15:00:42 +08:00
Simon Lin
fbb268df5c
Merge pull request #107
2026-09-20 15:00:42 +08:00
Simon Lin
dc086d22db
Merge pull request #103
2026-09-20 15:00:41 +08:00
Simon Lin
19dee49168
docs: remove hiring and donation sections
2026-09-17 07:53:30 +08:00
FelixWang
c51504667c
feat(glm): 模型表补充 GLM-5.3 / 5.3-Flash / 5.2
...
智谱当前 /models 实际可用(实测 api.z.ai 与 open.bigmodel.cn 返回一致):
glm-4.5 glm-4.5-air glm-4.6 glm-4.7 glm-5 glm-5-turbo
glm-5.1 glm-5.2 glm-5.3 glm-5.3-flash
原表 quick 档到 glm-5 为止、deep 档到 glm-5.1 为止,5.2 / 5.3 已上线但未收录,
用户在 Web 侧栏和 CLI 里都选不到。
本次补齐:
quick: glm-5.3-flash / glm-5.3 / glm-5 / glm-4.7
deep: glm-5.3 / glm-5.2 / glm-5.1 / glm-5
低成本项(glm-5 / glm-4.7)保留作为回退,`Custom model ID` 仍在末尾。
纯增补,不改任何既有选项的语义。
2026-09-16 11:20:49 +08:00
FelixWang
a13f336e03
fix(a_stock): 概念板块把百度风控 403 谎报成「该股无概念板块」
...
百度 PAE `getrelatedblock` 被风控时返回 HTTP 403 +:
{"ResultCode": 0(整数), "Result": {"code": 403, "isCaptchaEnabled": true,
"msg": "hit risk"}}
外层 `ResultCode` 是**整数** 0,而代码里是 `str(d.get("ResultCode", -1)) != "0"`,
整数 0 正好通过检查,随后 `result.get(code, [])` 取空,落到
`return f"No concept/block data for {code}"`。
后果:一次「取数被拦」被当成「该股确实没有概念板块」这个事实喂给模型,
且报告里完全看不出异常。现在单独识别 `Result.code == 403` 并如实报出失败原因。
顺带把手工拼接的 query string 换成 `params=`(原写法把 code 直接插进 URL,
若 code 含需转义字符会拼出坏 URL)。
补充实测:该接口对 python-requests 的 TLS 指纹做风控——同一时刻 curl
(编码 / 不编码均可)与 curl_cffi `impersonate=chrome` 都返回 200,
而 requests 连续 6/6 返回 403。要稳定取数需要浏览器指纹伪装,
这属于是否新增 curl_cffi 直接依赖的决策,本 PR 不擅自引入。
2026-09-16 11:20:49 +08:00
FelixWang
2444646ac9
fix(a_stock): 同花顺一致预期在 pandas 3.x 下必然取空
...
`_ths_eps_forecast` 把 HTML 文本直接传给 `pd.read_html`。pandas 3.x 起
`read_html` 的 `io` 参数只接受路径 / URL / 文件对象,字符串会被当作**路径**,
于是必然抛 FileNotFoundError;异常消息里还带着整页 133KB HTML,把日志刷满。
实测 pandas 3.0.5:
pd.read_html('<table>...</table>') -> FileNotFoundError
pd.read_html(io.StringIO('<table>...</table>')) -> OK
影响范围:`get_fundamentals` 的一致预期 EPS 段和 `get_profit_forecast` 双双失效。
用 io.StringIO 包装后实测可正常取到 002008 的 2026-2028 三年一致预期(14 家机构)。
pyproject 声明的是 `pandas>=2.3.0`,pandas 3.x 在允许区间内,属于必现回归。
2026-09-16 11:20:49 +08:00
sc
13a9a21af7
refactor(agents): dedupe last-argument injection in debate and risk nodes
2026-09-08 21:47:19 +08:00
sc
f9b5946d22
feat(agents): add compact_history for rolling-window debate compaction
2026-09-08 21:47:18 +08:00
Codex
ac4de230f8
feat(report): warn when exported data is incomplete
2026-09-08 08:46:00 +00:00
Codex
2dad8afffc
feat(data): track and retry missing data tasks
2026-09-08 08:43:17 +00:00
Simon Lin and Claude Fable 5.1
f1bd10f946
chore: release v0.5.17 — LLM 配置持久化落到 ~/.tradingagents 并修订阅覆盖的恢复(#96 补修)
...
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com >
v0.5.17
2026-09-05 10:02:23 +08:00
WenhuaXia
7654e2304e
feat(web): 持久化 LLM 模型配置,重开标签页不再回到默认 provider ( #96 )
...
Web UI 的 provider / quick·deep 模型 / base_url / subscription_scope / 自定义模型 ID 现在写入 .llm_config.json,页面加载时用 setdefault 恢复(不覆盖当次修改);写失败只记 warning 不打断分析。
Contributed by @WenhuaXia.
2026-09-05 09:56:04 +08:00
Simon Lin
119fa8da90
docs: update AI role focus
2026-09-04 16:32:31 +08:00
Simon Lin and Claude Fable 5.1
4b9d16f10d
chore: release v0.5.16
...
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com >
v0.5.16
2026-09-02 08:02:33 +08:00
Simon Lin and Claude Fable 5.1
dc737a09fb
fix: 只传部分 config 时 TradingAgentsGraph 直接 KeyError(#101)
...
README 快速开始的示例只给 4 个键,而 __init__ 里 `config or DEFAULT_CONFIG` 是整体替换,
紧接着 os.makedirs(config["data_cache_dir"]) 就抛 KeyError —— 照 README 粘贴即崩。
- 新增 merge_config():传入的 config 当覆盖项与 DEFAULT_CONFIG 浅合并,
与 dataflows 层 set_config() 的合并语义对齐;传完整 config 的用户行为不变
- README 中英文说清 config 是传给 TradingAgentsGraph(config=...) 的字典、不是仓库里的文件,
以及这段代码放在哪运行
- 根目录 main.py 从上游残留的 NVDA/yfinance 示例改成与 README 一致的 A 股可运行示例
- 新增 tests/test_partial_config.py
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com >
2026-09-02 08:02:33 +08:00
Simon Lin
22f91015dc
docs: add author career opportunities note
2026-09-01 14:21:57 +08:00
k176060444-lgtm
3563c10d99
fix(llm): bound DeepSeek V4 output via model capabilities
...
Capped only explicitly identified DeepSeek V4 thinking models at 8192
tokens (reasoning + content) via capabilities.py, per PR #100 maintainer
review. Follow-up to #100 (which removed the contested global
DEFAULT_CONFIG max_tokens=8192 and kept it at None / provider-native).
Upstream #1204 : uncapped V4 reasoning chains can trip the OpenCode Go /
OpenAI-compatible gateway ~3 min idle timeout.
- Add default_max_tokens to ModelCapabilities and
_DEEPSEEK_V4_DEFAULT_MAX_TOKENS = 8192 (single source; matches
anthropic_client _THIRD_PARTY_DEFAULT_MAX_TOKENS = 8192 provenance,
#91 report-truncated feedback). Only DEEPSEEK_THINKING carries it.
- OpenAIClient.get_llm fills max_tokens from capabilities only when the
caller did not already set one (explicit TRADINGAGENTS_MAX_TOKENS /
role_llms max_tokens wins). Matcher reuses the existing strict
DeepSeek V4 pattern ^deepseek-v4(?:$|[.-]) — V3.x, Claude/OpenAI/
Gemini/MiniMax/unknown models stay at None.
- Tests cover V4 vs non-V4, V3.x non-match, explicit-override wins,
and provider-kwargs -> llm propagation plus capability regression.
No change to DEFAULT_CONFIG global None, timeout/retry/streaming, or
reasoning_content capture (those remain in #100 ).
2026-08-21 15:10:50 +08:00
Simon Lin
ed778c51ee
chore: release v0.5.15
v0.5.15
2026-08-19 15:50:46 +08:00
KK and k176060444-lgtm
8db46605b3
feat: support per-role api_key in role_llms for multi-gateway setups ( #94 )
...
* feat: support per-role api_key in role_llms for multi-gateway setups
* test: add per-role api_key precedence tests for openai_compatible provider
---------
Co-authored-by: k176060444-lgtm <k176060444-lgtm@users.noreply.github.com >
2026-08-19 15:43:12 +08:00
Simon Lin
0badc3340c
fix: 连字符分隔符被当成构词 / 版本号三处不同步(codex 第九轮)
...
1. `最终评级:**Sell**- 退出` 里的 - 只是分隔符,却被当成"会延续成更长的词"判否,
parse_rating 静默返回 Hold,记录下错误的决策。
判据再补一层:连字符要看后面——跟字母/数字是构词(Sell-off / Buy-side 拒),
跟空白或其它字符只是分隔符(Sell- 退出 收)。覆盖矩阵扩到 27 例。
2. 上一版改了 pyproject 和 CHANGELOG,漏了 CLAUDE.md 的「当前版本」行,后续 agent
和发版流程会读到旧版本。新增 test_version_consistency.py,三处不一致直接失败,
不再靠人记得。
测试:新增 4 例,369 passed / 13 skipped / 0 failed。→ v0.5.14
v0.5.14
2026-08-09 15:30:44 +12:00
Simon Lin
1edf4be27b
fix: 加粗+连字符仍被判成评级(正则回溯,codex 第八轮)
...
v0.5.12 把 markdown 收尾星号写成 \*{0,2}(?!词字符)——先消耗再判断会回溯:
`建议:**Sell**-off risk remains elevated` 里 \*{0,2} 先吃掉 **,被 - 判否后退一步
只吃一个 *,剩下那个 * 恰好满足边界,于是又判成 Sell。正好把这条规则本来要挡的
连字符散文放了回来。
改成把星号放进前瞻内部((?!\*{0,2}词字符))——"后面不能是(0~2 个星号 + 词字符)"
没有可回溯的余地。`最终评级:**Sell**` 不受影响。
⚠️ 刻意不用占有量词 (?>...) / *+:那是 Python 3.11+ 特性,而本项目声明
requires-python = ">=3.10",3.10 用户会在导入时就 re.error——比逻辑 bug 更硬的破坏。
新增守卫用例直接检查编译后的 pattern。
覆盖矩阵扩到 25 例。测试:新增 4 例,365 passed / 13 skipped / 0 failed。→ v0.5.13
2026-08-09 15:23:53 +12:00
Simon Lin
be38f469d8
refactor: 评级边界与 BESTIP 保护改用正确抽象(codex 第七轮)
...
这两块前后各被修了三轮"修了又漏",问题不在某个字符,在抽象选错了。
1. 评级边界:枚举标点 → 「不能延续成更长的词」
第七轮指出 v0.5.11 收紧后又误伤 `最终评级:Buy(基于风险收益比)`——枚举的是
收尾标点,没算开括号,合法评级被静默改写成 Hold。
三轮轨迹:无边界→`Buyer interest`判Buy;(?![A-Za-z])→`Sell-off`判Sell;
枚举收尾标点→`Buy(...)`反被判Hold。
枚举允许的标点是填不完的坑。改成只问:紧跟其后的字符会不会让它变成另一个词
([A-Za-z0-9_-])?会就不算评级,中文/括号/标点/空白/行尾一律放行。
新增 22 例参数化矩阵,并写明改这条规则必须整张过一遍。
2. BESTIP 保护:手动调还原 → 上下文管理器
原来在两处手动调 _restore_bestip(),再加一条提前返回就会漏,而漏掉的后果是
静默留下一台死服务器。改成 with _preserve_mootdx_bestip() as keep:选中时
调 keep() 表示这次覆写是想要的,其余每条退出路径(含异常)自动还原。
_get_mootdx_client 114 → 82 行。
端到端实测:真实探测 38 台全失败后,用户配置的 218.6.170.47 完好无损。
测试:新增 21 例,361 passed / 13 skipped / 0 failed。版本 → v0.5.12
2026-08-09 15:16:18 +12:00
Simon Lin
f5cd0ef67f
fix: 上一版那两个修复本身都没修对(codex 第六轮)
...
1. BESTIP 快照取到的是空默认值 → v0.5.10 的修复无效
新进程里 mootdx 要等 BaseQuotes.__init__ 调 config.setup() 之后才把持久化的值
读进来,此前 get("BESTIP") 是模块默认空值。快照到空值后,全部探测失败时的
"还原"反而把用户真实配置抹成空——比不还原更糟。
实测 0.11.7:setup 前 {'HQ': ''},setup 后 {'HQ': ['218.6.170.47', 7709]}。
现在快照前先显式 setup();端到端验证真实探测 38 台全失败后用户配置完好。
测试也改为复刻真实构造函数语义(旧假件不调 setup,抓不到这条)。
2. 评级边界仍放行连字符散文 → v0.5.10 的修复不完整
(?![A-Za-z]) 只挡紧跟字母的情况,连字符和数字后缀照样过关:
`建议:Sell-off risk remains elevated` → Sell、`最终评级:Buy2024` → Buy。
改为要求评级词后是真正的结束(行尾/空白/中文/常见标点),并先吃掉 markdown
收尾星号,`最终评级:**Sell**` 不受影响。
测试:新增 2 例,340 passed / 13 skipped / 0 failed。版本 → v0.5.11
2026-08-09 15:05:04 +12:00
Simon Lin
cbabc02fc9
fix: 探测覆写 mootdx 配置 / 中英混排评级误判(codex 第五轮)
...
两处都是新增行为自己带出来的副作用。
1. 探测服务器会覆写用户配置的 mootdx 服务器
StdQuotes.__init__ 里有 config.set('BESTIP', {'HQ': self.server})——每建一次
带 server 的 client 都会持久化写进配置文件。v0.5.6 把候选表扩到 38 台后,逐台
探测等于一路覆写用户原本配好的服务器,最后留下最后一台失败的:裸 factory 兜底
(读 BESTIP)再也救不回来,同机上其它用 mootdx 的程序也被连累。
现在探测前快照 BESTIP,兜底前与全失败时都还原。
2. 中文标签后跟英文散文被误判成评级
_CN_LABEL_EN_RE 缺词边界:`最终评级:Buyer interest remains weak` → Buy,
`建议:Selling pressure is high` → Sell。误判会写进记忆日志再污染绩效统计,
报告里完全看不出来。已加 (?![A-Za-z]),正常中英混排不受影响。
测试:新增 4 例,338 passed / 13 skipped / 0 failed。版本 → v0.5.10
2026-08-09 14:55:30 +12:00
Simon Lin
3968973958
fix: 未完成任务索引写失败不再静默吞掉(承接 #93)
...
#93 的重试 + 降级思路是对的,但最后一层 `except OSError: pass` 完全静默——
索引一直写不进去时用户永远不会知道,「未完成任务」列表长期不更新也无从排查。
改为打一条 warning:仍然不往上抛(不中断分析,读取端容错、下次会重建),
但至少可见。本项目对静默吞错一贯从严。
2026-08-09 14:50:12 +12:00