top of page

How to Calculate Probability Distribution of Stock Returns in Python

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!


Probability Distribution of Stock Returns in Python
Probability Distribution of Stock Returns in Python
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()
Probability Distribution of Stock Returns
Probability Distribution of Stock Returns
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


bottom of page