Custom indicator in cBot different results visual mode compared to silent mode

Created at 20 Jun 2024, 13:20
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
BE

bernhardCM

Joined 06.11.2023

Custom indicator in cBot different results visual mode compared to silent mode
20 Jun 2024, 13:20


Hello,

I found a lot of threads regarding that matter and according to these, that matter should be solved actually, but in current cTrader Desktop version I still get different results.

I made an indicator which should show me when price crosses an ema based on ticks, but chart itself is in different timeframe (Minute in my case). On common chart it would be just working for live bars (which handles ticks in indicator.calculation method) but not for historical bars, so the ticks of a candle these are in the pins above/below open/close are ignored. So my idea was to check it within a cBot as backtesting to be able to check also history bars.

In visual mode it shows the correct result, also crosses which are only in the pins of a candle were recognized. Red marked example below shows that finally the price moved up from candle.low to candle.close and crosses the ema Up by that move. That is shown in the histogram at the bottom by a value above 0 (Downs would be below 0):

The same code run without visual mode, shows a wrong result, the example mentioned above as well a lot of other crosses were not recognized:

Below is the belonging code:

Indicator:

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.Intrinsics.X86;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo
{
    [Levels(0)]
    [Indicator(IsOverlay = false, AccessRights = AccessRights.None, TimeZone = TimeZones.UTC)]
    public class BSMACrossHist : Indicator
    {
        [Parameter("Moving Average Type", DefaultValue = MovingAverageType.Exponential)]
        public MovingAverageType MAType { get; set; }

        [Parameter("Periods", DefaultValue = 50)]
        public int Periods { get; set; }

        [Output("Cross", LineColor = "#FF898989", Thickness = 5, PlotType = PlotType.Histogram)]
        public IndicatorDataSeries IndicatorDataSeries_Cross { get; set; }

        private MovingAverage MA;
        
        private double LastTick_Close = 0;
        private double LastTick_MA = 0;

        protected override void Initialize()
        {
            this.MA = Indicators.MovingAverage(Bars.ClosePrices, Periods, MAType);
        }

        public override void Calculate(int CurrentIndex)
        {
            double MA_01 = this.MA.Result[CurrentIndex];
            string Message = string.Format("Server-Time: {0}, Index: {1}", Server.Time.ToString("dd.MM.yyyy HH:mm:ss.fff"), CurrentIndex.ToString());

            if (Bars.ClosePrices[CurrentIndex] > MA_01 && !(this.LastTick_Close > this.LastTick_MA))
            {
                this.IndicatorDataSeries_Cross[CurrentIndex] = 1;
                Print("Up: " + Message);
            }
            else if (Bars.ClosePrices[CurrentIndex] < MA_01 && !(this.LastTick_Close < this.LastTick_MA))
            {
                this.IndicatorDataSeries_Cross[CurrentIndex] = -1;
                Print("Down: " + Message);
            }

            this.LastTick_Close = Bars.ClosePrices[CurrentIndex];
            this.LastTick_MA = MA_01;
        }
    }
}

and the cBot:

using System;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    [Robot(AccessRights = AccessRights.None, AddIndicators = true)]
    public class BSTest : Robot
    {
        private BSMACrossHist BS_MACross1;
        private MovingAverage MA;

        protected override void OnStart()
        {
            this.MA = Indicators.MovingAverage(Bars.ClosePrices, 40, MovingAverageType.Exponential);
            this.BS_MACross1 = Indicators.GetIndicator<BSMACrossHist>(MovingAverageType.Exponential, 40);
        }

        protected override void OnTick()
        {
            if (!double.IsNaN(this.BS_MACross1.IndicatorDataSeries_Cross.LastValue))
            {
                string Message = string.Format("Server-Time: {0}, Up/Down: {1}", Server.Time.ToString("dd.MM.yyyy HH:mm:ss.fff"), 			this.BS_MACross1.IndicatorDataSeries_Cross.LastValue.ToString());
                Print(Message);
            }
        }

        protected override void OnStop()
        {
            // Handle cBot stop here
        }
    }
}

By the print messages in indicator.calculation method it is obvious, that all ticks are processed and cross values will be correctly set there, but these are not displayed on the chart (and maybe not processable in the cBot - that I could/did not check yet) 

I guess it's an chart update issue, chart in silent mode is not updated finally after all ticks were processed ?!

Or is there something wrong in my code, which would explain differences between visual and silent mode?

Thank you!

Best regards,

Bernhard

PS: I could verify whether cBot get's the correct values of the indicator, whether in visual or silent mode and I can confirm cBot get's it correct in both modes! So it could be only an chart update issue.

The log output of both modes is exactly the same, at the mentioned/red marked time above in screenshots:

19.06.2024 19:59:58.415 | Info | Server-Time: 19.06.2024 19:59:58.415, Up/Down: 1
19.06.2024 20:00:00.002 | Info | Server-Time: 19.06.2024 20:00:00.002, Up/Down: 1
19.06.2024 20:00:01.237 | Info | Server-Time: 19.06.2024 20:00:01.237, Up/Down: 1
19.06.2024 20:00:02.767 | Info | Server-Time: 19.06.2024 20:00:02.767, Up/Down: 1
19.06.2024 20:00:03.036 | Info | Server-Time: 19.06.2024 20:00:03.036, Up/Down: 1
19.06.2024 20:00:03.518 | Info | Server-Time: 19.06.2024 20:00:03.518, Up/Down: 1
19.06.2024 20:00:04.435 | Info | Server-Time: 19.06.2024 20:00:04.435, Up/Down: 1
19.06.2024 20:00:05.363 | Info | Server-Time: 19.06.2024 20:00:05.363, Up/Down: 1
19.06.2024 20:00:05.638 | Info | Server-Time: 19.06.2024 20:00:05.638, Up/Down: 1
19.06.2024 20:00:06.036 | Info | Server-Time: 19.06.2024 20:00:06.036, Up/Down: 1
19.06.2024 20:00:08.982 | Info | Server-Time: 19.06.2024 20:00:08.982, Up/Down: 1
19.06.2024 20:00:09.236 | Info | Server-Time: 19.06.2024 20:00:09.236, Up/Down: 1
19.06.2024 20:00:09.437 | Info | Down: Server-Time: 19.06.2024 20:00:09.437, Index: 1373
19.06.2024 20:00:09.437 | Info | Server-Time: 19.06.2024 20:00:09.437, Up/Down: -1
19.06.2024 20:00:10.365 | Info | Up: Server-Time: 19.06.2024 20:00:10.365, Index: 1373
19.06.2024 20:00:10.365 | Info | Server-Time: 19.06.2024 20:00:10.365, Up/Down: 1
19.06.2024 20:00:12.001 | Info | Down: Server-Time: 19.06.2024 20:00:12.001, Index: 1373
19.06.2024 20:00:12.001 | Info | Server-Time: 19.06.2024 20:00:12.001, Up/Down: -1
19.06.2024 20:00:13.035 | Info | Up: Server-Time: 19.06.2024 20:00:13.035, Index: 1373
19.06.2024 20:00:13.035 | Info | Server-Time: 19.06.2024 20:00:13.035, Up/Down: 1
19.06.2024 20:00:17.037 | Info | Down: Server-Time: 19.06.2024 20:00:17.037, Index: 1373
19.06.2024 20:00:17.037 | Info | Server-Time: 19.06.2024 20:00:17.037, Up/Down: -1
19.06.2024 20:00:17.269 | Info | Server-Time: 19.06.2024 20:00:17.269, Up/Down: -1
19.06.2024 20:00:30.234 | Info | Up: Server-Time: 19.06.2024 20:00:30.234, Index: 1373
19.06.2024 20:00:30.234 | Info | Server-Time: 19.06.2024 20:00:30.234, Up/Down: 1
19.06.2024 20:00:38.707 | Info | Server-Time: 19.06.2024 20:00:38.707, Up/Down: 1

So finally only the question, could you confirm it's a bug and when it will be resolved? :-)

 


@bernhardCM
Replies

PanagiotisCharalampous
21 Jun 2024, 05:35

Hi there,

The bug is in your code. The difference between visual and non visual is that in visual mode, the indicator is calculated on every tick, while in non visual mode, the indicator is calculated once at the end of the backtesting. So in visual mode, your condition will become true at some tick while in non visual mode, it will never become true, since the calculate method is only called once per bar, considering only the closed prices.

I would suggest you use High/Low values instead of Close values to resolve the problem.

Best regards, 

Panagiotis


@PanagiotisCharalampous

bernhardCM
21 Jun 2024, 06:48 ( Updated at: 21 Jun 2024, 06:49 )

thanks for your prompt reply.

hmmm, so for backtesting in non visual mode, the setting “tick-data” (instead of m1 data) will not be used, that was not clear to me and looks frankly spoken … wrong ;-) 

but now I know how it works. Thank you for clarification!

By the way, how about Optimization, there we can also select "tick-data accurate”. Are the indicators there also only calculated once per bar? Because there is no visual mode available.

Thank you.

 


@bernhardCM

PanagiotisCharalampous
21 Jun 2024, 10:34

RE: Custom indicator in cBot different results visual mode compared to silent mode

bernhardCM said: 

thanks for your prompt reply.

hmmm, so for backtesting in non visual mode, the setting “tick-data” (instead of m1 data) will not be used, that was not clear to me and looks frankly spoken … wrong ;-) 

but now I know how it works. Thank you for clarification!

By the way, how about Optimization, there we can also select "tick-data accurate”. Are the indicators there also only calculated once per bar? Because there is no visual mode available.

Thank you.

 

No that is not what I said. Indicators referenced in a strategy will use the source set in the backtesting settings. Indicators applied on the chart will be rendered at the moment they are applied, so all past bars will be considered historical


@PanagiotisCharalampous

bernhardCM
21 Jun 2024, 10:50

RE: RE: Custom indicator in cBot different results visual mode compared to silent mode

No that is not what I said. Indicators referenced in a strategy will use the source set in the backtesting settings. Indicators applied on the chart will be rendered at the moment they are applied, so all past bars will be considered historical

first of all, Panagiotis thanks for your great replies to actually all threads I found in this forum already, as well to this one.

Just to make it sure in my own (not native English speaking … poorer) words ;-)

  1. with “strategy” I guess you mean a cBot.
  2. backtesting settings & optimization settings (e.g. ticks instead of chart timeframe data) will be correct processed, in the backend of backtesting & optimization
  3. point 2. is also applicable for indicators on the chart shown on backtesting in visual mode
  4. all other indicators (chart in trade section or chart in backtesting in NON visual mode) will show historically only chart timeframe data, for “IsLastBar” it will be also consider ticks

That's what I extracted as summary and it's no open question, except I wrote something wrong.

Thanks for all and have a nice weekend!


@bernhardCM

PanagiotisCharalampous
26 Jun 2024, 06:44

RE: RE: RE: Custom indicator in cBot different results visual mode compared to silent mode

bernhardCM said: 

No that is not what I said. Indicators referenced in a strategy will use the source set in the backtesting settings. Indicators applied on the chart will be rendered at the moment they are applied, so all past bars will be considered historical

first of all, Panagiotis thanks for your great replies to actually all threads I found in this forum already, as well to this one.

Just to make it sure in my own (not native English speaking … poorer) words ;-)

  1. with “strategy” I guess you mean a cBot.
  2. backtesting settings & optimization settings (e.g. ticks instead of chart timeframe data) will be correct processed, in the backend of backtesting & optimization
  3. point 2. is also applicable for indicators on the chart shown on backtesting in visual mode
  4. all other indicators (chart in trade section or chart in backtesting in NON visual mode) will show historically only chart timeframe data, for “IsLastBar” it will be also consider ticks

That's what I extracted as summary and it's no open question, except I wrote something wrong.

Thanks for all and have a nice weekend!

Hi there,

Yes correct.


@PanagiotisCharalampous