Commit Graph
130 Commits
Author SHA1 Message Date
Haozhe Wu d3c76819c3 fix: complete October 11-12 maintenance and research updates
Fix live option guards, grounding operand evidence, source-bound benchmarks, trade artifacts, attribution, drawdowns, valuation tolerances, and SEC point-in-time factor inputs.

Add Brazil research data and market support, 13 fundamental and valuation factors, channel progress forwarding, and opt-in ZimaOS templates. Update seven README News sections with three visible dates.

Validation: 17,635 backend tests passed; 1,084 final targeted tests and 103 frontend tests passed. Frontend build, package build, documentation checks, and CI gates passed.
2026-10-12 02:29:46 +08:00
Haozhe Wu 6965c2884b Complete UTF-8 recovery, channel review, pinned portfolio surfaces and validation repairs 2026-10-10 23:05:38 +08:00
Haozhe Wu f1fee5d35f Fix causal option pricing, channel refresh state, and market routing
Preserve scientific-notation amounts and add regression coverage for the five review findings. Update README News after successful backend, frontend, and contract checks.

Signed-off-by: Haozhe Wu <haozhe_wu@connect.hku.hk>
2026-10-09 19:18:19 +08:00
Haozhe Wu ce73fff5a4 Finish thirteen-PR integration and repair uncovered boundary cases
Signed-off-by: Haozhe Wu <haozhe_wu@connect.hku.hk>
2026-10-09 18:42:52 +08:00
Haozhe Wu e5097b3931 Merge pull request #1730: fix(loaders): retire mootdx from the default A-share chain and health canary 2026-10-09 18:15:43 +08:00
Yufeng He ef75335115 fix(loaders): retire mootdx from the default A-share chain and health canary
TDX quote servers stopped answering the client protocol mootdx/tdxpy
speak (2026-07, mootdx/mootdx#157): every kline category, market and
server returns empty, realtime quotes return zero rows, and get_k_data
dies on a KeyError inside mootdx. Upstream has been dormant since 2024,
and the weekly health lane has been red on mootdx since it started.

Each auto-mode fetch still spent ~9.5s inside mootdx before falling
through to eastmoney, so the dead slot was pure latency tax on every
A-share call.

Drop mootdx from FALLBACK_CHAINS["a_share"] and from the canary set
(tracked under EXCLUDED_PUBLIC_SOURCES with the upstream issue as the
reason). The loader stays registered: explicit source="mootdx" calls
keep working if a compatible fork ever restores the protocol. Docs
(en/zh/ja/ko/es/ar/id), tool schema hints, env examples and the
data-routing/mootdx skills updated to match.

Closes #1729

Signed-off-by: Yufeng He <40085740+he-yufeng@users.noreply.github.com>
2026-10-08 04:13:20 +08:00
Haozhe Wu 14cabaf195 docs: record October 7 and 8 maintenance updates 2026-10-08 03:32:24 +08:00
Haozhe Wu 7f6908b7e1 fix(live): stop active attempts and isolate durable schedules
Wait for actual session terminal events, cancel in-flight analysis on runner stop, and finish scheduler teardown across startup, concurrent stops and API shutdown. Correct heartbeat status units and remove stopped sentinels.

Isolate broker job stores with legacy migration and complete atomic writes under concurrency. Skip malformed emergency-close symbols and overflowing quantities, and make capped grounding feedback explicit about omitted findings.

Validation: 16,817 backend tests passed (190 skipped), 38 frontend status tests passed, and changed Python syntax/lint passed. Update seven README News entries.
2026-10-06 01:28:07 +08:00
Haozhe Wu c214c0356d fix(grounding): keep recovery refs within figure kinds 2026-10-05 12:09:53 +08:00
Haozhe Wu f6e72428b7 fix: finish research prompts and grouped validation boundaries 2026-10-05 11:16:24 +08:00
Haozhe Wu 8c6bfe0f98 docs: publish October 4 workflow news and synchronize tool inventories
Signed-off-by: Haozhe Wu <haozhe_wu@connect.hku.hk>
2026-10-04 03:15:00 +08:00
Haozhe Wu a347943c6b Merge PR #1585: deny unsupported Robinhood option orders 2026-10-04 02:34:16 +08:00
Haozhe Wu 085131f81e Merge PR #1647: structured reads of manifest-listed run artifacts 2026-10-04 02:33:57 +08:00
Haozhe Wu 438c578193 Merge PR #1649: editable channel-aware scheduled delivery 2026-10-04 02:31:33 +08:00
Haozhe Wu b2dfe9a66f docs: announce sixteen research and reliability fixes in seven locales
Signed-off-by: Haozhe Wu <haozhe_wu@connect.hku.hk>
2026-10-03 16:20:49 +08:00
Haozhe Wu f21aa13d90 docs: publish October 2 maintenance news in all README languages 2026-10-02 16:14:41 +08:00
Haozhe Wu a6764391a7 Merge pull request #1486 from shadowinlife/feat/southbound-flow-tool
feat(tools): get_southbound_flow — the only live Stock-Connect net-flow signal (Eastmoney datacenter primary, HKEX official fallback)
2026-10-01 15:46:47 +08:00
zeus229 db9d631197 docs(scheduled): describe editable channel-aware delivery
Signed-off-by: zeus229 <69399886+zeus229@users.noreply.github.com>
2026-09-30 17:02:10 -03:00
shadowinlife faac0d2bac feat(tools): read_run_artifact — manifest-driven structured reads of run artifacts
Goal: give MCP clients token-cheap structured access to backtest run
artifacts. read_file returns raw CSV text and truncates mid-file; this
tool parses the artifact once and serves typed JSON pages a client can
page through or chart directly. Implements #1645.

Design: the run_card.json artifacts manifest (path/sha256/size_bytes per
file) is the trust anchor. Friendly aliases (equity, trades, metrics,
positions, target_positions, ohlcv:<CODE>, run_card) resolve by a fixed
mapping and work without a card; any other value is treated as a
run_dir-relative path accepted only when the manifest lists it, so a new
artifact kind becomes readable with zero code change. Manifest entries
are themselves validated — no absolute paths, no drive prefixes, no '..'
segments under either separator style — and every resolution is
re-checked with resolve() + is_relative_to(run_root), so a tampered card
can never point the reader outside the run directory. Three formats:
rows (lossless offset paging with honest truncated/next_offset),
downsample (equal-stride, first+last pinned), meta (columns/total_rows/
size_bytes, plus the manifest sha256 and manifest_size_bytes when
listed). Envelopes stay within a 120K-character budget by shrinking
whole records following _result_paging's proportional-shrink pattern —
never mid-record, never broken JSON.

Contract: purely additive read-only surface (75th MCP tool, 108th
registry tool); errors return {"ok": false, "error", "hint"} and success
envelopes carry no ok/status field.

Tests: 44 cases — manifest acceptance and refusal (unlisted relative
paths, '..' and absolute tampered entries, symlinked manifest entries,
non-served suffixes), aliases with absent/corrupt cards, meta sha256
exposure, 3821-row downsample endpoint pinning, lossless paging walk,
traversal refusals, coercion, projection, budget shrink/re-stride/
floor, clamping, exact envelope key sets. README/SKILL count pins
updated (74->75 MCP, 107->108 registry); test_readme_counts,
test_distribution_skill_manifest and the MCP smoke suite are green.

Signed-off-by: shadowinlife <shadowinlife@gmail.com>
2026-10-01 01:17:41 +08:00
Haozhe Wu 18027a0c2b docs: CHANGELOG and News for the 09-30 merges
Unreleased entries for #1572, #1634, #1636, #1578, #1602 and #1637.
#1572's own CHANGELOG hunk was written into the 0.1.16 section before
that release was cut, so it is dropped from the merge and rewritten
here under its own PR number (it cited #1569, the Email/WebSocket issue).
2026-09-30 16:35:12 +08:00
Haozhe Wu 6d4e7834af Merge PR #1572: guided Web UI config for Feishu
# Conflicts:
#	CHANGELOG.md
2026-09-30 16:27:29 +08:00
Haozhe Wu 36485bf55b docs(readme): write the fallback chains in the order the loader walks
Crypto read okx · ccxt · binance and forex mt5 · yfinance · akshare in
all seven READMEs, while FALLBACK_CHAINS walks binance before ccxt and
akshare before yfinance. The note "futures / fund / macro → tushare /
akshare" was stale too: futures is akshare → local (#1395), funds
tushare → akshare, macro akshare → tushare. Canada, Vietnam, Argentina
and indices had no bullet.

test_fallback_chains_are_written_in_the_order_the_loader_walks compares
every chain a README writes with _DEFAULT_CHAINS, both ways, as
sequences, so translated labels need no mapping.
2026-09-29 17:22:36 +08:00
Haozhe Wu e1dbea8ad3 release: 0.1.16 — a number that can show where it came from
Rolls up 492 commits / 116 merged pull requests since 0.1.15, from 16
contributors.

The final-answer grounding gate stopped guessing what a number is from
the words around it: the model declares each figure's role (observed,
derived, proposed, cited or count), the gate checks the declaration
against the session's tool evidence, and a figure that fails is cut from
the answer instead of the whole answer being refused. A backtest's own
output now grounds the report written about it, run cards cite a metric
only where the saved CSV agrees, and the generated broker matrix states
each profile's permissions as declarations. Research runs keep what they
fetched: compaction follows the model's real context window instead of a
fixed 40K estimate. The missing-data sweep reached 59 more alphas.
Argentina (BYMA), weekly and monthly bars, Bahasa Indonesia, Gildata,
OpenCode, Email and WebSocket channels and four broker connectors (KIS,
Upbit, Toss Securities, Scalable Capital) land alongside.

Verified before release: the reporter's risk-parity prompt, which had
stopped with no_progress after 93 seconds on DeepSeek V4 Pro, completed
on 4a40a7f6's parent in 8m13s with both backtests run, 13 steps saved and
the report released with its core figures grounded.

Version declarations bumped in pyproject.toml, agent/SKILL.md,
Dockerfile, frontend/package.json, both package-lock.json entries, all
nine locales and the Layout test mock. CHANGELOG cites 116/116 merged
pull requests and credits 16/16 authors. README News carries the release
in seven languages, three entries visible.
2026-09-29 16:13:16 +08:00
Haozhe Wu 67271863da docs: add September 29 news in seven languages 2026-09-29 15:22:16 +08:00
Haozhe Wu 47a036d66d fix: harden grounding corrections and MT5 identity integration 2026-09-28 16:44:55 +08:00
Haozhe Wu dec2c0e6b8 fix: complete September 28 reliability reviews and broker documentation
Bound BaoStock messages and serialize SDK sessions; verify Copilot credential
lookup expiry without changing the SDK's per-call credential resolution.
Run public-loader health checks in isolated, credential-free processes and a
separate dependency environment, with explicit failure reports and a weekly
workflow. Render broker capabilities per profile and document verification
requirements. Update September 28 News in all seven README languages.

Closes #1626
Closes #1623
Closes #1617
Closes #1492
2026-09-28 16:07:06 +08:00
Haozhe Wu 0244eceaaf fix: complete September 27 reviews and surface verified run-card evidence 2026-09-27 10:57:33 +08:00
Haozhe Wu b4569ffbef docs: add September 26 maintenance news in seven languages 2026-09-26 23:36:25 +08:00
Haozhe Wu 5e9ffd1a73 fix(frontend): cancel delayed history scrolls when leaving a chat 2026-09-25 21:18:27 +08:00
Haozhe Wu d945a1b782 docs(readme): add September 25 maintenance news in seven languages 2026-09-25 21:11:07 +08:00
shadowinlife 8c2cbec00e docs(readme): add Feishu to the guided Web UI channel list in seven languages
Mirrors the DingTalk/QQ sentence in the "Configure from the Web UI"
paragraph across README.md and the six translations, in lockstep.

Part of #1569.

Signed-off-by: shadowinlife <shadowinlife@gmail.com>
2026-09-25 18:49:21 +08:00
lorenzozanee 8845b722f7 fix(robinhood): gate unsupported option orders
Signed-off-by: lorenzozanee <wyz0707@proton.me>
2026-09-25 10:37:16 +08:00
Haozhe Wu 1f6e05d3ba fix(backtest): Hong Kong RMB and USD counters stay out of the HKD pool, decided by the code
The BYMA / TSX fix could not close Hong Kong. The hk_equity chain starts with
Tencent and Eastmoney, which declare no currency, so a guard on Yahoo's
declared currency only moved a counter to the next source. The venue gives a
better handle. HKEX's Stock Code Allocation Plan (updated 2026-03-12) assigns
80000-89999 to "Products traded in Renminbi", and 09000-09199, 09200-09399,
09400-09499, 09500-09599, 09700-09799, 09800-09849, 10900-10999 and
41500-41599 to products traded in USD. Every other .HK code trades in HKD, and
that includes 09600-09699 and 09850-09999 (9988.HK, 9618.HK). Checked against
the currency Yahoo declared for 24 codes on 2026-09-24: 6 CNY, 10 USD and
8 HKD, all matching.

Before: 80700.HK (Tencent's RMB counter, 375.40 CNY) or 9834.HK (a USD ETF)
ran in the HK engine's HKD pool next to 00700.HK with no check at all, because
Composite's mixed-currency guard only runs across markets. The grounding gate
also required the answer to call their prices HKD.

- _market_hooks.hk_counter_currency(): the one table. code_currency() uses it,
  so Composite's guard sees CNY / USD counters.
- runner._create_market_engine refuses a Hong Kong code traded in another
  currency, for single-market and cross-market runs alike, before any engine
  prices it.
- grounding identity._infer_currency reads the same table (lazy import, as
  context.py already imports from backtest), so 80700.HK is quoted in CNY
  whichever source served it.

Tests cover the 24 live codes, both sides of every range boundary, the refusal
(mixed, pure RMB, USD, cross-market) and an HKD-only run that still builds.
Mutants each fail: no RMB range (12), a USD range one code too wide (1),
code_currency ignoring the counter (1), the runner guard off (4), grounding
ignoring the counter (1). Related suites: 2769 passed.
2026-09-24 20:08:03 +08:00
Haozhe Wu 9830ab8f6b docs: the header break was openai 3.19.2, not openai 3.x (#1573)
openai 3.19.0 still built request headers with the case-sensitive
_merge_mappings; 3.19.2 switched to _merge_headers. Main's pre-fix code with
langchain-openai 1.6.5 passes 9/9 on openai 3.19.0 and fails the one test on
3.19.2. The comments, test docstring, CHANGELOG and news said 3.x.
2026-09-24 19:02:46 +08:00
Haozhe Wu e65832d348 docs(readme): 2026-09-24 news in seven languages, and CHANGELOG 2026-09-24 18:55:24 +08:00
Haozhe Wu 62842f4f4b Merge PR #1544: feat(channels): guided Web UI config for Email and WebSocket
# Conflicts:
#	CHANGELOG.md
2026-09-24 18:48:12 +08:00
Haozhe Wu a65427a3d5 docs(readme): 2026-09-23 news in seven languages, and CHANGELOG 2026-09-23 12:30:00 +08:00
shadowinlife c67af90752 Merge branch 'main' into feat/email-websocket-web-config 2026-09-23 10:36:14 +08:00
shadowinlife d4861f36e3 docs(readme): sync Email/WebSocket guided-config sentence to all locales
The English README's "Configure from the Web UI" paragraph gained the
Email/WebSocket guided-channel sentence in the previous commit; mirror it
into the six translated READMEs (zh, ja, ko, ar, es, id) at the same slot
— after the QQ sentence, before the Test-connection sentence — keeping
IMAP/SMTP/TLS/WebSocket/Test connection verbatim. Prose-only; no count or
roster change, so test_readme_counts stays green (108 passed).

Follow-up to #1519 (extends #1520).

Signed-off-by: shadowinlife <shadowinlife@gmail.com>
2026-09-22 15:47:29 +08:00
Haozhe Wu 863b401486 docs(readme): second 2026-09-22 news entry in seven languages, and CHANGELOG
Weekly and monthly bars (#1479), price indices stamped raw (#1541), the
compaction replay (#1488), field-ref tail-risk identity (#1444) and the
QVeris refusal (#1494). The 2026-09-20 entry, which announced that 1M was
rejected, moves under Earlier news.
2026-09-22 11:55:23 +08:00
Haozhe Wu 6ca364f757 feat(data): weekly and monthly bars, built from daily ones (#1479)
get_market_data and backtests accept 1W and 1M. A monthly review over
21 months used to mean 440 daily rows that microcompaction cleared
faster than the agent could aggregate them, until the no-progress
budget killed the run; one call now returns 21 bars.

Every loader is still asked for daily bars, and loaders.base.resample_bars
builds the period bar at the three fetch boundaries (runner.fetch_data_map,
market_data.fetch_market_data, the benchmark fetch). Few sources serve
weekly or monthly bars and those that do disagree on where a week ends
and how its bar is adjusted, so one resample keeps a weekly bar the same
thing whichever source served the days, at the daily caliber. A week runs
Monday to Sunday, a month is a calendar month, and each bar is stamped
with the last trading day inside it, when its close is known: first open,
highest high, lowest low, last close, summed volume and amount, vwap
weighted by volume, mean funding rate, last value of any other column.

The places that read an interval token learned the two new ones, and
1M is matched before any case fold, which would read it as a minute:
- calc_bars_per_year: 52 and 12 whatever the market's trading days;
- the runner's spacing check: a weekly or monthly file declared 1D now
  matches 1W / 1M; the calendar branch is left for quarterly files;
- _interval_span_hours: 168h and a mean month of 730.5h, so a weekly
  perpetual bar settles 21 funding periods instead of falling back to one;
- strict 100x compared the lower-cased token, so 1M would have passed as
  one minute; attribution lower-cased too and would annualise a monthly
  run at 98,280 bars a year;
- get_market_data serves 1W / 1M and the 1wk / 1mo spellings; the #1480
  guard that refused them is gone, and the case fold no longer maps 1m and
  1M onto one key;
- the technical-indicator tool documented 1wk / 1mo but handed them to the
  loaders verbatim, and fetched two days per bar whatever the interval, so
  200 weekly bars came back as 57.
READMEs x7, the MCP docstring and the strategy-generate skill list them.
2026-09-22 11:35:26 +08:00
Haozhe Wu f3d8cf1f44 docs(readme): add #1517 to the 2026-09-22 news and CHANGELOG 2026-09-22 02:22:52 +08:00
Haozhe Wu f9355d6feb docs(readme): 2026-09-22 news in seven languages, and CHANGELOG 2026-09-22 02:13:52 +08:00
Haozhe Wu 0285acdcf5 docs(readme): 2026-09-21 news in seven languages
Channel configuration from the Web UI (#1520, #1529), the missing-bar alpha
class, the data-tool fixes, Indonesian, and the Requesty removal. The news
entry #1520 carried for 2026-09-20 is folded into it; three entries stay
visible in every README, README_id.md included.
2026-09-21 20:39:53 +08:00
Haozhe Wu 051aeb5509 refactor(providers): remove the Requesty built-in provider
Requesty (added in #474) is an OpenAI-compatible gateway whose capabilities
were a copy of OpenRouter's: same provider/model naming, same
extra_body.reasoning opt-in, no adapter code of its own. Built-in slots are
kept for providers with their own behaviour; a gateway that speaks an
existing wire format is configured through that provider, and #1532 (API
Route) is being closed on the same grounds.

Migration, identical request shape: LANGCHAIN_PROVIDER=openrouter,
OPENROUTER_BASE_URL=https://router.requesty.ai/v1, OPENROUTER_API_KEY=<the
Requesty key>. Past news and contributor credits in the READMEs are left
as history; the supported-provider lists drop it.
2026-09-21 20:35:37 +08:00
Haozhe Wu ed0751809f Merge PR #1529: feat(channels): QQ web configuration with connection test and guided setup 2026-09-21 20:31:28 +08:00
Haozhe Wu 1bf0bd62d4 Merge PR #1520: feat(channels): web-based channel configuration with connection test and hot apply
# Conflicts:
#	frontend/src/pages/Settings.tsx
2026-09-21 20:31:27 +08:00
Haozhe Wu ead3f2e74c fix(gildata): READMEs, order fixtures and token text for the new loader (#1474)
The PR's CI failed on its own changes: the seven README loader tree lines
still said 27 sources without gildata, and two tests pinned a seven-source
A-share order that stops validating once gildata joins the chain.
README_id.md, which landed after the PR's base, also gets the source-table
row, the count and the chain. The loader docstring and CHANGELOG still said
the token rides the URL query string; since the review it is sent in the
Authorization header.
2026-09-21 20:31:02 +08:00
Haozhe Wu e6095d5209 Merge PR #1474: feat(data): Gildata (恒生聚源) A-share OHLCV loader via the raw-api MCP endpoint 2026-09-21 20:29:34 +08:00
shadowinlife b851738741 docs(readme): QQ joins the guided web-config channels
One sentence per README in the existing "Configure from the Web UI"
paragraph: register a bot on the QQ Open Platform (q.qq.com), copy
AppID/AppSecret into the form, verify with Test connection before
saving, then enable - no public callback URL needed (WebSocket via the
official botpy SDK). The DingTalk "first fully-guided channel"
sentence stays; news entries are historical and untouched.

Part of #1519.

Signed-off-by: shadowinlife <shadowinlife@gmail.com>
2026-09-21 12:22:05 +08:00