The NY "Silver Bullet": How Smart Money Exploits the 10 AM Window
Re: The NY "Silver Bullet": How Smart Money Exploits the 10 AM Window
Execution Notes
Broker Time Configuration: The string inputs 10:00 and 11:00 check your terminal's local broker time, not strict EST. You will need to calculate your ECN broker's offset to Eastern Standard Time (typically shifting the inputs to 15:00 or 16:00 depending on Daylight Saving Time) and apply those shifted strings in the EA settings.
Raw Price Spread Reality: On high-speed ECN accounts, limit orders placed mathematically exactly on the FVG extreme won't trigger if the spread fails to clear the Ask line (for longs) or Bid line (for shorts). You may need to subtract half a pip (0.00005 or 0.05 on JPY pairs) from the MT4/MT5 limits to guarantee a fill during rapid 1-minute chart retracements.
Broker Time Configuration: The string inputs 10:00 and 11:00 check your terminal's local broker time, not strict EST. You will need to calculate your ECN broker's offset to Eastern Standard Time (typically shifting the inputs to 15:00 or 16:00 depending on Daylight Saving Time) and apply those shifted strings in the EA settings.
Raw Price Spread Reality: On high-speed ECN accounts, limit orders placed mathematically exactly on the FVG extreme won't trigger if the spread fails to clear the Ask line (for longs) or Bid line (for shorts). You may need to subtract half a pip (0.00005 or 0.05 on JPY pairs) from the MT4/MT5 limits to guarantee a fill during rapid 1-minute chart retracements.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The NY "Silver Bullet": How Smart Money Exploits the 10 AM Window
Order rejections—specifically MT4's Error 130 and MT5's Code 10016 (Invalid Stops)—are often the "silent killers" of automated scalping systems. Because limits and stop-losses in the Silver Bullet strategy are placed extremely close to the current market price, they frequently collide with the broker's dynamically changing StopsLevel (minimum distance for SL/TP) or FreezeLevel (minimum distance to modify pending orders).
To effectively track this, the logging tool must capture the exact market microstructure (Ask, Bid, minimum broker limits) at the exact millisecond the rejection occurs.
To effectively track this, the logging tool must capture the exact market microstructure (Ask, Bid, minimum broker limits) at the exact millisecond the rejection occurs.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The NY "Silver Bullet": How Smart Money Exploits the 10 AM Window
1. MT5 Rejection Logger (MQL5)
MT5 uses the MqlTradeResult structure inside the CTrade class to evaluate execution errors. Place this function at the bottom of your MT5 EA. It logs to the terminal journal and generates a persistent .csv file for offline analysis.
MT5 uses the MqlTradeResult structure inside the CTrade class to evaluate execution errors. Place this function at the bottom of your MT5 EA. It logs to the terminal journal and generates a persistent .csv file for offline analysis.
Code: Select all
//+------------------------------------------------------------------+
//| MT5 Rejection Logger |
//+------------------------------------------------------------------+
void LogTradeRejectionMT5(ENUM_ORDER_TYPE orderType, double entryPrice, double stopLoss, double takeProfit, uint retcode) {
// Ignore successful executions
if(retcode == TRADE_RETCODE_PLACED || retcode == TRADE_RETCODE_DONE) return;
string action = EnumToString(orderType);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
// Convert broker limit levels to actual price distances
double stopsLvl = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
double freezeLvl = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_FREEZE_LEVEL) * SymbolInfoDouble(_Symbol, SYMBOL_POINT);
string logMsg = StringFormat(
"%s | SYM: %s | TYPE: %s | ENTRY: %.5f | SL: %.5f | TP: %.5f | ASK: %.5f | BID: %.5f | STOPS_LVL: %.5f | FREEZE_LVL: %.5f | ERR: %d",
TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS), _Symbol, action,
entryPrice, stopLoss, takeProfit, ask, bid, stopsLvl, freezeLvl, retcode
);
// Print to terminal journal
Print("🚨 REJECTION: ", logMsg);
// Write to a persistent CSV for external analysis
int handle = FileOpen("SilverBullet_Rejections_MT5.csv", FILE_READ|FILE_WRITE|FILE_TXT|FILE_ANSI);
if(handle != INVALID_HANDLE) {
FileSeek(handle, 0, SEEK_END);
FileWrite(handle, logMsg);
FileClose(handle);
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The NY "Silver Bullet": How Smart Money Exploits the 10 AM Window
2. MT4 Rejection Logger (MQL4)
In MT4, a failed OrderSend() command resets the system error cache, meaning you must immediately capture the error code using GetLastError() before executing any other commands.
In MT4, a failed OrderSend() command resets the system error cache, meaning you must immediately capture the error code using GetLastError() before executing any other commands.
Code: Select all
//+------------------------------------------------------------------+
//| MT4 Rejection Logger |
//+------------------------------------------------------------------+
#include <stdlib.mqh> // Required for ErrorDescription()
void LogTradeRejectionMT4(int cmd, double entryPrice, double stopLoss, double takeProfit, int errorCode) {
// Ignore successful executions
if(errorCode == 0) return;
string action = "UNKNOWN";
if(cmd == OP_BUYLIMIT) action = "BUY_LIMIT";
if(cmd == OP_SELLLIMIT) action = "SELL_LIMIT";
// Convert broker limit levels to actual price distances
double stopsLvl = MarketInfo(Symbol(), MODE_STOPLEVEL) * Point;
double freezeLvl = MarketInfo(Symbol(), MODE_FREEZELEVEL) * Point;
string logMsg = StringFormat(
"%s | SYM: %s | TYPE: %s | ENTRY: %.5f | SL: %.5f | TP: %.5f | ASK: %.5f | BID: %.5f | STOPS_LVL: %.5f | FREEZE_LVL: %.5f | ERR: %d (%s)",
TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS), Symbol(), action,
entryPrice, stopLoss, takeProfit, Ask, Bid, stopsLvl, freezeLvl, errorCode, ErrorDescription(errorCode)
);
// Print to terminal journal
Print("🚨 REJECTION: ", logMsg);
// Write to a persistent CSV for external analysis
int handle = FileOpen("SilverBullet_Rejections_MT4.csv", FILE_READ|FILE_WRITE|FILE_TXT|FILE_ANSI);
if(handle != INVALID_HANDLE) {
FileSeek(handle, 0, SEEK_END);
FileWrite(handle, logMsg);
FileClose(handle);
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The NY "Silver Bullet": How Smart Money Exploits the 10 AM Window
3. Integrating the Loggers into the EAs
To activate the logging architecture, locate the ExecuteLimitOrder() function in both EAs and replace the default order placement blocks with the routed logic below.
For MT5 (ICT_SilverBullet_MT5.mq5):
To activate the logging architecture, locate the ExecuteLimitOrder() function in both EAs and replace the default order placement blocks with the routed logic below.
For MT5 (ICT_SilverBullet_MT5.mq5):
Code: Select all
if(type == ORDER_TYPE_BUY_LIMIT) {
if(trade.BuyLimit(lotSize, entryNorm, _Symbol, slNorm, tpNorm, ORDER_TIME_GTC, 0, "Silver Bullet Long")) {
tradeTakenThisSession = true;
} else {
// Check the Trade Result Return Code immediately after rejection
LogTradeRejectionMT5(ORDER_TYPE_BUY_LIMIT, entryNorm, slNorm, tpNorm, trade.ResultRetcode());
}
} else {
if(trade.SellLimit(lotSize, entryNorm, _Symbol, slNorm, tpNorm, ORDER_TIME_GTC, 0, "Silver Bullet Short")) {
tradeTakenThisSession = true;
} else {
LogTradeRejectionMT5(ORDER_TYPE_SELL_LIMIT, entryNorm, slNorm, tpNorm, trade.ResultRetcode());
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The NY "Silver Bullet": How Smart Money Exploits the 10 AM Window
For MT4 (ICT_SilverBullet_MT4.mq4):
Code: Select all
color arrColor = (opType == OP_BUYLIMIT) ? clrGreen : clrRed;
int ticket = OrderSend(Symbol(), opType, lotSize, entryNorm, 3, slNorm, tpNorm, "Silver Bullet", InpMagicNumber, 0, arrColor);
if(ticket > 0) {
tradeTakenThisSession = true;
} else {
// Capture the error from the system variable immediately
int err = GetLastError();
LogTradeRejectionMT4(opType, entryNorm, slNorm, tpNorm, err);
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The NY "Silver Bullet": How Smart Money Exploits the 10 AM Window
Key insight: You will most frequently encounter these rejections during the actual 10:00 AM sweep when sudden liquidity spikes cause the ECN broker's spreads and stop levels to dynamically widen beyond the tight parameters of the 1-minute FVG entry window.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The NY "Silver Bullet": How Smart Money Exploits the 10 AM Window
Here is the complete cBot translated for cTrader (cAlgo) using C#.
Because cTrader operates on a modern .NET environment, we can take advantage of explicit TimeZoneInfo handling to ensure the 10:00 AM EST window is rigidly enforced regardless of your broker's server time.
Additionally, the cTrader TradeResult object provides robust, built-in error handling. This script captures the exact ErrorCode, Bid/Ask spreads, and pip distances at the moment of an InvalidStopLossTakeProfit rejection and writes it persistently to a CSV file in your local Documents folder.
The ICT Silver Bullet cBot (C#)
Because cTrader operates on a modern .NET environment, we can take advantage of explicit TimeZoneInfo handling to ensure the 10:00 AM EST window is rigidly enforced regardless of your broker's server time.
Additionally, the cTrader TradeResult object provides robust, built-in error handling. This script captures the exact ErrorCode, Bid/Ask spreads, and pip distances at the moment of an InvalidStopLossTakeProfit rejection and writes it persistently to a CSV file in your local Documents folder.
The ICT Silver Bullet cBot (C#)
Code: Select all
using System;
using System.IO;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
namespace cAlgo.Robots
{
// AccessRights.File is required to write rejection logs to your local drive
[Robot(TimeZone = TimeZones.EasternStandardTime, AccessRights = AccessRights.File)]
public class ICTSilverBullet : Robot
{
[Parameter("Session Start (EST)", Group = "Time Window", DefaultValue = "10:00")]
public string SessionStartStr { get; set; }
[Parameter("Session End (EST)", Group = "Time Window", DefaultValue = "11:00")]
public string SessionEndStr { get; set; }
[Parameter("Risk/Reward Ratio", Group = "Strategy Parameters", DefaultValue = 2.0)]
public double RiskReward { get; set; }
[Parameter("Sweep Lookback", Group = "Strategy Parameters", DefaultValue = 10)]
public int SwingLength { get; set; }
[Parameter("Enable HTF Filter", Group = "Higher Timeframe Filter", DefaultValue = true)]
public bool UseHtfFilter { get; set; }
[Parameter("HTF Timeframe", Group = "Higher Timeframe Filter", DefaultValue = "Hour4")]
public TimeFrame HtfTimeframe { get; set; }
[Parameter("HTF EMA Length", Group = "Higher Timeframe Filter", DefaultValue = 20)]
public int HtfEmaLength { get; set; }
[Parameter("Risk % Per Trade", Group = "Risk Management", DefaultValue = 2.0)]
public double RiskPercent { get; set; }
private TimeSpan _sessionStart;
private TimeSpan _sessionEnd;
private bool _tradeTakenThisSession;
private bool _wasInSession;
private string _label = "SilverBullet";
private Bars _htfBars;
private ExponentialMovingAverage _htfEma;
protected override void OnStart()
{
TimeSpan.TryParse(SessionStartStr, out _sessionStart);
TimeSpan.TryParse(SessionEndStr, out _sessionEnd);
if (UseHtfFilter)
{
_htfBars = MarketData.GetBars(HtfTimeframe);
_htfEma = Indicators.ExponentialMovingAverage(_htfBars.ClosePrices, HtfEmaLength);
}
}
protected override void OnBar()
{
// Server.Time strictly aligns with EST because of the Robot Attribute TimeZone
TimeSpan currentTime = Server.Time.TimeOfDay;
bool inSession = currentTime >= _sessionStart && currentTime < _sessionEnd;
if (inSession && !_wasInSession)
_tradeTakenThisSession = false;
if (!inSession && _wasInSession)
CancelAllPending();
_wasInSession = inSession;
// Prevent scanning if we are outside the window or already positioned
if (!inSession || _tradeTakenThisSession || IsTradeActive())
return;
// 1. Higher Timeframe Bias
bool bullishBias = true, bearishBias = true;
if (UseHtfFilter)
{
// Pull index Count-2 to get the LAST CLOSED H4 candle, avoiding repaint logic
int htfIndex = _htfBars.ClosePrices.Count - 2;
if (htfIndex >= 0)
{
double htfClose = _htfBars.ClosePrices[htfIndex];
double emaValue = _htfEma.Result[htfIndex];
bullishBias = htfClose > emaValue;
bearishBias = htfClose < emaValue;
}
}
// Ensure we have enough bars to scan
if (Bars.Count < SwingLength + 3) return;
// 2. Liquidity Sweep Detection (Scanning Bars 3 through 3+SwingLength)
double recentHigh = double.MinValue;
double recentLow = double.MaxValue;
for (int i = 3; i < 3 + SwingLength; i++)
{
recentHigh = Math.Max(recentHigh, Bars.HighPrices.Last(i));
recentLow = Math.Min(recentLow, Bars.LowPrices.Last(i));
}
bool sweptHigh = Bars.HighPrices.Last(1) >= recentHigh || Bars.HighPrices.Last(0) >= recentHigh;
bool sweptLow = Bars.LowPrices.Last(1) <= recentLow || Bars.LowPrices.Last(0) <= recentLow;
// 3. FVG (Imbalance) Detection
bool isBullishFvg = Bars.LowPrices.Last(0) > Bars.HighPrices.Last(2) && Bars.ClosePrices.Last(1) > Bars.OpenPrices.Last(1);
bool isBearishFvg = Bars.HighPrices.Last(0) < Bars.LowPrices.Last(2) && Bars.ClosePrices.Last(1) < Bars.OpenPrices.Last(1);
// 4. Execution Logic
if (sweptLow && isBullishFvg && bullishBias)
{
double entryLimit = Bars.HighPrices.Last(2);
double sl = Math.Min(Bars.LowPrices.Last(0), Math.Min(Bars.LowPrices.Last(1), Bars.LowPrices.Last(2)));
ExecuteLimitOrder(TradeType.Buy, entryLimit, sl);
}
else if (sweptHigh && isBearishFvg && bearishBias)
{
double entryLimit = Bars.LowPrices.Last(2);
double sl = Math.Max(Bars.HighPrices.Last(0), Math.Max(Bars.HighPrices.Last(1), Bars.HighPrices.Last(2)));
ExecuteLimitOrder(TradeType.Sell, entryLimit, sl);
}
}
// =========================================================================
// TRADE EXECUTION & SIZING
// =========================================================================
private void ExecuteLimitOrder(TradeType tradeType, double entryLimit, double stopLoss)
{
double riskInPrice = Math.Abs(entryLimit - stopLoss);
if (riskInPrice <= 0) return;
double riskInPips = riskInPrice / Symbol.PipSize;
double takeProfit = tradeType == TradeType.Buy
? entryLimit + (riskInPrice * RiskReward)
: entryLimit - (riskInPrice * RiskReward);
double tpInPips = Math.Abs(entryLimit - takeProfit) / Symbol.PipSize;
double volume = CalculateVolume(riskInPips);
if (volume <= 0) return;
entryLimit = Math.Round(entryLimit, Symbol.Digits);
// Place order and explicitly catch the TradeResult
TradeResult result = PlaceLimitOrder(tradeType, SymbolName, volume, entryLimit, _label, riskInPips, tpInPips);
if (result.IsSuccessful)
{
_tradeTakenThisSession = true;
}
else
{
// Divert to the automated logger on failure
LogRejection(tradeType, entryLimit, stopLoss, takeProfit, riskInPips, result.Error);
}
}
private double CalculateVolume(double riskInPips)
{
double riskAmount = Account.Balance * (RiskPercent / 100.0);
// Symbol.PipValue represents the monetary value of 1 pip for Symbol.VolumeInUnitsMin
double exactVolume = (riskAmount / (riskInPips * Symbol.PipValue)) * Symbol.VolumeInUnitsMin;
return Symbol.NormalizeVolumeInUnits(exactVolume, RoundingMode.Down);
}
// =========================================================================
// AUTOMATED REJECTION LOGGER
// =========================================================================
private void LogRejection(TradeType tradeType, double entry, double sl, double tp, double slPips, ErrorCode? error)
{
if (error == null) return;
string action = tradeType.ToString().ToUpper() + "_LIMIT";
double spreadPips = Symbol.Spread / Symbol.PipSize;
string logMsg = string.Format(
"{0} | SYM: {1} | TYPE: {2} | ENTRY: {3:F5} | SL: {4:F5} ({5:F1} pips) | TP: {6:F5} | ASK: {7:F5} | BID: {8:F5} | SPREAD: {9:F1} pips | ERR: {10}",
Server.Time.ToString("yyyy-MM-dd HH:mm:ss"), SymbolName, action,
entry, sl, slPips, tp, Symbol.Ask, Symbol.Bid, spreadPips, error.ToString()
);
// Print to the cTrader Automate Log tab
Print("🚨 REJECTION: " + logMsg);
try
{
// Write to a persistent CSV in the user's Documents folder
string docsPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
string filePath = Path.Combine(docsPath, "cAlgo", "SilverBullet_Rejections.csv");
Directory.CreateDirectory(Path.GetDirectoryName(filePath));
File.AppendAllText(filePath, logMsg + Environment.NewLine);
}
catch (Exception ex)
{
Print("Failed to write to local rejection log file: " + ex.Message);
}
}
// =========================================================================
// SESSION CLEANUP
// =========================================================================
private bool IsTradeActive()
{
return Positions.Count(p => p.SymbolName == SymbolName && p.Label == _label) > 0 ||
PendingOrders.Count(p => p.SymbolName == SymbolName && p.Label == _label) > 0;
}
private void CancelAllPending()
{
var orders = PendingOrders.Where(p => p.SymbolName == SymbolName && p.Label == _label).ToList();
foreach (var order in orders)
{
CancelPendingOrder(order);
}
}
}
}Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The NY "Silver Bullet": How Smart Money Exploits the 10 AM Window
Key Architectural Differences in cTrader
Native TimeZone Enforcement: Because cTrader is built on .NET, applying [Robot(TimeZone = TimeZones.EasternStandardTime)] at the class level forces the Server.Time object within the cBot to inherently convert to New York time. You no longer have to worry about shifting the 10:00 and 11:00 input parameters manually when daylight saving time shifts your broker's server time.
TradeResult.Error Logging: The MT4/MT5 platforms rely heavily on hidden error codes. cTrader parses the rejection directly via result.Error, outputting readable ErrorCode enums natively (e.g., ErrorCode.InvalidStopLossTakeProfit).
Local I/O Access: You must set AccessRights = AccessRights.File in the [Robot] attribute, otherwise cTrader's security sandbox will actively block the logger from generating the .csv file in your Documents/cAlgo directory.
Native TimeZone Enforcement: Because cTrader is built on .NET, applying [Robot(TimeZone = TimeZones.EasternStandardTime)] at the class level forces the Server.Time object within the cBot to inherently convert to New York time. You no longer have to worry about shifting the 10:00 and 11:00 input parameters manually when daylight saving time shifts your broker's server time.
TradeResult.Error Logging: The MT4/MT5 platforms rely heavily on hidden error codes. cTrader parses the rejection directly via result.Error, outputting readable ErrorCode enums natively (e.g., ErrorCode.InvalidStopLossTakeProfit).
Local I/O Access: You must set AccessRights = AccessRights.File in the [Robot] attribute, otherwise cTrader's security sandbox will actively block the logger from generating the .csv file in your Documents/cAlgo directory.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: The NY "Silver Bullet": How Smart Money Exploits the 10 AM Window
To elevate this to a production-grade algorithmic system, the architecture must move away from a monolithic procedural script and adopt C# enterprise patterns. Institutional execution demands strict separation of concerns (SOLID principles), state-machine logic, and heavy microstructure safeguards to prevent the algorithm from self-destructing during news spikes or latency events.
Here is the refactored cBot engineered for production deployment:
Production Architectural Upgrades
State Machine Management: Replaced boolean flags with an explicit enum SessionState to govern the bot's execution lifecycle cleanly, preventing rogue loop evaluations.
Microstructure Safeguards (Spread Filter): The 10:00 AM EST window frequently overlaps with high-impact US news (like JOLTS or ISM). The MaxSpreadPips filter halts evaluation if liquidity voids cause spreads to blow out, protecting your micro-scalp R:R.
Execution Safety (NormalizePrice): Calculating a dynamic limit order off a candlestick wick can result in a price with 6 decimal places. Sending raw math variables to a broker server often triggers InvalidPrice rejections. Wrapping the math in Symbol.NormalizePrice() ensures the payload perfectly matches your broker's tick size tick step.
Decoupled Telemetry: The logging engine is wrapped in robust try-catch blocks and completely decoupled from the execution engine, ensuring disk I/O errors never crash the live trading thread.
Here is the refactored cBot engineered for production deployment:
Production Architectural Upgrades
State Machine Management: Replaced boolean flags with an explicit enum SessionState to govern the bot's execution lifecycle cleanly, preventing rogue loop evaluations.
Microstructure Safeguards (Spread Filter): The 10:00 AM EST window frequently overlaps with high-impact US news (like JOLTS or ISM). The MaxSpreadPips filter halts evaluation if liquidity voids cause spreads to blow out, protecting your micro-scalp R:R.
Execution Safety (NormalizePrice): Calculating a dynamic limit order off a candlestick wick can result in a price with 6 decimal places. Sending raw math variables to a broker server often triggers InvalidPrice rejections. Wrapping the math in Symbol.NormalizePrice() ensures the payload perfectly matches your broker's tick size tick step.
Decoupled Telemetry: The logging engine is wrapped in robust try-catch blocks and completely decoupled from the execution engine, ensuring disk I/O errors never crash the live trading thread.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.