Ensemble Modelling¶
In this Project, you are going to implement soft voting classifier machine learning model on Apple stock data. You can use other stock's data as well.
The notebook is structured as follows:
- Import Libraries and Data
- Split Data into Train and Test and Scale the Features
- Implement Voting Classifier
- Strategy Analysis
Import Libraries and Data¶
You will use the pandas and numpy libraries for data storage and manipulation. You will use the XGBoost, Logistic Regression, ADABoost, and SVM models which will be used by the voting classifier to predict the final output. You will be using the sklearn library for using the different ML models.
# Import libraries for data manipulation
import numpy as np
import pandas as pd
import os
# For machine learning models
import xgboost
from xgboost import XGBClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import VotingClassifier
from sklearn.ensemble import ExtraTreesClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.linear_model import LogisticRegression
from sklearn import svm
from sklearn.preprocessing import StandardScaler
# Import matplotlib as an alias plt and set the style
import matplotlib.pyplot as plt
%matplotlib inline
plt.style.use("seaborn-v0_8-whitegrid")
# Import sys to append the path for custom function file
import sys
sys.path.append(os.path.abspath("../.."))
# Import the custom function file
from Support.advanced_momentum_1_1 import target_var, train_test_split, \
generate_trade_sheet, trade_analytics, \
performance_metrics, predict_signals
# Ignore warnings
import warnings
warnings.filterwarnings('ignore')
Read the Data¶
You will use the Apple stock data stored in the file aapl_jan_2004_feb_2024.csv and aapl_jun_2020_jan_2024.csv.
Further, you will use the features generated from the encoder-decoder model stored in the csv file encoded_features_apple_momentum_jan_2006_jan_2024.csv. This file was created similar to the manner we created the features in the notebook Encoder-Decoder Approach to Reduce Features.
All the data files are stored in a downloadable zip file which is located in the summary section of the course.
# Import the pandas library and read the CSV file containing stock data
stock_data = pd.read_csv(
'../../Data/aapl_jan_2004_feb_2024.csv', index_col=0)
# Convert the index of the stock_data DataFrame to datetime format
stock_data.index = pd.to_datetime(stock_data.index)
aapl_test_prices = pd.read_csv(
'../../Data/aapl_jun_2020_jan_2024.csv', index_col=0)
# Import the pandas library again and read the CSV file containing encoded features
features = pd.read_csv(
'../../Data/encoded_features_apple_momentum_jan_2006_jan_2024.csv', index_col=0)
Calculate Target Variable¶
Now, you will create the target variable which checks whether the momentum indicator for a period of 20 is positive or not.
# Function call
target = target_var(stock_data, 20)
# Display the last 5 rows of the target dataframe
target.head()
| signal | |
|---|---|
| Date | |
| 2004-01-02 | 1 |
| 2004-01-05 | 1 |
| 2004-01-06 | -1 |
| 2004-01-07 | -1 |
| 2004-01-08 | -1 |
The features dataframe contains encoded features that start two years after the date range covered by the target dataframe. This is because certain technical indicators have a lookback period of 504.
Thus, we will make sure both features and target variables are of the same length.
# Find the start date from the 'features' dataframe
start_date = features.index[0]
# Select rows from 'stock_data' starting from the start date
target = target.loc[start_date:]
Split Data into Train and Test and Scale the Features¶
You will use the function train_test_split saved in the amtmls_util_quantra file to perform the functions of splitting the dataset and scaling the X_test dataframe.
# Split dataset and store the scaler
X_train, X_test, y_train, y_test, scaler = train_test_split(features, target, split_proportion=0.8)
Implement Voting Classifier¶
You are using four machine learning models, XGBoost, Logistic Regression, ADABoost, and SVM models whose predicted output will be aggregated by the voting classifier model, and depending on the type of voting, the final output will be generated.
# --------------- Classifier 1: XGBoost ------------------------------------------
xgb = XGBClassifier(n_estimators=15, max_depth=3,
random_state=42, eval_metric='logloss')
# --------------- Classifier 2: Logistic Regression Classifier------------------------------------------
lr = LogisticRegression(random_state=42)
# --------------- Classifier 3: AdaBoost Classifier ------------------------------------------
ada = AdaBoostClassifier(n_estimators=15, random_state=42)
# --------------- Classifier 4: SVM------------------------------------------
svc = svm.SVC(kernel='rbf', probability=True, random_state=42)
# Define a list to store the different models
estimator = []
estimator.append(('LR', lr))
estimator.append(('XGB', xgb))
estimator.append(('ada', ada))
estimator.append(('SVC', svc))
Soft Voting Classifier Model¶
After defining the base learners, you will define the voting classifier model. For this capstone project, you will implement the soft voting classifier model now.
# Implement voting classifier with hard voting
vot_soft = VotingClassifier(estimators=estimator, voting='soft')
# Fit the voting classifier model
vot_soft.fit(X_train, y_train)
VotingClassifier(estimators=[('LR', LogisticRegression(random_state=42)),
('XGB',
XGBClassifier(base_score=None, booster=None,
callbacks=None,
colsample_bylevel=None,
colsample_bynode=None,
colsample_bytree=None, device=None,
early_stopping_rounds=None,
enable_categorical=False,
eval_metric='logloss',
feature_types=None,
feature_weights=None, gamma=None,
grow_poli...
max_cat_threshold=None,
max_cat_to_onehot=None,
max_delta_step=None, max_depth=3,
max_leaves=None,
min_child_weight=None, missing=nan,
monotone_constraints=None,
multi_strategy=None,
n_estimators=15, n_jobs=None,
num_parallel_tree=None, ...)),
('ada',
AdaBoostClassifier(n_estimators=15,
random_state=42)),
('SVC', SVC(probability=True, random_state=42))],
voting='soft')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook. On GitHub, the HTML representation is unable to render, please try loading this page with nbviewer.org.
Parameters
Parameters
Parameters
Parameters
Parameters
Use Trained Model to Predict Target Variable¶
Once you have trained the model, you will use the test features dataset which has not been seen by the model and give the signal buy, which is 1, or sell, which is -1. You will use the function predict_signals, which takes the test dataset and using the trained model, predicts the target variable and provides the signal.
# Generate trading signals
signals = predict_signals(X_test, aapl_test_prices, vot_soft, scaler)
Strategy Analysis¶
Now that you have predicted whether the stock is in momentum or not, you will generate the trade sheet.
# Generate trade sheet
trade_sheet = generate_trade_sheet(signals)
# Display trade sheet
trade_sheet
| Position | Entry Date | Entry Price | Exit Date | Exit Price | PnL | |
|---|---|---|---|---|---|---|
| 0 | 1.0 | 08-06-2020 | 81.53 | 06-10-2020 | 110.86 | 29.33 |
| 1 | -1.0 | 07-10-2020 | 112.74 | 08-04-2021 | 128.13 | -15.39 |
| 2 | 1.0 | 09-04-2021 | 130.72 | 08-06-2021 | 124.78 | -5.94 |
| 3 | -1.0 | 09-06-2021 | 125.16 | 08-07-2021 | 141.02 | -15.86 |
| 4 | 1.0 | 09-07-2021 | 142.87 | 06-08-2021 | 144.09 | 1.22 |
| 5 | -1.0 | 09-08-2021 | 144.05 | 07-09-2021 | 154.50 | -10.45 |
| 6 | 1.0 | 08-09-2021 | 152.94 | 06-10-2021 | 140.01 | -12.93 |
| 7 | -1.0 | 07-10-2021 | 141.28 | 04-11-2021 | 148.85 | -7.57 |
| 8 | 1.0 | 05-11-2021 | 149.38 | 08-03-2022 | 155.66 | 6.28 |
| 9 | -1.0 | 09-03-2022 | 161.11 | 06-04-2022 | 169.89 | -8.78 |
| 10 | 1.0 | 07-04-2022 | 170.20 | 06-05-2022 | 155.73 | -14.47 |
| 11 | -1.0 | 09-05-2022 | 150.56 | 07-06-2022 | 147.25 | 3.31 |
| 12 | 1.0 | 08-06-2022 | 146.50 | 09-08-2023 | 177.49 | 30.99 |
| 13 | -1.0 | 10-08-2023 | 177.27 | 09-10-2023 | 178.53 | -1.26 |
| 14 | 1.0 | 10-10-2023 | 177.93 | 07-12-2023 | 194.02 | 16.09 |
You will use the function trade_analytics which gives the summary of the trades carried out.
# Trade Analytics
trade_analysis = trade_analytics(trade_sheet)
# Display the analytics
trade_analysis
| Strategy | |
|---|---|
| Total PnL | -5.43 |
| Total Trades | 15 |
| Number of Winners | 6 |
| Number of Losers | 9 |
| Win (%) | 40.0 |
| Loss (%) | 60.0 |
| Average Profit of Winning Trade | 14.54 |
| Average Loss of Losing Trade | 10.29 |
| Average Holding Time | 34 days 16:00:00 |
| Profit Factor | 0.94 |
You can see that from June 8, 2020, to December 7, 2023, the momentum trading strategy-based ML model took 15 trades with different profit and loss amounts. The strategy is overall positive with a profit of $32.3. The profit factor is 1.48 with 8 winning trades and 7 losing trades. Let's check the performance analytics now.
# Analyse performance metrics
performance = performance_metrics(signals)
Strategy CAGR -1.43% Annualised Volatility 29.74% Sharpe Ratio 0.03 Maximum Drawdown -63.35%
Conclusion¶
You have tried the momentum trading strategy on Apple stock data using multiple ML models and the reduced features which were created by the autoencoder (Encoder-Decoder) model. You can tweak this strategy by using different features and combining different ML models as well.