Assistance with custom indicator when referencing - Error MSB4006 There is a circular dependency in the target dependency graph
Created at 04 Jan 2025, 13:36
Assistance with custom indicator when referencing - Error MSB4006 There is a circular dependency in the target dependency graph
04 Jan 2025, 13:36
Good day
I need assistance with a custom indicator error MSB4006; the indicator displays data correctly but when referencing it from a cBot, it generates an error when building the bot. The indicator is an NRTR Channel indicator.
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
namespace cAlgo
{
[Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class NRTRChannel : Indicator
{
[Parameter("ATR Period", DefaultValue = 40)]
public int ATRPeriod { get; set; }
[Parameter("ATR Multiplier", DefaultValue = 2.0)]
public double ATRMultiplier { get; set; }
[Parameter("Show Price Labels", DefaultValue = true)]
public bool ShowLabels { get; set; }
[Output("longResistance", LineColor = "DeepSkyBlue", PlotType = PlotType.DiscontinuousLine, LineStyle = LineStyle.Dots, Thickness = 2)]
public IndicatorDataSeries CeilingBuffer { get; set; }
[Output("longSupport", LineColor = "DeepSkyBlue", PlotType = PlotType.DiscontinuousLine, LineStyle = LineStyle.Dots, Thickness = 2)]
public IndicatorDataSeries BuyBuffer { get; set; }
[Output("shortSupport", LineColor = "LightSalmon", PlotType = PlotType.DiscontinuousLine, LineStyle = LineStyle.Dots, Thickness = 2)]
public IndicatorDataSeries SellBuffer { get; set; }
[Output("shortResistance", LineColor = "LightSalmon", PlotType = PlotType.DiscontinuousLine, LineStyle = LineStyle.Dots, Thickness = 2)]
public IndicatorDataSeries FloorBuffer { get; set; }
private IndicatorDataSeries trendBuffer;
private AverageTrueRange atr;
private const int UP_TREND = 1;
private const int DOWN_TREND = -1;
protected override void Initialize()
{
trendBuffer = CreateDataSeries();
atr = Indicators.AverageTrueRange(ATRPeriod, MovingAverageType.Simple);
}
public override void Calculate(int index)
{
if (index <= ATRPeriod)
return;
if (index == ATRPeriod + 1)
{
if (Bars.ClosePrices[index] > Bars.LowPrices[index])
{
trendBuffer[index] = UP_TREND;
CeilingBuffer[index] = Bars.ClosePrices[index];
BuyBuffer[index] = Bars.ClosePrices[index] - ATRMultiplier * atr.Result[index];
}
else
{
trendBuffer[index] = DOWN_TREND;
FloorBuffer[index] = Bars.ClosePrices[index];
SellBuffer[index] = Bars.ClosePrices[index] + ATRMultiplier * atr.Result[index];
}
return;
}
if (trendBuffer[index - 1] > 0)
{
if (Bars.LowPrices[index] > CeilingBuffer[index - 1])
{
CeilingBuffer[index] = Bars.ClosePrices[index];
FloorBuffer[index] = double.NaN;
BuyBuffer[index] = Bars.ClosePrices[index] - ATRMultiplier * atr.Result[index];
SellBuffer[index] = double.NaN;
trendBuffer[index] = UP_TREND;
}
else if (Bars.ClosePrices[index] < BuyBuffer[index - 1])
{
trendBuffer[index] = DOWN_TREND;
FloorBuffer[index] = Bars.ClosePrices[index];
SellBuffer[index] = Bars.ClosePrices[index] + ATRMultiplier * atr.Result[index];
CeilingBuffer[index] = double.NaN;
BuyBuffer[index] = double.NaN;
}
else
{
CopyPreviousValues(index);
}
}
else
{
if (Bars.HighPrices[index] < FloorBuffer[index - 1])
{
FloorBuffer[index] = Bars.ClosePrices[index];
CeilingBuffer[index] = double.NaN;
SellBuffer[index] = Bars.ClosePrices[index] + ATRMultiplier * atr.Result[index];
BuyBuffer[index] = double.NaN;
trendBuffer[index] = DOWN_TREND;
}
else if (Bars.ClosePrices[index] > SellBuffer[index - 1])
{
trendBuffer[index] = UP_TREND;
CeilingBuffer[index] = Bars.ClosePrices[index];
BuyBuffer[index] = Bars.ClosePrices[index] - ATRMultiplier * atr.Result[index];
FloorBuffer[index] = double.NaN;
SellBuffer[index] = double.NaN;
}
else
{
CopyPreviousValues(index);
}
}
if (ShowLabels && index == Bars.ClosePrices.Count - 1)
{
ShowPriceLevels(index);
}
}
private void CopyPreviousValues(int index)
{
SellBuffer[index] = SellBuffer[index - 1];
BuyBuffer[index] = BuyBuffer[index - 1];
CeilingBuffer[index] = CeilingBuffer[index - 1];
FloorBuffer[index] = FloorBuffer[index - 1];
trendBuffer[index] = trendBuffer[index - 1];
}
private void ShowPriceLevels(int index)
{
var existingLabels = Chart.Objects.Where(obj => obj.Name.StartsWith("NRTR_"));
foreach (var label in existingLabels)
{
Chart.RemoveObject(label.Name);
}
cAlgo.API.Color color;
double upperLevel, lowerLevel;
if (trendBuffer[index] == UP_TREND)
{
color = cAlgo.API.Color.DeepSkyBlue;
upperLevel = CeilingBuffer[index];
lowerLevel = BuyBuffer[index];
}
else
{
color = cAlgo.API.Color.LightSalmon;
upperLevel = SellBuffer[index];
lowerLevel = FloorBuffer[index];
}
if (!double.IsNaN(upperLevel))
{
var upperText = Chart.DrawText(
"NRTR_Res_" + index,
upperLevel.ToString("F5"),
index,
upperLevel,
color
);
upperText.VerticalAlignment = VerticalAlignment.Center;
upperText.HorizontalAlignment = HorizontalAlignment.Right;
}
if (!double.IsNaN(lowerLevel))
{
var lowerText = Chart.DrawText(
"NRTR_Sup_" + index,
lowerLevel.ToString("F5"),
index,
lowerLevel,
color
);
lowerText.VerticalAlignment = VerticalAlignment.Center;
lowerText.HorizontalAlignment = HorizontalAlignment.Right;
}
}
}
}