fix: read the data feed through the Tradier wrapper — live volume was 80-160x

With BROKER=tradier the loop's `client` is a TradierClient that delegates
market data to the Alpaca client in `data_client`. Two places read the feed
as getattr(client.settings, "feed", "iex"). TradierSettings has no feed, so
both read "iex" even though the container runs ALPACA_DATA_FEED=sip (verified
in the running loop and in config_overrides):

  - step_vratio kept computing IEX->SIP ratios as if on the free feed
  - ingest_live_minute_bars multiplied the real SIP volume by those ratios

Checked against the paper stack's SIP bars for the same minutes: prices are
identical and unscaled volume matches 1.00x, but scaled rows run x83 (GLND),
x117-126 (GRML) and x163 (SKYQ). The 2026-09-25 GRML signal logged a
cum_volume of 1.39 billion shares and an rvol of 64.6. For any name with a
ratio, every volume gate — rvol, the 300k day-volume floor, min dollar
volume, the 2.5%-of-volume liquidity cap, and the gap x rvol ranking — has
been reading inflated numbers since the stack went live on 2026-07-31.

data_feed() reads through data_client when present. The regression test
wraps a SIP client in a TradierClient and fails without the fix.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
momentum devandClaude Opus 5.5 committed 2026-09-25 11:14:11 -05:00
1 parent e2e9687c45
commit 7f1ebe9cab
3 files changed
+30 -2

No files matched your search

+16
View File
@@ -94,3 +94,19 @@ def test_sip_feed_refuses_double_scaling():
flat = [v for row in con.rows for v in row]
assert 2500 in flat and 62500 not in flat # sip volume kept, NOT re-scaled
assert "alpaca_sip" in flat and "alpaca_iex_scaled" not in flat
def test_tradier_wrapper_reads_the_wrapped_feed():
# the live Tradier stack wraps the Alpaca data client; the wrapper's own
# settings have no `feed`, which used to read as "iex" and re-scale real SIP
# volume by the IEX ratios (the 80-160x live over-count, 2026-07-31..09-25)
from tradier_broker.client import TradierClient
from tradier_broker.settings import TradierSettings
wrapped = TradierClient(TradierSettings(access_token="t", account_id="a"),
data_client=_SipClient())
con = _Con()
ingest_live_minute_bars(con, wrapped, ["GOOD"], volume_scale={"GOOD": 25.0})
flat = [v for row in con.rows for v in row]
assert 2500 in flat and 62500 not in flat
assert "alpaca_sip" in flat and "alpaca_iex_scaled" not in flat