Files
quantconnect--lean/Algorithm.Python/PytorchNeuralNetworkAlgorithm.py
T
2019-07-05 14:10:29 -07:00

110 lines
4.3 KiB
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.
import clr
clr.AddReference("System")
clr.AddReference("QuantConnect.Algorithm")
clr.AddReference("QuantConnect.Common")
from System import *
from QuantConnect import *
from QuantConnect.Algorithm import *
import numpy as np
import torch
import torch.nn.functional as F
class PytorchNeuralNetworkAlgorithm(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2013, 10, 7) # Set Start Date
self.SetEndDate(2013, 10, 8)
self.SetCash(100000) # Set Strategy Cash
spy = self.AddEquity("SPY", Resolution.Minute)
self.symbols = [spy.Symbol]
self.lookback = 30
self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.AfterMarketOpen("SPY", 28), Action(self.NetTrain))
self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.AfterMarketOpen("SPY", 30), Action(self.Trade))
def OnData(self, data):
self.data = data
def NetTrain(self):
history = self.History(self.symbols, self.lookback + 1, Resolution.Daily)
self.prices_x = {}
self.prices_y = {}
self.sell_prices = {}
self.buy_prices = {}
for symbol in self.symbols:
if not history.empty:
self.prices_x[symbol.Value] = list(history.loc[symbol.Value]['open'])[:-1]
self.prices_y[symbol.Value] = list(history.loc[symbol.Value]['open'])[1:]
for symbol in self.symbols:
if symbol.Value in self.prices_x:
net = Net(n_feature=1, n_hidden=10, n_output=1) # define the network
optimizer = torch.optim.SGD(net.parameters(), lr=0.2)
loss_func = torch.nn.MSELoss() # this is for regression mean squared loss
for t in range(200):
# Get data
x = torch.from_numpy(np.array(self.prices_x[symbol.Value])).float()
y = torch.from_numpy(np.array(self.prices_y[symbol.Value])).float()
x = x.unsqueeze(1)
y = y.unsqueeze(1)
prediction = net(x) # input x and predict based on x
loss = loss_func(prediction, y) # must be (1. nn output, 2. target)
optimizer.zero_grad() # clear gradients for next train
loss.backward() # backpropagation, compute gradients
optimizer.step() # apply gradients
# Follow the trend
self.buy_prices[symbol.Value] = net(y)[-1] + np.std(y.data.numpy())
self.sell_prices[symbol.Value] = net(y)[-1] - np.std(y.data.numpy())
def Trade(self):
for i in self.Portfolio.Values:
# liquidate
if self.data[i.Symbol.Value].Open < self.sell_prices[i.Symbol.Value] and i.Invested:
self.Liquidate(i.Symbol)
# buy
if self.data[i.Symbol.Value].Open > self.buy_prices[i.Symbol.Value] and not i.Invested:
self.SetHoldings(i.Symbol, 1 / len(self.symbols))
class Net(torch.nn.Module):
def __init__(self, n_feature, n_hidden, n_output):
super(Net, self).__init__()
self.hidden = torch.nn.Linear(n_feature, n_hidden) # hidden layer
self.predict = torch.nn.Linear(n_hidden, n_output) # output layer
def forward(self, x):
x = F.relu(self.hidden(x)) # activation function for hidden layer
x = self.predict(x) # linear output
return x