Skip to content

Paper-only execution-capacity harness for Alpaca order actions (rate-limit-adaptive, websocket state) - #165

Merged
seathatflowsinourveins merged 3 commits into
mainfrom
claude/order-throughput-20260924
Sep 24, 2026
Merged

seathatflowsinourveins merged 3 commits into
mainfrom
claude/order-throughput-20260924

Conversation

@seathatflowsinourveins

Copy link
Copy Markdown
Collaborator

Adds blueprints/us-equities/order-throughput/, a paper-only execution-capacity harness for Alpaca order actions. It measures how many order actions per minute the paper account sustains. It generates no strategy trades: the adaptive-paper README says "no strategy manufactures trades to hit a throughput target", and its orders are never counted as trades.

What it does

  • Rate budget. The budget is floor(min(cap, trading x-ratelimit-limit) × 0.9). The limit is read from a preflight call to the trading endpoint only, so the market-data endpoint's 10000 limit never sets it. A token bucket, a hard rolling 60 s count and a remaining/reset guard all apply. A 429 freezes all calls and backs off using Retry-After, then the reset time, then exponential delay. The same code runs at 200/min and at 1000/min once the header rises (for example on Elite or a non-retail account).
  • Order state. State comes from the trade_updates websocket. REST calls are spent on submits and cancels, with one bounded reconciliation at the end. Ambiguous submits are never resent.
  • Default plan. It places 1-share non-marketable limit buys far below the bid and cancels each one individually. Cancel-all is impossible through the reused GuardedSession, which allows DELETE only on /v2/orders/{uuid}. The code path exists only behind a proven-no-foreign-orders guard.
  • Safety. It refuses non-paper URLs and honours safety.DEFAULT_STOP. It holds the adaptive-paper account lock, and it refuses to start while unacknowledged positions or orders exist or adaptive-paper trial state is present. Totals, duration, open orders and notional are capped. Cleanup always runs.
  • Rate-limit evidence. rate-limit-evidence-20260924.json records:
    • the 4 Alpaca sources: usage limit, raising it, Elite and paper trading;
    • the repository-observed headers: trading 200 (419 observations), data 10000 (9), each with its file;
    • the round-trip arithmetic.

Evidence class: offline fixture only. No Alpaca call was made.

  • On this host (threadripper4090-nativestack), the pinned runtime is installed from adaptive-paper/requirements.txt: Python 3.12.3, nautilus-trader 2.0.0rc5 and alpaca-py 0.44.0.
  • tests.test_order_throughput: 60 OK.
  • test_adaptive_*: 671 OK (skipped=1). With the SDK present, 191 formerly skipped tests now run.
  • scripts/validate.py and validate_catalogs.py pass.
  • The only failure in the full suite is the host-only test_effort_default_guard.test_shipped_guard_is_verbatim, caused by a stale ~/.claude hook. It also fails on plain main.

Review. Two independent read-only reviewers covered broker side effects and safety, and correctness and measurement validity. They raised 12 findings, one of them high: an action was counted when dispatched, not when its outcome was known. All were fixed in 6b57b93, with 16 new regression tests.

Not yet done

  • There is no native_paper receipt. The first run needs a private paper credential file on the running host.
  • The acceptance criteria in the README (≥170 submits/min for 5 windows, 0 unhandled 429s, 100% stream completeness, clean reconciliation) have not been observed yet.

🤖 Generated with Claude Code

Scout and others added 2 commits September 24, 2026 02:18
blueprints/us-equities/order-throughput measures sustained order actions
(REST submits + individual cancels) per 60 s on an Alpaca paper account,
with order state taken from the trade_updates websocket and a bounded REST
reconciliation at the end. It is an execution-capacity qualification only:
probes are non-marketable 1-share limit BUYs below the bid, cancelled
individually, and receipts state they are never strategy trades.

- rate_governor: budget = floor(min(cap, observed trading x-ratelimit-limit)
  * headroom); token bucket + rolling 60 s cap + x-ratelimit-remaining/reset
  reserve; 429 freezes and backs off per Retry-After/reset/exponential; a
  rising header lifts the budget up to the cap (same code at 200 and 1000).
- capacity: engine, bounds, STOP (adaptive-paper DEFAULT_STOP), account
  lock, adaptive-lane conflict guard, acknowledged-exposure refusal,
  cancel-all guard (off by default), cleanup on exit/signal/exception with
  verified zero open harness orders, reconciliation, receipt and CLI.
- alpaca_capacity_port: native paper port reusing adaptive-paper transport
  (GuardedSession, preflight, trade_updates stream class) read-only.
- capacity_fixture: offline fake clock/broker/stream (offline_fixture).
- rate-limit-evidence-20260924.json (+ rate_limit_evidence.py --check):
  cited limits, 419 trading:200 / 9 data:10000 headers measured from the
  retained trial outputs, and submit/cancel/round-trip arithmetic.

Tests: tests/test_order_throughput.py (44 offline tests). The native port
has not been run against Alpaca or the pinned SDK in this change.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Fixes from review of the paper execution-capacity harness:

- _collect records a failing in-flight future instead of raising, so
  cleanup always sends cancels, sweeps by prefix and verifies; a failed
  submit becomes ambiguous and the first port defect fails the run.
- Cleanup's deadline is 60 s of unfrozen time: a 429 backoff extends it
  up to a hard ceiling (timeout + 3 x max backoff), with up to 3
  sweep/verification rounds; failing steps are recorded, not fatal.
- Every page of an order listing is admitted by the governor
  (list_orders takes an admit callback in the native port and fixture).
- Sustained capacity counts only completed order actions (2xx submits
  and cancels); attempted actions are reported separately.
- Websocket completeness includes orders the final broker listing proves
  existed, e.g. an ambiguous submit whose order was created.
- acceptance.passed requires the frozen criteria (>= 5 windows, ratio
  >= 0.85) and no health freezes; it is marked self-reported and the
  README requires an independent observation for native acceptance.
- A 0600 exclusive JSONL journal (prefix fsynced before any order,
  intents before each POST) plus recover/audit commands for crash
  recovery.
- Receipt provenance: git revision, source hashes, SDK and Python
  versions, sanitized argv, end time and exit code.
- Stream and REST completion times are stamped on their own threads; the
  quote refresh runs on a worker.
- The session reserve covers stream start, the cleanup ceiling,
  reconciliation and a margin.
- The script entry point runs through the importable module, so the
  ports' capacity.Response is the engine's class (as __main__, completed
  actions were uncounted and sweep cancels failed).

Tests: 60 offline tests (16 new), including multi-inflight out-of-order
completion, a real ThreadPoolExecutor, a created order with a lost
response, crash then journal recovery, and the script entry point.

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

chatgpt-codex-connector Bot commented Sep 24, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-24T06:52:06.101740Z 6b57b93 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6b57b9303a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread blueprints/us-equities/order-throughput/capacity.py
Comment thread blueprints/us-equities/order-throughput/alpaca_capacity_port.py
Comment thread blueprints/us-equities/order-throughput/alpaca_capacity_port.py Outdated
Comment thread blueprints/us-equities/order-throughput/capacity.py
Comment thread blueprints/us-equities/order-throughput/capacity.py
Comment thread blueprints/us-equities/order-throughput/rate_governor.py Outdated
…ght, full Retry-After

- Reconciliation compares the whole nonzero-position snapshot with the
  preflight (all_positions_unchanged, changed_position_symbols), not only
  the probe symbol.
- Quotes carry ts_ns from normalize_quote; a missing, stale (>60 s,
  max_quote_age_seconds) or future-dated quote refuses the run, and a stale
  refresh freezes submissions.
- recover uses a trading-only recovery_preflight (GET /v2/account) so a
  market-data outage cannot block cancelling a crashed run's orders.
- Broker-designated Retry-After/x-ratelimit-reset delays are honoured in
  full; max_backoff caps only the exponential fallback, and a longer broker
  delay stops submissions (rate_limit_backoff_exceeds_max).
- README cites the Trading API reference for after_order_id and states the
  max_http_429 tolerance semantics.

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant