Advertisement IC Markets

Timeframe Should Match Your Reaction Speed, Not Your Ambition

Master exponential money management, position sizing calculators, strict daily stop-loss limits, and overcoming FOMO on micro-timeframes.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Timeframe Should Match Your Reaction Speed, Not Your Ambition

Post by PTScalper »

1. MetaTrader 5 (MQL5) Version

Save as an Indicator (.mq5). It uses MT5's PeriodSeconds() and iTime structure for precise real-time state management.

Code: Select all

//+------------------------------------------------------------------+
//|                                          ExecutionAnchor_MT5.mq5 |
//|                                     Mindful Scalping UI Overlay  |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property indicator_plots 0

//--- Inputs
input color InpColorFast   = clrMaroon;
input color InpColorOpt    = clrTeal;
input color InpColorMacro  = clrNavy;
input color InpColorText   = clrWhite;

//--- Object Names
string obj_bg = "ExecAnchor_BG";
string obj_header = "ExecAnchor_Header";
string obj_timer = "ExecAnchor_Timer";
string obj_body1 = "ExecAnchor_Body1";
string obj_body2 = "ExecAnchor_Body2";
string obj_body3 = "ExecAnchor_Body3";

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   EventSetTimer(1); // 1-second tick for the timer
   CreateUI();
   UpdateDashboard();
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   EventKillTimer();
   ObjectsDeleteAll(0, "ExecAnchor_");
   ChartRedraw();
  }

//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
  {
   return(rates_total);
  }

//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   UpdateDashboard();
  }

//+------------------------------------------------------------------+
//| Core Logic & UI Updates                                          |
//+------------------------------------------------------------------+
void UpdateDashboard()
  {
   int tfMinutes = PeriodSeconds(_Period) / 60;
   color stateColor = InpColorMacro;
   
   string headerStr = "";
   string b1 = "", b2 = "", b3 = "";

   // Determine State
   if(tfMinutes < 5)
     {
      stateColor = InpColorFast;
      headerStr = "⚠️ RUSHED EXECUTION ZONE (" + EnumToString(_Period) + ")";
      b1 = "There is no prize for the fastest timeframe.";
      b2 = "If you are second-guessing entries or missing closes,";
      b3 = "drop to a slower chart where you can think clearly.";
     }
   else if(tfMinutes >= 5 && tfMinutes <= 15)
     {
      stateColor = InpColorOpt;
      headerStr = "✅ CLEAN EXECUTION ZONE (" + EnumToString(_Period) + ")";
      b1 = "Match execution to actual processing speed.";
      b2 = "Focus on clean, consistent decisions without";
      b3 = "the rushed pressure of micro-timeframes.";
     }
   else
     {
      stateColor = InpColorMacro;
      headerStr = "📘 MACRO CONTEXT ZONE (" + EnumToString(_Period) + ")";
      b1 = "Higher timeframes dictate structural bias.";
      b2 = "Ensure your execution timeframe aligns with";
      b3 = "your demonstrated reaction speed.";
     }

   // Timer Calculation
   datetime currentCandleOpen = iTime(_Symbol, _Period, 0);
   datetime nextCandleOpen = currentCandleOpen + PeriodSeconds(_Period);
   int secondsRemaining = (int)(nextCandleOpen - TimeCurrent());
   
   string timerStr = "Market Closed";
   if(secondsRemaining > 0)
     {
      int h = secondsRemaining / 3600;
      int m = (secondsRemaining % 3600) / 60;
      int s = secondsRemaining % 60;
      timerStr = StringFormat("Candle Close: %02d:%02d:%02d", h, m, s);
     }

   // Update Objects
   ObjectSetInteger(0, obj_bg, OBJPROP_BGCOLOR, stateColor);
   ObjectSetString(0, obj_header, OBJPROP_TEXT, headerStr);
   ObjectSetString(0, obj_timer, OBJPROP_TEXT, timerStr);
   ObjectSetString(0, obj_body1, OBJPROP_TEXT, b1);
   ObjectSetString(0, obj_body2, OBJPROP_TEXT, b2);
   ObjectSetString(0, obj_body3, OBJPROP_TEXT, b3);
   
   ChartRedraw();
  }

//+------------------------------------------------------------------+
//| UI Generation                                                    |
//+------------------------------------------------------------------+
void CreateUI()
  {
   int x = 20, y = 20;
   
   // Background
   ObjectCreate(0, obj_bg, OBJ_RECTANGLE_LABEL, 0, 0, 0);
   ObjectSetInteger(0, obj_bg, OBJPROP_CORNER, CORNER_RIGHT_LOWER);
   ObjectSetInteger(0, obj_bg, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, obj_bg, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, obj_bg, OBJPROP_XSIZE, 350);
   ObjectSetInteger(0, obj_bg, OBJPROP_YSIZE, 110);
   ObjectSetInteger(0, obj_bg, OBJPROP_COLOR, clrNONE);
   ObjectSetInteger(0, obj_bg, OBJPROP_BACK, true);

   // Text Creation Macro
   CreateText(obj_header, x + 10, y + 80, 10, true);
   CreateText(obj_timer, x + 10, y + 60, 10, true);
   CreateText(obj_body1, x + 10, y + 40, 8, false);
   CreateText(obj_body2, x + 10, y + 25, 8, false);
   CreateText(obj_body3, x + 10, y + 10, 8, false);
  }

void CreateText(string name, int x, int y, int fontSize, bool isBold)
  {
   ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
   ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_LOWER);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
   ObjectSetString(0, name, OBJPROP_FONT, "Consolas");
   ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);
   ObjectSetInteger(0, name, OBJPROP_COLOR, InpColorText);
   ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
  }
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Recommended broker for automated trading & scalping IC Markets
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Timeframe Should Match Your Reaction Speed, Not Your Ambition

Post by PTScalper »

2. MetaTrader 4 (MQL4) Version

Save as an Indicator (.mq4). MT4 requires Period() (which returns minutes natively) and slightly different parameter signatures for ObjectCreate().

Code: Select all

//+------------------------------------------------------------------+
//|                                          ExecutionAnchor_MT4.mq4 |
//|                                     Mindful Scalping UI Overlay  |
//+------------------------------------------------------------------+
#property indicator_chart_window
#property strict

//--- Inputs
input color InpColorFast   = clrMaroon;
input color InpColorOpt    = clrTeal;
input color InpColorMacro  = clrNavy;
input color InpColorText   = clrWhite;

//--- Object Names
string obj_bg = "ExecAnchor_BG";
string obj_header = "ExecAnchor_Header";
string obj_timer = "ExecAnchor_Timer";
string obj_body1 = "ExecAnchor_Body1";
string obj_body2 = "ExecAnchor_Body2";
string obj_body3 = "ExecAnchor_Body3";

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   EventSetTimer(1); 
   CreateUI();
   UpdateDashboard();
   return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason)
  {
   EventKillTimer();
   ObjectsDeleteAll(0, "ExecAnchor_");
   WindowRedraw();
  }

int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[])
  {
   return(rates_total);
  }

void OnTimer()
  {
   UpdateDashboard();
  }

//+------------------------------------------------------------------+
//| Core Logic & UI Updates                                          |
//+------------------------------------------------------------------+
void UpdateDashboard()
  {
   int tfMinutes = Period(); // Returns exactly minutes in MT4
   color stateColor = InpColorMacro;
   
   string headerStr = "";
   string b1 = "", b2 = "", b3 = "";

   // Determine State
   if(tfMinutes < 5)
     {
      stateColor = InpColorFast;
      headerStr = "⚠️ RUSHED EXECUTION (" + IntegerToString(tfMinutes) + "M)";
      b1 = "There is no prize for the fastest timeframe.";
      b2 = "If you are second-guessing entries or missing closes,";
      b3 = "drop to a slower chart where you can think clearly.";
     }
   else if(tfMinutes >= 5 && tfMinutes <= 15)
     {
      stateColor = InpColorOpt;
      headerStr = "✅ CLEAN EXECUTION (" + IntegerToString(tfMinutes) + "M)";
      b1 = "Match execution to actual processing speed.";
      b2 = "Focus on clean, consistent decisions without";
      b3 = "the rushed pressure of micro-timeframes.";
     }
   else
     {
      stateColor = InpColorMacro;
      headerStr = "📘 MACRO CONTEXT (" + IntegerToString(tfMinutes) + "M)";
      b1 = "Higher timeframes dictate structural bias.";
      b2 = "Ensure your execution timeframe aligns with";
      b3 = "your demonstrated reaction speed.";
     }

   // Timer Calculation
   datetime currentCandleOpen = iTime(Symbol(), Period(), 0);
   datetime nextCandleOpen = currentCandleOpen + (Period() * 60);
   int secondsRemaining = (int)(nextCandleOpen - TimeCurrent());
   
   string timerStr = "Market Closed";
   if(secondsRemaining > 0)
     {
      int h = secondsRemaining / 3600;
      int m = (secondsRemaining % 3600) / 60;
      int s = secondsRemaining % 60;
      timerStr = StringFormat("Candle Close: %02d:%02d:%02d", h, m, s);
     }

   // Update Objects
   ObjectSetInteger(0, obj_bg, OBJPROP_BGCOLOR, stateColor);
   ObjectSetString(0, obj_header, OBJPROP_TEXT, headerStr);
   ObjectSetString(0, obj_timer, OBJPROP_TEXT, timerStr);
   ObjectSetString(0, obj_body1, OBJPROP_TEXT, b1);
   ObjectSetString(0, obj_body2, OBJPROP_TEXT, b2);
   ObjectSetString(0, obj_body3, OBJPROP_TEXT, b3);
   
   WindowRedraw();
  }

//+------------------------------------------------------------------+
//| UI Generation                                                    |
//+------------------------------------------------------------------+
void CreateUI()
  {
   int x = 20, y = 20;
   
   ObjectCreate(0, obj_bg, OBJ_RECTANGLE_LABEL, 0, 0, 0);
   ObjectSetInteger(0, obj_bg, OBJPROP_CORNER, CORNER_RIGHT_LOWER);
   ObjectSetInteger(0, obj_bg, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, obj_bg, OBJPROP_YDISTANCE, y);
   ObjectSetInteger(0, obj_bg, OBJPROP_XSIZE, 350);
   ObjectSetInteger(0, obj_bg, OBJPROP_YSIZE, 110);
   ObjectSetInteger(0, obj_bg, OBJPROP_COLOR, clrNONE);
   ObjectSetInteger(0, obj_bg, OBJPROP_BACK, true);

   CreateText(obj_header, x + 10, y + 80, 10);
   CreateText(obj_timer, x + 10, y + 60, 10);
   CreateText(obj_body1, x + 10, y + 40, 8);
   CreateText(obj_body2, x + 10, y + 25, 8);
   CreateText(obj_body3, x + 10, y + 10, 8);
  }

void CreateText(string name, int x, int y, int fontSize)
  {
   ObjectCreate(0, name, OBJ_LABEL, 0, 0, 0);
   ObjectSetInteger(0, name, OBJPROP_CORNER, CORNER_RIGHT_LOWER);
   ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
   ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
   ObjectSetString(0, name, OBJPROP_FONT, "Consolas");
   ObjectSetInteger(0, name, OBJPROP_FONTSIZE, fontSize);
   ObjectSetInteger(0, name, OBJPROP_COLOR, InpColorText);
   ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
  }
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Timeframe Should Match Your Reaction Speed, Not Your Ambition

Post by PTScalper »

For cTrader, indicators use C# and natively support UI overlays via the Chart.CreateUIElement() panel architecture or direct canvas drawing.

This professional cTrader Indicator (ExecutionAnchor.cs) builds a clean, hardware-accelerated WPF-style control panel directly on your chart canvas. It includes dynamic color states, real-time candle close countdowns, and updates smoothly every second using timer events.

cTrader Indicator (C# / cBot & Indicator API)

Create a new Indicator in cTrader Automate, paste this code, and compile:

Code: Select all

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

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class ExecutionAnchor : Indicator
    {
        [Parameter("Position", DefaultValue = ControlPosition.BottomRight)]
        public ControlPosition DashboardPosition { get; set; }

        [Parameter("Danger Zone Color (< 5m)", DefaultValue = "Maroon")]
        public string ColorFast { get; set; }

        [Parameter("Optimal Zone Color (5m - 15m)", DefaultValue = "Teal")]
        public string ColorOpt { get; set; }

        [Parameter("Macro Zone Color (> 15m)", DefaultValue = "Navy")]
        public string ColorMacro { get; set; }

        private Border _mainBorder;
        private TextBlock _headerText;
        private TextBlock _timerText;
        private TextBlock _bodyText1;
        private TextBlock _bodyText2;
        private TextBlock _bodyText3;

        protected override void Initialize()
        {
            // Build Panel Layout Container
            var panel = new StackPanel
            {
                Orientation = Orientation.Vertical,
                Spacing = 4,
                Margin = new Thickness(10)
            };

            _headerText = new TextBlock
            {
                FontWeight = FontWeight.Bold,
                FontSize = 11,
                ForegroundColor = Color.White
            };

            _timerText = new TextBlock
            {
                FontWeight = FontWeight.Bold,
                FontSize = 11,
                ForegroundColor = Color.Cyan
            };

            _bodyText1 = new TextBlock { FontSize = 10, ForegroundColor = Color.LightGray };
            _bodyText2 = new TextBlock { FontSize = 10, ForegroundColor = Color.LightGray };
            _bodyText3 = new TextBlock { FontSize = 10, ForegroundColor = Color.LightGray };

            panel.AddChild(_headerText);
            panel.AddChild(_timerText);
            panel.AddChild(new TextBlock { Text = "" }); // Spacer
            panel.AddChild(_bodyText1);
            panel.AddChild(_bodyText2);
            panel.AddChild(_bodyText3);

            _mainBorder = new Border
            {
                Child = panel,
                BackgroundColor = Color.FromHex(ColorMacro),
                Opacity = 0.85,
                Padding = new Thickness(10),
                CornerRadius = new CornerRadius(4),
                HorizontalAlignment = HorizontalAlignment.Right,
                VerticalAlignment = VerticalAlignment.Bottom
            };

            // Bind to Chart UI
            Chart.AddControl(_mainBorder);
            
            // Register Timer for 1-second interval countdown updates
            Timer.Start(1);
        }

        public override void Calculate(int index)
        {
            // Only update logic on the last bar or tick equivalent
            if (index == Bars.Count - 1)
            {
                UpdateDashboardData();
            }
        }

        protected override void OnTimer()
        {
            UpdateDashboardData();
        }

        private void UpdateDashboardData()
        {
            // Determine Timeframe Duration in Minutes
            int tfMinutes = 1;
            var tf = TimeFrame;
            
            if (tf == TimeFrame.Minute) tfMinutes = 1;
            else if (tf == TimeFrame.Minute2) tfMinutes = 2;
            else if (tf == TimeFrame.Minute3) tfMinutes = 3;
            else if (tf == TimeFrame.Minute4) tfMinutes = 4;
            else if (tf == TimeFrame.Minute5) tfMinutes = 5;
            else if (tf == TimeFrame.Minute10) tfMinutes = 10;
            else if (tf == TimeFrame.Minute15) tfMinutes = 15;
            else if (tf == TimeFrame.Minute30) tfMinutes = 30;
            else if (tf == TimeFrame.Hour) tfMinutes = 60;
            else if (tf == TimeFrame.Hour4) tfMinutes = 240;
            else if (tf == TimeFrame.Daily) tfMinutes = 1440;
            else tfMinutes = (int)tf.ToTimeSpan().TotalMinutes;

            string tfName = tf.ToString();
            
            // State Logic
            if (tfMinutes < 5)
            {
                _mainBorder.BackgroundColor = Color.FromHex("#8B0000"); // Dark Red / Maroon
                _headerText.Text = $"⚠️ RUSHED EXECUTION ZONE ({tfName})";
                _bodyText1.Text = "There is no prize for the fastest timeframe.";
                _bodyText2.Text = "If you are second-guessing entries or missing closes,";
                _bodyText3.Text = "drop to a slower chart where you can think clearly.";
            }
            else if (tfMinutes >= 5 && tfMinutes <= 15)
            {
                _mainBorder.BackgroundColor = Color.FromHex("#008080"); // Teal
                _headerText.Text = $"✅ CLEAN EXECUTION ZONE ({tfName})";
                _bodyText1.Text = "Match execution to actual processing speed.";
                _bodyText2.Text = "Focus on clean, consistent decisions without";
                _bodyText3.Text = "the rushed pressure of micro-timeframes.";
            }
            else
            {
                _mainBorder.BackgroundColor = Color.FromHex("#000080"); // Navy
                _headerText.Text = $"📘 MACRO CONTEXT ZONE ({tfName})";
                _bodyText1.Text = "Higher timeframes dictate structural bias.";
                _bodyText2.Text = "Ensure your execution timeframe aligns with";
                _bodyText3.Text = "your demonstrated reaction speed.";
            }

            // Real-time Candle Close Countdown Calculation
            DateTime currentBarOpenTime = Bars.OpenTimes[Bars.Count - 1];
            DateTime nextBarOpenTime = currentBarOpenTime.Add(tf.ToTimeSpan());
            TimeSpan timeRemaining = nextBarOpenTime - Server.Time;

            if (timeRemaining.TotalSeconds > 0)
            {
                _timerText.Text = $"Candle Close: {timeRemaining.Hours:D2}:{timeRemaining.Minutes:D2}:{timeRemaining.Seconds:D2}";
            }
            else
            {
                _timerText.Text = "Candle Close: Synchronizing...";
            }
        }

        protected override void OnStop()
        {
            if (_mainBorder != null)
            {
                Chart.RemoveControl(_mainBorder);
            }
        }
    }
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3349
Joined: Mon Jul 20, 2026 1:28 pm

Re: Timeframe Should Match Your Reaction Speed, Not Your Ambition

Post by PTScalper »

Architectural Highlights:

Native WPF Layout Engine: cTrader handles containers (StackPanel, Border) natively, ensuring crisp text rendering that scales cleanly without artifacts during chart panning or zooming.

Dual Update Lifecycle: Combines standard indicator calculation triggers with a robust Timer.Start(1) thread hook, ensuring the candle close countdown updates every single second even on illiquid instruments or flat markets.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Post Reply