MULTISYMBOL INDICATOR NOT SHOWING PROPER RESULTS ON SCREEN (CHANGING UPON CHART SYMBOL)

Created at 11 Jun 2020, 11:45
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!
OR

orsica

Joined 05.12.2019

MULTISYMBOL INDICATOR NOT SHOWING PROPER RESULTS ON SCREEN (CHANGING UPON CHART SYMBOL)
11 Jun 2020, 11:45


I'm trying to show in the indicator box under the chart a custom indicator named TSI but I want to display this indicator for various symbols (not necessarily including the symbol of the chart) together in the box. I'm finding a strange behaviour changing display and values when I change the chart symbol. Here below the list of the indicator, the custom indicator and some screeshots:

INDICATOR (NOT WORKING PROPERLY):

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

namespace cAlgo.Indicators
{

    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class TSI_ENSEMBLE : Indicator
    {

        [Parameter("Short Period", Group = "TSI", DefaultValue = 13, MinValue = 1)]
        public int ShortPeriod { get; set; }

        [Parameter("Long Period", Group = "TSI", DefaultValue = 25, MinValue = 1)]
        public int LongPeriod { get; set; }

        [Parameter("MA Type", Group = "TSI", DefaultValue = MovingAverageType.Exponential)]
        public MovingAverageType MaType { get; set; }

        [Output("EURUSDTSI", Thickness = 1, LineColor = "Red")]
        public IndicatorDataSeries eurUsdTsi { get; set; }

        [Output("EURGBPTSI", Thickness = 1, LineColor = "Orange")]
        public IndicatorDataSeries eurGbpTsi { get; set; }

        private TSI eurUsdtsi_ind;
        private TSI eurGbptsi_ind;

        private IndicatorDataSeries eurUsdTSI;
        private IndicatorDataSeries eurGbpTSI;


        protected override void Initialize()
        {

            eurUsdTSI = CreateDataSeries();
            eurGbpTSI = CreateDataSeries();

            var eurUsd_series = MarketData.GetBars(TimeFrame.Hour, "EURUSD");
            var eurGbp_series = MarketData.GetBars(TimeFrame.Hour, "EURGBP");


            eurUsdtsi_ind = Indicators.GetIndicator<TSI>(eurUsd_series.ClosePrices, ShortPeriod, LongPeriod, MaType);
            eurGbptsi_ind = Indicators.GetIndicator<TSI>(eurGbp_series.ClosePrices, ShortPeriod, LongPeriod, MaType);


        }

        public override void Calculate(int index)
        {

            if (index < 1)
            {
                eurUsdTsi[index] = 0;
                eurGbpTsi[index] = 0;
                return;
            }

            eurUsdTSI[index] = eurUsdtsi_ind.Tsi[index];
            eurGbpTSI[index] = eurGbptsi_ind.Tsi[index];

            eurUsdTsi[index] = eurUsdTSI[index];
            eurGbpTsi[index] = eurGbpTSI[index];

        }

    }
}

 

CUSTOM INDICATOR (WORKING PROPERLY):

using System;
using cAlgo.API;
using cAlgo.API.Indicators;

namespace cAlgo.Indicators
{
    [Levels(-25, 0, 25)]
    [Indicator(AccessRights = AccessRights.None)]
    public class TSI : Indicator
    {
        private MovingAverage _divisor;
        private MovingAverage _longDivisor;
        private MovingAverage _dividend;
        private MovingAverage _longDividend;

        private IndicatorDataSeries _dataSeries;
        private IndicatorDataSeries _dataSeriesAbs;
        private IndicatorDataSeries _tsiSeries;

        [Parameter()]
        public DataSeries Source { get; set; }

        [Parameter("ShortPeriod", DefaultValue = 13, MinValue = 1)]
        public int ShortPeriod { get; set; }

        [Parameter("LongPeriod", DefaultValue = 25, MinValue = 1)]
        public int LongPeriod { get; set; }

        [Parameter("MA Type", DefaultValue = MovingAverageType.Exponential, MinValue = MovingAverageType.Simple, MaxValue = MovingAverageType.Exponential)]
        public MovingAverageType MaType { get; set; }


        [Output("Tsi", LineColor = "Red")]
        public IndicatorDataSeries Tsi { get; set; }


        protected override void Initialize()
        {

            _dataSeries = CreateDataSeries();
            _dataSeriesAbs = CreateDataSeries();
            _tsiSeries = CreateDataSeries();

            _longDividend = Indicators.MovingAverage(_dataSeries, LongPeriod, MaType);
            _dividend = Indicators.MovingAverage(_longDividend.Result, ShortPeriod, MaType);

            _longDivisor = Indicators.MovingAverage(_dataSeriesAbs, LongPeriod, MaType);
            _divisor = Indicators.MovingAverage(_longDivisor.Result, ShortPeriod, MaType);


        }

        public override void Calculate(int index)
        {
            if (index < 1)
            {
                Tsi[index] = 0;
                return;
            }

            _dataSeries[index] = Bars.ClosePrices[index] - Bars.ClosePrices[index - 1];
            _dataSeriesAbs[index] = Math.Abs(Bars.ClosePrices[index] - Bars.ClosePrices[index - 1]);

            double tsiDivisor = _divisor.Result[index];
            double tsiDividend = _dividend.Result[index];

            if (Math.Abs(tsiDivisor) < double.Epsilon)
                _tsiSeries[index] = 0;
            else
                _tsiSeries[index] = 100.0 * tsiDividend / tsiDivisor;

            Tsi[index] = _tsiSeries[index];

        }

    }
}

SCREENSHOT WITH EURUSD ON CHART

SCREENSHOT WITH AUDCAD ON CHART


@orsica
Replies

PanagiotisCharalampous
11 Jun 2020, 11:59

Hi orsica,

The problem is that you do not use the correct indices. See below how to code this properly

        Bars eurUsd_series;
        Bars eurGbp_series;

        protected override void Initialize()
        {

            eurUsdTSI = CreateDataSeries();
            eurGbpTSI = CreateDataSeries();

            eurUsd_series = MarketData.GetBars(TimeFrame.Hour, "EURUSD");
            eurGbp_series = MarketData.GetBars(TimeFrame.Hour, "EURGBP");


            eurUsdtsi_ind = Indicators.GetIndicator<TSI>(eurUsd_series.ClosePrices, ShortPeriod, LongPeriod, MaType);
            eurGbptsi_ind = Indicators.GetIndicator<TSI>(eurGbp_series.ClosePrices, ShortPeriod, LongPeriod, MaType);


        }

        public override void Calculate(int index)
        {

            if (index < 1)
            {
                eurUsdTsi[index] = 0;
                eurGbpTsi[index] = 0;
                return;
            }

            eurUsdTSI[index] = eurUsdtsi_ind.Tsi[eurUsd_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])];
            eurGbpTSI[index] = eurGbptsi_ind.Tsi[eurGbp_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])];

            eurUsdTsi[index] = eurUsdTSI[index];
            eurGbpTsi[index] = eurGbpTSI[index];
        }

Best Regards,

Panagiotis 

Join us on Telegram

 


@PanagiotisCharalampous

orsica
10 Sep 2020, 13:50

RE:

Dear Panagiotis,

still have problems with indicator showing different results depending on symbol timeframe, could you check please (maybe I didn't understand well the index adaptation inside calculate):

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

namespace cAlgo.Indicators
{

    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class TSI_ORIGINAL2 : Indicator
    {

        [Parameter("Long Period", Group = "TSI", DefaultValue = 25, MinValue = 1)]
        public int LongPeriod { get; set; }

        [Parameter("Short Period", Group = "TSI", DefaultValue = 15, MinValue = 1)]
        public int ShortPeriod { get; set; }

        [Parameter("Max-MIn Period", Group = "TSI", DefaultValue = 1000, MinValue = 1)]
        public int MaxMinPeriod { get; set; }

        [Parameter("Timeframe", Group = "TSI", DefaultValue = "Hour")]
        public TimeFrame timeFrame { get; set; }

        [Parameter("MA Type", Group = "TSI", DefaultValue = MovingAverageType.Exponential)]
        public MovingAverageType MaType { get; set; }

        [Output("EUR", Thickness = 1, LineColor = "Green")]
        public IndicatorDataSeries eurIdxOrig { get; set; }


        //******* DEFINISCO LE MEDIE MOBILI PER L'EURO*********
        private MovingAverage eur_Ema1;
        private MovingAverage eur_Ema2;
        private MovingAverage eur_Abs_Ema1;
        private MovingAverage eur_Abs_Ema2;
        //*****************************************************


        //******* DEFINISCO LE SERIE TIPO INDICATORE MOMENTUM VARI CAMBI CON L'EURO*********
        private IndicatorDataSeries mtm_eurUsd_series;
        private IndicatorDataSeries mtm_eurGbp_series;
        private IndicatorDataSeries mtm_eurJpy_series;
        private IndicatorDataSeries mtm_eurCad_series;
        private IndicatorDataSeries mtm_eurChf_series;
        private IndicatorDataSeries mtm_eurNzd_series;
        private IndicatorDataSeries mtm_eurAud_series;
        //**********************************************************************************

        //******* DEFINISCO LE SERIE TIPO INDICATORE MOMENTUM SINTETICO PER L'EURO**********
        private IndicatorDataSeries mtm_eur_series;
        private IndicatorDataSeries abs_mtm_eur_series;
        //**********************************************************************************

        //******* DEFINISCO LE SERIE DELLE BARRE DEI CAMBI CON L'EURO*********
        Bars eurUsd_series;
        Bars eurGbp_series;
        Bars eurJpy_series;
        Bars eurCad_series;
        Bars eurChf_series;
        Bars eurNzd_series;
        Bars eurAud_series;
        //********************************************************************

        //******* INIZIALIZZO LE VARIABILI PER LE LABEL DI PERCENTUALE A DESTRA (MAX,MIN,ACTUAL) PER L'EURO********
        double maxeurIdxOrig = 0;
        double mineurIdxOrig = 0;
        double labeurIdxOrig = 0;
        //*********************************************************************************************************



        protected override void Initialize()
        {
            //******* INIZIALIZZO LE SERIE DEI MOMENTUM DEI VARI CAMBI CON L'EURO*********
            mtm_eurUsd_series = CreateDataSeries();
            mtm_eurGbp_series = CreateDataSeries();
            mtm_eurJpy_series = CreateDataSeries();
            mtm_eurCad_series = CreateDataSeries();
            mtm_eurChf_series = CreateDataSeries();
            mtm_eurNzd_series = CreateDataSeries();
            mtm_eurAud_series = CreateDataSeries();
            //****************************************************************************

            //******* INIZIALIZZO LE SERIE DEL MOMENTUM SINTETICO PER L'EURO**********
            mtm_eur_series = CreateDataSeries();
            abs_mtm_eur_series = CreateDataSeries();
            //************************************************************************

            //******* CARICO I DATI DELLE SERIE DELLE BARRE DEI CAMBI CON L'EURO ***************
            eurUsd_series = MarketData.GetBars(timeFrame, "EURUSD");
            eurGbp_series = MarketData.GetBars(timeFrame, "EURGBP");
            eurJpy_series = MarketData.GetBars(timeFrame, "EURJPY");
            eurCad_series = MarketData.GetBars(timeFrame, "EURCAD");
            eurChf_series = MarketData.GetBars(timeFrame, "EURCHF");
            eurNzd_series = MarketData.GetBars(timeFrame, "EURNZD");
            eurAud_series = MarketData.GetBars(timeFrame, "EURAUD");
            //**********************************************************************************

            //******** INIZIALIZZO LE MEDIE MOBILI PER IL CALCOLO DEL TSI PER L'EURO *************************
            eur_Ema1 = Indicators.MovingAverage(mtm_eur_series, LongPeriod, MaType);
            eur_Ema2 = Indicators.MovingAverage(eur_Ema1.Result, ShortPeriod, MaType);
            eur_Abs_Ema1 = Indicators.MovingAverage(abs_mtm_eur_series, LongPeriod, MaType);
            eur_Abs_Ema2 = Indicators.MovingAverage(eur_Abs_Ema1.Result, ShortPeriod, MaType);
            //*************************************************************************************


        }

        public override void Calculate(int index)
        {
            //******** AZZERO IL VALORE DELL'INDICE SINTETICO DELL'EURO AL PRIMO FIX UTILE ***************
            if (index < 1)
            {
                eurIdxOrig[index] = 0;

                return;
            }
            //********************************************************************************************



            //******** POPOLO LE SERIE DEI MOMENTUM DEI VARI CAMBI CON L'EURO ****************************
            mtm_eurUsd_series[index] = (eurUsd_series.ClosePrices[eurUsd_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])] - eurUsd_series.OpenPrices[eurUsd_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])]) / (eurUsd_series.OpenPrices[eurUsd_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])]);
            mtm_eurGbp_series[index] = (eurGbp_series.ClosePrices[eurGbp_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])] - eurGbp_series.OpenPrices[eurGbp_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])]) / (eurGbp_series.OpenPrices[eurGbp_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])]);
            mtm_eurJpy_series[index] = (eurJpy_series.ClosePrices[eurJpy_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])] - eurJpy_series.OpenPrices[eurJpy_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])]) / (eurJpy_series.OpenPrices[eurJpy_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])]);
            mtm_eurCad_series[index] = (eurCad_series.ClosePrices[eurCad_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])] - eurCad_series.OpenPrices[eurCad_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])]) / (eurCad_series.OpenPrices[eurCad_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])]);
            mtm_eurChf_series[index] = (eurChf_series.ClosePrices[eurChf_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])] - eurChf_series.OpenPrices[eurChf_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])]) / (eurChf_series.OpenPrices[eurChf_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])]);
            mtm_eurNzd_series[index] = (eurNzd_series.ClosePrices[eurNzd_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])] - eurNzd_series.OpenPrices[eurNzd_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])]) / (eurNzd_series.OpenPrices[eurNzd_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])]);
            mtm_eurAud_series[index] = (eurAud_series.ClosePrices[eurAud_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])] - eurAud_series.OpenPrices[eurAud_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])]) / (eurAud_series.OpenPrices[eurAud_series.OpenTimes.GetIndexByTime(Bars.OpenTimes[index])]);
            //********************************************************************************************


            //******** POPOLO LA SERIE DEL MOMENTUM SINTESI DEI VARI MOMENTUM PER L'EURO **************************************************************************************************************************************
            mtm_eur_series[index] = mtm_eurUsd_series[index] + mtm_eurGbp_series[index] + mtm_eurJpy_series[index] + mtm_eurCad_series[index] + mtm_eurChf_series[index] + mtm_eurNzd_series[index] + mtm_eurAud_series[index];
            abs_mtm_eur_series[index] = Math.Abs(mtm_eur_series[index]);
            //*****************************************************************************************************************************************************************************************************************


            //******** POPOLO LA SERIE DELL'INDICE SINTETICO DELL'EURO *******************************
            double eur_tsiDivisor = eur_Abs_Ema2.Result[index];
            double eur_tsiDividend = eur_Ema2.Result[index];

            if (Math.Abs(eur_tsiDivisor) < double.Epsilon)
            {
                eurIdxOrig[index] = 0;
            }
            else
            {
                eurIdxOrig[index] = 100.0 * eur_tsiDividend / eur_tsiDivisor;
            }
            //*****************************************************************************************


            //******** CERCO NELLA SERIE DELL'INDICE SINTETICO DELL'EURO IL MINIMO E IL MASSIMO NEI MAXMINPERIOD PERIODI ******
            maxeurIdxOrig = Functions.Maximum(eurIdxOrig, MaxMinPeriod);
            mineurIdxOrig = Functions.Minimum(eurIdxOrig, MaxMinPeriod);
            //*****************************************************************************************************************

            //******** CALCOLO LA PERCENTUALE ATTUALE RISPETTO AL MINIMO O AL MASSIMO PRECEDENTI ******************************
            if (eurIdxOrig[index] >= 0)
            {
                labeurIdxOrig = +(eurIdxOrig[index] * 100 / maxeurIdxOrig);
            }
            else
            {
                labeurIdxOrig = -(eurIdxOrig[index] * 100 / mineurIdxOrig);
            }
            //*****************************************************************************************************************


            //******** STAMPO MASSIMO,ATTUALE,MINIMO E PERCENTUALE ATTUALE ************************************************************************************************
            string eurIdxLabOrig = "\n" + "EUR : " + Convert.ToString(Math.Round(eurIdxOrig[index], 2)) + " ( " + Convert.ToString(Math.Round(labeurIdxOrig, 2)) + " % ) ";
            var text1 = IndicatorArea.DrawStaticText("eurIdx", eurIdxLabOrig, VerticalAlignment.Top, HorizontalAlignment.Right, Color.Green);
            //*************************************************************************************************************************************************************


        }

    }
}


@orsica

PanagiotisCharalampous
10 Sep 2020, 15:27 ( Updated at: 21 Dec 2023, 09:22 )

Hi orsica,

The problem is with your averages

            double eur_tsiDivisor = eur_Abs_Ema2.Result[index];
            double eur_tsiDividend = eur_Ema2.Result[index];

A 25 period average on h1 is not the same with a 25 period average on m30. If you cut the timeframe into half, then you need to double your averaging periods so that the averaged period covers the same timespan. See below

But even in this case, you should not expect the results to be identical as a lower timeframe has more data, thus a better "analysis".

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous