DEV Community

Gennady
Gennady

Posted on

How I Built a Profitable Crypto Trading Bot with Freqtrade and Bybit

How I Built a Profitable Crypto Trading Bot with Freqtrade and BybitMost crypto trading bots lose money. Not because algorithmic trading doesn't work, but because developers skip the boring parts -- backtesting, risk management, and proper validation. Here's how I built a system that actually performs, and the architecture decisions that made the difference.## Why FreqtradeI evaluated several frameworks before settling on Freqtrade. The alternatives -- CCXT-based custom solutions, Hummingbot, Jesse -- each had tradeoffs. Freqtrade won for three reasons:1. Native Bybit support with both spot and futures2. Built-in backtesting engine that accounts for fees and slippage3. Strategy abstraction that keeps signal logic separate from executionThe framework handles order management, position sizing, and exchange API quirks. You focus on the actual trading logic.## Architecture OverviewThe system runs on a VPS (Ubuntu, 2GB RAM is plenty) with this stack:


Freqtrade (strategy engine) | +-- Bybit API (execution) | +-- SQLite (trade history) | +-- REST API (monitoring) | +-- Telegram Bot (alerts)

The strategy itself is a Python class. Here's the skeleton:

pythonclass TrendRiderStrategy(IStrategy): minimal_roi = {"0": 0.05, "30": 0.025, "60": 0.01} stoploss = -0.03 trailing_stop = True trailing_stop_positive = 0.01 def populate_indicators(self, dataframe, metadata): dataframe['rsi'] = ta.RSI(dataframe, timeperiod=14) dataframe['ema_fast'] = ta.EMA(dataframe, timeperiod=8) dataframe['ema_slow'] = ta.EMA(dataframe, timeperiod=21) dataframe['macd'], dataframe['signal'], _ = ta.MACD( dataframe, fastperiod=12, slowperiod=26, signalperiod=9 ) return dataframe def populate_entry_trend(self, dataframe, metadata): dataframe.loc[ (dataframe['ema_fast'] > dataframe['ema_slow']) & (dataframe['rsi'] < 70) & (dataframe['macd'] > dataframe['signal']), 'enter_long' ] = 1 return dataframe

The real edge isn't in the indicators -- it's in the combination of entry conditions, exit timing, and risk parameters.## Backtesting: Where Most Bots FailHere's the part that took 80% of the development time. I backtested across:- 12 months of data (not just bull markets)- Multiple pairs (BTC/USDT, ETH/USDT, SOL/USDT)- Different market conditions (trending, ranging, crashing)The initial strategy had a 72% win rate in backtests but only 45% in forward testing. The gap came from overfitting to historical patterns. After stripping out the noise and keeping only robust signals, the numbers settled at a more honest 67.9% win rate with 1.42% max drawdown.

bashfreqtrade backtesting --strategy TrendRiderStrategy --timerange 20250101-20260101 --pairs BTC/USDT ETH/USDT SOL/USDT --fee 0.001

Key insight: if your backtest looks too good, it probably is. A strategy with 90%+ win rate almost certainly won't survive live markets.## Risk ManagementThe trailing stop configuration matters more than entry signals. My setup:- Initial stoploss: -3% (hard floor)- Trailing stop: activates at +1% profit- ROI table: takes profit at 5% immediately, 2.5% after 30 candles, 1% after 60This means the bot locks in gains quickly and cuts losses before they compound. The max drawdown of 1.42% over 12 months validates this approach.## Deployment and MonitoringRunning on a VPS with systemd for auto-restart:

ini[Unit]Description=Freqtrade Trading BotAfter=network.target[Service]ExecStart=/usr/bin/freqtrade trade --config config.jsonRestart=alwaysRestartSec=10

For monitoring, I built a dashboard that tracks every trade in real time. You can see the live performance at trendrider.net -- full transparency with P&L charts, drawdown tracking, and individual trade breakdown.## Lessons Learned1. Backtest on bear markets too. A strategy that only works in uptrends will blow up eventually.2. Fees eat profits. At 0.1% per trade, a strategy making 50 trades/day needs significant alpha to stay positive.3. Paper trade for at least 2 weeks before going live. API behavior differs from backtests in subtle ways.4. Keep it simple. My best-performing strategy uses 3 indicators. The one with 12 indicators performed worst.5. Monitor 24/7. A bot that silently stops trading at 3am is worse than no bot at all.## What's NextThe current system runs on Bybit with 5 pairs. I'm working on expanding to more pairs and adding a prop trading evaluation through HyroTrader. The goal is to prove the strategy works with real capital under professional scrutiny.If you're building something similar, start with Freqtrade's documentation and their Discord community. The framework handles 90% of the complexity -- your job is the strategy and the discipline to validate it properly.---Building a crypto trading bot? Check out the live performance dashboard at trendrider.net to see what transparent algo trading looks like.

Top comments (0)