66 lines
2.3 KiB
Python
66 lines
2.3 KiB
Python
import pytest
|
|
|
|
from app.core.trailing_stop import evaluate_trailing_stop, trailing_profile
|
|
|
|
|
|
def test_fixed_trailing_stop_activates_with_profit_floor():
|
|
decision = evaluate_trailing_stop(
|
|
position={"entry_price": 100, "max_price": 100, "min_price": 100, "trailing_stop": 0},
|
|
current_price=104,
|
|
pnl_pct=4,
|
|
config={
|
|
"trailing_stop_enabled": True,
|
|
"trailing_mode": "fixed",
|
|
"trailing_activate_pnl_pct": 3,
|
|
"trailing_min_lock_profit_pct": 0.5,
|
|
"trailing_distance_pct": 1.5,
|
|
},
|
|
).as_dict()
|
|
|
|
assert decision["action"] == "activate"
|
|
assert decision["event_type"] == "trailing_activate"
|
|
assert decision["activated"] is True
|
|
assert decision["trailing_mode"] == "fixed"
|
|
assert decision["trailing_stop"] == pytest.approx(102.44)
|
|
|
|
|
|
def test_trailing_stop_never_moves_down():
|
|
decision = evaluate_trailing_stop(
|
|
position={"entry_price": 100, "max_price": 106, "min_price": 100, "trailing_stop": 104},
|
|
current_price=104.5,
|
|
pnl_pct=4.5,
|
|
config={
|
|
"trailing_stop_enabled": True,
|
|
"trailing_mode": "fixed",
|
|
"trailing_activate_pnl_pct": 3,
|
|
"trailing_min_lock_profit_pct": 0.5,
|
|
"trailing_distance_pct": 1.5,
|
|
},
|
|
).as_dict()
|
|
|
|
assert decision["action"] == "hold"
|
|
assert decision["reason"] == "unchanged"
|
|
assert decision["trailing_stop"] == pytest.approx(104)
|
|
|
|
|
|
def test_volatility_profile_widens_activation_and_distance():
|
|
profile = trailing_profile(
|
|
{"entry_price": 100, "max_price": 100, "min_price": 98},
|
|
current_price=110,
|
|
pnl_pct=10,
|
|
config={
|
|
"trailing_mode": "volatility",
|
|
"trailing_activate_pnl_pct": 3,
|
|
"trailing_distance_pct": 1.5,
|
|
"trailing_volatility_activation_mult": 0.6,
|
|
"trailing_volatility_distance_mult": 0.7,
|
|
"trailing_volatility_max_activation_pct": 8,
|
|
"trailing_volatility_max_distance_pct": 8,
|
|
},
|
|
)
|
|
|
|
assert profile["trailing_mode"] == "volatility"
|
|
assert profile["volatility_pct"] == pytest.approx(12)
|
|
assert profile["activate_pnl_pct"] == pytest.approx(7.2)
|
|
assert profile["distance_pct"] == pytest.approx(8.0)
|