from app.core.strategy_registry import ( LONG_BOX_RETEST_4H_STRATEGY, LONG_COMPRESSION_BREAKOUT_STRATEGY, LONG_MOMENTUM_BREAKOUT_STRATEGY, LONG_SECOND_WAVE_PULLBACK_STRATEGY, SHORT_BREAKDOWN_RETEST_STRATEGY, SHORT_WEAK_BOUNCE_FAILURE_STRATEGY, ) from app.strategies.altcoin_breakout import ( build_compression_breakout_4h_signal, build_long_box_retest_4h_signal, build_long_momentum_breakout_signal, build_long_second_wave_pullback_signal, ) from app.strategies.short_breakdown import build_breakdown_retest_short_1h_signal, build_short_weak_bounce_failure_signal def test_long_intraday_momentum_requires_current_trigger(): signal = build_long_momentum_breakout_signal( symbol="MOM/USDT", result={"score": 8, "signals": ["1H量价齐飞", "15min即刻入场"], "trigger_context": {"current_triggers": ["15m"]}}, entry_plan={"entry_action": "可即刻买入"}, ) missing = build_long_momentum_breakout_signal( symbol="MOM/USDT", result={"score": 8, "signals": ["1H量价齐飞"]}, entry_plan={"entry_action": "可即刻买入"}, ) assert signal.to_json_dict()["strategy_code"] == LONG_MOMENTUM_BREAKOUT_STRATEGY assert signal.status == "candidate" assert missing is None def test_long_second_wave_pullback_can_wait_for_entry(): signal = build_long_second_wave_pullback_signal( symbol="WAVE/USDT", result={"score": 10, "signals": ["24h强势榜", "1H箱体突破回踩", "量价齐飞"]}, entry_plan={"entry_action": "等回踩"}, ) assert signal.to_json_dict()["strategy_code"] == LONG_SECOND_WAVE_PULLBACK_STRATEGY assert signal.status == "candidate" def test_long_compression_breakout_requires_current_entry_context(): signal = build_compression_breakout_4h_signal( symbol="COMP/USDT", result={"score": 9, "signals": ["4H静K蓄力", "压缩突破", "15min即刻入场"], "trigger_context": {"current_triggers": ["15m"]}}, entry_plan={"entry_action": "可即刻买入"}, ) assert signal.to_json_dict()["strategy_code"] == LONG_COMPRESSION_BREAKOUT_STRATEGY assert signal.status == "candidate" def test_long_box_retest_4h_keeps_pullback_waiting_signal(): signal = build_long_box_retest_4h_signal( symbol="BOX/USDT", result={"score": 9, "signals": ["4H箱体突破回踩", "15min回踩确认"]}, entry_plan={"entry_action": "等回踩"}, ) assert signal.to_json_dict()["strategy_code"] == LONG_BOX_RETEST_4H_STRATEGY assert signal.status == "candidate" def test_short_breakdown_retest_observes_until_retest_rejected(): signal = build_breakdown_retest_short_1h_signal( symbol="BD/USDT", current_price=9.5, detection={ "detected": True, "quality": "良好", "score": 5, "breakdown_level": 10, "retest_zone": 10, "stop_level": 10.4, "target_1": 8.8, "retest_rejected": False, "relative_weakness": True, }, entry_plan={"side": "short", "entry_action": "等回踩"}, market_regime={"risk_level": "high"}, ) assert signal.to_json_dict()["strategy_code"] == SHORT_BREAKDOWN_RETEST_STRATEGY assert signal.status == "observe" def test_short_weak_bounce_failure_needs_weak_market(): signal = build_short_weak_bounce_failure_signal( symbol="WB/USDT", result={"score": 7, "signals": ["15min反抽失败", "弱反弹失败"], "market_regime": {"regime": "risk_off", "risk_level": "high"}}, entry_plan={"side": "short", "entry_action": "可即刻买入"}, ) assert signal.to_json_dict()["strategy_code"] == SHORT_WEAK_BOUNCE_FAILURE_STRATEGY assert signal.status == "candidate"