QuantConnect/Lean · error · RegressionTestException
We shouldn't be invested anymore
Error message
We shouldn't be invested anymore
What it means
OnEndOfAlgorithm asserts Portfolio.Invested is false. The algorithm enters future-option positions each month but expects them all to be closed by expiry/delisting before the algorithm ends. A remaining investment means a position was not liquidated at contract expiry.
Source
Thrown at Algorithm.CSharp/DelistingFutureOptionRegressionAlgorithm.cs:91
foreach (var chain in slice.OptionChains.Values)
{
foreach (var contractsValue in chain.Contracts.Values)
{
MarketOrder(contractsValue.Symbol, 1);
_traded = true;
}
}
}
public override void OnEndOfAlgorithm()
{
if (!_traded)
{
throw new RegressionTestException("We expected some FOP trading to happen");
}
if (Portfolio.Invested)
{
throw new RegressionTestException("We shouldn't be invested anymore");
}
}
/// <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 bool CanRunLocally { get; } = true;
/// <summary>
/// This is used by the regression test system to indicate which languages this algorithm is written in.
/// </summary>
public List<Language> Languages { get; } = new() { Language.CSharp };
/// <summary>
/// Data Points count of all timeslices of algorithm
/// </summary>
public virtual long DataPoints => 462641;
View on GitHub (pinned to d2c3659f87)
Solutions
- Check which symbol is still invested at OnEndOfAlgorithm via Portfolio.Holdings or Securities.Values.Where(s => s.Invested).
- Verify the held contract's expiry date is on or before SetEndDate (2020-03-23).
- Ensure Lean delisting liquidation processes future options correctly (this regression guards issue #5160).
- If the end date genuinely leaves an open position, either liquidate manually before end or adjust the date.
Defensive patterns
Strategy: validation
Validate before calling
public override void OnEndOfAlgorithm()
{
if (Portfolio.Invested)
{
var held = Securities.Values.Where(s => s.Invested).Select(s => s.Symbol);
throw new InvalidOperationException($"Still invested in: {string.Join(",", held)}");
}
} Prevention
- Ensure all entered positions expire before SetEndDate or liquidate manually.
- Log held symbols and their expiry dates near the end of the algorithm.
- Verify delisting liquidation fires for future options.
When it happens
Trigger: A FOP or future position survives past its expiry because Lean's automatic delisting liquidation did not fire, or because the contract was not yet delisted by the algorithm end date (2020-03-23).
Common situations: The end date falls before the last held contract's expiry, a delisting liquidation bug, or the algorithm re-enters a position late in the final month that does not expire before end.
Related errors
- [{UtcTime}] We hold a delisted securities: {string.Join(",",
- Expiry warning with time {delisting.time} but is expected to
- Delisting warning received at an unexpected date: {self.time
- Delisting occurred at unexpected time: {delisting.time} - ex
- Delisting notice received at an unexpected date: {self.time}
AI-assisted analysis of QuantConnect/Lean@d2c3659f87 (2026-08-13).
Data as JSON: /api/errors/46f0d5db262f85c7.
Report an issue: GitHub.