| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455 |
- from dataclasses import replace
- import pytest
- from okx_codex_trader.bb_squeeze_strategy import EMPTY_STATE, signal_from_frame, strategy_name
- from okx_codex_trader.models import Candle
- from scripts.run_bb_squeeze_executor import aligned_frame_from_candles
- from tests.test_run_bb_squeeze_executor import btc_up_candles, middle_exit_candles
- def live_frame(candles: list[Candle]):
- return aligned_frame_from_candles(candles, btc_up_candles([candle.ts for candle in candles]))
- def test_strategy_name_includes_breakeven_parameters() -> None:
- assert strategy_name().endswith("-be0.008-0.001")
- def test_breakeven_protection_uses_prior_confirmed_mfe() -> None:
- candles = middle_exit_candles(1.0)
- candles[-1] = Candle(
- symbol="ETH-USDT-SWAP",
- ts=candles[-1].ts,
- open=100.4,
- high=100.5,
- low=100.05,
- close=100.2,
- volume=1_000.0,
- )
- state = replace(EMPTY_STATE, active_side="long", entry_price=100.0, entry_candle_ts=candles[-2].ts, last_candle_ts=candles[-2].ts, max_favorable_move_pct=0.008)
- next_state, signal = signal_from_frame(live_frame(candles), state)
- assert signal["signal"] == "exit_breakeven"
- assert signal["target_side"] == "flat"
- assert next_state.active_side is None
- def test_favorable_move_updates_without_same_candle_breakeven_exit() -> None:
- candles = middle_exit_candles(1.0)
- candles[-1] = Candle(
- symbol="ETH-USDT-SWAP",
- ts=candles[-1].ts,
- open=100.0,
- high=100.9,
- low=100.0,
- close=100.4,
- volume=1_000.0,
- )
- state = replace(EMPTY_STATE, active_side="long", entry_price=100.0, entry_candle_ts=candles[-2].ts, last_candle_ts=candles[-2].ts, max_favorable_move_pct=0.0)
- next_state, signal = signal_from_frame(live_frame(candles), state)
- assert signal["signal"] == "hold"
- assert next_state.max_favorable_move_pct == pytest.approx(0.009)
|