Commit Graph
2866 Commits
Author SHA1 Message Date
Haozhe Wu b504f3b19a Merge PR #1726: fix(kis): see SOR fills and recover from a server-invalidated token
Desktop Windows / package (push) Waiting to run
Build and Push Docker Image / validate-build (push) Waiting to run
Build and Push Docker Image / build-and-push (push) Skipped
CI / Hash lock / macOS ARM64 (push) Waiting to run
CI / Hash lock / Linux x64 (push) Waiting to run
CI / Hash lock / Windows x64 (push) Waiting to run
CI / test / Python 3.11 (push) Waiting to run
CI / test / Python 3.14 (push) Waiting to run
CI / frontend (push) Waiting to run
CI / Windows 11 ARM64 / Python 3.14 background lifecycle (push) Waiting to run
CI / Windows Server 2025 x64 / Python 3.14 background lifecycle (push) Waiting to run
CI / Windows desktop source lifecycle (push) Waiting to run
Wiki / validate (push) Waiting to run
Deploy Wiki / Deploy to Cloudflare Pages (push) Canceled after 0s
2026-10-08 03:11:00 +08:00
Haozhe Wu 5baa3d9d0b Merge PR #1709: feat(email): add optional password protection for PDF reports 2026-10-08 03:10:00 +08:00
Haozhe Wu 4eade6b6b2 Merge PR #1727: fix(options): use full-sample downside deviation for Sortino 2026-10-07 22:24:00 +08:00
Haozhe Wu b52c281b90 Merge PR #1725: test(loaders): wire shared OHLCV contract assertion into per-loader suites 2026-10-07 22:23:00 +08:00
Haozhe Wu 786de66549 Merge PR #1721: fix(governance): make archive ledger verification report corruption instead of crashing 2026-10-07 22:22:00 +08:00
Haozhe Wu 1858a6fdf1 Merge PR #1720: fix(hypotheses): honor a search limit of zero instead of returning one 2026-10-07 22:21:00 +08:00
Haozhe Wu 41e778d64d Merge PR #1719: fix(volatility): reject invalid Heston inputs before integration 2026-10-07 22:20:00 +08:00
Haozhe Wu a434cab9cf Merge PR #1718: fix(factormodel): report incomplete exposures as unmatched weight 2026-10-07 22:19:00 +08:00
Haozhe Wu c5fb1ba9f6 Merge PR #1717: fix(risk-xray): keep missing prices out of adjacent return pairs 2026-10-07 22:18:00 +08:00
Haozhe Wu 7aeee74c21 Merge PR #1716: fix(credit): retain scheduled CDS coupons before the final stub 2026-10-07 22:17:00 +08:00
Haozhe Wu 3848166ea7 Merge PR #1715: fix(regime): preserve unknown density for undefined correlations 2026-10-07 22:16:00 +08:00
Haozhe Wu 88bf074a53 Merge PR #1714: fix(crossvalidation): skip fully purged walk-forward folds 2026-10-07 22:15:00 +08:00
Haozhe Wu 7c987f1c01 Merge PR #1713: fix(timeseries): preserve observation gaps in OU lag pairs 2026-10-07 22:14:00 +08:00
Haozhe Wu 69a452ab6e Merge PR #1712: fix(benchmark): honor A-share exchange suffixes for every source 2026-10-07 22:13:00 +08:00
Haozhe Wu 74f0f1423e Merge PR #1711: fix(correlation): keep equity names out of crypto fallback chains 2026-10-07 22:12:00 +08:00
Haozhe Wu 18aa53bde3 Merge PR #1710: fix(correlation): align daily histories across source time zones 2026-10-07 22:11:00 +08:00
Haozhe Wu 3bec8b7d88 Merge PR #1708: fix(context): keep system prompt byte-stable across runs for prefix cache 2026-10-07 22:10:00 +08:00
Rudy Celekli fbf7e2f591 fix(benchmark): recognize Yahoo Shanghai suffix
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-07 09:38:08 -04:00
jacob-clobotandClaude Opus 5 e9f8d1c145 fix(kis): see SOR fills and recover from a server-invalidated token
Two defects made the KIS connector look like an empty, healthy account on
a live Korean brokerage account.

`get_open_orders` asked `inquire-daily-ccld` for EXCG_ID_DVSN_CD=KRX only.
Since Nextrade (NXT) opened as a second venue, brokers route most retail
orders through SOR, and the endpoint's venue buckets are DISJOINT rather
than nested: a live account returned 6 rows for KRX and 33 for SOR with
ZERO overlap. Every SOR-routed fill was invisible, so `open_orders` and
`executions` came back empty while the account had traded that morning.
Ask each venue in `_EXCHANGE_IDS_INQUIRY` and merge on (ord_dt, odno). A
venue the broker rejects is reported in `venue_errors` instead of hiding
the others' fills.

KIS issues ONE token per app_key, so a token minted for the other
environment — or by any other process sharing the key — silently
invalidates the cached one long before its reported `expires_at`. The
cache still looked valid, so every call failed with "기간이 만료된
token 입니다" until the file aged out. Detect that message, drop the
cache, and re-issue once.

Order placement still goes to KRX only; this changes the read path.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Signed-off-by: jacob-clobot <jacob@clobot.co.kr>
2026-10-07 19:01:16 +09:00
Jackzigen 25118412a3 test(loaders): dedupe imports, pin contract vocabulary, cover remaining loaders
Adversarial review follow-ups on #1725:

- The bulk wiring duplicated the loader import block in 17 files
  (identical adjacent 'from backtest.loaders...' lines). Remove the
  copies; ruff F811 never flagged them because both were used.
- _CONTRACT_REASONS was defined but never consulted, so a typo'd
  reason string would pass silently. bad() now asserts membership.
- Wire the shared contract into the 5 remaining per-loader suites
  (okx, wallex, zerodha, ccxt-perpetual, longbridge) so the claim
  'every per-loader suite' holds. okx and wallex are canary symbols
  in loader_health — exactly the drift-prone loaders to pin.

Full unit suite: 1813 passed, 71 skipped (4 OAuth/MCP env failures
and 6 akshare forex failures reproduce on clean upstream/main).

Signed-off-by: Jackzigen <Jackzigen@users.noreply.github.com>
2026-10-07 14:37:58 +08:00
Jackzigen b2ca55c598 test(loaders): wire shared OHLCV contract assertion into per-loader suites
Each per-loader test file pinned its canonical fixture with bespoke
assertions; the only shared schema check lived in the weekly health
lane. A data-source drift that renames/reorders columns or lets
non-finite values through now only breaks whichever bespoke assertions
happen to cover it, and can slip past review unnoticed.

Extract the canonical-frame checks from backtest/loader_health.py into
tests/loader_contract.py (one call, same failure vocabulary) and wire
it into every per-loader suite's canonical-frame test (24 files).

This is the first step of the #1723 roadmap: with every loader suite
asserting the same shared contract, a loader that emits a
non-conforming frame fails its own suite immediately instead of
waiting for the weekly health lane.

Closes #1723 (step 1/3)

Signed-off-by: Jackzigen <Jackzigen@users.noreply.github.com>
2026-10-07 13:56:05 +08:00
Rudy Celekli a4e5314312 fix: Count incomplete factor exposure rows as unmatched weight rather than measuring missing factors as zero.
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-06 09:19:44 -04:00
Rudy Celekli 5bd03149b3 fix: Compute risk-xray returns before calendar alignment so missing prices cannot fabricate multi-bar one-period returns.
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-06 09:19:39 -04:00
Rudy Celekli 7fcc22bb50 fix: Keep correlation density unknown when constant or missing series make asset pairs unmeasurable.
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-06 09:19:27 -04:00
Rudy Celekli b89c4e3836 fix: Skip walk-forward folds where purging leaves no training data, as promised by the splitter contract.
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-06 09:19:25 -04:00
Rudy Celekli 8639a21406 fix: Align daily correlation and regime bars by each source local calendar date before joining.
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-06 09:19:10 -04:00
Rudy Celekli e4c1419c8a fix: Use authoritative A-share exchange suffixes when choosing the strategy benchmark for any source.
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-06 09:15:30 -04:00
Rudy Celekli 9111a98145 fix: Reject non-finite Heston inputs and invalid integration bounds before an invalid integral can become a zero option price.
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-06 09:10:06 -04:00
Rudy Celekli 939e964488 fix: Keep CDS premium dates on the requested frequency and price a final stub for fractional maturities.
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-06 09:10:04 -04:00
Rudy Celekli 93602c2162 fix: Recognize crypto pair forms rather than routing equity names such as ABNB by bare quote suffix.
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-06 09:10:02 -04:00
Rudy Celekli ac9ea99258 fix: Preserve missing observations until OU lag pairs are built so a gap cannot become a one-step transition.
Signed-off-by: Rudy Celekli <47457359+rudycelekli@users.noreply.github.com>
2026-10-06 09:07:19 -04:00
Lanre Shittu 77fc417e55 fix(governance): make archive ledger verification report corruption instead of crashing
Signed-off-by: Lanre Shittu <136805224+Shizoqua@users.noreply.github.com>
2026-10-06 11:51:10 +00:00
Lanre Shittu a31e3a54ca fix(hypotheses): honor a search limit of zero instead of returning one
Signed-off-by: Lanre Shittu <136805224+Shizoqua@users.noreply.github.com>
2026-10-06 11:44:54 +00:00
JackzigenandClaude 1aaef8dd33 test(context): address review — drop dead memory_summary kwarg, pin envelope ordering
- Remove stale memory_summary= kwarg from test_system_prompt_format_succeeds
  (str.format tolerates excess kwargs, so it silently passed while masking
  a potential reintroduction of the field).
- Pin that the <agent-state> envelope stays a sibling prefix outside
  <user-message> tags when loop.py goal-context wrapping is active.

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-06 19:15:39 +08:00
JackzigenandClaude df776a1b75 fix(context): keep system prompt byte-stable across runs for prefix cache
WorkspaceMemory.to_summary() renders run_dir (fresh timestamp_uuid per
run) and tool counters (bumped every tool call). Rendering it into the
system prompt (## State section) meant the prompt bytes changed on every
turn and every tool call, invalidating the provider prefix cache for
everything after that point — including the cache_control block the
Anthropic adapter marks on the system message.

Move the volatile summary into the first user message wrapped in an
<agent-state> envelope (same convention as <recalled-memories>), drop
the ## State section from the template, and pin the new property with
tests: system prompt is byte-identical when only run_dir/counters
differ, and no counter or run-dir value reaches the system prompt.

Fixes #1707

Co-authored-by: Claude <noreply@anthropic.com>
2026-10-06 18:49:55 +08:00
zeus229 79f2ceb1a5 feat(email): protect scheduled PDF reports with password
Signed-off-by: zeus229 <69399886+zeus229@users.noreply.github.com>
2026-10-06 04:47:18 +00: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 785c757cd5 Merge PR #1706: respect US equity early closes 2026-10-06 00:51:16 +08:00
Haozhe Wu 440e0dd519 Merge PR #1702: preserve clean figures during answer correction 2026-10-06 00:51:15 +08:00
Haozhe Wu dfacbc841d Merge PR #1703: harden emergency cancel and flatten scans 2026-10-06 00:51:15 +08:00
Haozhe Wu 11c5c9afbc Merge PR #1704: keep live runner control attached to its scheduler 2026-10-06 00:51:15 +08:00
Rix 80e74cda55 fix(options): use full-sample downside deviation for Sortino
Signed-off-by: Rix <henrychao.ch@gmail.com>
2026-10-05 22:25:08 +08:00
Haozhe Wu 41376e3d00 test(pdf): verify RTL pagination independently of extraction order 2026-10-05 17:09:04 +08:00
Yufeng He d4c159808f fix(live): close the us_equity session at the early bell on half-days
MARKET_SPECS only modelled full-day holidays, so on NYSE early-close
days (day after Thanksgiving, weekday Christmas Eve) the market-hours
gate stayed open until 16:00 ET and the runner ticked a closed market
all afternoon: reconcile, agent invoke, audit.

_MarketSpec now carries an early_closes date -> bell mapping and
market_is_open_at resolves the close per date. The static table covers
the same 2026/2027 window as the holiday set.

Signed-off-by: Yufeng He <40085740+he-yufeng@users.noreply.github.com>
2026-10-05 16:05:24 +08:00
Romzhou a665113120 fix(live): keep the runner driver alive for the scheduler's lifetime
`_drive_runner` awaited `LiveRunner.run_loop()` to completion and then
returned. `run_loop` is fire-and-forget: it resolves the jobs, calls
`Scheduler.start()` — which only spawns the loop task — and returns. The
task wrapping the driver is the only handle `POST /live/runner/stop`
holds, and its `add_done_callback` unregisters the task the moment the
driver returns. The result is that a runner whose driver returned keeps
firing `run_once()` on its cadence while `stop` answers
`was_running: false`, so the loop is never torn down and cannot be
stopped through the API.

Park the driver on the scheduler's loop task instead, so the driver's
lifetime is the scheduler's lifetime. Cancelling the driver then
actually stops trading. Teardown goes through `Scheduler.stop()` in a
`finally`, tolerant of both sync and async `stop` implementations.

Both helper reads are `getattr`-defensive: neither `LiveRunner` nor
`Scheduler` publishes an accessor for the loop task, so private access
is the only option without widening the change. A runner whose `run_loop`
declined to start — no scheduler, or a missing or expired mandate —
leaves `_task` unset and returns immediately as before.

Adds five tests covering: the driver staying registered while the
scheduler runs, `stop` reporting `was_running: true` and actually
stopping the scheduler, stop idempotency after a real stop, async
`run_loop` teardown, and the preserved declined-start behaviour.

Signed-off-by: Romzhou <1962128849@qq.com>
2026-10-05 14:54:36 +08:00
Romzhou c312d5cb01 fix(live): harden the preemptive halt sweep against ledger failures and malformed broker records
Signed-off-by: Romzhou <1962128849@qq.com>
2026-10-05 14:10:09 +08:00
Yufeng He f8a5a63dae fix(grounding): hand the correction prompt the figures it should keep
A mixed rejection used to name only the failing figures. With 65 issues
on the table and nothing saying which values the gate had already
passed, the safest-looking play for the model was to rewrite whole
numeric sections as qualitative prose. zeus229's production run on #1622
lost a valid Risk X-Ray block and a portfolio-vs-benchmarks table that
way: the corrected draft passed, minus most of its numbers.

The gate now carries the measured figures that checked clean on the
ValidationResult, and the correction prompt tells the model to keep
them exactly as written: "only the figures listed above need work". A
spelling that fails anywhere in the draft is endorsed nowhere, and bare
integers stay off the list since an unchecked pass would vouch for
nothing.

Tests: three new pins in test_grounding_release.py, red before the fix
and green after (the keep list names the clean figures in document
order and none of the rejected ones; no section renders when nothing
passed; the list caps at 24 values and counts the rest). The 667
grounding tests and the full agent suite pass.

Ref #1622

Signed-off-by: Yufeng He <40085740+he-yufeng@users.noreply.github.com>
2026-10-05 13:18:24 +08:00
Haozhe Wu c214c0356d fix(grounding): keep recovery refs within figure kinds 2026-10-05 12:09:53 +08:00
Haozhe Wu ecc02039c8 Merge PR #1638: suggest real field refs for unknown call ids 2026-10-05 12:04:56 +08:00
Haozhe Wu f6e72428b7 fix: finish research prompts and grouped validation boundaries 2026-10-05 11:16:24 +08:00