I am trying to backtest my double calendar spread strategy, which includes both long call calendar spread and long put calendar spread. I found how to place a single calendar spread order from the documentation center. However, when I tried to place a double calendar spread, which has four legs, I got the “Insufficient Buying Power” error. All four legs could not be placed. 

If I placed the two calendar spreads separately, only the first order, either put or call, can be placed successfully; the second one also got the “Insufficient Buying Power” error.

Here is the code

def on_data(self, slice: Slice) -> None:
        if slice.time.hour == 09 and slice.time.minute == 45:
            self.Debug(f'MarginRemaining={self.Portfolio.MarginRemaining}')
            self.Debug(self.option_symbol)
            self.Debug(slice.option_chains)
            chains = slice.option_chains.get(self.option_symbol)
            short_expire_date = slice.time.date() + timedelta(days=14)
            long_expire_date = slice.time.date() + timedelta(days=15)
            legs = []

            if self._put_delta != 0:
                puts = [i for i in chains if i.right == OptionRight.PUT]
                puts_short = [i for i in puts if i.expiry.date() == short_expire_date]
                puts_long = [i for i in puts if i.expiry.date() == long_expire_date]
                deltas = [i.greeks.delta for i in puts_short]
                if len(puts_short) and len(puts_long):
                    short_put = min(puts_short, key=lambda obj: abs(abs(obj.greeks.delta) - self._put_delta))
                    long_put = next((obj for obj in puts_long if obj.strike == short_put.strike), None)
                    if short_put and long_put:
                        self.Debug(f'Sell put at {short_put.strike}, {np.mean([short_put.ask_price, short_put.bid_price])}')
                        self.Debug(f'Buy put at {long_put.strike}, {np.mean([long_put.ask_price, long_put.bid_price])}')
                        # self.MarketOrder(short_put.Symbol, -1)
                        # self.MarketOrder(long_put.Symbol, 1)
                        legs = [Leg.create(short_put.symbol, -1), Leg.create(long_put.symbol, 1)]
                        ## If I do self.combo_market_order(legs) here, it can go through but the call side will fail due to insufficient buying power.

            if self._call_delta != 0:
                calls = [i for i in chains if i.right == OptionRight.CALL]
                calls_short = [i for i in calls if i.expiry.date() == short_expire_date]
                calls_long = [i for i in calls if i.expiry.date() == long_expire_date]
                if len(calls_short) and len(calls_long):
                    short_call = min(calls_short, key=lambda obj: abs(abs(obj.greeks.delta) - self._call_delta))
                    long_call = next((obj for obj in calls_long if obj.strike == short_call.strike), None)
                    if short_call and long_call:
                        self.Debug(f'Sell call at {short_call.strike}, {np.mean([short_call.ask_price, short_call.bid_price])}')
                        self.Debug(f'Buy call {long_call.strike}, {np.mean([long_call.ask_price, long_call.bid_price])}')
                        # self.MarketOrder(short_call.Symbol, -1)
                        # self.MarketOrder(long_call.Symbol, 1)
                        legs = legs + [Leg.create(short_call.symbol, -1), Leg.create(long_call.symbol, 1)]

            if len(legs) > 0:
                self.combo_market_order(legs, 1) ### Here the legs can include four legs.