Misunderstanding of the process: Order created but not executed at the same price
-
I used the code Quickstart in the documentation but with my own data (which is on a minute basis). I would like now to understand why my orders are created but not executed at the same price and days later... thanks! I am really a beginner with the platform, so any help is more than welcome. This is the code I used so far:
class TestStrategy(bt.Strategy): params = ( ('maperiod', 60), ) def log(self, txt, dt=None): ''' Logging function for this strategy''' 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 self.data_cpa = self.datas[0].high self.data_cpb = self.datas[0].low self.order = None self.buyprice = None self.buycomm = None 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: %.8f, Cost: %.8f, Comm %.8f' % (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: %.8f, Cost: %.8f, Comm %.8f' % (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') self.order = None def notify_trade(self, trade): if not trade.isclosed: return self.log('OPERATION PROFIT, GROSS %.8f, NET %.f' % (trade.pnl, trade.pnlcomm)) self.htrade = trade def next(self): # Simply log the closing price of the series from the reference self.log('Close, %.8f' % self.dataclose[0]) if self.order: return if not self.position: if self.dataclose[0] >= self.sma[0]: # BUY, BUY, BUY!!! (with all possible default parameters) self.log('BUY CREATE, %.8f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.buy(price= self.dataclose[0]) else: if self.dataclose[0] <= self.sma[0]: # SELL, SELL, SELL!!! (with all possible default parameters) self.log('SELL CREATE, %.8f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.sell(price= self.dataclose[0])
-
@viktor-w said in Misunderstanding of the process: Order created but not executed at the same price:
I used the code Quickstart in the documentation but with my own data (which is on a minute basis)
No you haven't. You are using something different. Your code
@viktor-w said in Misunderstanding of the process: Order created but not executed at the same price:
# Keep track of the created order to avoid a 2nd order self.order = self.buy(price= self.dataclose[0])
Code from: https://www.backtrader.com/docu/quickstart/quickstart.html#do-not-only-buy-but-sell
# Keep track of the created order to avoid a 2nd order self.order = self.buy()
There is a clear obvious difference. When you code, small differences can mean a huge difference.
@viktor-w said in Misunderstanding of the process: Order created but not executed at the same price:
I would like now to understand why my orders are created but not executed at the same price and days later... thanks! I am really a beginner with the platform, so any help is more than welcome.
The code is apparently producing logs in the console. Why don't you paste them and point out an example of what you think is wrong? This is a rhetorical question to point out, that if you think there is something wrong, we cannot know it, because there is no information as to what yo think is wrong.
Furthermore, you only show the strategy, but believe me: the most obvious mistake you are making it's not in that part of the code. It is in the code you aren't showing.
In any case let me point you to this:
and look at what a
Market
order is. Let me explain it here: it is an order for which YOU DON'T specify the price. The Market price is used. No, not the market price you currently see, but the one which you still haven't seen, i.e.: the next incoming price tick (if you use daily bars, that's already the next trading day) -
@backtrader , I am still lost with your platform. I simplified my code so that it looks like this:
class TestStrategy(bt.Strategy): params = ( ('maperiod', 60), ) def log(self, txt, dt=None): ''' Logging function for this strategy''' 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 self.data_cpa = self.datas[0].high self.data_cpb = self.datas[0].low self.order = None self.buyprice = None self.buycomm = None 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, %.8f' % order.executed.price) elif order.issell(): self.log('SELL EXECUTED, %.8f' % order.executed.price) self.bar_executed = 0 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 %.8f, NET %.f' % (trade.pnl, trade.pnlcomm)) def next(self): # Simply log the closing price of the series from the reference self.log('Close, %.8f' % self.dataclose[0]) if self.order: return # Check if we are in the market if not self.position: if self.dataclose[0] > self.sma[0]: # BUY, BUY, BUY!!! (with all possible default parameters) self.log('BUY CREATE, %.8f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.buy(price= self.dataclose[0]) else: if self.dataclose[0] < self.sma[0]: # SELL, SELL, SELL!!! (with all possible default parameters) self.log('SELL CREATE, %.8f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.sell(price= self.dataclose[0]) if __name__ == '__main__': # Create a cerebro entity cerebro = bt.Cerebro(cheat_on_open=True) # Add a strategy cerebro.addstrategy(TestStrategy) # retrieve the csv file modpath = os.path.dirname(os.path.abspath(sys.argv[0])) datapath = os.path.join(modpath, './datas/zrxeth_sample.txt') # Create a Data Feed data = bt.feeds.GenericCSVData( dataname = datapath, fromdate=datetime.datetime(2018, 9, 28), todate=datetime.datetime(2018, 12, 3), nullvalue=0.0, dtformat=('%Y-%m-%d %H:%M:%S'), datetime=0, high=1, low=2, open=3, close=4, volume=5, openinterest=-1 ) # Add the Data Feed to Cerebro cerebro.adddata(data) # Set our desired cash start cerebro.broker.setcash(100.0) # Print out the starting conditions print('Starting Portfolio Value: %.8f' % cerebro.broker.getvalue()) # Run over everything cerebro.run() # Print out the final result print('Final Portfolio Value: %.8f' % cerebro.broker.getvalue())
I did cerebro 'cheat_on_open' = true , but I do not understand why when the order is created at a price it is not executed at the same price, it looks like that:
2018-09-28, Close, 0.00298747 2018-09-28, BUY CREATE, 0.00298747 2018-09-28, BUY EXECUTED, 0.00299252 2018-09-28, Close, 0.00298747 2018-09-28, Close, 0.00298865 2018-09-28, Close, 0.00298813 2018-09-28, Close, 0.00298808
-
@viktor-w said in Cheat_on_open true: how to execute the order on another price than the next open price:
For now my code looks like this:
class TestStrategy(bt.Strategy): params = ( ('maperiod', 60), ) def log(self, txt, dt=None): ''' Logging function for this strategy''' 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 self.data_cpa = self.datas[0].high self.data_cpb = self.datas[0].low self.order = None self.buyprice = None self.buycomm = None 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, %.8f' % order.executed.price) elif order.issell(): self.log('SELL EXECUTED, %.8f' % order.executed.price) self.bar_executed = 0 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 %.8f, NET %.f' % (trade.pnl, trade.pnlcomm)) def next(self): # Simply log the closing price of the series from the reference self.log('Close, %.8f' % self.dataclose[0]) if self.order: return # Check if we are in the market if not self.position: if self.dataclose[0] > self.sma[0]: # BUY, BUY, BUY!!! (with all possible default parameters) self.log('BUY CREATE, %.8f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.buy(price= self.dataclose[0]) else: if self.dataclose[0] < self.sma[0]: # SELL, SELL, SELL!!! (with all possible default parameters) self.log('SELL CREATE, %.8f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.sell(price= self.dataclose[0]) if __name__ == '__main__': # Create a cerebro entity cerebro = bt.Cerebro(cheat_on_open=True) # Add a strategy cerebro.addstrategy(TestStrategy) # retrieve the csv file modpath = os.path.dirname(os.path.abspath(sys.argv[0])) datapath = os.path.join(modpath, './datas/zrxeth_sample.txt') # Create a Data Feed data = bt.feeds.GenericCSVData( dataname = datapath, fromdate=datetime.datetime(2018, 9, 28), todate=datetime.datetime(2018, 12, 3), nullvalue=0.0, dtformat=('%Y-%m-%d %H:%M:%S'), datetime=0, high=1, low=2, open=3, close=4, volume=5, openinterest=-1 ) # Add the Data Feed to Cerebro cerebro.adddata(data) # Set our desired cash start cerebro.broker.setcash(100.0) # Print out the starting conditions print('Starting Portfolio Value: %.8f' % cerebro.broker.getvalue()) # Run over everything cerebro.run() # Print out the final result print('Final Portfolio Value: %.8f' % cerebro.broker.getvalue())
From my understanding of the library, when you use the parameter cheat_on_open=True, you can authorize the order the order to be executed directly and not the day after. However, the executed order takes as price the next open price, how is it possible to choose which price the order will apply? Thanks!
-
Let me put all the answers in one place:
-
If you use something which isn't `1-Day´ (which is the default) you have to tell the platform what your timeframe/compression is.
- See for example: Community - FAQ
-
If you issue a
Market
order, you will get the next incoming price, i.e.: the price the market wants to give you. It is irrelevant if you specify a price. See-
Docs - Strategy -
buy/sell
methods (see theexectype
parameter defaults) -
Check order execution types: Docs - Order Management and Execution
-
-
If you want to use
cheat-on-open
you should be using the corresponding methodnext_open
. It is clearly specified in the documentation (and it is so for good reasons). See- [Docs - Cheat On Open](https://www.backtrader.com/docu/cerebro/cheat-on-open/cheat-on-open.html]
@backtrader said in Misunderstanding of the process: Order created but not executed at the same price:
From my understanding of the library, when you use the parameter cheat_on_open=True, you can authorize the order the order to be executed directly and not the day after.
Algotrading is not about understanding, it is about knowing what you have to expect.
@backtrader said in Misunderstanding of the process: Order created but not executed at the same price:
However, the executed order takes as price the next open price, how is it possible to choose which price the order will apply? Thanks!Again:
Market
orders won't guarantee you the price (hence the nameMarket
) and there is no way to specify which price you will GET. Even for aLimit
order the only guarantee is that you will get that (or a better) price if the order is executed, but it may never be executed.You may actually be looking for
cheat-on-close
. See Docs - CerebroSome additional notes
@viktor-w said in Misunderstanding of the process: Order created but not executed at the same price:
but I do not understand why when the order is created at a price it is not executed at the same price
@viktor-w said in Misunderstanding of the process: Order created but not executed at the same price:
I am still lost with your platform
Let me be blunt: you are not (only) lost with the platform. You are lost with trading in general.
The most important part of algotrading is not the computer/programming part ... but knowing your trading. My very sincere advice: work very hard in understanding how trading works. If you don't know the rules of the house (which already holds the upper hand), the house is going to quickly get you out of business.
-
-
@backtrader, thanks for your reply. We are a company which does market making on new cryptocurrencies. So your statement saying that I do not have knowledge of trading is irrelevant as my goal is not trading. Stating that I am lost on trading and on your platform is thus a wrong statement as well, because you do not know what is my goal, what is my tragedy and at which end I will be using backtrader.
Anyway, I tried to read a bit more in detail your documentation and I still does not see how I can execute an order on the closing price of the next minute, do you have any other advice? thanks for your time and help! -
@backtrader the only line of code I needed was:
cerebro.broker.set_coc(True)
-
I am glad
@viktor-w said in Misunderstanding of the process: Order created but not executed at the same price:
@backtrader the only line of code I needed was: cerebro.broker.set_coc(True)
I am glad to know that was the only line of code you needed. I do truly and respectfully disagree.
And you also disagree with yourself. For example:
@viktor-w said in Misunderstanding of the process: Order created but not executed at the same price:
We are a company
You obviously can buy professional support then.