Hi staff, 

 I have been hitting my head against the wall for weeks now trying to figure this out and learn your platform! I am trying to write a simple bot that buys 0.7 delta call credit spreads. I modified the code to just buy one spread at a time, and it keeps giving me insufficient buying power errors. How can I fix this?

using System; using System.Collections.Generic; using System.Linq; using QuantConnect.Data; using QuantConnect.Data.Market; using QuantConnect.Data.Custom.CBOE; using QuantConnect.Interfaces; using QuantConnect.Orders; using QuantConnect.Securities.Option; namespace QuantConnect.Algorithm.CSharp { public class VentralCalibratedProcessor : QCAlgorithm { private Symbol _equitySymbol; private Symbol _optionSymbol; private QuantConnect.Indicators.RelativeStrengthIndex _rsi; public decimal MinDeltaLimit = 0.70M; public decimal MaxTradeSize = 0.25M; private OptionContract _longCall; public int DaysBeforeExp; public override void Initialize() { SetStartDate(2018, 1, 1); //Set Start Date SetEndDate(2018, 3, 1); //Set End Date SetCash(5000); //Set Strategy Cash var equity = AddEquity("SPY", Resolution.Minute); var option = AddOption("SPY", Resolution.Minute); this.Symbol(option.Symbol); _equitySymbol = equity.Symbol; _optionSymbol = option.Symbol; // 14 day RSI _rsi = this.RSI(equity.Symbol, 14); // Filter by 12 strikes and expiration 5 to 10 days option.SetFilter(universe => universe.IncludeWeeklys().Strikes(-15, 15).Expiration(5, 10)); option.PriceModel = OptionPriceModels.CrankNicolsonFD(); UniverseSettings.Leverage = 4; // Adding this to reproduce GH issue #2314 SetWarmup(TimeSpan.FromMinutes(1)); // use the underlying equity as the benchmark SetBenchmark(_equitySymbol); this.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage, AccountType.Margin); //Schedule.On(DateRules.EveryDay("SPY"), TimeRules.Every(TimeSpan.FromMinutes(5)), () =>{ //Debug("Specific Time: Fired at : " + Time); //}); } /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. /// Slice object keyed by symbol containing the stock data public override void OnData(Slice slice) { if(this.IsWarmingUp) return; if (IsMarketOpen(_equitySymbol) == false) { return; } if (!Portfolio.Invested) { OptionChain chain; if (slice.OptionChains.TryGetValue(_optionSymbol, out chain)) { // Find options between delta ranges closest to expiry date var itmCallDebitSpread = from option in chain where Math.Abs(option.Greeks.Delta) <= MinDeltaLimit && option.Right == OptionRight.Call orderby option.Expiry ascending, option.Strike select option; //foreach(var option in itmCallDebitSpread.ToList()){ //Debug(string.Format("Strike: {0} Expiration: {1} DTE: {2}", option.Strike, option.Expiry, (option.Expiry - Time).Days)); //} // Get the spread call options var longCall = itmCallDebitSpread.ToList()[0]; var shortCall = itmCallDebitSpread.ToList()[1]; _longCall = longCall; // Get debit for potential trade var spreadDebit = (longCall.AskPrice - shortCall.AskPrice) * 100; int numOfSpreadsToBuy = 0; bool canAffordToBuy = true; // Only allow trade size of percentage of portfolio var availableCash = Math.Floor(Portfolio.Cash * MaxTradeSize); while(canAffordToBuy){ numOfSpreadsToBuy++; // If we can afford to sell, increment amount if((availableCash - (numOfSpreadsToBuy * spreadDebit)) < 0){ numOfSpreadsToBuy--; canAffordToBuy = false; } } // Sell the spreads if(_rsi < 100) { //Debug("Spread Debit: $" + Math.Abs(numOfSpreadsToBuy * spreadDebit)); //Debug("Short Call Delta: " + shortCall.Greeks.Delta.ToString()); //Debug("Long Call Delta: " + longCall.Greeks.Delta.ToString()); //Debug(string.Format("Strikes - Long: {0} / Short: {1}", longCall.Strike, shortCall.Strike)); //Debug(string.Format("Expiry Date ({0}): {1}", (longCall.Expiry - Time).Days, longCall.Expiry)); // Buy the spreads (We use a loop for margin reasons) for(int i = 1; i<= numOfSpreadsToBuy; i++){ } Buy(longCall.Symbol, 1); Sell(shortCall.Symbol, 1); } } } else{ // Close positions based on stop-loss //foreach(var security in Securities){ //if(security.Value.Holdings.UnrealizedProfitPercent < -0.30M){ //Debug("Stop Loss - Profit Percent (P/L): " + (security.Value.Holdings.UnrealizedProfitPercent * 100) + "%"); //Liquidate(_optionSymbol); //} //} // Close positions before expiration to prevent assignment if(_longCall != null){ if((_longCall.Expiry - Time).Days <= DaysBeforeExp){ //Liquidate(_optionSymbol); //Debug("Closed options contracts early."); } } } } /// <summary> /// Order fill event handler. On an order fill update the resulting information is passed to this method. /// </summary> /// <param name="orderEvent">Order event details containing details of the evemts</param> /// <remarks>This method can be called asynchronously and so should only be used by seasoned C# experts. Ensure you use proper locks on thread-unsafe objects</remarks> public override void OnOrderEvent(OrderEvent orderEvent) { //Log(orderEvent.ToString()); var order = Transactions.GetOrderById(orderEvent.OrderId); if (order.Type == OrderType.OptionExercise){ Log(string.Format("{0}: {1}: {2}", Time, order.Type, orderEvent)); Liquidate(); } } public override void OnAssignmentOrderEvent(OrderEvent orderEvent){ Log(orderEvent.ToString()); Liquidate(); } } }

 

Backtest Handled Error: Order Error: id: 3, Insufficient buying power to complete order (Value:-26100), Reason: Id: 3, Initial Margin: -13707, Free Margin: 0
Order Error: id: 6, Insufficient buying power to complete order (Value:26050), Reason: Id: 6, Initial Margin: 13707, Free Margin: 0

Author