Constructing a simple Momentum Portfolio using past returns
Introduction:
As a quant investor or programmer, leveraging Python to analyze stock data can offer you a competitive edge. In this article, we’ll explore a comprehensive Python-based strategy to analyze stock performance, identify trends, and rank stocks based on momentum.
Influence of Research Papers: Key Insights
Our quant strategy is deeply influenced by several groundbreaking research papers that have shaped the understanding of financial markets and stock performance analysis. Here are the key papers and insights that informed our approach:
- Frog in the Pan — Stocks with Smoother Path Give Better Momentum Returns
Read the paper - 52 Week High Effect — Evidence from India
Read the paper - Absolute Momentum — Its Overlay on Trend Following
Read the paper
Why Python for Stock Analysis?
Python has emerged as a preferred tool for financial analysis due to its simplicity, robust libraries, and ease of handling large datasets. With libraries like yfinance
, pandas
, numpy
, and matplotlib
, you can fetch, manipulate, and visualize financial data efficiently.
Getting Started: Setting Up Your Environment
Before diving into the analysis, ensure you have the necessary Python libraries installed. You can install them using pip
:
pip install yfinance pandas numpy matplotlib
Step 1: Importing Libraries and Initializing Variables
First, import the required libraries and set up the list of stock tickers you wish to analyze. These tickers represent major companies listed on the National Stock Exchange (NSE) of India.
import yfinance as yf
import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import matplotlib.pyplot as plt
tickers = ["RELIANCE.NS", "TCS.NS", "HDFCBANK.NS", ...] # Add more tickers as needed
Step 2: Fetching Historical Stock Data
Use yfinance
to fetch historical stock data for the past two years. The data includes daily closing prices, which are crucial for calculating moving averages and returns.
def get_data(ticker, start_date, end_date):
return yf.download(ticker, start=start_date, end=end_date)
end_date = datetime.today()
start_date = end_date - timedelta(days=365 * 2)data = {}
for ticker in tickers:
try:
stock_data = get_data(ticker, start_date, end_date)
if len(stock_data) > 0:
data[ticker] = stock_data
except Exception as e:
print(f"Error fetching data for {ticker}: {e}")
Step 3: Calculating Key Indicators
For each stock, calculate the 100-day and 200-day Exponential Moving Averages (EMAs). These EMAs help identify long-term trends and signal potential buying or selling opportunities.
for ticker, df in data.items():
df['EMA100'] = df['Close'].ewm(span=100).mean()
df['EMA200'] = df['Close'].ewm(span=200).mean()
Step 4: Analyzing Stock Performance
We analyze stocks based on several criteria:
- 1-Year Return: Measures the stock’s performance over the past year.
- 52-Week High Proximity: Checks if the stock is within 20% of its 52-week high, indicating strong momentum.
- Percentage of Up Days: Calculates the percentage of positive trading days over the last 6 months.
summary = []
for ticker, df in data.items():
try:
one_year_return = (df['Close'][-1] / df['Close'][-252] - 1) * 100
high_52_week = df['Close'][-252:].max()
within_20_pct_high = df['Close'][-1] >= high_52_week * 0.8 six_month_data = df['Close'][-126:]
up_days = (six_month_data.pct_change() > 0).sum()
up_days_pct = up_days / len(six_month_data) * 100 if (df['Close'][-1] >= df['EMA100'][-1] >= df['EMA200'][-1] and
one_year_return >= 6.5 and
within_20_pct_high and
up_days_pct > 50): return_6m = (df['Close'][-1] / df['Close'][-126] - 1) * 100
return_3m = (df['Close'][-1] / df['Close'][-63] - 1) * 100
return_1m = (df['Close'][-1] / df['Close'][-21] - 1) * 100 summary.append({
'Ticker': ticker,
'Return_6M': return_6m,
'Return_3M': return_3m,
'Return_1M': return_1m,
})
except Exception as e:
print(f"Error analyzing {ticker}: {e}")
Step 5: Ranking Stocks Based on Performance
Convert the summary into a DataFrame and rank the stocks based on their 6-month, 3-month, and 1-month returns. The final rank is determined by the sum of these individual ranks.
df_summary = pd.DataFrame(summary)
df_summary['Return_6M'] = df_summary['Return_6M'].round(1)
df_summary['Return_3M'] = df_summary['Return_3M'].round(1)
df_summary['Return_1M'] = df_summary['Return_1M'].round(1)
df_summary['Rank_6M'] = df_summary['Return_6M'].rank(ascending=False)
df_summary['Rank_3M'] = df_summary['Return_3M'].rank(ascending=False)
df_summary['Rank_1M'] = df_summary['Return_1M'].rank(ascending=False)df_summary['Final_Rank'] = df_summary['Rank_6M'] + df_summary['Rank_3M'] + df_summary['Rank_1M']
df_summary_sorted = df_summary.sort_values('Final_Rank').head(30)
df_summary_sorted['Position'] = np.arange(1, len(df_summary_sorted) + 1)
Step 6: Visualizing the Results
Create a table to visualize the top 30 stocks based on the final rank. Highlight the top 15 stocks with a red line to distinguish them from the rest.
tbl_data = []
for i, row in df_summary_sorted.iterrows():
tbl_data.append([row['Ticker'],
row['Return_6M'], row['Rank_6M'],
row['Return_3M'], row['Rank_3M'],
row['Return_1M'], row['Rank_1M'],
row['Final_Rank'], row['Position']])
fig, ax = plt.subplots(figsize=(14, 10))
ax.axis('tight')
ax.axis('off')col_labels = ['Ticker', 'Return_6M', 'Rank_6M', 'Return_3M', 'Rank_3M', 'Return_1M', 'Rank_1M', 'Final_Rank', 'Position']
table = ax.table(cellText=tbl_data, colLabels=col_labels, cellLoc='center', loc='center')
table.auto_set_font_size(False)
table.set_fontsize(12)
table.scale(1, 1.5)for i in range(len(col_labels)):
cell = table[(15, i)]
cell.set_edgecolor('red')
cell.set_linewidth(3)plt.subplots_adjust(left=0.1, top=0.85)
plt.title('Top 30 Stocks Momentum Ranking', fontsize=18, y=1.05)
plt.show()
Results
This is how the results look like :
Conclusion
By following this Python-based strategy, you can efficiently analyze stock data, identify trends, and make data-driven investment decisions. This approach not only saves time but also provides a systematic way to rank and filter stocks based on performance metrics.
Whether you’re a quant investor or a programmer, integrating Python into your stock analysis toolkit can significantly enhance your ability to analyze and interpret financial data.
Link to Github https://github.com/Momentum1ab/MomentumScreener/blob/main/1%2C3%2C6m_MomentumScreener.ipynb
You can watch our detailed video explaining on the methodology of their research here
— — — — — — — — — — — — — — — — — — — — — —
QuantX-Builder for Mastering Momentum Investing. 4 week comprehensive learning programme.
bit.ly/QuantX-MomentumLAB
— — — — — — — — — — — — — — — — — — — — — —
Important Links
Youtube: https://www.youtube.com/@MomentumLab_IN
Twitter: https://x.com/MomentumLab_IN
**Disclaimer:** We are not SEBI registered advisors. Any content shared on or through our digital media channels is for information and education purposes only and should not be treated as investment or trading advice.