Beating moving stops as a scalper: rules that stuck
-
LondonScalper
- Posts: 701
- Joined: Sat Sep 05, 2026 7:54 am
Beating moving stops as a scalper: rules that stuck
Moving stops: the quiet account killer I had to name out loud.
I told myself I was "giving it room." I was moving invalidation because I did not want to be wrong on a ticket I had already sized. That is a different trade with a larger loss attached.
Counter-rules
1. Stop only tightens or stays; widening needs a written exception type (almost never used).
2. If I touch the stop line, journal tag stop_edit -- even if I put it back.
3. A time stop exists so I am not negotiating with the chart forever.
Winners that required a moved stop are not proof the edit was skill. They are often luck with extra risk. Making edits visible in the log was what reduced them -- shame works better than slogans.
How do you make stop edits visible enough that you cannot pretend they did not happen?
Platforms that make stop edits too easy need extra friction -- I sometimes use alerts at the stop instead of constant dragging. If the alert fires, I flatten or accept the planned loss. Dragging becomes a conscious violation, which is easier to tag than a "tiny adjustment" story.
I told myself I was "giving it room." I was moving invalidation because I did not want to be wrong on a ticket I had already sized. That is a different trade with a larger loss attached.
Counter-rules
1. Stop only tightens or stays; widening needs a written exception type (almost never used).
2. If I touch the stop line, journal tag stop_edit -- even if I put it back.
3. A time stop exists so I am not negotiating with the chart forever.
Winners that required a moved stop are not proof the edit was skill. They are often luck with extra risk. Making edits visible in the log was what reduced them -- shame works better than slogans.
How do you make stop edits visible enough that you cannot pretend they did not happen?
Platforms that make stop edits too easy need extra friction -- I sometimes use alerts at the stop instead of constant dragging. If the alert fires, I flatten or accept the planned loss. Dragging becomes a conscious violation, which is easier to tag than a "tiny adjustment" story.
Re: Beating moving stops as a scalper: rules that stuck
Hi LondonScalper,LondonScalper wrote: Mon Sep 14, 2026 8:38 pm Moving stops: the quiet account killer I had to name out loud.
I told myself I was "giving it room." I was moving invalidation because I did not want to be wrong on a ticket I had already sized. That is a different trade with a larger loss attached.
Counter-rules
1. Stop only tightens or stays; widening needs a written exception type (almost never used).
2. If I touch the stop line, journal tag stop_edit -- even if I put it back.
3. A time stop exists so I am not negotiating with the chart forever.
Winners that required a moved stop are not proof the edit was skill. They are often luck with extra risk. Making edits visible in the log was what reduced them -- shame works better than slogans.
How do you make stop edits visible enough that you cannot pretend they did not happen?
Platforms that make stop edits too easy need extra friction -- I sometimes use alerts at the stop instead of constant dragging. If the alert fires, I flatten or accept the planned loss. Dragging becomes a conscious violation, which is easier to tag than a "tiny adjustment" story.
Great post. That lie we tell ourselves about "giving it room" is exactly what turns a standard, planned loss into a severe psychological and financial drawdown. The moment we widen a stop, we aren't trading the original setup anymore; we are just funding our own refusal to be wrong.
When relying on raw price action—especially when mapping out structure on M15 or daily charts—the invalidation point is dictated strictly by the market, not our pain tolerance. If a structural swing breaks or a liquidity sweep fails to hold, the setup is objectively dead. Dragging the line lower just means holding onto a broken thesis and hoping for a bailout.
To answer your question about making edits visible: removing the temptation of seamless UI dragging is the best defense. If a platform makes it too easy to just click and slide a stop order on the chart, you have to engineer your own friction. Relying on an alert slightly ahead of the actual stop, as you mentioned, is a brilliant way to force a conscious intervention rather than a reflexive drag.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Beating moving stops as a scalper: rules that stuck
Here is a tool to help enforce that exact friction in TradingView.
Pine Script: Strict Invalidation & Alert Anchor
Because TradingView natively allows you to easily drag active orders around the chart, this script creates a rigid, visual "Hard Stop" line independent of your broker integration.
It uses the confirm=true argument on the inputs. When you add this indicator to your chart, it forces you to physically click the exact entry and stop levels on the chart. Once set, the lines cannot be dragged. To change them, you are forced to open the indicator settings menu—adding that necessary layer of psychological friction and making any "edit" a highly conscious choice. It also sets up the early warning alert buffer you mentioned.
Pine Script: Strict Invalidation & Alert Anchor
Because TradingView natively allows you to easily drag active orders around the chart, this script creates a rigid, visual "Hard Stop" line independent of your broker integration.
It uses the confirm=true argument on the inputs. When you add this indicator to your chart, it forces you to physically click the exact entry and stop levels on the chart. Once set, the lines cannot be dragged. To change them, you are forced to open the indicator settings menu—adding that necessary layer of psychological friction and making any "edit" a highly conscious choice. It also sets up the early warning alert buffer you mentioned.
Code: Select all
//@version=5
indicator("Strict Invalidation Anchor & Buffer Alert", overlay=true)
// 1. Interactive Inputs: Forces you to click the chart to set levels (adds friction)
in_entry = input.price(0.0, title="Entry Price", confirm=true)
in_stop = input.price(0.0, title="Hard Invalidation (Stop)", confirm=true)
in_dir = input.string("Long", title="Trade Direction", options=["Long", "Short"])
// 2. Alert Buffer Settings
buffer_ticks = input.int(10, title="Alert Buffer (Ticks/Pips prior to stop)")
// Calculate levels
var float hard_stop = in_stop
var float entry_price = in_entry
// 3. Plotting the immutable lines
plot(entry_price > 0 ? entry_price : na, color=color.new(color.blue, 30), style=plot.style_solid, linewidth=1, title="Entry")
plot(hard_stop > 0 ? hard_stop : na, color=color.new(color.red, 0), style=plot.style_linebr, linewidth=2, title="Hard Stop")
// 4. Calculate and plot the early warning alert zone
tick_size = syminfo.mintick
alert_level = in_dir == "Long" ? hard_stop + (buffer_ticks * tick_size) : hard_stop - (buffer_ticks * tick_size)
plot(hard_stop > 0 ? alert_level : na, color=color.new(color.orange, 0), style=plot.style_cross, linewidth=1, title="Alert Zone")
// 5. Alert Conditions
long_alert = in_dir == "Long" and ta.crossunder(low, alert_level)
short_alert = in_dir == "Short" and ta.crossover(high, alert_level)
if (long_alert or short_alert)
alert("Price is hitting your buffer zone! Accept the planned loss. DO NOT DRAG THE STOP.", alert.freq_once_per_bar_close)Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Beating moving stops as a scalper: rules that stuck
How to use it to kill the habit:
1.) Enter your trade and place your actual broker stop loss.
2.) Add this indicator to the chart. Click your entry, then click your structural invalidation point.
3.) Set an alert on the indicator in TradingView.
4.) The script paints a thick red line that cannot be moved with the mouse, alongside an orange crossed line (the buffer). If price touches the orange line, the alert fires off your pre-written warning, reminding you to accept the loss before the temptation to drag the real stop kicks in.
1.) Enter your trade and place your actual broker stop loss.
2.) Add this indicator to the chart. Click your entry, then click your structural invalidation point.
3.) Set an alert on the indicator in TradingView.
4.) The script paints a thick red line that cannot be moved with the mouse, alongside an orange crossed line (the buffer). If price touches the orange line, the alert fires off your pre-written warning, reminding you to accept the loss before the temptation to drag the real stop kicks in.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Beating moving stops as a scalper: rules that stuck
Regarding visibility and execution friction: retail trading platform UIs are built for convenience, making drag-and-drop order edits dangerously seamless. Engineering your own operational friction is a necessary defense mechanism.
Below is a more advanced, institutional-grade Pine Script solution. Rather than relying on basic plots, this script constructs an "Execution Matrix" using immutable line and label objects. By utilizing the confirm=true parameter, it forces you to physically anchor your entry, stop, and target levels via chart clicks. Once anchored, they cannot be manipulated on the chart interface. To modify them, you are forced to open the script's settings menu—creating a hard, physical interrupt to break the psychological loop of a "tiny adjustment."
Pine Script: Immutable Execution Matrix & Invalidation Anchor
This script calculates your exact risk in ticks/points, displays the R-multiple if a target is set, and generates a dynamic alert buffer zone calculated as a percentage of your total risk.
Below is a more advanced, institutional-grade Pine Script solution. Rather than relying on basic plots, this script constructs an "Execution Matrix" using immutable line and label objects. By utilizing the confirm=true parameter, it forces you to physically anchor your entry, stop, and target levels via chart clicks. Once anchored, they cannot be manipulated on the chart interface. To modify them, you are forced to open the script's settings menu—creating a hard, physical interrupt to break the psychological loop of a "tiny adjustment."
Pine Script: Immutable Execution Matrix & Invalidation Anchor
This script calculates your exact risk in ticks/points, displays the R-multiple if a target is set, and generates a dynamic alert buffer zone calculated as a percentage of your total risk.
Code: Select all
//@version=5
indicator("Execution Matrix: Immutable Invalidation", overlay=true, max_lines_count=10, max_labels_count=10)
// --- [ INTERACTIVE ANCHORS: FORCES CHART CLICKS (FRICTION) ] ---
i_entry = input.price(0.0, title="1. Anchor Entry Price", confirm=true)
i_stop = input.price(0.0, title="2. Anchor Invalidation (Stop Loss)", confirm=true)
i_tp = input.price(0.0, title="3. Anchor Target (Optional TP)", confirm=true)
// --- [ EXECUTION PARAMETERS ] ---
grp_risk = "Risk & Alert Parameters"
i_buffer_pct = input.int(15, title="Warning Buffer (% of Risk)", minval=1, maxval=50, group=grp_risk, tooltip="Alert fires when price breaches this percentage of your risk zone.")
// --- [ STATE VARIABLES & CALCULATIONS ] ---
var float entry_px = i_entry
var float stop_px = i_stop
var float tp_px = i_tp
var bool is_long = entry_px > stop_px
var bool is_short = entry_px < stop_px
var bool is_active = entry_px != 0 and stop_px != 0
var float risk_range = math.abs(entry_px - stop_px)
var float reward_range = tp_px != 0 ? math.abs(tp_px - entry_px) : na
var float r_multiple = reward_range / risk_range
// Calculate dynamic warning buffer level based on % of risk
var float buffer_dist = risk_range * (i_buffer_pct / 100.0)
var float warning_lvl = is_long ? (stop_px + buffer_dist) : (stop_px - buffer_dist)
// --- [ UI RENDERING (LAST BAR ONLY) ] ---
if barstate.islast and is_active
// Define UI styling
color c_entry = color.new(color.blue, 0)
color c_stop = color.new(color.red, 0)
color c_tp = color.new(color.teal, 0)
color c_warn = color.new(color.orange, 0)
// Draw Immutable Lines (Cannot be dragged on the chart)
line.new(x1=bar_index - 10, y1=entry_px, x2=bar_index + 10, y2=entry_px, color=c_entry, width=2, style=line.style_solid)
line.new(x1=bar_index - 10, y1=stop_px, x2=bar_index + 10, y2=stop_px, color=c_stop, width=3, style=line.style_solid)
line.new(x1=bar_index - 10, y1=warning_lvl, x2=bar_index + 10, y2=warning_lvl, color=c_warn, width=1, style=line.style_dashed)
if tp_px != 0
line.new(x1=bar_index - 10, y1=tp_px, x2=bar_index + 10, y2=tp_px, color=c_tp, width=2, style=line.style_solid)
// Draw Information Labels
string txt_stop = "INVALIDATION\nRisk: " + str.tostring(risk_range / syminfo.mintick, "#.##") + " Ticks"
label.new(x=bar_index + 12, y=stop_px, text=txt_stop, color=color.new(c_stop, 80), style=label.style_label_left, textcolor=color.white, size=size.small)
label.new(x=bar_index + 12, y=warning_lvl, text=str.tostring(i_buffer_pct) + "% Buffer Alert", color=color.new(c_warn, 80), style=label.style_label_left, textcolor=color.white, size=size.small)
if tp_px != 0
string txt_tp = "TARGET\nReward: " + str.tostring(reward_range / syminfo.mintick, "#.##") + " Ticks\nR: " + str.tostring(r_multiple, "#.##")
label.new(x=bar_index + 12, y=tp_px, text=txt_tp, color=color.new(c_tp, 80), style=label.style_label_left, textcolor=color.white, size=size.small)
// --- [ ALERT CONDITION LOGIC ] ---
bool cross_long_warn = is_long and ta.crossunder(low, warning_lvl)
bool cross_short_warn = is_short and ta.crossover(high, warning_lvl)
if (cross_long_warn or cross_short_warn)
alert("CRITICAL: Price has breached your " + str.tostring(i_buffer_pct) + "% risk buffer zone. Prepare to execute planned invalidation. DO NOT WIDEN STOP.", alert.freq_once_per_bar_close)Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Beating moving stops as a scalper: rules that stuck
Implementation Directives:
Initialization: When you apply this indicator, TradingView will suspend the chart and force you to point-and-click your exact Entry, Hard Stop, and Target.
Immutable Rendering: It uses line.new() and label.new() localized to the current price action. These objects are locked. You cannot highlight or drag them.
Dynamic Buffer: Instead of a static tick count, the early warning alert calculates a percentage of your structural risk (e.g., the last 15% of the distance before the stop). When that dashed orange line is hit, your terminal alerts you to face the music before the stop is tested.
Initialization: When you apply this indicator, TradingView will suspend the chart and force you to point-and-click your exact Entry, Hard Stop, and Target.
Immutable Rendering: It uses line.new() and label.new() localized to the current price action. These objects are locked. You cannot highlight or drag them.
Dynamic Buffer: Instead of a static tick count, the early warning alert calculates a percentage of your structural risk (e.g., the last 15% of the distance before the stop). When that dashed orange line is hit, your terminal alerts you to face the music before the stop is tested.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Beating moving stops as a scalper: rules that stuck
For maximum friction, this script includes a HardcoreMode toggle. If enabled, the EA will actively fight you: if it detects the native SL has been dragged wider than the Ghost Anchor, it instantly sends an order modification to snap the stop back to the original level.
MQL5 Implementation: The Ghost Anchor EA
Because of the C#-like syntax and robust position management, MQL5 handles this elegantly via OnTick(). It loops through open positions, anchors them, and actively monitors for UI manipulation.
MQL5 Implementation: The Ghost Anchor EA
Because of the C#-like syntax and robust position management, MQL5 handles this elegantly via OnTick(). It loops through open positions, anchors them, and actively monitors for UI manipulation.
Code: Select all
//+------------------------------------------------------------------+
//| GhostAnchor_Invalidation.mq5 |
//| Strict Invalidation, Buffer Alerts, and Stop Enforcement |
//+------------------------------------------------------------------+
#property strict
#include <Trade\Trade.mqh>
input string Grp1 = "--- Risk & Alert Parameters ---";
input double InpBufferPercent = 15.0; // Warning Buffer (% of Risk)
input bool InpHardcoreMode = true; // Hardcore Mode: Snap SL back if widened
CTrade trade;
void OnTick()
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
double open_price = PositionGetDouble(POSITION_PRICE_OPEN);
double current_sl = PositionGetDouble(POSITION_SL);
long pos_type = PositionGetInteger(POSITION_TYPE);
if(current_sl == 0) continue; // Ignore trades without a stop
string anchor_name = "Anchor_SL_" + IntegerToString(ticket);
string buffer_name = "Buffer_SL_" + IntegerToString(ticket);
// 1. CREATE IMMUTABLE ANCHORS (Executes once per trade)
if(ObjectFind(0, anchor_name) < 0)
{
// Create Ghost Anchor
DrawImmutableLine(anchor_name, current_sl, clrRed, STYLE_SOLID, 2);
ObjectSetString(0, anchor_name, OBJPROP_TEXT, "ORIGINAL INVALIDATION");
// Calculate & Create 15% Buffer Zone
double risk = MathAbs(open_price - current_sl);
double buffer_dist = risk * (InpBufferPercent / 100.0);
double buffer_price = (pos_type == POSITION_TYPE_BUY) ? current_sl + buffer_dist : current_sl - buffer_dist;
DrawImmutableLine(buffer_name, buffer_price, clrOrange, STYLE_DASH, 1);
ObjectSetString(0, buffer_name, OBJPROP_TEXT, "ALERT_READY"); // State tracker
}
else
{
// 2. MONITOR FOR STOP WIDENING
double original_sl = ObjectGetDouble(0, anchor_name, OBJPROP_PRICE);
// Check if user dragged the native line
if(NormalizeDouble(current_sl, _Digits) != NormalizeDouble(original_sl, _Digits))
{
bool is_widened = (pos_type == POSITION_TYPE_BUY && current_sl < original_sl) ||
(pos_type == POSITION_TYPE_SELL && current_sl > original_sl);
if(is_widened && InpHardcoreMode)
{
Print("VIOLATION DETECTED: Stop widened. Snapping back to structural anchor.");
trade.PositionModify(ticket, original_sl, PositionGetDouble(POSITION_TP));
}
}
// 3. BUFFER BREACH ALERT
double buffer_price = ObjectGetDouble(0, buffer_name, OBJPROP_PRICE);
string alert_state = ObjectGetString(0, buffer_name, OBJPROP_TEXT);
double current_price = (pos_type == POSITION_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_BID) : SymbolInfoDouble(_Symbol, SYMBOL_ASK);
bool breached = (pos_type == POSITION_TYPE_BUY && current_price <= buffer_price) ||
(pos_type == POSITION_TYPE_SELL && current_price >= buffer_price);
if(breached && alert_state == "ALERT_READY")
{
Alert("CRITICAL: Price breached ", InpBufferPercent, "% buffer on ", _Symbol, ". Accept the planned loss.");
ObjectSetString(0, buffer_name, OBJPROP_TEXT, "ALERT_FIRED"); // Prevent alert spam
}
}
}
}
//+------------------------------------------------------------------+
//| Utility: Draws lines that cannot be clicked or dragged |
//+------------------------------------------------------------------+
void DrawImmutableLine(string name, double price, color clr, ENUM_LINE_STYLE style, int width)
{
ObjectCreate(0, name, OBJ_HLINE, 0, 0, price);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_STYLE, style);
ObjectSetInteger(0, name, OBJPROP_WIDTH, width);
ObjectSetInteger(0, name, OBJPROP_BACK, true);
// The Friction: Prevent interaction
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_SELECTED, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true); // Hides from the Object List (Ctrl+B)
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Beating moving stops as a scalper: rules that stuck
MT4 Adaptation Logic
If you are deploying this on older MT4 terminals, the object creation logic (DrawImmutableLine) remains identical, but the loop needs to be adapted to the older MQL4 procedural order selection:
1.) Replace the PositionsTotal() loop with an OrdersTotal() loop.
2.) Use OrderSelect(i, SELECT_BY_POS, MODE_TRADES).
3.) Swap position getters for OrderTicket(), OrderOpenPrice(), OrderStopLoss(), and OrderType().
4.) If InpHardcoreMode triggers, replace the trade.PositionModify OOP call with the standard OrderModify(OrderTicket(), OrderOpenPrice(), original_sl, OrderTakeProfit(), 0, clrNONE).
By completely disabling OBJPROP_SELECTABLE and hiding the object from the terminal's object list, the Ghost Anchor requires a deliberate script uninstallation to remove. If price action on the M15 or Daily dictates that the trade is dead, this forces you to either face the loss or battle your own code to avoid it.
If you are deploying this on older MT4 terminals, the object creation logic (DrawImmutableLine) remains identical, but the loop needs to be adapted to the older MQL4 procedural order selection:
1.) Replace the PositionsTotal() loop with an OrdersTotal() loop.
2.) Use OrderSelect(i, SELECT_BY_POS, MODE_TRADES).
3.) Swap position getters for OrderTicket(), OrderOpenPrice(), OrderStopLoss(), and OrderType().
4.) If InpHardcoreMode triggers, replace the trade.PositionModify OOP call with the standard OrderModify(OrderTicket(), OrderOpenPrice(), original_sl, OrderTakeProfit(), 0, clrNONE).
By completely disabling OBJPROP_SELECTABLE and hiding the object from the terminal's object list, the Ghost Anchor requires a deliberate script uninstallation to remove. If price action on the M15 or Daily dictates that the trade is dead, this forces you to either face the loss or battle your own code to avoid it.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Beating moving stops as a scalper: rules that stuck
MQL4 Source Code (GhostAnchor_Invalidation.mq4)
Code: Select all
//+------------------------------------------------------------------+
//| GhostAnchor_Invalidation.mq4 |
//| Strict Invalidation & Stop Enforcement for MT4 |
//+------------------------------------------------------------------+
#property copyright "Execution Matrix"
#property link ""
#property version "1.00"
#property strict
// --- Input Parameters ---
input string InpSectionRisk = "--- Risk & Alert Settings ---";
input double InpBufferPercent = 15.0; // Warning Buffer (% of total risk)
input bool InpHardcoreMode = true; // Hardcore Mode: Snap SL back if widened
input int InpSlippage = 3; // Slippage for OrderModify (points)
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
Print("GhostAnchor EA initialized on ", Symbol(), ". Strict execution active.");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Clean up lines when EA is removed from the chart
CleanUpOrphanedAnchors();
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
// Filter: only current chart symbol and open market positions
if(OrderSymbol() != Symbol()) continue;
int order_type = OrderType();
if(order_type != OP_BUY && order_type != OP_SELL) continue;
int ticket = OrderTicket();
double open_price = OrderOpenPrice();
double current_sl = OrderStopLoss();
// Skip orders entered without an initial stop loss
if(current_sl == 0.0) continue;
string anchor_name = "GhostAnchor_SL_" + IntegerToString(ticket);
string buffer_name = "GhostBuffer_SL_" + IntegerToString(ticket);
// 1. FIRST-TIME REGISTRATION: Anchor original structural invalidation
if(ObjectFind(0, anchor_name) < 0)
{
// Create the immutable Ghost Anchor
DrawImmutableLine(anchor_name, current_sl, clrRed, STYLE_SOLID, 2);
ObjectSetString(0, anchor_name, OBJPROP_TEXT, "ORIGINAL_SL");
// Calculate & create the warning buffer line
double risk_range = MathAbs(open_price - current_sl);
double buffer_dist = risk_range * (InpBufferPercent / 100.0);
double buffer_price = (order_type == OP_BUY) ? (current_sl + buffer_dist) : (current_sl - buffer_dist);
DrawImmutableLine(buffer_name, buffer_price, clrOrange, STYLE_DASH, 1);
ObjectSetString(0, buffer_name, OBJPROP_TEXT, "ALERT_READY"); // State flag
}
else
{
// 2. CHECK FOR STOP LOSS WIDENING
double original_sl = ObjectGetDouble(0, anchor_name, OBJPROP_PRICE);
// Normalize values for comparison
double norm_current = NormalizeDouble(current_sl, Digits);
double norm_original = NormalizeDouble(original_sl, Digits);
if(norm_current != norm_original)
{
bool is_widened = (order_type == OP_BUY && norm_current < norm_original) ||
(order_type == OP_SELL && norm_current > norm_original);
if(is_widened)
{
Print("VIOLATION [Ticket #", ticket, "]: Stop widened beyond initial invalidation.");
if(InpHardcoreMode)
{
Print("HARDCORE ENFORCEMENT: Snapping Stop Loss back to ", original_sl);
bool res = OrderModify(ticket, open_price, original_sl, OrderTakeProfit(), 0, clrRed);
if(!res)
{
Print("OrderModify Error: ", GetLastError());
}
}
}
}
// 3. MONITOR WARNING BUFFER BREACH
double buffer_price = ObjectGetDouble(0, buffer_name, OBJPROP_PRICE);
string alert_state = ObjectGetString(0, buffer_name, OBJPROP_TEXT);
double current_price = (order_type == OP_BUY) ? Bid : Ask;
bool breached = (order_type == OP_BUY && current_price <= buffer_price) ||
(order_type == OP_SELL && current_price >= buffer_price);
if(breached && alert_state == "ALERT_READY")
{
Alert("EXECUTION ALERT: Price breached ", InpBufferPercent, "% buffer on ", Symbol(),
" [Ticket #", ticket, "]. Stand down and accept the planned loss.");
ObjectSetString(0, buffer_name, OBJPROP_TEXT, "ALERT_FIRED"); // Prevent multiple alert popups
}
}
}
// 4. CLEAN UP CLOSED TRADES
CleanUpOrphanedAnchors();
}
//+------------------------------------------------------------------+
//| Utility: Render locked lines hidden from standard chart UI |
//+------------------------------------------------------------------+
void DrawImmutableLine(string name, double price, color clr, int style, int width)
{
ObjectCreate(0, name, OBJ_HLINE, 0, 0, price);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_STYLE, style);
ObjectSetInteger(0, name, OBJPROP_WIDTH, width);
ObjectSetInteger(0, name, OBJPROP_BACK, true);
// Friction setup: Lock selection and hide from standard Object List dialog
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_SELECTED, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, true);
}
//+------------------------------------------------------------------+
//| Utility: Clean up anchor objects for tickets that no longer exist|
//+------------------------------------------------------------------+
void CleanUpOrphanedAnchors()
{
int total_objects = ObjectsTotal(0, -1, OBJ_HLINE);
for(int i = total_objects - 1; i >= 0; i--)
{
string obj_name = ObjectName(0, i, -1, OBJ_HLINE);
if(StringFind(obj_name, "GhostAnchor_SL_") >= 0 || StringFind(obj_name, "GhostBuffer_SL_") >= 0)
{
// Extract the ticket number from object name
string ticket_str = "";
if(StringFind(obj_name, "GhostAnchor_SL_") >= 0)
ticket_str = StringSubstr(obj_name, StringLen("GhostAnchor_SL_"));
else
ticket_str = StringSubstr(obj_name, StringLen("GhostBuffer_SL_"));
int ticket = (int)StringToInteger(ticket_str);
// Check if ticket is still active
bool still_open = false;
for(int j = OrdersTotal() - 1; j >= 0; j--)
{
if(OrderSelect(j, SELECT_BY_POS, MODE_TRADES))
{
if(OrderTicket() == ticket)
{
still_open = true;
break;
}
}
}
// If the position closed or stopped out, delete the lines
if(!still_open)
{
ObjectDelete(0, obj_name);
}
}
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Beating moving stops as a scalper: rules that stuck
Installation Steps in MetaTrader 4
1.) Open MT4 and press F4 to launch the MetaEditor.
2.) Go to File -> New -> Expert Advisor (template) and name it GhostAnchor_Invalidation.
3.) Paste the code into the editor, click Compile, and ensure there are 0 errors and 0 warnings.
4.) Drag the EA from your Navigator (Ctrl+N) onto your chart.
5.) In the EA properties dialog under the Common tab, make sure "Allow live trading" is checked (required so OrderModify() has permission to snap the stop loss back if widened).
1.) Open MT4 and press F4 to launch the MetaEditor.
2.) Go to File -> New -> Expert Advisor (template) and name it GhostAnchor_Invalidation.
3.) Paste the code into the editor, click Compile, and ensure there are 0 errors and 0 warnings.
4.) Drag the EA from your Navigator (Ctrl+N) onto your chart.
5.) In the EA properties dialog under the Common tab, make sure "Allow live trading" is checked (required so OrderModify() has permission to snap the stop loss back if widened).
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.