StockSharp/StockSharp · error · ArgumentOutOfRangeException

candlesSeries

Error message

candlesSeries

What it means

The Envelope calculator computes upper and lower price bands set at a fixed percentage offset from a moving average. Its Calculate method dispatches a 3DD ILGPU kernel over a series x parameters x candles grid, requiring a pre-computed totalSize (the flattened candle count across all sub-arrays) to size GPU memory buffers. An empty candlesSeries (outer Length == 0) keeps totalSize at 0, producing zero-length buffers and a degenerate kernel grid; ArgumentOutOfRangeException(nameof(candlesSeries)) fires at method entry to abort before any GPU allocation or dispatch.

Source

Thrown at Algo.Gpu/Indicators/GpuEnvelopeCalculator.cs:135

	/// Initializes a new instance of the <see cref="GpuEnvelopeCalculator"/> class.
	/// </summary>
	/// <param name="context">ILGPU context.</param>
	/// <param name="accelerator">ILGPU accelerator.</param>
	public GpuEnvelopeCalculator(Context context, Accelerator accelerator)
		: base(context, accelerator)
	{
		_paramsSeriesKernel = Accelerator.LoadAutoGroupedStreamKernel
			<Index3D, ArrayView<GpuCandle>, ArrayView<GpuEnvelopeResult>, ArrayView<int>, ArrayView<int>, ArrayView<GpuEnvelopeParams>>(EnvelopeParamsSeriesKernel);
	}

	/// <inheritdoc />
	public override GpuEnvelopeResult[][][] Calculate(GpuCandle[][] candlesSeries, GpuEnvelopeParams[] parameters)
	{
		ArgumentNullException.ThrowIfNull(candlesSeries);
		ArgumentNullException.ThrowIfNull(parameters);

		if (candlesSeries.Length == 0)
			throw new ArgumentOutOfRangeException(nameof(candlesSeries));

		if (parameters.Length == 0)
			throw new ArgumentOutOfRangeException(nameof(parameters));

		var seriesCount = candlesSeries.Length;

		// Flatten input
		var totalSize = 0;
		var seriesOffsets = new int[seriesCount];
		var seriesLengths = new int[seriesCount];

		for (var s = 0; s < seriesCount; s++)
		{
			seriesOffsets[s] = totalSize;
			var len = candlesSeries[s]?.Length ?? 0;
			seriesLengths[s] = len;
			totalSize += len;
		}

View on GitHub (pinned to 601a191de6)

Solutions

  1. Guard the call site: check candlesSeries.Length > 0 before invoking Calculate and return an empty GpuEnvelopeResult[][][] or log a warning instead of letting it throw.
  2. Verify the upstream data provider (REST API, database, file cache) actually returned rows; log the series count at the data boundary.
  3. If building the series from multiple sources or filters, ensure at least one sub-array with candles survives deduplication and date-range filtering.
  4. For batch pipelines, skip the calculator for symbols flagged as having insufficient data rather than passing an empty array through.

Example fix

// before -- throws ArgumentOutOfRangeException (ParamName: candlesSeries)
var results = calculator.Calculate(candlesSeries, parameters);

// after -- guard before calling
if (candlesSeries is null || candlesSeries.Length == 0)
{
    logger.LogWarning("GpuEnvelopeCalculator: no candle series, skipping");
    return Array.Empty<GpuEnvelopeResult[][][]>();
}
var results = calculator.Calculate(candlesSeries, parameters);
Defensive patterns

Strategy: validation

Validate before calling

// Pre-call validation for GpuEnvelopeCalculator.Calculate
if (candlesSeries is null || candlesSeries.Length == 0)
{
    logger.LogWarning("GpuEnvelopeCalculator: candle series is null or empty");
    return Array.Empty<GpuEnvelopeResult[][][]>();
}

Type guard

static bool HasCandleSeries(GpuCandle[][]? candlesSeries) =>
    candlesSeries is { Length: > 0 };

Try / catch

GpuEnvelopeResult[][][] results;
try
{
    results = calculator.Calculate(candlesSeries, parameters);
}
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "candlesSeries")
{
    logger.LogWarning("GpuEnvelopeCalculator: candle series was empty, returning empty results");
    results = Array.Empty<GpuEnvelopeResult[][][]>();
}

Prevention

When it happens

Trigger: Calling Calculate with a GpuCandle[][] whose outer Length is 0 (e.g., calculator.Calculate(Array.Empty<GpuCandle[]>(), parameters)). Also triggered when a LINQ pipeline, API deserializer, or database query returns an empty collection that is forwarded to Calculate without checking the element count.

Common situations: Newly listed symbols with no historical candle data in the data store; a date-range filter that excludes all available candles (weekends, holidays, future dates); a backfill job that failed silently or has not completed; a REST API or database query returning zero rows forwarded without a count check; a test fixture that constructed the calculator but forgot to populate candle data.

Related errors


AI-assisted analysis of StockSharp/StockSharp@601a191de6 (2026-08-13). Data as JSON: /api/errors/8d62f3d34ac5f109. Report an issue: GitHub.