Building a Crypto Trading Bot from Scratch - 9: Technical Indicators
First of all, Happy New Year, everyone! I am so excited for 2026 and with the growing potential we have achieved together with my Free and Paid subscribers on this platform. I had one thing in mind when I started this newsletter: that I really wanted to democratize the sophisticated ways of the trading world and tried to introduce the ways of quantitative strategies that might help us all in our daily trading lives. As you know, the barrier to entering this quant world is getting higher and higher. Even though we hear about all those juicy compensations at hedge funds and so on, it is a well-known fact that many people would like to learn such topics not just because they target such bloodthirsty professional quant world but rather just to help their own trading system. So it is really important for each of us to come together on this platform and learn things together in this new year!
So, again - Happy New Year, everyone! Thank you all for being with me all this time, and let’s rock 2026 by making more money together!
When I implemented the EMA crossover strategy, I glossed over one critical detail: calculating the actual exponential moving average. I just called calculate_ema(prices, period) and trusted it would work.
But implementing technical indicators correctly is harder than it looks. There are subtle bugs waiting to bite you, look-ahead bias, division by zero, NaN propagation, and off-by-one errors. Get it wrong, and your backtest looks amazing but your live trading loses money.
In this article, I’ll walk through implementing several popular indicators and show you the pitfalls I encountered along the way.
Why Implement Your Own Indicators?
You might be wondering: “Why not just use a library like TA-Lib or pandas-ta?”
Valid question. Here’s my thinking:
Reasons to use a library:
Battle-tested implementations
Comprehensive indicator coverage
Performance optimizations
Less code to maintain
Reasons to implement your own:
Understanding: You know exactly what the calculation does
Control: You can customize for your specific needs
Dependencies: Fewer external dependencies to manage
Learning: You understand technical analysis at a deeper level
For my trading bot, I went with a hybrid approach: implement the core indicators myself (EMA, SMA, RSI, MACD), and use libraries for more exotic ones if needed.
The Foundation: Simple Moving Average (SMA)
Let’s start with the simplest indicator: Simple Moving Average.
SMA is just the average of the last N prices:
SMA = (P1 + P2 + ... + PN) / N
Here’s a naive implementation:
def calculate_sma_naive(prices: List[float], period: int) -> List[float]:
“”“Calculate SMA - NAIVE VERSION (has issues).”“”
sma = []
for i in range(len(prices)):
if i < period - 1:
sma.append(None) # Not enough data yet
else:
window = prices[i - period + 1:i + 1]
sma.append(sum(window) / period)
return sma
This works, but it has issues:
Inefficient: Recalculates the sum for every window
Returns None: Some code expects NaN, not None
No validation: What if period is 0? Or negative?
Here’s my production version:


