QuantConnect/Lean · error · RegressionTestException

Trade volume should be greater than zero by the end of this

Error message

Trade volume should be greater than zero by the end of this algorithm

What it means

Thrown in OnEndOfAlgorithm when Portfolio.TotalSaleVolume equals zero, meaning no option orders were filled during the entire algorithm run. This assertion verifies that the EMA-cross trading logic actually generated and filled option orders on SPX contracts.

Source

Thrown at Algorithm.CSharp/BasicTemplateIndexOptionsAlgorithm.cs:110

                    }
                    else if (_emaFast < _emaSlow && contract.Right == OptionRight.Put)
                    {
                        Liquidate(InvertOption(contract.Symbol));
                        MarketOrder(contract.Symbol, 1);
                    }
                }
            }
        }

        public override void OnEndOfAlgorithm()
        {
            if (Portfolio[_spx].TotalSaleVolume > 0)
            {
                throw new RegressionTestException("Index is not tradable.");
            }
            if (Portfolio.TotalSaleVolume == 0)
            {
                throw new RegressionTestException("Trade volume should be greater than zero by the end of this algorithm");
            }
            AssertIndicators();
        }

        public Symbol InvertOption(Symbol symbol)
        {
            return QuantConnect.Symbol.CreateOption(
                symbol.Underlying,
                symbol.ID.Market,
                symbol.ID.OptionStyle,
                symbol.ID.OptionRight == OptionRight.Call ? OptionRight.Put : OptionRight.Call,
                symbol.ID.StrikePrice,
                symbol.ID.Date);
        }

        /// <summary>
        /// Asserts indicators are ready
        /// </summary>

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Verify SPX option data exists for the full date range (2021-01-04 to 2021-02-01).
  2. Check that slice.OptionChains is populated in OnData — log chain count per slice.
  3. Ensure EMA crossover occurs: log _emaFast and _emaSlow values to confirm the condition triggers.
  4. Relax or verify the CallsOnly filter does not exclude all available contracts.
  5. Inspect order tickets for rejection messages via ticket.Status and ticket.CancelMessage.

Example fix

// before — no log visibility into why no trades
if (Portfolio.TotalSaleVolume == 0)
{
    throw new RegressionTestException("Trade volume should be greater than zero");
}

// after — diagnose before asserting
if (Portfolio.TotalSaleVolume == 0)
{
    Log($"EMA Fast Ready: {_emaFast.IsReady}, Slow Ready: {_emaSlow.IsReady}");
    Log($"Cross current: fast={_emaFast} slow={_emaSlow}");
    throw new RegressionTestException("Trade volume should be greater than zero");
}
Defensive patterns

Strategy: validation

Validate before calling

// Before asserting volume, log diagnostic state
if (Portfolio.TotalSaleVolume == 0)
{
    Log($"EMA fast ready={_emaFast.IsReady}, slow ready={_emaSlow.IsReady}");
    Log($"Cross state: fast={_emaFast}, slow={_emaSlow}, fast>slow={_emaFast > _emaSlow}");
    Log($"Option chains received: check OnData logs");
}

Prevention

When it happens

Trigger: The EMA fast/slow cross condition never triggers because indicators are not ready, the option chain filter (CallsOnly) returns no contracts, slice.OptionChains is always empty, or MarketOrder calls are rejected/invalid before filling.

Common situations: Option data files missing for the date range, option filter too restrictive, EMA indicators never reaching the crossover state within the backtest window, or a brokerage model change rejecting option orders.

Related errors


AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13). Data as JSON: /api/errors/d9727421796d5cfc. Report an issue: GitHub.