Trading Bot

A year of systematic strategy testing against two years of market data.

I spent over a year building a cryptocurrency trading system: thirty-plus strategies, a backtesting engine, risk management, position sizing, and a full command-line control interface. The harder problem turned out to be measurement — building something I could trust enough to act on its results.

Terminal listing the trading bot's project files, strategies and core modules

Building the instrument

Before testing any strategy I had to be able to trust the measurement. The backtester models transaction costs explicitly — 0.26% exchange fees plus 0.15% slippage, 0.41% round trip — and reports Sharpe ratio, maximum drawdown, profit factor and win rate rather than raw returns. Hourly candles across six to twenty pairs, kept in local CSV so a run could be repeated exactly. The historical dataset went through several rounds: downloaders for two different exchanges, pairs added and dropped as strategies changed, older sets deleted when they stopped being relevant. What survives is a fraction of what was tested.

Trading bot configuration file with paper trading, risk management and strategy settings

What I tested

Flash crash recovery, volatility breakout, post-crash timing, whale tracking. When those underperformed I moved to the classical indicators — RSI, Bollinger Bands, MACD, momentum, mean reversion. Then a multi-filter integrated strategy combining trend, volatility and volume confirmation. Each round was a hypothesis, tested against the same two years of data, and the results are documented directly in the code — signal counts, win rates, and the parameter sweeps that produced them.

Terminal running a backtest of RSI, Bollinger, MACD and momentum strategies on six EUR trading pairs

Running it

The system ran from a command-line interface I built around it — start, stop, monitor, positions, performance, backup, reset. Paper trading was enforced in code rather than left as a setting, because the difference between a virtual balance and a real one is one config value and I did not trust myself to check it every time. For a period I moved the whole thing into containers to test it in a clean environment rather than against whatever my machine happened to have installed.

A bug in my own measurement

At one point the backtest was reporting 78% losses. The strategies weren’t that bad — the backtester was opening duplicate positions in the same symbol, compounding a single bad entry. Finding a methodological error in your own instrument is uncomfortable, and it’s also the moment the project became real research rather than wishful thinking.

What the numbers said

Transaction costs dominated. At 0.41% per round trip, a strategy targeting 2% per trade gives up a fifth of its margin before it starts, and none cleared that reliably across bull, bear and sideways market conditions. The system worked; the thesis didn’t. I closed it and moved on.

Terminal output of a parameter sweep test for flash crash, recovery timing and compression settings
Backtest summary: 30 tests, none meeting the 20% annual return and Sharpe 1.0 criteria

Sole developer, personal project · Python, pandas, NumPy, ccxt, SQLite, bash · 2024–⁠2025