Advertisement IC Markets

A practical guide to flat-before-news discipline

Discuss 1-minute to 15-minute price action setups, fading intraday momentum, key support/resistance zones, and proven short-term trading methodologies.
FTtrader
Posts: 954
Joined: Mon Aug 03, 2026 2:43 pm

Re: A practical guide to flat-before-news discipline

Post by FTtrader »

Important Operational Note:

Algorithmic Trading Permission: Because these scripts execute trading functions (OrderDelete), you must ensure that "Allow DLL imports" (if applicable in your build setup) and "Allow algorithmic trading" are enabled in your MetaTrader terminal settings, and the "Algo Trading" button is toggled ON in the top toolbar when attaching the indicator to the chart.
Recommended broker for automated trading & scalping IC Markets
FTtrader
Posts: 954
Joined: Mon Aug 03, 2026 2:43 pm

Re: A practical guide to flat-before-news discipline

Post by FTtrader »

In cTrader, there is a strict architectural boundary you need to account for: Indicators cannot modify or cancel orders. Because this tool requires active trading permissions (CancelPendingOrder), it must be built as a cBot, not a custom indicator.

You can simply attach this cBot to your chart, leave its trading parameters alone, and let it run purely as an order-cancellation background service and visualizer.

Here is the production-ready C# code for the cAlgo API. It uses a 1-second OnTimer() loop rather than OnTick(). This is a critical edge for news trading: right before a Tier-1 print, the order book can empty out so completely that the tick feed stalls. A timer ensures your orders are pulled exactly on the clock, regardless of incoming tick flow.

cTrader: Advanced News Blackout cBot

1.) Open cTrader Automate.

2.) Create a New cBot (not an Indicator) and name it NewsBlackoutEnforcer.

3.) Paste the following C# code and build.
FTtrader
Posts: 954
Joined: Mon Aug 03, 2026 2:43 pm

Re: A practical guide to flat-before-news discipline

Post by FTtrader »

Ctrader version:

Code: Select all

using System;
using cAlgo.API;

namespace cAlgo.Robots
{
    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class NewsBlackoutEnforcer : Robot
    {
        // =========================================================================
        // INPUTS: TIME ZONES & EVENTS
        // =========================================================================
        [Parameter("Enable Event 1", DefaultValue = true, Group = "Event 1 (e.g., Early News)")]
        public bool EnableEvent1 { get; set; }

        [Parameter("Start Time (HH:mm:ss)", DefaultValue = "14:20:00", Group = "Event 1 (e.g., Early News)")]
        public string E1Start { get; set; }

        [Parameter("End Time (HH:mm:ss)", DefaultValue = "14:40:00", Group = "Event 1 (e.g., Early News)")]
        public string E1End { get; set; }

        [Parameter("Enable Event 2", DefaultValue = false, Group = "Event 2 (e.g., Tier-1 Print)")]
        public bool EnableEvent2 { get; set; }

        [Parameter("Start Time (HH:mm:ss)", DefaultValue = "19:50:00", Group = "Event 2 (e.g., Tier-1 Print)")]
        public string E2Start { get; set; }

        [Parameter("End Time (HH:mm:ss)", DefaultValue = "20:20:00", Group = "Event 2 (e.g., Tier-1 Print)")]
        public string E2End { get; set; }

        // =========================================================================
        // INPUTS: VISUALS & AESTHETICS
        // =========================================================================
        [Parameter("Post-News Recovery (Minutes)", DefaultValue = 3, Group = "Aesthetics")]
        public int RecoveryMinutes { get; set; }

        [Parameter("Blackout Color (Hex)", DefaultValue = "#408B0000", Group = "Aesthetics")]
        public string BlackoutColorHex { get; set; } // Default: Semi-transparent DarkRed

        [Parameter("Recovery Color (Hex)", DefaultValue = "#40696969", Group = "Aesthetics")]
        public string RecoveryColorHex { get; set; } // Default: Semi-transparent DimGray

        // State trackers to prevent alert spamming and loop continuous logic
        private bool _e1Triggered, _e1Cleared;
        private bool _e2Triggered, _e2Cleared;

        protected override void OnStart()
        {
            // Execute on a rigid 1-second clock, decoupling logic from market tick volume
            Timer.Start(1);
        }

        protected override void OnTimer()
        {
            DateTime now = Server.Time;

            ProcessEvent(1, EnableEvent1, E1Start, E1End, ref _e1Triggered, ref _e1Cleared, now);
            ProcessEvent(2, EnableEvent2, E2Start, E2End, ref _e2Triggered, ref _e2Cleared, now);
        }

        private void ProcessEvent(int eventId, bool isEnabled, string startStr, string endStr, ref bool isTriggered, ref bool isCleared, DateTime now)
        {
            if (!isEnabled) return;

            // Parse time configurations
            if (!TimeSpan.TryParse(startStr, out TimeSpan startTimeSpan) || !TimeSpan.TryParse(endStr, out TimeSpan endTimeSpan))
            {
                Print($"[ERROR] Invalid time format for Event {eventId}. Use HH:mm:ss.");
                return;
            }

            DateTime startTime = now.Date.Add(startTimeSpan);
            DateTime endTime = now.Date.Add(endTimeSpan);
            DateTime recoveryTime = endTime.AddMinutes(RecoveryMinutes);

            // 1. Entering Blackout Window
            if (now >= startTime && now < endTime)
            {
                if (!isTriggered)
                {
                    isTriggered = true;
                    isCleared = false;
                    
                    CancelWorkingOrders();
                    DrawZones(eventId, startTime, endTime, recoveryTime);
                    
                    // Alert logic
                    Notifications.PlaySound(SoundType.DoorBell);
                    Print($"[BLACKOUT ENTRY - Event {eventId}] Working orders cancelled. Spread expansion expected.");
                }
            }

            // 2. Exiting Blackout / Entering Recovery
            if (now >= endTime && now < recoveryTime)
            {
                if (!isCleared && isTriggered)
                {
                    isCleared = true;
                    Print($"[BLACKOUT CLEARED - Event {eventId}] Verifying DOM liquidity and spread reversion.");
                }
            }

            // 3. Reset state for the next trading session (after recovery completes)
            if (now >= recoveryTime && isTriggered)
            {
                isTriggered = false;
                isCleared = false;
            }
        }

        private void CancelWorkingOrders()
        {
            // Loop backwards or securely through pending orders to prevent collection modification errors
            foreach (var order in PendingOrders)
            {
                if (order.SymbolName == SymbolName)
                {
                    CancelPendingOrder(order);
                }
            }
        }

        private void DrawZones(int eventId, DateTime start, DateTime end, DateTime recovery)
        {
            // cTrader rectangles require Y-axis price boundaries. 
            // We use an arbitrarily large pip distance to simulate a full vertical background fill.
            double top = Symbol.Ask + (Symbol.PipSize * 3000);
            double bottom = Symbol.Bid - (Symbol.PipSize * 3000);
            
            Color blackoutColor = Color.FromHex(BlackoutColorHex);
            Color recoveryColor = Color.FromHex(RecoveryColorHex);
            
            string blackoutName = $"News_Blackout_{eventId}_{start:yyyyMMdd}";
            string recoveryName = $"News_Recovery_{eventId}_{start:yyyyMMdd}";

            // Render Blackout Zone
            var blackoutBox = Chart.DrawRectangle(blackoutName, start, bottom, end, top, blackoutColor);
            blackoutBox.IsFilled = true;
            blackoutBox.IsInteractive = false; // Prevent accidental clicks/drags during scalping

            // Render Post-News Recovery Zone
            var recoveryBox = Chart.DrawRectangle(recoveryName, end, bottom, recovery, top, recoveryColor);
            recoveryBox.IsFilled = true;
            recoveryBox.IsInteractive = false;
        }
    }
}
LondonScalper
Posts: 701
Joined: Sat Sep 05, 2026 7:54 am

Re: A practical guide to flat-before-news discipline

Post by LondonScalper »

FTtrader wrote:Tier-1 news is a hard flat: thin books and widened spreads make sitting through CPI/NFP/FOMC a coin flip. For medium-tier events, scalp only if liquidity and structure are exceptionally clean and the stop sits outside expected noise; a winning trade that breaks the blackout is still a process strike.
Agreed on both layers — Tier-1 is non-negotiable flat, and a green ticket that violated the blackout is still logged as a process fault.

My written window is T−10 to T+10 for standard Tier-1 (longer into FOMC). Working orders cancel at T−10; calendar alerts fire; re-entry only after spread and tape normalise and a short checklist passes. The release print itself is never a signal.

For medium-tier I allow a reduced-size scalp only when the book is two-sided and my stop sits clearly outside the expected noise band. If either condition fails, I treat it as Tier-1 behaviour and stay flat.

Rule: blackout breach = process strike even when P&L is green. On medium-tier, do you require both clean liquidity and a pre-marked stop outside noise, or is one of those enough to keep the ticket open?
LondonNewsTrader
Posts: 79
Joined: Mon Sep 21, 2026 9:30 am

Re: A practical guide to flat-before-news discipline

Post by LondonNewsTrader »

FTtrader wrote:This Pine Script translates your manual checklist into a visual and automated chart tool. It handles Point 1 (setting the window), Point 3 (platform alerts), and visually reminds you of Point 4 (waiting for post-chaos structure).
Codifying flat-before-news is one of the few automations that actually saves accounts.

My London sheet still starts on paper the night before: which prints are Tier-1, blackout T−10/T+10 in broker time, and whether I am allowed any working orders at all. The multi-event state machine (early CPI, cash open, later FOMC) matches how real days look — one "news" toggle is not enough when the US calendar stacks.

Alert text that says cancel working orders beats a silent background colour. Post-chaos structure means waiting until spreads and rejects normalise, not taking the first M1 impulse because the box turned off.

Are your blackout windows set in exchange time with a verified broker offset, or do you still catch yourself once a month on a DST mismatch?
PropScalpDesk
Posts: 273
Joined: Sat Sep 19, 2026 7:50 pm

Re: A practical guide to flat-before-news discipline

Post by PropScalpDesk »

FTtrader wrote:Pro Pine Script: Advanced News Blackout Enforcer This version is built with cleaner architecture.
Flat-before-news is a checklist: cancel pendings, flatten working risk, note the next window. Doing only one of the three is how “I thought I was flat” happens.

Discipline is the list, not the feeling.

Do you rehearse the checklist the night before Tier-1 weeks?

I also log refused tickets so flat time counts as work — otherwise the desk invents activity.

I write the walk-away before London so it is not negotiated mid-tape.

If the idea needs a story longer than one line, it waits for another window.

Funded trailing DD is the external referee that keeps the desk honest.

Boring survival beats a clever recovery that spends the week’s DD band.

Topic note from my sheet for t=12403: keep risk unchanged until the sample says otherwise.
Post Reply