QuantConnect/Lean · error · RegressionTestException
Index is not tradable.
Error message
Index is not tradable.
What it means
Thrown in OnEndOfAlgorithm when Portfolio[Spx].TotalSaleVolume is greater than zero, meaning the Lean engine filled at least one order directly on the SPX index symbol. Index securities are non-tradable by design — they serve as price references and option underlyings only. A fill on the index itself indicates the engine incorrectly treated the index as a tradable security.
Source
Thrown at Algorithm.CSharp/BasicTemplateIndexAlgorithm.cs:112
}
/// <summary>
/// Asserts indicators are ready
/// </summary>
/// <exception cref="RegressionTestException"></exception>
protected void AssertIndicators()
{
if (!_emaSlow.IsReady || !_emaFast.IsReady)
{
throw new RegressionTestException("Indicators are not ready!");
}
}
public override void OnEndOfAlgorithm()
{
if (Portfolio[Spx].TotalSaleVolume > 0)
{
throw new RegressionTestException("Index is not tradable.");
}
AssertIndicators();
}
/// <summary>
/// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm.
/// </summary>
public virtual bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public virtual List<Language> Languages { get; } = new() { Language.CSharp, Language.Python };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public virtual long DataPoints => 16199;View on GitHub (pinned to d2c3659f87)
Solutions
- Ensure all order calls use SpxOption (or another tradable derivative), never Spx directly.
- Verify Securities[Spx].IsTradable is false after Initialize — add a debug log to confirm.
- Check IndexSecurity constructor and SecurityService for changes that may have reset IsTradable to true.
- Inspect the algorithm's OnData logic to confirm no Liquidate(Spx) or MarketOrder(Spx) call paths exist.
Example fix
// before — accidentally trading the index MarketOrder(Spx, 1); // after — trade the option on the index MarketOrder(SpxOption, 1);
Defensive patterns
Strategy: validation
Validate before calling
// Before running, verify index is non-tradable
if (Securities[Spx].IsTradable)
{
Log($"WARNING: {Spx} is marked tradable — index should not be tradable");
} Type guard
bool IsIndexNonTradable(Symbol sym) =>
Securities[sym].Type == SecurityType.Index && !Securities[sym].IsTradable; Try / catch
try
{
if (Portfolio[Spx].TotalSaleVolume > 0)
throw new RegressionTestException("Index is not tradable.");
}
catch (RegressionTestException ex)
{
Log($"Index fill detected: volume={Portfolio[Spx].TotalSaleVolume}");
throw;
} Prevention
- Never pass an index Symbol directly to MarketOrder, SetHoldings, or Liquidate.
- Add a code review check for any order method call with an index-typed symbol.
- Log Securities[index].IsTradable after Initialize to verify default behavior.
- Use option or ETF symbols derived from the index for all trades.
When it happens
Trigger: Code calls MarketOrder(Spx, qty) or SetHoldings(Spx, target) on the raw index symbol, the engine's security initialization fails to set IsTradable=false for index types, or a brokerage model change inadvertently allows index order fills.
Common situations: Accidentally passing the index Symbol instead of an option Symbol to an order method, a regression introduced in SecurityService or BrokerageModel that changes the default tradability of Index securities, or modifying the algorithm to trade the index directly without using SetIsTradable(true) first.
Related errors
- Index is not tradable.
- Index is not tradable.
- Index is tradable.
- Expected positive TotalMarginUsed, got {Portfolio.TotalMargi
- Expected an open position at end of algorithm
AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13).
Data as JSON: /api/errors/af84a67c952b8d40.
Report an issue: GitHub.