Review sweep: money-path fixes + security + delete 805MB dead weight
Consolidated 4-tool review (2 correctness agents + Codex + over-eng audit). Money-path (regression-tested): - _flatten_all: moved the fresh-broker close from close_session INTO the shared function + added a broker-held guard on entry cancellation, so the daily-loss CIRCUIT BREAKER (which called _flatten_all raw) no longer strips a just-filled bracket's legs or leaves a sync-gap fill naked. One guard, all callers. - restart state rebuild: _fresh_entries cap, _requested_symbols dedup, and losing benches now rebuild from today's events on boot — a mid-session restart no longer resets the cap to 0 or re-fires a resting order into a duplicate (the 2026-07-06 incident). - POST /orders no longer retries a lost-response URLError (was re-sending duplicate live orders); GET/DELETE still retry. - expire_stale_entries now @_locked (raced the trigger thread). - _session_open: ET conversion instead of a hardcoded 13:30-13:33Z window that only matched EDT — the fast path armed nothing all winter. Security: - admin panel fail-CLOSED on empty ADMIN_TOKEN (was fail-open on a panel fronting the docker socket); header-only token, constant-time compare. - admin API responses redact secret override VALUES (live keys would have echoed after a paper->live switch). - dashboard: removed wildcard CORS (cross-origin drive-by could drive trade actions); optional DASHBOARD_TOKEN gate on POST. Deletions (~805MB + dead code shipped in the prod image): momentum- rebuilt.zip, archive venv/htmlcov, and schwab/ core/ telemetry/ models/ runtime/providers/ storage/replay.py controlroom/ + three dead evaluation stubs + package.json — all verified zero-importer. +4 regression tests. 99 money-path/trigger/exit tests green. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
1 parent
cad9051a96
commit
d54a2a930c
28 files changed
+210
-1789
No files matched your search
@@ -231,3 +231,31 @@ def test_reconcile_seeds_from_persisted_snapshot_after_restart(store):
|
||||
rows = _closed(store)
|
||||
assert len(rows) == 1 and rows[0]["symbol"] == "REST"
|
||||
assert rows[0]["realized_pnl"] == 5.0 # (2.5 - 2.0) * 10
|
||||
|
||||
|
||||
def test_post_not_retried_on_urlerror(monkeypatch):
|
||||
"""Lost-response URLError on POST /orders must NOT re-send (duplicate live
|
||||
order, 2026-07-06). GET/DELETE still retry."""
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
from alpaca_paper.client import AlpacaPaperClient
|
||||
from alpaca_paper.settings import AlpacaPaperSettings
|
||||
cli = AlpacaPaperClient.__new__(AlpacaPaperClient)
|
||||
cli.timeout = 1
|
||||
cli.max_retries = 2
|
||||
cli._headers = lambda: {}
|
||||
calls = {"n": 0}
|
||||
|
||||
def boom(req, timeout=None):
|
||||
calls["n"] += 1
|
||||
raise urllib.error.URLError("connection reset")
|
||||
|
||||
monkeypatch.setattr(urllib.request, "urlopen", boom)
|
||||
import pytest
|
||||
with pytest.raises(urllib.error.URLError):
|
||||
cli._request("POST", "https://x/v2/orders", body={"symbol": "AAA"})
|
||||
assert calls["n"] == 1, "POST must not retry a lost-response URLError"
|
||||
calls["n"] = 0
|
||||
with pytest.raises(urllib.error.URLError):
|
||||
cli._request("GET", "https://x/v2/account")
|
||||
assert calls["n"] > 1, "idempotent GET should still retry"
|
||||
Whitespace-only changes.
@@ -875,3 +875,59 @@ def test_session_gate_bars_after_hours_entries():
|
||||
assert svc._outside_session(datetime(2026, 7, 9, 9, 30, tzinfo=ET)) is None # the open
|
||||
svc.settings = ExecutionSettings(session_only=False)
|
||||
assert svc._outside_session(datetime(2026, 7, 9, 20, 9, tzinfo=ET)) is None # opt-out works
|
||||
|
||||
|
||||
def test_flatten_all_closes_broker_position_missed_by_snapshot(store):
|
||||
"""Naked-through-breaker fix: a position that filled in the sync gap isn't in
|
||||
the event-store held set, so _flatten_all's step-2 skips it. Step 3 (moved out
|
||||
of close_session so the daily-loss breaker gets it too) closes it from fresh
|
||||
broker positions."""
|
||||
from alpaca_paper.execution import AlpacaPaperExecutor
|
||||
|
||||
class _Cli:
|
||||
def __init__(self):
|
||||
self.closed = []
|
||||
self.pos = [{"symbol": "GAP", "qty": "100"}] # filled, snapshot missed it
|
||||
|
||||
def get_positions(self, fresh=False):
|
||||
return list(self.pos)
|
||||
|
||||
def close_position(self, symbol, qty=None, percentage=None):
|
||||
self.closed.append(symbol)
|
||||
self.pos = [p for p in self.pos if p["symbol"] != symbol]
|
||||
return {"id": "c"}
|
||||
|
||||
def get_orders(self, **kw):
|
||||
return []
|
||||
|
||||
def cancel_order(self, oid):
|
||||
pass
|
||||
|
||||
cli = _Cli()
|
||||
svc = TradingExecutionService(
|
||||
store, executor=AlpacaPaperExecutor(store, client=cli),
|
||||
settings=ExecutionSettings(auto_approve=True), session_id="t")
|
||||
result = svc._flatten_all("daily_loss_circuit_breaker")
|
||||
assert "GAP" in cli.closed, "breaker flatten must close broker positions the snapshot missed"
|
||||
assert "GAP" in result["closed_positions"]
|
||||
|
||||
|
||||
def test_daily_state_rebuilds_from_events_on_restart(store):
|
||||
"""Mid-session restart must not reset the entry cap to 0 or forget resting
|
||||
orders (re-fire => duplicate order, 2026-07-06). A new service instance
|
||||
rebuilds fresh-fill count, requested symbols, and losing benches from today."""
|
||||
from storage.event_schema import OrderSubmittedEvent, OrderFilledEvent, PositionClosedEvent
|
||||
now = datetime.now()
|
||||
store.emit(OrderSubmittedEvent(timestamp=now, mode=EventMode.PAPER, correlation_id="t",
|
||||
message="sub", order_id="o1", symbol="AAA", side="buy", quantity=10, price=5.0,
|
||||
broker_order_id="b1"))
|
||||
store.emit(OrderFilledEvent(timestamp=now, mode=EventMode.PAPER, correlation_id="t",
|
||||
message="fill", order_id="o1", symbol="AAA", fill_price=5.0, fill_quantity=10,
|
||||
broker_order_id="b1"))
|
||||
store.emit(PositionClosedEvent(timestamp=now, mode=EventMode.PAPER, correlation_id="t",
|
||||
message="closed", position_id="p1", symbol="AAA", side="buy", quantity=10,
|
||||
entry_price=5.0, exit_price=4.5, realized_pnl=-5.0, exit_reason="stop"))
|
||||
svc = make_service(store) # boot AFTER the events land
|
||||
assert svc._fresh_entries["n"] == 1, "cap count must survive restart"
|
||||
assert "AAA" in svc._requested_symbols, "resting-order dedup must survive restart"
|
||||
assert "AAA" in svc._exited_today, "losing bench must survive restart"
|
||||
Reference in new issue
Block a user