Indicator returns different value when used in a BOT compared to onscreen

Created at 14 Nov 2019, 15:31
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!
LI

lisabeaney

Joined 08.10.2019

Indicator returns different value when used in a BOT compared to onscreen
14 Nov 2019, 15:31


Hi,

I have written this SuperTrend Indicator to display on screen as a continuous line :

// Author       : Lisa Beaney   
// Description  : SuperTrend line with option to display text for buy/sell mode
// Date         : 31st October 2019
using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class SuperTrendv1 : Indicator
    {
        [Parameter("Period", Group = "Indicator", DefaultValue = 13)]
        public int period { get; set; }

        [Parameter("Multiplier", Group = "Indicator", DefaultValue = 1.5)]
        public double multiplier { get; set; }

        [Parameter("Display Text", Group = "Display", DefaultValue = false)]
        public bool displayText { get; set; }

        [Parameter("Horiz. Alignment", Group = "Display", DefaultValue = HorizontalAlignment.Right)]
        public HorizontalAlignment HAlign { get; set; }

        [Output("SuperTrend", LineColor = "Yellow")]
        public IndicatorDataSeries superTrend { get; set; }

        private AverageTrueRange mATR;
        private IndicatorDataSeries up;
        private IndicatorDataSeries dn;

        private bool flag;
        private bool flagh;
        private int trend;
        private int prevtrend;



        protected override void Initialize()
        {
            // Initialize and create nested indicators
            mATR = Indicators.AverageTrueRange(period, MovingAverageType.Simple);
            up = CreateDataSeries();
            dn = CreateDataSeries();
            trend = 1;
            prevtrend = 1;

        }

        public override void Calculate(int index)
        {

            
                // Calculate value at specified index
                // Result[index] = ...
                double price = (MarketSeries.High[index] + MarketSeries.Low[index]) / 2;
                double moy = mATR.Result[index];
                double close = MarketSeries.Close[index];
                up[index] = price + multiplier * moy;
                dn[index] = price - multiplier * moy;


                prevtrend = trend;

                // Check if we need a flat section
                if (trend == 1 && dn[index] <= dn[index - 1])
                {
                    dn[index] = dn[index - 1];
                }
                if (trend == -1 && up[index] >= up[index - 1])
                {
                    up[index] = up[index - 1];
                }

                // Check what the current trend is
                if (close > up[index])
                {
                    trend = 1;
                }
                else
                {
                    if (close < dn[index])
                    {
                        trend = -1;
                    }
                }

                // Check if the trend has switch to short
                if (trend <= 0 && prevtrend >= 0)
                {
                    flag = true;
                }
                else
                {
                    flag = false;
                }

                if (trend >= 0 && prevtrend <= 0)
                {
                    flagh = true;
                }
                else
                {
                    flagh = false;
                }



                // Set the correct value depending on trend and display the line
                if (flag)
                {
                    up[index] = price + multiplier * moy;
                }
                if (flagh)
                {
                    dn[index] = price - multiplier * moy;
                }
                if (trend == 1)
                {
                    superTrend[index] = dn[index];
                }
                else
                {
                    superTrend[index] = up[index];
                }

                if (displayText)
                {
                    if (superTrend[index] < price)
                    {
                        Chart.DrawStaticText("1", " SuperTrend Buy mode", VerticalAlignment.Top, HAlign, Color.Green);
                    }
                    else
                    {
                        Chart.DrawStaticText("1", " SuperTrend Sell mode", VerticalAlignment.Top, HAlign, Color.Red);
                    }
                }
       

        }
    }
}

When I use it on a chart it all looks fine and behaves the way it should.

When I use it in a BOT it returns different values to those on screen. I've run the BOT in backtest mode for the 1st Nov 2019 and when I look at the log between 12:18 & 12:19 it detects a change in trend but the onscreen version doesn't.

This is the code for the BOT :

// Description  : FTSE M1 strategy
// Author       : Lisa Beaney
// Date         : 23rd October 2019
//
// 11th November 2019 - Added option to hide the display of the text
// 13th November 2019 - Added the option to send Telegram messages
// 14th November 2019 - Stripped right back for bug fixing - TEST VERSION ONLY NOT FOR FURTHER DEVELOPMENT



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



namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class FTSEM1StrategyTEST : Robot
    {
        [Parameter("Quantity (Lots)", Group = "Trading", DefaultValue = 1, MinValue = 0.01, Step = 0.01)]
        public double PQuantity { get; set; }

        [Parameter("Stop (pips)", Group = "Stop & Limit", DefaultValue = 100, MinValue = 5, Step = 1)]
        public int PBuyStop { get; set; }

        [Parameter("Limit (pips)", Group = "Stop & Limit", DefaultValue = 100, MinValue = 5, Step = 1)]
        public int PBuyLimit { get; set; }

        // Definitions needed for indicators

        private SuperTrendv1 st;

        private double close;
        private int Trend, PrevTrend;
        private double STValue;
        private const string label = "FTSE M1 BETA";


        protected override void OnStart()
        {
            st = Indicators.GetIndicator<SuperTrendv1>(13, 1.5, false, HorizontalAlignment.Right);
        }

        protected override void OnBar()
        {
            // This code will execute on the close of one candle and the open of the next.
            // Count the number of open trades
            var totalPositions = Positions.FindAll(label).Length;
            close = MarketSeries.Close.LastValue;
            STValue = (Math.Round(st.superTrend.LastValue, 4));

            // Check for a change in direction of superTrend
            if (STValue > close)
            {
                Trend = -1;
                Print("SHORT Trend STValue - {0} \t Close - {1} ", STValue, close);
            }


            if (STValue < close)
            {
                Trend = 1;
                Print("LONG Trend STValue - {0} \t Close - {1} ", STValue, close);
            }

            //Print("Total Positions {0}", totalPositions);
            if (totalPositions == 0 && Trend == 1 && PrevTrend == -1)
            {

                // Go long here
                Print("Long trade taken \t superTrend - {0} \t Close - {1} ", STValue, close);
                ExecuteMarketOrder(TradeType.Buy, SymbolName, VolumeInUnits, label, PBuyStop, PBuyLimit);

            }
            if (totalPositions == 0 && Trend == -1 && PrevTrend == 1)
            {

                // Go Short here
                Print("Short trade taken \t superTrend - {0} \t Close - {1} ", STValue, close);

                ExecuteMarketOrder(TradeType.Sell, SymbolName, VolumeInUnits, label, PBuyStop, PBuyLimit);

            }

            PrevTrend = Trend;

        }
        protected override void OnStop()
        {

        }
        private double VolumeInUnits
        {
            get { return Symbol.QuantityToVolumeInUnits(PQuantity); }
        }


    }
}

I've stripped out just about everything else it was doing so I coould focus on the SuperTrend. I know I'm most probably doing something daft but this seems to be one of those times that I just can't see for looking !

I should add that this is running on UK100 1 minute chart


@lisabeaney
Replies

PanagiotisCharalampous
14 Nov 2019, 15:34

Hi Lisa,

You can read about the reasons this happens here.

Best Regards,

Panagiotis


@PanagiotisCharalampous

lisabeaney
14 Nov 2019, 16:19

Thank you ! I missed that when I was searching the forum


@lisabeaney

lisabeaney
18 Nov 2019, 12:30 ( Updated at: 21 Dec 2023, 09:21 )

RE:

Panagiotis Charalampous said:

Hi Lisa,

You can read about the reasons this happens here.

Best Regards,

Panagiotis

Hi,

I've run this on a demo account and it does the same thing...... Any ideas ??


@lisabeaney