For the benefit of others, I have decided to share the full code of the datafeed extension solution that worked for me:
# Define Dynamic Class for Loading Data
class GenericCSV(bt.feeds.GenericCSVData):
lines = ('stock_p_change', 'predictions')
params = (('nullvalue', float('NaN')),
('dtformat', '%m/%d/%Y'),
('stock_p_change', 7),
('predictions', 8))
# Trading Strategy
class SPYStrategy(bt.Strategy):
def __init__(self):
# The indicator autoregisters and will plot even if no obvious
# reference is kept to it in the class
pass
def next(self):
if self.data.predictions > 0 and self.data.stock_p_change < -0.005:
self.buy(stake=1000)
else:
if self.data.predictions < 1 and self.data.stock_p_change > 0:
self.close()
def notify_trade(self, trade):
dt = self.data.datetime.date()
if trade.isclosed:
print('{} {} Closed: PnL Gross {}, Net {}'.format(
dt,
trade.data._name,
round(trade.pnl,2),
round(trade.pnlcomm,2)))
# Variable for our starting cash
startcash = 10000
# Create a cerebro entity
cerebro = bt.Cerebro(stdstats=False)
# Set Commission - The Proportional Transaction Cost is Set as the Commission
cerebro.broker.setcommission(commission=0.005199108990760269)
# Add a strategy
cerebro.addstrategy(SPYStrategy)
# Get Data
data = GenericCSV(dataname="event_based_backtesting.csv")
cerebro.adddata(data)
# Run over everything
cerebro.run()
# Get final portfolio Value
portvalue = cerebro.broker.getvalue()
pnl = portvalue - startcash
# Print out the final result
print('Final Portfolio Value: ${}'.format(portvalue))
print('P/L: ${}'.format(pnl))
# Finally plot the end results
cerebro.plot(style='line')
To check if the added variables are being read in correctly--sometimes using the parameter "7" for your added variables may accidentally parse "openinterest" as an added variable--you can use this code:
# Define Dynamic Class for Loading Data
class GenericCSV(bt.feeds.GenericCSVData):
lines = ('stock_p_change', 'predictions')
params = (('nullvalue', float('NaN')),
('dtformat', '%m/%d/%Y'),
('stock_p_change', 7),
('predictions', 8))
# Trading Strategy
class SPYStrategy(bt.Strategy):
def __init__(self):
# The indicator autoregisters and will plot even if no obvious
# reference is kept to it in the class
pass
def next(self):
print('%03d %f %f, %f' % (
len(self),
self.data.close[0],
self.data.stock_p_change[0],
self.data.predictions[0],))
# Create a cerebro entity
cerebro = bt.Cerebro(stdstats=False)
# Add a strategy
cerebro.addstrategy(SPYStrategy)
# Get Data
data = GenericCSV(dataname="event_based_backtesting.csv")
cerebro.adddata(data)
# Run over everything
cerebro.run()