For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/
Execute orders with bid/ask prices
-
@Nigel said in Execute on bid/ask:
BidAskCSV
Hello,
I am also using Bid/ask data. Wanted to do a test where I buy and sell like @Nigel did.
But it seems like the orders are not being executed because when I access the order.Exuecuted.price is always 0.from __future__ import (absolute_import, division, print_function, unicode_literals) import argparse import backtrader as bt import backtrader.feeds as btfeeds #import backtrader.indicators as btind import random class BidAskCSV(btfeeds.GenericCSVData): linesoverride = True # discard usual OHLC structure # datetime must be present and last lines = ('bid', 'ask', 'close', 'open','low', 'high', 'datetime') # datetime (always 1st) and then the desired order for params = ( # (datetime, 0), # inherited from parent class ('bid', 1), # default field pos 1 ('ask', 2), # default field pos 2 ('close', 2), ('open', 1), ('low', 1), ('high',2) ) def __init__(self): super(BidAskCSV, self).__init__()
The strategy:
class St(bt.Strategy): def log(self, txt, dt= None): """Logging function """ dt= dt or self.datas[0].datetime[0] if isinstance(dt, float): dt = bt.num2date(dt) print('%s, %s' % (dt.isoformat(), txt)) def __init__(self): self.order = None self.dataclose= self.datas[0].close #self.dataclose = self.datas[0].close[0] 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 enougth cash if order.status in [order.Completed]: if order.isbuy(): self.log( 'BUY EXECUTED, Price: %.2f, Cost: %.2f' % (order.executed.price, order.executed.value)) self.buyprice = order.executed.price else: # Sell self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f' % (order.executed.price, order.executed.value)) 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 %.2f, NET %.2f' % (trade.pnl, trade.pnlcomm)) def next(self): dtstr = self.datas[0].datetime.datetime().isoformat() txt = '%4d: %s - Bid %.4f - %.4f Ask, CLOSE %.4f ' % ( (len(self), dtstr, self.datas[0].bid[0], self.datas[0].ask[0], self.datas[0].close[0])) print(txt) position = self.getposition(data=self.datas[0]) rand = random.random() print('-------------') print ('Random:', rand) print('-------------') if rand < 0.2: if position: # SELL (with all possible default parameters) self.log('SELL CREATE '.format(self.data.bid[0])) # Keep track of the created order to avoid a 2nd order self.order = self.sell(data=self.datas[0]) print ('Bid', self.data.bid[0]) elif rand > 0.8: if not position: # BUY (with all possible default parameters) self.log('BUY CREATE {}'.format(self.data.ask[0])) # Keep track of the created order to avoid a 2nd order self.order = self.buy(data=self.datas[0]) self.log('Executed Price:{}'.format(self.order.executed.price)) print ('Executed Price:', self.order.executed.price) print ('ASK', self.data.ask[0])
and finale code:
def parse_args(): parser = argparse.ArgumentParser( description='Bid/Ask Line Hierarchy', formatter_class=argparse.ArgumentDefaultsHelpFormatter, ) parser.add_argument('--data', '-d', action='store', required=False, default='bidask.csv', help='data to add to the system') parser.add_argument('--dtformat', '-dt', required=False, default='%m/%d/%Y %H:%M:%S', help='Format of datetime in input') return parser.parse_args() def runstrategy(): args = parse_args() cerebro = bt.Cerebro() # Create a cerebro data = BidAskCSV(dataname=args.data, dtformat=args.dtformat) cerebro.adddata(data) # Add the 1st data to cerebro # Set our desired cash start cerebro.broker.setcash(100000.0) # Add the strategy to cerebro cerebro.addstrategy(St) # Add a FixedSize sizer according to the stake cerebro.addsizer(bt.sizers.FixedSize, stake=10) # Print out the starting conditions print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) # Run over everything cerebro.run() # Print out the final result print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue()) if __name__ == '__main__': runstrategy()
This is what I get as output:
Starting Portfolio Value: 100000.00 1: 2010-02-03T23:59:59.999989 - Bid 0.5346 - 0.5347 Ask, CLOSE 0.5347 ------------- Random: 0.329840335116921 ------------- 2: 2010-02-03T23:59:59.999989 - Bid 0.5343 - 0.5347 Ask, CLOSE 0.5347 ------------- Random: 0.680459956622627 ------------- 3: 2010-02-03T23:59:59.999989 - Bid 0.5543 - 0.5545 Ask, CLOSE 0.5545 ------------- Random: 0.04838233726017549 ------------- 4: 2010-02-03T23:59:59.999989 - Bid 0.5342 - 0.5344 Ask, CLOSE 0.5344 ------------- Random: 0.7977225266469058 ------------- 5: 2010-02-03T23:59:59.999989 - Bid 0.5245 - 0.5464 Ask, CLOSE 0.5464 ------------- Random: 0.8661165246756014 ------------- 2010-02-03T23:59:59.999989, BUY CREATE 0.5464 2010-02-03T23:59:59.999989, Executed Price:0.0 Executed Price: 0.0 ASK 0.5464 6: 2010-02-03T23:59:59.999989 - Bid 0.5460 - 0.5470 Ask, CLOSE 0.5470 ------------- Random: 0.7797905933237207 ------------- 7: 2010-02-03T23:59:59.999989 - Bid 0.5824 - 0.5826 Ask, CLOSE 0.5826 ------------- Random: 0.585687043100518 ------------- 8: 2010-02-03T23:59:59.999989 - Bid 0.5371 - 0.5374 Ask, CLOSE 0.5374 ------------- Random: 0.2171674683269379 ------------- 9: 2010-02-03T23:59:59.999989 - Bid 0.5793 - 0.5794 Ask, CLOSE 0.5794 ------------- Random: 0.6576887524911412 ------------- 10: 2010-02-03T23:59:59.999989 - Bid 0.5684 - 0.5688 Ask, CLOSE 0.5688 ------------- Random: 0.406599019686264 ------------- Final Portfolio Value: 100000.00
I don't understand what I am doing wrong, and why the orders are not being executed. Can I get some help here? Thanks!