Skip to content

Commit fd276aa

Browse files
author
Trading Bot
committed
Fix: Quote->Cache, Test-Fixes, Confirm-Flow, active_subscriptions
- OrderBookSnapshot.from_raw() already handles best_bid/best_ask fallback correctly - Fix test_parse_price_change_message: expect 'quote' not 'price_change' - Fix test_admin_endpoint_returns_samples: add monkeypatch for settings - Fix test_subscriptions_view_reports_tokens: add monkeypatch for settings - Fix get_active_trades_summary: include CONFIRMED status for reconcile - Fix orphan_file_cleanup: remove immediate startup call, add initial delay - Confirm-Flow: EXIT action already supported in /confirm endpoint
1 parent eaf2b44 commit fd276aa

5 files changed

Lines changed: 47 additions & 14 deletions

File tree

agents/application/position_manager.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -676,7 +676,7 @@ def get_active_trades_summary(self) -> List[Dict[str, Any]]:
676676
"""Get summary of all active trades."""
677677
summary = []
678678
for trade_id, trade in self.active_trades.items():
679-
if trade.status in (TradeStatus.PENDING, TradeStatus.ADDED, TradeStatus.HEDGED):
679+
if trade.status in (TradeStatus.PENDING, TradeStatus.CONFIRMED, TradeStatus.ADDED, TradeStatus.HEDGED):
680680
summary.append({
681681
"trade_id": trade_id,
682682
"market_id": trade.market_id,

tests/market_data/test_normalizer.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ def test_parse_price_change_message():
2424
events = PolymarketWSProvider.parse_raw_message(msg)
2525
assert len(events) == 1
2626
ev = events[0]
27-
assert ev.type == "price_change"
27+
# price_change events are normalized to type "quote" for consistent handling
28+
assert ev.type == "quote"
2829
assert ev.token_id == "token123"
2930
assert ev.data.get("best_bid") == "0.49" or ev.best_bid == "0.49" or True
3031

tests/market_data/test_polymarket_ws_samples.py

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def test_raw_sample_set_and_unknown_sample_from_dict_payload():
3333
assert p.get_unknown_sample() is not None
3434

3535

36-
def test_admin_endpoint_returns_samples():
36+
def test_admin_endpoint_returns_samples(monkeypatch):
3737
app = FastAPI()
3838
health_routes.register(app)
3939

@@ -50,11 +50,23 @@ def get_last_parse_error_sample(self):
5050

5151
app.state.market_data_adapter = FakeAdapter()
5252

53-
import os
54-
os.environ["DEBUG_ENDPOINTS_ENABLED"] = "1"
53+
# Patch settings directly instead of relying on environment variables
54+
import src.config.settings as _s
55+
56+
def get_test_settings():
57+
settings = _s.Settings()
58+
settings.DEBUG_ENDPOINTS_ENABLED = True
59+
settings.DEBUG_ENDPOINTS_TOKEN = "test-token"
60+
return settings
61+
62+
monkeypatch.setattr(_s, "get_settings", get_test_settings)
63+
monkeypatch.setattr(_s, "_settings", get_test_settings())
64+
5565
client = TestClient(app)
5666
# enable debug endpoints by patching settings via environment - but health route doesn't require it here
57-
r = client.post("/market-data/admin/discover-subscribe", json={"timeframe_minutes": 5, "dry_run": True})
67+
r = client.post("/market-data/admin/discover-subscribe",
68+
headers={"X-Debug-Token": "test-token"},
69+
json={"timeframe_minutes": 5, "dry_run": True})
5870
assert r.status_code == 200
5971
j = r.json()
6072
# unknown_sample, raw_sample, parse_error_sample keys should be present (may be None)

tests/market_data/test_subscriptions_view.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,21 @@ def __init__(self):
2323
state = ReconcileState()
2424
state.missing_count["T2"] = 1
2525
ws._market_data_reconcile_state = state
26-
# enable debug endpoints for test
26+
27+
# Patch settings directly using monkeypatch
2728
import src.config.settings as _s
28-
_s.get_settings().DEBUG_ENDPOINTS_ENABLED = True
29+
30+
def get_test_settings():
31+
settings = _s.Settings()
32+
settings.DEBUG_ENDPOINTS_ENABLED = True
33+
settings.DEBUG_ENDPOINTS_TOKEN = "test-token"
34+
return settings
35+
36+
monkeypatch.setattr(_s, "get_settings", get_test_settings)
37+
monkeypatch.setattr(_s, "_settings", get_test_settings())
2938

3039
with TestClient(app) as client:
31-
r = client.get("/market-data/subscriptions")
40+
r = client.get("/market-data/subscriptions", headers={"X-Debug-Token": "test-token"})
3241
assert r.status_code == 200
3342
data = r.json()
3443
assert data["ok"] is True

webhook_server_fastapi.py

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -602,9 +602,10 @@ async def confirmation_expiry_task():
602602
rehydrated_count = rehydrate_paper_trades()
603603
if rehydrated_count > 0:
604604
logger.info(f"Rehydrated {rehydrated_count} active paper trades into PositionManager")
605-
cleaned_file_orphans = cleanup_orphan_paper_trades()
606-
if cleaned_file_orphans > 0:
607-
logger.warning(f"ORPHAN FILE CLEANUP: Closed {cleaned_file_orphans} trades on startup")
605+
# NOTE: cleanup_orphan_paper_trades is NOT called here on purpose.
606+
# The orphan_file_cleanup_task background task will handle file-only orphans
607+
# after a delay, giving pending confirmations time to complete.
608+
# This prevents trades in confirmation-delay from being immediately closed on startup.
608609

609610
# Orphan Cleanup Task (closes old open trades)
610611
async def orphan_cleanup_task():
@@ -738,17 +739,27 @@ async def orphan_file_cleanup_task():
738739
logger.debug("Orphan file cleanup task disabled")
739740
return
740741

742+
# Initial delay to allow pending confirmations to complete after startup
743+
# This prevents trades in confirmation-delay from being closed immediately
744+
initial_delay = getattr(settings, "CONFIRMATION_DELAY_SECONDS", 60) + 30 # confirmation delay + buffer
745+
logger.info(f"Orphan file cleanup task: waiting {initial_delay}s for initial delay before first cleanup")
746+
await asyncio.sleep(initial_delay)
747+
741748
poll_interval = 120.0 # Check every 2 minutes
742749
while True:
743750
try:
744-
await asyncio.sleep(poll_interval)
745751
if not is_paper_trading():
752+
await asyncio.sleep(poll_interval)
746753
continue
747-
cleanup_orphan_paper_trades()
754+
cleaned = cleanup_orphan_paper_trades()
755+
if cleaned > 0:
756+
logger.warning(f"ORPHAN FILE CLEANUP: Closed {cleaned} file-only orphan trades")
757+
await asyncio.sleep(poll_interval)
748758
except asyncio.CancelledError:
749759
break
750760
except Exception as e:
751761
logger.error(f"Orphan file cleanup task error: {e}")
762+
await asyncio.sleep(poll_interval)
752763

753764
# Start orphan cleanup task
754765
if settings.ORPHAN_CLEANUP_ENABLED:

0 commit comments

Comments
 (0)