Allow disabling stop loss exits
This commit is contained in:
@@ -90,6 +90,7 @@ def make_settings():
|
||||
time_series_probe_size_multiplier=0.40,
|
||||
time_series_rebound_fallback_enabled=True,
|
||||
stop_loss_percent=0.02,
|
||||
stop_loss_exit_enabled=True,
|
||||
take_profit_percent=0.035,
|
||||
trailing_stop_percent=0.015,
|
||||
min_hold_seconds=180,
|
||||
|
||||
@@ -233,6 +233,90 @@ def test_trend_macd_exits_on_atr_trailing_stop(make_settings, tmp_path) -> None:
|
||||
assert "ATR trailing" in signal.reason
|
||||
|
||||
|
||||
def test_trend_macd_holds_below_stop_when_stop_loss_exit_disabled(make_settings, tmp_path) -> None:
|
||||
settings = make_settings(
|
||||
tmp_path,
|
||||
strategy_mode="trend_macd",
|
||||
stop_loss_exit_enabled=False,
|
||||
atr_trailing_multiplier=2.2,
|
||||
)
|
||||
strategy = SpotStrategy(settings)
|
||||
candles = _trend_entry_candles(close=99.0, ema50=95.0, macd_cross_up=False)
|
||||
candles[-2].macd = 0.1
|
||||
candles[-2].macd_signal = 0.0
|
||||
candles[-1].macd = 0.1
|
||||
candles[-1].macd_signal = 0.0
|
||||
candles[-1].atr_14 = 1.0
|
||||
position = Position(1, "BTCUSDT", 1, 100, 100, 0.1, 96, 120, 100.5)
|
||||
ticker = Ticker("BTCUSDT", 95.5, 95.49, 95.51, 1_000_000, 100, 0)
|
||||
|
||||
signal = strategy.exit_signal(position, candles, ticker)
|
||||
|
||||
assert signal.action == "HOLD"
|
||||
assert signal.diagnostics["stop_loss"] is None
|
||||
assert signal.diagnostics["stop_loss_exit_enabled"] is False
|
||||
|
||||
|
||||
def test_torch_atr_trailing_without_stop_loss_waits_for_profit_stop(make_settings, tmp_path) -> None:
|
||||
settings = make_settings(
|
||||
tmp_path,
|
||||
strategy_mode="torch_forecast",
|
||||
stop_loss_exit_enabled=False,
|
||||
atr_trailing_multiplier=2.2,
|
||||
)
|
||||
strategy = SpotStrategy(settings)
|
||||
candles = _trend_entry_candles(close=99.0, ema50=95.0, macd_cross_up=False)
|
||||
candles[-1].atr_14 = 1.0
|
||||
position = Position(1, "BTCUSDT", 1, 100, 100, 0.1, 96, 120, 101.0)
|
||||
ticker = Ticker("BTCUSDT", 98.7, 98.69, 98.71, 1_000_000, 100, 0)
|
||||
|
||||
signal = strategy.exit_signal(
|
||||
position,
|
||||
candles,
|
||||
ticker,
|
||||
forecast={
|
||||
"usable": True,
|
||||
"model": "torch_lstm",
|
||||
"expected_return_percent": 0.4,
|
||||
"probability_up": 0.62,
|
||||
"skill": 0.18,
|
||||
},
|
||||
)
|
||||
|
||||
assert signal.action == "HOLD"
|
||||
assert signal.diagnostics["atr_trailing_stop"] is None
|
||||
|
||||
|
||||
def test_torch_atr_trailing_without_stop_loss_can_lock_profit(make_settings, tmp_path) -> None:
|
||||
settings = make_settings(
|
||||
tmp_path,
|
||||
strategy_mode="torch_forecast",
|
||||
stop_loss_exit_enabled=False,
|
||||
atr_trailing_multiplier=2.2,
|
||||
)
|
||||
strategy = SpotStrategy(settings)
|
||||
candles = _trend_entry_candles(close=104.0, ema50=95.0, macd_cross_up=False)
|
||||
candles[-1].atr_14 = 1.0
|
||||
position = Position(1, "BTCUSDT", 1, 100, 100, 0.1, 96, 120, 104.0)
|
||||
ticker = Ticker("BTCUSDT", 101.7, 101.69, 101.71, 1_000_000, 100, 0)
|
||||
|
||||
signal = strategy.exit_signal(
|
||||
position,
|
||||
candles,
|
||||
ticker,
|
||||
forecast={
|
||||
"usable": True,
|
||||
"model": "torch_lstm",
|
||||
"expected_return_percent": 0.4,
|
||||
"probability_up": 0.62,
|
||||
"skill": 0.18,
|
||||
},
|
||||
)
|
||||
|
||||
assert signal.action == "SELL"
|
||||
assert "ATR trailing" in signal.reason
|
||||
|
||||
|
||||
def test_torch_forecast_buys_only_from_positive_torch_edge(make_settings, tmp_path) -> None:
|
||||
settings = make_settings(
|
||||
tmp_path,
|
||||
|
||||
Reference in New Issue
Block a user