1
This commit is contained in:
parent
42da844a80
commit
1e4d2e39d9
@ -91,6 +91,7 @@ def _load_pending_paper_order_recs() -> list[dict]:
|
|||||||
SELECT
|
SELECT
|
||||||
po.recommendation_id AS id,
|
po.recommendation_id AS id,
|
||||||
po.symbol,
|
po.symbol,
|
||||||
|
po.side,
|
||||||
po.target_price AS entry_price,
|
po.target_price AS entry_price,
|
||||||
po.stop_loss,
|
po.stop_loss,
|
||||||
po.tp1,
|
po.tp1,
|
||||||
@ -98,6 +99,10 @@ def _load_pending_paper_order_recs() -> list[dict]:
|
|||||||
po.source_status AS execution_status,
|
po.source_status AS execution_status,
|
||||||
po.source_action AS action_status,
|
po.source_action AS action_status,
|
||||||
po.strategy_version,
|
po.strategy_version,
|
||||||
|
po.strategy_code,
|
||||||
|
po.strategy_signal_id,
|
||||||
|
po.strategy_snapshot_json,
|
||||||
|
po.factor_roles_json,
|
||||||
po.entry_plan_snapshot_json AS entry_plan_json
|
po.entry_plan_snapshot_json AS entry_plan_json
|
||||||
FROM paper_orders po
|
FROM paper_orders po
|
||||||
WHERE po.status='pending'
|
WHERE po.status='pending'
|
||||||
@ -151,24 +156,35 @@ def load_stream_targets(limit: int | None = None, cfg: dict | None = None) -> di
|
|||||||
max_symbols = max(1, _safe_int(limit or cfg.get("max_stream_symbols"), 200))
|
max_symbols = max(1, _safe_int(limit or cfg.get("max_stream_symbols"), 200))
|
||||||
targets: dict[str, dict] = {}
|
targets: dict[str, dict] = {}
|
||||||
|
|
||||||
if cfg.get("include_actionable_recommendations", True):
|
# Execution state must never be crowded out by a large watch/recommendation
|
||||||
for rec in get_active_recommendations_deduped(actionable_only=True, limit=max_symbols, with_meta=False):
|
# set. Pending orders and open positions drive fills, TP/SL, trailing stops,
|
||||||
symbol = str(rec.get("symbol") or "").strip().upper()
|
# and live protection sync; recommendations only use the remaining capacity.
|
||||||
if symbol:
|
|
||||||
targets[symbol] = dict(rec)
|
|
||||||
|
|
||||||
if cfg.get("include_open_paper_trades", True):
|
if cfg.get("include_open_paper_trades", True):
|
||||||
for rec in _load_pending_paper_order_recs():
|
for rec in _load_pending_paper_order_recs():
|
||||||
symbol = str(rec.get("symbol") or "").strip().upper()
|
symbol = str(rec.get("symbol") or "").strip().upper()
|
||||||
if symbol:
|
if symbol:
|
||||||
targets[symbol] = rec
|
targets[symbol] = rec
|
||||||
|
if len(targets) >= max_symbols:
|
||||||
|
return targets
|
||||||
|
|
||||||
for rec in _load_open_paper_trade_recs():
|
for rec in _load_open_paper_trade_recs():
|
||||||
symbol = str(rec.get("symbol") or "").strip().upper()
|
symbol = str(rec.get("symbol") or "").strip().upper()
|
||||||
if symbol:
|
if symbol:
|
||||||
targets[symbol] = rec
|
targets[symbol] = rec
|
||||||
|
if len(targets) >= max_symbols:
|
||||||
|
return targets
|
||||||
|
|
||||||
return dict(list(targets.items())[:max_symbols])
|
if cfg.get("include_actionable_recommendations", True):
|
||||||
|
remaining = max(0, max_symbols - len(targets))
|
||||||
|
if remaining > 0:
|
||||||
|
for rec in get_active_recommendations_deduped(actionable_only=True, limit=remaining, with_meta=False):
|
||||||
|
symbol = str(rec.get("symbol") or "").strip().upper()
|
||||||
|
if symbol and symbol not in targets:
|
||||||
|
targets[symbol] = dict(rec)
|
||||||
|
if len(targets) >= max_symbols:
|
||||||
|
break
|
||||||
|
|
||||||
|
return targets
|
||||||
|
|
||||||
|
|
||||||
def handle_price_tick(symbol: str, price: float, targets: dict[str, dict], event_time: str | None = None, cfg: dict | None = None) -> dict:
|
def handle_price_tick(symbol: str, price: float, targets: dict[str, dict], event_time: str | None = None, cfg: dict | None = None) -> dict:
|
||||||
|
|||||||
@ -268,6 +268,38 @@ def test_price_streamer_prioritizes_pending_order_over_same_symbol_recommendatio
|
|||||||
assert list_paper_trades()["items"][0]["recommendation_id"] == pending_id
|
assert list_paper_trades()["items"][0]["recommendation_id"] == pending_id
|
||||||
|
|
||||||
|
|
||||||
|
def test_price_streamer_subscription_prioritizes_execution_symbols(monkeypatch):
|
||||||
|
monkeypatch.setattr(
|
||||||
|
price_streamer,
|
||||||
|
"_load_pending_paper_order_recs",
|
||||||
|
lambda: [{"id": 1, "symbol": "PUMP/USDT", "side": "long", "entry_price": 0.001636}],
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
price_streamer,
|
||||||
|
"_load_open_paper_trade_recs",
|
||||||
|
lambda: [{"id": 2, "symbol": "WLD/USDT", "side": "long", "entry_price": 0.5}],
|
||||||
|
)
|
||||||
|
monkeypatch.setattr(
|
||||||
|
price_streamer,
|
||||||
|
"get_active_recommendations_deduped",
|
||||||
|
lambda **kwargs: [
|
||||||
|
{"id": 3, "symbol": "AAA/USDT"},
|
||||||
|
{"id": 4, "symbol": "BBB/USDT"},
|
||||||
|
{"id": 5, "symbol": "CCC/USDT"},
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
targets = price_streamer.load_stream_targets(
|
||||||
|
limit=2,
|
||||||
|
cfg={
|
||||||
|
"include_actionable_recommendations": True,
|
||||||
|
"include_open_paper_trades": True,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
assert list(targets.keys()) == ["PUMP/USDT", "WLD/USDT"]
|
||||||
|
|
||||||
|
|
||||||
def test_price_streamer_builds_binance_combined_stream_url():
|
def test_price_streamer_builds_binance_combined_stream_url():
|
||||||
url = price_streamer._stream_url(["BTC/USDT", "ETH/USDT"], {"stream_url": "wss://example.test/stream"})
|
url = price_streamer._stream_url(["BTC/USDT", "ETH/USDT"], {"stream_url": "wss://example.test/stream"})
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user