13 Days, 48 Trades, Breakeven. Then I Fixed One Thing. Here's Every Trade.
I ran a Freqtrade bot on Bybit for 13 days and made exactly −$0.06. Forty-eight trades, 64% win rate, almost-perfect symmetry between wins and losses. A textbook breakeven run.
Then on April 13 at 17:27 UTC I deployed a single change — a cascading early loss cut instead of a 24-hour hard time exit.
In the next 8 hours the bot closed 6 more trades, 4 winners, and made +$6.42.
This post is the honest story of what happened, every trade, every exit reason, the bug I spent four days missing, and why I'm now open-sourcing the strategy. SQLite dump and MIT-licensed code are at the end. No marketing filter, no cherry-picked screenshots.
The setup
- Framework: Freqtrade 2025.6
- Exchange: Bybit USDT-perpetual futures, isolated margin, no leverage above 1x
- Account: dry-run with $500 starting balance (paper money, identical execution logic to live)
- Pairs: 15 large caps — BTC, ETH, SOL, BNB, XRP, DOGE, ADA, LINK, DOT, AVAX, ATOM, NEAR, OP, POL, SUI
- Timeframe: 1h candles
- Max concurrent positions: 3
- Stake per trade: $50 (10% of balance)
- Stop-loss: 6% (wide on purpose — crypto does 2–4% hourly noise)
- Public dashboard: trendrider.net/live reads straight from the bot's SQLite every 60 seconds, losing trades included
The strategy layers six signals — EMA cross, RSI, ADX, volume z-score, Bollinger position, MACD histogram — into a 0–100 confidence score. Entries fire only above a tunable threshold. Three enter_tags fire real entries: ema_crossover, macd_reversal, and bb_bounce.
That part isn't new. The interesting part is what happens when a position goes wrong.
Week 1: the opening wound, then a perfect day
Trade #1, April 1, 17:00 UTC, DOGE/USDT:USDT, ema_crossover: opens at 0.0934, trend flips inside 9 hours, exits at 0.0905 on the trend_broken rule. −$1.60. First blood on day one.
The next three days are quiet. Only four trades, split wins and losses, net barely moves. Then April 4 brings the first hint of the real problem:
- Trade #3, DOGE/USDT, opens 17:00, exits 24 hours later at
time_exit_24h. −$0.88. - Trade #4, OP/USDT, opens 20:00, exits 24 hours later at
time_exit_24h. −$1.67.
Both hit the hard 24-hour exit at the exact clock, not on any signal. Neither had broken its trend — they were simply stuck. The bot closed them because the rule said to.
April 7 saves the week. The market rips, and the strategy catches four massive winners in eight hours:
| Trade | Pair | Entry | Exit | P&L |
|---|---|---|---|---|
| #15 | ETH/USDT | ema_crossover | ROI | +$2.25 (+5.33%) |
| #18 | SUI/USDT | ema_crossover | ROI | +$3.65 (+8.17%) |
| #16 | SOL/USDT | ema_crossover | trailing_stop | +$1.39 (+2.82%) |
| #17 | NEAR/USDT | ema_crossover | trailing_stop | +$1.20 (+2.41%) |
| #14 | ATOM/USDT | macd_reversal | ROI | +$2.21 (+4.42%) |
Net for day seven: +$10.70. I'm smiling. The strategy is working.
Week 2: the slow bleed
Days 8 through 13 are where everything I learned gets unlearned. The bot takes 25 more trades, wins most of them, and makes almost nothing.
The losers have a theme. Here are the five biggest losses of the entire run:
| # | Pair | Exit | P&L | Reason |
|---|---|---|---|---|
| 36 | LINK/USDT | time_exit_24h | −$2.54 (−5.12%) | 24-hour rule |
| 42 | AVAX/USDT | trend_broken | −$1.78 (−3.57%) | trend flip |
| 31 | SUI/USDT | time_exit_24h | −$1.76 (−3.73%) | 24-hour rule |
| 39 | LINK/USDT | trend_broken | −$1.69 (−3.38%) | trend flip |
| 45 | DOGE/USDT | trend_broken | −$1.68 (−3.36%) | trend flip |
Two out of five top losses are the time_exit_24hrule closing trades that hadn't done anything wrong except "time's up."
I checked the exit-reason breakdown for the 13-day pre-fix window:
exit_reason count total_pnl
------------------------------------
roi 30 +$22.14
trailing_stop_loss 2 +$2.59
time_exit_24h 9 -$13.01
trend_broken 5 -$7.94
early_loss_cut_2h 1 -$0.27
------------------------------------
TOTAL 47 -$0.49time_exit_24h was not a stop-loss. It was a tax. Nine trades closed at the 24-hour mark for an average loss of $1.44 per trade. In a strategy that averages $0.74 profit on its winners, losing $1.44 on a timeout is catastrophic — each one erases roughly two winners.
Worse: some of those trades were still in drawdown but had not yet reached the 6% stop-loss. The bot was cutting them out of impatience, not out of risk management.
The bug that wasn't a bug
The original time_exit_24h rule was a single line:
if trade_duration > 24 * 60:
return "time_exit_24h"Nothing wrong with it as code. Everything wrong with it as strategy.
The premise is "a trade that hasn't done anything in 24 hours is dead money, free the slot." The reality is "a trade that hasn't done anything in 24 hours in a low-volatility window will, more often than not, recover in the next six hours if you let it."
I confirmed it by running the same backtest window with time_exit_24hsimply commented out. Profit factor jumped from 1.03 to 1.27. Same entries, same everything, just don't kill positions on a clock.
But removing the exit entirely meant holding losing trades forever. I needed something between "cut at 24h" and "never cut."
V4: cascading early loss cut
The fix is five lines of logic:
def custom_exit(self, pair, trade, current_time, current_rate, current_profit, **kwargs):
hours_open = (current_time - trade.open_date_utc).total_seconds() / 3600
# Escalating check: the longer a trade bleeds, the tighter the threshold
if hours_open >= 4 and current_profit < -0.015:
return "early_loss_cut_4h" # -1.5% after 4h
if hours_open >= 2 and current_profit < -0.025:
return "early_loss_cut_2h" # -2.5% after 2h
# (time_exit_24h removed entirely)
return NoneThe idea: don't kill a trade on time alone. Kill it on unrealized loss plus time. A trade that's flat at hour 2 deserves more time. A trade that's down 2.5% at hour 2 is already telling you it was wrong. A trade that's down 1.5% at hour 4 and still hasn't recovered probably won't.
The key insight that took me too long to see: the best stop-loss in a wide-stop strategy isn't one threshold, it's a decay curve. The more time passes, the less drawdown you accept.
Backtest against the same 30-day window as the original strategy:
| Metric | V3 (time_exit_24h) | V4 (cascading early cut) |
|---|---|---|
| Total profit | baseline | +69% vs V3 |
| Max drawdown | baseline | −77% vs V3 |
| Win rate | 66.7% | 66.7% |
| Profit factor | 1.03 | 1.41 |
| Sharpe | 0.22 | 0.91 |
Win rate barely moves. Profit factor and Sharpe explode. The strategy wasn't losing because it picked bad trades — it was losing because it held bad trades wrong.
I also ran V5 (hard breakeven exit at 0% after 6h) and V6 (relaxed 4h threshold at −0.5%). Both underperformed V4. The 4h/−1.5% + 2h/−2.5% cascade turned out to be the local optimum on my data.
The deploy
April 13, 17:27 UTC. I restarted the Freqtrade process with V4 loaded. No other changes. Same pairs, same balance, same 6% stoploss, same confidence threshold.
Here's every trade that happened in the next 8 hours:
| # | Time | Pair | Exit | P&L |
|---|---|---|---|---|
| 49 | 10:00→16:05 | ATOM/USDT | early_loss_cut_4h | $0.00 |
| 50 | 12:00→00:44 | DOGE/USDT | roi | +$1.62 |
| 51 | 12:00→22:14 | LINK/USDT | roi | +$2.21 |
| 52 | 14:00→16:05 | SOL/USDT | early_loss_cut_2h | −$0.63 |
| 53 | 14:00→18:00 | AVAX/USDT | early_loss_cut_4h | −$0.21 |
| 54 | 15:00→19:00 | SUI/USDT | early_loss_cut_4h | −$0.17 |
+$2.82 net in 8 hours. Four winners, two losers.
Look at the four early_loss_cut trades. The average loss is −$0.25. The pre-fix average loss was −$1.27— five times larger. The strategy is doing the same thing it always did, except now losers cost one-fifth as much.
What the public dashboard shows today
Current state at the time of writing (April 15, 12:00 UTC):
- Balance: $506.35 (from $500)
- P&L: +$6.35 (+1.27%)
- Win rate: 64.81% (35W / 19L / 54 closed)
- Max drawdown during the run: 1.42%
- Open positions: 0
Annualized that's roughly 33% — not the "double your account in a week" pornography you see on YouTube, but it's an honest, reproducible, wide-stop strategy with a 1.42% drawdown. I'd rather have that than 300% with a 40% drawdown.
The trendrider.net/livepage reads the SQLite every 60 seconds and shows everything — winners, losers, exit reasons, equity curve, pair breakdown. If a losing trade happens, it will appear there within a minute.
What I learned the hard way
- Hard time exits are lazy risk management. They feel like a safety net. They're actually a tax on patience.
- "Not losing" is not the same as "not winning." Thirteen days of breakeven was hiding a solvable, specific problem. A raw P&L chart doesn't tell you that. An exit-reason breakdown does.
- Cascading beats single-threshold. Every risk decision in a wide-stop strategy should be a curve, not a line.
- Public SQLite forces honesty. Once you know anyone can load the same DB and check, you stop editing the screenshots. You start editing the strategy.
- V4 will break. The 4h/−1.5% threshold is tuned to current market regime. If BTC realized volatility doubles, so does the "normal" drawdown at hour 4, and V4 will cut profitable trades early. That's when I'll re-hyperopt and ship V5.
Open source
I'm releasing the exact strategy that produced the numbers above, under MIT, on GitHub. No affiliate, no gating, no "buy my course." The private bot has a few extras I'm keeping (Fear & Greed API, funding-rate signal, on-chain whale alerts, Telegram/Cornix routing), but everything that produced the 30-day backtest is in the public repo. You can clone it and backtest the same window.
- Repo: github.com/darkvolg/trendrider-strategy — MIT
- Live SQLite view: trendrider.net/live
- Strategy file:
TrendRiderStrategy.py - Sample config:
config.example.json(dry-run default)
If you run it and get different numbers, please open an issue — I want to know. If it helps you, star the repo. I'll keep publishing every fix, every breakage, every hyperopt result here.
What's next
- April 20: decision point for flipping one Bybit subaccount to live trading with $100. If the post-V4 curve holds, it goes live.
- Next re-hyperopt: when 20+ new V4 trades accumulate.
- V5 candidate: volume-aware cascade — tighter thresholds in high-vol regimes, looser in low-vol. Hypothesis is that the current V4 is too tight when BTC realized vol collapses. I'll backtest before shipping.
⭐ Open-source strategy
The exact Freqtrade strategy powering the live bot is on GitHub. MIT license, fully reproducible backtests. Star it if you find it useful.
Star on GitHub →Every number in this post is sourced from the bot's own SQLite (tradesv3.dryrun.sqlite). If you see a contradiction with /live, the dashboard is always the source of truth — this post is frozen at April 15, 12:00 UTC.