For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See:

Sizer and Margin acting strange

  • Hey all - I have had this strange issue ever since I started using backtrader, and I have no idea what I am doing wrong even after reviewing all the documentation just now. The issue is that I get a Order Canceled/Margin/Rejected message even when I should definitely have more than enough cash in the account. Here are the specifics:

    • I have set up a simple strategy to place a plain vanilla buy order on the 200th bar of the price data (for testing).
        def next(self):
            if len(self.dataclose) == 200:
                self.log('BUY CREATE, %.2f' % self.dataclose[0])
    • The price at this time is $1.59 ie "BUY CREATE, 1.59"

    2001-04-19, BUY CREATE, 1.59

    • I set start cash to 10000

    • sizer._getsizing returns 1000

    Therefore, the size of the trade should be about $1590. Why can't I place this order? I should be able to buy up to 6,288 shares at this price. Also, there is no gap the next morning, this doesn't work with cheat on open either. I have not added any margin or commission information, everything is exactly like it is in the tutorials. This has been confusing me since the beginning, because sometimes I can get backtests to run by specifying random margin amounts and commission=0, but with them both being default and this notional size clearly lower than the value of the account, I don't understand what I am doing wrong. This works with stake = 1 and 100, but not 1000 and I can't identify what area of the code is causing this constraint. I have made also made sure that inside the sizer also returns 1.59, which it does. Any help would be appreciated.

    class TestStrategy(bt.Strategy):
        def __init__(self):
            self.order = None
            self.dataclose = self.datas[0].close
        def log(self, txt, dt=None):
            ''' Logging function for this strategy'''
            dt = dt or self.datas[0]
            print('%s, %s' % (dt.isoformat(), txt))
        def notify_order(self, order):
            if order.status in [order.Submitted, order.Accepted]:
                # Buy/Sell order submitted/accepted to/by broker - Nothing to do
            # 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, %.2f' % order.executed.price)
                elif order.issell():
                    self.log('SELL EXECUTED, %.2f' % order.executed.price)
                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 next(self):
            if len(self.dataclose) == 200:
                self.log('BUY CREATE, %.2f' % self.dataclose[0])
    class FixedSize(bt.Sizer):
        params = (('stake', 1000),)
        def _getsizing(self, comminfo, cash, data, isbuy):
            return self.params.stake
    cerebro = bt.Cerebro()

  • I think I figured out the issue. I am using an adjusted close column to calculate the signals, but the open, high, low columns are not adjusted.

Log in to reply