Skip to content

feat(finance): add a bounded retry policy for transient venue refusals - #6752

Merged
loopx-agent merged 2 commits into
mainfrom
codex/finance-transient-retry
Oct 17, 2026
Merged

loopx-agent merged 2 commits into
mainfrom
codex/finance-transient-retry

Conversation

@loopx-agent

Copy link
Copy Markdown
Collaborator

Why

A venue refuses an order either transiently (rate limit, request timeout) or terminally (insufficient balance, invalid precision). Retrying is only safe when the executor has already proven that the previous attempt produced no effect — so the decision needs a policy that takes that observation rather than a bare loop. Every adapter otherwise re-implements this ad hoc, and the usual bugs are retrying terminal refusals or re-submitting after a delayed fill.

What

packages/loopx-finance-execution gains transient_retry:

  • classify_venue_refusal(message) → retryable / terminal over a fixed set of public signals (rate limit, request timeout, 稍后重试, try again). Unknown or empty text is terminal.
  • RetryPolicy(max_attempts=4, waits_seconds=(12,25,35), max_total_seconds=150) validates its own bounds.
  • may_retry(...) returns (allowed, reason) with stable tokens: venue_effect_observed, attempt_budget_spent, time_budget_spent, refusal_not_retryable, operation_expired, retry_admissible.
  • next_wait_seconds(policy, attempt) gives the backoff, with the last entry repeating.

Boundaries

Pure functions: no IO, no credentials, no venue call, no execution authority. The adapter still owns submission and the readback that feeds venue_effect_observed.

Verification

/Users/huangruiteng/Developer/loopx/.venv/bin/python -m pytest tests/extensions/test_finance_transient_retry.py -q
8 passed

Covers rate-limit/timeout classification, terminal refusals, a visible effect blocking any retry, attempt and time budgets, the operation deadline, the backoff schedule and policy validation.

A venue refuses an order for transient reasons (rate limits, request
timeouts) and for terminal ones (insufficient balance, invalid precision).
Retrying a submission is only safe when the executor first proves the earlier
attempt produced no effect, so the decision helper takes that observation
instead of assuming it.

classify_venue_refusal() maps a bounded set of public refusal signals to
retryable/terminal and treats anything unknown as terminal. RetryPolicy fixes
the attempt budget, the backoff schedule and a wall-clock ceiling, and
may_retry() returns a stable public token explaining the decision - visible
effect, spent attempt or time budget, non-retryable refusal, or an operation
deadline already reached.

The module performs no IO, classifies no private material and grants no
execution authority; venue adapters keep the actual submission and readback.

Signed-off-by: LoopX Agent <337587101+loopx-agent@users.noreply.github.com>
@loopx-agent
loopx-agent merged commit 6da1b46 into main Oct 17, 2026
5 of 8 checks passed
@loopx-agent
loopx-agent deleted the codex/finance-transient-retry branch October 17, 2026 15:11
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