| Overall Statistics |
|
Total Orders 0 Average Win 0% Average Loss 0% Compounding Annual Return 0% Drawdown 0% Expectancy 0 Start Equity 100000 End Equity 100000 Net Profit 0% Sharpe Ratio 0 Sortino Ratio 0 Probabilistic Sharpe Ratio 0% Loss Rate 0% Win Rate 0% Profit-Loss Ratio 0 Alpha 0 Beta 0 Annual Standard Deviation 0 Annual Variance 0 Information Ratio -1.681 Tracking Error 0.109 Treynor Ratio 0 Total Fees $0.00 Estimated Strategy Capacity $0 Lowest Capacity Asset Portfolio Turnover 0% |
'''
Random Forest classifier to predict the direction of SPY's price movement and trades options accordingly.
'''
from AlgorithmImports import *
# Import necessary libraries for machine learning
from sklearn.ensemble import RandomForestClassifier
import numpy as np
class SPYOptionMLTradingAlgorithm(QCAlgorithm):
'''
Initializes the algorithm with necessary parameters and settings.
'''
def Initialize(self):
self.SetStartDate(2023, 1, 2)
self.SetEndDate(2023, 12, 31)
self.SetCash(100_000)
self.spy = self.AddEquity("SPY", Resolution.Minute)
self.lookback = 30
self.training_data = []
self.model = RandomForestClassifier(n_estimators=10)
# Schedules the model training to occur at the start of each month.
self.schedule.on(self.date_rules.month_start("SPY"), self.time_rules.after_market_open("SPY", 30), self.TrainModel)
# Schedule trading logic to run before market close every day
self.Schedule.On(self.date_rules.every_day("SPY"), self.time_rules.before_market_close("SPY", 10), self.TradeOptions)
# Schedule liquidation of all holdings at 3:55 PM
self.Schedule.On(self.date_rules.every_day(), self.time_rules.at(15, 55), lambda: self.Liquidate())
'''
Trains the Random Forest model using historical SPY price data.
'''
def TrainModel(self) -> None:
history = self.History(self.spy.Symbol, self.lookback + 1, Resolution.Daily)
if history.empty or history.isnull().values.any():
return
# Calculate features and labels for the model
features = np.diff(history['close'])
labels = np.where(features >= 0, 1, 0)[:-1]
features = features.reshape(-1, 1)[:-1]
# Fit the model to the training data
self.model.fit(features, labels)
'''
Predicts the direction of SPY's price movement and trades options accordingly.
'''
def TradeOptions(self):
# Get the current SPY price and calculate the feature for prediction
today_features = np.array([self.spy.Price - self.spy.Close])
# Make a prediction using the trained model
prediction = self.model.predict(today_features.reshape(1, -1))
# Buy a call option if the prediction is positive, otherwise buy a put option
if prediction[0] == 1:
option = self.BuyCallOption()
else:
option = self.BuyPutOption()
# If an option contract is found, place a market order to buy it
if option is not None:
# Check if the option contract exists in the security list before placing an order
if self.Securities.ContainsKey(option):
self.MarketOrder(option, 1)
else:
self.Log("Option contract not found in security list: " + str(option))
'''
Returns a call option contract with the closest expiration date.
'''
def BuyCallOption(self):
return self.GetOptionContract(True)
'''
Returns a put option contract with the closest expiration date.
'''
def BuyPutOption(self):
return self.GetOptionContract(False)
'''
Returns an option contract based on the specified option type (call or put) and closest expiration date.
'''
def GetOptionContract(self, is_call):
contracts = self.option_chain_provider.get_option_contract_list(self.spy.Symbol, self.Time)
if is_call:
contracts = [i for i in contracts if i.ID.OptionRight == OptionRight.Call]
else:
contracts = [i for i in contracts if i.ID.OptionRight == OptionRight.Put]
# Sort contracts by expiration date and select the closest one
contracts = sorted(contracts, key=lambda x: abs((x.ID.Date - self.Time).days))
zero_dte_contracts = [i for i in contracts if (i.ID.Date - self.Time).days == 0]
if zero_dte_contracts:
return zero_dte_contracts[0]
else:
return None