The Quest Begins (The “Why”)
I remember staring at a candlestick chart for a crypto token, feeling like I was stuck in a loop — just like Neo before he takes the red pill. The price kept jumping up and down, and every time I thought I’d spotted a trend, the market laughed and reversed. I kept asking myself: Is there a way to see through the noise?
That frustration pushed me to dive into technical analysis. I wasn’t looking for a crystal ball; I just wanted a couple of simple, reliable signals that could tell me when the market was likely to keep moving in one direction or when it was due for a pause. Moving averages and the Relative Strength Index (RSI) showed up again and again in tutorials, but the explanations felt dry, like reading a user manual for a spaceship. I wanted to feel how they work, not just copy‑paste formulas.
The Revelation (The Insight)
Here’s the thing: a moving average is just the market’s short‑term memory. It smooths out price fluctuations by averaging the last n periods, so you can see whether the current price is sitting above or below that average. If price is above the MA, the short‑term trend is bullish; below, it’s bearish.
The RSI, on the other hand, is like a tension gauge. It measures how hard the price has been pushing up versus down over a look‑back window (usually 14 periods) and spits out a value between 0 and 100. Above 70? The asset might be overbought — think of it as a rubber band stretched too far, ready to snap back. Below 30? It could be oversold, meaning selling pressure may be exhausted.
When you combine them, you get a richer picture: the moving average tells you which way the market is leaning, while the RSI hints at how exhausted that lean is. It’s like having both a compass and a fatigue meter on a hike.
Wielding the Power (Code & Examples)
Let’s get our hands dirty with some real Python. I’ll show a “before” version where I just eyeballed the price, then an “after” version where we add the indicators.
The Struggle – Raw Price Only
import pandas as pd
import yfinance as yf
# Grab some data
df = yf.download("BTC-USD", period="6mo", interval="1d")
print(df[['Close']].tail())
Output (just a snippet):
Close
Date
2024-09-20 26542.1
2024-09-21 26789.3
2024-09-22 27010.5
2024-09-23 26850.0
2024-09-24 27230.7
Looking at those numbers, it’s hard to say whether we’re in an uptrend or just a random bounce.
The Victory – Adding MA and RSI
First, we compute a 20‑day simple moving average (SMA) and the RSI. I’ll use the classic Wilder’s RSI formula because it’s easy to follow and shows the inner workings.
import numpy as np
# ----- 20‑day SMA -----
df['SMA_20'] = df['Close'].rolling(window=20).mean()
# ----- RSI (14‑day) -----
delta = df['Close'].diff()
gain = np.where(delta > 0, delta, 0)
loss = np.where(delta < 0, -delta, 0)
# Wilder's smoothing (alpha = 1/period)
period = 14
avg_gain = pd.Series(gain).ewm(alpha=1/period, adjust=False).mean()
avg_loss = pd.Series(loss).ewm(alpha=1/period, adjust=False).mean()
rs = avg_gain / avg_loss
df['RSI'] = 100 - (100 / (1 + rs))
# Show the latest row with our new columns
print(df[['Close', 'SMA_20', 'RSI']].tail())
Result (example):
Close SMA_20 RSI
Date
2024-09-20 26542.1 26012.3 58.4
2024-09-21 26789.3 26105.7 61.2
2024-09-22 27010.5 26230.1 64.7
2024-09-23 26850.0 26312.4 62.9
2024-09-24 27230.7 26421.8 66.3
Now the story is clearer:
- The price (
Close) is sitting above the 20‑day SMA, suggesting a short‑term bullish bias. - The RSI is hovering in the 55‑70 range — strong momentum but not yet into overbought territory (>70).
If the RSI crept past 70 while the price stayed above the SMA, I’d start watching for a possible pull‑back or a shift to a sideways consolidation. Conversely, if the price fell below the SMA and the RSI dropped under 30, that’d be a classic bearish signal.
Common Traps (The “Bosses” to Avoid)
Using the wrong window length – A 5‑day SMA reacts to every tick and looks noisy; a 200‑day SMA is so lazy it barely moves. I once tried a 5‑day SMA on daily crypto data and got whipsawed left and right. The fix? Match the window to your trading horizon: short‑term traders might use 10‑20, swing traders 50‑100, investors 200.
Forgetting to handle NaN values – The first n rows of a rolling average or RSI will be
NaNbecause there isn’t enough history. If you blindly feed those into a strategy, you’ll get unexpected errors or false signals. Always.dropna()or use.iloc[n:]before making decisions.Treating RSI > 70 as an automatic sell signal – In strong trends, the RSI can stay overbought for weeks. I learned this the hard way when I shorted a parabolic move just because the RSI flashed 78, only to watch the price keep climbing. Use RSI as a filter, not a trigger: look for divergence (price makes a new high, RSI makes a lower high) before acting.
Why This New Power Matters
Armed with these two indicators, I went from “guessing the market’s mood” to having a repeatable framework. I can now:
- Quickly gauge whether a pull‑back is likely just a breather or the start of a reversal.
- Build simple entry/exit rules (e.g., go long when price crosses above the SMA and RSI rises from below 50).
- Back‑test strategies with confidence, knowing the indicators are calculated correctly.
It’s like upgrading from a wooden sword to a lightsaber — still requires skill, but the tool does a lot of the heavy lifting for you.
Your Turn
Here’s a challenge: take the snippet above, swap the 20‑day SMA for an exponential moving average (EMA), and experiment with different RSI periods (9, 25). Plot the results with matplotlib and see how the signals shift.
What did you discover? Did the EMA give you earlier signals? Did a shorter RSI catch overbought/oversold zones faster? Drop your findings in the comments — let’s turn this into a shared quest log!
Happy coding, and may your trends be ever in your favor. 🚀
Top comments (0)