StockSharp/StockSharp · error · ArgumentOutOfRangeException

Specified argument was out of the range of valid values. (Pa

Error message

Specified argument was out of the range of valid values. (Parameter 'candlesSeries')

What it means

GpuPriceVolumeTrendCalculator.Calculate throws ArgumentOutOfRangeException on the 'candlesSeries' guard when the outer series array is empty (Length == 0). This is the array-of-series, not an individual candle array: a null inner series is tolerated via `candlesSeries[s]?.Length ?? 0`, but a completely empty outer array leaves nothing to process and is rejected before GPU buffer allocation.

Source

Thrown at Algo.Gpu/Indicators/GpuPriceVolumeTrendCalculator.cs:44

	/// Initializes a new instance of the <see cref="GpuPriceVolumeTrendCalculator"/> class.
	/// </summary>
	/// <param name="context">ILGPU context.</param>
	/// <param name="accelerator">ILGPU accelerator.</param>
	public GpuPriceVolumeTrendCalculator(Context context, Accelerator accelerator)
		: base(context, accelerator)
	{
		_kernel = Accelerator.LoadAutoGroupedStreamKernel
			<Index2D, ArrayView<GpuCandle>, ArrayView<GpuIndicatorResult>, ArrayView<int>, ArrayView<int>, ArrayView<GpuPriceVolumeTrendParams>>(PriceVolumeTrendParamsSeriesKernel);
	}

	/// <inheritdoc />
	public override GpuIndicatorResult[][][] Calculate(GpuCandle[][] candlesSeries, GpuPriceVolumeTrendParams[] 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. Pass a candlesSeries array containing at least one (possibly empty or null) inner series, or skip the call entirely when there are no series.
  2. If you intend 'nothing to do', return an empty result from the caller rather than calling the GPU calculator.
  3. Validate the symbol universe upstream so an empty batch is handled before reaching Calculate.

Example fix

// before
calc.Calculate(Array.Empty<GpuCandle[]>(), parameters);
// after
if (candlesSeries.Length == 0) return Array.Empty<GpuIndicatorResult[][]>();
calc.Calculate(candlesSeries, parameters);
Defensive patterns

Strategy: validation

Validate before calling

if (candlesSeries is null || candlesSeries.Length == 0) return Array.Empty<GpuIndicatorResult[][]>();

Type guard

static bool HasSeries(GpuCandle[][] series) => series is { Length: > 0 };

Prevention

When it happens

Trigger: Calling Calculate(new GpuCandle[0][], parameters) or Calculate(Array.Empty<GpuCandle[]>(), parameters). Also when a multi-symbol batch ends up with zero symbols after filtering.

Common situations: A symbol universe filter removes every symbol; a date-range query returns no candles so the caller passes an empty series array; a test harness forgets to seed candle data.

Related errors


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