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))