Backtest perpetually running, can't interrupt kernel/pandas data
-
I'm running into an issue where upon running a backtest, ipython will keep in a state of running with the asterisk [*] and no amount of spamming the interrupt kernel button will stop it. Restarting the kernel works, but I don't understand where the issue is originating. One idea of origin is that I am trying to feed pandas data, and it's fully possible that I'm not implementing it correctly. The strategy isn't anything special, it's simply the moving average cross taken from the quickstart page. My dataframe (ps) looks like this:
And the rest of my code is:
from __future__ import (absolute_import, division, print_function, unicode_literals) import datetime # For datetime objects import os.path # To manage paths import sys # To find out the script name (in argv[0]) import MySQLdb import pandas as pd # Import the backtrader platform import backtrader as bt import backtrader.feeds as btfeeds # Create a Stratey class TestStrategy(bt.Strategy): params = ( ('maperiod', 15), ('printlog', False), ) def log(self, txt, dt=None, doprint=False): ''' Logging function fot this strategy''' if self.params.printlog or doprint: dt = dt or self.datas[0].datetime.date(0) print('%s, %s' % (dt.isoformat(), txt)) def __init__(self): # Keep a reference to the "close" line in the data[0] dataseries self.dataclose = self.datas[0].close # To keep track of pending orders and buy price/commission self.order = None self.buyprice = None self.buycomm = None # Add a MovingAverageSimple indicator self.sma = bt.indicators.SimpleMovingAverage( self.datas[0], period=self.params.maperiod) def notify_order(self, order): if order.status in [order.Submitted, order.Accepted]: # Buy/Sell order submitted/accepted to/by broker - Nothing to do return # Check if an order has been completed # Attention: broker could reject order if not enough cash if order.status in [order.Completed]: if order.isbuy(): self.log( 'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' % (order.executed.price, order.executed.value, order.executed.comm)) self.buyprice = order.executed.price self.buycomm = order.executed.comm else: # Sell self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' % (order.executed.price, order.executed.value, order.executed.comm)) self.bar_executed = len(self) elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('Order Canceled/Margin/Rejected') # Write down: no pending order self.order = None def notify_trade(self, trade): if not trade.isclosed: return self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' % (trade.pnl, trade.pnlcomm)) def next(self): # Simply log the closing price of the series from the reference self.log('Close, %.2f' % self.dataclose[0]) # Check if an order is pending ... if yes, we cannot send a 2nd one if self.order: return # Check if we are in the market if not self.position: # Not yet ... we MIGHT BUY if ... if self.dataclose[0] > self.sma[0]: # BUY, BUY, BUY!!! (with all possible default parameters) self.log('BUY CREATE, %.2f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.buy() else: if self.dataclose[0] < self.sma[0]: # SELL, SELL, SELL!!! (with all possible default parameters) self.log('SELL CREATE, %.2f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.sell() def stop(self): self.log('(MA Period %2d) Ending Value %.2f' % (self.params.maperiod, self.broker.getvalue()), doprint=True) if __name__ == '__main__': # Create a cerebro entity cerebro = bt.Cerebro() # Add a strategy strats = cerebro.optstrategy( TestStrategy, maperiod=range(10, 31)) # Datas are in a subfolder of the samples. Need to find where the script is # because it could have been called from anywhere #modpath = os.path.dirname(os.path.abspath(sys.argv[0])) #datapath = os.path.join(modpath, '../../datas/orcl-1995-2014.txt') # Create a Data Feed data = btfeeds.PandasData(dataname=ps) # Add the Data Feed to Cerebro cerebro.adddata(data) # Set our desired cash start cerebro.broker.setcash(1000000.0) # Add a FixedSize sizer according to the stake cerebro.addsizer(bt.sizers.FixedSize, stake=10) # Set the commission cerebro.broker.setcommission(commission=0.0) # Run over everything cerebro.run()
If anybody has experienced this before or has any suggestions I'd love to hear about it, I'll be working all night. Thanks.
EDIT: I have additionally tried setting the index to the datetime and running again, still no change
-
In your description you have omitted the most important point: "You are optimizing the strategy". Even if you see it so, it is no longer the sample script with just a change in the data feed.
The Kernel is known to hijack the start process of Python and have problems with
multiprocessing
This is a known problem and has nothing to do with
backtrader
: https://community.backtrader.com/topic/744/optstrategy-not-working-in-jupyter -
@backtrader, Thank you for the explanation. I was just getting ready to post an update saying that it's working now. I started over from scratch, converted my data to csv, copy & pasted through the quickstart page, and everything has been going smoothly.