How to Build a Technical Analysis and Trading Strategy Workflow with pandas-ta-classic
In this tutorial, we demonstrate how to use pandas-ta-classic for implementing a complete technical analysis and trading strategy workflow. We begin by installing the necessary libraries, including pandas-ta-classic, yfinance, and matplotlib. Next, we download historical OHLCV stock data of Apple (AAPL) from January 1, 2018 to December 31, 2024 using the yfinance library. We then clean and preprocess this data by converting it into a DataFrame with appropriate column names.
- **Install Required Libraries**:
_pip(["pandas-ta-classic", "yfinance", "matplotlib"]) - **Download Historical Data**:
yf.download(TICKER, start=START, end=END) - **Clean and Process Data**:
raw.rename(columns=str.lower).rename(columns={"open": "Open", "high": "High", "low": "Low", "close": "Close", "volume": "Volume"}).dropna().copy()
We then calculate popular technical indicators such as Simple Moving Average (SMA), Exponential Moving Average (EMA), Relative Strength Index (RSI), Average True Range (ATR), MACD, Bollinger Bands, and candlestick patterns using the .ta DataFrame extension. We also apply a custom distance-from-EMA feature to enhance our strategy.
df.ta.sma(length=20)df.ta.sma(length=50)df.ta.ema(length=200)df.ta.rsi(length=14)df.ta.atr(length=14)df.ta.macd(append=True)df.ta.bbands(length=20, std=2.0)my_strategy = ta.Strategy(name="AdvancedDemo", ...)
We then run a multi-indicator strategy using ta.strategy(my_strategy), which incorporates various indicators like HMA, ADX, Aroon Oscillator, Stochastic Oscillator, On-Balance Volume (OBV), Money Flow Index (MFI), Williams %R (Willr), Commodity Channel Index (CCI), and Kaufman’s Adaptive Moving Average (Kc). We also detect Doji candle patterns using df.ta.cdl_doji(append=True).
df["dist_ema200_pct"] = (df["close"] / df["EMA_200"]) - 1.0 * 100df.ta.cdl_doji(append=True)
To ensure we have a comprehensive view of the strategy, we calculate weekly RSI for higher timeframes and join it back to our daily DataFrame. We define entry and exit conditions based on trends, momentum signals, and multi-timeframe indicators like Bollinger Bands.
weekly = df[["open", "high", "low", "close", "volume"]].resample("W-FRI").agg({"open":"first","high":"max","low":"min","close":"last","volume":"sum"})df["RSI_W_14"] = ta.rsi(weekly["close"], length=14)df.ta.cdl_doji(append=True)
We then create a weekly version of the daily OHLCV data and calculate RSI for higher timeframes. We join this back to our daily DataFrame and shift it so that we do not use future information in our trading logic. We define entry conditions based on trends, momentum signals, and multi-timeframe indicators like Bollinger Bands. Finally, we create a position variable to track whether the strategy is long or short at each time step.
We finally calculate performance metrics such as CAGR (Compound Annual Growth Rate), volatility, Sharpe ratio, Sortino ratio, maximum drawdown, win rate, and final equity using our defined perf function. We compare these results against a simple buy-and-hold strategy to determine whether the added signal logic improves performance.
Key Takeaways
- We used pandas-ta-classic for implementing a comprehensive technical analysis workflow.
- Indicator calculations were performed using the .ta DataFrame extension, including popular indicators like SMA, EMA, RSI, and Bollinger Bands.
- A custom multi-indicator strategy was applied to enhance our trading signals.
- We used weekly data for higher timeframes, ensuring that we did not use future information in our backtest.
- Performance metrics were calculated using the
perffunction to evaluate the effectiveness of our strategy compared to a simple buy-and-hold approach.
For those interested in the technical details and further exploration, you can refer to the provided code snippets for more information on each step.
Stay ahead of AI. Get the most important stories delivered to your inbox — no spam, no noise.




