Everyone builds a crypto bot at some point. Most lose money. Mine didn't — but not for the reasons I expected.
After 101 trades and 83 days of backtesting, here's what actually mattered.
The Strategy That Worked: OBV Accumulation
I tried three different strategies before finding one that held up. Moving average crossovers? Too many false signals. RSI divergence? Works in textbooks, not in crypto's 24/7 volatility.
What worked: On-Balance Volume (OBV) Accumulation.
The idea is simple — track volume flow before price moves. When OBV is accumulating (smart money buying) while price is flat or dipping, that's your signal.
def calculate_obv_accumulation(candles, lookback=20):
obv = [0]
for i in range(1, len(candles)):
if candles[i].close > candles[i-1].close:
obv.append(obv[-1] + candles[i].volume)
elif candles[i].close < candles[i-1].close:
obv.append(obv[-1] - candles[i].volume)
else:
obv.append(obv[-1])
# Accumulation = OBV rising while price is flat
obv_slope = linear_regression_slope(obv[-lookback:])
price_slope = linear_regression_slope(
[c.close for c in candles[-lookback:]]
)
return obv_slope > 0 and abs(price_slope) < threshold # e.g., 0.02
This catches the "smart money" accumulation phase — institutional buying that precedes price moves.
The Numbers (Real, Not Cherry-Picked)
- 101 backtested trades across Jan–Mar 2026
- 37.6% win rate — yes, fewer than half my trades win
- Risk-to-Reward: 2.33 — but winners are 2.3x bigger than losers
- Max drawdown: $0.31 per trade
That win rate looks bad until you do the math:
Expected value = (0.376 × 2.33) - (0.624 × 1.0) = 0.876 - 0.624 = +0.252
Every dollar risked returns $0.25 on average. That's the R:R discovery that changed everything for me — you don't need to be right most of the time, you need your wins to be bigger than your losses.
What I Got Wrong First
Mistake 1: No momentum exhaustion check
My first version would buy at the top of a pump because OBV was "accumulating." Added a momentum exhaustion gate:
def is_momentum_exhausted(candles, period=14):
recent_gains = sum(
c.close - c.open for c in candles[-period:]
if c.close > c.open
)
recent_losses = abs(sum(
c.close - c.open for c in candles[-period:]
if c.close < c.open
))
if recent_losses == 0:
return True # All gains, no pullback = exhausted
ratio = recent_gains / recent_losses
return ratio > 3.0 # Overbought threshold
This single check eliminated my worst trades.
Mistake 2: Same position size for everything
BNB and BTC don't move the same way. Volatility-adjusted sizing was the fix — smaller positions on volatile coins, bigger on stable ones. Sounds obvious in hindsight.
Mistake 3: No cooldown between trades
Without a per-symbol cooldown, the bot would enter and exit the same coin 3 times in an hour on noise. Added a 30-minute cooldown per symbol. Trade frequency dropped, profitability went up.
The Testing Obsession
The bot has 1,143 automated tests. That sounds excessive for a side project. It's not.
Crypto trades with real money. A bug isn't "the page looks weird" — it's "I just lost $500 at 3am while sleeping." Every safety mechanism has tests:
- Stop-loss caps per coin
- Anti-hedge protection (no conflicting long + short)
- Position recovery on restart
- Score velocity detection (blocks stale signals)
def test_anti_hedge_protection():
"""Bot must never hold LONG and SHORT on same symbol"""
bot.open_position("BTCUSDT", "LONG")
with pytest.raises(AntiHedgeError):
bot.open_position("BTCUSDT", "SHORT")
If you're building anything that touches money, test like your sleep depends on it — because it does.
The Stack
- Python 3.12 with asyncio (crypto = lots of concurrent WebSocket streams)
- PostgreSQL with asyncpg (connection pooling for high-frequency inserts)
- FastAPI dashboard for monitoring
- Docker for deployment (one command on any VPS)
- Telegram bot for trade alerts on my phone
Total infra cost: ~$5/month on a Hetzner ARM VPS.
What I'd Do Differently
Start with backtesting, not live trading. I wasted 2 weeks on live trades with an unproven strategy. Build the backtester first.
Track MFE (Maximum Favorable Excursion). This tells you how far winning trades go before reversing — critical for setting trailing stops from real data, not gut feeling.
Futures from day one. 80% of my best signals are SHORT opportunities in bear markets. Spot-only means you're blind to half the market.
Don't trust indicators in isolation. OBV alone isn't enough. The scoring system combines multiple signals, and the accumulation pattern is just the strongest weight.
Is It Worth Building Your Own?
If you want to learn: absolutely. I learned more about markets from building this bot than from any course or book.
If you want passive income: maybe. The bot works, but crypto is crypto — strategies degrade, markets change, exchanges update APIs. It's not "set and forget."
If you want guaranteed returns: no. And anyone promising that is lying.
The real value is the framework — once you have a tested backtesting engine, a solid executor, and proper safety mechanisms, you can swap strategies as markets evolve.
Building in public. Follow along for more real numbers, no hype.
Top comments (0)