StockSharp/StockSharp · error · ArgumentOutOfRangeException
candlesSeries
Error message
candlesSeries
What it means
The Fractal Adaptive Moving Average (FRAMA) calculator computes an adaptive moving average whose smoothing constant responds to the fractal dimension of recent price action. Its Calculate method dispatches a 2DD ILGPU kernel over a series x parameters 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/GpuFractalAdaptiveMovingAverageCalculator.cs:62
/// Initializes a new instance of the <see cref="GpuFractalAdaptiveMovingAverageCalculator"/> class.
/// </summary>
/// <param name="context">ILGPU context.</param>
/// <param name="accelerator">ILGPU accelerator.</param>
public GpuFractalAdaptiveMovingAverageCalculator(Context context, Accelerator accelerator)
: base(context, accelerator)
{
_kernel = Accelerator.LoadAutoGroupedStreamKernel
<Index2D, ArrayView<GpuCandle>, ArrayView<GpuIndicatorResult>, ArrayView<int>, ArrayView<int>, ArrayView<GpuFramaParams>>(FramaParamsSeriesKernel);
}
/// <inheritdoc />
public override GpuIndicatorResult[][][] Calculate(GpuCandle[][] candlesSeries, GpuFramaParams[] 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
- Guard the call site: check candlesSeries.Length > 0 before invoking Calculate and return an empty GpuIndicatorResult[][][] or log a warning instead of letting it throw.
- Verify the upstream data provider (REST API, database, file cache) actually returned rows; log the series count at the data boundary.
- If building the series from multiple sources or filters, ensure at least one sub-array with candles survives deduplication and date-range filtering.
- 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("GpuFractalAdaptiveMovingAverageCalculator: no candle series, skipping");
return Array.Empty<GpuIndicatorResult[][][]>();
}
var results = calculator.Calculate(candlesSeries, parameters); Defensive patterns
Strategy: validation
Validate before calling
// Pre-call validation for GpuFractalAdaptiveMovingAverageCalculator.Calculate
if (candlesSeries is null || candlesSeries.Length == 0)
{
logger.LogWarning("GpuFractalAdaptiveMovingAverageCalculator: candle series is null or empty");
return Array.Empty<GpuIndicatorResult[][][]>();
} Type guard
static bool HasCandleSeries(GpuCandle[][]? candlesSeries) =>
candlesSeries is { Length: > 0 }; Try / catch
GpuIndicatorResult[][][] results;
try
{
results = calculator.Calculate(candlesSeries, parameters);
}
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "candlesSeries")
{
logger.LogWarning("GpuFractalAdaptiveMovingAverageCalculator: candle series was empty, returning empty results");
results = Array.Empty<GpuIndicatorResult[][][]>();
} Prevention
- Null- and empty-check every jagged array before passing it to a GPU calculator.
- Log element counts at each data boundary (API, cache, file) to catch upstream gaps early.
- Skip calculation for symbols flagged as having insufficient data instead of passing an empty array through.
- Write edge-case unit tests that pass empty and single-element series to verify guard behavior.
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/22aa17e1d40e8fcb.
Report an issue: GitHub.