Intermediate
Technical Indicators
Calculate key technical indicators: RSI, MACD, Bollinger Bands, moving averages, and volume-based indicators that serve as features for the LSTM model.
Technical Indicator Calculations
# app/indicators.py
import pandas as pd
import numpy as np
class TechnicalIndicators:
@staticmethod
def rsi(series: pd.Series, period: int = 14) -> pd.Series:
delta = series.diff()
gain = delta.where(delta > 0, 0).rolling(period).mean()
loss = (-delta.where(delta < 0, 0)).rolling(period).mean()
rs = gain / loss
return 100 - (100 / (1 + rs))
@staticmethod
def macd(series: pd.Series, fast=12, slow=26, signal=9):
ema_fast = series.ewm(span=fast).mean()
ema_slow = series.ewm(span=slow).mean()
macd_line = ema_fast - ema_slow
signal_line = macd_line.ewm(span=signal).mean()
histogram = macd_line - signal_line
return macd_line, signal_line, histogram
@staticmethod
def bollinger_bands(series: pd.Series, period=20, std_dev=2):
sma = series.rolling(period).mean()
std = series.rolling(period).std()
upper = sma + (std * std_dev)
lower = sma - (std * std_dev)
width = (upper - lower) / sma
return upper, sma, lower, width
@staticmethod
def moving_averages(series: pd.Series):
return {
"sma_10": series.rolling(10).mean(),
"sma_20": series.rolling(20).mean(),
"sma_50": series.rolling(50).mean(),
"ema_12": series.ewm(span=12).mean(),
"ema_26": series.ewm(span=26).mean(),
}
def add_all(self, df: pd.DataFrame) -> pd.DataFrame:
close = df["Close"]
df["rsi"] = self.rsi(close)
df["macd"], df["macd_signal"], df["macd_hist"] = self.macd(close)
df["bb_upper"], df["bb_mid"], df["bb_lower"], df["bb_width"] = self.bollinger_bands(close)
mas = self.moving_averages(close)
for name, series in mas.items():
df[name] = series
df["price_sma_ratio"] = close / df["sma_20"]
return df.dropna()
Testing Indicators
from app.data_collector import StockDataCollector
from app.indicators import TechnicalIndicators
collector = StockDataCollector()
df = collector.fetch_history("AAPL")
ti = TechnicalIndicators()
df = ti.add_all(df)
print(f"Features: {list(df.columns)}")
print(f"RSI range: {df['rsi'].min():.1f} - {df['rsi'].max():.1f}")
print(f"Shape after indicators: {df.shape}")
Feature selection: Not all indicators improve predictions. Use correlation analysis and feature importance from a simple model to select the most predictive indicators for your target stock.
Key Takeaways
- RSI measures momentum: above 70 is overbought, below 30 is oversold.
- MACD captures trend direction and momentum through moving average crossovers.
- Bollinger Bands measure volatility: narrow bands suggest a breakout is coming.
- Combining multiple indicators as features gives the LSTM model richer context.
Lilly Tech Systems