67 – Predicting the Stock Market in Real-Time with an ARIMA Model

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:

  1. Install Required Libraries (if not already installed),
  2. Import Libraries,
  3. Ignore Warnings
  4. Pull Live Data from the Stock Market,
  5. Evaluate Various Iterations of ARIMA Models,
  6. Fit an ARIMA Model,
  7. Diagnose the Model,
  8. Forecast the Stock,
  9. Insights from the Stock, and
  10. 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”

Leave a comment