Multi-timeframe robots/indicators

Created at 30 Aug 2013, 12:37
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!
cAlgo_Development's avatar

cAlgo_Development

Joined 20.02.2013

Multi-timeframe robots/indicators
30 Aug 2013, 12:37


We added new functionality to cAlgo - the ability for robots and indicators to retrieve OHLCV data for multiple timeframes. This can be done using the MarketData.GetSeries method:

MarketSeries m5series = MarketData.GetSeries(TimeFrame.Minute5);

We recommend to call the GetSeries method in the Robot.OnStart() or the Indicator.Initialize() methods.

When the series for a specified timeframe is received, you can access the series values or build an indicator based on that series:

private MarketSeries m10;
private MovingAverage ma;

protected override void OnStart()
{
    m10 = MarketData.GetSeries(TimeFrame.Minute10);
    ma = Indicators.SimpleMovingAverage(m10.High, 14);
}

The new version of our Demo cTrader and cAlgo is released and can be downloaded from www.spotware.com

Update: Backtesting of Multi-timeframe robots is supported now.


@cAlgo_Development
Replies

cAlgo_Development
30 Aug 2013, 12:53 ( Updated at: 21 Dec 2023, 09:20 )

TimeFrame parameters

Another feature that has been introduced, is parameters of TimeFrame type that can be used in multi-timeframe robots and indicators:

 

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC)]
    public class MultiTimeFrameBot : Robot
    {
        [Parameter("Another Timeframe", DefaultValue = "Minute10")]
        public TimeFrame AnotherTimeFrame { get; set; }

        protected override void OnStart()
        {
            var anotherSeries = MarketData.GetSeries(AnotherTimeFrame);

            Print("My TimeFrame: {0}, Last high: {1}, Last Low: {2}", TimeFrame, MarketSeries.High.LastValue, MarketSeries.Low.LastValue);
            Print("Another TimeFrame: {0}, Last high: {1}, Last Low: {2}", AnotherTimeFrame, anotherSeries.High.LastValue, anotherSeries.Low.LastValue);
        }
    }
}

As a result we have a robot like this:



@cAlgo_Development

cAlgo_Development
30 Aug 2013, 12:56

Indicator example: Multi-timeframe moving average

In this example, we output moving averages with the same period for different timeframes on a single chart:



Source code:

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

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC)]
    public class MultiTF_MA : Indicator
    {
        [Parameter(DefaultValue = 50)]
        public int Period { get; set; }

        [Output("MA", Color = Colors.Yellow)]
        public IndicatorDataSeries MA { get; set; }

        [Output("MA5", Color = Colors.Orange)]
        public IndicatorDataSeries MA5 { get; set; }

        [Output("MA10", Color = Colors.Red)]
        public IndicatorDataSeries MA10 { get; set; }

        private MarketSeries series5;
        private MarketSeries series10;

        private MovingAverage ma;
        private MovingAverage ma5;
        private MovingAverage ma10;

        protected override void Initialize()
        {
            series5 = MarketData.GetSeries(TimeFrame.Minute5);
            series10 = MarketData.GetSeries(TimeFrame.Minute10);

            ma = Indicators.MovingAverage(MarketSeries.Close, Period, MovingAverageType.Triangular);
            ma5 = Indicators.MovingAverage(series5.Close, Period, MovingAverageType.Triangular);
            ma10 = Indicators.MovingAverage(series10.Close, Period, MovingAverageType.Triangular);
        }

        public override void Calculate(int index)
        {
            MA[index] = ma.Result[index];

            var index5 = GetIndexByDate(series5, MarketSeries.OpenTime[index]);
            if (index5 != -1)
                MA5[index] = ma5.Result[index5];

            var index10 = GetIndexByDate(series10, MarketSeries.OpenTime[index]);
            if (index10 != -1)
                MA10[index] = ma10.Result[index10];
        }


        private int GetIndexByDate(MarketSeries series, DateTime time)
        {
            for (int i = series.Close.Count - 1; i > 0; i--)
            {
                if (time == series.OpenTime[i])
                    return i;
            }
            return -1;
        }
    }
}

 


@cAlgo_Development

cAlgo_Development
30 Aug 2013, 14:02

Multi-timeframe robot

This is the RSI robot. It uses a daily Average True Range value as a filter, i.e. it does not trade if the ATR value is greater than the specified parameter value:

 

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC)]
    public class SampleRSIRobot : Robot
    {
        [Parameter("Max ATR Value", DefaultValue = 0.01)]
        public double MaxAtrValue { get; set; }

        private RelativeStrengthIndex rsi;
        private AverageTrueRange atr;

        protected override void OnStart()
        {
            rsi = Indicators.RelativeStrengthIndex(MarketSeries.Close, 14);

            var dailySeries = MarketData.GetSeries(TimeFrame.Daily);
            atr = Indicators.AverageTrueRange(dailySeries, 20, MovingAverageType.Simple);
        }

        protected override void OnTick()
        {
            if (Trade.IsExecuting)
                return;

            // Do nothing if daily ATR value > Max allowed value
            if (atr.Result.LastValue > MaxAtrValue)
                return;

            if (rsi.Result.LastValue < 30)
            {
                OpenPosition(TradeType.Buy);
            }
            else if (rsi.Result.LastValue > 70)
            {
                OpenPosition(TradeType.Sell);
            }
        }

        private void OpenPosition(TradeType tradeType)
        {
            foreach (var position in Account.Positions)
            {
                if (position.Label == "SampleRSIRobot" && position.TradeType != tradeType)
                {
                    Trade.Close(position);
                }
            }

            bool hasNeededPosition = Account.Positions.Any(position => position.Label == "SampleRSIRobot" && position.TradeType == tradeType);
            if (!hasNeededPosition)
            {
                var request = new MarketOrderRequest(tradeType, 10000) 
                {
                    Label = "SampleRSIRobot",
                    StopLossPips = 20
                };
                Trade.Send(request);
            }
        }
    }
}

 


@cAlgo_Development

kricka
31 Aug 2013, 00:29

Hi,

we are welcoming this possibility to trade different time frames i cAlgo. A very much needed function for developers.

Thanks..


@kricka

Neob1y
17 Sep 2013, 16:37

Hi,

when do support Multi-timeframe baktesting?

Thanks.


@Neob1y

cAlgo_Development
17 Sep 2013, 17:12

We are already working on it. Backtesting will be available very soon.


@cAlgo_Development

Neob1y
17 Sep 2013, 17:39

RE:

cAlgo_Development said:

We are already working on it. Backtesting will be available very soon.

Thanks for the answer.


@Neob1y

andromeda
24 Sep 2013, 01:35

RE:

Thank you for this upgrade which seems to be something I am looking for.

Is there any description of how to use these series in the context of Calculate method?

I know Calculate is called with an index parameter.

How that index relates to instantiated m10 or m1 for that matter ?

How often Calculate method is called by who and when and what is index relative to ?

(I know it is called at some irregular intervals in real time and any time a graph point is evaluated,

but I cannot correlate it to the last "10 minute" or "one minute" bar.)

My question may seem naive for you guys who know this software inside out, but this kind of

questions arise for anyone new to cAlgo. We badly need some glue logic described somewhere.

Descriptions are minimalistic. A simple question like Print method nowhere describes where

does the print go to. So far I know it goes o a log file, but could not find the log anywhere.

I find cAlgo exeptionally cool tool but I am having trouble to get started due to insufficient

description. C# is not an issue here but general concept of all classes and objects and how they tie together.

Of course I will slowly build the picture but it will be a long process.

Cheers

 

cAlgo_Development said:

 

We added new functionality to cAlgo - the ability for robots and indicators to retrieve OHLCV data for multiple timeframes. This can be done using the MarketData.GetSeries method:

MarketSeries m5series = MarketData.GetSeries(TimeFrame.Minute5);

We recommend to call the GetSeries method in the Robot.OnStart() or the Indicator.Initialize() methods.

When the series for a specified timeframe is received, you can access the series values or build an indicator based on that series:

private MarketSeries m10;
private MovingAverage ma;

protected override void OnStart()
{
    m10 = MarketData.GetSeries(TimeFrame.Minute10);
    ma = Indicators.SimpleMovingAverage(m10.High, 14);
}

The new version of our Demo cTrader and cAlgo is released and can be downloaded from www.spotware.com

Backtesting of Multi-timeframe robots in not supported yet. We will support it in the next version.

 


@andromeda

Spotware
24 Sep 2013, 12:31 ( Updated at: 23 Jan 2024, 13:16 )

RE: RE:

andromeda said:

How that index relates to instantiated m10 or m1 for that matter ?

How often Calculate method is called by who and when and what is index relative to ?

(I know it is called at some irregular intervals in real time and any time a graph point is evaluated,

but I cannot correlate it to the last "10 minute" or "one minute" bar.)

 

The Calculate method is called on each historical bar in the series the instance is attached to (i.e. EURUSD H1). Once it reaches real time, it is called on each incoming tick of that symbol, as well as on each incoming tick of any other symbols for which the series are retrieved.

The "index" that is the parameter to the Calculate method, is the index of the series that the instance is attached to. The series of other timeframes / symbols have different indexes. So, to get the index of a specific series you would need to use a method such as GetIndexByDate (Described in the example above: [Multi-timeframe moving average])

 

         private int GetIndexByDate(MarketSeries series, DateTime time)
        {
            for (int i = series.Close.Count - 1; i > 0; i--)
            {
                if (time == series.OpenTime[i])
                    return i;
            }
            return -1;
        }
    }
}

Descriptions are minimalistic. A simple question like Print method nowhere describes where

does the print go to. So far I know it goes o a log file, but could not find the log anywhere.

I find cAlgo exeptionally cool tool but I am having trouble to get started due to insufficient

description. C# is not an issue here but general concept of all classes and objects and how they tie together.

 The Print method prints to the Log within the platform, not a log file. It is the last tab in the bottom panel of the chart view.

We are preparing a manual for cAlgo with more detailed descriptions of all the main classes in the API.


@Spotware

Spotware
01 Oct 2013, 14:59

New version of cAlgo supports backtesting of multi-timeframe robots. Please check our demo build.


@Spotware

PCWalker
14 Jun 2014, 08:51

RE:

Spotware said:

New version of cAlgo supports backtesting of multi-timeframe robots. Please check our demo build.

Great upgrade.


@PCWalker

zofoyobis
11 Nov 2014, 07:04

I am trying to use this feature to create Heikin-Ashi indicator with custom timeframe as below. The value of haClose in the HeikinAshiClose series looks correct but I am always getting NaN for haOpen. I am not sure if something like below is supported?

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

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class TFHeikinAshiIndicator : Indicator
    {
        [Parameter("Heikin-Ashi Timeframe")]
        public TimeFrame HeikinAshiTimeframe { get; set; }

        [Output("Open", Color = Colors.DarkSlateBlue)]
        public IndicatorDataSeries HeikinAshiOpen { get; set; }

        [Output("Close", Color = Colors.SlateBlue)]
        public IndicatorDataSeries HeikinAshiClose { get; set; }

        private MarketSeries heikinAshiSeries;

        protected override void Initialize()
        {
            heikinAshiSeries = MarketData.GetSeries(HeikinAshiTimeframe);
        }

        public override void Calculate(int index)
        {
            int heikinAshiSeriesIndex = GetIndexByDate(heikinAshiSeries, MarketSeries.OpenTime[index]);

            double open = heikinAshiSeries.Open[heikinAshiSeriesIndex];
            double high = heikinAshiSeries.High[heikinAshiSeriesIndex];
            double low = heikinAshiSeries.Low[heikinAshiSeriesIndex];
            double close = heikinAshiSeries.Close[heikinAshiSeriesIndex];

            double haClose = (open + high + low + close) / 4;
            double haOpen;
            if (heikinAshiSeriesIndex != -1)
                haOpen = (HeikinAshiOpen[heikinAshiSeriesIndex - 1] + HeikinAshiClose[heikinAshiSeriesIndex - 1]) / 2;
            else
                haOpen = (open + close) / 2;

            ChartObjects.DrawText("ha", string.Format("heikinAshiSeriesIndex={0} haOpen={1}, haClose={2}", heikinAshiSeriesIndex, haOpen, haClose), StaticPosition.TopLeft, Colors.Red);

            HeikinAshiOpen[heikinAshiSeriesIndex] = haOpen;
            HeikinAshiClose[heikinAshiSeriesIndex] = haClose;
        }

        private int GetIndexByDate(MarketSeries series, DateTime time)
        {
            for (int i = series.Close.Count - 1; i > 0; i--)
            {
                if (time == series.OpenTime[i])
                    return i;
            }
            return -1;
        }
    }
}

 


@zofoyobis

Spotware
12 Nov 2014, 09:35

We can recommend you to contact one of our Partners or post a job in Development Jobs section.


@Spotware

crank
02 Jan 2015, 22:22

RE: Indicator example: Multi-timeframe moving average

Without plotting the actual moving average lines, how would I just output the numerical value of how far the 100 DAY moving average is from the current price on a one HOUR price chart, plotting just the numerical value in the top left corner of the a one hour price chart, i.e.,

(100 DAY moving average value) - (Current price on a one HOUR chart). With the numerical value output in the top left corner of the one hour chart. When I'm looking at shorter time frame charts like an hour or 15 minute charts, I want to know how far the close is from DAILY moving averages. The code below really only works if you want to know the MAs of shorter timeframes than the chart that you are viewing. I want to know the opposite, i.e, show longer timeframe MAs on shorter timeframe charts.

In this example, we output moving averages with the same period for different timeframes on a single chart:

 

Source code:

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

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC)]
    public class MultiTF_MA : Indicator
    {
        [Parameter(DefaultValue = 50)]
        public int Period { get; set; }

        [Output("MA", Color = Colors.Yellow)]
        public IndicatorDataSeries MA { get; set; }

        [Output("MA5", Color = Colors.Orange)]
        public IndicatorDataSeries MA5 { get; set; }

        [Output("MA10", Color = Colors.Red)]
        public IndicatorDataSeries MA10 { get; set; }

        private MarketSeries series5;
        private MarketSeries series10;

        private MovingAverage ma;
        private MovingAverage ma5;
        private MovingAverage ma10;

        protected override void Initialize()
        {
            series5 = MarketData.GetSeries(TimeFrame.Minute5);
            series10 = MarketData.GetSeries(TimeFrame.Minute10);

            ma = Indicators.MovingAverage(MarketSeries.Close, Period, MovingAverageType.Triangular);
            ma5 = Indicators.MovingAverage(series5.Close, Period, MovingAverageType.Triangular);
            ma10 = Indicators.MovingAverage(series10.Close, Period, MovingAverageType.Triangular);
        }

        public override void Calculate(int index)
        {
            MA[index] = ma.Result[index];

            var index5 = GetIndexByDate(series5, MarketSeries.OpenTime[index]);
            if (index5 != -1)
                MA5[index] = ma5.Result[index5];

            var index10 = GetIndexByDate(series10, MarketSeries.OpenTime[index]);
            if (index10 != -1)
                MA10[index] = ma10.Result[index10];
        }


        private int GetIndexByDate(MarketSeries series, DateTime time)
        {
            for (int i = series.Close.Count - 1; i > 0; i--)
            {
                if (time == series.OpenTime[i])
                    return i;
            }
            return -1;
        }
    }
}

 

 


@crank

cjdduarte
24 Mar 2015, 02:46

RE:

able to implement this code?
Really needed it

 

zofoyobis said:

I am trying to use this feature to create Heikin-Ashi indicator with custom timeframe as below. The value of haClose in the HeikinAshiClose series looks correct but I am always getting NaN for haOpen. I am not sure if something like below is supported?

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

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class TFHeikinAshiIndicator : Indicator
    {
        [Parameter("Heikin-Ashi Timeframe")]
        public TimeFrame HeikinAshiTimeframe { get; set; }

        [Output("Open", Color = Colors.DarkSlateBlue)]
        public IndicatorDataSeries HeikinAshiOpen { get; set; }

        [Output("Close", Color = Colors.SlateBlue)]
        public IndicatorDataSeries HeikinAshiClose { get; set; }

        private MarketSeries heikinAshiSeries;

        protected override void Initialize()
        {
            heikinAshiSeries = MarketData.GetSeries(HeikinAshiTimeframe);
        }

        public override void Calculate(int index)
        {
            int heikinAshiSeriesIndex = GetIndexByDate(heikinAshiSeries, MarketSeries.OpenTime[index]);

            double open = heikinAshiSeries.Open[heikinAshiSeriesIndex];
            double high = heikinAshiSeries.High[heikinAshiSeriesIndex];
            double low = heikinAshiSeries.Low[heikinAshiSeriesIndex];
            double close = heikinAshiSeries.Close[heikinAshiSeriesIndex];

            double haClose = (open + high + low + close) / 4;
            double haOpen;
            if (heikinAshiSeriesIndex != -1)
                haOpen = (HeikinAshiOpen[heikinAshiSeriesIndex - 1] + HeikinAshiClose[heikinAshiSeriesIndex - 1]) / 2;
            else
                haOpen = (open + close) / 2;

            ChartObjects.DrawText("ha", string.Format("heikinAshiSeriesIndex={0} haOpen={1}, haClose={2}", heikinAshiSeriesIndex, haOpen, haClose), StaticPosition.TopLeft, Colors.Red);

            HeikinAshiOpen[heikinAshiSeriesIndex] = haOpen;
            HeikinAshiClose[heikinAshiSeriesIndex] = haClose;
        }

        private int GetIndexByDate(MarketSeries series, DateTime time)
        {
            for (int i = series.Close.Count - 1; i > 0; i--)
            {
                if (time == series.OpenTime[i])
                    return i;
            }
            return -1;
        }
    }
}

 

 


@cjdduarte

aharonzbaida
16 Oct 2015, 09:48

RE: Indicator example: Multi-timeframe moving average

cAlgo_Development said:

In this example, we output moving averages with the same period for different timeframes on a single chart:

 

Source code:

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

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC)]
    public class MultiTF_MA : Indicator
    {
        [Parameter(DefaultValue = 50)]
        public int Period { get; set; }

        [Output("MA", Color = Colors.Yellow)]
        public IndicatorDataSeries MA { get; set; }

        [Output("MA5", Color = Colors.Orange)]
        public IndicatorDataSeries MA5 { get; set; }

        [Output("MA10", Color = Colors.Red)]
        public IndicatorDataSeries MA10 { get; set; }

        private MarketSeries series5;
        private MarketSeries series10;

        private MovingAverage ma;
        private MovingAverage ma5;
        private MovingAverage ma10;

        protected override void Initialize()
        {
            series5 = MarketData.GetSeries(TimeFrame.Minute5);
            series10 = MarketData.GetSeries(TimeFrame.Minute10);

            ma = Indicators.MovingAverage(MarketSeries.Close, Period, MovingAverageType.Triangular);
            ma5 = Indicators.MovingAverage(series5.Close, Period, MovingAverageType.Triangular);
            ma10 = Indicators.MovingAverage(series10.Close, Period, MovingAverageType.Triangular);
        }

        public override void Calculate(int index)
        {
            MA[index] = ma.Result[index];

            var index5 = GetIndexByDate(series5, MarketSeries.OpenTime[index]);
            if (index5 != -1)
                MA5[index] = ma5.Result[index5];

            var index10 = GetIndexByDate(series10, MarketSeries.OpenTime[index]);
            if (index10 != -1)
                MA10[index] = ma10.Result[index10];
        }


        private int GetIndexByDate(MarketSeries series, DateTime time)
        {
            for (int i = series.Close.Count - 1; i > 0; i--)
            {
                if (time == series.OpenTime[i])
                    return i;
            }
            return -1;
        }
    }
}

 

A modification to the above example that solves missing values when attaching indicator to chart of lower time frame than the M5: the index function returns a match,or the closest previous value in higher time frame series.

//modified GetIndexByDate() from ctdn example

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

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC)]
    public class MultiTF_MA : Indicator
    {
        [Parameter(DefaultValue = 50)]
        public int Period { get; set; }
        
        [Output("MA", Color = Colors.Yellow)]
        public IndicatorDataSeries MA { get; set; }

        [Output("MA5", Color = Colors.Orange)]
        public IndicatorDataSeries MA5 { get; set; }

        [Output("MA10", Color = Colors.Red)]
        public IndicatorDataSeries MA10 { get; set; }

        private MarketSeries series5;
        private MarketSeries series10;

        private MovingAverage ma;
        private MovingAverage ma5;
        private MovingAverage ma10;

        protected override void Initialize()
        {
            series5 = MarketData.GetSeries(TimeFrame.Minute5);
            series10 = MarketData.GetSeries(TimeFrame.Minute10);

            ma = Indicators.MovingAverage(MarketSeries.Close, Period, MovingAverageType.Triangular);
            ma5 = Indicators.MovingAverage(series5.Close, Period, MovingAverageType.Triangular);
            ma10 = Indicators.MovingAverage(series10.Close, Period, MovingAverageType.Triangular);
        }

        public override void Calculate(int index)
        {
            MA[index] = ma.Result[index];

            //var index5 = GetIndexByDate(series5, MarketSeries.OpenTime[index]);
            var index5 = GetIndexByTime(series5, MarketSeries.OpenTime[index]); 
            if (index5 != -1)
                MA5[index] = ma5.Result[index5];

            //var index10 = GetIndexByDate(series10, MarketSeries.OpenTime[index]);
            var index10 = GetIndexByTime(series10, MarketSeries.OpenTime[index]);
            if (index10 != -1)
                MA10[index] = ma10.Result[index10];
        }


        private int GetIndexByDate(MarketSeries series, DateTime time)
        {
            for (int i = series.Close.Count - 1; i > 0; i--)
            {
                if (time == series.OpenTime[i])
                    return i;
            }
            return -1;
        }

        private int GetIndexByTime(MarketSeries searchSeries, DateTime desiredTime)
        {
            Print("desired time=" + desiredTime.ToString());
            //loop over time series backwards till closest match found
            for (int i = searchSeries.Close.Count - 1; i > 0; i--)
            {
                if (desiredTime == searchSeries.OpenTime[i])
                {
                    return i;
                }
                else if (searchSeries.OpenTime[i] < desiredTime) return i; //return last value prev. to desired
                
            }
            return -1;
        }
    }
}


@aharonzbaida

emmamgibbons42
16 Apr 2017, 22:46

Thats a great feature. I love multiple EMA in with different time frame.  


@emmamgibbons42

diiptrade
27 Jul 2017, 08:17

MarketData.GetSeries doesnt work properly!!!

For example, If indicator is on Hour1 Timeframe and I want to get DataSeries from Minute1 Timeframe, it only get truncated Minute1 DataSeries.

DataSeries.Close.Count = 6000

M1DataSeries.Close.Count = 9000, but it should be at least 6 000 x 60 = 360 000!

And when you scroll to the beginning DataSeries.Close is updated, but M1DataSeries.Close is the same = 9000.

Please, fix it!


@diiptrade

irmscher9
10 Feb 2018, 15:28

How do I create Directional Movement System instance of a different timeframe?

private MarketSeries m5;

 

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

namespace cAlgo
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class testdel : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        public MarketSeries m5;
        public DirectionalMovementSystem _dms5m;


        protected override void OnStart()
        {
            m5 = MarketData.GetSeries(TimeFrame.Minute5);
            _dms5m = Indicators.DirectionalMovementSystem(m5.Close, 14);
        }

    }
}

 


@irmscher9

irmscher9
10 Feb 2018, 15:28

The code above seem doesn;t work...


@irmscher9

PanagiotisCharalampous
12 Feb 2018, 11:35

Hi irmscher9,

Why do you say that the code is not working? Do you get an exception? Do you get unexpected results? If you give us more information, it will be easier for us to help you.

Best Regards,

Panagiotis


@PanagiotisCharalampous

Dagfx
25 Feb 2018, 22:26

Whenever I install the Multi-timeframe moving average, the ctrader keeps disconnecting and reconnecting and so on...Till I remove the indicator all of it. What's the problem?


@Dagfx

PanagiotisCharalampous
26 Feb 2018, 11:17

Hi daguerfi,

When did you observe this behavior? Was it during a weekend?

Best Regards,

Panagiotis


@PanagiotisCharalampous

rmsuleman
26 Mar 2018, 23:16 ( Updated at: 21 Dec 2023, 09:20 )

RE: Indicator example: Multi-timeframe moving average

I am trying to install the code using calgo but I get the following error when I try to build it. Please let me know how to fix it. Thanks

 

cAlgo_Development said:

In this example, we output moving averages with the same period for different timeframes on a single chart:

 

Source code:

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

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC)]
    public class MultiTF_MA : Indicator
    {
        [Parameter(DefaultValue = 50)]
        public int Period { get; set; }

        [Output("MA", Color = Colors.Yellow)]
        public IndicatorDataSeries MA { get; set; }

        [Output("MA5", Color = Colors.Orange)]
        public IndicatorDataSeries MA5 { get; set; }

        [Output("MA10", Color = Colors.Red)]
        public IndicatorDataSeries MA10 { get; set; }

        private MarketSeries series5;
        private MarketSeries series10;

        private MovingAverage ma;
        private MovingAverage ma5;
        private MovingAverage ma10;

        protected override void Initialize()
        {
            series5 = MarketData.GetSeries(TimeFrame.Minute5);
            series10 = MarketData.GetSeries(TimeFrame.Minute10);

            ma = Indicators.MovingAverage(MarketSeries.Close, Period, MovingAverageType.Triangular);
            ma5 = Indicators.MovingAverage(series5.Close, Period, MovingAverageType.Triangular);
            ma10 = Indicators.MovingAverage(series10.Close, Period, MovingAverageType.Triangular);
        }

        public override void Calculate(int index)
        {
            MA[index] = ma.Result[index];

            var index5 = GetIndexByDate(series5, MarketSeries.OpenTime[index]);
            if (index5 != -1)
                MA5[index] = ma5.Result[index5];

            var index10 = GetIndexByDate(series10, MarketSeries.OpenTime[index]);
            if (index10 != -1)
                MA10[index] = ma10.Result[index10];
        }


        private int GetIndexByDate(MarketSeries series, DateTime time)
        {
            for (int i = series.Close.Count - 1; i > 0; i--)
            {
                if (time == series.OpenTime[i])
                    return i;
            }
            return -1;
        }
    }
}

 

 


@rmsuleman

PanagiotisCharalampous
27 Mar 2018, 09:27

Hi rmsuleman,

I tried to build the indicator and I have no problems. However the error message references Robots folder which is used for cBots. Am I missing something?

Best Regards,

Panagiotis


@PanagiotisCharalampous

... Deleted by UFO ...

Vitali Gajdabrus
03 Nov 2018, 23:41

RE:

Panagiotis Charalampous said:

Hi Panagiotis...

How to use timeframe Tick: t1, t2 ... t50 and others?

series_t5 = MarketData.GetSeries(TimeFrame.Tick5); ???

 


@Vitali Gajdabrus

Vitali Gajdabrus
04 Nov 2018, 18:24

RE:

Panagiotis Charalampous said:

How to do it?

double dY = 0.5 * args.ChartArea.Height;
double dX0 = 0.25 * args.ChartArea.Width;
double dX1 = 0.75 * args.ChartArea.Width;
Chart.DrawTrendLine("test", dX0, dY, dX1, dY, Color.Red);

 


@Vitali Gajdabrus

Vitali Gajdabrus
05 Nov 2018, 07:29

RE: RE:

Vitali Gajdabrus said:

...

Chart.DrawTrendLine("test", dX0, dY, dX1, dY, Color.Red);

I have already solved this problem.

 Thank.


@Vitali Gajdabrus

oliveira.phc
12 Dec 2018, 20:09

RE:

cAlgo_Development said:

We added new functionality to cAlgo - the ability for robots and indicators to retrieve OHLCV data for multiple timeframes. This can be done using the MarketData.GetSeries method:

MarketSeries m5series = MarketData.GetSeries(TimeFrame.Minute5);

We recommend to call the GetSeries method in the Robot.OnStart() or the Indicator.Initialize() methods.

When the series for a specified timeframe is received, you can access the series values or build an indicator based on that series:

private MarketSeries m10;
private MovingAverage ma;

protected override void OnStart()
{
    m10 = MarketData.GetSeries(TimeFrame.Minute10);
    ma = Indicators.SimpleMovingAverage(m10.High, 14);
}

The new version of our Demo cTrader and cAlgo is released and can be downloaded from www.spotware.com

Update: Backtesting of Multi-timeframe robots is supported now.

Hello again.

Is it technically impossible to have multiple timeframes of type "tick"? If not, I will make a suggestion for it.

Kind regards,

Paulo Oliveira


@oliveira.phc

PanagiotisCharalampous
13 Dec 2018, 09:53

Hi oliveira.phc,

A workaround is to get the timeframe as a parameter. See below

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.None)]
    public class NewcBot : Robot
    {
        [Parameter]
        public TimeFrame Timeframe { get; set; }

        protected override void OnStart()
        {
            var t = MarketData.GetSeries(Timeframe);
        }

        protected override void OnTick()
        {

        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

Best Regards,

Panagiotis


@PanagiotisCharalampous

oliveira.phc
17 Dec 2018, 12:26

RE:
Panagiotis Charalampous said:

Hi oliveira.phc,

A workaround is to get the timeframe as a parameter. See below

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.None)]
    public class NewcBot : Robot
    {
        [Parameter]
        public TimeFrame Timeframe { get; set; }

        protected override void OnStart()
        {
            var t = MarketData.GetSeries(Timeframe);
        }

        protected override void OnTick()
        {

        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

Best Regards,

Panagiotis


Thank you for your readiness, Panagiotis. But, regarding the TimeFrame class, wouldn't it be necessary to update the API in order add properties of type Tick to it? The current API only have properties of type Time. https://ctrader.com/api/reference/timeframe I don't know if it is technically possible for cTrader to have multiple timeframe bots of type Tick, but it seems that it is doable for now. Kind regards, Paulo Oliveira
@oliveira.phc

oliveira.phc
17 Dec 2018, 12:28

RE: RE:
Sorry, I meant NOT doable for now.
@oliveira.phc

PanagiotisCharalampous
17 Dec 2018, 12:36

Hi oliveira.phc,

MarketData.GetSeries(Timeframe) should work fine for tick data, as long as you set the timeframe from the interface. We just need to update the Timeframe class. We will do this in one of he upcoming updates.

Best Regards,

Panagiotis


@PanagiotisCharalampous

oliveira.phc
17 Dec 2018, 12:58

RE:
Thanks again.
@oliveira.phc

shrumr
02 Feb 2019, 02:37 ( Updated at: 21 Dec 2023, 09:21 )

I have modified the indicator to just display daily 50/100/200 averages on the chart. 

Please have alook. I am very novice at this. 

 

I do wanted to ask, is it possible to disable this overlay value which appear on when mouse hovers over the MA lines?

 

 

Here is the full code:

 

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

namespace cAlgo.Indicators
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC)]
    public class MultiTF_MA2 : Indicator
    {

        [Output("MA50", Color = Colors.Red)]
        public IndicatorDataSeries MA50 { get; set; }

        [Output("MA100", Color = Colors.Green)]
        public IndicatorDataSeries MA100 { get; set; }

        [Output("MA200", Color = Colors.White)]
        public IndicatorDataSeries MA200 { get; set; }

        private MarketSeries seriesdaily;

        private MovingAverage ma50;
        private MovingAverage ma100;
        private MovingAverage ma200;

        protected override void Initialize()
        {
            seriesdaily = MarketData.GetSeries(TimeFrame.Daily);
            ma50 = Indicators.MovingAverage(seriesdaily.Close, 50, MovingAverageType.Simple);
            ma100 = Indicators.MovingAverage(seriesdaily.Close, 100, MovingAverageType.Simple);
            ma200 = Indicators.MovingAverage(seriesdaily.Close, 200, MovingAverageType.Simple);
        }

        public override void Calculate(int index)
        {

            var index50 = GetIndexByDate(seriesdaily, MarketSeries.OpenTime[index]);
            if (index50 != -1)
                MA50[index] = ma50.Result[index50];

            var index100 = GetIndexByDate(seriesdaily, MarketSeries.OpenTime[index]);
            if (index100 != -1)
                MA100[index] = ma100.Result[index100];

            var index200 = GetIndexByDate(seriesdaily, MarketSeries.OpenTime[index]);
            if (index200 != -1)
                MA200[index] = ma200.Result[index200];

        }


        private int GetIndexByDate(MarketSeries series, DateTime time)
        {
            for (int i = series.Close.Count - 1; i > 0; i--)
            {
                if (time == series.OpenTime[i])
                    return i;
            }
            return -1;
        }
    }
}

 


@shrumr

PanagiotisCharalampous
04 Feb 2019, 10:22

Hi shrumr,

At the moment this is not possible.

Best Regards,

Panagiotis


@PanagiotisCharalampous

Vitali Gajdabrus
04 Feb 2019, 10:40

RE:

 

Hi oliveira.phc,

MarketData.GetSeries(Timeframe) should work fine for tick data, as long as you set the timeframe from the interface. We just need to update the Timeframe class. We will do this in one of he upcoming updates.

Have you updated the Timeframe class?

MarketData.GetSeries(Timeframe.tick)

How can i do this?


@Vitali Gajdabrus

ctid1032297
07 Mar 2019, 17:33

RE:

cAlgo_Development said:

We added new functionality to cAlgo - the ability for robots and indicators to retrieve OHLCV data for multiple timeframes. This can be done using the MarketData.GetSeries method:

MarketSeries m5series = MarketData.GetSeries(TimeFrame.Minute5);

We recommend to call the GetSeries method in the Robot.OnStart() or the Indicator.Initialize() methods.

When the series for a specified timeframe is received, you can access the series values or build an indicator based on that series:

private MarketSeries m10;
private MovingAverage ma;

protected override void OnStart()
{
    m10 = MarketData.GetSeries(TimeFrame.Minute10);
    ma = Indicators.SimpleMovingAverage(m10.High, 14);
}

The new version of our Demo cTrader and cAlgo is released and can be downloaded from www.spotware.com

Update: Backtesting of Multi-timeframe robots is supported now.

Is it possible to call this but not for one of the time based timeframes? I.e Range bars?


@ctid1032297

PanagiotisCharalampous
07 Mar 2019, 17:59

Hi ctid1032297,

Thanks for posting in our forum. Renko and Range bars are not available yet.

Best Regards,

Panagiotis


@PanagiotisCharalampous

anjanbfx@gmail.com
18 Mar 2019, 06:14

RE:

Panagiotis Charalampous said:

Hi ctid1032297,

Thanks for posting in our forum. Renko and Range bars are not available yet.

Best Regards,

Panagiotis

Hi,

is this feature available for Renko bars of different Ticks.

Thanks


@anjanbfx@gmail.com

alexnikon
27 Jul 2020, 09:22

Multi-timeframe

Great solution! It works! But the Build Results give me that MarketSeries method is obsolete. Could you advise how update it? 


@alexnikon

PanagiotisCharalampous
27 Jul 2020, 09:36

Hi alexnikon,

MarketSeries has been replaced by Bars.

Best Regards,

Panagiotis 

Join us on Telegram

 


@PanagiotisCharalampous

alexnikon
01 Aug 2020, 13:27

multi-timeframes

Hi guys. I'm struggling to make a multi-time-frame Gann-high-low indicator. I have tried to use all examples from the website, but with no success. It doesn't want to recognise the custom time-frames and doesn't work properly. Could some one give me an advise, please?..


@alexnikon

PanagiotisCharalampous
03 Aug 2020, 08:25

Hi alexnikon,

To give you an advice, you need to provide more information. It would be better to create a new thread, post your code and explain your issue in detail.

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

alexnikon
03 Aug 2020, 13:04

RE:

PanagiotisCharalampous said:

Hi alexnikon,

To give you an advice, you need to provide more information. It would be better to create a new thread, post your code and explain your issue in detail.

Best Regards,

Panagiotis 

Join us on Telegram

Dear PanagiotisCharalampous thanks a lot for the reply. Greatly appreciated...

I'm traying to design a GannHighLow Multi-Timeframe indicator useful to build up a multi-frame cBot afterwards, and with no success at the moment.

I have tried a referencing and also a direct re-coding of the provided by cTrader samples. Still no success. Both options work well on the chats with the same time scale, but are showing some nonsense lines on the chats with longer or shorter timeframes. It looks like the problem is in re-indexing of series for the Custom Timeframe. The HiLo is using the [index - 1] value, which might be deteriorating the graph, but my knowledge is too limited to sort it out. It would be great, if you could give some advise... Thanks in advance.

One of the codes, which I'm trying to finish, is here:

// from updated "GannHighLow" by 'kalex718' at 12/09/2012
using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;

namespace cAlgo
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class MyMultiFrameHiLo2 : Indicator
    {
        [Parameter("Period", DefaultValue = 10)]
        public int Period { get; set; }

        [Parameter("Timeframe1", DefaultValue = "Daily")]
        public TimeFrame Timeframe { get; set; }

        [Output("Support", LineColor = "#FF02AFF1", Thickness = 1)]
        public IndicatorDataSeries Support { get; set; }

        private Bars _bars;
        private SimpleMovingAverage _smaHigh;
        private SimpleMovingAverage _smaLow;
//-------------------------------------------------------------------------------------------------------
        protected override void Initialize()
        {
            _bars = MarketData.GetBars(Timeframe);
            _smaHigh = Indicators.SimpleMovingAverage(_bars.HighPrices, Period);
            _smaLow = Indicators.SimpleMovingAverage(_bars.LowPrices, Period);
        }
        public override void Calculate(int index)
        {
            if (index < Period)
                return;
            double close = Bars.ClosePrices[index];
            double smaHigh = _smaHigh.Result[index - 0];
            double smaHighPrev = _smaHigh.Result[index - 1];
            double smaLow = _smaLow.Result[index - 0];
            double smaLowPrev = _smaLow.Result[index - 1];
//-------------------------------------------------------------------------------------------------------
            if (close > smaHigh)
                Support[index] = smaLow;
            else
            {
                if (close < smaLow)
                    Support[index] = smaHigh;
                else
                {
                    if (Support[index - 1] == smaHighPrev)
                        Support[index] = smaHigh;
                    else
                        Support[index] = smaLow;
                }
            }
        }
    }
}


@alexnikon

PanagiotisCharalampous
03 Aug 2020, 15:04

Hi alexnikon,

I am not sure what is the indicator supposed to do but your indexing is definitely wrong. See below how to get the correct indices for your indicators


            double smaHigh = _smaHigh.Result[_bars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]) - 0];
            double smaHighPrev = _smaHigh.Result[_bars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]) - 1];
            double smaLow = _smaLow.Result[_bars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]) - 0];
            double smaLowPrev = _smaLow.Result[_bars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]) - 1];

Let me know if this helps

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

alexnikon
03 Aug 2020, 15:41

RE:

PanagiotisCharalampous said:

Hi alexnikon,

I am not sure what is the indicator supposed to do but your indexing is definitely wrong. See below how to get the correct indices for your indicators


            double smaHigh = _smaHigh.Result[_bars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]) - 0];
            double smaHighPrev = _smaHigh.Result[_bars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]) - 1];
            double smaLow = _smaLow.Result[_bars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]) - 0];
            double smaLowPrev = _smaLow.Result[_bars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]) - 1];

Let me know if this helps

Best Regards,

Panagiotis 

Join us on Telegram

Thanks a lot !! It looks better. It draws more sensible line if the Custom timescale is shorter than the carrier chart, but it is still wrong if it is longer. F.e. on the base H1 chart, the Custom frame M10 looks nearly properly (even not sure), but the D1 is wrong...

Note: I want eventually use the GannHiLo for a cBot to trigger when Close price crosses the HiLo on the triple screen view (by Elder). It seams to be working as a kind of dynamic support line...

The updated code with your suggestion follows:

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

namespace cAlgo
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class MyMultiFrameHiLo2 : Indicator
    {

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

        [Parameter("Timeframe1", DefaultValue = "Daily")]
        public TimeFrame Timeframe { get; set; }

        [Output("Support", LineColor = "#FF02AFF1", Thickness = 1)]
        public IndicatorDataSeries Support { get; set; }

        private Bars _bars;
        private SimpleMovingAverage _smaHigh;
        private SimpleMovingAverage _smaLow;

        protected override void Initialize()
        {
            _bars = MarketData.GetBars(Timeframe);
            _smaHigh = Indicators.SimpleMovingAverage(_bars.HighPrices, Period);
            _smaLow = Indicators.SimpleMovingAverage(_bars.LowPrices, Period);
        }
        public override void Calculate(int index)
        {
            if (index < Period)
                return;

            double close = Bars.ClosePrices[index];

           /* ------ excluded ----------------------------------------

            double smaHigh = _smaHigh.Result[index - 0];
            double smaHighPrev = _smaHigh.Result[index - 1];
            double smaLow = _smaLow.Result[index - 0];
            double smaLowPrev = _smaLow.Result[index - 1];
            ------------------------------------------------------------*/
            double smaHigh = _smaHigh.Result[_bars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]) - 0];
            double smaHighPrev = _smaHigh.Result[_bars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]) - 1];
            double smaLow = _smaLow.Result[_bars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]) - 0];
            double smaLowPrev = _smaLow.Result[_bars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]) - 1];
//------------------------------------------------------------------------
            if (close > smaHigh)
                Support[index] = smaLow;
            else
            {
                if (close < smaLow)
                    Support[index] = smaHigh;
                else
                {
                    if (Support[index - 1] == smaHighPrev)
                        Support[index] = smaHigh;
                    else
                        Support[index] = smaLow;
                }
            }
        }
    }
}


@alexnikon

PanagiotisCharalampous
03 Aug 2020, 15:45

Hi alexnikon,

I cannot help you further at the moment because I have no idea what is the indicator expected to do. You need to provide more information of what the expected outcome should be and what does the indicator do instead. Screenshots would be helpful.

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

alexnikon
03 Aug 2020, 23:41

RE:

PanagiotisCharalampous said:

Hi alexnikon,

I cannot help you further at the moment because I have no idea what is the indicator expected to do. You need to provide more information of what the expected outcome should be and what does the indicator do instead. Screenshots would be helpful.

Best Regards,

Panagiotis 

Join us on Telegram

Dear PanagiotisCharalampous. Thank you very much again. Sorry, the Gann-High-Low indicator isn't very popular. It is based on moving averages of High and Low prices of the series. It shows only one of them which is below the trend - would it be  the average of Highs or Lows depending of the trend direction. The line sharply swaps the side around the trend when the Close price penetrates the actual high or low price average line in the opposite movement and the trend changes direction (pict.1).

Not sure whether my explanation is clear, but hope the pictures can help. I sorry for asking so much attention... Thanks in advance...

Pic.1


@alexnikon

PanagiotisCharalampous
04 Aug 2020, 08:14

Hi alexnikon,

Thanks for the additional information but the screenshot does not explain what is the problem with higher timeframes. Can you elaborate? What does it do and what should it do instead?

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

alexnikon
04 Aug 2020, 11:14 ( Updated at: 21 Dec 2023, 09:22 )

RE: RE:

alexnikon said:

PanagiotisCharalampous said:

Hi alexnikon,

I cannot help you further at the moment because I have no idea what is the indicator expected to do. You need to provide more information of what the expected outcome should be and what does the indicator do instead. Screenshots would be helpful.

Best Regards,

Panagiotis 

Join us on Telegram

Dear PanagiotisCharalampous. Thank you very much again. Sorry, the Gann-High-Low indicator isn't very popular. It is based on moving averages of High and Low prices of the series. It shows only one of them which is below the trend - would it be  the average of Highs or Lows depending of the trend direction. The line sharply swaps the side around the trend when the Close price penetrates the actual high or low price average line in the opposite movement and the trend changes direction (pict.1).

Not sure whether my explanation is clear, but hope the pictures can help. I sorry for asking so much attention... Thanks in advance...

Pic.1

 

Dear Panagiotic

Here you can see what the H1 chart looks like when I use consecutively M5, Daily and H1 (normal) custom frames.

(Sorry for publishing them this way. Can not see how to attach the link from cTrader directly...)

Thank you very much.


@alexnikon

PanagiotisCharalampous
04 Aug 2020, 12:03

Hi alexnikon,

I used the same timeframes but the chart looks fine to me

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

alexnikon
04 Aug 2020, 12:18 ( Updated at: 21 Dec 2023, 09:22 )

RE:

PanagiotisCharalampous said:

Hi alexnikon,

I used the same timeframes but the chart looks fine to me

Best Regards,

Panagiotis 

 

Join us on Telegram

Oooo!! I hope I'm wrong. I'll try to fit it in a robot. Thank you very much. I highly appreciate your help!


@alexnikon

... Deleted by UFO ...

... Deleted by UFO ...

xeulav
11 Dec 2020, 11:06

RE: RE:

Hello,

the MarketData.GetSeries is obsolete now.

 


@xeulav

FalcoPereGrinus
28 Jan 2021, 11:49 ( Updated at: 21 Dec 2023, 09:22 )

 

Hello there I want to add ma50 and ma200 values ​​to my strategy in the daily period, but both give the same value of ma50. Where am I making a mistake? Thanks for your help.

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewcBot : Robot
    {
        [Parameter(DefaultValue = 0.0)]
        public double Parameter { get; set; }

        [Parameter("Slow Periods", Group = "Simple Moving Average", DefaultValue = 200)]
        public int SlowPeriods { get; set; }

        [Parameter("Fast Periods", Group = "Simple Moving Average", DefaultValue = 50)]
        public int FastPeriods { get; set; }

        private MovingAverage FastSMA;
        private MovingAverage SlowSMA;
        private Bars D1;

        protected override void OnStart()
        {
            D1 = MarketData.GetBars(TimeFrame.Daily);
            FastSMA = Indicators.SimpleMovingAverage(D1.ClosePrices, FastPeriods);
            SlowSMA = Indicators.SimpleMovingAverage(D1.ClosePrices, SlowPeriods);
        }

        protected override void OnTick()
        {
            Print("FSMA={0},SSMA={0}", FastSMA.Result.LastValue, SlowSMA.Result.LastValue);
        }

        protected override void OnStop()
        {
            // Put your deinitialization logic here
        }
    }
}

 

 


@FalcoPereGrinus

PanagiotisCharalampous
28 Jan 2021, 13:45

Hi FalcoPereGrinus,

Try 

Print("FSMA={0},SSMA={1}", FastSMA.Result.LastValue, SlowSMA.Result.LastValue);

instead.

Best Regards,

Panagiotis 

Join us on Telegram


@PanagiotisCharalampous

FalcoPereGrinus
28 Jan 2021, 13:52

RE:

PanagiotisCharalampous said:

Hi FalcoPereGrinus,

Try 

Print("FSMA={0},SSMA={1}", FastSMA.Result.LastValue, SlowSMA.Result.LastValue);

instead.

Best Regards,

Panagiotis 

Join us on Telegram

Hi Panagiotis;

Thank you very much. I apologize for my carelessness.


@FalcoPereGrinus

cW22Trader
08 Sep 2021, 23:28 ( Updated at: 21 Dec 2023, 09:22 )

Historical Data is wrong

Hi,

Why is the historical data wrong when using a different time frame and retrieving the index by GetIndexByTime? How could the indicator already know the high and low value (sma period = 1) at 9 pm of the previous day (see 1. screen shot)? If I a reduce dataIndex by 1 it is correct but is this how you should use GetIndexByTime? If you leave the indicator on the chart for a while, the values calculated while the chart was open behave different then the ones calculated from historical data during initializaiton of the indicator (see 2. screen shot). The last 3 bars all have different low values (red line) but all others (calculated during init) alway have 2 same values (this was done on 1m chart with tf parameter set to 2m).

Kind regards

 

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 TimeFrameMA : Indicator
    {
        [Parameter("Time Frame", DefaultValue = "Daily")]
        public TimeFrame Timeframe { get; set; }

        [Parameter("MA Periods", DefaultValue = 3, MinValue = 1)]
        public int Periods { get; set; }

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

        [Output("High", Thickness = 3)]
        public IndicatorDataSeries High { get; set; }

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

        private Bars data;
        private MovingAverage maH, maL;


        protected override void Initialize()
        {
            data = MarketData.GetBars(Timeframe);
            maH = Indicators.MovingAverage(data.HighPrices, Periods, MAType);
            maL = Indicators.MovingAverage(data.LowPrices, Periods, MAType);
        }

        public override void Calculate(int index)
        {
            var indexData = data.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);
            if (indexData > 0)
            {
                High[index] = maH.Result[indexData];
                Low[index] = maL.Result[indexData];
            }
        }
    }
}


@cW22Trader

PanagiotisCharalampous
09 Sep 2021, 08:43

Hi cW22Trader,

How could the indicator already know the high and low value (sma period = 1) at 9 pm of the previous day (see 1. screen shot)?

Because you are retrieving data for historical bars that have already been closed. All the bars you retrieve are closed bars. When you get data using GetIndexByTime(), you don't get the bar as it was at the specific point of time, but the completed bar where the requested time falls in.

If you are looking to find the bar state at the specific point of time, then this functionality is not offered by the API. You will need to develop something yourself.

Best Regards,

Panagiotis 

Join us on Telegram and Facebook  


@PanagiotisCharalampous

cW22Trader
03 Oct 2021, 18:57

RE:

Hi Panagiotis,

PanagiotisCharalampous said:

Hi cW22Trader,

How could the indicator already know the high and low value (sma period = 1) at 9 pm of the previous day (see 1. screen shot)?

Because you are retrieving data for historical bars that have already been closed. All the bars you retrieve are closed bars. When you get data using GetIndexByTime(), you don't get the bar as it was at the specific point of time, but the completed bar where the requested time falls in.

If you are looking to find the bar state at the specific point of time, then this functionality is not offered by the API. You will need to develop something yourself.

Best Regards,

Panagiotis 

Join us on Telegram and Facebook  

I understand that the API does not offer intermediat data of a past bar of a different time frame. Unfortunately, this makes it impossible to run in backtest since the data form a different time frame is futur data.

E.g. on a 1h chart with an indicator using data form the 4h time frame and simply displays the OHLC data as static text on chart, every time a new 4h bar starts it already shows the future high and low of the next 4h in visual backtesting. I would expect that the last bar of the 4h time frame "builds up" during the next 4h in visual backtesting and only stores the open, high, low and close of that bar once it is complete just like it does in real-time mode.

Kind regards


@cW22Trader

Marin0ss
28 Jan 2022, 22:18

Refer price/indicator values on different Range chart

Hi Ctrader team,

Is it possible to refer to Open/Close/High/Low values & Indicator results from a different Range Bar chart?

Like running Ra100 Chart while getting values from Ra500 for example, just like referring values in a higher TF?

If not yet possible; any plans to implement this already?

Thanks in advance!


@Marin0ss

cW22Trader
28 Jan 2022, 22:53

RE: Refer price/indicator values on different Range chart

Marin0ss said:

Hi Ctrader team,

Is it possible to refer to Open/Close/High/Low values & Indicator results from a different Range Bar chart?

Like running Ra100 Chart while getting values from Ra500 for example, just like referring values in a higher TF?

If not yet possible; any plans to implement this already?

Thanks in advance!

I think this is possible at least with Renko. This should be the same with Range bars.

But be carefull when using OHLC data of "higher" or larger TF. On historical data of e.g. on a chart it will use future data of the higher TF. E.g. a Ra100 bar just closed and your indicator algo gets triggered and you also get the data from the Ra500 bar using this API "Ra500bar.OpenTimes.GetIndexByTime(Ra100bar.OpenTimes[index])". The Ra500 bar may not be closed yet but since on historical data you only have access to completed OHLC data, you would use future data of that Ra500 bar which produces unrealistic results.

@cTrader Team: please correct me if I'm wrong...

Kind regards


@cW22Trader

Marin0ss
29 Jan 2022, 14:43 ( Updated at: 29 Jan 2022, 15:47 )

RE: RE: Refer price/indicator values on different Range chart

cW22Trader said:

Marin0ss said:

Hi Ctrader team,

Is it possible to refer to Open/Close/High/Low values & Indicator results from a different Range Bar chart?

Like running Ra100 Chart while getting values from Ra500 for example, just like referring values in a higher TF?

If not yet possible; any plans to implement this already?

Thanks in advance!

I think this is possible at least with Renko. This should be the same with Range bars.

But be carefull when using OHLC data of "higher" or larger TF. On historical data of e.g. on a chart it will use future data of the higher TF. E.g. a Ra100 bar just closed and your indicator algo gets triggered and you also get the data from the Ra500 bar using this API "Ra500bar.OpenTimes.GetIndexByTime(Ra100bar.OpenTimes[index])". The Ra500 bar may not be closed yet but since on historical data you only have access to completed OHLC data, you would use future data of that Ra500 bar which produces unrealistic results.

@cTrader Team: please correct me if I'm wrong...

Kind regards

Thanks! Got me further. I can now get the values from a custom Indicator; but I can't seem to refer to a different RangeBar chart with the standard build in Indicators (for e.g. Supertrend).

Could you help me out a bit here?

So, the DSS values I get back correct; ST values are from the TF the Bot is running on; so that is also fine.

But When I add Ra500 to the ST500 line, like below, it fails and mentioned an overload as only wants to see 2 arguments.

ST500 = Indicators.Supertrend(Ra500, 10, 3.0);

(If I change the indicator to for example a Moving Average like: ST500 = Indicators.MovingAverage(Ra500.ClosePrices, 10, MovingAverageType.Exponential);, no error messages displayed. So seems issue with Supertrend, or I misconfigure it..)

I also got it working if I download the custom Supertrend indicator that can be found in the Algorithms section, but I rather use the standard one located in cTrader.

Ps. I add the code to OnStart, so I can test this in the weekend, as we cannot Backtest RangeBar data..

Thanks in advance!

//#reference: ..\Indicators\DSS Bressert.algo
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.None)]
    public class RangeBarMTFtest : Robot
    {
        private DSSBressert DSS;

        private Supertrend ST;
        private Supertrend ST500;

        private Bars Ra500;

        protected override void OnStart()
        {
            Ra500 = MarketData.GetBars(TimeFrame.Range500);

            DSS = Indicators.GetIndicator<DSSBressert>(Ra500, 13, 8, 8);

            ST = Indicators.Supertrend(10, 3.0);

            ST500 = Indicators.Supertrend(Ra500, 10, 3.0);

 


@Marin0ss

amusleh
31 Jan 2022, 07:59

RE: RE: RE: Refer price/indicator values on different Range chart

Marin0ss said:

Thanks! Got me further. I can now get the values from a custom Indicator; but I can't seem to refer to a different RangeBar chart with the standard build in Indicators (for e.g. Supertrend).

Could you help me out a bit here?

So, the DSS values I get back correct; ST values are from the TF the Bot is running on; so that is also fine.

But When I add Ra500 to the ST500 line, like below, it fails and mentioned an overload as only wants to see 2 arguments.

ST500 = Indicators.Supertrend(Ra500, 10, 3.0);

(If I change the indicator to for example a Moving Average like: ST500 = Indicators.MovingAverage(Ra500.ClosePrices, 10, MovingAverageType.Exponential);, no error messages displayed. So seems issue with Supertrend, or I misconfigure it..)

I also got it working if I download the custom Supertrend indicator that can be found in the Algorithms section, but I rather use the standard one located in cTrader.

Ps. I add the code to OnStart, so I can test this in the weekend, as we cannot Backtest RangeBar data..

Thanks in advance!

//#reference: ..\Indicators\DSS Bressert.algo
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.None)]
    public class RangeBarMTFtest : Robot
    {
        private DSSBressert DSS;

        private Supertrend ST;
        private Supertrend ST500;

        private Bars Ra500;

        protected override void OnStart()
        {
            Ra500 = MarketData.GetBars(TimeFrame.Range500);

            DSS = Indicators.GetIndicator<DSSBressert>(Ra500, 13, 8, 8);

            ST = Indicators.Supertrend(10, 3.0);

            ST500 = Indicators.Supertrend(Ra500, 10, 3.0);

 

Hi,

The built-in super trend indicator doesn't support multiple time frames, you can only use if for the current time frame.

If you want to use super trend on another time frame then you have to develop a custom version by yourself, you can find some examples on site if you search.


@amusleh

ahmadtrader448
16 Jan 2024, 09:37 ( Updated at: 17 Jan 2024, 06:31 )

get movingaverages on histogram

hello guys,

I calculated histograms over the higher timeframe of 15 minutes timeframe and fitted them on a lower timeframe of 5 minutes,

Is there any way to get a moving average on the higher timeframe histograms of 15 minutes on a lower timeframe of 5 minutes?

MAson15Min_hist      = Indicators.MovingAverage(15Min_hist , MAsonhistPeriod  , MAsonhistMethod);

 

 

 

 


@ahmadtrader448

PanagiotisCharalampous
17 Jan 2024, 06:59

RE: get movingaverages on histogram

ahmadtrader448 said: 

hello guys,

I calculated histograms over the higher timeframe of 15 minutes timeframe and fitted them on a lower timeframe of 5 minutes,

Is there any way to get a moving average on the higher timeframe histograms of 15 minutes on a lower timeframe of 5 minutes?

MAson15Min_hist      = Indicators.MovingAverage(15Min_hist , MAsonhistPeriod  , MAsonhistMethod);

 

 

 

 

Hi Ahmad,

What is stopping you from doing so? The code sample you have shared should have more or less work, if the data source you pass to the indicator is correct. 

Best regards,

Panagiotis


@PanagiotisCharalampous

ahmadtrader448
17 Jan 2024, 10:15

RE: RE: get movingaverages on histogram

PanagiotisCharalampous said: 

ahmadtrader448 said: 

Hi Panagiotis, 

thanks for supporting me, to be specific I wanna get the moving average on the Histogram time series which is calculated on higher timeframes such as (15 minutes) on a lower timeframe chart (5 Min), I got the histogram time series on a higher timeframe(15 minutes)  correct, but when trying to get Moving averages on that histogram not return the correct data values ( data values of Movingaverage on 15 Min Histograme on lower time frame chart (5 min) not equal  data values of Movingaverage on 15 Min Histograme on higher timeframe chart (15 min) ), and to be more specific I will set part of my code to check my processes.

all processes return correct data values, expect Movingaverages  on Histogram, Knowing as i drop that indicator 2 time first time on 5 minutes chart ana second time on 15 minutes chart

//-----------------------------------------------------------------------------------------------------------------------------------------

// import required libraries
//-------------------------- 
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using cAlgo.API;
using cAlgo.API.Collections;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

// Main Function 
namespace cAlgo
{
    
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None ,AutoRescale = false)]
    public class MAsON_MTFHistograms : Indicator
    {
        // Get Bars for MTFs Histogram Field prices:
        private Bars baseBarsMTFHistogramFP   ;
        // Get Bars for MTFs Histogram Movingaverages:
        private Bars baseBarsMTFHistogramMAs  ;
        //-------------------------------------------------
        //-------------------------------------------------
        // TFs Selector Paramters ::
        [Parameter("MTFs", DefaultValue = "Minute15", Group = "MTF Histogram Calcu Paramters")]
        public TimeFrame TFS { get; set; }

        // MTFS Histograms Field Prices Selector ::      
        [Parameter("MTF Histogram Applied Price", DefaultValue = FPs.Close,Group = "MTF Histogram Calcu Paramters")]
        public FPs MTFHistogramFP { get; set; }
        // MTFs Histogram MAs Methods:
        [Parameter("MTF Histogram MAs Method"   , DefaultValue = MovingAverageType.Simple, Group = "MTF Histogram Calcu Paramters")]   
        public MovingAverageType MTFHistogramMAsMethod { get; set; }
        //   MTFs Histogram MAs Field Price:
        [Parameter("MTF Histogram MAs FP"       , DefaultValue = DataSeriesType.Close,Group = "MTF Histogram Calcu Paramters")]
        public DataSeriesType MTFHistogramMAsFP { get; set; }
        //   MTFs Histogram MAs Periodicity:
        [Parameter("MTF Histogram MAs Period"   , DefaultValue = 14, MinValue = 1, Group = "MTF Histogram Calcu Paramters")]
        public int MTFHistogramMAsPeriod { get; set; }
        //-------------------------------------------------------------------------------------
        //-------------------------------------------------------------------------------------
        //   MAs on MTFs Histograms Method  : 
        [Parameter("MAs on MTFHistogram Method", DefaultValue = MovingAverageType.Simple, Group = "MAs on MTF Histogram Calcu Paramters")]   
        public MovingAverageType MAsonMTFHistogramMethod { get; set; }
        //   MAs on MTFs Histograms Periodicity  : 
        [Parameter("MAs on MTFHistogram Period", DefaultValue = 14, MinValue = 1, Group = "MAs on MTF Histogram Calcu Paramters")]
        public int MAsonMTFHistogramPeriod { get; set; }
        //-----------------------------------------------------------------------------------------------------
        //-----------------------------------------------------------------------------------------------------
        // Out Put VAloies to precient values :
        [Output("Validate_Values"  , LineColor = "Green", PlotType = PlotType.Line, Thickness = 3)]
        public IndicatorDataSeries Validate_Values { get; set; }
//================================================================================================ 
        // MTFHistogram  MAs intialization as Movingaverages :
        private MovingAverage MTFHistogramMAs;
        // MTFHistogram intialization as DataSeries :
        private IndicatorDataSeries MTFHistogram;
        // MTFHistogram intialization as Movingaverages :
        private MovingAverage MAsonMTFHistogram;
//================================================================================================ 
        protected override void Initialize()
        {
            // Get Bars MTFS Histograms Field prices:
            baseBarsMTFHistogramFP    = MarketData.GetBars(TFS);
            // Get Bars MTFS Histograms Moving averages :
            baseBarsMTFHistogramMAs  = MarketData.GetBars(TFS);
            var baseSeriesDevMAsBTFs = GetBaseSeriesMTFHistogramMAs();
            MTFHistogramMAs  = Indicators.MovingAverage(baseSeriesDevMAsBTFs    , MTFHistogramMAsPeriod , MTFHistogramMAsMethod);
            // MTFs MAs onDev calcu 
            MTFHistogram         = CreateDataSeries();
            MAsonMTFHistogram    = Indicators.MovingAverage(MTFHistogram  , MAsonMTFHistogramPeriod  , MAsonMTFHistogramMethod);
        }
//================================================================================================ 
        public override void Calculate(int i)
        {
            
            // MTFs DevFPs 
            var MTFHIstogramFPindx   = baseBarsMTFHistogramFP.OpenTimes.GetIndexByTime(Bars.OpenTimes[i]);
            var MTFHIstogramFPBTF_Val = 0.0;
             switch (MTFHistogramFP)
             {
                 case FPs.Open:
                    MTFHIstogramFPBTF_Val =  baseBarsMTFHistogramFP.OpenPrices[MTFHIstogramFPindx] ;
                    break;
                 case FPs.High:
                    MTFHIstogramFPBTF_Val =  baseBarsMTFHistogramFP.HighPrices[MTFHIstogramFPindx];
                    break;
                 case FPs.Low:
                    MTFHIstogramFPBTF_Val =  baseBarsMTFHistogramFP.LowPrices[MTFHIstogramFPindx] ;
                    break;
                 case FPs.Close:
                    MTFHIstogramFPBTF_Val =  baseBarsMTFHistogramFP.ClosePrices[MTFHIstogramFPindx] ;
                    break;  
             }
            //----------------------------------------------------------------------------------------------
            // MTFs Histogram CAlculations :
            var MTFHIstogramMAsindx    = baseBarsMTFHistogramMAs.OpenTimes.GetIndexByTime(Bars.OpenTimes[i]);
            MTFHistogram[i]            = MTFHIstogramFPBTF_Val  - MTFHistogramMAs.Result[MTFHIstogramMAsindx];
            // MAs on MTF HIstograms Calcu ::
            Validate_Values[i]         = MAsonMTFHistogram.Result[i];
            //-----------------------------------------------------------------------------------------------

        } // End of the Processes function ::
//================================================================================================ 
        // Get Field Prices Based on Drop down list of Field Prices paramters :
        //---------------------------------
        private DataSeries GetBaseSeriesMTFHistogramMAs()
        {
            switch (MTFHistogramMAsFP)
            {
                case DataSeriesType.Open:
                    return baseBarsMTFHistogramMAs.OpenPrices;
                    
                case DataSeriesType.High:
                    return baseBarsMTFHistogramMAs.HighPrices;

                case DataSeriesType.Low:
                    return baseBarsMTFHistogramMAs.LowPrices;

                case DataSeriesType.Close:
                    return baseBarsMTFHistogramMAs.ClosePrices;
                default:

                    throw new ArgumentOutOfRangeException("DataSeriesType");
            }
        }
//================================================================================================ 

    } // End
//================================================================================================ 
//================================================================================================ 
     // drop down list fo FPs:
     public enum DataSeriesType
     {
         Open,
         High,
         Low,
         Close
     }
    //-------------------------
     // drop down list fo FPs:
     public enum FPs
     {
         Open,
         High,
         Low,
         Close
     }
    //-------------------------
}

//------------------------------------------------------------------------------------------------------------------------------------------

 

Best regards,

Ahmad

 


@ahmadtrader448