Order Execution Price NAN - single column pandas data input
I am testing a very basic hello world script the exception being that I am using a single column pandas dataframe as my data source (because that is what I am using as the input for my strategy).
Everything appears to be working fine, except that my the order object inside the loop shows
price=nanand throws off the loop. When I check the value of the portfolio at the end of the script, it is
nan. I'm assuming it is related to my data source but I cannot find the error looking through the source code.
cerebro = bt.Cerebro() cerebro.addstrategy(EMACross, fast_period=11, slow_period=25) # Make data object - we only have a "close" in column 0 data = bt.feeds.PandasData(dataname=btc_df, open=None, high=None, low=None, close=0, volume=None, openinterest=None) cerebro.adddata(data) # add data to engine cerebro.run() cerebro.broker.getvalue()
At this point, everything runs and prints to the console, the first order produces
"> BUY EXECUTED, nan"
Then, every order after produces a Rejected, Cancelled, Margin error.
Here is my strategy object, you can see I am passing in size and price to the order function -
class EMACross(bt.Strategy): def __init__(self, fast_period, slow_period): self.dataclose = self.datas.close self.order = None self.fastma = bt.ind.ExponentialMovingAverage(self.datas, period=fast_period) self.slowma = bt.ind.ExponentialMovingAverage(self.datas, period=slow_period) self.buysig = bt.ind.CrossOver(self.fastma, self.slowma) self.sellsig = bt.ind.CrossDown(self.fastma, self.slowma) def log(self, txt, dt=None): dt = dt or self.datas.datetime.date(0) print('%s, %s' % (dt.isoformat(), txt)) def notify_order(self, order): if order.status in [order.Submitted, order.Accepted]: return if order.status in [order.Completed]: if order.isbuy(): self.log('BUY EXECUTED, %.2f' % order.executed.price) elif order.issell(): self.log('SELL EXECUTED, %.2f' % order.executed.price) elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('Order Cancelled/Margin/Rejected') self.order = None def next(self): self.log('Close, %.2f' % self.dataclose) if self.order: return # Initial Order if not self.position: if self.buysig > 0: self.log('BUY CREATE, %.2f' % self.dataclose) self.order = self.buy(size=1, price=self.dataclose) return elif self.sellsig > 0: self.log('SELL CREATE, %.2f' % self.dataclose) self.order = self.sell(size=1, price=self.dataclose) return else: return # Find out if we are long or short side = self.position.size if side > 0: # we are long if self.sellsig > 0: self.order = self.sell(size=2, price=self.dataclose) else: return else: if self.buysig > 0: self.order = self.buy(size=2, price=self.dataclose) else: return return
Any help is very much appreciated!! I've been debugging this for several hours. My first time using backtrader.
See at the top
For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/
You want to see how
Marketorders are executed. This:
self.order = self.buy(size=1, price=self.dataclose)
is impossibility. You cannot specify the execution price of a
Marketorder. Provide an opening price (you probably do also want to provide a high and low)
Makes perfect sense. I was able to get execution by specifying
Thank you for the help!
I think you are pretty new to trading and should take some time to understand things and grasp the concepts. Specifying
exectype=bt.Order.Closehas only done something which doesn't have the effect you are looking for.
That order execution type is intended for intraday data, for orders which are issued before the trading day is over and which will be executed with the closing tick (in the most well known exchanges it does execute at the end of the auction which follows the end of regular trading)
What you need:
- Provide an
openprice (it can be the same as the close if you don't have any other) to get something realistic
cheat-on-closeand work with the current close (it is called
cheatfor a reason)
- Provide an