Always Check the Higher Timeframe Trend First
Always Check the Higher Timeframe Trend First
Before taking any scalp on a 1-minute or 5-minute chart, take ten seconds to glance at the 1-hour and 4-hour charts for the same pair. This single habit, more than almost any other adjustment, tends to meaningfully improve win rates for scalpers who weren't previously doing it.
Here's the underlying logic. Short-timeframe price action doesn't exist in a vacuum — it's happening within the context of a broader trend (or lack thereof) playing out on higher timeframes. A 5-minute bullish setup that aligns with a clear 4-hour uptrend has the broader market structure working in its favor. The same 5-minute bullish setup appearing during a clear 4-hour downtrend is essentially fighting the tide, hoping for a counter-trend bounce to work out.
This doesn't mean counter-trend scalps never work — they do, sometimes. But statistically, across a large sample of trades, scalping with the higher timeframe trend has a meaningfully better hit rate than scalping against it, even when your actual entry and exit both happen on a very short timeframe.
Make this a literal, physical step in your process: before entering any trade, pull up the 1-hour and 4-hour charts, note the general direction, and only proceed with full confidence if your short-timeframe setup lines up with that broader context — or at minimum, size down and be extra selective if you're deliberately taking a counter-trend setup.
Here's the underlying logic. Short-timeframe price action doesn't exist in a vacuum — it's happening within the context of a broader trend (or lack thereof) playing out on higher timeframes. A 5-minute bullish setup that aligns with a clear 4-hour uptrend has the broader market structure working in its favor. The same 5-minute bullish setup appearing during a clear 4-hour downtrend is essentially fighting the tide, hoping for a counter-trend bounce to work out.
This doesn't mean counter-trend scalps never work — they do, sometimes. But statistically, across a large sample of trades, scalping with the higher timeframe trend has a meaningfully better hit rate than scalping against it, even when your actual entry and exit both happen on a very short timeframe.
Make this a literal, physical step in your process: before entering any trade, pull up the 1-hour and 4-hour charts, note the general direction, and only proceed with full confidence if your short-timeframe setup lines up with that broader context — or at minimum, size down and be extra selective if you're deliberately taking a counter-trend setup.
It’s Fairman 
Re: Always Check the Higher Timeframe Trend First
Hi Fairman,
yeah i agree.
First of all i check H4 and D1 charts, to see where the market is and what is the major trend, where are interesting Supports and Resistances.
And final execution i do from M15 most of the time.
yeah i agree.
First of all i check H4 and D1 charts, to see where the market is and what is the major trend, where are interesting Supports and Resistances.
And final execution i do from M15 most of the time.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Re: Always Check the Higher Timeframe Trend First
Spot on, Fairman. Aligning lower timeframe (LTF) execution with higher timeframe (HTF) market structure is one of the easiest ways to filter out low-probability chop.Fairman wrote: Sat Aug 22, 2026 10:28 am Before taking any scalp on a 1-minute or 5-minute chart, take ten seconds to glance at the 1-hour and 4-hour charts for the same pair. This single habit, more than almost any other adjustment, tends to meaningfully improve win rates for scalpers who weren't previously doing it.
Here's the underlying logic. Short-timeframe price action doesn't exist in a vacuum — it's happening within the context of a broader trend (or lack thereof) playing out on higher timeframes. A 5-minute bullish setup that aligns with a clear 4-hour uptrend has the broader market structure working in its favor. The same 5-minute bullish setup appearing during a clear 4-hour downtrend is essentially fighting the tide, hoping for a counter-trend bounce to work out.
This doesn't mean counter-trend scalps never work — they do, sometimes. But statistically, across a large sample of trades, scalping with the higher timeframe trend has a meaningfully better hit rate than scalping against it, even when your actual entry and exit both happen on a very short timeframe.
Make this a literal, physical step in your process: before entering any trade, pull up the 1-hour and 4-hour charts, note the general direction, and only proceed with full confidence if your short-timeframe setup lines up with that broader context — or at minimum, size down and be extra selective if you're deliberately taking a counter-trend setup.
When you are scalping the 1M or 5M, you are essentially trading the micro-volatility of the broader 1H/4H candle. If that 4H candle is printing a strong directional move, fighting it on the 1M chart requires pinpoint accuracy and gives you zero margin for error. Conversely, trading in the direction of the HTF flow means that even if your LTF entry is slightly off, the broader macroeconomic momentum will often bail you out.
For those trading algorithmically, this is exactly why hardcoding a simple H1/H4 moving average or price-action filter into your execution scripts drastically reduces drawdowns during choppy sessions. It takes the subjective guesswork out of "is the trend strong enough?" and forces you to stay on the right side of the volume.
Great reminder for both manual and system traders alike.
I prepared EA strategy based on your idea, so please check it and let me know, if you like or how would you like to improve it.
MT4 Strategy (MQL4)
This Expert Advisor (EA) translates Fairman's logic into code. It checks the current timeframe (e.g., M1 or M5) for a standard moving average crossover, but strictly filters the execution based on the trend direction of the H1 and H4 charts using a 50 EMA.
Code: Select all
//+------------------------------------------------------------------+
//| HTF_Trend_Scalp.mq4 |
//| H1/H4 Trend Filter for LTF Scalping |
//+------------------------------------------------------------------+
#property copyright "Custom MT4 Strategy"
#property link ""
#property version "1.00"
#property strict
//--- Input Parameters
input double InpLots = 0.1; // Lot Size
input int InpStopLoss = 100; // Stop Loss (in points)
input int InpTakeProfit = 200; // Take Profit (in points)
input int InpSlippage = 3; // Max Slippage
//--- HTF Filter Settings
input int InpHTF_Period = 50; // HTF EMA Period for Trend
input int InpLTF_Fast_MA = 9; // LTF Fast EMA (Trigger)
input int InpLTF_Slow_MA = 21; // LTF Slow EMA (Trigger)
input int InpMagicNumber = 80808; // Magic Number
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// 1. Check if we already have an open position (simple 1-trade limit)
if(OrdersTotal() > 0) return;
// 2. Fetch H1 and H4 Trend Data (Shift 1 to use closed candles)
double emaH1 = iMA(Symbol(), PERIOD_H1, InpHTF_Period, 0, MODE_EMA, PRICE_CLOSE, 1);
double emaH4 = iMA(Symbol(), PERIOD_H4, InpHTF_Period, 0, MODE_EMA, PRICE_CLOSE, 1);
double closeH1 = iClose(Symbol(), PERIOD_H1, 1);
double closeH4 = iClose(Symbol(), PERIOD_H4, 1);
// 3. Define the HTF Market Structure
bool isHTFUptrend = (closeH1 > emaH1) && (closeH4 > emaH4);
bool isHTFDowntrend = (closeH1 < emaH1) && (closeH4 < emaH4);
// 4. Fetch LTF Trigger Data (M1/M5 Current Chart)
double ltfFast_1 = iMA(Symbol(), 0, InpLTF_Fast_MA, 0, MODE_EMA, PRICE_CLOSE, 1);
double ltfSlow_1 = iMA(Symbol(), 0, InpLTF_Slow_MA, 0, MODE_EMA, PRICE_CLOSE, 1);
double ltfFast_2 = iMA(Symbol(), 0, InpLTF_Fast_MA, 0, MODE_EMA, PRICE_CLOSE, 2);
double ltfSlow_2 = iMA(Symbol(), 0, InpLTF_Slow_MA, 0, MODE_EMA, PRICE_CLOSE, 2);
// 5. Define LTF Execution Triggers (Crossover)
bool buyTrigger = (ltfFast_1 > ltfSlow_1) && (ltfFast_2 <= ltfSlow_2);
bool sellTrigger = (ltfFast_1 < ltfSlow_1) && (ltfFast_2 >= ltfSlow_2);
// 6. Execute Trades: Trigger MUST align with HTF Filter
double point = MarketInfo(Symbol(), MODE_POINT);
if(isHTFUptrend && buyTrigger)
{
double sl = Ask - (InpStopLoss * point);
double tp = Ask + (InpTakeProfit * point);
int ticket = OrderSend(Symbol(), OP_BUY, InpLots, Ask, InpSlippage, sl, tp, "HTF Buy Signal", InpMagicNumber, 0, clrGreen);
if(ticket < 0) Print("OrderSend failed with error #", GetLastError());
}
else if(isHTFDowntrend && sellTrigger)
{
double sl = Bid + (InpStopLoss * point);
double tp = Bid - (InpTakeProfit * point);
int ticket = OrderSend(Symbol(), OP_SELL, InpLots, Bid, InpSlippage, sl, tp, "HTF Sell Signal", InpMagicNumber, 0, clrRed);
if(ticket < 0) Print("OrderSend failed with error #", GetLastError());
}
}
//+------------------------------------------------------------------+Re: Always Check the Higher Timeframe Trend First
How the Code Works
The HTF Filter (isHTFUptrend / isHTFDowntrend): It queries the PERIOD_H1 and PERIOD_H4 directly, regardless of what timeframe the chart is currently running on. It ensures that the close of the previous hourly and 4-hour candles are above/below their respective 50 EMAs.
The LTF Trigger: It runs a standard 9/21 EMA crossover on the current chart (0 timeframe) as the scalp entry signal.
The Execution Lock: The OrderSend commands are strictly gated by the HTF booleans. If a 9/21 bullish cross happens on the M1 chart while the H4 is bearish, the EA ignores it completely.
The HTF Filter (isHTFUptrend / isHTFDowntrend): It queries the PERIOD_H1 and PERIOD_H4 directly, regardless of what timeframe the chart is currently running on. It ensures that the close of the previous hourly and 4-hour candles are above/below their respective 50 EMAs.
The LTF Trigger: It runs a standard 9/21 EMA crossover on the current chart (0 timeframe) as the scalp entry signal.
The Execution Lock: The OrderSend commands are strictly gated by the HTF booleans. If a 9/21 bullish cross happens on the M1 chart while the H4 is bearish, the EA ignores it completely.
Re: Always Check the Higher Timeframe Trend First
Here is the translation into TradingView Pine Script (v5).
Since you have an extensive background in algorithmic trading, the key architectural difference to note here is how we handle the higher timeframe (HTF) data. To perfectly replicate the MT4 shift 1 logic and avoid TradingView's notorious request.security repainting issues, the script fetches the [1] (closed bar) state of the H1 and H4 charts directly within the security context.
Since you have an extensive background in algorithmic trading, the key architectural difference to note here is how we handle the higher timeframe (HTF) data. To perfectly replicate the MT4 shift 1 logic and avoid TradingView's notorious request.security repainting issues, the script fetches the [1] (closed bar) state of the H1 and H4 charts directly within the security context.
Code: Select all
//@version=5
strategy("HTF Trend Scalp Filter", overlay=true, margin_long=100, margin_short=100)
// --- Input Parameters ---
// LTF Trigger Settings
ltfFastLen = input.int(9, title="LTF Fast EMA")
ltfSlowLen = input.int(21, title="LTF Slow EMA")
// HTF Filter Settings
htfEmaLen = input.int(50, title="HTF EMA Period")
// Risk Settings (in ticks/points)
slTicks = input.int(100, title="Stop Loss (Ticks/Points)")
tpTicks = input.int(200, title="Take Profit (Ticks/Points)")
// --- HTF Logic (Using closed bars to prevent repainting) ---
// We evaluate the condition entirely inside the security context for accuracy
isHTFBullish(tf, len) =>
request.security(syminfo.tickerid, tf, close[1] > ta.ema(close, len)[1], lookahead=barmerge.lookahead_off)
isHTFBearish(tf, len) =>
request.security(syminfo.tickerid, tf, close[1] < ta.ema(close, len)[1], lookahead=barmerge.lookahead_off)
// Fetch H1 (60 min) and H4 (240 min) states
h1Bull = isHTFBullish("60", htfEmaLen)
h4Bull = isHTFBullish("240", htfEmaLen)
h1Bear = isHTFBearish("60", htfEmaLen)
h4Bear = isHTFBearish("240", htfEmaLen)
// Define structural trend
htfUptrend = h1Bull and h4Bull
htfDowntrend = h1Bear and h4Bear
// --- LTF Logic (Current Chart) ---
fastEma = ta.ema(close, ltfFastLen)
slowEma = ta.ema(close, ltfSlowLen)
// Triggers
buyTrigger = ta.crossover(fastEma, slowEma)
sellTrigger = ta.crossunder(fastEma, slowEma)
// --- Execution & Trade Management ---
if htfUptrend and buyTrigger
strategy.entry("Long", strategy.long)
// strategy.exit operates in ticks, mirroring MT4's point logic
strategy.exit("Exit Long", "Long", loss=slTicks, profit=tpTicks)
if htfDowntrend and sellTrigger
strategy.entry("Short", strategy.short)
strategy.exit("Exit Short", "Short", loss=slTicks, profit=tpTicks)
// --- Visuals ---
plot(fastEma, color=color.blue, title="Fast EMA", linewidth=2)
plot(slowEma, color=color.red, title="Slow EMA", linewidth=2)
// Paint the background green/red when the HTF criteria are met to easily visualize the filter
bgcolor(htfUptrend ? color.new(color.green, 90) : htfDowntrend ? color.new(color.red, 90) : na, title="HTF Context")Re: Always Check the Higher Timeframe Trend First
Key Differences from MT4:
Background Highlighting: I added a bgcolor function at the bottom. When you drop this onto a 1M or 5M chart, the background will lightly paint green or red when the H1 and H4 trends are aligned. This makes it much easier to visually backtest when the algorithm was "armed" to take trades.
Exit Logic: The strategy.exit function uses loss and profit parameters which operate in ticks (minimum price movements), which perfectly mirrors the point-based offset we used in the MQL4 script.
Background Highlighting: I added a bgcolor function at the bottom. When you drop this onto a 1M or 5M chart, the background will lightly paint green or red when the H1 and H4 trends are aligned. This makes it much easier to visually backtest when the algorithm was "armed" to take trades.
Exit Logic: The strategy.exit function uses loss and profit parameters which operate in ticks (minimum price movements), which perfectly mirrors the point-based offset we used in the MQL4 script.
Re: Always Check the Higher Timeframe Trend First
Plus here is more Pro version:
To elevate this from a basic script to a professional, institutional-grade algorithm, we need to introduce features that account for real-world trading mechanics.
When running high-frequency or algorithmic scalping strategies, a professional script must include commission and slippage modeling, time-of-day filters (to avoid spread blowouts during rollover), state management (to prevent over-exposure), and a clean UI with grouped inputs and an on-chart dashboard.
Here is the upgraded, professional version in Pine Script v5.
To elevate this from a basic script to a professional, institutional-grade algorithm, we need to introduce features that account for real-world trading mechanics.
When running high-frequency or algorithmic scalping strategies, a professional script must include commission and slippage modeling, time-of-day filters (to avoid spread blowouts during rollover), state management (to prevent over-exposure), and a clean UI with grouped inputs and an on-chart dashboard.
Here is the upgraded, professional version in Pine Script v5.
Code: Select all
//@version=5
strategy("Pro HTF Scalping Filter", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=2, commission_type=strategy.commission.cash_per_order, commission_value=3, slippage=1)
// =====================================================================
// 1. INPUT PARAMETERS (Grouped for Clean UI)
// =====================================================================
var G_HTF = "1. Higher Timeframe Context"
htf1_tf = input.timeframe("60", title="Primary HTF", group=G_HTF, tooltip="Typically the 1-Hour chart.")
htf2_tf = input.timeframe("240", title="Secondary HTF", group=G_HTF, tooltip="Typically the 4-Hour chart.")
htf_len = input.int(50, title="HTF Trend EMA", group=G_HTF)
var G_LTF = "2. Scalp Triggers (Current Chart)"
fast_len = input.int(9, title="Fast EMA Trigger", inline="EMA", group=G_LTF)
slow_len = input.int(21, title="Slow EMA Trigger", inline="EMA", group=G_LTF)
var G_RISK = "3. Risk & Execution"
sl_pts = input.int(100, title="Stop Loss (Points)", inline="Risk", group=G_RISK)
tp_pts = input.int(200, title="Take Profit (Points)", inline="Risk", group=G_RISK)
var G_TIME = "4. Trading Window"
use_sess = input.bool(true, title="Enable Time Filter", group=G_TIME)
session = input.session("0800-1700", title="Active Session", group=G_TIME, tooltip="Limits trading to high-liquidity hours to avoid spread blowouts.")
var G_DASH = "5. Display"
show_hud = input.bool(true, title="Show On-Chart Dashboard", group=G_DASH)
// =====================================================================
// 2. TIME & SESSION MANAGEMENT
// =====================================================================
// Returns true if the current bar is within the designated trading session
in_session = not use_sess or not na(time(timeframe.period, session))
// =====================================================================
// 3. HIGHER TIMEFRAME (HTF) LOGIC
// =====================================================================
// Using a custom function to fetch non-repainting HTF data
get_htf_trend(tf, len) =>
request.security(syminfo.tickerid, tf, close[1] > ta.ema(close, len)[1], lookahead=barmerge.lookahead_off)
// Fetch states
is_htf1_bull = get_htf_trend(htf1_tf, htf_len)
is_htf2_bull = get_htf_trend(htf2_tf, htf_len)
// Since it's a binary check (above/below EMA), bearish is simply the inverse
is_htf1_bear = not is_htf1_bull
is_htf2_bear = not is_htf2_bull
// Structural context
htf_uptrend = is_htf1_bull and is_htf2_bull
htf_downtrend = is_htf1_bear and is_htf2_bear
// =====================================================================
// 4. LOWER TIMEFRAME (LTF) TRIGGERS
// =====================================================================
fast_ema = ta.ema(close, fast_len)
slow_ema = ta.ema(close, slow_len)
buy_trigger = ta.crossover(fast_ema, slow_ema)
sell_trigger = ta.crossunder(fast_ema, slow_ema)
// =====================================================================
// 5. EXECUTION & STATE MANAGEMENT
// =====================================================================
// State checks to prevent firing overlapping orders
is_flat = strategy.position_size == 0
if in_session and is_flat
if htf_uptrend and buy_trigger
strategy.entry("Long", strategy.long)
strategy.exit("Exit Long", "Long", loss=sl_pts, profit=tp_pts)
if htf_downtrend and sell_trigger
strategy.entry("Short", strategy.short)
strategy.exit("Exit Short", "Short", loss=sl_pts, profit=tp_pts)
// Close positions flat at the end of the trading session to avoid overnight holding risk
if use_sess and ta.crossunder(time(timeframe.period, session) ? 1 : 0, 0.5)
strategy.close_all(comment="Session Close")
// =====================================================================
// 6. VISUALS & HUD (Heads Up Display)
// =====================================================================
plot(fast_ema, color=color.new(#2962FF, 0), title="Fast EMA", linewidth=2)
plot(slow_ema, color=color.new(#FF6D00, 0), title="Slow EMA", linewidth=2)
// Paint background when HTF aligns
bg_color = htf_uptrend ? color.new(color.green, 95) : htf_downtrend ? color.new(color.red, 95) : na
bgcolor(bg_color, title="HTF Context")
// Draw Information Dashboard
if show_hud
var table hud = table.new(position.top_right, 2, 4, border_width=1, border_color=color.gray, frame_color=color.gray, frame_width=1)
table.cell(hud, 0, 0, "HTF FILTER", text_color=color.white, bgcolor=color.black, text_halign=text.align_center)
table.cell(hud, 1, 0, "STATUS", text_color=color.white, bgcolor=color.black, text_halign=text.align_center)
table.cell(hud, 0, 1, "Primary (" + htf1_tf + ")", text_color=color.white, bgcolor=color.gray)
table.cell(hud, 1, 1, is_htf1_bull ? "BULL" : "BEAR", text_color=color.white, bgcolor=is_htf1_bull ? color.green : color.red)
table.cell(hud, 0, 2, "Secondary (" + htf2_tf + ")", text_color=color.white, bgcolor=color.gray)
table.cell(hud, 1, 2, is_htf2_bull ? "BULL" : "BEAR", text_color=color.white, bgcolor=is_htf2_bull ? color.green : color.red)
table.cell(hud, 0, 3, "Master Context", text_color=color.white, bgcolor=color.gray)
table.cell(hud, 1, 3, htf_uptrend ? "LONG ONLY" : htf_downtrend ? "SHORT ONLY" : "CHOP (NO TRADE)", text_color=color.white, bgcolor=htf_uptrend ? color.green : htf_downtrend ? color.red : color.orange)Re: Always Check the Higher Timeframe Trend First
What makes this "Professional"?
Realistic Backtesting: The strategy() declaration now models initial capital, percent-of-equity position sizing, custom commissions (e.g., $3 per round turn), and slippage modeling. This ensures your backtest results accurately reflect realistic market friction, rather than impossible theoretical gains.
Time-of-Day Management: Added a strictly bounded session filter (in_session). This guarantees the algorithm won't take trades during the Asia open or right at New York close when spreads widen and execution fills are poor. It also auto-flattens any open positions at the end of the session.
State Management: The logic now uses is_flat. This ensures the script doesn't rapidly fire redundant orders if multiple trigger crosses happen in the same trend direction before the target or stop is hit.
Dynamic Inputs & Tooltips: The variables are now organized into cleanly grouped arrays (group= and inline=) in the TradingView UI, complete with tooltips explaining their functions, avoiding a cluttered settings menu.
Heads Up Display (HUD): It generates an on-chart data table in the top right corner. You can instantly look at your chart and see whether the 1-Hour and 4-Hour algorithms are registering Bullish or Bearish without having to flip timeframes or guess why a trade wasn't taken.
Realistic Backtesting: The strategy() declaration now models initial capital, percent-of-equity position sizing, custom commissions (e.g., $3 per round turn), and slippage modeling. This ensures your backtest results accurately reflect realistic market friction, rather than impossible theoretical gains.
Time-of-Day Management: Added a strictly bounded session filter (in_session). This guarantees the algorithm won't take trades during the Asia open or right at New York close when spreads widen and execution fills are poor. It also auto-flattens any open positions at the end of the session.
State Management: The logic now uses is_flat. This ensures the script doesn't rapidly fire redundant orders if multiple trigger crosses happen in the same trend direction before the target or stop is hit.
Dynamic Inputs & Tooltips: The variables are now organized into cleanly grouped arrays (group= and inline=) in the TradingView UI, complete with tooltips explaining their functions, avoiding a cluttered settings menu.
Heads Up Display (HUD): It generates an on-chart data table in the top right corner. You can instantly look at your chart and see whether the 1-Hour and 4-Hour algorithms are registering Bullish or Bearish without having to flip timeframes or guess why a trade wasn't taken.
Re: Always Check the Higher Timeframe Trend First
And here is the upgraded professional algorithm with the dynamic ATR (Average True Range) trailing stop built directly into the core execution engine.
I set this up with a dropdown menu in the UI so you can seamlessly toggle between your classic Fixed Points and the new ATR Trailing Stop without having to rewrite code. Because different assets behave differently (e.g., Forex pairs trend smoother, whereas Silver can be highly erratic), this allows you to rapidly adapt your exit engine during backtesting to fit the specific market's volatility profile.
Pro HTF Scalper with ATR Trail (Pine Script v5)
I set this up with a dropdown menu in the UI so you can seamlessly toggle between your classic Fixed Points and the new ATR Trailing Stop without having to rewrite code. Because different assets behave differently (e.g., Forex pairs trend smoother, whereas Silver can be highly erratic), this allows you to rapidly adapt your exit engine during backtesting to fit the specific market's volatility profile.
Pro HTF Scalper with ATR Trail (Pine Script v5)
Code: Select all
//@version=5
strategy("Pro HTF Scalper with ATR Trail", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=2, commission_type=strategy.commission.cash_per_order, commission_value=3, slippage=1)
// =====================================================================
// 1. INPUT PARAMETERS
// =====================================================================
var G_HTF = "1. Higher Timeframe Context"
htf1_tf = input.timeframe("60", title="Primary HTF", group=G_HTF)
htf2_tf = input.timeframe("240", title="Secondary HTF", group=G_HTF)
htf_len = input.int(50, title="HTF Trend EMA", group=G_HTF)
var G_LTF = "2. Scalp Triggers (Current Chart)"
fast_len = input.int(9, title="Fast EMA Trigger", inline="EMA", group=G_LTF)
slow_len = input.int(21, title="Slow EMA Trigger", inline="EMA", group=G_LTF)
var G_RISK = "3. Risk Management & Exits"
exit_mode = input.string("ATR Trailing Stop", options=["Fixed Points", "ATR Trailing Stop"], title="Exit Mode", group=G_RISK)
// Fixed point settings
sl_pts = input.int(100, title="Fixed Stop Loss (Points)", group=G_RISK, tooltip="Only used if 'Fixed Points' is selected.")
tp_pts = input.int(200, title="Fixed Take Profit (Points)", group=G_RISK, tooltip="Only used if 'Fixed Points' is selected.")
// ATR Settings
atr_len = input.int(14, title="ATR Length", inline="ATR", group=G_RISK)
atr_mult = input.float(2.0, title="ATR Multiplier", step=0.1, inline="ATR", group=G_RISK)
var G_TIME = "4. Trading Window"
use_sess = input.bool(true, title="Enable Time Filter", group=G_TIME)
session = input.session("0800-1700", title="Active Session", group=G_TIME)
var G_DASH = "5. Display"
show_hud = input.bool(true, title="Show On-Chart Dashboard", group=G_DASH)
// =====================================================================
// 2. TIME, SESSIONS & STATE
// =====================================================================
in_session = not use_sess or not na(time(timeframe.period, session))
is_flat = strategy.position_size == 0
// =====================================================================
// 3. HIGHER TIMEFRAME (HTF) LOGIC
// =====================================================================
get_htf_trend(tf, len) =>
request.security(syminfo.tickerid, tf, close[1] > ta.ema(close, len)[1], lookahead=barmerge.lookahead_off)
is_htf1_bull = get_htf_trend(htf1_tf, htf_len)
is_htf2_bull = get_htf_trend(htf2_tf, htf_len)
is_htf1_bear = not is_htf1_bull
is_htf2_bear = not is_htf2_bull
htf_uptrend = is_htf1_bull and is_htf2_bull
htf_downtrend = is_htf1_bear and is_htf2_bear
// =====================================================================
// 4. LOWER TIMEFRAME (LTF) TRIGGERS
// =====================================================================
fast_ema = ta.ema(close, fast_len)
slow_ema = ta.ema(close, slow_len)
buy_trigger = ta.crossover(fast_ema, slow_ema)
sell_trigger = ta.crossunder(fast_ema, slow_ema)
// =====================================================================
// 5. EXECUTION & TRAILING STOP LOGIC
// =====================================================================
var float trail_stop = na
atr_val = ta.atr(atr_len)
// Entry Logic
if in_session and is_flat
if htf_uptrend and buy_trigger
strategy.entry("Long", strategy.long)
if exit_mode == "Fixed Points"
strategy.exit("Exit Long", "Long", loss=sl_pts, profit=tp_pts)
else
trail_stop := close - (atr_val * atr_mult) // Initialize starting stop
if htf_downtrend and sell_trigger
strategy.entry("Short", strategy.short)
if exit_mode == "Fixed Points"
strategy.exit("Exit Short", "Short", loss=sl_pts, profit=tp_pts)
else
trail_stop := close + (atr_val * atr_mult) // Initialize starting stop
// Dynamic ATR Ratchet Logic
if exit_mode == "ATR Trailing Stop"
if strategy.position_size > 0
new_stop = close - (atr_val * atr_mult)
trail_stop := math.max(nz(trail_stop, new_stop), new_stop) // Ratchet up only
strategy.exit("Trail Long", "Long", stop=trail_stop)
if strategy.position_size < 0
new_stop = close + (atr_val * atr_mult)
trail_stop := math.min(nz(trail_stop, new_stop), new_stop) // Ratchet down only
strategy.exit("Trail Short", "Short", stop=trail_stop)
// Reset trailing stop memory when flat
if is_flat
trail_stop := na
// End of session flatten
if use_sess and ta.crossunder(time(timeframe.period, session) ? 1 : 0, 0.5)
strategy.close_all(comment="Session Close")
// =====================================================================
// 6. VISUALS & HUD
// =====================================================================
plot(fast_ema, color=color.new(#2962FF, 0), title="Fast EMA", linewidth=2)
plot(slow_ema, color=color.new(#FF6D00, 0), title="Slow EMA", linewidth=2)
// Plot the Trailing Stop Line (Stepline style makes it look mechanical)
plot(exit_mode == "ATR Trailing Stop" and not is_flat ? trail_stop : na, color=color.new(color.fuchsia, 0), style=plot.style_stepline, linewidth=2, title="ATR Trailing Stop")
bg_color = htf_uptrend ? color.new(color.green, 95) : htf_downtrend ? color.new(color.red, 95) : na
bgcolor(bg_color, title="HTF Context")
if show_hud
var table hud = table.new(position.top_right, 2, 4, border_width=1, border_color=color.gray, frame_color=color.gray, frame_width=1)
table.cell(hud, 0, 0, "HTF FILTER", text_color=color.white, bgcolor=color.black, text_halign=text.align_center)
table.cell(hud, 1, 0, "STATUS", text_color=color.white, bgcolor=color.black, text_halign=text.align_center)
table.cell(hud, 0, 1, "Primary (" + htf1_tf + ")", text_color=color.white, bgcolor=color.gray)
table.cell(hud, 1, 1, is_htf1_bull ? "BULL" : "BEAR", text_color=color.white, bgcolor=is_htf1_bull ? color.green : color.red)
table.cell(hud, 0, 2, "Secondary (" + htf2_tf + ")", text_color=color.white, bgcolor=color.gray)
table.cell(hud, 1, 2, is_htf2_bull ? "BULL" : "BEAR", text_color=color.white, bgcolor=is_htf2_bull ? color.green : color.red)
table.cell(hud, 0, 3, "Master Context", text_color=color.white, bgcolor=color.gray)
table.cell(hud, 1, 3, htf_uptrend ? "LONG ONLY" : htf_downtrend ? "SHORT ONLY" : "CHOP", text_color=color.white, bgcolor=htf_uptrend ? color.green : htf_downtrend ? color.red : color.orange)Re: Always Check the Higher Timeframe Trend First
How the ATR Engine Works
The Ratchet Mechanism: I used math.max() for longs and math.min() for shorts. This ensures that the trailing stop behaves like a true Chandelier Exit—it can only ever move in the direction of profit to lock in gains. If the ATR expands rapidly but price pulls back, the stop line "freezes" in place.
Visual Overlay: At the bottom, I added a visual plot using plot.style_stepline. When you take a trade, you will see a bright fuchsia stair-step line rendering right behind your candles, making it extremely easy to spot check whether the dynamic stop is trailing tightly enough to your liking.
Execution Safety: The strategy.exit() function is called repeatedly while in a trade, seamlessly updating the existing broker order with the newly calculated trail_stop price to guarantee it never lags.
The Ratchet Mechanism: I used math.max() for longs and math.min() for shorts. This ensures that the trailing stop behaves like a true Chandelier Exit—it can only ever move in the direction of profit to lock in gains. If the ATR expands rapidly but price pulls back, the stop line "freezes" in place.
Visual Overlay: At the bottom, I added a visual plot using plot.style_stepline. When you take a trade, you will see a bright fuchsia stair-step line rendering right behind your candles, making it extremely easy to spot check whether the dynamic stop is trailing tightly enough to your liking.
Execution Safety: The strategy.exit() function is called repeatedly while in a trade, seamlessly updating the existing broker order with the newly calculated trail_stop price to guarantee it never lags.