import pytest from app.db import altcoin_db from app.db.paper_trading import list_paper_trades, sync_recommendation from app.db.runtime_config_db import set_config from app.services import price_streamer @pytest.fixture def buy_now_rec(monkeypatch): set_config("system", "paper_trading", { "enabled": True, "trade_notional_usdt": 5000, "trade_leverage": 5, "fee_rate": 0, "slippage_pct": 0, }) set_config("system", "price_streamer", { "enabled": True, "update_latest_price_cache": True, "sync_paper_trading": True, "include_actionable_recommendations": True, "include_open_paper_trades": True, }) altcoin_db.init_db() rec_id = altcoin_db.create_recommendation( symbol="WS/USDT", rec_state="爆发", rec_score=28, entry_price=100, stop_loss=95, tp1=106, tp2=112, signals=["当前15min即刻入场信号"], entry_plan={ "entry_action": "可即刻买入", "entry_price": 100, "stop_loss": 95, "tp1": 106, "tp2": 112, "risk_reward_ok": True, "entry_trigger_confirmed": True, }, ) return next(r for r in altcoin_db.get_active_recommendations_deduped(actionable_only=False) if r["id"] == rec_id) def test_price_streamer_loads_actionable_targets(buy_now_rec): targets = price_streamer.load_stream_targets() assert "WS/USDT" in targets assert targets["WS/USDT"]["id"] == buy_now_rec["id"] def test_price_streamer_tick_opens_and_closes_paper_trade(buy_now_rec): targets = {"WS/USDT": buy_now_rec} opened = price_streamer.handle_price_tick("WS/USDT", 100, targets, event_time="2026-05-16T10:00:00") targets = price_streamer.load_stream_targets() closed = price_streamer.handle_price_tick("WS/USDT", 106, targets, event_time="2026-05-16T10:01:00") assert opened["paper_trading"]["opened"] is True assert closed["paper_trading"]["closed"] is True assert closed["paper_trading"]["exit_reason"] == "tp1" trade = list_paper_trades()["items"][0] assert trade["status"] == "closed" assert trade["notional_usdt"] == pytest.approx(5000.0) def test_price_streamer_tracks_open_paper_trade_without_active_rec(buy_now_rec): sync_recommendation(buy_now_rec, 100, event_time="2026-05-16T10:00:00") targets = price_streamer.load_stream_targets() assert "WS/USDT" in targets assert targets["WS/USDT"]["id"] == buy_now_rec["id"] def test_price_streamer_builds_binance_combined_stream_url(): url = price_streamer._stream_url(["BTC/USDT", "ETH/USDT"], {"stream_url": "wss://example.test/stream"}) assert url == "wss://example.test/stream?streams=btcusdt@ticker/ethusdt@ticker" def test_price_streamer_parse_ticker_message(): symbol, price = price_streamer._parse_ticker_message('{"stream":"wsusdt@ticker","data":{"s":"WSUSDT","c":"101.5"}}') assert symbol == "WS/USDT" assert price == pytest.approx(101.5)