QuantConnect/Lean · error · RegressionTestException

CustomOptionPriceModel.Evaluate() was never called

Error message

CustomOptionPriceModel.Evaluate() was never called

What it means

Asserts the custom option price model's Evaluate was invoked at least once. EvaluationCount is incremented inside CustomOptionPriceModel.Evaluate; if it is 0 at OnEndOfAlgorithm, the option never priced a contract (no evaluation request reached the model).

Source

Thrown at Algorithm.CSharp/CustomOptionPriceModelRegressionAlgorithm.cs:74

                var underlyingPrice = chain.Underlying.Price;
                var atmContract = chain
                    .OrderByDescending(x => x.Expiry)
                    .ThenBy(x => Math.Abs(chain.Underlying.Price - x.Strike))
                    .ThenByDescending(x => x.Right)
                    .FirstOrDefault();

                if (atmContract != null && atmContract.TheoreticalPrice > 0)
                {
                    MarketOrder(atmContract.Symbol, 1);
                }
            }
        }

        public override void OnEndOfAlgorithm()
        {
            if (_optionPriceModel.EvaluationCount == 0)
            {
                throw new RegressionTestException("CustomOptionPriceModel.Evaluate() was never called");
            }
        }

        private class CustomOptionPriceModel : IOptionPriceModel
        {
            public int EvaluationCount { get; private set; }
            public OptionPriceModelResult Evaluate(OptionPriceModelParameters parameters)
            {
                EvaluationCount++;
                var contract = parameters.Contract;
                var underlying = contract.UnderlyingLastPrice;
                var strike = contract.Strike;
                var greeks = new Greeks(0.5m, 0.2m, 0.15m, 0.05m, 0.1m, 2.0m);

                decimal intrinsicValue;
                if (contract.Right == OptionRight.Call)
                {
                    intrinsicValue = Math.Max(0, underlying - strike);

View on GitHub (pinned to d2c3659f87)

Solutions

  1. Ensure the algorithm accesses an option contract's price/Greeks (e.g., evaluates atmContract.TheoreticalPrice) so the engine invokes Evaluate.
  2. Confirm SetOptionPriceModel is called on the option security (not the underlying) and that the option chain resolves at least one contract.
  3. Verify the ATM selection logic actually picks a contract; a null atmContract skips the evaluation path.
  4. Run over a date range with active option data so the chain populates and pricing is requested.

Example fix

// before: model set but never queried, Evaluate never runs
option.SetOptionPriceModel(new CustomOptionPriceModel());
// ...no Greek/price access...

// after: force an evaluation by reading the theoretical price
var atm = OptionChainProvider.GetOptionContractList(option.Symbol, Time).First();
var _ = atm.TheoreticalPrice; // triggers Evaluate, increments EvaluationCount
Defensive patterns

Strategy: validation

Validate before calling

// Confirm an option contract resolves and force an evaluation
var chain = OptionChainProvider.GetOptionContractList(option.Symbol, Time);
if (!chain.Any()) Log("No option contracts; price model will not be evaluated.");

Type guard

bool HasContracts(IEnumerable<Symbol> chain) => chain.Any();

Prevention

When it happens

Trigger: Assigning an IOptionPriceModel to an option contract (e.g., SetOptionPriceModel or option.PriceModel = ...) but the engine never requests a price evaluation because no Greek/price query occurred, or the model was assigned to the wrong object.

Common situations: Model set after the option was added but the algorithm never accessed Greeks/TheoreticalPrice, so evaluation was never triggered; the ATM-contract branch (atmContract != null && TheoreticalPrice > 0) never executed because no contract resolved; or the model was assigned to a non-option security.

Related errors


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