StockSharp/StockSharp · error · ArgumentException
Indicator cannot be composite.
Error message
Indicator cannot be composite.
What it means
ValidateIndicators() is called by the multi-indicator Bind overloads (2 through 8 indicators). It rejects any indicator that implements IComplexIndicator (a composite indicator with multiple result outputs) because the decimal extraction logic val.ToDecimal(indicator.Source) assumes a single-result indicator. Composite indicators produce multiple result values that cannot be mapped to a single decimal, so binding them through this path would produce incorrect data.
Source
Thrown at Algo.Strategies/Legacy/StrategyOld_HighLevel.cs:662
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
- Replace composite indicators with their individual simple sub-indicators (e.g., use the MACD's SignalLine or Histogram component directly rather than the MACD container).
- For composite indicators, use BindEx with IIndicatorValue[] callbacks instead of Bind with decimal[] callbacks, which handles multi-output values.
- Check indicator is not IComplexIndicator before passing to Bind overloads that validate.
Example fix
// before
handler.Bind(new[] { sma, macd }, (msg, vals) => { ... });
// macd is IComplexIndicator -> throws
// after
handler.Bind(new[] { sma, macd.SignalLine }, (msg, vals) => { ... });
// or use BindEx:
handler.BindEx(new[] { sma, macd }, (msg, ivs) => { ... }, false); Defensive patterns
Strategy: validation
Validate before calling
foreach (var ind in indicators)
{
if (ind is IComplexIndicator)
throw new InvalidOperationException($"{ind.GetType().Name} is composite; use BindEx or sub-indicators.");
} Type guard
static bool IsSimpleIndicator(IIndicator ind) => ind is not IComplexIndicator;
Prevention
- Check for IComplexIndicator before passing indicators to multi-indicator Bind overloads.
- Use sub-indicator components (e.g., macd.SignalLine) instead of the composite container.
- Fall back to BindEx with IIndicatorValue[] callbacks when composites are needed.
When it happens
Trigger: Passing a composite indicator (e.g., one implementing IComplexIndicator like Macd or any multi-output indicator) to a Bind overload that calls ValidateIndicators.
Common situations: Using a MACD, Band, or other multi-output indicator in a multi-indicator Bind call. Refactoring a single-output indicator into a composite without updating the binding code. Misidentifying an indicator as simple when it actually implements IComplexIndicator.
Related errors
- Indicators array cannot be empty.
- Indicator cannot be null.
- Specified argument was out of the range of valid values. (Pa
- Specified argument was out of the range of valid values. (Pa
- Specified argument was out of the range of valid values. (Pa
AI-assisted analysis of StockSharp/StockSharp@601a191de6 (2026-08-13).
Data as JSON: /api/errors/c6a2c29a5ce649e3.
Report an issue: GitHub.