Skip to content

Incentive monitor (market + non-market signals) and a preregistered paper forward study - #187

Merged
seathatflowsinourveins merged 7 commits into
mainfrom
claude/incentive-monitor-20260924
Sep 25, 2026
Merged

seathatflowsinourveins merged 7 commits into
mainfrom
claude/incentive-monitor-20260924

Conversation

@seathatflowsinourveins

Copy link
Copy Markdown
Owner

What

  • blueprints/us-equities/incentive-monitor/monitor.py is a continuous, data-only recorder. It never places orders. It records:
    • SIP snapshots of every active tradable US equity (REST, about 24 calls per sweep against the measured 10,000/min data limit);
    • OPRA option trades for every contract (websocket *, msgpack), aggregated per root, with large prints kept;
    • Benzinga news (websocket *);
    • SEC EDGAR current filings (8-K, 6-K, Schedule 13D, SC TO-T, 425, S-1, 424B4; declared contact sent to SEC only);
    • Nasdaq Trader halts.
  • The monitor also:
    • builds an unvalidated early-stage board with fixed weights;
    • publishes incentive_symbols and its own code hash, start time and stream downtime;
    • after a restart, rebuilds the session's state from its own files.
  • forward-protocol-v1.json plus board_scan.py form a paper forward study, incentive-board-forward-v1-20260924, frozen before its first order. Its design:
    • decisions at 10:30 and 13:30 ET;
    • at most 5 operating companies with a non-price incentive and a fresh-snapshot gain of 0–10%;
    • 4 incentive-free controls per selected name from the same gain bucket, never shared across the day;
    • an exclusive decision ledger (no re-rolls), with a record for every refusal;
    • sha256 bindings for the code, the running monitor, the engine files, the pinned configs and the scan;
    • a single analysis point with the bootstrap and RNG fixed.
  • Execution goes through the merged adaptive-paper mover trial mode (Mover trial mode for the adaptive NautilusTrader paper engine (SYN-verified; paper needs an isolated account) #172): exit X2, 200 USD per entry, 1x, and its own state root.

Review trail (all before any order)

  1. Pre-outcome review of 920edde3: no-go, 19 findings. Resolved in 532e4b5f.
  2. Re-review: no-go, N1–N9. Resolved in 1fba0f36 and 32a0c205.
  3. Final check: go, with two conditions: the running monitor's code hash is bound, and the engine runs only on the recorded scan hash. Both are enforced in 07c74015.

The gate_relation follows the revised live gates in #183.

Evidence

  • python3 -m unittest tests.test_incentive_monitor tests.test_incentive_forward: 34 OK.
  • Full python3 -m unittest: 3,978 OK, 419 skipped.
  • scripts/validate.py and evidence_manifest.py --check: passed.
  • Live dry runs on 2026-09-24 (timing guard bypassed in the harness only; no order) ran end to end in about 5 s:
    • 1 then 5 names selected, with 4 then 20 matched controls;
    • 6,581 operating companies;
    • the engine's own mover_runner.py check returned valid with the pinned config sha256;
    • the scan hash matched the decision record.
  • Monitor entitlements measured with a paper key of an Algo Trader Plus user:
    • data REST limit header 10,000/min;
    • OPRA wildcard at about 920 trades/s;
    • news wildcard connected;
    • the SIP stock stream is left to the engine (one connection per endpoint).

Limits

  • The board weights are heuristic, fixed without outcome data.
  • Paper fills are simulated.
  • Licensed data stays private; nothing per-event is committed.

🤖 Generated with Claude Code

…and a preregistered paper forward study

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…t order

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…, exclusive ledger, operating companies, exact analysis)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…isions within 90 minutes of an early close

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…cans, full Trust disclosure, retry rule

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
…separate from paper performance

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

@seathatflowsinourveins

Copy link
Copy Markdown
Owner Author

CI note (2026-09-25). validate-macos became a required check on main today (#226 and ruleset 23739774). This PR's latest CI run predates that change, so it has no validate-macos status, and GitHub shows the check as expected and waiting.

Nothing in the PR needs to change. The next push, or a close and reopen, runs the current adoption-bootstrap.yml, which reports validate-macos on every pull request.

🤖 Generated with Claude Code

@seathatflowsinourveins seathatflowsinourveins added the lane:trading Trading lane: sim, paper and live north star label Sep 25, 2026
…onflicts)

Brings the branch onto main 5b6014e so CI, including the required
validate-macos check, runs on the current workflows.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@seathatflowsinourveins

Copy link
Copy Markdown
Owner Author

Trading lane, 2026-09-25: carrying this PR to merge.

Under the agreed lane split this PR is trading-lane work, and it has had no commits since 2026-09-24. The trading-lane coordinator is carrying it, per the user's approval of dormant-owner merges. The original owner can still take it back by replying here.

What changed:

  • main (269602b) was merged in as 14bf5fc. The merge was clean and there was no force-push.
  • The PR adds files only.
  • The push re-runs CI on the current workflows, including the required validate-macos check.

Checks on the merged tree:

  • tests.test_incentive_monitor tests.test_incentive_forward: 34 OK, 0 skipped, on both system Python and the pinned adaptive-paper runtime (Python 3.12.3, nautilus-trader 2.0.0rc5).
  • scripts/validate.py, evidence_manifest.py --check and validate_convergence.py --all-recorded pass.

After the engine P0 release (#221, #242, #243):

I'll merge once the required checks pass. #220, which is stacked on this PR, will then be retargeted to main.

🤖 Generated with Claude Code

@seathatflowsinourveins
seathatflowsinourveins merged commit 3e4054d into main Sep 25, 2026
24 checks passed
@seathatflowsinourveins
seathatflowsinourveins deleted the claude/incentive-monitor-20260924 branch September 25, 2026 20:01
seathatflowsinourveins pushed a commit that referenced this pull request Sep 25, 2026
… merge

#187 was squash-merged as 3e4054d, so its files were added on both sides.
The five files this PR changes conflicted and resolve to this PR's head
(1f136ba) byte for byte. The merged tree differs from main by exactly this
PR's own delta over #187 (05c2849..1f136ba; 5 files, +3529/-122). Main's
monitor.py and board_scan.py still match FROZEN_V1.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
seathatflowsinourveins pushed a commit that referenced this pull request Sep 25, 2026
…1 as a v2 input

board_scan.ENGINE_FILES hashes 8 engine files. The transitive import closure
of mover_runner.py within adaptive-paper/ adds 14 more modules that the list
omits, measured on main after #187:
- 4 existed when v1 froze (05c2849) and have changed since;
- 6 are unchanged since the freeze;
- 4 were added after it, including corporate_actions and financing from the
  engine P0 release.

The v1 bridge is frozen, so the gap stays in v1 as a recorded limitation.
Protocol v2 should bind the whole engine (every *.py, or a clean-checkout
tree hash) plus the runtime lock before its pre-outcome review. No v1 order
has been placed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
seathatflowsinourveins added a commit that referenced this pull request Sep 25, 2026
…, 20 s sweeps, option IV, FINRA short volume (board v2) (#220)

* Incentive monitor (market and non-market signals, early-stage board) and a preregistered paper forward study

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Forward study: amendments from the pre-outcome review before the first order

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Forward study: second pre-outcome review amendments (subject-only M&A, exclusive ledger, operating companies, exact analysis)

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Forward study: schedule on Alpaca calendar trading days, skipping decisions within 90 minutes of an early close

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Forward study: refuse boards from unbound monitor code, clear stale scans, full Trust disclosure, retry rule

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Forward study: gate relation as a prospective out-of-sample holdout, separate from paper performance

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Incentive monitor v2: status/LULD stream, corporate-action events, screener, option chains, FINRA short volume, budgeted sweeps, board v2

Sources added to monitor.py, each recorded with receive times in owner-only files and held to an explicit per-source
call budget written to monitor.jsonl:
- IEX stock stream (v2/iex; v2/sip stays with the engine): statuses, LULD bands and imbalances for every symbol,
  merged with the Nasdaq RSS into one halt state (latest event by its own time wins); message counts per type and
  tape measure tape coverage (CTA statuses on IEX are unobserved so far). A host lease per stream endpoint refuses a
  second holder before it connects; a 406 on the IEX endpoint waits instead of contending.
- Corporate-action events (SSE on the documented stream host): every event archived, deduplicated by ULID event id,
  resumed with Last-Event-Id; splits, mergers, spin-offs and name/symbol changes surfaced as board context from a
  bounded 30-day replay plus the live stream.
- Screener: most actives by volume and by trades, top movers (3 calls per sweep).
- Option chain snapshots for the top 25 candidates by the v1 score (one page each), near-the-money implied volatility
  and a per-root IV change against the previous session (same expiry) or the first value today; open interest from
  the contracts endpoint once per root per day.
- FINRA daily consolidated short sale volume: at most one request per sweep, after 18:05 ET, stored once with a
  manifest; header and trailer count checked.
- Sweep cadence 20 s by default; the plan is refused (exit 2) above 5% of the 10,000/min data limit, above 5% of the
  200/min trading limit, or with the Nasdaq RSS polled more than once a minute; a call over its source cap is refused
  before any request.

Board v2 (board-v2.json, board_version 2) keeps every v1 component and weight (score_v1) and adds fixed, unvalidated
components: stream_news_halt 2.0, stream_volatility_halt 1.0, corporate_action 0.5, iv_runup 1.0,
short_volume_high 0.5. board.json stays board version 1. board_scan.py refuses any board whose board_version differs
from the protocol's (forward protocol v1 pins 1; the frozen protocol file is unchanged).

Evidence: synthetic fixtures and one local-integration once-sweep against a synthetic response router (no network);
docs.alpaca.markets and FINRA pages re-read 2026-09-24; the monitor was not run against live endpoints.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Incentive monitor v2: run beside v1 as a follower, session-gated IV, review fixes

Resolve the two independent reviews of 736c555.

- Coexistence: every run declares --standalone or --follow-v1 V1_OUT. A follower
  holds no news/OPRA stream, polls neither EDGAR nor the Nasdaq RSS (zero budgets),
  reads version 1's appended lines and writes board-v2.json only. --standalone
  refuses while a version 1 monitor runs on this host (/proc). Leases live in one
  fixed per-user directory. The stream backoff resets only after data or 60 s
  connected, and 402/405/409/410 stop a stream.
- Options: chains and IV sampled 09:45-16:00 ET only. The previous-session
  baseline is the last in-session row, the first-today baseline is per expiry,
  and IV older than two sweeps no longer counts. The expiry window is 35 days
  (it always holds a monthly), an empty in-band chain is retried once without
  the band, and a chain poll has a deadline. Open interest is opt-in and paused
  near the trading limit.
- Boards: one scoring pass feeds both boards, and board.json is written before
  any v2 work, which is guarded (board_v2_error). Halts keep v1 precedence
  across sources, and any RSS halt today blocks stream_volatility_halt.
- Corporate actions: US region only, first-insert time kept, and malformed
  symbols ignored. The archive resumes from its last id whatever its age and
  records ca_resume_gap only when that id is not redelivered. An empty archive
  seeds from the retained history; the context replay is bounded and runs on
  the stream thread.
- FINRA: every failure waits an hour. Each stored file is checked once more
  after the next publication, and superseded versions are kept.
- Budgets: the daily-bar load resumes at the failed request under a
  per-minute cap, and --rss-seconds 0 is refused.
- Halts: a multi-day halt enters the merged state, and a moved resumption
  replaces the earlier one.
- Frozen v1: the monitor refuses to run beside protocol v1's frozen bridge,
  and board_scan refuses protocol v1 decisions under non-frozen code
  (code_not_frozen).

Evidence (synthetic fixtures / local integration, no network): 121 tests OK,
0 skipped, under python3 and the pinned engine venv; scripts/validate.py passed.
Every new test fails against 736c555, and 54 fix-revert mutants plus the
builder's 10 are all killed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Incentive monitor README: record the engine binding gap of protocol v1 as a v2 input

board_scan.ENGINE_FILES hashes 8 engine files. The transitive import closure
of mover_runner.py within adaptive-paper/ adds 14 more modules that the list
omits, measured on main after #187:
- 4 existed when v1 froze (05c2849) and have changed since;
- 6 are unchanged since the freeze;
- 4 were added after it, including corporate_actions and financing from the
  engine P0 release.

The v1 bridge is frozen, so the gap stays in v1 as a recorded limitation.
Protocol v2 should bind the whole engine (every *.py, or a clean-checkout
tree hash) plus the runtime lock before its pre-outcome review. No v1 order
has been placed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

* Incentive monitor tests: route and count fake responses by parsed hostname (CodeQL)

CodeQL flagged py/incomplete-url-substring-sanitization at four places in
tests/test_incentive_monitor.py: "nasdaqtrader.com" in url and "sec.gov" in u.
A substring test also matches a lookalike host or a query string. A host_is()
helper now compares urlsplit(url).hostname with the domain and its
subdomains. The router, both URL-count assertions and the unflagged sec.gov
assertion use it. host_is rejects ?u=nasdaqtrader.com,
nasdaqtrader.com.evil.example and notsec.gov. 121 tests pass on system
Python and on the pinned runtime.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: seathatflowsinourveins <234074349+seathatflowsinourveins@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-authored-by: Scout <scout@local>
seathatflowsinourveins added a commit that referenced this pull request Sep 25, 2026
… incentive board and data lake, and the recounted WSL host (#288)

- simulation: 866 to 884 fills per min at 70 ms exact release, 30 of 30
  minutes, and 672 at 1 s (#254, sim-capacity/receipts/20260925-elite-tier.json).
- paper: adds the margin financing model (#243); still blocked on the
  paper keys (HTTP 401).
- mover-early-entry-studies: v1 to v3, with the v3 core merged (#190) and not
  frozen.
- New gates:
  - incentive-board-forward (#187, #220): 0 orders;
  - data-lake-source (#208): minute-bar pilot not run.
- wsl-workstation-host: the foundation lane's wording. Counts were recounted
  on main 0074a0c by the last independent_session verdict per receipt,
  superseded excluded: 69 receipts, 56 agree, 1 needs changes, 0 awaiting
  review, 12 superseded (#285).

The foundation lane acked the strings and the recount rule.

Co-authored-by: Scout <scout@local>
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

lane:trading Trading lane: sim, paper and live north star

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant