Advertisement IC Markets

Invalidation rules on GBPUSD M15 before entry

Discuss 1-minute to 15-minute price action setups, fading intraday momentum, key support/resistance zones, and proven short-term trading methodologies.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: Invalidation rules on GBPUSD M15 before entry

Post by PTScalper »

Institutional Workflow in MetaTrader:

Apply the Indicator: Drag the indicator onto your GBPUSD chart.

The Hard Stop: It will overlay in the bottom right corner showing LOCKED (AWAITING INPUT). It will not calculate anything. It protects you from yourself.

Arming the Trade: When you find your M15 invalidation, press Ctrl + I (Indicator List), double-click the indicator, and type the exact price into the InvalPrice input field.

The HUD Comes Alive: The dashboard instantly flips to ARMED in green. It factors in your live Bid/Ask spread, queries the exact dollar-value of a pip from your broker server, normalizes it to your broker's lot stepping (e.g., 0.01), and prints the exact Execution Lot Size on your screen.

If the distance requires a size below 0.01 to maintain your 1% risk rule, the HUD flashes red with VIOLATION (< MIN LOT). At that point, process dictates you close the chart and walk away.
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: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: Invalidation rules on GBPUSD M15 before entry

Post by PTScalper »

cTrader is arguably the most advanced platform for strict, process-driven execution because it uses modern C# (.NET) and a built-in WPF UI framework. Unlike MetaTrader’s clunky floating text, cTrader allows us to build a seamless, native institutional dashboard directly onto the chart canvas. Furthermore, cTrader calculates cross-currency pip values and standard lots automatically through its native Symbol object—no manual JPY conversions required.

Here is the C# code for cTrader Automate.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: Invalidation rules on GBPUSD M15 before entry

Post by PTScalper »

cTrader (cAlgo) - Institutional Execution Engine

1.) Open cTrader and navigate to the Automate tab (left sidebar).

2.) Click New Indicator, name it InstitutionalRiskEngine.

3.) Replace all the default code with the C# block below, then click Build (or press F6).
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: Invalidation rules on GBPUSD M15 before entry

Post by PTScalper »

Ctrader pro level code

Code: Select all

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 InstitutionalRiskEngine : Indicator
    {
        // =========================================================================
        // INPUTS: STRICT ENTRY PROTOCOL
        // =========================================================================
        [Parameter("Invalidation Price (0 = Locked)", Group = "1. Hard Execution", DefaultValue = 0.0)]
        public double InvalPrice { get; set; }

        [Parameter("Target Price", Group = "1. Hard Execution", DefaultValue = 0.0)]
        public double TargetPrice { get; set; }

        [Parameter("Spread + Slippage Est (Pips)", Group = "1. Hard Execution", DefaultValue = 1.2)]
        public double SpreadEst { get; set; }

        [Parameter("Risk Exposure (%)", Group = "2. Capital Allocation", DefaultValue = 1.0)]
        public double RiskPct { get; set; }

        // =========================================================================
        // UI COMPONENTS
        // =========================================================================
        private TextBlock _statusValue;
        private TextBlock _invalValue;
        private TextBlock _riskValue;
        private TextBlock _lotValue;
        private TextBlock _rrValue;

        protected override void Initialize()
        {
            // Build the sterile, native HUD
            var border = new Border
            {
                BorderColor = Color.FromArgb(255, 30, 30, 30),
                BorderThickness = new Thickness(2),
                BackgroundColor = Color.FromArgb(240, 15, 15, 15),
                HorizontalAlignment = HorizontalAlignment.Right,
                VerticalAlignment = VerticalAlignment.Bottom,
                Margin = new Thickness(20)
            };

            var mainPanel = new StackPanel { Orientation = Orientation.Vertical, Margin = new Thickness(10) };

            mainPanel.AddChild(CreateRow("SYSTEM STATUS", out _statusValue));
            mainPanel.AddChild(CreateRow("M15 Invalidation Node", out _invalValue));
            mainPanel.AddChild(CreateRow("Stop (Pips + Spread)", out _riskValue));
            mainPanel.AddChild(CreateRow("Execution Size (Lots)", out _lotValue));
            mainPanel.AddChild(CreateRow("Net Expectancy", out _rrValue));

            var vocalizeText = new TextBlock 
            { 
                Text = "[ VOCALIZE PARAMETERS BEFORE CLICKING ]", 
                ForegroundColor = Color.DimGray, 
                Margin = new Thickness(0, 10, 0, 0),
                TextAlignment = TextAlignment.Center
            };
            mainPanel.AddChild(vocalizeText);

            border.Child = mainPanel;
            Chart.AddControl(border);
        }

        public override void Calculate(int index)
        {
            // Only calculate risk variables on the live ticker
            if (!IsLastBar) return;

            bool isArmed = InvalPrice > 0;
            double currentPrice = Symbol.Bid;

            if (isArmed)
            {
                // Risk Mathematics
                double distPipsRaw = Math.Abs(currentPrice - InvalPrice) / Symbol.PipSize;
                double totalRiskPips = distPipsRaw + SpreadEst;
                double riskCap = Account.Balance * (RiskPct / 100.0);

                // cTrader Institutional Sizing
                double exactVolumeUnits = 0;
                if (totalRiskPips > 0 && Symbol.PipValue > 0)
                {
                    exactVolumeUnits = riskCap / (totalRiskPips * Symbol.PipValue);
                }

                // Normalize against broker limits
                double safeVolumeUnits = Symbol.NormalizeVolumeInUnits(exactVolumeUnits, RoundingMode.Down);
                double lotSize = Symbol.VolumeInUnitsToQuantity(safeVolumeUnits);
                bool isOversize = safeVolumeUnits < Symbol.VolumeInUnitsMin;

                // Net Expectancy Mathematics
                double netRMultiple = 0;
                if (TargetPrice > 0)
                {
                    double targetPipsRaw = Math.Abs(TargetPrice - currentPrice) / Symbol.PipSize;
                    double netRewardPips = Math.Max(0.0, targetPipsRaw - SpreadEst);
                    if (totalRiskPips > 0) netRMultiple = netRewardPips / totalRiskPips;
                }

                // Update HUD Strings & Colors
                _statusValue.Text = "ARMED";
                _statusValue.ForegroundColor = Color.SeaGreen;

                _invalValue.Text = InvalPrice.ToString("F5");
                _riskValue.Text = Math.Round(totalRiskPips, 1).ToString();

                if (isOversize)
                {
                    _lotValue.Text = "VIOLATION (< MIN LOT)";
                    _lotValue.ForegroundColor = Color.Red;
                }
                else
                {
                    _lotValue.Text = lotSize.ToString("F2");
                    _lotValue.ForegroundColor = Color.DeepSkyBlue;
                }

                if (TargetPrice > 0)
                {
                    _rrValue.Text = Math.Round(netRMultiple, 2).ToString() + " R";
                    _rrValue.ForegroundColor = netRMultiple >= 2.0 ? Color.LimeGreen : (netRMultiple >= 1.0 ? Color.Orange : Color.DimGray);
                }
                else
                {
                    _rrValue.Text = "---";
                    _rrValue.ForegroundColor = Color.White;
                }

                // Render Structural Lines
                Chart.DrawHorizontalLine("InvalLine", InvalPrice, Color.Maroon, 1, LineStyle.Lines);
                if (TargetPrice > 0)
                    Chart.DrawHorizontalLine("TargetLine", TargetPrice, Color.DarkCyan, 1, LineStyle.Lines);
            }
            else
            {
                // Lockout State
                _statusValue.Text = "LOCKED (AWAITING INPUT)";
                _statusValue.ForegroundColor = Color.Firebrick;

                _invalValue.Text = "---";
                _riskValue.Text = "---";
                _lotValue.Text = "---";
                _lotValue.ForegroundColor = Color.White;
                _rrValue.Text = "---";
                _rrValue.ForegroundColor = Color.White;

                Chart.RemoveObject("InvalLine");
                Chart.RemoveObject("TargetLine");
            }
        }

        // --- Helper for Grid Layout ---
        private StackPanel CreateRow(string label, out TextBlock valueText)
        {
            var row = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(0, 2, 0, 2) };
            
            row.AddChild(new TextBlock { Text = label + " : ", ForegroundColor = Color.Silver, Width = 150 });
            
            valueText = new TextBlock { Text = "---", ForegroundColor = Color.White, Width = 150, TextAlignment = TextAlignment.Right };
            row.AddChild(valueText);
            
            return row;
        }
    }
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: Invalidation rules on GBPUSD M15 before entry

Post by PTScalper »

The cTrader Advantage

Flawless Backend Math: Notice the equation riskCap / (totalRiskPips * Symbol.PipValue). In MT4/MT5, deriving the dynamic pip value requires querying MODE_TICKVALUE, finding the tick size, and doing multi-step algebra. cTrader's Symbol.PipValue automatically gives you the exact account currency value of a single pip for one unit of volume. It never fails, whether you trade GBPUSD or exotic crosses.

Native Normalization: The Symbol.NormalizeVolumeInUnits command seamlessly rounds the exact math down to your broker's specific stepping rules, protecting you from order-rejection errors.

Chart Object Binding: The UI panel sits as a native object inside the Chart.AddControl() wrapper, meaning it stays perfectly scaled and anchored to your screen regardless of how you zoom or pan the price chart.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: Invalidation rules on GBPUSD M15 before entry

Post by PTScalper »

To elevate this to an institutional standard, we must move away from a passive indicator and build an Active Execution Engine (cBot).

A professional does not calculate risk on a HUD and then manually switch over to a broker terminal to execute—that gap introduces slippage, hesitation, and manual entry errors.

We will transition this into a strict cTrader cBot. It places a sterile, on-chart terminal directly over price action. It does not ask you if you want to buy or sell; it deduces the trade direction based entirely on where you place your invalidation.

Furthermore, I have coded your vocalization rule into a physical circuit breaker. The execution button remains dead until you physically check a box confirming you have stated the invalidation aloud.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: Invalidation rules on GBPUSD M15 before entry

Post by PTScalper »

cTrader cBot: Institutional Execution Terminal

1.) Open cTrader, go to the Automate tab, and select Robots (not Indicators).

2.) Click New Robot, name it StrictExecutionEngine.

3.) Paste the following C# code. Click Build (F6).

4.) Drag it onto your GBPUSD chart.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: Invalidation rules on GBPUSD M15 before entry

Post by PTScalper »

Ctrader institutional level code

Code: Select all

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

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class StrictExecutionEngine : Robot
    {
        [Parameter("Risk Exposure (%)", Group = "Risk Management", DefaultValue = 1.0)]
        public double RiskPct { get; set; }

        [Parameter("Strict R:R Gating (Block < 2R)", Group = "Process Controls", DefaultValue = true)]
        public bool StrictRR { get; set; }

        [Parameter("Max Allowed Spread (Pips)", Group = "Process Controls", DefaultValue = 2.0)]
        public double MaxSpreadPips { get; set; }

        // UI Elements
        private TextBox _invalInput;
        private TextBox _targetInput;
        private CheckBox _vocalizeCheck;
        private Button _executeBtn;
        private TextBlock _hudStatus;
        private TextBlock _hudSize;
        private TextBlock _hudExpectancy;

        // Trade State
        private double _parsedInval = 0.0;
        private double _parsedTarget = 0.0;
        private double _exactVolume = 0;
        private TradeType _derivedDirection;

        protected override void OnStart()
        {
            BuildInstitutionalTerminal();
        }

        protected override void OnTick()
        {
            UpdateEngineMath();
        }

        private void UpdateEngineMath()
        {
            double currentSpread = Symbol.Spread / Symbol.PipSize;

            // 1. Validate Inputs
            bool hasValidInval = double.TryParse(_invalInput.Text, out _parsedInval) && _parsedInval > 0;
            double.TryParse(_targetInput.Text, out _parsedTarget);

            if (!hasValidInval)
            {
                LockTerminal("AWAITING STRUCTURAL INVALIDATION");
                return;
            }

            // 2. Deduce Direction from Structure
            _derivedDirection = (_parsedInval < Symbol.Ask) ? TradeType.Buy : TradeType.Sell;
            double entryPrice = (_derivedDirection == TradeType.Buy) ? Symbol.Ask : Symbol.Bid;

            // 3. Risk & Distance Math
            double riskPips = Math.Abs(entryPrice - _parsedInval) / Symbol.PipSize;
            double riskCap = Account.Balance * (RiskPct / 100.0);

            if (riskPips <= 0) return;

            // Institutional Volume Normalization
            double exactUnits = riskCap / (riskPips * Symbol.PipValue);
            _exactVolume = Symbol.NormalizeVolumeInUnits(exactUnits, RoundingMode.Down);
            double displayLots = Symbol.VolumeInUnitsToQuantity(_exactVolume);

            // 4. Expectancy Math
            double netRMultiple = 0;
            if (_parsedTarget > 0)
            {
                double targetPipsRaw = Math.Abs(_parsedTarget - entryPrice) / Symbol.PipSize;
                netRMultiple = targetPipsRaw / riskPips; // Net spread naturally accounted for in entryPrice
            }

            // 5. Hard Gating (The Rules)
            bool isOversize = _exactVolume < Symbol.VolumeInUnitsMin;
            bool isSpreadViolation = currentSpread > MaxSpreadPips;
            bool isRRViolation = StrictRR && _parsedTarget > 0 && netRMultiple < 2.0;

            // 6. UI Updates
            _hudSize.Text = isOversize ? "VIOLATION (< MIN LOT)" : $"{displayLots:F2} Lots";
            _hudSize.ForegroundColor = isOversize ? Color.Red : Color.DeepSkyBlue;

            if (_parsedTarget > 0)
            {
                _hudExpectancy.Text = $"{netRMultiple:F2} R";
                _hudExpectancy.ForegroundColor = isRRViolation ? Color.Red : Color.LimeGreen;
            }

            if (isOversize) LockTerminal("VIOLATION: INVALIDATION TOO WIDE");
            else if (isSpreadViolation) LockTerminal($"VIOLATION: SPREAD ({currentSpread:F1}) EXCEEDS MAX");
            else if (isRRViolation) LockTerminal("VIOLATION: EXPECTANCY < 2.0 R");
            else ArmTerminal(_derivedDirection);

            // Render Chart Lines
            Chart.DrawHorizontalLine("InvalLine", _parsedInval, Color.Maroon, 1, LineStyle.Lines);
            if (_parsedTarget > 0) Chart.DrawHorizontalLine("TargetLine", _parsedTarget, Color.DarkCyan, 1, LineStyle.Lines);
        }

        private void LockTerminal(string message)
        {
            _hudStatus.Text = message;
            _hudStatus.ForegroundColor = Color.Firebrick;
            _executeBtn.IsEnabled = false;
            _executeBtn.Text = "SYSTEM LOCKED";
            _executeBtn.BackgroundColor = Color.FromArgb(100, 40, 40, 40);
        }

        private void ArmTerminal(TradeType dir)
        {
            _hudStatus.Text = "SYSTEM ARMED";
            _hudStatus.ForegroundColor = Color.SeaGreen;

            // The final circuit breaker
            if (_vocalizeCheck.IsChecked == true)
            {
                _executeBtn.IsEnabled = true;
                _executeBtn.Text = $"EXECUTE {dir.ToString().ToUpper()}";
                _executeBtn.BackgroundColor = dir == TradeType.Buy ? Color.FromArgb(255, 10, 120, 60) : Color.FromArgb(255, 180, 40, 40);
            }
            else
            {
                _executeBtn.IsEnabled = false;
                _executeBtn.Text = "PENDING VOCALIZATION";
                _executeBtn.BackgroundColor = Color.FromArgb(100, 40, 40, 40);
            }
        }

        private void OnExecuteClick(ButtonClickEventArgs args)
        {
            if (_exactVolume < Symbol.VolumeInUnitsMin) return;

            // Convert prices to pips for StopLoss/TakeProfit parameters
            double entryPrice = (_derivedDirection == TradeType.Buy) ? Symbol.Ask : Symbol.Bid;
            double slPips = Math.Abs(entryPrice - _parsedInval) / Symbol.PipSize;
            double tpPips = _parsedTarget > 0 ? Math.Abs(_parsedTarget - entryPrice) / Symbol.PipSize : 0;
            double? finalTpPips = tpPips > 0 ? tpPips : (double?)null;

            ExecuteMarketOrder(_derivedDirection, SymbolName, _exactVolume, "StrictEngine", slPips, finalTpPips);
            
            // Reset terminal after execution
            _invalInput.Text = "";
            _targetInput.Text = "";
            _vocalizeCheck.IsChecked = false;
            Chart.RemoveObject("InvalLine");
            Chart.RemoveObject("TargetLine");
        }

        private void BuildInstitutionalTerminal()
        {
            var panel = new StackPanel
            {
                HorizontalAlignment = HorizontalAlignment.Right,
                VerticalAlignment = VerticalAlignment.Bottom,
                BackgroundColor = Color.FromArgb(250, 15, 15, 15),
                Margin = new Thickness(20),
                Width = 280
            };

            // Border Header
            panel.AddChild(new Border { BackgroundColor = Color.FromArgb(255, 30, 30, 30), Height = 25, Child = new TextBlock { Text = "INSTITUTIONAL EXECUTION PROTOCOL", FontWeight = FontWeight.Bold, ForegroundColor = Color.Silver, TextAlignment = TextAlignment.Center, Margin = new Thickness(0,4,0,0) } });

            // Inputs
            _invalInput = new TextBox { Margin = new Thickness(10, 10, 10, 5), ForegroundColor = Color.Maroon };
            _targetInput = new TextBox { Margin = new Thickness(10, 0, 10, 10), ForegroundColor = Color.DarkCyan };
            _invalInput.TextChanged += args => UpdateEngineMath();
            _targetInput.TextChanged += args => UpdateEngineMath();

            panel.AddChild(CreateInputRow("M15 Invalidation Price:", _invalInput));
            panel.AddChild(CreateInputRow("Target Price (Opt):", _targetInput));

            // Data Readouts
            _hudStatus = new TextBlock { Text = "AWAITING INPUT", ForegroundColor = Color.Firebrick, Margin = new Thickness(10, 5, 10, 2), FontWeight = FontWeight.Bold };
            _hudSize = new TextBlock { Text = "---", ForegroundColor = Color.White, Margin = new Thickness(10, 2, 10, 2) };
            _hudExpectancy = new TextBlock { Text = "---", ForegroundColor = Color.White, Margin = new Thickness(10, 2, 10, 10) };

            panel.AddChild(_hudStatus);
            panel.AddChild(_hudSize);
            panel.AddChild(_hudExpectancy);

            // The Circuit Breaker Checkbox
            _vocalizeCheck = new CheckBox { Text = "I have vocalized the invalidation.", Margin = new Thickness(10, 10, 10, 10), ForegroundColor = Color.DimGray };
            _vocalizeCheck.Checked += args => UpdateEngineMath();
            _vocalizeCheck.Unchecked += args => UpdateEngineMath();
            panel.AddChild(_vocalizeCheck);

            // Execution Button
            _executeBtn = new Button { Text = "SYSTEM LOCKED", IsEnabled = false, Height = 40, Margin = new Thickness(10), BackgroundColor = Color.FromArgb(100, 40, 40, 40), ForegroundColor = Color.White, FontWeight = FontWeight.Bold };
            _executeBtn.Click += OnExecuteClick;
            panel.AddChild(_executeBtn);

            Chart.AddControl(panel);
        }

        private StackPanel CreateInputRow(string label, TextBox inputField)
        {
            var row = new StackPanel { Orientation = Orientation.Horizontal, Margin = new Thickness(10, 2, 10, 2) };
            row.AddChild(new TextBlock { Text = label, Width = 140, ForegroundColor = Color.Gray, VerticalAlignment = VerticalAlignment.Center });
            inputField.Width = 110;
            row.AddChild(inputField);
            return row;
        }
    }
}
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 3027
Joined: Mon Jul 20, 2026 1:28 pm

Re: Invalidation rules on GBPUSD M15 before entry

Post by PTScalper »

The Pro Workflow

Directionless Entry: You no longer tell the platform to Buy or Sell. You type your M15 invalidation node into the chart terminal. If price is 1.2500 and you type 1.2480, the engine instantly knows you are long.

Expectancy Gating: If you input a Target Price, the robot calculates your net R-multiple. By default, I turned on StrictRR. If your setup yields less than 2.0 R, the robot locks you out. It will block the execution button and print VIOLATION: EXPECTANCY < 2.0 R.

Spread Guard: If high-impact news hits and the spread expands past 2.0 pips (adjustable), the robot immediately disarms the execution button to protect you from being filled in a liquidity void.

The Circuit Breaker: Even if your lot sizing, RR, and spread are perfect, the button remains dead. It reads PENDING VOCALIZATION. You must take your mouse, physically click the checkbox confirming you spoke the invalidation aloud, and only then will the Execute button light up with your exact side (Buy/Sell) and size.

When you click it, the cBot drops the order directly to the broker server with the Stop Loss mathematically attached to the exact tick you typed. Mid-trade redraws are effectively eliminated.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Post Reply