Orders not executing with sufficient broker cash
-
Hi, I am not sure why trades will not execute for certain stocks although there is enough balance for them to execute. I am giving my code below, it is based on random entry.
Because I am using np.random.randint, my results will not be the same as yours so I will just give an outline of the result.
Since I am asking the code to execute a trade randomly whenever rand_int = 20 and I have 10 datas in my feeds, it should execute 10 trades whenever the condition is met, of course that also means that I should have enough cash in the broker to execute all 10 trades. I am also asking the code to exit after 10 days.
Now my problem is that after creation of my orders on 2016-06-30 all but 3 get executed on 2016-07-01. Have Look at Bajajfinsv, NTPC and ICICI in the results code, these are the orders that hit margin. My broker balance after execution of 7 of the 10 orders created is 19334, while Bajajfinsv trade cannot be executed since the order value (23216) is much more than the broker cash (19334), NTPC order value (1302.5) and ICICI (2186.8) should have got executed, but they didn't. Why would that be?
class random_strat(bt.Strategy): def __init__(self): self.inds = {} for d in self.datas: self.inds[d] = {} self.inds[d]['close'] = d.close self.inds[d]['open'] = d.open self.orders = {} def log(self, txt, dt=None): dt = self.datas[0].datetime.date() print(f'Date: {dt}, {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(f'BUY EXECUTED: {order.executed.price}, Cost: {order.executed.value}') self.execprice = order.executed.price self.totalcost = order.executed.value self.bar_executed = len(self) # o2 = self.sell(data = order.data, exectype=bt.Order.Stop, price= 0.95 * self.execprice, ) # o3 = self.sell(data = order.data, exectype=bt.Order.Limit, price = 1.10 * self.execprice, oco = o2) # self.log(f'STOP AT: {o2.created.price}, TARGET AT: {o3.created.price}') # self.orders[order.data].append(o2) # self.orders[order.data].append(o3) # print(f'NEWLY ADDED: {self.orders}') elif order.issell(): self.sellprice = order.executed.price self.sellcost = order.executed.value self.log(f'SELL EXECUTED: {self.sellprice}, Cost: {self.sellcost}') elif order.status in [order.Canceled, order.Margin, order.Rejected]: self.log('Order Canceled/Margin/Rejected') order_name = ['main', 'stop', 'limit', 'close'] if not order.alive(): dorders = self.orders[order.data] # print(f'DORDERS: {dorders}') idx = dorders.index(order) # print(f'IDX: {idx}') dorders[idx] = None # print(f'DORORDERSIDX: {dorders[idx]}') self.log('-- No longer alive {} Ref'.format(order_name[idx])) self.log(f'Account Balance: {cerebro.broker.getcash()}') if all(x is None for x in dorders): dorders[:] = [] def notify_trade(self, trade): if trade.isopen: return else: self.log(f'OPERATION PROFIT: GROSS {trade.pnl}, NET {trade.pnlcomm}, Trade PnL: {trade.pnlcomm/self.totalcost}') self.log(f'Updated Account Balance: {cerebro.broker.getcash()}') def next(self): rand_int = np.random.randint(1, 50) print(f'RANDINT: {rand_int}') for d in self.datas: name = d._name pos = self.getposition(d).size self.log(f'{name}, Close: {d.close[0]}, Pos: {pos}') if not pos and not self.orders.get(d, None): if self.inds[d]['open'][0] > 0 and rand_int == 20: o1 = self.buy(data = d) self.log(f'NAME: {name}, BUY CREATED: {o1.created.price}') self.orders[d] = [o1] elif pos: if len(self) >= (self.bar_executed + 9): o2 = self.sell(data = d) self.log(f'NAME:{name}, SELL CREATED: {o2.created.price}') self.orders[d].append(o2) cerebro = bt.Cerebro() cerebro.broker.set_cash(250000) print(f'Starting Portfolio Value: {cerebro.broker.getvalue()}') for n in range(len(stock_df[:10])): dataset = list(zip(stock_df, names)) data = bt.feeds.PandasData(dataname=dataset[n][0], datetime=None, open=-1, high=-1, low=-1, close=-1, volume=-1) cerebro.adddata(data, name = dataset[n][1]) cerebro.addstrategy(random_strat) cerebro.addsizer(bt.sizers.FixedSize, stake=10) cerebro.addanalyzer(trades_list, _name = 'tradelist') # cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name = 'ta') strat = cerebro.run(tradehistory = True) strats = strat[0].analyzers.tradelist.get_analysis() # strats_two = strat[0].analyzers.ta.get_analysis() trades = pd.DataFrame(strats) print(f'Final Portfolio Value: {cerebro.broker.getvalue()}')
RESULTS:
Date: 2016-06-30, JSWSTEEL, Close: 146.44, Pos: 0 Date: 2016-06-30, NAME: JSWSTEEL, BUY CREATED: 146.44 Date: 2016-06-30, MARUTI, Close: 4187.2, Pos: 0 Date: 2016-06-30, NAME: MARUTI, BUY CREATED: 4187.2 Date: 2016-06-30, ITC, Close: 245.6, Pos: 0 Date: 2016-06-30, NAME: ITC, BUY CREATED: 245.6 Date: 2016-06-30, ULTRACEMCO, Close: 3411.0, Pos: 0 Date: 2016-06-30, NAME: ULTRACEMCO, BUY CREATED: 3411.0 Date: 2016-06-30, SHREECEM, Close: 14546.5, Pos: 0 Date: 2016-06-30, NAME: SHREECEM, BUY CREATED: 14546.5 Date: 2016-06-30, TATASTEEL, Close: 303.19, Pos: 0 Date: 2016-06-30, NAME: TATASTEEL, BUY CREATED: 303.19 Date: 2016-06-30, HINDUNILVR, Close: 898.55, Pos: 0 Date: 2016-06-30, NAME: HINDUNILVR, BUY CREATED: 898.55 Date: 2016-06-30, BAJAJFINSV, Close: 2321.6, Pos: 0 Date: 2016-06-30, NAME: BAJAJFINSV, BUY CREATED: 2321.6 Date: 2016-06-30, NTPC, Close: 130.25, Pos: 0 Date: 2016-06-30, NAME: NTPC, BUY CREATED: 130.25 Date: 2016-06-30, ICICIBANK, Close: 218.68, Pos: 0 Date: 2016-06-30, NAME: ICICIBANK, BUY CREATED: 218.68 Date: 2016-07-01, Order Canceled/Margin/Rejected Date: 2016-07-01, -- No longer alive main Ref Date: 2016-07-01, Account Balance: 19334.399999999983 Date: 2016-07-01, Order Canceled/Margin/Rejected Date: 2016-07-01, -- No longer alive main Ref Date: 2016-07-01, Account Balance: 19334.399999999983 Date: 2016-07-01, Order Canceled/Margin/Rejected Date: 2016-07-01, -- No longer alive main Ref Date: 2016-07-01, Account Balance: 19334.399999999983 Date: 2016-07-01, BUY EXECUTED: 147.51, Cost: 1475.1 Date: 2016-07-01, -- No longer alive main Ref Date: 2016-07-01, Account Balance: 19334.399999999983 Date: 2016-07-01, BUY EXECUTED: 4188.6, Cost: 41886.0 Date: 2016-07-01, -- No longer alive main Ref Date: 2016-07-01, Account Balance: 19334.399999999983 Date: 2016-07-01, BUY EXECUTED: 243.3, Cost: 2433.0 Date: 2016-07-01, -- No longer alive main Ref Date: 2016-07-01, Account Balance: 19334.399999999983 Date: 2016-07-01, BUY EXECUTED: 3410.0, Cost: 34100.0 Date: 2016-07-01, -- No longer alive main Ref Date: 2016-07-01, Account Balance: 19334.399999999983 Date: 2016-07-01, BUY EXECUTED: 14555.0, Cost: 145550.0 Date: 2016-07-01, -- No longer alive main Ref Date: 2016-07-01, Account Balance: 19334.399999999983 Date: 2016-07-01, BUY EXECUTED: 307.48, Cost: 3074.8 Date: 2016-07-01, -- No longer alive main Ref Date: 2016-07-01, Account Balance: 19334.399999999983 Date: 2016-07-01, BUY EXECUTED: 898.6, Cost: 8986.0 Date: 2016-07-01, -- No longer alive main Ref Date: 2016-07-01, Account Balance: 19334.399999999983