from app.bars.models import Bar, Timeframe from app.bars.store import InMemoryBarStore def bar(t, close=1): return Bar(Timeframe.M1, t, 1, 2, 0, close, 10, False, "ES=F", "replay") def test_store_replaces_forming_bar_and_bounds_history(): store = InMemoryBarStore(2) store.put(bar(60)) store.put(bar(60, 2)) store.put(bar(120)) store.put(bar(180)) assert [value.t for value in store.get(Timeframe.M1)] == [120, 180] assert store.get(Timeframe.M1, 1)[0].t == 180 def test_a_closed_bar_replaces_its_bucket_behind_the_tail(): # Ticks open the next minute before the exchange's own bar for the previous # one arrives. Matching only the tail dropped it, leaving the tick-built # approximation — with its partial volume — in place permanently. from app.bars.models import Bar, Timeframe from app.bars.store import InMemoryBarStore store = InMemoryBarStore(100) common = dict(tf=Timeframe.M1, symbol="/ES", source="schwab") store.put(Bar(t=60, o=1, h=2, l=1, c=2, v=5, closed=False, **common)) store.put(Bar(t=120, o=2, h=3, l=2, c=3, v=1, closed=False, **common)) # The authoritative bar for the first minute, arriving late. store.put(Bar(t=60, o=1, h=9, l=1, c=4, v=400, closed=True, **common)) held = store.get(Timeframe.M1) assert [b.t for b in held] == [60, 120] assert held[0].closed is True assert held[0].v == 400, "the exchange's volume must win over the tick estimate" def test_a_tick_cannot_overwrite_a_settled_bar(): from app.bars.models import Bar, Timeframe from app.bars.store import InMemoryBarStore store = InMemoryBarStore(100) common = dict(tf=Timeframe.M1, symbol="/ES", source="schwab") store.put(Bar(t=60, o=1, h=9, l=1, c=4, v=400, closed=True, **common)) store.put(Bar(t=60, o=1, h=2, l=1, c=2, v=5, closed=False, **common)) held = store.get(Timeframe.M1)[0] assert held.closed is True and held.v == 400