Replies

kabbajjad
08 May 2025, 17:35

RE: MTF Custom Indicator

firemyst said: 

To start, you do need to get the Bars data for every other time frame you want that isn't the chart's timeframe:

Bars _marketSeries = MarketData.GetBars(SourceTimeFrame, Symbol.Name);

 

Then, in your calculate method, you need to get the latest information from that/those timeframe(s):

int altIndex = index;
if (Bars.TimeFrame != _marketSeries.TimeFrame)
{
   altIndex = _marketSeries.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);
}

 

Then get the values you want using that altIndex Some examples with the moving average and standard deviation:

 

double maResultIndex = _movingAverage.Result[altIndex];
double sd = StandardDeviation * _standardDeviation.Result[altIndex];

 

Hello, Thank you for your response.

However I still have the same problem, could you tell me if that part of the code I added looks correct. The panel still gives me a correct value for the current Timeframe that I have on the chart but the values are wrong for the other Timeframes.

Ex : Image 1 (displayed on the 1m timeframe) we have a correct value for m1 but wrong value for m5 (arrow down that should be up). Image 2 I switched to m5 and you can see that now the arrow for m5 switched to bullish (correct value because price > blue line)

 



 

 

Here's my full code : 
using System;
using System.Collections.Generic;
using System.Text;
using cAlgo.API;

namespace cAlgo
{
    [Indicator(IsOverlay = true, AccessRights = AccessRights.None)]
    public class MultiTimeframeSwingPanel : Indicator
    {
        [Parameter("Swing Point Period", DefaultValue = 5, MinValue = 1, MaxValue = 50)]
        public int Period { get; set; }

        private Dictionary<TimeFrame, double> CenterLine;
        private Dictionary<Bars, string> TimeframeLabels;

        private Bars m1TF, m5TF, m15TF, m30TF, h1TF, h4TF, d1TF, w1TF;

        private string lastString;

        protected override void Initialize()
        {
            lastString = "start";
            // Initialize all center‑lines to NaN
            CenterLine = new Dictionary<TimeFrame, double>();

            m1TF = MarketData.GetBars(TimeFrame.Minute, Symbol.Name);
            m5TF = MarketData.GetBars(TimeFrame.Minute5, Symbol.Name);
            m15TF = MarketData.GetBars(TimeFrame.Minute15, Symbol.Name);
            m30TF = MarketData.GetBars(TimeFrame.Minute30, Symbol.Name);
            h1TF = MarketData.GetBars(TimeFrame.Hour, Symbol.Name);
            h4TF = MarketData.GetBars(TimeFrame.Hour4, Symbol.Name);
            d1TF = MarketData.GetBars(TimeFrame.Daily, Symbol.Name);
            w1TF = MarketData.GetBars(TimeFrame.Weekly, Symbol.Name);

            // Initialize timeframe labels
            TimeframeLabels = new Dictionary<Bars, string>
            {
                { m1TF, "M1" },
                { m5TF, "M5" },
                { m15TF, "M15" },
                { m30TF, "M30" },
                { h1TF, "H1" },
                { h4TF, "H4" },
                { d1TF, "D1" },
                { w1TF, "W1" }
            };

            // Initialize center lines
            foreach (var tf in TimeframeLabels.Keys)
            {
                CenterLine[tf.TimeFrame] = double.NaN;
            }
        }

        public override void Calculate(int index)
        {
            var sb = new StringBuilder();

            foreach (var tfPair in TimeframeLabels)
            {
                var tfBars = tfPair.Key;
                var label = tfPair.Value;

                int altIndex = index;
                if (Bars.TimeFrame != tfBars.TimeFrame)
                {
                    altIndex = tfBars.OpenTimes.GetIndexByTime(Bars.OpenTimes[index]);
                }


                int pivotIndex = altIndex - Period;

                // 1) Detect pivot high
                bool isHigh = true;
                for (int i = 1; i <= Period; i++)
                {
                    if (tfBars.HighPrices[pivotIndex] <= tfBars.HighPrices[pivotIndex - i] ||
                        tfBars.HighPrices[pivotIndex] <= tfBars.HighPrices[pivotIndex + i])
                    {
                        isHigh = false;
                        break;
                    }
                }

                // 2) Update that TF's center‑line
                double lastPivotPoint = isHigh
                    ? tfBars.HighPrices[pivotIndex]
                    : double.NaN;

                double prevCL = CenterLine[tfBars.TimeFrame];
                double currCL = double.IsNaN(prevCL)
                    ? lastPivotPoint
                    : (double.IsNaN(lastPivotPoint)
                        ? prevCL
                        : (prevCL * 2 + lastPivotPoint) / 3);

                CenterLine[tfBars.TimeFrame] = currCL;

                double lastClose = tfBars.ClosePrices[altIndex];
                bool bullish = lastClose > currCL;
                string arrow = bullish ? "↑" : "↓";
                sb.AppendLine($"{label}: {arrow}");
            }


            Chart.RemoveObject("mtfPanel");
            Chart.DrawStaticText(
                "mtfPanel",
                sb.ToString(),
                VerticalAlignment.Top,
                HorizontalAlignment.Right,
                Color.White
            );
        }
    }
}


I appreciate your help !
Best regards,
Jad


@kabbajjad

kabbajjad
24 Apr 2025, 23:19

RE: RE:

Update here it worked perfectly. Try to limit it to a set amount of objects and delete the previous ones!

kabbajjad said: 

Thanks I will test that and update you!

claudiorubbiani said: 

You can invoke the Chart.RemoveAllObjects() to have everything deleted in one shot.

I would limit the number of objects drawn on the chart during backtesting.

 

Ciao,

Claudio

 

 


@kabbajjad

kabbajjad
11 Mar 2025, 09:54

RE:

Thanks I will test that and update you!

claudiorubbiani said: 

You can invoke the Chart.RemoveAllObjects() to have everything deleted in one shot.

I would limit the number of objects drawn on the chart during backtesting.

 

Ciao,

Claudio

 


@kabbajjad

kabbajjad
09 Mar 2025, 16:20 ( Updated at: 10 Mar 2025, 09:11 )

RE: RE: For developers

Hello, 
if you are interested for some coding help, I offer my services.  :D

 

 

CharlieRoy said: 

firemyst said: 

Use Visual Studio, Visual Studio Code, or some other development platform to compile the code. You can easily copy error messages from them.

 

Or perhaps just read the error message, try to comprehend it, and fix yourself? 

 

AI isn't the be all end all 🤪

Yeah will do. MT4/5's MetaEditor allows me to copy basic text error messages, I think cTraders Build Result window is in Java or some other script which surprisingly does not allow simple copy and paste. Essential for coding with AI.. which is here to stay. If I could afford to hire someone I would! Like the cBot / Algo backtesting section a lot. Thankd. 

 

 


@kabbajjad