Define Your Trading Session Windows in Advance
Define Your Trading Session Windows in Advance
Decide, in writing, exactly which hours you trade — for example, specifically the London open, or specifically the London-New York overlap — and commit genuinely to not trading outside those defined windows, even when a chart outside your window looks tempting.
This might seem like an overly rigid rule at first glance, but it addresses a specific, common failure mode: scalping outside your carefully chosen liquidity windows generally means dealing with worse spreads, thinner participation, choppier and less reliable price action, and lower-quality setups overall compared to the windows you deliberately selected for good reasons.
The temptation to break this rule usually shows up in a specific, recognizable moment: you've had a quiet session within your defined window, you're feeling restless or unsatisfied, and as your window closes, you notice the chart doing something interesting just outside your normal hours. The pull to "just take this one trade" outside your window is strong precisely because it's rationalized as an exception rather than a pattern.
Treat your defined session windows the way you'd treat any other core risk rule — non-negotiable, not subject to in-the-moment renegotiation based on how a particular day happened to go. If you consistently find good setups outside your current window, that's useful data for revising your plan deliberately, during a calm review period — not a reason to spontaneously override it mid-session.
This might seem like an overly rigid rule at first glance, but it addresses a specific, common failure mode: scalping outside your carefully chosen liquidity windows generally means dealing with worse spreads, thinner participation, choppier and less reliable price action, and lower-quality setups overall compared to the windows you deliberately selected for good reasons.
The temptation to break this rule usually shows up in a specific, recognizable moment: you've had a quiet session within your defined window, you're feeling restless or unsatisfied, and as your window closes, you notice the chart doing something interesting just outside your normal hours. The pull to "just take this one trade" outside your window is strong precisely because it's rationalized as an exception rather than a pattern.
Treat your defined session windows the way you'd treat any other core risk rule — non-negotiable, not subject to in-the-moment renegotiation based on how a particular day happened to go. If you consistently find good setups outside your current window, that's useful data for revising your plan deliberately, during a calm review period — not a reason to spontaneously override it mid-session.
It’s Fairman 
Re: Define Your Trading Session Windows in Advance
Spot on, Fairman. Relying purely on willpower to avoid trading outside of optimal liquidity windows is a massive leak in most traders' systems. When you are scalping, you are entirely dependent on volume and momentum. Outside of the major overlaps (like London/NY), the spread widening and choppy, algor-driven price action will absolutely chew through the profits you built during the main session.Fairman wrote: Sat Aug 22, 2026 10:49 am Decide, in writing, exactly which hours you trade — for example, specifically the London open, or specifically the London-New York overlap — and commit genuinely to not trading outside those defined windows, even when a chart outside your window looks tempting.
This might seem like an overly rigid rule at first glance, but it addresses a specific, common failure mode: scalping outside your carefully chosen liquidity windows generally means dealing with worse spreads, thinner participation, choppier and less reliable price action, and lower-quality setups overall compared to the windows you deliberately selected for good reasons.
The temptation to break this rule usually shows up in a specific, recognizable moment: you've had a quiet session within your defined window, you're feeling restless or unsatisfied, and as your window closes, you notice the chart doing something interesting just outside your normal hours. The pull to "just take this one trade" outside your window is strong precisely because it's rationalized as an exception rather than a pattern.
Treat your defined session windows the way you'd treat any other core risk rule — non-negotiable, not subject to in-the-moment renegotiation based on how a particular day happened to go. If you consistently find good setups outside your current window, that's useful data for revising your plan deliberately, during a calm review period — not a reason to spontaneously override it mid-session.
That "just one more trade" mentality usually hits right as the volatility dries up, which is exactly the worst time to force a setup.
To take the human element out of it entirely, I always recommend hardcoding these session filters directly into your trading tools. If the EA or script physically cannot execute an order outside of the designated minutes, you save yourself from your own boredom.
Here is a clean and lightweight MT4 (MQL4) time window checker you can drop into your EAs to enforce this rule. It converts the server time into absolute minutes, which safely handles sessions that cross midnight.
MQL4 Trading Session Filter
Code: Select all
//--- Input parameters for session times (Broker Server Time)
extern int StartHour = 8; // Session Start Hour
extern int StartMinute = 0; // Session Start Minute
extern int EndHour = 17; // Session End Hour
extern int EndMinute = 0; // Session End Minute
//+------------------------------------------------------------------+
//| Checks if current server time is within the allowed window |
//+------------------------------------------------------------------+
bool IsWithinTradingSession()
{
datetime currentTime = TimeCurrent();
int currentHour = TimeHour(currentTime);
int currentMinute = TimeMinute(currentTime);
// Convert times to total minutes from midnight for easy comparison
int currentTotalMinutes = (currentHour * 60) + currentMinute;
int startTotalMinutes = (StartHour * 60) + StartMinute;
int endTotalMinutes = (EndHour * 60) + EndMinute;
// Scenario 1: Session stays within the same day (e.g., 08:00 to 17:00)
if(startTotalMinutes < endTotalMinutes)
{
if(currentTotalMinutes >= startTotalMinutes && currentTotalMinutes < endTotalMinutes)
return true;
}
// Scenario 2: Session crosses midnight (e.g., 22:00 to 02:00)
else if(startTotalMinutes > endTotalMinutes)
{
if(currentTotalMinutes >= startTotalMinutes || currentTotalMinutes < endTotalMinutes)
return true;
}
// Scenario 3: Start and End times are identical (24/7 trading)
else
{
return true;
}
return false;
}Re: Define Your Trading Session Windows in Advance
How to use it:
Just wrap your entry logic inside the OnTick() function with this boolean check.
Treating your session times as a hard risk parameter is a game changer. If you're consistently seeing setups you want to trade at 18:00 broker time, log it in your journal, backtest it over a few months of tick data, and adjust your parameters offline. Never override the system mid-session.
Just wrap your entry logic inside the OnTick() function with this boolean check.
Code: Select all
void OnTick()
{
// If we are outside the session window, exit the tick immediately
if(!IsWithinTradingSession())
{
// Optional: Add logic here to close open positions at session end
return;
}
// ... Your standard entry logic goes here ...
}Re: Define Your Trading Session Windows in Advance
Here is the adapted version for MetaTrader 5 (MQL5), updated with MQL5-standard conventions (using input parameters, MqlDateTime, and strict typing).
MQL5 Trading Session Filter
MQL5 Trading Session Filter
Code: Select all
//--- Input parameters for session times (Broker Server Time)
input group "=== Session Filter Settings ==="
input int InpStartHour = 8; // Session Start Hour (0-23)
input int InpStartMinute = 0; // Session Start Minute (0-59)
input int InpEndHour = 17; // Session End Hour (0-23)
input int InpEndMinute = 0; // Session End Minute (0-59)
//+------------------------------------------------------------------+
//| Checks if current server time is within the allowed window |
//+------------------------------------------------------------------+
bool IsWithinTradingSession()
{
MqlDateTime dt;
TimeToStruct(TimeCurrent(), dt);
// Convert hours and minutes to total elapsed minutes from midnight
int currentTotalMinutes = (dt.hour * 60) + dt.min;
int startTotalMinutes = (InpStartHour * 60) + InpStartMinute;
int endTotalMinutes = (InpEndHour * 60) + InpEndMinute;
// Scenario 1: Intra-day window (e.g., 08:00 to 17:00)
if(startTotalMinutes < endTotalMinutes)
{
return (currentTotalMinutes >= startTotalMinutes && currentTotalMinutes < endTotalMinutes);
}
// Scenario 2: Window crosses midnight (e.g., 22:00 to 02:00)
else if(startTotalMinutes > endTotalMinutes)
{
return (currentTotalMinutes >= startTotalMinutes || currentTotalMinutes < endTotalMinutes);
}
// Scenario 3: 24-hour trading / No filter
else
{
return true;
}
}Re: Define Your Trading Session Windows in Advance
Implementation in OnTick()
Key Differences from MT4:
Time Decomposition: Instead of MT4's legacy TimeHour() and TimeMinute(), MT5 utilizes TimeToStruct(TimeCurrent(), dt) with the MqlDateTime structure, which eliminates multiple function calls and runs faster during backtests.
Input Scoping: Uses input group and input modifiers rather than extern, conforming to modern MQL5 style standards.
Code: Select all
void OnTick()
{
// Block execution outside defined liquidity hours
if(!IsWithinTradingSession())
{
// Optional: Add logic to manage/close existing positions or trail stops
return;
}
// ... Order execution and strategy logic ...
}Time Decomposition: Instead of MT4's legacy TimeHour() and TimeMinute(), MT5 utilizes TimeToStruct(TimeCurrent(), dt) with the MqlDateTime structure, which eliminates multiple function calls and runs faster during backtests.
Input Scoping: Uses input group and input modifiers rather than extern, conforming to modern MQL5 style standards.
Re: Define Your Trading Session Windows in Advance
Here is the Pine Script (v5) version.
TradingView makes this significantly easier than MetaTrader because Pine Script has a native input.session() type. It automatically handles midnight crossings, timezone conversions, and weekend gaps without requiring you to manually calculate elapsed minutes.
Pine Script Session Filter
TradingView makes this significantly easier than MetaTrader because Pine Script has a native input.session() type. It automatically handles midnight crossings, timezone conversions, and weekend gaps without requiring you to manually calculate elapsed minutes.
Pine Script Session Filter
Code: Select all
//@version=5
strategy("Session Window Filter", overlay=true)
// --- Inputs ---
// Format is "HHMM-HHMM". It natively handles overnight sessions (e.g., "2200-0200").
sessionWindow = input.session("0800-1700", title="Trading Window")
// Timezone alignment ensures your window stays locked to the correct market
// regardless of the user's local PC time.
tz = input.string("Europe/London", title="Time Zone", options=["GMT", "Europe/London", "America/New_York", "Asia/Tokyo", "Exchange"])
// --- Core Logic ---
// The time() function returns a valid timestamp if the current bar falls within the session.
// If outside the session, it returns 'na' (not available).
inSession = not na(time(timeframe.period, sessionWindow, tz))
// --- Visual Output ---
// Highlights the background so you can visually verify your liquidity windows
bgcolor(inSession ? color.new(color.blue, 90) : na, title="Active Session Background")
// --- Execution Logic ---
// Example of how to wrap your conditions
// myEntryCondition = ta.crossover(ta.sma(close, 10), ta.sma(close, 20))
//
// if inSession and myEntryCondition
// strategy.entry("Long", strategy.long)Re: Define Your Trading Session Windows in Advance
Key Differences from MQL:
String-based Sessions: Instead of separate hour and minute inputs, you just use "0800-1700".
Built-in Timezones: You can lock the script to "Europe/London" or "America/New_York". This ensures daylight saving time shifts (like when the US switches to DST a few weeks before Europe) don't accidentally offset your algorithmic trading windows.
Visual Verification: The bgcolor function paints the chart during your active window, making it immediately obvious during backtesting if your times are aligned perfectly with the market volume.
String-based Sessions: Instead of separate hour and minute inputs, you just use "0800-1700".
Built-in Timezones: You can lock the script to "Europe/London" or "America/New_York". This ensures daylight saving time shifts (like when the US switches to DST a few weeks before Europe) don't accidentally offset your algorithmic trading windows.
Visual Verification: The bgcolor function paints the chart during your active window, making it immediately obvious during backtesting if your times are aligned perfectly with the market volume.
Re: Define Your Trading Session Windows in Advance
Since we already looked at a standard MT5 approach earlier, let's step it up this time.
For high-volume scalping environments—especially in fast-moving forex or silver markets—calling TimeToStruct() on every single tick can become a bottleneck. When thousands of ticks are firing per second, you want to keep the OnTick() execution as lightweight as possible to minimize latency.
Here is an optimized MQL5 version that caches the session state and only recalculates it when the server minute actually changes. This saves significant CPU cycles during rapid price action.
Optimized MQL5 Session Filter (Low Latency)
For high-volume scalping environments—especially in fast-moving forex or silver markets—calling TimeToStruct() on every single tick can become a bottleneck. When thousands of ticks are firing per second, you want to keep the OnTick() execution as lightweight as possible to minimize latency.
Here is an optimized MQL5 version that caches the session state and only recalculates it when the server minute actually changes. This saves significant CPU cycles during rapid price action.
Optimized MQL5 Session Filter (Low Latency)
Code: Select all
//--- Input parameters for session times
input group "=== Session Filter Settings ==="
input int InpStartHour = 8; // Session Start Hour (0-23)
input int InpStartMinute = 0; // Session Start Minute (0-59)
input int InpEndHour = 17; // Session End Hour (0-23)
input int InpEndMinute = 0; // Session End Minute (0-59)
//--- Global variables for state caching
bool g_inSession = false;
datetime g_lastMinute = 0;
//+------------------------------------------------------------------+
//| Highly optimized session check for fast tick environments |
//+------------------------------------------------------------------+
bool IsWithinTradingSession()
{
datetime currentTime = TimeCurrent();
// Strip seconds to find the current minute boundary
datetime currentMinuteTick = currentTime - (currentTime % 60);
// OPTIMIZATION: If we are in the same minute as the last check,
// just return the cached boolean. Skip the heavy math.
if(currentMinuteTick == g_lastMinute)
{
return g_inSession;
}
// Minute has changed; update the cache tracker
g_lastMinute = currentMinuteTick;
// Perform the actual time calculation
MqlDateTime dt;
TimeToStruct(currentTime, dt);
int currentTotalMinutes = (dt.hour * 60) + dt.min;
int startTotalMinutes = (InpStartHour * 60) + InpStartMinute;
int endTotalMinutes = (InpEndHour * 60) + InpEndMinute;
if(startTotalMinutes < endTotalMinutes)
{
g_inSession = (currentTotalMinutes >= startTotalMinutes && currentTotalMinutes < endTotalMinutes);
}
else if(startTotalMinutes > endTotalMinutes)
{
g_inSession = (currentTotalMinutes >= startTotalMinutes || currentTotalMinutes < endTotalMinutes);
}
else
{
g_inSession = true;
}
return g_inSession;
}Re: Define Your Trading Session Windows in Advance
Why this matters for algorithmic execution:
By dropping the modulo operator (currentTime % 60) into the check, the EA bypasses the MqlDateTime structure conversion entirely for 99% of incoming ticks. If you are blasting through heavy market overlaps with highly sensitive entry filters, this ensures the session check never slows down your trade triggers.
By dropping the modulo operator (currentTime % 60) into the check, the EA bypasses the MqlDateTime structure conversion entirely for 99% of incoming ticks. If you are blasting through heavy market overlaps with highly sensitive entry filters, this ensures the session check never slows down your trade triggers.
Re: Define Your Trading Session Windows in Advance
Here is the translation for cTrader (C#).
Because cTrader is built on modern C#, we don't have to manually calculate minutes like we did in MQL. We can use the native C# TimeSpan struct, which makes comparing times of day incredibly fast and mathematically elegant.
cTrader C# Session Filter
Because cTrader is built on modern C#, we don't have to manually calculate minutes like we did in MQL. We can use the native C# TimeSpan struct, which makes comparing times of day incredibly fast and mathematically elegant.
cTrader C# Session Filter
Code: Select all
using System;
using cAlgo.API;
namespace cAlgo.Robots
{
// The TimeZone attribute locks your Server.Time to a specific zone
// so daylight saving changes on your local PC don't break your bot.
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class SessionFilterBot : Robot
{
// --- Input Parameters ---
// Using strings allows for clean "HH:mm" formatting in the cTrader UI
[Parameter("Start Time (HH:mm)", Group = "Session Filter", DefaultValue = "08:00")]
public string StartTimeStr { get; set; }
[Parameter("End Time (HH:mm)", Group = "Session Filter", DefaultValue = "17:00")]
public string EndTimeStr { get; set; }
// Cached TimeSpan objects for high-speed tick comparison
private TimeSpan _startTime;
private TimeSpan _endTime;
protected override void OnStart()
{
// Parse the string inputs into C# TimeSpan objects once at startup
if (!TimeSpan.TryParse(StartTimeStr, out _startTime) ||
!TimeSpan.TryParse(EndTimeStr, out _endTime))
{
Print("Error: Invalid time format. Please use HH:mm (e.g., 08:30).");
Stop(); // Halt the bot if the user types gibberish
}
}
protected override void OnTick()
{
// Block execution outside defined liquidity hours
if (!IsWithinTradingSession())
{
// Optional: Manage trailing stops or close positions at session end here
return;
}
// ... Your standard order execution logic goes here ...
}
//+------------------------------------------------------------------+
//| Checks if current server time is within the allowed window |
//+------------------------------------------------------------------+
private bool IsWithinTradingSession()
{
// Extract just the time of day (drops the date)
TimeSpan currentTime = Server.Time.TimeOfDay;
// Scenario 1: Intra-day window (e.g., 08:00 to 17:00)
if (_startTime < _endTime)
{
return currentTime >= _startTime && currentTime < _endTime;
}
// Scenario 2: Window crosses midnight (e.g., 22:00 to 02:00)
else if (_startTime > _endTime)
{
return currentTime >= _startTime || currentTime < _endTime;
}
// Scenario 3: 24-hour trading / No filter
else
{
return true;
}
}
}
}