munger-engine / docs /RSI_MACD.pine
dromerosm's picture
feat: integrate real Alpaca orders in detail page and chart with layer toggles
bf9d545
// © 2026 Enhanced for Munger Engine Strategy
// This script combines MACD and RSI with multi-timeframe analysis,
// divergence detection, and momentum confirmation to complement
// the Munger Engine weekly value investing strategy.
//@version=6
indicator("Enhanced RSI & MACD", "RSI/MACD+", false)
// =====================
// 1. INPUTS
// =====================
// --- Display Mode ---
display_group = "0. Display Mode"
indicator_mode = input.string("MACD", "Show Indicator", options=["MACD", "RSI"], group = display_group)
// --- MACD Inputs ---
macd_group = "1. MACD Settings"
fast_len = input.int(12, "Fast Length", group = macd_group)
slow_len = input.int(26, "Slow Length", group = macd_group)
signal_len = input.int(9, "Signal Length", group = macd_group)
source = input.source(close, "Source", group = macd_group)
// --- RSI Inputs ---
rsi_group = "2. RSI Settings"
rsi_len = input.int(14, "RSI Length", group = rsi_group)
rsi_ob = input.int(70, "Overbought Level", group = rsi_group)
rsi_os = input.int(30, "Oversold Level", group = rsi_group)
// --- Multi-Timeframe ---
mtf_group = "3. Multi-Timeframe"
show_weekly = input.bool(true, "Show Weekly Indicators", group = mtf_group)
weekly_opacity = input.int(50, "Weekly Line Opacity", minval=0, maxval=100, group = mtf_group)
// --- Divergence Detection ---
div_group = "4. Divergence Detection"
enable_div = input.bool(true, "Enable Divergence Detection", group = div_group)
div_lookback = input.int(5, "Lookback Period", minval=2, maxval=20, group = div_group)
// --- Momentum Confirmation ---
mom_group = "5. Momentum Signals"
show_momentum = input.bool(true, "Show Momentum Background", group = mom_group)
show_info_panel = input.bool(true, "Show Info Panel", group = mom_group)
// =====================
// 2. CALCULATIONS
// =====================
// --- Daily MACD & RSI ---
[macdLine, signalLine, histLine] = ta.macd(source, fast_len, slow_len, signal_len)
rsi_val = ta.rsi(source, rsi_len)
// --- Weekly MACD & RSI ---
calc_weekly_indicators() =>
[w_macd, w_signal, w_hist] = ta.macd(close, fast_len, slow_len, signal_len)
w_rsi = ta.rsi(close, rsi_len)
[w_macd, w_signal, w_hist, w_rsi]
[w_macdLine, w_signalLine, w_histLine, w_rsi_val] = request.security(syminfo.tickerid, "W", calc_weekly_indicators())
// --- Momentum State ---
// Bullish: RSI > 50 AND MACD hist rising
// Bearish: RSI < 50 OR MACD hist falling
macd_rising = histLine > histLine[1]
macd_falling = histLine < histLine[1]
momentum_bullish = rsi_val > 50 and macd_rising
momentum_bearish = rsi_val < 50 or macd_falling
momentum_neutral = not momentum_bullish and not momentum_bearish
// Weekly momentum
w_macd_rising = w_histLine > w_histLine[1]
w_momentum_bullish = w_rsi_val > 50 and w_macd_rising
// --- Divergence Detection ---
// Bullish Divergence: Price lower low, RSI higher low
// Bearish Divergence: Price higher high, RSI lower high
find_pivot_low(src, left, right) =>
pivot = true
for i = 1 to left
if src[i] < src
pivot := false
for i = 0 to right - 1
if src[i] < src
pivot := false
pivot
find_pivot_high(src, left, right) =>
pivot = true
for i = 1 to left
if src[i] > src
pivot := false
for i = 0 to right - 1
if src[i] > src
pivot := false
pivot
// Detect divergences and store reason text
var float last_pivot_low_price = na
var float last_pivot_low_rsi = na
var int last_pivot_low_bar = na
var float last_pivot_high_price = na
var float last_pivot_high_rsi = na
var int last_pivot_high_bar = na
bullish_div = false
bearish_div = false
var string bullish_reason = ""
var string bearish_reason = ""
if enable_div
// Check for pivot lows
if find_pivot_low(low, div_lookback, div_lookback)
if not na(last_pivot_low_price)
// Price made lower low, RSI made higher low
if low < last_pivot_low_price and rsi_val > last_pivot_low_rsi
bullish_div := true
bullish_reason := "BULLISH DIVERGENCE\n" +
"------------------------\n" +
"Price: Lower Low\n" +
" Prev: " + str.tostring(last_pivot_low_price, format.mintick) + "\n" +
" Now: " + str.tostring(low, format.mintick) + "\n" +
"RSI: Higher Low\n" +
" Prev: " + str.tostring(last_pivot_low_rsi, "#.2") + "\n" +
" Now: " + str.tostring(rsi_val, "#.2") + "\n" +
"------------------------\n" +
"Signal: Potential reversal up"
last_pivot_low_price := low
last_pivot_low_rsi := rsi_val
last_pivot_low_bar := bar_index
// Check for pivot highs
if find_pivot_high(high, div_lookback, div_lookback)
if not na(last_pivot_high_price)
// Price made higher high, RSI made lower high
if high > last_pivot_high_price and rsi_val < last_pivot_high_rsi
bearish_div := true
bearish_reason := "BEARISH DIVERGENCE\n" +
"------------------------\n" +
"Price: Higher High\n" +
" Prev: " + str.tostring(last_pivot_high_price, format.mintick) + "\n" +
" Now: " + str.tostring(high, format.mintick) + "\n" +
"RSI: Lower High\n" +
" Prev: " + str.tostring(last_pivot_high_rsi, "#.2") + "\n" +
" Now: " + str.tostring(rsi_val, "#.2") + "\n" +
"------------------------\n" +
"Signal: Potential reversal down"
last_pivot_high_price := high
last_pivot_high_rsi := rsi_val
last_pivot_high_bar := bar_index
// =====================
// 3. PLOTTING
// =====================
// --- Background for Momentum Zones ---
bgcolor_color = show_momentum ?
(momentum_bullish ? color.new(color.green, 95) :
momentum_bearish ? color.new(color.red, 95) :
color.new(color.gray, 98)) : na
bgcolor(bgcolor_color, title="Momentum Background")
// --- Plot MACD (if selected) ---
show_macd = indicator_mode == "MACD"
histColor = histLine >= 0 ? color.new(color.green, 40) : color.new(color.red, 40)
plot(show_macd ? histLine : na, title="Daily Histogram", style=plot.style_histogram, color=histColor, linewidth=2)
plot(show_macd ? macdLine : na, title="Daily MACD", color=color.new(color.blue, 0), linewidth=2)
plot(show_macd ? signalLine : na, title="Daily Signal", color=color.new(color.orange, 0), linewidth=2)
hline(0, "Zero Line", color.gray, hline.style_dashed)
// --- Plot Weekly MACD (if enabled and MACD mode) ---
w_histColor = w_histLine >= 0 ? color.new(color.green, weekly_opacity) : color.new(color.red, weekly_opacity)
plot(show_macd and show_weekly ? w_histLine : na, title="Weekly Histogram", style=plot.style_line, color=w_histColor, linewidth=1)
plot(show_macd and show_weekly ? w_macdLine : na, title="Weekly MACD", color=color.new(color.blue, weekly_opacity), linewidth=1, style=plot.style_circles)
plot(show_macd and show_weekly ? w_signalLine : na, title="Weekly Signal", color=color.new(color.orange, weekly_opacity), linewidth=1, style=plot.style_circles)
// --- Plot RSI (if selected) ---
show_rsi = indicator_mode == "RSI"
plot(show_rsi ? rsi_val : na, title="Daily RSI", color=color.new(color.purple, 0), linewidth=2)
plot(show_rsi and show_weekly ? w_rsi_val : na, title="Weekly RSI", color=color.new(color.purple, weekly_opacity), linewidth=1, style=plot.style_circles)
// Plot RSI reference levels (only when RSI mode)
ob_line = hline(show_rsi ? rsi_ob : na, "RSI Overbought", color.maroon, hline.style_dashed)
os_line = hline(show_rsi ? rsi_os : na, "RSI Oversold", color.maroon, hline.style_dashed)
mid_line = hline(show_rsi ? 50 : na, "RSI Midline", color.gray, hline.style_dotted)
fill(ob_line, os_line, color=show_rsi ? color.new(color.purple, 90) : na, title="RSI Background Fill")
// --- Divergence Markers with Tooltips ---
// Position labels based on indicator mode for visibility
label_y_bottom = show_rsi ? rsi_os - 5 : histLine < 0 ? histLine * 1.5 : -math.abs(histLine) * 0.5
label_y_top = show_rsi ? rsi_ob + 5 : histLine > 0 ? histLine * 1.5 : math.abs(histLine) * 0.5
if bullish_div
label.new(bar_index, label_y_bottom, text="▲", color=color.lime, textcolor=color.white,
style=label.style_label_up, size=size.small, tooltip=bullish_reason)
if bearish_div
label.new(bar_index, label_y_top, text="▼", color=color.red, textcolor=color.white,
style=label.style_label_down, size=size.small, tooltip=bearish_reason)
// =====================
// 4. INFO PANEL
// =====================
if show_info_panel and barstate.islast
var table info_panel = table.new(position.bottom_right, 2, 5, border_width=1)
// Header
table.cell(info_panel, 0, 0, "Timeframe", bgcolor=color.gray, text_color=color.white, text_size=size.small)
table.cell(info_panel, 1, 0, "Momentum", bgcolor=color.gray, text_color=color.white, text_size=size.small)
// Daily
daily_state = momentum_bullish ? "BULLISH" : momentum_bearish ? "BEARISH" : "NEUTRAL"
daily_color = momentum_bullish ? color.new(color.green, 70) : momentum_bearish ? color.new(color.red, 70) : color.new(color.gray, 70)
table.cell(info_panel, 0, 1, "Daily", text_size=size.small)
table.cell(info_panel, 1, 1, daily_state, bgcolor=daily_color, text_size=size.small)
// Weekly
weekly_state = w_momentum_bullish ? "BULLISH" : "BEARISH"
weekly_color = w_momentum_bullish ? color.new(color.green, 70) : color.new(color.red, 70)
table.cell(info_panel, 0, 2, "Weekly", text_size=size.small)
table.cell(info_panel, 1, 2, weekly_state, bgcolor=weekly_color, text_size=size.small)
// RSI Comparison
rsi_diff = rsi_val - w_rsi_val
rsi_trend = rsi_diff > 0 ? "D > W" : "D < W"
table.cell(info_panel, 0, 3, "RSI", text_size=size.small)
table.cell(info_panel, 1, 3, rsi_trend, text_size=size.small)
// MACD Trend
macd_trend = macd_rising ? "RISING" : macd_falling ? "FALLING" : "FLAT"
macd_color = macd_rising ? color.new(color.green, 70) : macd_falling ? color.new(color.red, 70) : color.new(color.gray, 70)
table.cell(info_panel, 0, 4, "MACD", text_size=size.small)
table.cell(info_panel, 1, 4, macd_trend, bgcolor=macd_color, text_size=size.small)