DEV Community

Gennady
Gennady

Posted on • Originally published at trendrider.net

I Tested 4 Stop Loss Methods on My Crypto Bot — Here's What Actually Works

Running an algorithmic trading bot is one of those things that sounds glamorous until you watch your carefully crafted strategy bleed money because your stop loss logic is garbage.

I've been running a Freqtrade-based crypto bot on Bybit for several months now, trading BTC/USDT, ETH/USDT, SOL/USDT, and a handful of altcoin futures pairs. Over the past 3 months, I systematically tested four different stop loss approaches to figure out which one actually protects capital without killing profitability.

Here's what I found.


Method 1: Fixed Percentage Stop Loss

The simplest approach. Set a fixed percentage below your entry price. If the trade drops by that amount, you're out.

I tested three variants: -2%, -3.5%, and -6%.

# Freqtrade strategy — fixed percentage stop loss
class MyStrategy(IStrategy):
    stoploss = -0.035  # -3.5% fixed stop loss

    # No trailing, no custom logic
    trailing_stop = False
Enter fullscreen mode Exit fullscreen mode

Pros:

  • Dead simple to implement and understand
  • Predictable risk per trade
  • Easy to calculate position sizing

Cons:

  • Doesn't adapt to market volatility — a -2% stop on BTC during a volatile week is basically guaranteed to get hit
  • Too tight = stopped out on noise; too wide = excessive losses on real reversals

The -2% stop had a terrible win rate (41%) because crypto is volatile enough that normal price action triggers it constantly. The -6% stop had better win rates but the average loss was painful. -3.5% was the sweet spot for my strategy's typical holding period of 4-18 hours.


Method 2: Trailing Stop Loss

A trailing stop follows the price upward and locks in profits. If BTC moves 5% in your favor, the stop moves up with it, so you capture some of that gain even if it reverses.

class MyStrategy(IStrategy):
    stoploss = -0.035

    # Trailing stop configuration
    trailing_stop = True
    trailing_stop_positive = 0.01     # Start trailing at +1% profit
    trailing_stop_positive_offset = 0.02  # Only activate after +2% profit
    trailing_only_offset_is_reached = True
Enter fullscreen mode Exit fullscreen mode

Pros:

  • Locks in profits on strong moves
  • Lets winners run while protecting gains
  • Great in trending markets

Cons:

  • Whipsaws destroy you in crypto. The market pumps 3%, your trail activates, then a 1.5% pullback (totally normal) stops you out right before it pumps another 5%.
  • You end up capturing the middle of moves instead of the full move
  • In choppy/ranging markets, it's worse than a fixed stop

In my backtests, trailing stops performed about 8% worse than the fixed -3.5% stop in terms of total profit. The whipsaw problem is real — crypto moves in jagged patterns, not smooth trends.


Method 3: ATR-Based Dynamic Stop Loss

This is where things get interesting. ATR (Average True Range) measures how much an asset typically moves in a given period. By setting your stop as a multiple of ATR, it automatically adapts to current volatility.

When BTC is calm, your stop is tight. When it's volatile, your stop gives more room.

import talib.abstract as ta

class MyStrategy(IStrategy):
    stoploss = -0.10  # Wide safety net (ATR handles the real stop)

    def populate_indicators(self, dataframe, metadata):
        dataframe['atr'] = ta.ATR(dataframe, timeperiod=14)
        return dataframe

    def custom_stoploss(self, pair, trade, current_time,
                        current_rate, current_profit, **kwargs):
        dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
        last_candle = dataframe.iloc[-1]

        if last_candle['atr'] > 0:
            # Stop loss at 2x ATR below current price
            atr_stop = (last_candle['atr'] * 2) / current_rate
            return -atr_stop

        return -0.035  # Fallback to fixed stop
Enter fullscreen mode Exit fullscreen mode

Pros:

  • Automatically adapts to volatility — no manual tuning per asset
  • Works well across different pairs (BTC, ETH, SOL all have different volatility profiles)
  • Reduces false stops during volatile periods
  • More sophisticated risk management

Cons:

  • More complex to implement and debug
  • ATR can lag during sudden volatility spikes
  • Harder to calculate exact risk per trade in advance
  • The multiplier (2x ATR in my case) still needs tuning

ATR-based stops performed ~5% better than fixed stops across all pairs combined. The biggest improvement was on altcoins, where volatility varies dramatically day-to-day.


Method 4: Time-Based Exit

This one is underrated. Instead of (or in addition to) a price-based stop, you exit the trade if it hasn't reached a profit threshold after N hours. The logic: if your signal was right, the move should happen within a reasonable timeframe. If it hasn't moved, your thesis is probably wrong.

from datetime import timedelta

class MyStrategy(IStrategy):
    stoploss = -0.035

    def custom_exit(self, pair, trade, current_time,
                    current_rate, current_profit, **kwargs):
        # Exit if trade is open > 24 hours and profit < 1%
        trade_duration = current_time - trade.open_date_utc
        if trade_duration > timedelta(hours=24) and current_profit < 0.01:
            return 'time_exit_24h'

        # Exit if trade is open > 48 hours regardless
        if trade_duration > timedelta(hours=48):
            return 'time_exit_48h'

        return None
Enter fullscreen mode Exit fullscreen mode

Pros:

  • Frees up capital from stagnant positions
  • Reduces exposure time (less time in market = less risk)
  • Catches trades that would otherwise slowly bleed with fees
  • Complements price-based stops perfectly

Cons:

  • You might exit right before a delayed move
  • Requires understanding your strategy's typical winning timeframe
  • Not useful if your strategy has highly variable holding periods

The 24-hour time exit was a game-changer. It eliminated a whole category of trades that would sit at -0.5% to -1.5% for days, slowly bleeding funding fees. These "zombie trades" were dragging down my overall performance more than I realized.


Results: Head-to-Head Comparison

Here are the actual backtest results across 3 months of crypto futures data (BTC, ETH, SOL, AVAX, LINK on 5m candles):

Method Win Rate Avg Profit/Trade Max Drawdown Total Profit
Fixed -2% 41.2% -0.18% -18.4% -12.3%
Fixed -3.5% 58.7% +0.42% -11.2% +28.6%
Fixed -6% 63.1% +0.31% -16.8% +19.4%
Trailing (from +2%) 54.3% +0.38% -12.7% +22.1%
ATR-based (2x) 61.4% +0.51% -9.8% +33.2%
Time exit (24h) only 55.8% +0.29% -13.1% +18.7%
Hybrid: -3.5% + 24h time 62.8% +0.54% -8.9% +36.4%

What I Actually Use Now

After all this testing, my production strategy uses a hybrid approach: a fixed -3.5% stop loss combined with a 24-hour time-based exit.

class TrendRiderStrategy(IStrategy):
    stoploss = -0.035  # Fixed -3.5% stop
    trailing_stop = False

    def custom_exit(self, pair, trade, current_time,
                    current_rate, current_profit, **kwargs):
        trade_duration = current_time - trade.open_date_utc

        # Time exit: 24h with < 1% profit
        if trade_duration > timedelta(hours=24) and current_profit < 0.01:
            return 'time_exit'

        # Take profit at 4%+
        if current_profit >= 0.04:
            return 'take_profit'

        return None
Enter fullscreen mode Exit fullscreen mode

Why this combo works:

  1. The -3.5% stop handles real reversals and limits downside
  2. The 24h time exit cleans up zombie trades that go nowhere
  3. Together they give the lowest max drawdown (-8.9%) of any method tested
  4. The win rate stays above 62% which is solid for crypto

Key Insight

The "best" stop loss doesn't exist in isolation. It depends entirely on:

  • Your strategy's holding period — short-term scalps need tighter stops; swing trades need room to breathe
  • The market regime — trending markets favor trailing stops; ranging markets favor fixed + time exits
  • Your pair's volatility profile — what works for BTC won't work for a small-cap altcoin

The real lesson is: backtest every stop loss method against YOUR specific strategy, on YOUR specific pairs, for YOUR specific timeframe. Don't copy someone else's -2% stop and wonder why you're getting stopped out every other trade.

And please, for the love of all that is holy, don't trade crypto without a stop loss. I've seen what happens. It's not pretty.


If you're building a trading bot, check out TrendRider at trendrider.net — we share our signals and results transparently.

Top comments (0)