synchronization issue between the indicator and the cBot
synchronization issue between the indicator and the cBot
11 Mar 2025, 18:56
Hello everyone,
I need your help. I'm sure it's something trivial, but I'm just starting out, so I hope you'll forgive me:
So, I tried to write the code for an indicator and then created a cBot with the same logic, but unfortunately, I'm having trouble managing the indication of the last candle to use for calculations.
The logic behind the indicator is very simple:
First, I calculate a channel made up of highs and lows over a specific period, excluding the last candle.
If a candle closes outside the channel, I consider it a breakout signal and open a position following the trend.
The problem is that while for the indicator using the index is sufficient, for the bot I'm using Bars.Count - 1, and this makes me unsure about which candle the bot is actually considering.
In fact, when running a simple backtest of the bot and adding the indicator to the chart, I see that sometimes the bot opens positions even when there are no signals.
I'll share both the indicator and bot codes, and I hope someone more experienced than me (it doesn't take much) can help me out.
Thank you very much!
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
namespace cAlgo
{
[Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
public class BreakingBoundIndicator : Indicator
{
[Parameter("Channel Lenght", DefaultValue = 25)]
public int ChLenght { get; set; }
[Parameter("Skip Amount", DefaultValue = 1, MinValue = 1, Step = 1)]
public int SkipAmount { get; set; } = 1;
// OUTPUT
[Output("UpBoundPlot", LineColor = "gray", PlotType = PlotType.Line, Thickness = 1)]
public IndicatorDataSeries UpBoundPlot { get; set; }
[Output("DownBoundPlot", LineColor = "gray", PlotType = PlotType.Line, Thickness = 1)]
public IndicatorDataSeries DownBoundPlot { get; set; }
private int lastCandle;
private double upBound;
private double downBound;
protected override void Initialize()
{
}
public override void Calculate(int index)
{
lastCandle = index;
//Channel
upBound = Bars.HighPrices.TakeLast(ChLenght + 1).SkipLast(SkipAmount).Max();
downBound = Bars.LowPrices.TakeLast(ChLenght + 1).SkipLast(SkipAmount).Min();
bool breakUp = Bars.ClosePrices[lastCandle] > upBound;
bool breakDown = Bars.ClosePrices[lastCandle] < downBound;
if (breakUp)
{
Chart.DrawIcon("Buy" + lastCandle, ChartIconType.UpTriangle, lastCandle, Bars.LowPrices.Last(), Color.Green);
}
if (breakDown)
{
Chart.DrawIcon("Sell" + lastCandle, ChartIconType.DownTriangle, lastCandle, Bars.HighPrices.Last(), Color.Red);
}
// Plot
UpBoundPlot[lastCandle] = upBound;
DownBoundPlot[lastCandle] = downBound;
}
}
}
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Collections;
namespace cAlgo
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class BreakingBoundsBot : Robot
{
[Parameter("Lots", DefaultValue = 0.5, Group = "Trade", Step = 0.05)]
public double Quantity { get; set; }
[Parameter("Take Profit (Pips)", DefaultValue = 20, Group = "Trade", Step = 1)]
public double TakeProfitInPips { get; set; }
[Parameter("Stop Loss (Pips)", DefaultValue = 18, Group = "Trade", Step = 1)]
public double StopLossInPips { get; set; }
[Parameter("Channel Lenght", DefaultValue = 25)]
public int ChLenght { get; set; }
[Parameter("Skip Amount", DefaultValue = 1, MinValue = 1, Step = 1)]
public int SkipAmount { get; set; } = 1;
private int lastCandle;
private string LabelBuy = "BBB-Buy";
private string LabelSell = "BBB-Sell";
private double upBound;
private double downBound;
protected override void OnStart()
{
}
protected override void OnBar()
{
var volume = Symbol.QuantityToVolumeInUnits(Quantity);
volume = Symbol.NormalizeVolumeInUnits(volume, RoundingMode.Down);
lastCandle = Bars.Count - 1;
//Channel
upBound = Bars.HighPrices.TakeLast(ChLenght + 1).SkipLast(SkipAmount).Max();
downBound = Bars.LowPrices.TakeLast(ChLenght + 1).SkipLast(SkipAmount).Min();
bool breakUp = Bars.ClosePrices[lastCandle] > upBound;
bool breakDown = Bars.ClosePrices[lastCandle] < downBound;
if (breakUp)
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, volume, LabelBuy, StopLossInPips, TakeProfitInPips);
Chart.DrawIcon("Buy" + lastCandle, ChartIconType.UpTriangle, lastCandle, Bars.LowPrices.Last(), Color.Green);
}
if (breakDown)
{
ExecuteMarketOrder(TradeType.Sell, SymbolName, volume, LabelSell, StopLossInPips, TakeProfitInPips);
Chart.DrawIcon("Sell" + lastCandle, ChartIconType.DownTriangle, lastCandle, Bars.HighPrices.Last(), Color.Red);
}
}
}
}