| Overall Statistics |
|
Total Trades 17 Average Win 11.34% Average Loss -4.76% Compounding Annual Return 8.180% Drawdown 17.000% Expectancy 1.538 Net Profit 60.305% Sharpe Ratio 0.738 Loss Rate 25% Win Rate 75% Profit-Loss Ratio 2.38 Alpha 0.11 Beta -1.253 Annual Standard Deviation 0.116 Annual Variance 0.013 Information Ratio 0.565 Tracking Error 0.116 Treynor Ratio -0.068 Total Fees $58.17 |
import numpy as np
from keras.models import Sequential
from keras.layers import Dense, Activation
from keras.optimizers import SGD
class KerasNeuralNetworkAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2013, 1, 1) # Set Start Date
self.SetEndDate(2019, 1, 1) # Set End Date
self.SetCash(100000) # Set Strategy Cash
spy = self.AddEquity("SPY", Resolution.Minute)
self.symbols = [spy.Symbol] # This way can be easily extended to multiply symbols
self.lookback = 30 # day of lookback for historical data
self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.AfterMarketOpen("SPY", 28), self.NetTrain) # train Neural Network
self.Schedule.On(self.DateRules.Every(DayOfWeek.Monday), self.TimeRules.AfterMarketOpen("SPY", 30), self.Trade)
def NetTrain(self):
# Daily historical data is used to train the machine learning model
history = self.History(self.symbols, self.lookback + 1, Resolution.Daily)
# dicts that store prices for training
self.prices_x = {}
self.prices_y = {}
# dicts that store prices for sell and buy
self.sell_prices = {}
self.buy_prices = {}
for symbol in self.symbols:
if not history.empty:
# x: pridictors; y: response
self.prices_x[symbol] = list(history.loc[symbol.Value]['open'])[:-1]
self.prices_y[symbol] = list(history.loc[symbol.Value]['open'])[1:]
for symbol in self.symbols:
if symbol in self.prices_x:
# convert the original data to np array for fitting the keras NN model
x_data = np.array(self.prices_x[symbol])
y_data = np.array(self.prices_y[symbol])
# build a neural network from the 1st layer to the last layer
model = Sequential()
model.add(Dense(10, input_dim = 1))
model.add(Activation('relu'))
model.add(Dense(1))
sgd = SGD(lr = 0.01) # learning rate = 0.01
# choose loss function and optimizing method
model.compile(loss='mse', optimizer=sgd)
# pick an iteration number large enough for convergence
for step in range(701):
# training the model
cost = model.train_on_batch(x_data, y_data)
# get the final predicted price
y_pred_final = model.predict(y_data)[0][-1]
# Follow the trend
self.buy_prices[symbol] = y_pred_final + np.std(y_data)
self.sell_prices[symbol] = y_pred_final - np.std(y_data)
def Trade(self):
'''
Enter or exit positions based on relationship of the open price of the current bar and the prices defined by the machine learning model.
Liquidate if the open price is below the sell price and buy if the open price is above the buy price
'''
for holding in self.Portfolio.Values:
if self.CurrentSlice[holding.Symbol].Open < self.sell_prices[holding.Symbol] and holding.Invested:
self.Liquidate(holding.Symbol)
if self.CurrentSlice[holding.Symbol].Open > self.buy_prices[holding.Symbol] and not holding.Invested:
self.SetHoldings(holding.Symbol, 1 / len(self.symbols))