Referencing the Indicator for different Timeframe

Created at 06 Oct 2021, 05:44
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!
VE

velu130486

Joined 08.11.2019 Blocked

Referencing the Indicator for different Timeframe
06 Oct 2021, 05:44


Hello All,

I got the below Indicator from this forum (thanks for the developer) and this is very good compared to other moving averages, so I am using this Indicator in my Cbot via references.

vma = Indicators.GetIndicator<VariableMovingAverage>(6);

I request your support how to use this indicator in Cbot to get the moving average value based on another timeframe.

For ex I am using the bot in 15 mins TF and the bot able to get the M15 Moving average value as per above, how to the H1 or H4 moving average value in the same bot, because I want to use it as filter for opening orders.

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 VariableMovingAverage : Indicator
    {
        [Parameter(DefaultValue = 6)]
        public int Period { get; set; }
 
        [Output("Main", LineColor = "Cyan")]
        public IndicatorDataSeries Result { get; set; }
 
        double K = 1;
        IndicatorDataSeries pdmS, mdmS, pdiS, mdiS, iS, tempResult;
        protected override void Initialize()
        {
            K /= Period;
            pdmS = CreateDataSeries();
            mdmS = CreateDataSeries();
            pdiS = CreateDataSeries();
            mdiS = CreateDataSeries();
            iS = CreateDataSeries();
            tempResult = CreateDataSeries();
        }

        public override void Calculate(int index)
        {
            double pdm = Math.Max(Bars[index].Close - Bars[index - 1].Close, 0), mdm = Math.Max(Bars[index - 1].Close - Bars[index].Close, 0);
            pdmS[index] = ((1 - K) * (double.IsNaN(pdmS[index - 1]) ? 0 : pdmS[index - 1]) + K * pdm);
            mdmS[index] = ((1 - K) * (double.IsNaN(mdmS[index - 1]) ? 0 : mdmS[index - 1]) + K * mdm);
            double pdi = pdmS[index] / (pdmS[index] + mdmS[index]);
            double mdi = mdmS[index] / (pdmS[index] + mdmS[index]);
            pdiS[index] = ((1 - K) * (double.IsNaN(pdiS[index - 1]) ? 0 : pdiS[index - 1]) + K * pdi);
            mdiS[index] = ((1 - K) * (double.IsNaN(mdiS[index - 1]) ? 0 : mdiS[index - 1]) + K * mdi);
            iS[index] = ((1 - K) * (double.IsNaN(iS[index - 1]) ? 0 : iS[index - 1]) + K * Math.Abs(pdiS[index] - mdiS[index]) / (pdiS[index] + mdiS[index]));
            double hhv = iS.Maximum(Period);
            double llv = iS.Minimum(Period);
            tempResult[index] = (1 - K * (iS[index] - llv) / (hhv - llv)) * (double.IsNaN(tempResult[index - 1]) ? 0 : tempResult[index - 1]) + Bars[index].Close * K * (iS[index] - llv) / (hhv - llv);
            if (index > Period * 10)
                Result[index] = tempResult[index];
        }
    }
}

Thanks and Regards

R. Vadivelan


Replies

amusleh
06 Oct 2021, 09:16

Hi,

The indicator doesn't support multi time frame, it only has one parameter which is Period.

To make it multi time frame it should have a data series source parameter so you would be able to pass another time price series to it and indicator will use that instead of current chart price series.

Try this:

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

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

        [Parameter("TimeFrame")]
        public TimeFrame BaseTimeFrame { get; set; }

        [Output("Main", LineColor = "Cyan")]
        public IndicatorDataSeries Result { get; set; }

        private double K = 1;
        private IndicatorDataSeries pdmS, mdmS, pdiS, mdiS, iS, tempResult;
        private Bars _baseBars;

        protected override void Initialize()
        {
            _baseBars = MarketData.GetBars(BaseTimeFrame);

            K /= Period;
            pdmS = CreateDataSeries();
            mdmS = CreateDataSeries();
            pdiS = CreateDataSeries();
            mdiS = CreateDataSeries();
            iS = CreateDataSeries();
            tempResult = CreateDataSeries();
        }

        public override void Calculate(int index)
        {
            var baseIndex = _baseBars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);

            if (baseIndex < Period) return;

            double pdm = Math.Max(_baseBars[baseIndex].Close - _baseBars[baseIndex - 1].Close, 0), mdm = Math.Max(_baseBars[baseIndex - 1].Close - _baseBars[baseIndex].Close, 0);
            pdmS[index] = ((1 - K) * (double.IsNaN(pdmS[index - 1]) ? 0 : pdmS[index - 1]) + K * pdm);
            mdmS[index] = ((1 - K) * (double.IsNaN(mdmS[index - 1]) ? 0 : mdmS[index - 1]) + K * mdm);
            double pdi = pdmS[index] / (pdmS[index] + mdmS[index]);
            double mdi = mdmS[index] / (pdmS[index] + mdmS[index]);
            pdiS[index] = ((1 - K) * (double.IsNaN(pdiS[index - 1]) ? 0 : pdiS[index - 1]) + K * pdi);
            mdiS[index] = ((1 - K) * (double.IsNaN(mdiS[index - 1]) ? 0 : mdiS[index - 1]) + K * mdi);
            iS[index] = ((1 - K) * (double.IsNaN(iS[index - 1]) ? 0 : iS[index - 1]) + K * Math.Abs(pdiS[index] - mdiS[index]) / (pdiS[index] + mdiS[index]));
            double hhv = iS.Maximum(Period);
            double llv = iS.Minimum(Period);
            tempResult[index] = (1 - K * (iS[index] - llv) / (hhv - llv)) * (double.IsNaN(tempResult[index - 1]) ? 0 : tempResult[index - 1]) + _baseBars[baseIndex].Close * K * (iS[index] - llv) / (hhv - llv);
            if (index > Period * 10)
                Result[index] = tempResult[index];
        }
    }
}

I have added a new TimeFrame parameter on it, you can use it to pass an specific time frame to indicator so it will use that time frame price data instead of current time frame.

When using multiple time frames data the other time frame might not load all the historical data that your current chart time frame loaded, so you have to use LoadMoreHistory method of Bars to load more history based on your chart current amount of loaded data.

 


@amusleh

velu130486
06 Oct 2021, 11:00 ( Updated at: 21 Dec 2023, 09:22 )

RE:

Thank you Ahmad for your quick support. Actually I dont want to have the historical data, I would like to know the VMA value at the same time in both M15 and H4 timeframe to filter the signals.

So I used the same indicator as below, please advice me if it is wrong.

vma = Indicators.GetIndicator<VariableMovingAverage>(6,TimeFrame.Hour4);

However when I do the backtest and print the values I found there is a difference between the printed values and actual chart values as attached.

And the values are not matching with live chart for the same time. Just want to know the reason for my better understanding or to know anything I did wrong.

Anyhow thanks again for your support, very much appreciated.

Thanks and Regards

R. Vadivelan

amusleh said:

Hi,

The indicator doesn't support multi time frame, it only has one parameter which is Period.

To make it multi time frame it should have a data series source parameter so you would be able to pass another time price series to it and indicator will use that instead of current chart price series.

Try this:

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

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

        [Parameter("TimeFrame")]
        public TimeFrame BaseTimeFrame { get; set; }

        [Output("Main", LineColor = "Cyan")]
        public IndicatorDataSeries Result { get; set; }

        private double K = 1;
        private IndicatorDataSeries pdmS, mdmS, pdiS, mdiS, iS, tempResult;
        private Bars _baseBars;

        protected override void Initialize()
        {
            _baseBars = MarketData.GetBars(BaseTimeFrame);

            K /= Period;
            pdmS = CreateDataSeries();
            mdmS = CreateDataSeries();
            pdiS = CreateDataSeries();
            mdiS = CreateDataSeries();
            iS = CreateDataSeries();
            tempResult = CreateDataSeries();
        }

        public override void Calculate(int index)
        {
            var baseIndex = _baseBars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);

            if (baseIndex < Period) return;

            double pdm = Math.Max(_baseBars[baseIndex].Close - _baseBars[baseIndex - 1].Close, 0), mdm = Math.Max(_baseBars[baseIndex - 1].Close - _baseBars[baseIndex].Close, 0);
            pdmS[index] = ((1 - K) * (double.IsNaN(pdmS[index - 1]) ? 0 : pdmS[index - 1]) + K * pdm);
            mdmS[index] = ((1 - K) * (double.IsNaN(mdmS[index - 1]) ? 0 : mdmS[index - 1]) + K * mdm);
            double pdi = pdmS[index] / (pdmS[index] + mdmS[index]);
            double mdi = mdmS[index] / (pdmS[index] + mdmS[index]);
            pdiS[index] = ((1 - K) * (double.IsNaN(pdiS[index - 1]) ? 0 : pdiS[index - 1]) + K * pdi);
            mdiS[index] = ((1 - K) * (double.IsNaN(mdiS[index - 1]) ? 0 : mdiS[index - 1]) + K * mdi);
            iS[index] = ((1 - K) * (double.IsNaN(iS[index - 1]) ? 0 : iS[index - 1]) + K * Math.Abs(pdiS[index] - mdiS[index]) / (pdiS[index] + mdiS[index]));
            double hhv = iS.Maximum(Period);
            double llv = iS.Minimum(Period);
            tempResult[index] = (1 - K * (iS[index] - llv) / (hhv - llv)) * (double.IsNaN(tempResult[index - 1]) ? 0 : tempResult[index - 1]) + _baseBars[baseIndex].Close * K * (iS[index] - llv) / (hhv - llv);
            if (index > Period * 10)
                Result[index] = tempResult[index];
        }
    }
}

I have added a new TimeFrame parameter on it, you can use it to pass an specific time frame to indicator so it will use that time frame price data instead of current time frame.

When using multiple time frames data the other time frame might not load all the historical data that your current chart time frame loaded, so you have to use LoadMoreHistory method of Bars to load more history based on your chart current amount of loaded data.

 

 


amusleh
06 Oct 2021, 12:40

Hi,

If you call LoadMoreHistory method it will load more bars data for that time frame, you can call it if your indicator needs to.

Regarding values not matching issue, it can be caused by difference in data that your cBot process and fed to indicator for calculation.

You can also check the indicator calculation code, the indicator itself can be the reason too.

The code I posted was just a guide for you to make the indicator support multiple time frames, not something read for use on your code.


@amusleh