Skip to content
All library documents

Weekly Neural Network Price Forecasts for Equity Trading

Article Strategy library · Author: QuantConnect

Summary

This algorithm trains a separate feedforward neural network for each of three exchange-traded funds using recent daily opening prices. The model uses one input layer with a hidden ReLU layer and a single output, and is trained to predict the next opening price from the preceding price. Training is scheduled weekly, with recent history refreshed before fitting. The code also saves and reloads models through persistent object storage.

For trading, it compares the current opening price with the latest model prediction adjusted by the standard deviation of recent opening prices. An existing holding is liquidated when price falls below the lower threshold; a new position is opened when price rises above the upper threshold. Positions are allocated equally across the tracked securities. The document is implementation code, not a research report: it supplies no performance statistics, benchmark comparison, or evidence of predictive value. It also leaves details such as transaction costs and model validation unaddressed, so the rules require independent testing before they can support conclusions about trading efficacy.

Key ideas

  • The code trains a separate neural network for each of three equity ETFs using recent daily opening prices.
  • Each model learns to map an opening price to the following day's opening price.
  • Trading compares the current open with the latest forecast plus or minus recent price variability.
  • The algorithm schedules weekly training and saves models between runs.
  • No backtest results or validation evidence are provided.

Tags

Full text
# KerasNeuralNetworkAlgorithm


# KerasNeuralNetworkAlgorithm









## Source (Apache-2.0)

```python
# QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
# Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from AlgorithmImports import *

from keras.models import *
from tensorflow import keras
from keras import Sequential
from keras.layers import Dense, Activation
from keras.optimizers import SGD

class KerasNeuralNetworkAlgorithm(QCAlgorithm):

    def initialize(self) -> None:
        self.set_start_date(2019, 1, 1)   # Set Start Date
        self.set_end_date(2020, 4, 1)     # Set End Date
        self.set_cash(100000)            # Set Strategy Cash

        self._model_by_symbol = {}

        for ticker in ["SPY", "QQQ", "TLT"]:
            symbol = self.add_equity(ticker).symbol

            # Read the model saved in the ObjectStore
            for kvp in self.object_store:
                key = f'{symbol}_model'
                if not (key == kvp.key and kvp.value):
                    continue
                file_path = self.object_store.get_file_path(kvp.key)
                self._model_by_symbol[symbol] = keras.models.load_model(file_path)
                self.debug(f'Model for {symbol} sucessfully retrieved. File {file_path}. Size {len(kvp.value)}. Weights {self._model_by_symbol[symbol].get_weights()}')

        # Look-back period for training set
        self._lookback = 30

        # Train Neural Network every monday
        self.train(
            self.date_rules.every(DayOfWeek.MONDAY),
            self.time_rules.after_market_open("SPY"),
            self.neural_network_training)

        # Place trades on Monday, 30 minutes after the market is open
        self.schedule.on(
            self.date_rules.every_day("SPY"),
            self.time_rules.after_market_open("SPY", 30),
            self.trade)

    def on_end_of_algorithm(self) -> None:
        ''' Save the data and the mode using the ObjectStore '''
        for symbol, model in self._model_by_symbol.items():
            key = f'{symbol}_model.keras'
            file = self.object_store.get_file_path(key)
            model.save(file)
            self.object_store.save(key)
            self.debug(f'Model for {symbol} sucessfully saved in the ObjectStore')

    def neural_network_training(self) -> None:
        '''Train the Neural Network and save the model in the ObjectStore'''
        symbols = self.securities.keys()

        # Daily historical data is used to train the machine learning model
        history = self.history(symbols, self._lookback + 1, Resolution.DAILY)
        history = history.open.unstack(0)

        for symbol in symbols:
            if symbol not in history:
                continue

            predictor = history[symbol][:-1]
            predictand = history[symbol][1:]

            # 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(learning_rate = 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(200):
                # training the model
                cost = model.train_on_batch(predictor, predictand)

            self._model_by_symbol[symbol] = model

    def trade(self) -> None:
        '''
        Predict the price using the trained model and out-of-sample data
        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
        '''
        target = 1 / len(self.securities)

        for symbol, model in self._model_by_symbol.items():
            if symbol not in self.current_slice.bars:
                continue
            
            # Get the out-of-sample history
            history = self.history(symbol, self._lookback, Resolution.DAILY)
            history = history.open.unstack(0)[symbol]

            # Get the final predicted price
            prediction = model.predict(history)[0][-1]
            history_std = np.std(history)

            holding = self.portfolio[symbol]
            open_price = self.current_slice.bars[symbol].open

            # Follow the trend
            if holding.invested:
                if open_price < prediction - history_std:
                    self.liquidate(symbol)
            else:
                if open_price > prediction + history_std:
                    self.set_holdings(symbol, target)

```

Shown in full with attribution under the source's licence. Licence: Apache-2.0

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.