Page 3 of 3

Re: Best forex brokers with low spreads for scalping

Posted: Mon Sep 21, 2026 6:13 pm
by PTScalper
What Makes This The "Ultimate Pro" MT Version:

The Live Data Advantage (InpUseLiveSpread): By default, this script now hooks into MetaTrader's live order book. During news events when liquidity drops, you will actively see the "Spread Drag" value jump up in real-time, accurately reflecting your expanding trading costs in a way TradingView simply cannot do natively.

True Dark-Mode Dashboard: Instead of text floating invisibly over candles, this version generates a fully rendered OBJ_RECTANGLE_LABEL graphical panel in the top-right corner. It uses proper bounding boxes, custom hex RGB colors (C'20,20,20'), and right-justified numeric columns (ANCHOR_RIGHT_UPPER) so the decimals line up perfectly—exactly matching the institutional look of the Pine Script table.

Re: Best forex brokers with low spreads for scalping

Posted: Mon Sep 21, 2026 6:14 pm
by PTScalper
To translate this "Pro" level institutional model to cTrader, we must shift from Pine Script/MQL to C# (.NET), which is what cTrader’s Automate API uses.

cTrader is arguably the most advanced retail platform for UI design because it uses a native WPF-style (Windows Presentation Foundation) layout system. This allows us to build a truly stunning, responsive, and native-looking institutional dashboard directly on the chart, without the clunky limitations of MetaTrader's graphical labels.

Here is the ultimate Institutional Execution Drag Model for cTrader.

Re: Best forex brokers with low spreads for scalping

Posted: Mon Sep 21, 2026 6:15 pm
by PTScalper
How to Install in cTrader:

1.) Open cTrader and go to the Automate tab (left menu).

2.) Click the Indicators tab, then click the New button (+ icon).

3.) Name it ProExecutionModel.

3.) Delete the default code, paste the C# code below, and click Build (or press F7).

4.) Add it to any chart from the Indicators menu.

Re: Best forex brokers with low spreads for scalping

Posted: Mon Sep 21, 2026 6:15 pm
by PTScalper
The cTrader C# Code

Code: Select all

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 ProExecutionModel : Indicator
    {
        public enum FeeTypeEnum { PerLot, Percentage }

        // =========================================================================
        // INPUT PARAMETERS
        // =========================================================================
        [Parameter("Volume (Units, e.g., 100000 for 1 Lot)", Group = "1. Position & Fees", DefaultValue = 100000)]
        public double InpVolume { get; set; }

        [Parameter("Fee Type", Group = "1. Position & Fees", DefaultValue = FeeTypeEnum.PerLot)]
        public FeeTypeEnum InpFeeType { get; set; }

        [Parameter("Fee Rate (Per Lot or %)", Group = "1. Position & Fees", DefaultValue = 3.5)]
        public double InpFeeRate { get; set; }

        [Parameter("Fixed Ticket Fee ($)", Group = "1. Position & Fees", DefaultValue = 0.0)]
        public double InpFixedFee { get; set; }

        [Parameter("Use Live Broker Spread?", Group = "2. Market Impact", DefaultValue = true)]
        public bool InpUseLiveSpread { get; set; }

        [Parameter("Base Spread (Pips, if Live is false)", Group = "2. Market Impact", DefaultValue = 1.0)]
        public double InpBaseSpread { get; set; }

        [Parameter("Base Slippage Per Side (Pips)", Group = "2. Market Impact", DefaultValue = 1.0)]
        public double InpBaseSlippage { get; set; }

        [Parameter("Use Vol-Adjusted Slippage (ATR)?", Group = "2. Market Impact", DefaultValue = true)]
        public bool InpUseDynSlip { get; set; }

        [Parameter("ATR Slippage Factor", Group = "2. Market Impact", DefaultValue = 0.05)]
        public double InpSlipFactor { get; set; }

        // =========================================================================
        // ON-CHART PLOTS (BREAKEVEN ENVELOPE)
        // =========================================================================
        [Output("Long Breakeven", LineColor = "#008080", PlotType = PlotType.Line, LineStyle = LineStyle.Lines)]
        public IndicatorDataSeries LongBE { get; set; }

        [Output("Short Breakeven", LineColor = "#800000", PlotType = PlotType.Line, LineStyle = LineStyle.Lines)]
        public IndicatorDataSeries ShortBE { get; set; }

        // =========================================================================
        // GLOBAL VARIABLES & UI CONTROLS
        // =========================================================================
        private AverageTrueRange _atr;
        private TextBlock _valNotional, _valComm, _valSpread, _valSlip, _valTotal, _valDrag, _valBE;

        protected override void Initialize()
        {
            _atr = Indicators.AverageTrueRange(14, MovingAverageType.Simple);
            DrawInstitutionalDashboard();
        }

        public override void Calculate(int index)
        {
            if (index < 14) return;

            double currentPrice = Bars.ClosePrices[index];
            
            // 1. Core Base Metrics
            // cTrader's Symbol.PipValue is the value of 1 pip for 1 unit of volume.
            double pipValueTotal = Symbol.PipValue * InpVolume;
            if (pipValueTotal == 0) pipValueTotal = 1; // Failsafe
            
            double notionalValue = InpVolume * currentPrice;

            // 2. Volatility Adjusted Slippage (ATR)
            double atrInPips = _atr.Result[index] / Symbol.PipSize;
            double dynSlip = InpBaseSlippage;
            if (InpUseDynSlip) dynSlip += (atrInPips * InpSlipFactor);

            // 3. Live Spread vs Manual
            double currentSpread = InpBaseSpread;
            if (InpUseLiveSpread) currentSpread = Symbol.Spread / Symbol.PipSize;

            // 4. Cost Calculations (Round Trip)
            // Note: PerLot assumes 1 standard lot = 100,000 units
            double commCost = (InpFeeType == FeeTypeEnum.PerLot) 
                ? (InpFeeRate * (InpVolume / 100000)) + InpFixedFee 
                : (notionalValue * (InpFeeRate / 100)) + InpFixedFee;
                
            double spreadCost = currentSpread * pipValueTotal;
            double slipCost = (dynSlip * 2) * pipValueTotal; 
            double totalCost = commCost + spreadCost + slipCost;

            // 5. Breakeven Math
            double pipsToBE = totalCost / pipValueTotal;
            LongBE[index] = currentPrice + (pipsToBE * Symbol.PipSize);
            ShortBE[index] = currentPrice - (pipsToBE * Symbol.PipSize);

            // 6. Update UI (Only on the live ticking bar to save CPU)
            if (IsLastBar)
            {
                double acctBal = Account.Balance;
                double acctDrag = (acctBal > 0) ? (totalCost / acctBal) * 100 : 0;
                string ccy = Account.Asset.Name;

                _valNotional.Text = $"{Math.Round(notionalValue, 2):N2} {ccy}";
                _valComm.Text = $"{Math.Round(commCost, 2):N2} {ccy}";
                _valSpread.Text = $"{Math.Round(spreadCost, 2):N2} {ccy}";
                _valSlip.Text = $"{Math.Round(slipCost, 2):N2} {ccy}";
                _valTotal.Text = $"{Math.Round(totalCost, 2):N2} {ccy}";
                _valDrag.Text = $"{Math.Round(acctDrag, 3):N3}%";
                _valBE.Text = $"{Math.Round(pipsToBE, 1):N1}";
            }
        }

        // =========================================================================
        // NATIVE WPF-STYLE UI GENERATION
        // =========================================================================
        private void DrawInstitutionalDashboard()
        {
            var grid = new Grid(7, 2) { Margin = new Thickness(15) };

            // Grid Column Settings
            grid.Columns.Add(new Column { Width = GridLength.Auto });
            grid.Columns.Add(new Column { Width = new GridLength(120, GridUnitType.Pixel) });

            // Initialize dynamic TextBlocks
            _valNotional = CreateValueText("#B0BEC5");
            _valComm = CreateValueText("#FF5252");
            _valSpread = CreateValueText("#FF5252");
            _valSlip = CreateValueText(InpUseDynSlip ? "#FFA726" : "#FF5252");
            _valTotal = CreateValueText("#29B6F6", true);
            _valDrag = CreateValueText("#FF8A65", true);
            _valBE = CreateValueText("#FFD54F", true);

            // Populate Grid Rows
            AddGridRow(grid, 0, "Notional Exposure:", _valNotional, "#B0BEC5");
            AddGridRow(grid, 1, "Broker Commissions:", _valComm, "#B0BEC5");
            AddGridRow(grid, 2, InpUseLiveSpread ? "Spread Drag (LIVE):" : "Spread Drag (STATIC):", _valSpread, "#B0BEC5");
            AddGridRow(grid, 3, "Est. Slippage (ATR):", _valSlip, "#B0BEC5");
            AddGridRow(grid, 4, "Total Overhead:", _valTotal, "#29B6F6", true);
            AddGridRow(grid, 5, "Portfolio Drag:", _valDrag, "#B0BEC5");
            AddGridRow(grid, 6, "Pips to Breakeven:", _valBE, "#FFD54F", true);

            // Container Panel Styling
            var border = new Border
            {
                BackgroundColor = Color.FromArgb(220, 20, 20, 20),
                BorderColor = Color.FromArgb(255, 60, 60, 60),
                BorderThickness = new Thickness(1),
                CornerRadius = 5,
                HorizontalAlignment = HorizontalAlignment.Right,
                VerticalAlignment = VerticalAlignment.Top,
                Margin = new Thickness(20),
                Child = new StackPanel
                {
                    Orientation = Orientation.Vertical,
                    Children = 
                    {
                        new TextBlock 
                        { 
                            Text = $"Execution Drag Model | {SymbolName}", 
                            ForegroundColor = Color.White, 
                            FontWeight = FontWeight.Bold,
                            Margin = new Thickness(15, 15, 15, 5)
                        },
                        grid
                    }
                }
            };

            Chart.AddControl(border);
        }

        private TextBlock CreateValueText(string hexColor, bool isBold = false)
        {
            return new TextBlock
            {
                ForegroundColor = Color.FromHex(hexColor),
                HorizontalAlignment = HorizontalAlignment.Right,
                FontWeight = isBold ? FontWeight.Bold : FontWeight.Normal,
                Margin = new Thickness(10, 5, 0, 5)
            };
        }

        private void AddGridRow(Grid grid, int rowIndex, string label, TextBlock valueBlock, string labelColorHex, bool isBold = false)
        {
            var title = new TextBlock
            {
                Text = label,
                ForegroundColor = Color.FromHex(labelColorHex),
                FontWeight = isBold ? FontWeight.Bold : FontWeight.Normal,
                Margin = new Thickness(0, 5, 10, 5)
            };

            grid.AddChild(title, rowIndex, 0);
            grid.AddChild(valueBlock, rowIndex, 1);
        }
    }
}

Re: Best forex brokers with low spreads for scalping

Posted: Mon Sep 21, 2026 6:16 pm
by PTScalper
What makes this version "Pro" specific to cTrader:

WPF Native UI Architecture: While Pine Script and MetaTrader rely on rudimentary table/label overlays, cTrader uses actual layout containers (Grid, StackPanel, Border). This script leverages them to create a fully native UI panel with exact pixel margins, dynamic column sizing, rounded corners (CornerRadius = 5), and partial transparency (FromArgb(220, 20, 20, 20)).

Object-Oriented Efficiency: The dashboard is rendered exactly once during Initialize(). During live market hours, the Calculate() loop only updates the .Text properties of the pre-loaded TextBlocks. This uses virtually zero CPU overhead, ensuring no latency during high-frequency trading.

Flawless Asset Sizing: cTrader uses "Units" natively (e.g., 100,000 is 1 standard FX lot). The script translates this perfectly into monetary value dynamically using Symbol.PipValue * InpVolume, meaning it automatically adjusts the math flawlessly whether you are trading Forex (Pips), Indices (Points), or Crypto (Cents), completely avoiding the tedious manual conversions needed in MetaTrader.