Code: Select all
//@version=5
indicator("Ghost Executions: HTF vs LTF Framework", overlay=true)
// ==============================================================================
// 1. INPUTS & PARAMETERS
// ==============================================================================
grp_wide = "1H Structural Zone (Wide)"
i_wide_sl_pips = input.float(50.0, "Wide SL (pips)", group=grp_wide)
i_wide_rr = input.float(2.0, "Wide Target (R)", group=grp_wide)
grp_ref = "Lower Timeframe (Refined)"
i_ref_sl_pips = input.float(20.0, "Refined SL (pips)", group=grp_ref)
i_ref_rr = input.float(5.0, "Refined Target (R)", group=grp_ref)
i_ltf_window = input.int(12, "Max Bars to wait for LTF Signal", tooltip="If LTF condition doesn't fire within this many bars of the HTF trigger, it counts as a missed trade.", group=grp_ref)
// Pip Calculation (Adjustable for Spot Forex vs Metals)
pip_size = syminfo.mintick * (syminfo.type == "forex" ? 10 : 1)
// ==============================================================================
// 2. YOUR CUSTOM ENTRY LOGIC (Replace these placeholders)
// ==============================================================================
// Example placeholders: EMA crossover for HTF, Price crossing EMA for LTF
emaFast = ta.ema(close, 20)
emaSlow = ta.ema(close, 50)
// HTF Triggers (e.g., Price hits the 1H Zone)
htf_long_cond = ta.crossover(emaFast, emaSlow)
htf_short_cond = ta.crossunder(emaFast, emaSlow)
// LTF Triggers (e.g., 5m or 1m confirmation pattern)
// For testing out of the box, we just require a strong close in the trade direction
ltf_long_cond = close > open and close > ta.ema(close, 9)
ltf_short_cond = close < open and close < ta.ema(close, 9)
// ==============================================================================
// 3. STATE MANAGEMENT
// ==============================================================================
var int wide_dir = 0 // 1 = Long, -1 = Short, 0 = Flat
var float wide_ep = na, var float wide_sl = na, var float wide_tp = na
var int ref_dir = 0
var float ref_ep = na, var float ref_sl = na, var float ref_tp = na
// Search Window State
var bool searching_ltf = false
var int search_dir = 0
var int bars_since_htf = 0
// Metrics Trackers
var float wide_R_total = 0.0
var int wide_wins = 0, var int wide_losses = 0
var float ref_R_total = 0.0
var int ref_wins = 0, var int ref_losses = 0
var int ref_missed = 0
// ==============================================================================
// 4. EXECUTION ENGINE
// ==============================================================================
// A. Triggering HTF (Wide)
if (htf_long_cond or htf_short_cond) and wide_dir == 0
wide_dir := htf_long_cond ? 1 : -1
wide_ep := close
sl_dist = i_wide_sl_pips * pip_size
tp_dist = sl_dist * i_wide_rr
wide_sl := wide_dir == 1 ? wide_ep - sl_dist : wide_ep + sl_dist
wide_tp := wide_dir == 1 ? wide_ep + tp_dist : wide_ep - tp_dist
// Open the window for the LTF signal
searching_ltf := true
search_dir := wide_dir
bars_since_htf := 0
// B. Hunting for LTF (Refined)
if searching_ltf and ref_dir == 0
// Check if window expired
if bars_since_htf > i_ltf_window
searching_ltf := false
ref_missed += 1
else
// Check for LTF signal matching HTF direction
ltf_trigger = (search_dir == 1 and ltf_long_cond) or (search_dir == -1 and ltf_short_cond)
if ltf_trigger
ref_dir := search_dir
ref_ep := close
sl_dist = i_ref_sl_pips * pip_size
tp_dist = sl_dist * i_ref_rr
ref_sl := ref_dir == 1 ? ref_ep - sl_dist : ref_ep + sl_dist
ref_tp := ref_dir == 1 ? ref_ep + tp_dist : ref_ep - tp_dist
searching_ltf := false
bars_since_htf += 1
// C. Trade Management (Checking hits on active trades)
if wide_dir != 0
hit_tp = (wide_dir == 1 and high >= wide_tp) or (wide_dir == -1 and low <= wide_tp)
hit_sl = (wide_dir == 1 and low <= wide_sl) or (wide_dir == -1 and high >= wide_sl)
if hit_tp
wide_R_total += i_wide_rr
wide_wins += 1
wide_dir := 0
else if hit_sl
wide_R_total -= 1.0
wide_losses += 1
wide_dir := 0
if ref_dir != 0
hit_tp = (ref_dir == 1 and high >= ref_tp) or (ref_dir == -1 and low <= ref_tp)
hit_sl = (ref_dir == 1 and low <= ref_sl) or (ref_dir == -1 and high >= ref_sl)
if hit_tp
ref_R_total += i_ref_rr
ref_wins += 1
ref_dir := 0
else if hit_sl
ref_R_total -= 1.0
ref_losses += 1
ref_dir := 0
// ==============================================================================
// 5. DASHBOARD UI
// ==============================================================================
var table dash = table.new(position.top_right, 4, 4, border_width=1)
if barstate.islast
table.cell(dash, 0, 0, "Strategy", text_color=color.white, bgcolor=color.gray)
table.cell(dash, 1, 0, "Total R", text_color=color.white, bgcolor=color.gray)
table.cell(dash, 2, 0, "Win %", text_color=color.white, bgcolor=color.gray)
table.cell(dash, 3, 0, "Trades / Missed", text_color=color.white, bgcolor=color.gray)
// Wide Row
wide_trades = wide_wins + wide_losses
wide_wr = wide_trades > 0 ? (wide_wins / wide_trades) * 100 : 0.0
table.cell(dash, 0, 1, "1H Structural", text_color=color.white, bgcolor=color.blue)
table.cell(dash, 1, 1, str.tostring(math.round(wide_R_total, 2)) + " R", text_color=wide_R_total >= 0 ? color.lime : color.red, bgcolor=color.new(color.black, 20))
table.cell(dash, 2, 1, str.tostring(math.round(wide_wr, 1)) + "%", text_color=color.white, bgcolor=color.new(color.black, 20))
table.cell(dash, 3, 1, str.tostring(wide_trades) + " / 0", text_color=color.white, bgcolor=color.new(color.black, 20))
// Refined Row
ref_trades = ref_wins + ref_losses
ref_wr = ref_trades > 0 ? (ref_wins / ref_trades) * 100 : 0.0
table.cell(dash, 0, 2, "LTF Refined", text_color=color.white, bgcolor=color.orange)
table.cell(dash, 1, 2, str.tostring(math.round(ref_R_total, 2)) + " R", text_color=ref_R_total >= 0 ? color.lime : color.red, bgcolor=color.new(color.black, 20))
table.cell(dash, 2, 2, str.tostring(math.round(ref_wr, 1)) + "%", text_color=color.white, bgcolor=color.new(color.black, 20))
table.cell(dash, 3, 2, str.tostring(ref_trades) + " / " + str.tostring(ref_missed), text_color=color.white, bgcolor=color.new(color.black, 20))