How to Calculate Probability Distribution of Stock Returns in Python
- Intrendias

- Oct 5, 2024
- 2 min read
This coding tutorial calculates the probability distribution of weekly stock returns to capture a stock's volatility and measure the probability of a stock increasing by a threshold percentage. Calculating the stock return probability distribution is popular in statistics, quantitative analysis, and algorithmic trading to forecast future stock prices and assess risk management. The probability distribution of stock returns represents the likelihood of different returns that a stock might generate over a certain period. This coding tutorial uses the normal distribution for model simplicity.
This coding video takes advantage of the yfinance python library to gather historic stock prices to derive weekly stock returns as a percentage. This coding tutorial also uses the scipy library for the normal distribution functions like the survival function. The survival function (also known as the complementary cumulative distribution function, or CCDF) in the context of normal distributions describes the probability that a random variable x takes on a value greater than a certain threshold.
Let's jump into the code and see how to calculate probability distribution of stock returns in python below! Check out the full video tutorial on YouTube!
import pandas as pd
import numpy as np
import yfinance as yf
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import norm
import scipy.stats as stats
ticker = 'BTC-USD'
df = yf.download(ticker,period='10y',interval='1d')
weekly_data = df.resample('W').agg({'Close':['first','last']})
weekly_data.columns = ['start_of_week_price','end_of_week_price']
weekly_data['start_of_week'] = weekly_data.index - pd.offsets.Week(weekday=0) + pd.offsets.BDay(0)
weekly_data['end_of_week'] = weekly_data.index - pd.offsets.Week(weekday=4) + pd.offsets.BDay(0)
weekly_data['PriceChange'] = weekly_data['end_of_week_price'] - weekly_data['start_of_week_price']
weekly_data['PercentChange'] = (weekly_data['PriceChange'] / weekly_data['start_of_week_price'])*100
percent_changes = weekly_data['PercentChange'].dropna()
# Plot the histogram
plt.figure(figsize=(10, 6))
sns.histplot(percent_changes, bins=30, kde=True, stat="density")
(mu, sigma) = norm.fit(percent_changes)
xmin, xmax = plt.xlim()
x = np.linspace(xmin, xmax, 100)
p = norm.pdf(x,mu,sigma)
plt.plot(x,p,'k',linewidth=2)
plt.axvline(mu,color='r', linestyle='dashed', linewidth=2)
plt.axvline(mu+sigma, color='g', linestyle='dashed', linewidth=2)
plt.axvline(mu - sigma, color='g', linestyle='dashed', linewidth=2)
plt.axvline(mu + 2*sigma, color='b', linestyle='dashed', linewidth=2)
plt.axvline(mu - 2*sigma, color='b', linestyle='dashed', linewidth=2)
# Add labels for the lines
plt.text(mu, plt.ylim()[1] * 0.9, 'mean', color='r', ha='center')
plt.text(mu + sigma, plt.ylim()[1] * 0.8, '+1σ', color='g', ha='center')
plt.text(mu - sigma, plt.ylim()[1] * 0.8, '-1σ', color='g', ha='center')
plt.text(mu + 2*sigma, plt.ylim()[1] * 0.7, '+2σ', color='b', ha='center')
plt.text(mu - 2*sigma, plt.ylim()[1] * 0.7, '-2σ', color='b', ha='center')
title = "Fit results: mu = %.2f, sigma = %.2f" % (mu, sigma)
plt.title(title)
plt.xlabel('Percent Change')
plt.ylabel('Density')
plt.show()threshold = 5
probability = norm.sf(threshold, loc=mu, scale=sigma)
print(f"The probability of {ticker} stock going up more than {threshold}% in one week is {round(probability*100,1):.1f}%")The probability of BTC-USD stock going up more than 5% in one week is 31.7%.
I hope this code is helpful! Check out other coding blog posts and algorithmic trading videos on my channel! Happy trading!
Was this code helpful?
Yes
No
*Intrendias is not financial advice.






Comments