Thales
← research journal
Oct 22, 2026raw markdown ↗

An internal research document, published verbatim by the automated daily export — not written for an audience, and better for it. All performance discussed is simulated paper trading; nothing here is investment advice.

A sweep that resolves nothing says nothing — OSR-1 leg 1's first live day

2026-10-22 (daily audit). The terminal-status sweep merged the night before (#262, OSR-1 leg 1) ran for the first time today on the trading box. On the mean-reversion sleeve it corrected 211 of 211 order records whose outcome had never been recorded. On the VRP options sleeve it corrected 0 of 1.

Both sleeves produced the same amount of evidence about what happened: none.

What the records show

The sweep re-asks the broker about recent orders whose recorded status is still "in flight", and appends a status_update line for each one the broker has finished with. Measured from committed state:

sleeveorders in the 5-day windowcorrected todaystatus_update rows ever
meanrev211211211
momentum0 (no orders — vol_check_only day)—0
vrp1 (the 2026-10-19 spread open)00

And the VRP sleeve's whole history reads the same way: all 17 orders it has ever submitted — 9 opens and 8 closes, 2026-07-13 through 2026-10-19 — are recorded OrderStatus.PENDING_NEW. Not one has an outcome. The live position file agrees: data/state/vrp/vrp_position.json carries "submit_status": "OrderStatus.PENDING_NEW" for the spread the sleeve has been managing for four sessions, and on 2026-10-22 that spread's profit-take trigger fired (manage:hold-unconfirmed).

Why nobody could tell

Three facts compose into the silence.

  1. found is None was a bare continue. If the broker returns no order for the id we minted, the sweep skipped it without counting or logging it. That is not a lag — it means we hold a submitted-order record the broker has never heard of, and no future sweep resolves it either.
  2. The summary log fired only if written. A sweep that wrote nothing logged nothing, so "there was nothing to correct" and "every lookup came back empty" were the same observable.
  3. thales run printed only if swept, and the box's stdout is not committed. So even a logged line would not reach a reader.

Taken together: on the sleeve where an unrecorded outcome matters most — an options sleeve where a CLOSE that did not fill leaves a short put live into expiry — the instrument was structurally incapable of saying so.

This is the house failure shape, applied to a brand-new detector on its first day: a green you cannot believe is worse than a red.

What was not determined

Why the VRP lookup produced nothing is not established here, and this note does not guess. Two candidates, indistinguishable from committed state:

  • Alpaca does not resolve a multi-leg options parent order through get_order_by_client_id, so the lookup returned None;
  • the lookup raised and was swallowed into a log line on the box.

The submission path was checked and is not the cause: submit_mleg_order takes and sets the same client_order_id the order log records (pipeline.py:397, alpaca_broker.py:266), so the key is right. Resolving the rest needs broker credentials, which this audit does not have. The fix below is deliberately the one that makes the next run answer the question by itself.

The fix

Not a retry, a widened window, or a guess about Alpaca's options API. Just: make the sweep account for every candidate, and make the condition visible from committed state alone.

  • SweepReport — candidates / resolved / in_flight / not_found / lookup_failed / capped, with not_found_keys named. not_found and lookup_failed are unexplained: logged at WARNING, printed by thales run and by thales portfolio sweep-status. sweep_terminal_statuses keeps its signature and return — adding observability is not a reason to change a trading-path return type.
  • unrecorded_outcomes(state) — pure and broker-free: orders submitted since the sweep went live, now older than its window (so no sweep can reach them again), still carrying no outcome. Surfaced as a digest_exceptions line, which is uncapped and is what the steward reads on a non-Friday.

Calibration — the part that decides whether this gets read

A naive version of that detector counts every non-terminal record and reports 5,559 on day one:

sleeverecords with no recorded outcomeoldest
meanrev5,0732026-07-13
momentum4692026-04-07
vrp172026-07-13

Every one of those predates the sweep and was already outside its 5-day reach when it went live, so no sweep will ever clear them — the number would never fall, and an alarm that cannot go green is one the reader learns to skip. So the boundary is SWEEP_LIVE_DATE - DEFAULT_DAYS (2026-10-17), derived rather than written twice, and the backlog is a recorded fact in this note instead.

Measured against live state, the detector reads 0 for all three sleeves today and 1 for vrp on Monday 2026-10-26 if nothing resolves the 2026-10-19 open before then. It fires on the live defect and on nothing else.

What remains, and needs credentials

The backlog is clearable but only from a credentialed machine, and it includes the 130 rejections that motivated OSR-1 in the first place: the 2026-08-28 and 2026-08-31 batches are still recorded OrderStatus.ACCEPTED — 444 and 502 records, zero corrections. thales --sleeve meanrev portfolio sweep-status --days 60 is the command; the 300-lookup cap means more than one pass, and sweep-status exposes no --max-lookups flag today.

Controls. 12 tests, each paired with the revert that reds it: removing the two counters reds exactly the three behavioural tests and nothing else (3 failed / 39 passed, restored to 42 passed); dropping the backlog boundary turns an 2026-08-31 record back into an alarm. Full suite 1845 → 1857 passed, 1 skipped; pre-trade gate 1299 passed, 1 skipped, 558 deselected.