//@version=5indicator("M&T", overlay=false, precision=4, max_labels_count=500)
// ==========================================// 1. INPUTS// ==========================================grp_ma = "MA Settings"src = input.source(close, "Price Source", group=grp_ma)ma_type = input.string("HWEMA", "MA Type", options=["SMA", "EMA", "Hull", "HWEMA"], group=grp_ma)ma_len = input.int(20, "MA Length", minval=1, group=grp_ma)
grp_proxy = "Buying/Selling Proxy"proxy_len = input.int(20, "Proxy Length", minval=1, group=grp_proxy)
grp_mtf = "MTF Momentum"use_tf1 = input.bool(true, "MTF 1", inline="tf1", group=grp_mtf)tf1 = input.timeframe("D", "", inline="tf1", group=grp_mtf)use_tf2 = input.bool(true, "MTF 2", inline="tf2", group=grp_mtf)tf2 = input.timeframe("3M", "", inline="tf2", group=grp_mtf)use_tf3 = input.bool(true, "MTF 3", inline="tf3", group=grp_mtf)tf3 = input.timeframe("12M", "", inline="tf3", group=grp_mtf)
grp_lines = "HTF Open Lines (Price Chart)"show_o1 = input.bool(true, "Show MTF 1 Open", group=grp_lines)show_o2 = input.bool(true, "Show MTF 2 Open", group=grp_lines)show_o3 = input.bool(true, "Show MTF 3 Open", group=grp_lines)
grp_bands = "HTF Exhaustion Bands"show_bands = input.bool(true, "Show Bands on Price Chart", group=grp_bands)band_lkbk = input.int(10, "Lookback Period", minval=2, group=grp_bands)band_mult = input.float(4.0, "Standard Deviation", minval=0, step=0.5, group=grp_bands)show_arr = input.bool(true, "Show Exhaustion Arrows", group=grp_bands)
grp_vis = "Visual Settings"upCol = input.color(color.lime, "Strong Bull", group=grp_vis)dnCol = input.color(color.red, "Strong Bear", group=grp_vis)bullWarn = input.color(color.orange, "Weak Bear", group=grp_vis)bearWarn = input.color(color.yellow, "Weak Bull", group=grp_vis)neutCol = input.color(color.white, "Neutral", group=grp_vis)dotSize = input.int(3, "Dot Size (1-10)", minval=1, maxval=10, group=grp_vis)v_gap = input.float(1.5, "Vertical Spacing", minval=0.5, group=grp_vis)
// ==========================================// 2. CALCULATIONS// ==========================================// Proxy CalculationrocSum = 0.0for i = 1 to proxy_len rocSum += math.log(close) - math.log(close[i])rocAverage = rocSum / proxy_lenproxy_bull = rocAverage >= 0
// --- HEATMAP LOGIC ---// Check if momentum is accelerating or decelerating compared to previous barbool proxy_rising = rocAverage > rocAverage[1]
// Determine dynamic color// If Bullish (>0): Bright Green if rising, Faded Green (50% transp) if falling (Divergence)// If Bearish (<0): Bright Red if falling, Faded Red (50% transp) if rising (Divergence)color col_proxy = proxy_bull ? (proxy_rising ? upCol : color.new(upCol, 50)) : (not proxy_rising ? dnCol : color.new(dnCol, 50))
o1 = request.security(syminfo.tickerid, tf1, open, lookahead=barmerge.lookahead_on)o2 = request.security(syminfo.tickerid, tf2, open, lookahead=barmerge.lookahead_on)o3 = request.security(syminfo.tickerid, tf3, open, lookahead=barmerge.lookahead_on)
get_secs(tf) => timeframe.in_seconds(tf)s1 = use_tf1 ? get_secs(tf1) : 0s2 = use_tf2 ? get_secs(tf2) : 0s3 = use_tf3 ? get_secs(tf3) : 0
high_tf = s3 >= s2 and s3 >= s1 and use_tf3 ? tf3 : s2 >= s1 and use_tf2 ? tf2 : use_tf1 ? tf1 : naimportant_open = high_tf == tf3 ? o3 : high_tf == tf2 ? o2 : o1current_dist = close - important_open
hwema_calc(source, len) => alpha = 1.0 wma_val = ta.wma(source, len) var float wema_ref = 0.0 wema_ref := alpha * wma_val + (1 - alpha) * nz(wema_ref[1]) ta.hma(wema_ref, len)
ma_val = ma_type == "HWEMA" ? hwema_calc(src, ma_len) : ta.sma(src, ma_len)ma_up = ma_val > ma_val[1]ma_dn = ma_val < ma_val[1]
is_pma_bull = close > ma_val and ma_upis_pma_bwrn = close > ma_val and not ma_upis_pma_bear = close < ma_val and ma_dnis_pma_ywrn = close < ma_val and not ma_dn
// ==========================================// 3. TFO ARRAY LOGIC (BANDS)// ==========================================var store_highest = array.new_float()var store_lowest = array.new_float()var float yearly_peak_up = 0.0var float yearly_peak_dn = 0.0
f_tfo_calc_band(arr, mult) => if array.size(arr) > 1 mean = array.avg(arr) accum = 0.0 for i = 0 to array.size(arr) - 1 accum += math.pow(math.abs(array.get(arr, i) - mean), 2) math.sqrt(accum / (array.size(arr) - 1)) * mult else 0.0
if timeframe.change(high_tf) if not na(yearly_peak_up) array.unshift(store_highest, yearly_peak_up) if array.size(store_highest) > band_lkbk array.pop(store_highest) if not na(yearly_peak_dn) array.unshift(store_lowest, yearly_peak_dn) if array.size(store_lowest) > band_lkbk array.pop(store_lowest) yearly_peak_up := 0.0 yearly_peak_dn := 0.0else yearly_peak_up := math.max(yearly_peak_up, current_dist) yearly_peak_dn := math.min(yearly_peak_dn, current_dist)
upper_band_price = important_open + f_tfo_calc_band(store_highest, band_mult)lower_band_price = important_open - f_tfo_calc_band(store_lowest, band_mult)
// ==========================================// 4. VISUALIZATION (DASHBOARD)// ==========================================y_pma = 0.0y_slope = v_gapy_proxy = v_gap * 2// Removed Proxy Signal Row, shifted MTF rows upy_tf1 = v_gap * 3y_tf2 = v_gap * 4y_tf3 = v_gap * 5
d_dots = display.all - display.status_line - display.price_scaled_bands = display.all - display.status_line
plot(is_pma_bull ? y_pma : na, "PtoMA Bull", color=upCol, linewidth=dotSize, style=plot.style_circles, display=d_dots, editable=false)plot(is_pma_bwrn ? y_pma : na, "PtoMA W-Bear", color=bullWarn, linewidth=dotSize, style=plot.style_circles, display=d_dots, editable=false)plot(is_pma_bear ? y_pma : na, "PtoMA Bear", color=dnCol, linewidth=dotSize, style=plot.style_circles, display=d_dots, editable=false)plot(is_pma_ywrn ? y_pma : na, "PtoMA W-Bull", color=bearWarn, linewidth=dotSize, style=plot.style_circles, display=d_dots, editable=false)
plot(ma_up ? y_slope : na, "Slope Bull", color=upCol, linewidth=dotSize, style=plot.style_circles, display=d_dots, editable=false)plot(ma_dn ? y_slope : na, "Slope Bear", color=dnCol, linewidth=dotSize, style=plot.style_circles, display=d_dots, editable=false)
// HEATMAP PLOTplot(y_proxy, "Proxy Heatmap", color=col_proxy, linewidth=dotSize, style=plot.style_circles, display=d_dots, editable=false)
plot(use_tf1 and close > o1 ? y_tf1 : na, "MTF1 Bull", color=upCol, linewidth=dotSize, style=plot.style_circles, display=d_dots, editable=false)plot(use_tf1 and close < o1 ? y_tf1 : na, "MTF1 Bear", color=dnCol, linewidth=dotSize, style=plot.style_circles, display=d_dots, editable=false)plot(use_tf2 and close > o2 ? y_tf2 : na, "MTF2 Bull", color=upCol, linewidth=dotSize, style=plot.style_circles, display=d_dots, editable=false)plot(use_tf2 and close < o2 ? y_tf2 : na, "MTF2 Bear", color=dnCol, linewidth=dotSize, style=plot.style_circles, display=d_dots, editable=false)plot(use_tf3 and close > o3 ? y_tf3 : na, "MTF3 Bull", color=upCol, linewidth=dotSize, style=plot.style_circles, display=d_dots, editable=false)plot(use_tf3 and close < o3 ? y_tf3 : na, "MTF3 Bear", color=dnCol, linewidth=dotSize, style=plot.style_circles, display=d_dots, editable=false)
// ==========================================// 5. PRICE CHART OVERLAYS// ==========================================d_bands := display.all - display.status_line - display.price_scale
plot(use_tf1 and show_o1 ? o1 : na, "MTF1 Open", color=color.gray, style=plot.style_stepline, linewidth=1, force_overlay=true, display=d_bands)plot(use_tf2 and show_o2 ? o2 : na, "MTF2 Open", color=color.gray, style=plot.style_stepline_diamond, linewidth=1, force_overlay=true, display=d_bands)plot(use_tf3 and show_o3 ? o3 : na, "MTF3 Open", color=color.gray, style=plot.style_stepline, linewidth=2, force_overlay=true, display=d_bands)
// RESTORED BANDSplot(show_bands ? upper_band_price : na, "Upper Band", color=color.lime, linewidth=2, force_overlay=true, display=d_bands)plot(show_bands ? lower_band_price : na, "Lower Band", color=color.red, linewidth=2, force_overlay=true, display=d_bands)
plotchar(show_arr and close > upper_band_price, "Upper Pierce", char='▼', location=location.abovebar, color=dnCol, size=size.tiny, force_overlay=true)plotchar(show_arr and close < lower_band_price, "Lower Pierce", char='▲', location=location.belowbar, color=upCol, size=size.tiny, force_overlay=true)
// ==========================================// 6. DYNAMIC LABELS// ==========================================f_draw_label(y_pos, txt, clr) => var label lbl = label.new(bar_index, y_pos, txt, xloc=xloc.bar_index, color=color.new(color.black,100), textcolor=clr, style=label.style_label_left, size=size.small) label.set_xy(lbl, bar_index + 2, y_pos) label.set_text(lbl, txt) label.set_textcolor(lbl, clr)
var label o1_lbl = navar label o2_lbl = navar label o3_lbl = navar label upper_lbl = navar label lower_lbl = na
if barstate.islast string pma_status = is_pma_bull ? "Strong Bull" : is_pma_bwrn ? "Weak Bear" : is_pma_bear ? "Strong Bear" : is_pma_ywrn ? "Weak Bull" : "Neutral" string pma_txt = "PtoMA: " + pma_status + " (" + str.tostring(close - ma_val, "#.##") + " | " + str.tostring(((close - ma_val) / ma_val) * 100, "#.##") + "%)" f_draw_label(y_pma, pma_txt, is_pma_bull ? upCol : is_pma_bwrn ? bullWarn : is_pma_bear ? dnCol : bearWarn) f_draw_label(y_slope, "Slope: " + (ma_up ? "Bullish" : ma_dn ? "Bearish" : "Neutral"), ma_up ? upCol : ma_dn ? dnCol : neutCol) // HEATMAP LABEL string proxy_str = (proxy_bull ? (proxy_rising ? "Bullish (Strong)" : "Bullish (Fading)") : (not proxy_rising ? "Bearish (Strong)" : "Bearish (Fading)")) + " | " + str.tostring(rocAverage*100, "#.##") f_draw_label(y_proxy, "Buying/Selling Proxy: (" + proxy_str + ")", col_proxy) if use_tf1 f_draw_label(y_tf1, tf1 + " Open: " + (close > o1 ? "Bullish" : "Bearish") + " (" + str.tostring(close - o1, "#.##") + " | " + str.tostring(((close - o1) / o1) * 100, "#.##") + "%)", close > o1 ? upCol : dnCol) if use_tf2 f_draw_label(y_tf2, tf2 + " Open: " + (close > o2 ? "Bullish" : "Bearish") + " (" + str.tostring(close - o2, "#.##") + " | " + str.tostring(((close - o2) / o2) * 100, "#.##") + "%)", close > o2 ? upCol : dnCol) if use_tf3 f_draw_label(y_tf3, tf3 + " Open: " + (close > o3 ? "Bullish" : "Bearish") + " (" + str.tostring(close - o3, "#.##") + " | " + str.tostring(((close - o3) / o3) * 100, "#.##") + "%)", close > o3 ? upCol : dnCol)
int l_offset = 5 // MTF 1 Adaptive Label if use_tf1 and show_o1 float o1_perc = ((close - o1) / o1) * 100 string o1_txt = tf1 + " Open: " + str.tostring(o1, "#.##") + " (" + str.tostring(o1_perc, "+#.##;-#.##") + "%)" color o1_bg = close > o1 ? color.new(upCol, 30) : close < o1 ? color.new(dnCol, 30) : color.new(color.gray, 30) if na(o1_lbl) o1_lbl := label.new(bar_index + l_offset, o1, o1_txt, xloc=xloc.bar_index, style=label.style_label_left, color=o1_bg, textcolor=color.white, size=size.small, force_overlay=true) else label.set_xy(o1_lbl, bar_index + l_offset, o1) label.set_text(o1_lbl, o1_txt) label.set_color(o1_lbl, o1_bg) // MTF 2 Adaptive Label if use_tf2 and show_o2 float o2_perc = ((close - o2) / o2) * 100 string o2_txt = tf2 + " Open: " + str.tostring(o2, "#.##") + " (" + str.tostring(o2_perc, "+#.##;-#.##") + "%)" color o2_bg = close > o2 ? color.new(upCol, 30) : close < o2 ? color.new(dnCol, 30) : color.new(color.gray, 30) if na(o2_lbl) o2_lbl := label.new(bar_index + l_offset, o2, o2_txt, xloc=xloc.bar_index, style=label.style_label_left, color=o2_bg, textcolor=color.white, size=size.small, force_overlay=true) else label.set_xy(o2_lbl, bar_index + l_offset, o2) label.set_text(o2_lbl, o2_txt) label.set_color(o2_lbl, o2_bg)
// MTF 3 Adaptive Label if use_tf3 and show_o3 float o3_perc = ((close - o3) / o3) * 100 string o3_txt = tf3 + " Open: " + str.tostring(o3, "#.##") + " (" + str.tostring(o3_perc, "+#.##;-#.##") + "%)" color o3_bg = close > o3 ? color.new(upCol, 30) : close < o3 ? color.new(dnCol, 30) : color.new(color.gray, 30) if na(o3_lbl) o3_lbl := label.new(bar_index + l_offset, o3, o3_txt, xloc=xloc.bar_index, style=label.style_label_left, color=o3_bg, textcolor=color.white, size=size.small, force_overlay=true) else label.set_xy(o3_lbl, bar_index + l_offset, o3) label.set_text(o3_lbl, o3_txt) label.set_color(o3_lbl, o3_bg)
// RESTORED BAND LABELS if show_bands float upper_perc = ((close - upper_band_price) / upper_band_price) * 100 string upper_txt = str.tostring(band_mult, "#.#") + "σ: " + str.tostring(upper_band_price, "#.##") + " (" + str.tostring(upper_perc, "+#.##;-#.##") + "%)" if na(upper_lbl) upper_lbl := label.new(bar_index + l_offset, upper_band_price, upper_txt, xloc=xloc.bar_index, style=label.style_label_left, color=color.new(color.lime, 40), textcolor=color.white, size=size.small, force_overlay=true) else label.set_xy(upper_lbl, bar_index + l_offset, upper_band_price) label.set_text(upper_lbl, upper_txt)
float lower_perc = ((close - lower_band_price) / lower_band_price) * 100 string lower_txt = str.tostring(band_mult, "#.#") + "σ: " + str.tostring(lower_band_price, "#.##") + " (" + str.tostring(lower_perc, "+#.##;-#.##") + "%)" if na(lower_lbl) lower_lbl := label.new(bar_index + l_offset, lower_band_price, lower_txt, xloc=xloc.bar_index, style=label.style_label_left, color=color.new(color.red, 40), textcolor=color.white, size=size.small, force_overlay=true) else label.set_xy(lower_lbl, bar_index + l_offset, lower_band_price) label.set_text(lower_lbl, lower_txt)