trader.resilience.retrying module¶
Protocol-preserving retry wrappers for read-only adapters.
These classes implement the read Protocols and nothing else, on purpose. RetryingBroker satisfies BrokerAdapter but not OrderPlacingBroker, so it cannot be handed to OrderExecutor and cannot be made to retry a submission. That matters more than it might look: a timeout on submit_limit_buy is not evidence the order failed to reach Alpaca, so a retry can place a second one. This project has already paid for a duplicate order once, on a live paper account, and a comment asking future code not to retry writes is weaker than an object that has no write to retry.
There is also no __getattr__ passthrough. A wrapper that forwarded unknown attributes would re-expose the wrapped broker’s submit_limit_buy and undo the whole guarantee, silently.
What is not covered here. Broker reads made inside a cycle (run_once reads positions, orders, and the account) keep the raw order-placing broker, because a read-only wrapper cannot be passed where an OrderPlacingBroker is required. Those are covered by the daemon’s cycle-level catch-all and its backoff instead — one failed read costs one cycle, not the process. Market data is the flakiest dependency and is wrapped, so a yfinance blip is absorbed inside the cycle rather than discarding it.
- class trader.resilience.retrying.RetryingBroker(broker, *, attempts, base_seconds, sleep=<built-in function sleep>)[source]¶
Bases:
objectBrokerAdapter with bounded retry. Holds no order-placing method.
- Parameters:
broker (BrokerAdapter)
attempts (int)
base_seconds (int)
sleep (Callable[[float], None])
- get_asset(symbol)[source]¶
Asset metadata, retried on transient failure.
- Parameters:
symbol (str)
- Return type:
TradableAsset | None
- class trader.resilience.retrying.RetryingMarketData(provider, *, attempts, base_seconds, sleep=<built-in function sleep>)[source]¶
Bases:
objectMarketDataProvider with bounded retry.
Wrapped where the broker’s in-cycle reads are not, because this one is genuinely flaky: yfinance is an unofficial scrape with no availability guarantee, and losing a cycle to one failed bar fetch is avoidable.
- Parameters:
provider (MarketDataProvider)
attempts (int)
base_seconds (int)
sleep (Callable[[float], None])
- get_quote(symbol)[source]¶
The latest quote, retried on transient failure.
- Parameters:
symbol (str)
- Return type:
- get_history(symbol, start, end, interval=None)[source]¶
Historical bars, retried on transient failure.
interval defaults to None here rather than to “1d” so an omitted argument reaches the provider omitted, and the provider’s own default stays the single definition of it. Duplicating “1d” here would mean two places to change it, one of which nobody would remember.
- Parameters:
symbol (str)
start (date)
end (date)
interval (str | None)
- Return type:
list[Bar]