Untitled

 avatar
unknown
plain_text
a month ago
13 kB
7
Indexable
// ============================================================
// POWELL TRADES MODEL — Rejection Blocks + OTE + Key Opens
// ============================================================
//@version=5
indicator("Powell Trades Model — RB + OTE + Key Opens", 
          shorttitle="Powell Trades", 
          overlay=true, 
          max_boxes_count=200, 
          max_lines_count=200,
          max_labels_count=200)

// ─────────────────────────────────────────────
// INPUTS
// ─────────────────────────────────────────────
grp_ko = "Key Opens"
show_ko_18  = input.bool(true,  "Show 18:00 Key Open (NY 6 PM)",  group=grp_ko)
show_ko_00  = input.bool(true,  "Show 00:00 Key Open (Midnight)",  group=grp_ko)
show_ko_10  = input.bool(true,  "Show 10:00 Key Open (NY 10 AM)", group=grp_ko)
ko_col_18   = input.color(color.new(#FF9800, 60), "18:00 Colour", group=grp_ko)
ko_col_00   = input.color(color.new(#00BCD4, 60), "00:00 Colour", group=grp_ko)
ko_col_10   = input.color(color.new(#E91E63, 60), "10:00 Colour", group=grp_ko)
ko_extend   = input.bool(true, "Extend Key Open Lines Right", group=grp_ko)

grp_rb = "Rejection Blocks"
show_rb      = input.bool(true,  "Show Rejection Blocks",          group=grp_rb)
rb_pivot_len = input.int(5,      "Pivot Length (bars each side)",  group=grp_rb, minval=2, maxval=20)
min_wick_pct = input.float(0.4,  "Min Wick : Body Ratio",          group=grp_rb, minval=0.1, step=0.1)
bull_rb_col  = input.color(color.new(#26A69A, 70), "Bullish RB Fill",   group=grp_rb)
bear_rb_col  = input.color(color.new(#EF5350, 70), "Bearish RB Fill",   group=grp_rb)
bull_rb_bdr  = input.color(#26A69A, "Bullish RB Border", group=grp_rb)
bear_rb_bdr  = input.color(#EF5350, "Bearish RB Border", group=grp_rb)
max_rb       = input.int(8, "Max Active RBs", group=grp_rb, minval=1, maxval=20)

grp_ote = "OTE Zone"
show_ote     = input.bool(true,  "Show OTE Zone",                  group=grp_ote)
ote_swing    = input.int(20,     "Swing Lookback (bars)",          group=grp_ote, minval=5, maxval=100)
ote_lo       = input.float(0.618,"OTE Low Level (Fib)",            group=grp_ote)
ote_hi       = input.float(0.786,"OTE High Level (Fib)",           group=grp_ote)
ote_bull_col = input.color(color.new(#26A69A, 88), "Bullish OTE Fill", group=grp_ote)
ote_bear_col = input.color(color.new(#EF5350, 88), "Bearish OTE Fill", group=grp_ote)

grp_sig = "Signals"
show_sigs    = input.bool(true, "Show Entry Signals", group=grp_sig)
sig_bull_col = input.color(#26A69A, "Bullish Signal Colour", group=grp_sig)
sig_bear_col = input.color(#EF5350, "Bearish Signal Colour", group=grp_sig)

// ─────────────────────────────────────────────
// TIMEZONE / KEY OPENS
// ─────────────────────────────────────────────
tz       = "America/New_York"
bar_hour = hour(time, tz)
bar_min  = minute(time, tz)

is_new_hour(h) =>
    bar_hour == h and bar_min == 0 and bar_hour[1] != h

ext_right = ko_extend ? extend.right : extend.none

if show_ko_18 and is_new_hour(18)
    line.new(bar_index, open, bar_index, open, color=ko_col_18, width=1, style=line.style_dashed, extend=ext_right)
    label.new(bar_index, open, "18:00 Open", color=color.new(ko_col_18, 80), textcolor=ko_col_18, style=label.style_label_right, size=size.small)

if show_ko_00 and is_new_hour(0)
    line.new(bar_index, open, bar_index, open, color=ko_col_00, width=1, style=line.style_dashed, extend=ext_right)
    label.new(bar_index, open, "00:00 Open", color=color.new(ko_col_00, 80), textcolor=ko_col_00, style=label.style_label_right, size=size.small)

if show_ko_10 and is_new_hour(10)
    line.new(bar_index, open, bar_index, open, color=ko_col_10, width=1, style=line.style_dashed, extend=ext_right)
    label.new(bar_index, open, "10:00 Open", color=color.new(ko_col_10, 80), textcolor=ko_col_10, style=label.style_label_right, size=size.small)

// ─────────────────────────────────────────────
// OTE ZONE
// ─────────────────────────────────────────────
swing_high = ta.highest(high, ote_swing)
swing_low  = ta.lowest(low,   ote_swing)
range_sz   = swing_high - swing_low

bull_ote_hi = swing_high - range_sz * ote_lo
bull_ote_lo = swing_high - range_sz * ote_hi
bear_ote_lo = swing_low  + range_sz * ote_lo
bear_ote_hi = swing_low  + range_sz * ote_hi

mid       = (swing_high + swing_low) / 2
bull_bias = close < mid
bear_bias = close > mid

var box ote_box = na
if show_ote and barstate.islast
    if not na(ote_box)
        box.delete(ote_box)
    if bull_bias
        ote_box := box.new(bar_index - ote_swing, bull_ote_hi, bar_index + 10, bull_ote_lo, bgcolor=ote_bull_col, border_color=bull_rb_bdr, border_width=1)
    else
        ote_box := box.new(bar_index - ote_swing, bear_ote_hi, bar_index + 10, bear_ote_lo, bgcolor=ote_bear_col, border_color=bear_rb_bdr, border_width=1)

// ─────────────────────────────────────────────
// REJECTION BLOCKS
// ─────────────────────────────────────────────
body_size(i)  => math.abs(close[i] - open[i])
upper_wick(i) => high[i]  - math.max(open[i], close[i])
lower_wick(i) => math.min(open[i], close[i]) - low[i]

is_bull_rb(i) =>
    bdy = body_size(i)
    lw  = lower_wick(i)
    bdy > 0 and lw / math.max(bdy, syminfo.mintick) >= min_wick_pct and close[i] > open[i]

is_bear_rb(i) =>
    bdy = body_size(i)
    uw  = upper_wick(i)
    bdy > 0 and uw / math.max(bdy, syminfo.mintick) >= min_wick_pct and close[i] < open[i]

ph = ta.pivothigh(high, rb_pivot_len, rb_pivot_len)
pl = ta.pivotlow(low,   rb_pivot_len, rb_pivot_len)

var rb_boxes   = array.new_box(0)
var rb_is_bull = array.new_bool(0)
var rb_lo_arr  = array.new_float(0)
var rb_hi_arr  = array.new_float(0)

in_bull_ote() => close >= bull_ote_lo and close <= bull_ote_hi
in_bear_ote() => close >= bear_ote_lo and close <= bear_ote_hi

if show_rb
    if not na(pl)
        pb = rb_pivot_len
        if is_bull_rb(pb)
            rb_top = math.min(open[pb], close[pb])
            rb_bot = low[pb]
            bx = box.new(bar_index - pb, rb_top, bar_index + 40, rb_bot,
                         bgcolor=bull_rb_col, border_color=bull_rb_bdr, border_width=1,
                         text="Bull RB", text_color=bull_rb_bdr, text_size=size.tiny,
                         text_halign=text.align_left, text_valign=text.align_top)
            array.push(rb_boxes, bx)
            array.push(rb_is_bull, true)
            array.push(rb_lo_arr, rb_bot)
            array.push(rb_hi_arr, rb_top)
            if array.size(rb_boxes) > max_rb
                box.delete(array.shift(rb_boxes))
                array.shift(rb_is_bull)
                array.shift(rb_lo_arr)
                array.shift(rb_hi_arr)

    if not na(ph)
        pb = rb_pivot_len
        if is_bear_rb(pb)
            rb_bot = math.max(open[pb], close[pb])
            rb_top = high[pb]
            bx = box.new(bar_index - pb, rb_top, bar_index + 40, rb_bot,
                         bgcolor=bear_rb_col, border_color=bear_rb_bdr, border_width=1,
                         text="Bear RB", text_color=bear_rb_bdr, text_size=size.tiny,
                         text_halign=text.align_left, text_valign=text.align_bottom)
            array.push(rb_boxes, bx)
            array.push(rb_is_bull, false)
            array.push(rb_lo_arr, rb_bot)
            array.push(rb_hi_arr, rb_top)
            if array.size(rb_boxes) > max_rb
                box.delete(array.shift(rb_boxes))
                array.shift(rb_is_bull)
                array.shift(rb_lo_arr)
                array.shift(rb_hi_arr)

// Extend boxes + invalidation
if array.size(rb_boxes) > 0
    for i = array.size(rb_boxes) - 1 to 0
        bx      = array.get(rb_boxes, i)
        is_bull = array.get(rb_is_bull, i)
        rb_lo   = array.get(rb_lo_arr, i)
        rb_hi   = array.get(rb_hi_arr, i)
        box.set_right(bx, bar_index + 5)
        if is_bull and low < rb_lo
            box.delete(bx)
            array.remove(rb_boxes, i)
            array.remove(rb_is_bull, i)
            array.remove(rb_lo_arr, i)
            array.remove(rb_hi_arr, i)
        else if not is_bull and high > rb_hi
            box.delete(bx)
            array.remove(rb_boxes, i)
            array.remove(rb_is_bull, i)
            array.remove(rb_lo_arr, i)
            array.remove(rb_hi_arr, i)

// ─────────────────────────────────────────────
// ENTRY SIGNALS
// ─────────────────────────────────────────────
bull_signal = false
bear_signal = false

if show_sigs and array.size(rb_boxes) > 0
    for i = 0 to array.size(rb_boxes) - 1
        is_bull = array.get(rb_is_bull, i)
        rb_lo   = array.get(rb_lo_arr, i)
        rb_hi   = array.get(rb_hi_arr, i)
        if is_bull and low <= rb_hi and low >= rb_lo and in_bull_ote()
            bull_signal := true
        if not is_bull and high >= rb_lo and high <= rb_hi and in_bear_ote()
            bear_signal := true

if bull_signal
    label.new(bar_index, low - syminfo.mintick * 10, "▲ BUY\nRB+OTE",
              color=sig_bull_col, textcolor=color.white, style=label.style_label_up, size=size.normal)

if bear_signal
    label.new(bar_index, high + syminfo.mintick * 10, "▼ SELL\nRB+OTE",
              color=sig_bear_col, textcolor=color.white, style=label.style_label_down, size=size.normal)

// ─────────────────────────────────────────────
// ALERTS
// ─────────────────────────────────────────────
alertcondition(bull_signal,     "Powell Bull — RB inside OTE", "Bullish RB inside OTE — Potential Long")
alertcondition(bear_signal,     "Powell Bear — RB inside OTE", "Bearish RB inside OTE — Potential Short")
alertcondition(is_new_hour(18), "18:00 Key Open", "18:00 Key Open fired")
alertcondition(is_new_hour(0),  "00:00 Key Open", "00:00 Key Open fired")
alertcondition(is_new_hour(10), "10:00 Key Open", "10:00 Key Open fired")

// ─────────────────────────────────────────────
// INFO TABLE
// ─────────────────────────────────────────────
var table info = table.new(position.top_right, 2, 6, bgcolor=color.new(color.black, 80), border_color=color.gray, border_width=1)
if barstate.islast
    table.cell(info, 0, 0, "POWELL MODEL",   text_color=color.white, text_size=size.small, bgcolor=color.new(#1a1a2e, 40))
    table.cell(info, 1, 0, "",               text_color=color.white, text_size=size.small, bgcolor=color.new(#1a1a2e, 40))
    table.cell(info, 0, 1, "Bias",           text_color=color.gray,  text_size=size.tiny)
    table.cell(info, 1, 1, bull_bias ? "BULLISH" : "BEARISH", text_color=bull_bias ? color.new(#26A69A,0) : color.new(#EF5350,0), text_size=size.small)
    table.cell(info, 0, 2, "OTE Range",      text_color=color.gray,  text_size=size.tiny)
    table.cell(info, 1, 2, bull_bias ? str.tostring(math.round(bull_ote_lo,2))+" – "+str.tostring(math.round(bull_ote_hi,2)) : str.tostring(math.round(bear_ote_lo,2))+" – "+str.tostring(math.round(bear_ote_hi,2)), text_color=color.white, text_size=size.tiny)
    table.cell(info, 0, 3, "Active RBs",     text_color=color.gray,  text_size=size.tiny)
    table.cell(info, 1, 3, str.tostring(array.size(rb_boxes)), text_color=color.white, text_size=size.small)
    table.cell(info, 0, 4, "In OTE?",        text_color=color.gray,  text_size=size.tiny)
    in_ote_now = (bull_bias and in_bull_ote()) or (bear_bias and in_bear_ote())
    table.cell(info, 1, 4, in_ote_now ? "✓ YES" : "✗ NO", text_color=in_ote_now ? color.new(#26A69A,0) : color.gray, text_size=size.small)
    table.cell(info, 0, 5, "H / L",          text_color=color.gray,  text_size=size.tiny)
    table.cell(info, 1, 5, str.tostring(math.round(swing_high,2))+" / "+str.tostring(math.round(swing_low,2)), text_color=color.white, text_size=size.tiny)
Editor is loading...
Leave a Comment