StockSharp/StockSharp · error · ArgumentException
Indicator cannot be composite.
Error message
Indicator cannot be composite.
What it means
Thrown by ValidateIndicators when an indicator argument implements IComplexIndicator (line 592-593). The scalar Bind/BindWithEmpty overloads extract exactly one decimal per indicator via indicator.Source, which is meaningless for a composite that emits several values (e.g. Bollinger Bands: UpBand/LowBand/MovingAverage), so composites are explicitly rejected with 'Indicator cannot be composite.'
Source
Thrown at Algo.Strategies/Strategy_HighLevelSubscriptions.cs:593
iv1.ToDecimal(indicator1.Source),
iv2.ToDecimal(indicator2.Source),
iv3.ToDecimal(indicator3.Source),
iv4.ToDecimal(indicator4.Source),
iv5.ToDecimal(indicator5.Source),
iv6.ToDecimal(indicator6.Source),
iv7.ToDecimal(indicator7.Source),
iv8.ToDecimal(indicator8.Source)), false);
}
private static void ValidateIndicators(params IIndicator[] indicators)
{
foreach (var ind in indicators)
{
if (ind is null)
throw new ArgumentNullException(nameof(indicators));
if (ind is IComplexIndicator)
throw new ArgumentException(LocalizedStrings.IndicatorNotComposite, nameof(indicators));
}
}
public ISubscriptionHandler<T> Bind(IIndicator[] indicators, Action<T, decimal[]> callback)
{
if (callback is null)
throw new ArgumentNullException(nameof(callback));
if (indicators is null)
throw new ArgumentNullException(nameof(indicators));
if (indicators.Any(i => i is IComplexIndicator))
throw new ArgumentException(LocalizedStrings.IndicatorNotComposite, nameof(indicators));
return BindEx(indicators, (v, ivs) => callback(v, [.. ivs.Select((val, idx) => val.ToDecimal(indicators[idx].Source))]), false);
}
public ISubscriptionHandler<T> BindWithEmpty(IIndicator[] indicators, Action<T, decimal?[]> callback)View on GitHub (pinned to 601a191de6)
Solutions
- Bind one of the composite's inner child indicators instead (e.g. bb.UpBand, bb.LowBand, or bb.MovingAverage), which are themselves non-composite IIndicator.
- Use BindEx(IIndicator, Action<T, IIndicatorValue>, bool) to receive the full IIndicatorValue and read whichever output you need.
- For multiple child outputs at once, use BindEx(IIndicator[], ...) and downcast each IIndicatorValue to the composite's typed value interface.
Example fix
// before
var bb = new BollingerBands();
handler.Bind(bb, (c, v) => OnPrice(c, v)); // ArgumentException: Indicator cannot be composite.
// after - bind a single inner band
handler.Bind(bb.UpBand, (c, v) => OnPrice(c, v));
// or read full composite value via BindEx
handler.BindEx(bb, (c, iv) => {
var bv = (IBollingerBandsValue)iv;
OnBands(c, bv.UpBand, bv.LowBand, bv.MovingAverage);
}, allowEmpty: true); Defensive patterns
Strategy: type-guard
Validate before calling
// Reject composites before calling a scalar Bind overload.
static void EnsureScalar(params IIndicator[] inds)
{
foreach (var i in inds)
if (i is IComplexIndicator)
throw new InvalidOperationException($"{i?.GetType().Name} is composite; bind an inner child or use BindEx.");
}
EnsureScalar(ind1, ind2);
handler.Bind(ind1, ind2, cb); Type guard
static bool IsScalarIndicator(IIndicator i)
=> i is not null && i is not IComplexIndicator; Prevention
- Know which indicators are composite: BollingerBands, StochasticOscillator, Ichimoku, Alligator, Envelope, Keltner/Donchian/Price channels, ADX/DMI, MACD-histogram variants, etc.
- For a composite, bind its inner child indicator (e.g. bb.UpBand) or use BindEx to receive the full IIndicatorValue.
- Filter dynamically-built indicator lists to exclude IComplexIndicator before passing them to a scalar Bind.
When it happens
Trigger: Passing any BaseComplexIndicator subclass directly into a positional Bind/BindWithEmpty: BollingerBands, StochasticOscillator, Ichimoku, Alligator, KeltnerChannels, DonchianChannels, Envelope, AverageDirectionalIndex, and ~30 others.
Common situations: Treating a composite indicator like a single-value indicator; assuming the fluent binder will pick a default band; upgrading a strategy from a single SMA to Bollinger Bands without switching to BindEx.
Related errors
- Value cannot be null. (Parameter 'indicators')
- LocalizedStrings.InvalidValue
- LocalizedStrings.InvalidValue
- LocalizedStrings.InvalidValue
- LocalizedStrings.InvalidValue
AI-assisted analysis of StockSharp/StockSharp@601a191de6 (2026-08-13).
Data as JSON: /api/errors/e0586f7c5df99b67.
Report an issue: GitHub.