Page 1 of 1

Screenshot protocol after a reject: what I keep for the weekly review

Posted: Sat Sep 12, 2026 9:05 pm
by LondonScalper
Execution hygiene — rejects and requotes, logged properly.

A reject that you don’t capture becomes a story by Sunday: “the broker was bad” or “I imagined it.” I prefer files.

Minimum capture when a reject happens
1. Timestamp (platform clock)
2. Symbol, side, size, order type
3. Screenshot of the reject/requote dialogue and the quote board if visible
4. Spread at the moment (typed into the journal if the shot doesn’t show it)
5. Whether I resubmitted, switched to limit, or stood aside

I don’t need a novel. One folder per week, filenames like 2026-09-12_GBPUSD_reject_0831. At weekly review I count rejects by session and by pair. Clusters matter more than one-off noise.

Rules that came from this habit
• No market-order spam after two rejects in a row — pause and reassess
• If rejects cluster only on one symbol in a window, that window gets a filter
• Don’t argue from memory with support; argue from the folder

This isn’t about picking fights with brokers. It’s about knowing whether my timing is the problem. If you already archive rejects, do you also keep the successful fill next to them for comparison, or only the failures?

Re: Screenshot protocol after a reject: what I keep for the weekly review

Posted: Sun Sep 13, 2026 10:32 pm
by PTScalper
LondonScalper wrote: Sat Sep 12, 2026 9:05 pm Execution hygiene — rejects and requotes, logged properly.

A reject that you don’t capture becomes a story by Sunday: “the broker was bad” or “I imagined it.” I prefer files.

Minimum capture when a reject happens
1. Timestamp (platform clock)
2. Symbol, side, size, order type
3. Screenshot of the reject/requote dialogue and the quote board if visible
4. Spread at the moment (typed into the journal if the shot doesn’t show it)
5. Whether I resubmitted, switched to limit, or stood aside

I don’t need a novel. One folder per week, filenames like 2026-09-12_GBPUSD_reject_0831. At weekly review I count rejects by session and by pair. Clusters matter more than one-off noise.

Rules that came from this habit
• No market-order spam after two rejects in a row — pause and reassess
• If rejects cluster only on one symbol in a window, that window gets a filter
• Don’t argue from memory with support; argue from the folder

This isn’t about picking fights with brokers. It’s about knowing whether my timing is the problem. If you already archive rejects, do you also keep the successful fill next to them for comparison, or only the failures?
Hi LondonScalper,

interesting idea, i hear about it for first time, to be honest.

Tracking the subsequent fill is the only way to calculate the "reject tax" — the exact cost in pips or ticks of the delay. When you review that folder on Sunday, seeing the eventual fill answers the most important behavioral question: Did the reject save me from a toxic spread spike, or did I get frustrated, mash the buy button, and chase price into a terrible entry?

Your rule about avoiding market-order spam after two rejects is top-tier execution hygiene. Brokers algorithms are designed to protect their liquidity during fast markets; mashing the button just guarantees you catch the absolute worst of the slippage once the order finally routes. Archiving the data removes the emotion and gives you undeniable leverage if a genuine tech issue occurred.

To complement your manual journaling, here is a Pine Script designed to automate the "window filtering" and "session clustering" you mentioned. Since Pine Script cannot log actual broker dialogues, this script identifies and filters the environmental conditions (extreme volatility spikes and micro-gaps) that trigger broker requotes and rejects.

It paints a background filter when a window becomes "toxic" for market orders, and includes a dashboard that counts these high-risk events by session, automating part of your weekly review.

Re: Screenshot protocol after a reject: what I keep for the weekly review

Posted: Sun Sep 13, 2026 10:32 pm
by PTScalper
Execution Filter & Requote Risk Dashboard (Pine Script v5)

Code: Select all

//@version=5
indicator("Execution Hygiene: Requote Risk & Session Filter", overlay=true)

// =========================================================================
// INPUTS & PARAMETERS
// =========================================================================
grp1 = "Requote/Reject Environment Criteria"
atrMult = input.float(2.5, title="Volatility Spike (ATR Multiplier)", group=grp1, tooltip="Flags bars where volatility is X times the ATR, likely causing requotes.")
atrLength = input.int(14, title="ATR Length", group=grp1)
flagGaps = input.bool(true, title="Flag Micro-Gaps", group=grp1, tooltip="Flags gaps between close and open, a primary cause of rejected market orders.")

grp2 = "Session Tracking (EST/EDT)"
londonTime = input.session("0300-1130", title="London Session", group=grp2)
nyTime = input.session("0800-1700", title="New York Session", group=grp2)

// =========================================================================
// RISK DETECTION LOGIC
// =========================================================================
atr = ta.atr(atrLength)
barVol = high - low
gapSize = math.abs(open - close[1])

// A "Risk Event" is a market condition where brokers typically pull liquidity, widen spreads, and reject market orders.
isSpikeRisk = barVol > (atr * atrMult)
isGapRisk = flagGaps and (gapSize > (atr * 0.5))
isRiskWindow = isSpikeRisk or isGapRisk

// =========================================================================
// THE "WINDOW FILTER" 
// =========================================================================
// Visually flags the chart so you know to pause market orders during this window
bgcolor(isRiskWindow ? color.new(color.red, 90) : na, title="Requote Risk Filter")

// =========================================================================
// SESSION CLUSTER TRACKING (For Weekly Review)
// =========================================================================
inLondon = not na(time(timeframe.period, londonTime, "America/New_York"))
inNY = not na(time(timeframe.period, nyTime, "America/New_York"))

var int londonRiskCount = 0
var int nyRiskCount = 0
var int asianRiskCount = 0

// Count the clusters
if isRiskWindow
    if inLondon
        londonRiskCount += 1
    else if inNY
        nyRiskCount += 1
    else
        asianRiskCount += 1

// =========================================================================
// WEEKLY REVIEW DASHBOARD
// =========================================================================
var table riskLog = table.new(position.bottom_right, 2, 4, border_width=1, border_color=color.gray)

if barstate.islast
    // Headers
    table.cell(riskLog, 0, 0, "Session", text_color=color.white, bgcolor=color.black)
    table.cell(riskLog, 1, 0, "Requote Risk Clusters", text_color=color.white, bgcolor=color.black)
    
    // London Data
    table.cell(riskLog, 0, 1, "London", text_color=color.white, bgcolor=color.rgb(43, 65, 94))
    table.cell(riskLog, 1, 1, str.tostring(londonRiskCount), text_color=color.white, bgcolor=londonRiskCount > 5 ? color.maroon : color.rgb(43, 65, 94))
    
    // NY Data
    table.cell(riskLog, 0, 2, "New York", text_color=color.white, bgcolor=color.rgb(43, 94, 62))
    table.cell(riskLog, 1, 2, str.tostring(nyRiskCount), text_color=color.white, bgcolor=nyRiskCount > 5 ? color.maroon : color.rgb(43, 94, 62))
    
    // Asian/Off-hours Data
    table.cell(riskLog, 0, 3, "Asian/Other", text_color=color.white, bgcolor=color.rgb(94, 76, 43))
    table.cell(riskLog, 1, 3, str.tostring(asianRiskCount), text_color=color.white, bgcolor=asianRiskCount > 5 ? color.maroon : color.rgb(94, 76, 43))

Re: Screenshot protocol after a reject: what I keep for the weekly review

Posted: Sun Sep 13, 2026 10:33 pm
by PTScalper
How to use this alongside your manual hygiene:

The Visual Filter: When the chart paints a red background, the underlying liquidity is thinning out or moving too fast. If you catch a reject here, the indicator confirms it's an environmental factor, reinforcing your rule to switch to limit orders or stand aside.

The Cluster Dashboard: The bottom-right table keeps a running tally of these hostile market conditions by session. If you are reviewing your screenshots on Sunday and see 6 rejects on GBPUSD during the London session, you can cross-reference the script's dashboard. If the script also flagged a high cluster of "Risk Events" in London, you know the pair was just behaving erratically. If the script shows a quiet market but you still got 6 rejects, it is time to open that folder and have a data-driven conversation with your broker's support desk.

Re: Screenshot protocol after a reject: what I keep for the weekly review

Posted: Sun Sep 13, 2026 10:37 pm
by PTScalper
While Pine Script is great for visual charting, moving this to MetaTrader opens up a massive upgrade: MetaTrader can access your local hard drive and actually take the screenshot for you.

Because of MT5’s architecture, we can go beyond a simple visual filter. We can build a background Expert Advisor (EA) that fully automates your journaling rule. When you click "Buy" and the broker rejects it, the EA will instantly snap a screenshot, grab the spread, and write a row to a CSV file.

Here are two scripts:

1. MT5 Auto-Logger EA (The Execution Supervisor)

Attach this to any chart and leave it running. It listens to the server in the background. If you manually place a trade and it is rejected or requoted, it instantly fulfills your exact logging checklist.

To use: Create a new Expert Advisor in MT5, paste this code, and compile.

Code: Select all

//+------------------------------------------------------------------+
//|                                   ExecutionHygieneLogger.mq5     |
//|                    Automated Reject/Requote Capture System       |
//+------------------------------------------------------------------+
#property strict

input bool     TakeScreenshot = true;
input string   LogPrefix      = "RejectLog_"; // Will save in MQL5/Files/

// MT5 Event Handler: Listens to all trade server responses
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
   // We only want to trigger on actual trade request results
   if(trans.type == TRADE_TRANSACTION_REQUEST)
     {
      // Check for Requote (10004), Reject (10006), Price Changed (10020), Off Quotes (10021)
      if(result.retcode == TRADE_RETCODE_REQUOTE || 
         result.retcode == TRADE_RETCODE_REJECT  || 
         result.retcode == TRADE_RETCODE_PRICE_OFF ||
         result.retcode == TRADE_RETCODE_PRICE_CHANGED)
        {
         LogRejectEvent(request, result);
        }
     }
  }

void LogRejectEvent(const MqlTradeRequest &req, const MqlTradeResult &res)
  {
   datetime now = TimeCurrent();
   
   // Format to match your naming convention: 2026-09-12
   string dateStr = TimeToString(now, TIME_DATE);
   StringReplace(dateStr, ".", "-"); 
   
   // Format time: 0831
   string timeStr = TimeToString(now, TIME_MINUTES);
   StringReplace(timeStr, ":", ""); 
   
   string symbol = req.symbol;
   string orderType = (req.type == ORDER_TYPE_BUY) ? "BUY" : (req.type == ORDER_TYPE_SELL) ? "SELL" : "PENDING";
   
   // Capture precise spread at the millisecond of rejection
   double spread = (SymbolInfoDouble(symbol, SYMBOL_ASK) - SymbolInfoDouble(symbol, SYMBOL_BID)) / SymbolInfoDouble(symbol, SYMBOL_POINT);
   
   // Naming Rule: 2026-09-12_GBPUSD_reject_0831
   string baseName = dateStr + "_" + symbol + "_reject_" + timeStr;
   
   // 1. Take Screenshot (Saves silently to MQL5/Files/)
   if(TakeScreenshot)
     {
      string imgPath = baseName + ".png";
      ChartScreenShot(0, imgPath, 1920, 1080, ALIGN_RIGHT);
      Print("Screenshot saved to MQL5/Files/ : ", imgPath);
     }
     
   // 2. Log to CSV (Creates one master file per week based on date)
   string csvPath = LogPrefix + dateStr + ".csv";
   int handle = FileOpen(csvPath, FILE_WRITE | FILE_READ | FILE_CSV | FILE_ANSI, ",");
   if(handle != INVALID_HANDLE)
     {
      FileSeek(handle, 0, SEEK_END);
      if(FileSize(handle) == 0) // Write headers if new file
        {
         FileWrite(handle, "Platform Time", "Symbol", "Side", "Volume", "Spread (Pts)", "Server Error Code", "Broker Comment", "Screenshot File");
        }
      FileWrite(handle, TimeToString(now, TIME_SECONDS), symbol, orderType, DoubleToString(req.volume, 2), 
                DoubleToString(spread, 0), IntegerToString(res.retcode), res.comment, baseName + ".png");
      FileClose(handle);
      Print("Reject data logged to CSV: ", csvPath);
     }
     
   // Alert the trader so you know to pause market orders
   Alert("EXECUTION HYGIENE: Order Rejected! Code: ", res.retcode, " | Spread: ", spread, " pts. Logged to files.");
  }

Re: Screenshot protocol after a reject: what I keep for the weekly review

Posted: Sun Sep 13, 2026 10:37 pm
by PTScalper
(Note: Standard MT4 architecture does not support intercepting manual F9 window errors via OnTradeTransaction. To get this automated behavior in MT4, traders typically use a third-party One-Click Trade panel that handles execution and internal error logging.)

Re: Screenshot protocol after a reject: what I keep for the weekly review

Posted: Sun Sep 13, 2026 10:38 pm
by PTScalper
2. MT4 / MT5 Indicator (Requote Risk Filter)

This is the direct translation of the Pine Script. It draws a red histogram at the bottom of your chart to flag hostile conditions (ATR spikes and micro-gaps) and tallies the session clusters on your chart as a comment.

To use: Create a new Custom Indicator, paste this code, and compile. It is written to be seamlessly compatible with both MT4 and MT5.

Code: Select all

//+------------------------------------------------------------------+
//|                                     RequoteRiskFilter.mq4/mq5    |
//|                 Flags environments prone to execution delays     |
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1

#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  clrRed
#property indicator_width1  3
#property indicator_minimum 0
#property indicator_maximum 1

input double ATR_Multiplier = 2.5;  // Volatility Spike (ATR Multiplier)
input int    ATR_Length     = 14;   // ATR Period
input bool   FlagGaps       = true; // Flag Micro-Gaps

double RiskBuffer[];
int    atrHandle;

int OnInit()
  {
   SetIndexBuffer(0, RiskBuffer, INDICATOR_DATA);
   PlotIndexSetString(0, PLOT_LABEL, "Risk Window");
   IndicatorSetString(INDICATOR_SHORTNAME, "Requote Risk Filter");
   
   #ifdef __MQL5__
   atrHandle = iATR(_Symbol, _Period, ATR_Length);
   #endif
   
   return(INIT_SUCCEEDED);
  }

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[])
  {
   int start = (prev_calculated > 0) ? prev_calculated - 1 : 1;
   
   #ifdef __MQL5__
   double atrArray[];
   if(CopyBuffer(atrHandle, 0, 0, rates_total, atrArray) <= 0) return(0);
   #endif

   int lonCount = 0, nyCount = 0, asCount = 0;

   // Calculate Risk Bars
   for(int i = start; i < rates_total; i++)
     {
      double atrVal = 0;
      #ifdef __MQL5__
         atrVal = atrArray[i];
      #else
         atrVal = iATR(_Symbol, _Period, ATR_Length, i); // MT4 Native
      #endif
      
      double barVol = high[i] - low[i];
      double gap    = MathAbs(open[i] - close[i-1]);
      
      bool isSpike = barVol > (atrVal * ATR_Multiplier);
      bool isGap   = FlagGaps && (gap > (atrVal * 0.5));
      
      if(isSpike || isGap)
         RiskBuffer[i] = 1.0;
      else
         RiskBuffer[i] = 0.0;
     }

   // Count today's session clusters for the dashboard
   datetime todayStart = iTime(_Symbol, PERIOD_D1, 0);
   for(int j = rates_total - 1; j >= 0; j--)
     {
      if(time[j] < todayStart) break; // Only count today
      
      if(RiskBuffer[j] > 0)
        {
         MqlDateTime dt;
         TimeToStruct(time[j], dt);
         
         // Basic Session Tracking (Server Time)
         if(dt.hour >= 3 && dt.hour < 11)      lonCount++;
         else if(dt.hour >= 8 && dt.hour < 17) nyCount++;
         else                                  asCount++;
        }
     }

   // Update Chart Dashboard Comment
   string dash = "--- EXECUTION HYGIENE DASHBOARD ---\n" +
                 "Requote Risk Clusters (Today)\n" +
                 "London Session: " + IntegerToString(lonCount) + "\n" +
                 "New York Session: " + IntegerToString(nyCount) + "\n" +
                 "Asian/Other: " + IntegerToString(asCount);
                 
   Comment(dash);
   
   return(rates_total);
  }