This blog is all about the long-game. In July, I created this ARMA model to best predict portions of the stock market. I have nothing invested and I was just curious as to the best way to integrate some knowledge I drilled at university. It just so happens that I can learn some coding skills along the way.
My plan was to analyse the previous data, forecast using that information, and compare the model to the current month’s data. If this was somewhat accurate, it suggests that I can use this model for the next month’s data (August), followed by the next (September), etc. So, that’s what I’ve done. I’ve created a model that forecasts segments of the stock market in real-time.
To run this model, I have decided to create it in Python, or Jupyter Notebook. Since I’m using a Mac, I’ve used Terminal to install libraries, specifically, Yfinance. What you can see below is the shortened version of the 9 steps outline that could be taken to analyse stock data:
- Install Required Libraries (if not already installed),
- Import Libraries,
- Ignore Warnings
- Pull Live Data from the Stock Market,
- Evaluate Various Iterations of ARIMA Models,
- Fit an ARIMA Model,
- Diagnose the Model,
- Forecast the Stock,
- Insights from the Stock, and
- Real-Time, Live Feed Updates.
Alternatively, I have provided the .ipynb file here:
https://drive.google.com/file/d/1trM_rlTm4wIqqJv3ExnzZlrjrqL3hp0q/view?usp=sharing
Steps
1. Install Required Libraries (if not already installed):
In Terminal:
pip install yfinance statsmodels
If you don’t already have pip installed, visit this site first.
2. Import Libraries
In Jupyter Notebook:
Import Libraries:
import yfinance as yf
import statsmodels.api as sm
import matplotlib.pyplot as plt
from statsmodels.tsa.arima.model import ARIMA
import pandas as pd
import numpy as np
import itertools
from scipy.stats import norm
3. Ignore Warnings
import warnings
warnings.filterwarnings(“ignore”)
4. Pull Live Data from the Stock Market
Fetch Live Data:
def fetch_stock_data(ticker, period=’1d’, interval=’1m’):
stock_data = yf.download(ticker, period=period, interval=interval)
stock_data.index = pd.to_datetime(stock_data.index)
stock_data = stock_data.asfreq(‘T’) # Setting frequency to minute
return stock_data[‘Close’]
ticker = ‘AAPL’ # Example ticker
stock_prices = fetch_stock_data(ticker)
display(stock_prices)
4. Evaluate Various Iterations of ARIMA Models
This portion of the code is an automated process that analyses various iterations (18) of the ARIMA model (3x autoregressive, 2x integrated, and 3x moving average; 3x2x3 = 18). If you’re interested in adjusting the code, I have highlighted the areas to adjust; p_values, d_values, and p_values.
Grid Search for ARIMA Hyperparameters:
def evaluate_arima_model(stock_prices, arima_order):
try:
model = ARIMA(stock_prices, order=arima_order)
fitted_model = model.fit()
aic = fitted_model.aic
return aic
except:
return float(“inf”)
def grid_search_arima(stock_prices, p_values, d_values, q_values):
best_score, best_cfg = float(“inf”), None
for p in p_values:
for d in d_values:
for q in q_values:
order = (p, d, q)
aic = evaluate_arima_model(stock_prices, order)
if aic < best_score:
best_score, best_cfg = aic, order
print(f”ARIMA{order} AIC={aic}”)
return best_cfg
p_values = range(0, 3)
d_values = range(0, 2)
q_values = range(0, 3)
best_order = grid_search_arima(stock_prices, p_values, d_values, q_values)
print(f”Best ARIMA order: {best_order}”)
5. Fit an ARIMA Model
Fit ARIMA Model with Best Parameters:
def fit_arima_model(stock_prices, order):
model = ARIMA(stock_prices, order=order)
fitted_model = model.fit()
return fitted_model
fitted_model = fit_arima_model(stock_prices, best_order)
6. Diagnose the Model
Model Diagnostics:
def model_diagnostics(fitted_model):
summary = fitted_model.summary()
aic = fitted_model.aic
bic = fitted_model.bic
pvalues = fitted_model.pvalues
print(“Model Summary:”)
print(summary)
print(“\nAIC:”, aic)
print(“BIC:”, bic)
print(“P-Values:”)
print(pvalues)
model_diagnostics(fitted_model)
7. Forecast the Stock
Forecast Future Prices:
def forecast_prices(fitted_model, steps=10):
forecast = fitted_model.get_forecast(steps=steps)
forecast_df = forecast.summary_frame()
return forecast_df[‘mean’], forecast_df[‘mean_se’], forecast_df[[‘mean_ci_lower’, ‘mean_ci_upper’]]
forecast, stderr, conf_int = forecast_prices(fitted_model)
8. Insights from the Stock
This function is intended to assist the various profiles of investors to adjust their behaviour (risk-takers, risk-neutral, and risk-averse) based on the output. This covers how the stock prices change and are being forecasted. This output provides insights into both qualitative and quantitative factors of the strategy, including average return, recent volatility, and buy/sell signals based on z-score.
Quantitative and Qualitative Insights for Different Risk Profiles:
def analyse_investment(stock_prices, forecast, stderr, conf_int):
# Calculate key metrics
recent_volatility = np.std(stock_prices[-30:]) # Standard deviation of the last 30 prices
recent_return = stock_prices.pct_change().mean() # Average return
forecast_mean = forecast.mean()
forecast_std = forecast.std()
# Calculate recent price changes
recent_price_change = stock_prices.pct_change()[-30:]
# Calculate signal thresholds
z_scores = (recent_price_change – recent_price_change.mean()) / recent_price_change.std()
buy_signals = z_scores < -2 # Buy signal for extreme negative changes
sell_signals = z_scores > 2 # Sell signal for extreme positive changes
print(“\nInvestment Analysis:”)
# Analysis for risk-taker
print(“\nRisk-Taker:”)
print(“The recent volatility is relatively high, indicating significant price movements.”)
print(f”Recent Volatility: {recent_volatility:.2f}”)
print(f”Recent Return: {recent_return:.2%}”)
print(f”Forecasted Mean Price: {forecast_mean:.2f}”)
print(f”Forecasted Std Dev: {forecast_std:.2f}”)
print(f”Buy Signals: {buy_signals.sum()} instances in the last 30 minutes”)
print(f”Sell Signals: {sell_signals.sum()} instances in the last 30 minutes”)
print(“This could provide opportunities for high returns if the market moves favorably.”)
print(“However, the high uncertainty might also lead to substantial losses.”)
# Analysis for risk-neutral
print(“\nRisk-Neutral:”)
print(“The recent volatility suggests that the stock has both upward and downward potential.”)
print(f”Recent Volatility: {recent_volatility:.2f}”)
print(f”Recent Return: {recent_return:.2%}”)
print(f”Forecasted Mean Price: {forecast_mean:.2f}”)
print(f”Forecasted Std Dev: {forecast_std:.2f}”)
print(“The forecasted mean price is positive, indicating potential gains.”)
print(“The standard deviation of the forecast indicates a balanced risk/reward scenario.”)
# Analysis for risk-averse
print(“\nRisk-Averse:”)
print(“The recent volatility might be concerning, indicating a high level of uncertainty.”)
print(f”Recent Volatility: {recent_volatility:.2f}”)
print(f”Recent Return: {recent_return:.2%}”)
print(f”Forecasted Mean Price: {forecast_mean:.2f}”)
print(f”Forecasted Std Dev: {forecast_std:.2f}”)
print(“The confidence intervals around the forecast suggest potential risk of losses.”)
print(“It may be better to consider safer investment options or wait for more stability in the stock’s price.”)
analyse_investment(stock_prices, forecast, stderr, conf_int)
9. Real-Time, Live Feed Updates
Live Feed Update:
import time
def live_feed(ticker, interval=60, steps=10, p_values=range(0, 3), d_values=range(0, 2), q_values=range(0, 3)):
while True:
stock_prices = fetch_stock_data(ticker)
best_order = grid_search_arima(stock_prices, p_values, d_values, q_values)
fitted_model = fit_arima_model(stock_prices, best_order)
forecast, stderr, conf_int = forecast_prices(fitted_model, steps)
# Print the latest forecast
print(f”Forecasted Prices: {forecast}”)
# Plot the results
plt.figure(figsize=(12, 6))
plt.plot(stock_prices.index, stock_prices, label=’Actual Prices’)
plt.plot(pd.date_range(stock_prices.index[-1], periods=steps, freq=’T’), forecast, label=’Forecasted Prices’)
plt.fill_between(pd.date_range(stock_prices.index[-1], periods=steps, freq=’T’), conf_int[‘mean_ci_lower’], conf_int[‘mean_ci_upper’], color=’pink’, alpha=0.3)
plt.legend()
plt.show()
# Print model diagnostics
model_diagnostics(fitted_model)
# Provide investment analysis
analyse_investment(stock_prices, forecast, stderr, conf_int)
# Wait for the next update
time.sleep(interval)
live_feed(ticker, interval=60, steps=10)
Conclusion
I’ve taken advantage of this blog post to develop skills to forecast the stock market in real-time with an ARIMA model. It was enjoyable to revisit and apply the knowledge acquired during my university, but also further develop my coding skills. I leveraged some Python libraries to develop further insights into the model. I was interested in marrying my understanding behind the model capabilities, using live data, evaluating various ARIMA iterations, fitting the best model, and providing insightful forecasts.
The real value of this exercise lies in the ability to generate real-time predictions and insights that cater to different investor profiles—risk-taker, risk-neutral, and risk-averse. This nuanced analysis is crucial for making informed decisions in the ever-volatile stock market. The model’s capacity to adapt and improve with continuous data inputs suggests a promising tool for future forecasting endeavours.
While the accuracy of the model over a short-term period like one month might not be perfect, the iterative process of refining the model based on new data and understanding its limitations is where the true learning occurs. It’s a testament to the importance of continuous improvement and adaptation in both the fields of finance and data science.
Looking ahead, the potential to integrate more sophisticated techniques, such as machine learning algorithms or combining multiple time series models, could further enhance the predictive power of this approach. For now, this ARIMA model serves as a robust foundation for real-time stock market analysis, offering valuable insights and a practical application of theoretical knowledge.
As I continue to explore and refine this model, I remain excited about the possibilities it holds for better understanding market dynamics and aiding investors in making more informed decisions. This experience underscores the importance of blending theoretical knowledge with practical application, and I look forward to sharing more insights and advancements in future blog posts.


One response to “67 – Predicting the Stock Market in Real-Time with an ARIMA Model”
[…] in October of this year (2024), I made a post about using an ARIMA Stock Market Predictor Model in Python. Today is an update of that predictor. This is essentially what data, science, and […]