Volume-Enhanced Candlestick Patterns 1
Overview
Scans for four major candlestick reversal patterns:
Harami
Engulfing
Morning/Evening Star
Piercing Line/Dark Cloud Cover
Underlying logic assumes that, at a turning point, the dominant side (bulls or bears) often delivers a “final” push—either a last surge of buying or selling—before the reversal truly takes hold.
Pattern Toggles
Each individual pattern can be turned on or off in the inputs.
Enable only the patterns you want to monitor to reduce chart clutter and speed up performance.
Volume Filter Toggle
On: Requires volume-based exhaustion or climax to confirm each pattern.
Off: Relies purely on price-action candlestick logic (no volume checks).
Grouped Labels & Confluence
When one or more patterns trigger on the same bar close, a single label is drawn:
Grouping multiple confirmed patterns on one bar increases confluence and signal strength.
Climax Volume × Multiplier
Adjusting this input affects signal frequency and conviction:
Higher multiplier → fewer signals but with stronger volume confirmation
Lower multiplier → more signals, each with a looser volume requirement
Alerts
Built-in alert condition for each individual pattern (bullish/bearish Harami, Engulfing, Star, Piercing, Dark Cloud Cover), so you can receive real-time notifications whenever a confirmation occurs.
Follow for Weekly Scripts
If you find this helpful, please hit Follow and 🚀button —I release a new scripts every week.
Disclaimer
Not Financial Advice. This script is for educational and research purposes only.
Use as Part of a Larger System. It should not be used in isolation; combine it with your own risk management rules, additional indicators, and broader market analysis.
No Guarantees. Candlestick patterns and volume filters can improve signal quality, but they do not guarantee profitable trades. Always perform your own due diligence before entering any position.
Candlestick analysis
Harman Nifty Indicator - Sell Puts & Sell CallsThis Indicator is desine to trade Nifty on 3 Minute Chart.
Harman-YNJ Setup Weekly-1.0This Indicator is Based on RSI and MACD. Useful to catch reversal trades.
Bullish/Bearish Market IndicatorIt shows clearly if bullish or bearish, it is a very clear pine and a game changer
eriktrades1995: supply demandThe Institutional Supply and Demand Zones indicator aims to identify and mark key price reversal areas on charts. These zones are considered places where institutions (large funds) concentrate their buying (forming demand zones) or selling (forming supply zones).
The core logic involves processing each candlestick sequentially. Before identifying new zones, the indicator checks if existing ones are still valid: demand zones become invalid if the current low breaks below their bottom, and supply zones become invalid if the current high breaks above their top. The most crucial part is identifying new zones, primarily based on the combination of the "previous" and "current" candlesticks. A demand zone (potential support) typically forms when a strong bullish candlestick (e.g., engulfing or significant reversal) appears after a bearish or doji candlestick, indicating strong buying interest. Conversely, a supply zone (potential resistance) usually forms when a strong bearish candlestick appears after a bullish or doji candlestick, signaling strong selling interest. The boundaries of these zones are typically derived from the open, high, or low prices of the candlesticks that form the pattern. Finally, the indicator draws the most recent and still valid supply zones (often filled in red as resistance) and demand zones (often filled in green as support) on the chart, up to a predefined maximum number. In essence, this indicator analyzes price action, particularly comparing candlestick body sizes and engulfing relationships, to pinpoint price levels where significant institutional buying or selling power might be concentrated. These zones can then act as support or resistance when prices re-approach them in the future.
Liquidity Sweep Candlestick Pattern with MA Filter📌 Liquidity Sweep Candlestick Pattern with MA Filter
This custom indicator detects liquidity sweep candlestick patterns—price action events where the market briefly breaks a previous candle’s high or low to trap traders—paired with optional filters such as moving averages, color change candles, and strictness rules for better signal accuracy.
🔍 What is a Liquidity Sweep?
A liquidity sweep occurs when the price briefly breaks the high or low of a previous candle and then reverses direction. These events often occur around key support/resistance zones and are used by institutional traders to trap retail positions before moving the price in the intended direction.
🟢 Bullish Liquidity Sweep Criteria
The current candle is bullish (closes above its open).
The low of the current candle breaks the low of the previous candle.
The candle closes above the previous candle’s open.
Optionally, in Strict mode, it must also close above the previous candle’s high.
Optionally, it can be filtered to only show if the candle changed color from the previous one (e.g., red to green).
Can be filtered to only show when the price is above or below a moving average (if MA filter is enabled).
🔴 Bearish Liquidity Sweep Criteria
The current candle is bearish (closes below its open).
The high of the current candle breaks the high of the previous candle.
The candle closes below the previous candle’s open.
Optionally, in Strict mode, it must also close below the previous candle’s low.
Optionally, it can be filtered to only show if the candle changed color from the previous one (e.g., green to red).
Can be filtered to only show when the price is above or below a moving average (if MA filter is enabled).
⚙️ Features & Customization
✅ Signal Strictness
Choose between:
Less Strict (default): Basic wick break and close conditions.
Strict: Must close beyond the wick of the previous candle.
✅ Color Change Candles Only
Enable this to only show patterns when the candle color changes (e.g., from red to green or green to red). Helps filter fake-outs.
✅ Moving Average Filter (optional)
Supports several types of MAs: SMA, EMA, WMA, VWMA, RMA, HMA
Choose whether signals should only appear above or below the selected moving average.
✅ Custom Visuals
Show short (BS) or full (Bull Sweep / Bear Sweep) labels
Plot triangles or arrows to represent bullish and bearish sweeps
Customize label and shape colors
Optionally show/hide the moving average line
✅ Alerts
Includes alert options for:
Bullish sweep
Bearish sweep
Any sweep
📈 How to Use
Add the indicator to your chart.
Configure the strictness, color change, or MA filters based on your strategy.
Observe signals where price is likely to reverse after taking out liquidity.
Use with key support/resistance levels, order blocks, or volume zones for confluence.
⚠️ Note
This tool is for educational and strategy-building purposes. Always confirm signals with other indicators, context, and sound risk management.
Patterns Combined: Gartley,Crab,Deep Crab,Bat,Butterfly, Shark
indicator('Harmonic Patterns : Gartley,Crab,Deep Crab,Bat,Butterfly, Shark ',shorttitle = 'Patterns Combined', overlay=true, max_bars_back=1000, max_lines_count=500, max_labels_count=500)
//
CRAK1 = input.int(13, step=10)
CRAK2 = input.int(17, step=10)
CRAK3 = input.int(110, step=10)
CRAK4 = input.int(109, step=10)
CRAK5 = input.int(103, step=10)
CRAK6 = input.int(1, step=10)
CRAK7 = input.int(1, step=10)
CRAK8 = input.int(9, step=10)
CRAK9 = input.int(11, step=10)
CRAK10 = input.int(120, step=10)
CRAK11 = input.int(200, step=10)
CRAK12 = input.int(200, step=10)
CRAK13 = input.int(110, step=10)
CRAK14 = input.int(11, step=10)
CRAK15 = input.int(12, step=10)
CRAK16 = input.int(2, step=10)
CRAK17 = input.int(1, step=10)
CRAK18 = input.int(2, step=10)
CRAK19 = input.int(1, step=10)
CRAK20 = input.int(2, step=10)
///
DETECT3 = input.int(18, step=10)
PATTERN1 = input(true)
PATTERN10 = input.int(18, step=5, minval=1)
COLORP1 = input(color.rgb(43, 52, 146, 55))
zigzag1Width = 1
zigzag1Style = line.style_dotted
PATTERN2 = input(true)
PATTERN20 = input.int(24, step=5, minval=1)
COLORP2 = input(color.rgb(43, 52, 146, 55))
zigzag2Width = 1
zigzag2Style = line.style_dotted
PATTERN3 = input(true)
PATTERN30 = input.int(32, step=5, minval=1)
COLORP3 = input(color.rgb(43, 52, 146, 55))
zigzag3Width = 1
zigzag3Style = line.style_dotted
PATTERN4 = input(true)
PATTERN40 = input.int(38, step=5, minval=1)
COLORP4 = input(color.rgb(43, 52, 146, 55))
zigzag4Width = 1
zigzag4Style = line.style_dotted
P11 = input(true)
P22 = input(true)
P33 = input(true)
P44 = input(true)
P55 = input(true)
P66 = input(true)
DETECTM = input.int(18, minval=5, step=5, maxval=200)
//
DATAC = input.int(350, step=10)
DATAC2 = input.int(400, step=10)
//
MaxRiskPerReward = input.int(29, title='DETECT/PER', step=10, minval=0)
//
//
E1 = input.int(370, step=10)
E2 = input.int(390, step=10)
showStatTable = false
CANCLE_PATTERNS = input(false)
//
CRAKD90 = input.int(200, step=10)
CRAKFALSE200 = input.int(200, step=10)
CRAKFALSE100 = input.int(300, step=10)
///
BULL_PATTERNS = input(color.silver)
BEAR_PATTERNS = input(color.blue)
err_min = (100 - DETECTM) / 100
err_max = (100 + DETECTM) / 100
var zigzagpivots1 = array.new_float(0)
var zigzagpivotbars1 = array.new_int(0)
var zigzagpivotdirs1 = array.new_int(0)
var zigzagpivots2 = array.new_float(0)
var zigzagpivotbars2 = array.new_int(0)
var zigzagpivotdirs2 = array.new_int(0)
var zigzagpivots3 = array.new_float(0)
var zigzagpivotbars3 = array.new_int(0)
var zigzagpivotdirs3 = array.new_int(0)
var zigzagpivots4 = array.new_float(0)
var zigzagpivotbars4 = array.new_int(0)
var zigzagpivotdirs4 = array.new_int(0)
var wmlines1 = array.new_line(8)
var wmtype1 = array.new_int(2, 1)
var wmLabels1 = array.new_bool(13, false)
var wmLabel1 = array.new_label(1)
var wmlines2 = array.new_line(8)
var wmtype2 = array.new_int(2, 1)
var wmLabels2 = array.new_bool(13, false)
var wmLabel2 = array.new_label(1)
var wmlines3 = array.new_line(8)
var wmtype3 = array.new_int(2, 1)
var wmLabels3 = array.new_bool(13, false)
var wmLabel3 = array.new_label(1)
var wmlines4 = array.new_line(8)
var wmtype4 = array.new_int(2, 1)
var wmLabels4 = array.new_bool(13, false)
var wmLabel4 = array.new_label(1)
pivots(length) =>
float phigh = ta.highestbars(high, length) == 0 ? high : na
float plow = ta.lowestbars(low, length) == 0 ? low : na
dir = 0
iff_1 = plow and na(phigh) ? -1 : dir
dir := phigh and na(plow) ? 1 : iff_1
zigzag(length, zigzagpivots, zigzagpivotbars, zigzagpivotdirs) =>
= pivots(length)
dirchanged = ta.change(dir)
if phigh or plow
value = dir == 1 ? phigh : plow
bar = bar_index
newDir = dir
if not dirchanged and array.size(zigzagpivots) >= 1
pivot = array.shift(zigzagpivots)
pivotbar = array.shift(zigzagpivotbars)
pivotdir = array.shift(zigzagpivotdirs)
useNewValues = value * pivotdir < pivot * pivotdir
value := useNewValues ? pivot : value
bar := useNewValues ? pivotbar : bar
bar
if array.size(zigzagpivots) >= 2
LastPoint = array.get(zigzagpivots, 1)
newDir := dir * value > dir * LastPoint ? dir * 2 : dir
newDir
array.unshift(zigzagpivots, value=value)
array.unshift(zigzagpivotbars, bar)
array.unshift(zigzagpivotdirs, newDir)
if array.size(zigzagpivots) > DETECT3
array.pop(zigzagpivots)
array.pop(zigzagpivotbars)
array.pop(zigzagpivotdirs)
get_harmonic_label(wmLabels, dir, price, bar) =>
isP11 = array.get(wmLabels, 0)
isP22 = array.get(wmLabels, 1)
isP33 = array.get(wmLabels, 2)
isP44 = array.get(wmLabels, 3)
isP55 = array.get(wmLabels, 4)
isP66 = array.get(wmLabels, 5)
labelText = isP11 ? 'Gartley' : ''
labelText := labelText + (isP22 ? (labelText == '' ? '' : ' ') + 'Crab' : '')
labelText := labelText + (isP33 ? (labelText == '' ? '' : ' ') + 'Deep Crab' : '')
labelText := labelText + (isP44 ? (labelText == '' ? '' : ' ') + 'Bat' : '')
labelText := labelText + (isP55 ? (labelText == '' ? '' : ' ') + 'Butterfly' : '')
labelText := labelText + (isP66 ? (labelText == '' ? '' : ' ') + 'Shark' : '')
trendColor = dir > 0 ? BULL_PATTERNS : BEAR_PATTERNS
baseLabel = label.new(x=bar, y=price, text=labelText, yloc=yloc.price, color=trendColor, style=dir < 1 ? label.style_label_down : label.style_label_up, textcolor=color.black, size=size.normal)
baseLabel
detect_harmonic_pattern(zigzagpivots, zigzagpivotbars, zigzagpivotdirs, wmlines, wmlabel, wmtype, wmLabels, zigzagColor, zigzagWidth, zigzagStyle, showZigZag) =>
start = CANCLE_PATTERNS ? 1 : 0
wm_pattern = false
abcd_pattern = false
double_pattern = false
if array.size(zigzagpivots) >= 6 + start and showZigZag
d = array.get(zigzagpivots, start + 0)
dBar = array.get(zigzagpivotbars, start + 0)
dDir = array.get(zigzagpivotdirs, start + 0)
c = array.get(zigzagpivots, start + 1)
cBar = array.get(zigzagpivotbars, start + 1)
cDir = array.get(zigzagpivotdirs, start + 1)
b = array.get(zigzagpivots, start + 2)
bBar = array.get(zigzagpivotbars, start + 2)
bDir = array.get(zigzagpivotdirs, start + 2)
a = array.get(zigzagpivots, start + 3)
aBar = array.get(zigzagpivotbars, start + 3)
aDir = array.get(zigzagpivotdirs, start + 3)
x = array.get(zigzagpivots, start + 4)
xBar = array.get(zigzagpivotbars, start + 4)
xDir = array.get(zigzagpivotdirs, start + 4)
y = array.get(zigzagpivots, start + 5)
yBar = array.get(zigzagpivotbars, start + 5)
yDir = array.get(zigzagpivotdirs, start + 5)
highPoint = math.max(x, a, b, c, d)
lowPoint = math.min(x, a, b, c, d)
dir = c > d ? 1 : -1
xabRatio = math.abs(b - a) / math.abs(x - a)
abcRatio = math.abs(c - b) / math.abs(a - b)
bcdRatio = math.abs(d - c) / math.abs(b - c)
xadRatio = math.abs(d - a) / math.abs(x - a)
yxaRatio = math.abs(a - x) / math.abs(y - x)
abTime = math.abs(aBar - bBar)
cdTime = math.abs(cBar - dBar)
abPrice = math.abs(a - b)
cdPrice = math.abs(c - d)
time_ratio = cdTime / abTime
price_ratio = cdPrice / abPrice
abcdDirection = a < b and a < c and c < b and c < d and a < d and b < d ? 1 : a > b and a > c and c > b and c > d and a > d and b > d ? -1 : 0
risk = math.abs(b - d)
reward = math.abs(c - d)
riskPerReward = risk * 100 / (risk + reward)
if b < highPoint and b > lowPoint
//gartley
if P11 and xabRatio >= 0.588 * err_min and xabRatio <= 0.648 * err_max and abcRatio >= 0.382 * err_min and abcRatio <= 0.886 * err_max and xadRatio >= 0.786 * err_min and xadRatio <= 0.886 * err_max
wm_pattern := true
array.set(wmLabels, 0, true)
else
array.set(wmLabels, 0, false)
//Crab
if P22 and xabRatio >= 0.382 * err_min and xabRatio <= 0.618 * err_max and abcRatio >= 0.382 * err_min and abcRatio <= 0.886 * err_max and xadRatio >= 1.618 * err_min and xadRatio <= 1.902 * err_max
wm_pattern := true
array.set(wmLabels, 1, true)
else
array.set(wmLabels, 1, false)
//Deep Crab
if P33 and xabRatio >= 0.886 * err_min and xabRatio <= 0.936 * err_max and abcRatio >= 0.382 * err_min and abcRatio <= 0.886 * err_max and xadRatio >= 1.618 * err_min and xadRatio <= 1.902 * err_max
wm_pattern := true
array.set(wmLabels, 2, true)
else
array.set(wmLabels, 2, false)
//Bat
if P44 and xabRatio >= 0.382 * err_min and xabRatio <= 0.55 * err_max and abcRatio >= 0.382 * err_min and abcRatio <= 0.886 * err_max and xadRatio >= 0.886 * err_min and xadRatio <= 0.886 * err_max
wm_pattern := true
array.set(wmLabels, 3, true)
else
array.set(wmLabels, 3, false)
//Butterfly
if P55 and xabRatio >= 0.755 * err_min and xabRatio <= 0.816 * err_max and abcRatio >= 0.382 * err_min and abcRatio <= 0.886 * err_max and xadRatio >= 1.272 * err_min and xadRatio <= 1.272 * err_max
wm_pattern := true
array.set(wmLabels, 4, true)
else
array.set(wmLabels, 4, false)
//Shark
if P66 and xabRatio >= 0.382 * err_min and xabRatio <= 0.618 * err_max and abcRatio >= 1.13 * err_min and abcRatio <= 1.618 * err_max and xadRatio >= 0.886 * err_min and xadRatio <= 1.13 * err_max
wm_pattern := true
array.set(wmLabels, 5, true)
else
array.set(wmLabels, 5, false)
cancelW = false
cancelA = false
cancelD = false
if wm_pattern and x == x and a == a and b == b and c == c
line.delete(array.get(wmlines, 0))
line.delete(array.get(wmlines, 1))
line.delete(array.get(wmlines, 2))
line.delete(array.get(wmlines, 3))
line.delete(array.get(wmlines, 4))
line.delete(array.get(wmlines, 5))
line.delete(array.get(wmlines, 6))
line.delete(array.get(wmlines, 7))
label.delete(array.get(wmlabel, 0))
cancelW := true
cancelW
if abcd_pattern and a == a and b == b and c == c
line.delete(array.get(wmlines, 1))
line.delete(array.get(wmlines, 2))
line.delete(array.get(wmlines, 3))
label.delete(array.get(wmlabel, 0))
cancelA := true
cancelA
if double_pattern and a == a and b == b and c == c
line.delete(array.get(wmlines, 5))
label.delete(array.get(wmlabel, 0))
cancelD := true
cancelD
if wm_pattern
xa = line.new(y1=x, y2=a, x1=xBar, x2=aBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
ab = line.new(y1=a, y2=b, x1=aBar, x2=bBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
bc = line.new(y1=b, y2=c, x1=bBar, x2=cBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
cd = line.new(y1=c, y2=d, x1=cBar, x2=dBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
xb = line.new(y1=x, y2=b, x1=xBar, x2=bBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
bd = line.new(y1=b, y2=d, x1=bBar, x2=dBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
xd = line.new(y1=x, y2=d, x1=xBar, x2=dBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
ac = line.new(y1=a, y2=c, x1=aBar, x2=cBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
array.set(wmlines, 0, xa)
array.set(wmlines, 1, ab)
array.set(wmlines, 2, bc)
array.set(wmlines, 3, cd)
array.set(wmlines, 4, xb)
array.set(wmlines, 5, bd)
array.set(wmlines, 6, xd)
array.set(wmlines, 7, ac)
array.set(wmtype, 0, dir)
linefill.new(xa, xb, color=color.rgb(44, 93, 136, 94))
linefill.new(bc, bd, color=color.rgb(44, 93, 136, 94))
if abcd_pattern and not wm_pattern
ab = line.new(y1=a, y2=b, x1=aBar, x2=bBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
bc = line.new(y1=b, y2=c, x1=bBar, x2=cBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
cd = line.new(y1=c, y2=d, x1=cBar, x2=dBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
array.set(wmlines, 1, ab)
array.set(wmlines, 2, bc)
array.set(wmlines, 3, cd)
array.set(wmtype, 0, dir)
if double_pattern and not wm_pattern
bd = line.new(y1=b, y2=d, x1=bBar, x2=dBar, color=zigzagColor, width=zigzagWidth, style=zigzagStyle)
array.set(wmlines, 5, bd)
array.set(wmtype, 0, dir)
if wm_pattern or abcd_pattern or double_pattern
array.set(wmlabel, 0, get_harmonic_label(wmLabels, dir, d, dBar))
pattern = wm_pattern and not wm_pattern or abcd_pattern and not abcd_pattern or double_pattern and not double_pattern
pattern
zigzag(PATTERN10, zigzagpivots1, zigzagpivotbars1, zigzagpivotdirs1)
zigzag(PATTERN20, zigzagpivots2, zigzagpivotbars2, zigzagpivotdirs2)
zigzag(PATTERN30, zigzagpivots3, zigzagpivotbars3, zigzagpivotdirs3)
zigzag(PATTERN40, zigzagpivots4, zigzagpivotbars4, zigzagpivotdirs4)
wm_pattern1 = detect_harmonic_pattern(zigzagpivots1, zigzagpivotbars1, zigzagpivotdirs1, wmlines1, wmLabel1, wmtype1, wmLabels1, COLORP1, zigzag1Width, zigzag1Style, PATTERN1)
wm_pattern2 = detect_harmonic_pattern(zigzagpivots2, zigzagpivotbars2, zigzagpivotdirs2, wmlines2, wmLabel2, wmtype2, wmLabels2, COLORP2, zigzag2Width, zigzag2Style, PATTERN2)
wm_pattern3 = detect_harmonic_pattern(zigzagpivots3, zigzagpivotbars3, zigzagpivotdirs3, wmlines3, wmLabel3, wmtype3, wmLabels3, COLORP3, zigzag3Width, zigzag3Style, PATTERN3)
wm_pattern4 = detect_harmonic_pattern(zigzagpivots4, zigzagpivotbars4, zigzagpivotdirs4, wmlines4, wmLabel4, wmtype4, wmLabels4, COLORP4, zigzag4Width, zigzag4Style, PATTERN4)
alertcondition(wm_pattern1 or wm_pattern2 or wm_pattern3 or wm_pattern4, title='Harmonic Alert', message='Harmonic Alert {{ticker}}')
var stats = table.new(position=position.top_right, columns=8, rows=DETECT3 + 2, border_width=1)
if barstate.islast and showStatTable
if PATTERN1
table.cell(table_id=stats, column=0, row=0, text='Zigzag ' + str.tostring(PATTERN10), bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=0, row=1, text='Price', bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=1, row=1, text='BarIndex', bgcolor=color.black, text_color=color.white)
for i = 0 to array.size(zigzagpivots1) - 1 by 1
bgcolor = array.get(zigzagpivotdirs1, i) == 1 ? color.lime : color.orange
table.cell(table_id=stats, column=0, row=i + 2, text=str.tostring(array.get(zigzagpivots1, i)), bgcolor=bgcolor)
table.cell(table_id=stats, column=1, row=i + 2, text=str.tostring(array.get(zigzagpivotbars2, i)), bgcolor=bgcolor)
if PATTERN2
table.cell(table_id=stats, column=2, row=0, text='Zigzag ' + str.tostring(PATTERN20), bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=2, row=1, text='Price', bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=3, row=1, text='BarIndex', bgcolor=color.black, text_color=color.white)
for i = 0 to array.size(zigzagpivots2) - 1 by 1
bgcolor = array.get(zigzagpivotdirs2, i) == 1 ? color.lime : color.orange
table.cell(table_id=stats, column=2, row=i + 2, text=str.tostring(array.get(zigzagpivots2, i)), bgcolor=bgcolor)
table.cell(table_id=stats, column=3, row=i + 2, text=str.tostring(array.get(zigzagpivotbars2, i)), bgcolor=bgcolor)
if PATTERN3
table.cell(table_id=stats, column=4, row=0, text='Zigzag ' + str.tostring(PATTERN30), bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=4, row=1, text='Price', bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=5, row=1, text='BarIndex', bgcolor=color.black, text_color=color.white)
for i = 0 to array.size(zigzagpivots3) - 1 by 1
bgcolor = array.get(zigzagpivotdirs3, i) == 1 ? color.lime : color.orange
table.cell(table_id=stats, column=4, row=i + 2, text=str.tostring(array.get(zigzagpivots3, i)), bgcolor=bgcolor)
table.cell(table_id=stats, column=5, row=i + 2, text=str.tostring(array.get(zigzagpivotbars3, i)), bgcolor=bgcolor)
if PATTERN4
table.cell(table_id=stats, column=6, row=0, text='Zigzag ' + str.tostring(PATTERN40), bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=6, row=1, text='Price', bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=7, row=1, text='BarIndex', bgcolor=color.black, text_color=color.white)
for i = 0 to array.size(zigzagpivots4) - 1 by 1
bgcolor = array.get(zigzagpivotdirs4, i) == 1 ? color.lime : color.orange
table.cell(table_id=stats, column=6, row=i + 2, text=str.tostring(array.get(zigzagpivots4, i)), bgcolor=bgcolor)
table.cell(table_id=stats, column=7, row=i + 2, text=str.tostring(array.get(zigzagpivotbars4, i)), bgcolor=bgcolor)
/////////
//'
//********************************************************
watermarki_supp = input.bool(true, 'Watermark', group = 'Author Sign') //confirm=true)
string i_tableYpos_oto_supp = input.string('top', 'Position', inline = '12', options = )
string i_tableXpos_oto_supp = input.string('right', '', inline = '12', options = )
int i_height_oto_supp = input.int(7, 'Height', minval = 1, maxval = 100, inline = '13')
int i_width_oto_supp = input.int(30, 'Width', minval = 1, maxval = 100, inline = '13a')
color i_c_text_oto_supp = input.color(color.new(color.white, 0), '', inline = '14')
color _bg_oto_supp = input.color(color.new(color.blue, 70), '', inline = '14')
string i_textSize = input.string('normal', 'Size', inline = '14', options = )
i_text2_supp = 'EarnWithEnigma'
i_text1_supp = 'When using the indicator EarnWithEnigma thank you'
var table watermark_supp = table.new(i_tableYpos_oto_supp + '_' + i_tableXpos_oto_supp, 1, 1)
if barstate.islast and watermarki_supp
varip bool _changeText_supp = true
_changeText_supp := not _changeText_supp
string _txt_supp = _changeText_supp ? i_text2_supp : i_text1_supp
table.cell(watermark_supp, 0, 0, i_text2_supp, i_width_oto_supp, i_height_oto_supp, i_c_text_oto_supp, text_size = i_textSize, bgcolor = _bg_oto_supp)
//#!
//fiboLevel= b + (1.618 * (c - b))
//line.new(x1=dBar+1, y1=fiboLevel, x2=dBar+40, y2=fiboLevel, color=color.red, width=1)
//isP11 = array.get(wmLabels, 0)
//isP22 = array.get(wmLabels, 1)
//isP33 = array.get(wmLabels, 2)
//isP44 = array.get(wmLabels, 3)
//isP55 = array.get(wmLabels, 4)
//isP66 = array.get(wmLabels, 5)
ICT + Kill Zone + Sillver Bullet
indicator("ICT + Sillver Bullet + Kill Zone ", overlay = true, max_labels_count = 500, max_lines_count = 500, max_boxes_count = 500)
// ---------------------------------------- Constant Functions --------------------------------------------------
get_line_type(_style) =>
result = switch _style
'Solid' => line.style_solid
'Dotted' => line.style_dotted
'Dashed' => line.style_dashed
result
get_size(x) =>
result = switch x
'Auto' => size.auto
'Tiny' => size.tiny
'Small' => size.small
'Normal' => size.normal
'Large' => size.large
'Huge' => size.huge
get_table_pos(pos) =>
result = switch pos
"Bottom Center" => position.bottom_center
"Bottom Left" => position.bottom_left
"Bottom Right" => position.bottom_right
"Middle Center" => position.middle_center
"Middle Left" => position.middle_left
"Middle Right" => position.middle_right
"Top Center" => position.top_center
"Top Left" => position.top_left
"Top Right" => position.top_right
// ---------------------------------------- Constant Functions --------------------------------------------------
// ---------------------------------------- Inputs --------------------------------------------------
var g_SETTINGS = "Settings"
max_days = input.int(3, "Session Drawing Limit", 1, tooltip = "Only this many drawings will be kept on the chart, for each selected drawing type (killzone boxes, pivot lines, open lines, etc.)", group = g_SETTINGS)
tf_limit = input.timeframe("30", "Timeframe Limit", tooltip = "Drawings will not appear on timeframes greater than or equal to this", group = g_SETTINGS)
gmt_tz = input.string('America/New_York', "Timezone", options = , tooltip = "Note GMT is not adjusted to reflect Daylight Saving Time changes", group = g_SETTINGS)
lbl_size = get_size(input.string('Normal', "Label Size", options = , tooltip = "The size of all labels", group = g_SETTINGS))
txt_color = input.color(color.black, "Text Color", tooltip = "The color of all label and table text", group = g_SETTINGS)
use_cutoff = input.bool(false, "Drawing Cutoff Time", inline = "CO", tooltip = "When enabled, all pivots and open price lines will stop extending at this time", group = g_SETTINGS)
cutoff = input.session("1800-1801", "", inline = "CO", group = g_SETTINGS)
var g_KZ = "Killzones"
show_kz = input.bool(true, "Show Killzone Boxes", inline = "KZ", group = g_KZ)
show_kz_text = input.bool(true, "Display Text", inline = "KZ", group = g_KZ)
use_asia = input.bool(true, "", inline = "ASIA", group = g_KZ)
as_txt = input.string("Asia", "", inline = "ASIA", group = g_KZ)
asia = input.session("2000-0000", "", inline = "ASIA", group = g_KZ)
as_color = input.color(color.blue, "", inline = "ASIA", group = g_KZ)
use_london = input.bool(true, "", inline = "LONDON", group = g_KZ)
lo_txt = input.string("London", "", inline = "LONDON", group = g_KZ)
london = input.session("0200-0500", "", inline = "LONDON", group = g_KZ)
lo_color = input.color(color.red, "", inline = "LONDON", group = g_KZ)
use_nyam = input.bool(true, "", inline = "NYAM", group = g_KZ)
na_txt = input.string("NY AM", "", inline = "NYAM", group = g_KZ)
nyam = input.session("0930-1100", "", inline = "NYAM", group = g_KZ)
na_color = input.color(#089981, "", inline = "NYAM", group = g_KZ)
use_nylu = input.bool(true, "", inline = "NYLU", group = g_KZ)
nl_txt = input.string("NY Lunch", "", inline = "NYLU", group = g_KZ)
nylu = input.session("1200-1300", "", inline = "NYLU", group = g_KZ)
nl_color = input.color(color.yellow, "", inline = "NYLU", group = g_KZ)
use_nypm = input.bool(true, "", inline = "NYPM", group = g_KZ)
np_txt = input.string("NY PM", "", inline = "NYPM", group = g_KZ)
nypm = input.session("1330-1600", "", inline = "NYPM", group = g_KZ)
np_color = input.color(color.purple, "", inline = "NYPM", group = g_KZ)
box_transparency = input.int(70, "Box Transparency", 0, 100, group = g_KZ)
text_transparency = input.int(50, "Text Transparency", 0, 100, group = g_KZ)
var g_LABELS = "Killzone Pivots"
show_pivots = input.bool(true, "Show Pivots", inline = "PV", group = g_LABELS)
use_alerts = input.bool(false, "Alert Broken Pivots", inline = "PV", tooltip = "The desired killzones must be enabled at the time that an alert is created, along with the show pivots option, in order for alerts to work", group = g_LABELS)
show_midpoints = input.bool(false, "Show Pivot Midpoints", group = g_LABELS)
show_labels = input.bool(true, "Show Pivot Labels", inline = "LB", tooltip = "Show labels denoting each killzone's high and low. Optionally choose to show the price of each level. Right side will show labels on the right-hand side of the chart until they are reached", group = g_LABELS)
label_price = input.bool(false, "Display Price", inline = "LB", group = g_LABELS)
label_right = input.bool(false, "Right Side", inline = "LB", group = g_LABELS)
ext_pivots = input.string("Until Mitigated", "Extend Pivots...", options = , group = g_LABELS)
ext_which = input.string("Most Recent", "...From Which Sessions", options = , group = g_LABELS)
ash_str = input.string("AS.H", "Killzone 1 Labels", inline = "L_AS", group = g_LABELS)
asl_str = input.string("AS.L", "", inline = "L_AS", group = g_LABELS)
loh_str = input.string("LO.H", "Killzone 2 Labels", inline = "L_LO", group = g_LABELS)
lol_str = input.string("LO.L", "", inline = "L_LO", group = g_LABELS)
nah_str = input.string("NYAM.H", "Killzone 3 Labels", inline = "L_NA", group = g_LABELS)
nal_str = input.string("NYAM.L", "", inline = "L_NA", group = g_LABELS)
nlh_str = input.string("NYL.H", "Killzone 4 Labels", inline = "L_NL", group = g_LABELS)
nll_str = input.string("NYL.L", "", inline = "L_NL", group = g_LABELS)
nph_str = input.string("NYPM.H", "Killzone 5 Labels", inline = "L_NP", group = g_LABELS)
npl_str = input.string("NYPM.L", "", inline = "L_NP", group = g_LABELS)
kzp_style = get_line_type(input.string(defval = 'Solid', title = "Pivot Style", options = , inline = "KZP", group = g_LABELS))
kzp_width = input.int(1, "", inline = "KZP", group = g_LABELS)
kzm_style = get_line_type(input.string(defval = 'Dotted', title = "Midpoint Style", options = , inline = "KZM", group = g_LABELS))
kzm_width = input.int(1, "", inline = "KZM", group = g_LABELS)
var g_RNG = "Killzone Range"
show_range = input.bool(false, "Show Killzone Range", tooltip = "Show the most recent ranges of each selected killzone, from high to low", group = g_RNG)
show_range_avg = input.bool(true, "Show Average", tooltip = "Show the average range of each selected killzone", group = g_RNG)
range_avg = input.int(5, "Average Length", 0, tooltip = "This many previous sessions will be used to calculate the average. If there isn't enough data on the current chart, it will use as many sessions as possible", group = g_RNG)
range_pos = get_table_pos(input.string('Top Right', "Table Position", options = , group = g_RNG))
range_size = get_size(input.string('Normal', "Table Size", options = , group = g_RNG))
var g_DWM = "Day - Week - Month"
sep_unlimited = input.bool(true, "Unlimited", tooltip = "Unlimited will show as many of the selected lines as possible. Otherwise, the session drawing limit will be used", group = g_DWM)
alert_HL = input.bool(false, "Alert High/Low Break", tooltip = "Alert when any selected highs and lows are traded through. The desired timeframe's high/low option must be enabled at the time that an alert is created", group = g_DWM)
show_d_open = input.bool(false, "D Open", inline = "DO", group = g_DWM)
dhl = input.bool(false, "High/Low", inline = "DO", tooltip = "", group = g_DWM)
ds = input.bool(false, "Separators", inline = "DO", tooltip = "Mark where a new day begins", group = g_DWM)
d_color = input.color(color.blue, "", inline = "DO", group = g_DWM)
show_w_open = input.bool(false, "W Open", inline = "WO", group = g_DWM)
whl = input.bool(false, "High/Low", inline = "WO", tooltip = "", group = g_DWM)
ws = input.bool(false, "Separators", inline = "WO", tooltip = "Mark where a new week begins", group = g_DWM)
w_color = input.color(#089981, "", inline = "WO", group = g_DWM)
show_m_open = input.bool(false, "M Open", inline = "MO", group = g_DWM)
mhl = input.bool(false, "High/Low", inline = "MO", tooltip = "", group = g_DWM)
ms = input.bool(false, "Separators", inline = "MO", tooltip = "Mark where a new month begins", group = g_DWM)
m_color = input.color(color.red, "", inline = "MO", group = g_DWM)
htf_style = get_line_type(input.string(defval = 'Solid', title = "Style", options = , inline = "D0", group = g_DWM))
htf_width = input.int(1, "", inline = "D0", group = g_DWM)
dow_labels = input.bool(true, "Day of Week Labels", inline = "DOW", group = g_DWM)
dow_yloc = input.string('Bottom', "", options = , inline = "DOW", group = g_DWM)
dow_xloc = input.string('Midnight', "", options = , inline = "DOW", group = g_DWM)
dow_hide_wknd = input.bool(true, "Hide Weekend Labels", group = g_DWM)
var g_OPEN = "Opening Prices"
open_unlimited = input.bool(true, "Unlimited", tooltip = "Unlimited will show as many of the selected lines as possible. Otherwise, the session drawing limit will be used", group = g_OPEN)
use_h1 = input.bool(true, "", inline = "H1", group = g_OPEN)
h1_text = input.string("True Day Open", "", inline = "H1", group = g_OPEN)
h1 = input.session("0000-0001", "", inline = "H1", group = g_OPEN)
h1_color = input.color(color.black, "", inline = "H1", group = g_OPEN)
use_h2 = input.bool(false, "", inline = "H2", group = g_OPEN)
h2_text = input.string("06:00", "", inline = "H2", group = g_OPEN)
h2 = input.session("0600-0601", "", inline = "H2", group = g_OPEN)
h2_color = input.color(color.black, "", inline = "H2", group = g_OPEN)
use_h3 = input.bool(false, "", inline = "H3", group = g_OPEN)
h3_text = input.string("10:00", "", inline = "H3", group = g_OPEN)
h3 = input.session("1000-1001", "", inline = "H3", group = g_OPEN)
h3_color = input.color(color.black, "", inline = "H3", group = g_OPEN)
use_h4 = input.bool(false, "", inline = "H4", group = g_OPEN)
h4_text = input.string("14:00", "", inline = "H4", group = g_OPEN)
h4 = input.session("1400-1401", "", inline = "H4", group = g_OPEN)
h4_color = input.color(color.black, "", inline = "H4", group = g_OPEN)
use_h5 = input.bool(false, "", inline = "H5", group = g_OPEN)
h5_text = input.string("00:00", "", inline = "H5", group = g_OPEN)
h5 = input.session("0000-0001", "", inline = "H5", group = g_OPEN)
h5_color = input.color(color.black, "", inline = "H5", group = g_OPEN)
use_h6 = input.bool(false, "", inline = "H6", group = g_OPEN)
h6_text = input.string("00:00", "", inline = "H6", group = g_OPEN)
h6 = input.session("0000-0001", "", inline = "H6", group = g_OPEN)
h6_color = input.color(color.black, "", inline = "H6", group = g_OPEN)
use_h7 = input.bool(false, "", inline = "H7", group = g_OPEN)
h7_text = input.string("00:00", "", inline = "H7", group = g_OPEN)
h7 = input.session("0000-0001", "", inline = "H7", group = g_OPEN)
h7_color = input.color(color.black, "", inline = "H7", group = g_OPEN)
use_h8 = input.bool(false, "", inline = "H8", group = g_OPEN)
h8_text = input.string("00:00", "", inline = "H8", group = g_OPEN)
h8 = input.session("0000-0001", "", inline = "H8", group = g_OPEN)
h8_color = input.color(color.black, "", inline = "H8", group = g_OPEN)
hz_style = get_line_type(input.string(defval = 'Dotted', title = "Style", options = , inline = "H0", group = g_OPEN))
hz_width = input.int(1, "", inline = "H0", group = g_OPEN)
var g_VERTICAL = "Timestamps"
v_unlimited = input.bool(true, "Unlimited", tooltip = "Unlimited will show as many of the selected lines as possible. Otherwise, the session drawing limit will be used", group = g_VERTICAL)
use_v1 = input.bool(false, "", inline = "V1", group = g_VERTICAL)
v1 = input.session("0000-0001", "", inline = "V1", group = g_VERTICAL)
v1_color = input.color(color.black, "", inline = "V1", group = g_VERTICAL)
use_v2 = input.bool(false, "", inline = "V2", group = g_VERTICAL)
v2 = input.session("0800-0801", "", inline = "V2", group = g_VERTICAL)
v2_color = input.color(color.black, "", inline = "V2", group = g_VERTICAL)
use_v3 = input.bool(false, "", inline = "V3", group = g_VERTICAL)
v3 = input.session("1000-1001", "", inline = "V3", group = g_VERTICAL)
v3_color = input.color(color.black, "", inline = "V3", group = g_VERTICAL)
use_v4 = input.bool(false, "", inline = "V4", group = g_VERTICAL)
v4 = input.session("1200-1201", "", inline = "V4", group = g_VERTICAL)
v4_color = input.color(color.black, "", inline = "V4", group = g_VERTICAL)
vl_style = get_line_type(input.string(defval = 'Dotted', title = "Style", options = , inline = "V0", group = g_VERTICAL))
vl_width = input.int(1, "", inline = "V0", group = g_VERTICAL)
// ---------------------------------------- Inputs --------------------------------------------------
// ---------------------------------------- Variables & Constants --------------------------------------------------
type kz
string _title
box _box
line _hi_line
line _md_line
line _lo_line
label _hi_label
label _lo_label
bool _hi_valid
bool _md_valid
bool _lo_valid
float _range_store
float _range_current
type hz
line LN
label LB
bool CO
type dwm_hl
line hi_line
line lo_line
label hi_label
label lo_label
bool hit_high = false
bool hit_low = false
type dwm_info
string tf
float o = na
float h = na
float l = na
float ph = na
float pl = na
var as_kz = kz.new(as_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float())
var lo_kz = kz.new(lo_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float())
var na_kz = kz.new(na_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float())
var nl_kz = kz.new(nl_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float())
var np_kz = kz.new(np_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float())
var hz_1 = hz.new(array.new_line(), array.new_label(), array.new_bool())
var hz_2 = hz.new(array.new_line(), array.new_label(), array.new_bool())
var hz_3 = hz.new(array.new_line(), array.new_label(), array.new_bool())
var hz_4 = hz.new(array.new_line(), array.new_label(), array.new_bool())
var hz_5 = hz.new(array.new_line(), array.new_label(), array.new_bool())
var hz_6 = hz.new(array.new_line(), array.new_label(), array.new_bool())
var hz_7 = hz.new(array.new_line(), array.new_label(), array.new_bool())
var hz_8 = hz.new(array.new_line(), array.new_label(), array.new_bool())
var d_hl = dwm_hl.new(array.new_line(), array.new_line(), array.new_label(), array.new_label())
var w_hl = dwm_hl.new(array.new_line(), array.new_line(), array.new_label(), array.new_label())
var m_hl = dwm_hl.new(array.new_line(), array.new_line(), array.new_label(), array.new_label())
var d_info = dwm_info.new("D")
var w_info = dwm_info.new("W")
var m_info = dwm_info.new("M")
t_as = not na(time("", asia, gmt_tz))
t_lo = not na(time("", london, gmt_tz))
t_na = not na(time("", nyam, gmt_tz))
t_nl = not na(time("", nylu, gmt_tz))
t_np = not na(time("", nypm, gmt_tz))
t_co = not na(time("", cutoff, gmt_tz))
t_h1 = not na(time("", h1, gmt_tz))
t_h2 = not na(time("", h2, gmt_tz))
t_h3 = not na(time("", h3, gmt_tz))
t_h4 = not na(time("", h4, gmt_tz))
t_h5 = not na(time("", h5, gmt_tz))
t_h6 = not na(time("", h6, gmt_tz))
t_h7 = not na(time("", h7, gmt_tz))
t_h8 = not na(time("", h8, gmt_tz))
t_v1 = not na(time("", v1, gmt_tz))
t_v2 = not na(time("", v2, gmt_tz))
t_v3 = not na(time("", v3, gmt_tz))
t_v4 = not na(time("", v4, gmt_tz))
var d_sep_line = array.new_line()
var w_sep_line = array.new_line()
var m_sep_line = array.new_line()
var d_line = array.new_line()
var w_line = array.new_line()
var m_line = array.new_line()
var d_label = array.new_label()
var w_label = array.new_label()
var m_label = array.new_label()
var v1_line = array.new_line()
var v2_line = array.new_line()
var v3_line = array.new_line()
var v4_line = array.new_line()
var transparent = #ffffff00
var ext_current = ext_which == 'Most Recent'
var ext_past = ext_pivots == 'Past Mitigation'
update_dwm_info(dwm_info n) =>
if timeframe.change(n.tf)
n.ph := n.h
n.pl := n.l
n.o := open
n.h := high
n.l := low
else
n.h := math.max(high, n.h)
n.l := math.min(low, n.l)
if dhl or show_d_open
update_dwm_info(d_info)
if whl or show_w_open
update_dwm_info(w_info)
if mhl or show_m_open
update_dwm_info(m_info)
// ---------------------------------------- Variables & Constants --------------------------------------------------
// ---------------------------------------- Functions --------------------------------------------------
get_box_color(color c) =>
result = color.new(c, box_transparency)
get_text_color(color c) =>
result = color.new(c, text_transparency)
// ---------------------------------------- Functions --------------------------------------------------
// ---------------------------------------- Core Logic --------------------------------------------------
dwm_sep(string tf, bool use, line arr, color col) =>
if use
if timeframe.change(tf)
arr.unshift(line.new(bar_index, high*1.0001, bar_index, low, style = htf_style, width = htf_width, extend = extend.both, color = col))
if not sep_unlimited and arr.size() > max_days
arr.pop().delete()
dwm_open(string tf, bool use, line lns, label lbls, dwm_info n, color col) =>
if use
if lns.size() > 0
lns.get(0).set_x2(time)
lbls.get(0).set_x(time)
if timeframe.change(tf)
lns.unshift(line.new(time, n.o, time, n.o, xloc = xloc.bar_time, style = htf_style, width = htf_width, color = col))
lbls.unshift(label.new(time, n.o, tf + " OPEN", xloc = xloc.bar_time, style = label.style_label_left, color = transparent, textcolor = txt_color, size = lbl_size))
if not sep_unlimited and lns.size() > max_days
lns.pop().delete()
lbls.pop().delete()
dwm_hl(string tf, bool use, dwm_hl hl, dwm_info n, color col) =>
if use
if hl.hi_line.size() > 0
hl.hi_line.get(0).set_x2(time)
hl.lo_line.get(0).set_x2(time)
hl.hi_label.get(0).set_x(time)
hl.lo_label.get(0).set_x(time)
if timeframe.change(tf)
hl.hi_line.unshift(line.new(time, n.ph, time, n.ph, xloc = xloc.bar_time, style = htf_style, width = htf_width, color = col))
hl.lo_line.unshift(line.new(time, n.pl, time, n.pl, xloc = xloc.bar_time, style = htf_style, width = htf_width, color = col))
hl.hi_label.unshift(label.new(time, n.ph, "P"+tf+"H", xloc = xloc.bar_time, style = label.style_label_left, color = transparent, textcolor = txt_color, size = lbl_size))
hl.lo_label.unshift(label.new(time, n.pl, "P"+tf+"L", xloc = xloc.bar_time, style = label.style_label_left, color = transparent, textcolor = txt_color, size = lbl_size))
hl.hit_high := false
hl.hit_low := false
if not sep_unlimited and hl.hi_line.size() > max_days
hl.hi_line.pop().delete()
hl.lo_line.pop().delete()
hl.hi_label.pop().delete()
hl.lo_label.pop().delete()
if hl.hi_line.size() > 0 and alert_HL
if not hl.hit_high and high > hl.hi_line.get(0).get_y1()
hl.hit_high := true
alert(str.format("Hit P{0}H", tf))
if not hl.hit_low and low < hl.lo_line.get(0).get_y1()
hl.hit_low := true
alert(str.format("Hit P{0}L", tf))
dwm() =>
if timeframe.in_seconds("") <= timeframe.in_seconds(tf_limit)
// DWM - Separators
dwm_sep("D", ds, d_sep_line, d_color)
dwm_sep("W", ws, w_sep_line, w_color)
dwm_sep("M", ms, m_sep_line, m_color)
// DWM - Open Lines
dwm_open("D", show_d_open, d_line, d_label, d_info, d_color)
dwm_open("W", show_w_open, w_line, w_label, w_info, w_color)
dwm_open("M", show_m_open, m_line, m_label, m_info, m_color)
// DWM - Highs and Lows
dwm_hl("D", dhl, d_hl, d_info, d_color)
dwm_hl("W", whl, w_hl, w_info, w_color)
dwm_hl("M", mhl, m_hl, m_info, m_color)
vline(bool use, bool t, line arr, color col) =>
if use
if t and not t
arr.unshift(line.new(bar_index, high*1.0001, bar_index, low, style = vl_style, width = vl_width, extend = extend.both, color = col))
if not v_unlimited
if arr.size() > max_days
arr.pop().delete()
vlines() =>
if timeframe.in_seconds("") <= timeframe.in_seconds(tf_limit)
vline(use_v1, t_v1, v1_line, v1_color)
vline(use_v2, t_v2, v2_line, v2_color)
vline(use_v3, t_v3, v3_line, v3_color)
vline(use_v4, t_v4, v4_line, v4_color)
hz_line(bool use, bool t, hz hz, string txt, color col) =>
if use
if t and not t
hz.LN.unshift(line.new(bar_index, open, bar_index, open, style = hz_style, width = hz_width, color = col))
hz.LB.unshift(label.new(bar_index, open, txt, style = label.style_label_left, color = transparent, textcolor = txt_color, size = lbl_size))
array.unshift(hz.CO, false)
if not open_unlimited and hz.LN.size() > max_days
hz.LN.pop().delete()
hz.LB.pop().delete()
hz.CO.pop()
if not t and hz.CO.size() > 0
if not hz.CO.get(0)
hz.LN.get(0).set_x2(bar_index)
hz.LB.get(0).set_x(bar_index)
if (use_cutoff ? t_co : false)
hz.CO.set(0, true)
hz_lines() =>
if timeframe.in_seconds("") <= timeframe.in_seconds(tf_limit)
hz_line(use_h1, t_h1, hz_1, h1_text, h1_color)
hz_line(use_h2, t_h2, hz_2, h2_text, h2_color)
hz_line(use_h3, t_h3, hz_3, h3_text, h3_color)
hz_line(use_h4, t_h4, hz_4, h4_text, h4_color)
hz_line(use_h5, t_h5, hz_5, h5_text, h5_color)
hz_line(use_h6, t_h6, hz_6, h6_text, h6_color)
hz_line(use_h7, t_h7, hz_7, h7_text, h7_color)
hz_line(use_h8, t_h8, hz_8, h8_text, h8_color)
del_kz(kz k) =>
if k._box.size() > max_days
k._box.pop().delete()
if k._hi_line.size() > max_days
k._hi_line.pop().delete()
k._lo_line.pop().delete()
k._hi_valid.pop()
k._lo_valid.pop()
if show_midpoints
k._md_line.pop().delete()
k._md_valid.pop()
if k._hi_label.size() > max_days
k._hi_label.pop().delete()
k._lo_label.pop().delete()
update_price_string(label L, float P) =>
S = L.get_text()
pre = str.substring(S, 0, str.pos(S, " "))
str.trim(pre)
L.set_text(str.format("{0} ({1})", pre, P))
adjust_in_kz(kz kz, bool t) =>
if t
kz._box.get(0).set_right(time)
kz._box.get(0).set_top(math.max(kz._box.get(0).get_top(), high))
kz._box.get(0).set_bottom(math.min(kz._box.get(0).get_bottom(), low))
kz._range_current := kz._box.get(0).get_top() - kz._box.get(0).get_bottom()
if show_pivots and kz._hi_line.size() > 0
if high > kz._hi_line.get(0).get_y1()
kz._hi_line.get(0).set_xy1(time, high)
kz._hi_line.get(0).set_xy2(time, high)
if low < kz._lo_line.get(0).get_y1()
kz._lo_line.get(0).set_xy1(time, low)
kz._lo_line.get(0).set_xy2(time, low)
if show_midpoints
kz._md_line.get(0).set_xy1(time, math.avg(kz._hi_line.get(0).get_y2(), kz._lo_line.get(0).get_y2()))
kz._md_line.get(0).set_xy2(time, math.avg(kz._hi_line.get(0).get_y2(), kz._lo_line.get(0).get_y2()))
if show_labels and kz._hi_label.size() > 0
if label_right
kz._hi_label.get(0).set_x(time)
kz._lo_label.get(0).set_x(time)
if high > kz._hi_label.get(0).get_y()
kz._hi_label.get(0).set_xy(time, high)
if label_price
update_price_string(kz._hi_label.get(0), high)
if low < kz._lo_label.get(0).get_y()
kz._lo_label.get(0).set_xy(time, low)
if label_price
update_price_string(kz._lo_label.get(0), low)
adjust_out_kz(kz kz, bool t) =>
if not t and kz._box.size() > 0
if t
array.unshift(kz._range_store, kz._range_current)
if kz._range_store.size() > range_avg
kz._range_store.pop()
if kz._box.size() > 0 and show_pivots
for i = 0 to kz._box.size() - 1
if not ext_current or (ext_current and i == 0)
if ext_past ? true : (kz._hi_valid.get(i) == true)
kz._hi_line.get(i).set_x2(time)
if show_labels and label_right
kz._hi_label.get(i).set_x(time)
if high > kz._hi_line.get(i).get_y1() and kz._hi_valid.get(i) == true
if use_alerts and i == 0
alert("Broke "+kz._title+" High", alert.freq_once_per_bar)
kz._hi_valid.set(i, false)
if show_labels and label_right
kz._hi_label.get(0).set_style(label.style_label_down)
else if (use_cutoff ? t_co : false)
kz._hi_valid.set(i, false)
if ext_past ? true : (kz._lo_valid.get(i) == true)
kz._lo_line.get(i).set_x2(time)
if show_labels and label_right
kz._lo_label.get(i).set_x(time)
if low < kz._lo_line.get(i).get_y1() and kz._lo_valid.get(i) == true
if use_alerts and i == 0
alert("Broke "+kz._title+" Low", alert.freq_once_per_bar)
kz._lo_valid.set(i, false)
if show_labels and label_right
kz._lo_label.get(0).set_style(label.style_label_up)
else if (use_cutoff ? t_co : false)
kz._lo_valid.set(i, false)
if show_midpoints
kz._md_line.get(i).set_x2(time)
else
break
manage_kz(kz kz, bool use, bool t, color c, string box_txt, string hi_txt, string lo_txt) =>
if timeframe.in_seconds("") <= timeframe.in_seconds(tf_limit) and use
if t and not t
_c = get_box_color(c)
_t = get_text_color(c)
kz._box.unshift(box.new(time, high, time, low, xloc = xloc.bar_time, border_color = show_kz ? _c : na, bgcolor = show_kz ? _c : na, text = (show_kz and show_kz_text) ? box_txt : na, text_color = _t))
if show_pivots
kz._hi_line.unshift(line.new(time, high, time, high, xloc = xloc.bar_time, style = kzp_style, color = c, width = kzp_width))
kz._lo_line.unshift(line.new(time, low, time, low, xloc = xloc.bar_time, style = kzp_style, color = c, width = kzp_width))
if show_midpoints
kz._md_line.unshift(line.new(time, math.avg(high, low), time, math.avg(high, low), xloc = xloc.bar_time, style = kzm_style, color = c, width = kzm_width))
array.unshift(kz._md_valid, true)
array.unshift(kz._hi_valid, true)
array.unshift(kz._lo_valid, true)
if show_labels
_hi_txt = label_price ? str.format("{0} ({1})", hi_txt, high) : hi_txt
_lo_txt = label_price ? str.format("{0} ({1})", lo_txt, low) : lo_txt
if label_right
kz._hi_label.unshift(label.new(time, high, _hi_txt, xloc = xloc.bar_time, color = transparent, textcolor = txt_color, style = label.style_label_left, size = lbl_size))
kz._lo_label.unshift(label.new(time, low, _lo_txt, xloc = xloc.bar_time, color = transparent, textcolor = txt_color, style = label.style_label_left, size = lbl_size))
else
kz._hi_label.unshift(label.new(time, high, _hi_txt, xloc = xloc.bar_time, color = transparent, textcolor = txt_color, style = label.style_label_down, size = lbl_size))
kz._lo_label.unshift(label.new(time, low, _lo_txt, xloc = xloc.bar_time, color = transparent, textcolor = txt_color, style = label.style_label_up, size = lbl_size))
del_kz(kz)
adjust_in_kz(kz, t)
adjust_out_kz(kz, t)
manage_kz(as_kz, use_asia, t_as, as_color, as_txt, ash_str, asl_str)
manage_kz(lo_kz, use_london, t_lo, lo_color, lo_txt, loh_str, lol_str)
manage_kz(na_kz, use_nyam, t_na, na_color, na_txt, nah_str, nal_str)
manage_kz(nl_kz, use_nylu, t_nl, nl_color, nl_txt, nlh_str, nll_str)
manage_kz(np_kz, use_nypm, t_np, np_color, np_txt, nph_str, npl_str)
dwm()
vlines()
hz_lines()
new_dow_time = dow_xloc == 'Midday' ? time - timeframe.in_seconds("D") / 2 * 1000 : time
new_day = dayofweek(new_dow_time, gmt_tz) != dayofweek(new_dow_time, gmt_tz)
var dow_top = dow_yloc == 'Top'
var saturday = "SATURDAY"
var sunday = "SUNDAY"
var monday = "MONDAY"
var tuesday = "TUESDAY"
var wednesday = "WEDNESDAY"
var thursday = "THURSDAY"
var friday = "FRIDAY"
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 1 and new_day and not dow_hide_wknd, location = dow_top ? location.top : location.bottom, char = "", textcolor = txt_color, text = sunday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 2 and new_day, location = dow_top ? location.top : location.bottom, char = "", textcolor = txt_color, text = monday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 3 and new_day, location = dow_top ? location.top : location.bottom, char = "", textcolor = txt_color, text = tuesday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 4 and new_day, location = dow_top ? location.top : location.bottom, char = "", textcolor = txt_color, text = wednesday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 5 and new_day, location = dow_top ? location.top : location.bottom, char = "", textcolor = txt_color, text = thursday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 6 and new_day, location = dow_top ? location.top : location.bottom, char = "", textcolor = txt_color, text = friday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 7 and new_day and not dow_hide_wknd, location = dow_top ? location.top : location.bottom, char = "", textcolor = txt_color, text = saturday)
get_min_days_stored() =>
store = array.new_int()
if as_kz._range_store.size() > 0
store.push(as_kz._range_store.size())
if lo_kz._range_store.size() > 0
store.push(lo_kz._range_store.size())
if na_kz._range_store.size() > 0
store.push(na_kz._range_store.size())
if nl_kz._range_store.size() > 0
store.push(nl_kz._range_store.size())
if np_kz._range_store.size() > 0
store.push(np_kz._range_store.size())
result = store.min()
set_table(table tbl, kz kz, int row, string txt, bool use, bool t, color col) =>
if use
table.cell(tbl, 0, row, txt, text_size = range_size, bgcolor = get_box_color(col), text_color = txt_color)
table.cell(tbl, 1, row, str.tostring(kz._range_current), text_size = range_size, bgcolor = t ? get_box_color(col) : na, text_color = txt_color)
if show_range_avg
table.cell(tbl, 2, row, str.tostring(kz._range_store.avg()), text_size = range_size, text_color = txt_color)
if show_range and barstate.islast
var tbl = table.new(range_pos, 10, 10, chart.bg_color, chart.fg_color, 2, chart.fg_color, 1)
table.cell(tbl, 0, 0, "Killzone", text_size = range_size, text_color = txt_color)
table.cell(tbl, 1, 0, "Range", text_size = range_size, text_color = txt_color)
if show_range_avg
table.cell(tbl, 2, 0, "Avg ("+str.tostring(get_min_days_stored())+")", text_size = range_size, text_color = txt_color)
set_table(tbl, as_kz, 1, as_txt, use_asia, t_as, as_color)
set_table(tbl, lo_kz, 2, lo_txt, use_london, t_lo, lo_color)
set_table(tbl, na_kz, 3, na_txt, use_nyam, t_na, na_color)
set_table(tbl, nl_kz, 4, nl_txt, use_nylu, t_nl, nl_color)
set_table(tbl, np_kz, 5, np_txt, use_nypm, t_np, np_color)
// ---------------------------------------- Core Logic --------------------------------------------------
//******************************** PULLBACK
lookback = input.int(50, minval=10, step=10, tooltip="How many bars to look back when finding moves", group="Logic")
displayMode = input.string("%", "Move measure", options= , tooltip="How to measures moves & pullbacks. Pips = Forex mode :)", group="Display", display=display.none)
usePercent = displayMode == "%"
usePips = displayMode == "Pips"
usePoints = displayMode == "Points"
showPrices = input.bool(false, "Prices", tooltip="Show start and end price of a move", group="Display")
showPullbacks = input.bool(true, "Pullbacks", tooltip="Show pullback information (if not checked, script just finds mvoes)", group="Display")
// Vertical margin between labels and candles
// Since pips are for forex and forex has lower volatility than crypto, we also adjust vmargin if usePips is true
vmargin = usePips ? 1.0005 : 1.005
// add fields here to stay backwards-compatible
// extended max/min functions
// Extensions of math.min and math.max which, unlike those functions, allow either of the parameters
// to be na (then the other parameter is returned). It's even okay if both parameters are na.
maxAllowingNA(float a, float b) => na(a) ? (na(b) ? na : b) : (na(b) ? a : math.max(a, b))
minAllowingNA(float a, float b) => na(a) ? (na(b) ? na : b) : (na(b) ? a : math.min(a, b))
// math.min and math.max, but with a direction argument (=invertable).
//
// If direction > 0, the functions behave like minAllowingNA and maxAllowingNA.
// If direction < 0, each function becomes its inverse - min becomes max and max becomes min.
// Result is undefined for direction == 0.
directionalMinAllowingNA(float direction, float a, float b) => direction < 0 ? maxAllowingNA(a, b) : minAllowingNA(a, b)
directionalMaxAllowingNA(float direction, float a, float b) => direction < 0 ? minAllowingNA(a, b) : maxAllowingNA(a, b)
// Representation of a single move or pullback
// (i.e. a start point and an end point)
type Move
int startBar // Bar where move starts (bar index)
float startPrice // Price at beginning of move
int endBar // Bar where move ends (bar index, inclusive)
float endPrice // Price at end of move
// Calculate size of move in percent - positive for up moves, negative for down moves
moveSize(Move move) => na(move) ? 0 : (move.endPrice/move.startPrice-1)*100
// Draw move as a dotted or solid line with a specified color. Transparency 30% is added.
// Supplying na is okay. Returns the line drawn.
drawMove(Move move, color color, bool dotted) =>
if not na(move)
style = dotted ? line.style_dotted : line.style_solid
line.new(move.startBar, move.startPrice, move.endBar, move.endPrice, xloc.bar_index, style=style, width=4, color=color.new(color, 30))
// Convert direction (negative or positive float) to color (red/green)
directionToColor(direction) => direction > 0 ? color.green : color.red
// Percentage rendering functions
unit = usePoints ? " points" : usePips ? " pips" : "%" // full unit string
unit1 = usePercent ? "%" : "" // "pips" and "points" sometimes omitted for brevity
// Add unit (% or pips) to a rendered number, with special handling for "1 pip"
addUnit(num) => usePips and num == "1" ? num + " pip" : num + unit
renderPoints(num) => num == "1" ? num + " point" : num + " points"
renderPips(percentage) => str.tostring(math.round(percentage*100))
renderPullback(percentage) => usePips ? renderPips(percentage) : str.tostring(percentage, "0.00")
renderMoveSize(percentage) => usePips ? renderPips(percentage) : str.tostring(percentage, "0.0")
// MoveFinder - the algorithm's main class that detects moves in a certain direction.
// There are 2 main MoveFinders (upFinder and downFinder).
// Each of these contains 2 nested MoveFinders that detect the pullbacks (pbFinder_lb and pbFinder_ub).
// This way, we can use the same core algorithm for the moves and the pullbacks.
// The MoveFinder remembers both
// -biggestMove - the biggest move found in the lookback interval, and
// -the current move (the biggest move out of all moves which end in the current candle), stored in startBar and startPrice.
type MoveFinder
int direction // 1 for detecting up moves, -1 for detecting down moves
bool useUpperBound = false // If true, we report the move size as an upper bound (otherwise a lower bound)
int startBar // First bar of current biggest move
float startPrice // Starting price of current biggest move
Move biggestMove // Current biggest move as an object
Move biggestPB_lb // Current biggest pullback within biggestMove (calculated as lower bound)
Move biggestPB_ub // Current biggest pullback within biggestMove (calculated as upper bound)
MoveFinder pbFinder_lb // A MoveFinder object used to find pullbacks (lower bound), unless we are already in a pullback MoveFinder (then na)
MoveFinder pbFinder_ub // Same for upper bound
// Visualization
label label // Label for current move (so it can be updated)
line line // Red/green move line for current move (so it can be updated)
line pbLine // Dotted pullback line for current move (so it can be updated)
// If this is a main move finder, reset its pullback finders to forget previously found pullbacks
method renewPullbackFinders(MoveFinder this) =>
if not na(this.pbFinder_lb)
this.pbFinder_lb := MoveFinder.new(-this.direction, false)
this.pbFinder_ub := MoveFinder.new(-this.direction, true)
// Called when a new biggest move is found, for one of those reasons:
// -it's the first move found
// -the current move is the biggest move and has changed or grown
// -the current move is bigger than the previously biggest move and it replaces it
method setBiggestMove(MoveFinder this, Move m) =>
// Save in biggestMove
this.biggestMove := m
// If we have pullback finders, grab and store pullbacks found
if not na(this.pbFinder_lb)
this.biggestPB_lb := this.pbFinder_lb.biggestMove
this.biggestPB_ub := this.pbFinder_ub.biggestMove
0 // Just to keep the parser happy (consistent return type)
// Update a MoveFinder with the latest candle (core function). Does not update the nested pullback finders.
method updateCore(MoveFinder this) =>
d = this.direction // We will need the direction a lot, so we call it "d". So d is 1 (finding up moves) or -1 (finding down moves)
// The end of the current candle's wick that is furthest in the move direction
extreme = d > 0 ? high : low
// Find the end of the current candle that is lowest in an up move (or highest in a down mvoe)
otherExtreme = d > 0 ? low : high
// Replace start price of current move with current candle's open if this enlarges the move
start = directionalMinAllowingNA(d, this.startPrice, open)
// true if this candle's wicks change the move's start price
newLow = na(this.startPrice) or d*otherExtreme < d*this.startPrice
// Begin move here if there is no move yet
bar1 = nz(this.startBar, bar_index)
// If we are in "upper bound" mode, we assume that the current candle touched its low first and then its high in an up move,
// or its high first and then its low in a down move. This way, we get the biggest move size compatible with the candle.
// (This distinction is necessary to handle historic candles properly without the help of realtime bars.)
if this.useUpperBound and newLow
start := otherExtreme
bar1 := bar_index
// Calculate new move size including current candle
move = d*(extreme/start-1)*100
// Is it the new biggest move? Then replace biggestMove.
if move > moveSize(this.biggestMove)*d
this.setBiggestMove(Move.new(bar1, start, bar_index, extreme))
// Use current candle as new move start if its wick is further back in the move direction
if newLow
this.startBar := bar_index
this.startPrice := otherExtreme
this.renewPullbackFinders() // We need new pullback finders too when we start a fresh move
// Prepare MoveFinder for a new move (reset all fields)
method flush(MoveFinder this) =>
this.biggestMove := na
this.biggestPB_lb := na
this.biggestPB_ub := na
this.startBar := na
this.startPrice := na
this.pbFinder_lb := MoveFinder.new(-this.direction, false)
this.pbFinder_ub := MoveFinder.new(-this.direction, true)
this.label := na
this.line := na
this.pbLine := na
// Display the current move, replacing its previous visualization if necessary
method showMove(MoveFinder this) =>
move = this.biggestMove
if not na(move) // Check if there is a move to display
// Delete the move's exiting visualization (if any)
label.delete(this.label)
line.delete(this.line)
line.delete(this.pbLine)
// Calculate colors, draw move line
color = directionToColor(this.direction)
pbColor = directionToColor(-this.direction)
this.line := drawMove(move, color, false)
// Show the pullback
pb = this.biggestPB_lb
if not na(pb)
//drawMove(pb, pbColor, true) // Use this to draw the pullback as a slanted line (hard to see though)
// Display pullback as dotted line at a small distance from candle
y = pb.endPrice/math.pow(vmargin, this.direction)
this.pbLine := line.new(pb.startBar, y, pb.endBar, y, width=2, color=color.gray, style=line.style_dotted)
// Render the label text
pb_lb = renderPullback(math.abs(moveSize(this.biggestPB_lb))) // Pullback size lower bound
pb_ub = renderPullback(math.abs(moveSize(this.biggestPB_ub))) // Pullback size upper bound
pbExact = pb_lb == pb_ub // true if lower and upper bound are identical
pbText = pbExact ? pb_lb : pb_lb + unit1 + "-" + pb_ub // Combine lower and upper bound as text
string moveSize = na
if usePoints
moveSize := renderPoints(str.tostring(math.round(math.abs(move.endPrice-move.startPrice)/syminfo.pointvalue)))
else
moveSize := addUnit(renderMoveSize(math.abs(moveSize(move)))) // Move size as text
moveKind = this.direction > 0 ? "upmove" : "downmove"
txt = (this.direction > 0 ? "+" : "-") + moveSize
tooltip = "A " + moveSize + " " + moveKind + " occurred"
if showPrices
sp = str.tostring(move.startPrice)
ep = str.tostring(move.endPrice)
txt := txt + " " + syminfo.currency + " " + sp + " ➡ " + ep
tooltip := tooltip + " from " + syminfo.currency + " " + sp + " to " + ep
if showPullbacks
txt := txt + " (pb " + (usePips ? pbText : addUnit(pbText)) + ")"
tooltip := tooltip + " with a maximum pullback"
+ (pbExact ? " of " + addUnit(pb_lb) + " (marked with gray dots)" : " between " + pb_lb + unit1 + " and " + addUnit(pb_ub) + " (go to lower timeframe for a more precise reading)")
// Create label pointing to end of move
this.label := label.new(move.endBar, move.endPrice*math.pow(vmargin, this.direction), txt, tooltip=tooltip,
style=(this.direction > 0 ? label.style_label_down : label.style_label_up),
color=color, textcolor=color.white)
// Flush (end) the current move when lookback limit is reached.
method enforceLookback(MoveFinder this) =>
if not na(this.biggestMove)
if this.biggestMove.startBar <= bar_index-lookback
this.flush()
// Update a MoveFinder with the latest candle (wrapper function). Also updates the nested pullback finders, if any.
method update(MoveFinder this) =>
// Update the pullback finders
if not na(this.pbFinder_lb) // If we have one, we also have the other
this.pbFinder_lb.updateCore()
this.pbFinder_ub.updateCore()
// Update the move finder itself
this.updateCore()
// Update visualization
this.showMove()
// End move if lookback limit reached
this.enforceLookback()
// The main MoveFinders, one for each direction.
// Note how the 2 embedded MoveFinders have opposite direction so they can find pullbacks.
var MoveFinder upFinder = MoveFinder.new(1, pbFinder_lb=MoveFinder.new(-1), pbFinder_ub=MoveFinder.new(-1))
var MoveFinder downFinder = MoveFinder.new(-1, pbFinder_lb=MoveFinder.new(1), pbFinder_ub=MoveFinder.new(1))
// Update the move finders (and nested pullback finders)
upFinder.update()
downFinder.update()
//**************************** GRIDBOT
//BEGIN SCRIPT
//Begin Settings Box============================================================================================================//
//easy_settings = input.bool(true, title='Show Easy Access Settngs Tool on Chart?', group = 'Settings Tool') //
//settings_location_bottom_right = input.bool( //
// defval = false, //
// title = 'Move Settings Tool to Bottom Right?', //
// group = 'Settings Tool') //
// ? position.bottom_right : position.middle_right //
//if easy_settings == true //
// var table settings_tool = table.new(settings_location_bottom_right, 1, 1, frame_color = color.black, frame_width = 0) //
// table.cell(settings_tool, 0, 0, text_size = size.small, //
// text = "⚙️", //
// tooltip='Double Click to Access Settings', //
//Questions regarding this indicator or need training? discord.com //
// text_color = color.black, bgcolor = color.new(color.orange, 100)) //
//End Settings Box==============================================================================================================//
show_historical = input.bool(defval = false, title = "Show Historical Lines on Chart?") //
show_as = input.bool(defval = false, title = "Show Historical Lines as DOTS not lines?") ? plot.style_cross : plot.style_linebr //
//HANDLES MAX_LINES_COUNTS ISSUE================================================================================================//
//lineLimitInput = input.int( //
// defval = 30, //
// title = 'Max Lines to Show', //
// tooltip = 'Adjust this number to increase or decrease the total number of lines seen on the chart. (ONLY this indicator)', //
// group = 'Line Settings' //
// ) //
//if array.size(line.all) > lineLimitInput //
// for i = 0 to array.size(line.all) - lineLimitInput - 1 //
// line.delete(array.get(line.all, i)) //
//END MAX_LINES_COUNTS ISSUE====================================================================================================//
//BEGIN Get User Inputs=========================================================================================================//
//BEGIN LINE SETTINGS //
extend_lines = input.bool( //
defval = false, //
title = 'Extend Lines on th chart?', //
tooltip = 'Checking this box will extend the current lines on the chart both directions', //
group = 'Line Settings' //
) ? extend.both : extend.none //
use_low_bullish = input.bool( //
defval = true, //
title = 'Use Low for Bullish Reversal Support Line?', //
tooltip = 'The default for the support line is the close of the candle, this setting changes it to the candle Low (wick)', //
group = 'Line Settings' //
) ? low : close //
use_high_bearish = input.bool( //
defval = true, //
title = 'Use High for Bearish Reversal Resistance Line?', //
tooltip = 'The default for the resistance line is the close of the candle, this setting changes it to the candle High (wick)', //
group = 'Line Settings' //
) ? high : close //
//END LINE SETTINGS //
//showlabel = input.bool(true, title='Show Alerts Box', group = 'Price label') //
showpricelabel = input.bool(true, title='Show Price Label', group = 'Price Label') //
only_bearish = input.bool( //
defval = false, //
title = ' Show only Bearish Labels on Chart', //
tooltip = 'checking this box will hide Bullish Reversal and only show Bearish Reversals', //
group = 'Signal Label Settings' //
) //
only_bullish = input.bool( //
defval = false, //
title = ' Show only Bullish Labels on Chart', //
tooltip = 'checking this box will hide Bearish Reversal and only show Bullish Reversals', //
group = 'Signal Label Settings' //
) //
//END Get User Inputs===========================================================================================================//
//==============================================================================================================================//
// PRICE LINE CODE //
//==============================================================================================================================//
//Begin Price Line //
bullish_direction = close >= open //Price is currently HIGHER than the opening price //
bearish_direction = close <= open //Price is currently LOWER than the opening price //
green_bar = open < close // Candle is a GREEN Candle //
red_bar = open > close // Candle is a RED Candle //
strong_bullish_direction = bullish_direction and green_bar // for bullish price color (Green Bar and Price is Higher than open) //
strong_bearish_direction = bearish_direction and red_bar // for bearish price color (Red Bar and Price is Lower than open) //
nuetral_bar = not strong_bearish_direction and not strong_bullish_direction // for neutral price color - This happens when the //
//price is NOT strong Bullish and NOT strong bearish meaning that the direction may be bullish, but the candle is red or that //
//the direction is bearish, but the candle is green. In other words, it is neither Strong Bearish or Strong Bullish. //
var line line_price = na //Initiate an empty line variable //
var label label_price1 = na //Intitiate an empty label variable // //
line_forward = input.int(8, title = 'PRICE Line Positive offset Length', //
group = 'Price Label') // distance FORWARD from bar_index / current bar //
line_back = input.int(-200, title = ' PRICE Line Negative offset length', //
group = 'Price Label') // distance BACKWARDS from the bar_index / current bar //
label_offset = input.int(8, title = "PRICE Offset", //
group = 'Price Label') // distance FORWARD from bar_index / current bar //
is_bar_index = bar_index //
if is_bar_index and showpricelabel //User wants to see the price line? //
line.delete(line_price ) //
label.delete(label_price1 ) //
price=close // current price of asset in realtime //
line_price:=line.new( //
bar_index +line_forward, //
close, //
bar_index +line_back, //
close, //
color //
= strong_bullish_direction ? color.new(color.lime, 0) //
: strong_bearish_direction ? color.new(color.red, 0) //
: nuetral_bar ? color.new(color.orange, 0) //
: na, //
width=2, //
style=line.style_dotted //
) //
label_price1:=label.new( //
bar_index +label_offset, //
close, //
text="$" + str.tostring(price), //
color=na, //
textcolor //
= strong_bullish_direction ? color.new(color.lime, 0) //
: strong_bearish_direction ? color.new(color.red, 0) //
: nuetral_bar ? color.new(color.orange, 0) //
: na, //
size=size.large //
) //
//==============================================================================================================================//
//BEGIN OPTIONAL PRICE LABEL SCRIPT=============================================================================================//
//var priceArray = array.new_float(0) //
//array.push(priceArray, close) //
//size = array.size(priceArray) //
//price = array.get(priceArray, size -1) //
////BEGIN USER INPUT FOR OPTIONAL PRICE LABEL //
//show_price_label = input.bool( //
// defval = true, //
// title = ' Show Price Label on Chart', //
// tooltip = 'Unchecking this box will hide the optional price label from the chart', //
// group = "Price Label Settings" //
// ) //
////END USER INPUT FOR OPTIONAL PRICE LABEL //
////BEGIN LABEL script for OPTIONAL PRICE LABEL //
//label pricelabel = na //
//if barstate.islast and show_price_label //
// pricelabel := label.new(bar_index, //
// y=0, //
// yloc=yloc.abovebar, //
// color = color.new(color.yellow, 0), //
// style = label.style_none, //
// text="Price: " + str.tostring(array.get(priceArray, size -1)), //
// textcolor = color.new(color.orange, 0)) //
// label.delete(pricelabel ) //
//END LABEL script for OPTIONAL PRICE LABEL //
//END OPTIONAL PRICE LABEL SCRIPT===============================================================================================//
//BEGIN Definitions=============================================================================================================//
price = close //
bullish_break = //
price > high //
and price > high //
and price > high //
and price > high //
and price > high //
a
Vertical Line at Specific TimeDraws a vertical line at a specific time.
Vertical lines at specific times of the day may help make it easier to identify parts of a session.
If you know you perform better during certain parts of the day utilize these lines to help stay aware of your trading session.
The hours seem a bit buggy but just adjust the time to make the lines what you want to see on the chart. The time can be adjusted in settings to get what you want it to do.
𝗫~𝗩𝗜𝗣 x 𝗔𝗜 🤖~1.0Our revolutionary trading indicator is the result of meticulously combining around 20 advanced technical indicators, 5 time-tested strategies, and over 130 crucial technical analysis factors. Beyond this robust foundation, we’ve infused it with cutting-edge artificial intelligence, ensuring real-time adaptability to dynamic market conditions. This powerhouse tool also integrates sophisticated market sentiment analysis, historical data pattern recognition, and volatility-based predictive algorithms. Designed for both novice and seasoned traders, our indicator continuously scans for optimal trading opportunities, generating high-probability buy and sell signals. With seamless integration of order flow analytics and liquidity mapping, it offers deeper market insights, helping traders make smarter decisions. The result? A tool that achieves an impressive accuracy of around 90%, consistently outperforming typical market expectations. Whether you’re aiming for precise scalping or long-term swings, our indicator empowers you to trade with confidence and a clear edge over the market.
AP_Trend_2.0AP_Trend 2.0 — Smart Trade Signal System
AP_Trend 2.0 is a proprietary multi-market signal system that provides **Buy/Sell entries**, with automatic **Take Profit (TP)**, **Stop Loss (SL)**, and **Trailing Stop (TS)** levels. It’s designed to help traders identify high-probability trend reversals and trend-following opportunities.
🔍 How It Works:
- Entry signals are based on a proprietary blend of trend filters, momentum shifts, and volatility compression patterns.
- Once a signal is triggered, the indicator plots SL based on recent swing lows/highs minus a buffer, TP based on dynamic risk-reward ratio, and TS that adjusts with price movement.
✨ Key Features:
- Buy / Sell signals
- Auto-TP / SL / TS level visualization
- Works on stocks, crypto, forex, futures
- Supports both intraday and swing trading
- Alert-ready for automation
This indicator is ideal for traders who want clear signals and structured trade management. Visual aids simplify decision-making, while adaptive logic tailors outputs to changing market conditions.
Note: Trailing Stop (TS) = auto-adjusted stop loss to protect profits.
ICT Plus © Trading Whale by SebasV🧠 ICT Plus © Trading Whale by SebasV
A comprehensive smart money concept (SMC) toolkit designed for traders looking to operate with institutional logic, precision, and structure.
🔍 What does this indicator do?
ICT Plus brings together the most powerful elements of price action and smart money strategies, combining them into a single, optimized indicator:
✅ Core Features:
Institutional Sweeps: Detects liquidity grabs with clean labeling and cooldown filters
Swing Highs & Lows: Visual structure mapping for trend analysis
Previous Day High & Low Levels: Automatically plots HOD/LOD with session separators
Market Structure: Identifies CHoCH & BOS based on customizable swing detection
Order Blocks & Breaker Blocks: With optional body-based validation and polarity tracking
Fair Value Gaps (FVG): Includes unmitigated level tracking and mitigation alerts
Scalping Signals: Fast-entry conditions using EMA, RSI, ADX, and confirmation with SuperTrend
Sweep Midpoint London Signal: Exclusive post-London logic with 200 EMA filter
Delta Volume Divergence: Spot hidden buying/selling pressure using cumulative delta and RSI
SuperTrend BIAS Summary Table: Quickly visualize multi-timeframe market bias
Fibonacci Golden Zone Tool: Projects swing-based 0.618 retracement zones with optional risk box
Full Alert System: Configurable alerts for all major signals and setups
📌 Recommendation:
Built for traders who follow ICT concepts, liquidity sweeps, and smart money frameworks, this tool is especially effective for those who combine structure, confluences, and volume-based divergence.
Timeframes from 1-minute to daily are supported. Best used in active sessions like London and New York
GStrategy1️⃣ Long entry based on RSI divergences.
2️⃣ Exit based on RSI filter (RSI> 40 after at least N bars).
3️⃣ Exit if the price has fallen more than 10% from the entry point.
4️⃣ Visualization of % difference for monitoring.
5️⃣ Flexibility: all parameters are configurable in the arguments window.
NOCTURNA v2.0 – Full Shadow EngineNOCTURNA v2.0 – Full Shadow Engine
✅ Auto & Manual Modes
✅ Grid (EVE), Trend (SENTINEL), Breakout (LUCIFER), Reversal (REAPER)
✅ SL, TP, Trailing Stop
✅ Dashboard + JSON Alerts
✅ 100% fixed & deployable
NOCTURNA v2.0 – Shadow Engine: Trail EditionNOCTURNA is the final evolution of LUCY.
She adapts to market conditions like shadow to light:
Mode Active When... Style
Lucifer Price is breaking trend boundaries Breakout sniper
Reaper Volatility spikes + candle exhaustion Reversal scalper
Sentinel Swing structure confirmed (EMA + MACD) Macro trend
EVE Flat EMAs + ATR squeeze = range mode DCA harvester
Mera Mera - Ying Yang & Inside, OutsideMera Mera
It is a structure that traps the previous candle formed in the same direction.
When the structure is Buy oriented, a blue dot is formed below it, when it is Sell oriented, a red dot is formed above it.
Sell Mera Mera, Buy Mera Mera alarm is available.
Ying Yang
It is a structure that traps the next candle formed in the same process.
When the structure is in Buy transactions, a blue triangle is formed under it, when it is in Sell transactions, a red triangle is formed under it.
Ying Yang Sell, Ying Yang Buy alert is available.
The calculation of inner bar and outer bar values is different.
After this formation, a transaction is sought by following the candle fractal formations.
Necessary visuals are below.
NOCTURNA v2.0 – Shadow Engine: Trail EditionModule Function
Lucifer Breakout sniper (trend trigger)
Reaper Reversal scalper (EMA 8/34 cross)
Sentinel Swing filter (EMA/MACD alignment)
EVE Grid trader (range + DCA logic)
Failsafe Auto-block high-volatility entries
TrailLogic Auto SL lock-in after % gain
HUD Visual mode/status panel
ElfieDT - TrapsThis indicator identifies potential traps signals.
We trust you can use this to your advantage.
Works on any timeframe and all trade able pairs.
SMA + S/R + Trendkanal + Alarme (15/30 Min Settings)This TradingView script combines several useful tools for intraday trading on 15- and 30-minute charts:
SMA Crossovers: Two Simple Moving Averages (short and long) are calculated and plotted. Buy and sell signals are detected when the short SMA crosses the long SMA upward or downward. These signals are shown as labels on the chart.
Automatic Support and Resistance Lines: Swing highs and lows are detected to identify key support and resistance levels. These are drawn as horizontal lines and can be limited in number.
Trend Channel: A dynamic trend channel is drawn based on linear regression of the highs and lows of the last n bars. The channel’s width can be adjusted.
Alerts: The script triggers alerts on SMA crossovers, breaks of support or resistance lines, and when the price leaves the trend channel.
Adjustable Parameters: The key parameters such as SMA lengths, lookback periods for support/resistance and trend channel, and channel width are configurable via the input menu. There is also a preset selection for 15- or 30-minute timeframes.
This script simplifies the analysis of trend changes, key price levels, and overall market structure for medium-term intraday trading.
Dieses TradingView-Skript kombiniert mehrere nützliche Werkzeuge für den Intraday-Handel auf 15- und 30-Minuten-Charts:
SMA-Kreuzungen: Zwei gleitende Durchschnitte (SMA kurz und SMA lang) werden berechnet und auf dem Chart angezeigt. Buy- und Sell-Signale werden erkannt, wenn der kurze SMA den langen SMA von unten nach oben bzw. von oben nach unten kreuzt. Diese Signale werden als Labels auf dem Chart angezeigt.
Automatische Support- und Resistance-Linien: Swing Highs und Lows werden erkannt, um wichtige Unterstützungs- und Widerstandsniveaus zu bestimmen. Diese werden als horizontale Linien eingezeichnet und können in der Anzahl begrenzt werden.
Trendkanal: Ein dynamischer Trendkanal wird basierend auf linearer Regression der Hoch- und Tiefpunkte der letzten n Kerzen gezeichnet. Der Abstand des Kanals kann angepasst werden.
Alarme: Das Skript generiert Alarme bei SMA-Kreuzungen, beim Durchbrechen von Support- oder Resistance-Linien sowie beim Verlassen des Trendkanals.
Einstellbare Parameter: Die wichtigsten Parameter wie SMA-Längen, Lookback-Längen für Support/Resistance und Trendkanal sowie die Kanalbreite sind über das Input-Menü flexibel anpassbar. Außerdem gibt es eine Auswahlmöglichkeit für voreingestellte Parameter für 15- oder 30-Minuten-Zeiteinheiten.
AI Trend Strategy (Fast/Slow Line with Alternate Signals)just trial. iam usin a ema strategy a very basic one. just buy when buy signal appears and sell when it says sell
Canuck Trading Projection IndicatorCanuck Trading Projection Indicator
Overview
The Canuck Trading Projection Indicator is a powerful PineScript v6 tool designed for TradingView to project potential bullish and bearish price trajectories based on historical price and volume movements. It provides traders with actionable insights by estimating future price targets and assigning confidence levels to each outlook, helping to identify probable market directions across any timeframe. Ideal for both short-term and long-term traders, this indicator combines momentum analysis, RSI filtering, support/resistance detection, and time-weighted trend analysis to deliver robust projections.
Features
Bullish and Bearish Projections: Forecasts price targets for upward (bullish) and downward (bearish) movements over a user-defined projection period (default 20 bars).
Confidence Levels: Assigns percentage confidence scores to each outlook, reflecting the likelihood of the projected price based on historical trends, volatility, and volume.
RSI Filter: Incorporates a 14-period Relative Strength Index (RSI) to validate trends, requiring RSI > 50 for bullish and RSI < 50 for bearish signals.
Support/Resistance Detection: Adjusts confidence levels when projections are near key swing highs/lows (within 2% of average price), boosting confidence by 5% for alignments.
Time-Based Weighting: Prioritizes recent price movements in trend analysis, giving more weight to newer bars for improved relevance.
Customizable Inputs: Allows users to tailor lookback period, projection bars, RSI period, confidence threshold, colors, and label positioning.
Forced Label Spacing: Prevents overlap of bullish and bearish text labels, even for tight projections, using fixed vertical slots when price differences are small (<2% of average price).
Timeframe Flexibility: Works seamlessly across all TradingView timeframes (e.g., 30-minute, hourly, daily, weekly, monthly), adapting projections to the chart’s resolution.
Clean Visualization: Displays projections as green (bullish) and red (bearish) dashed lines, with non-overlapping text labels at the projection endpoints showing price targets and confidence levels.
How It Works
The indicator analyzes historical price and volume data over a user-defined lookback period (default 50 bars) to calculate:
Momentum: Combines price changes and volume to assess trend strength, using a weighted moving average (WMA) for directional bias.
Trend Analysis: Counts bullish (price up, volume above average, RSI > 50) and bearish (price down, volume above average, RSI < 50) trends, weighting recent bars more heavily.
Projections:
Bullish Slope: Positive or flat when momentum is upward, scaled by price change and momentum intensity.
Bearish Slope: Negative or flat when momentum is downward, amplified by bearish confidence for stronger projections.
Projects prices forward by 20 bars (default) using current close plus slope times projection bars.
Confidence Levels:
Base confidence derived from the proportion of bullish/bearish trends, with a 5% minimum to avoid zero confidence.
Adjusted by volatility (lower volatility increases confidence), volume trends, and proximity to support/resistance levels.
Visualization:
Draws projection lines from the current close to the 20-bar future target.
Places text labels at line endpoints, showing price targets and confidence percentages, with forced spacing for readability.
Input Parameters
Lookback Period (default: 50): Number of bars for historical analysis (minimum 10).
Projection Bars (default: 20): Number of bars to project forward (minimum 5).
Confidence Threshold (default: 0.6): Minimum confidence for strong trend indication (0.1 to 1.0).
Bullish Projection Line Color (default: Green): Color for bullish projection line and label.
Bearish Projection Line Color (default: Red): Color for bearish projection line and label.
RSI Period (default: 14): Period for RSI momentum filter (minimum 5).
Label Vertical Offset (%) (default: 1.0): Base offset for labels as a percentage of price range (0.1% to 5.0%).
Minimum Label Spacing (%) (default: 2.0): Minimum vertical spacing between labels for tight projections (0.5% to 10.0%).
Usage Instructions
Add to Chart: Copy the script into TradingView’s Pine Editor, save, and add the indicator to your chart.
Select Timeframe: Apply to any timeframe (e.g., 30-minute, hourly, daily, weekly, monthly) to match your trading strategy.
Interpret Outputs:
Green Line/Label: Bullish price target and confidence (e.g., "Bullish: 414.37, Confidence: 35%").
Red Line/Label: Bearish price target and confidence (e.g., "Bearish: 279.08, Confidence: 41.3%").
Higher confidence indicates a stronger likelihood of the projected outcome.
Adjust Inputs:
Modify Lookback Period to focus on shorter/longer historical trends (e.g., 20 for short-term, 100 for long-term).
Change Projection Bars to adjust forecast horizon (e.g., 10 for shorter, 50 for longer).
Tweak RSI Period or Confidence Threshold for sensitivity to momentum or trend strength.
Customize Colors for visual preference.
Increase Minimum Label Spacing if labels overlap in volatile markets.
Combine with Analysis: Use alongside other indicators (e.g., moving averages, Bollinger Bands) or fundamental analysis to confirm signals, as projections are probabilistic.
Example: TSLA Across Timeframes
Using live TSLA data (close ~346.46 USD, May 31, 2025), the indicator produces:
30-Minute: Bullish 341.93 (13.3%), Bearish 327.96 (86.7%) – Strong bearish sentiment due to intraday volatility.
1-Hour: Bullish 342.00 (33.9%), Bearish 327.50 (62.3%) – Bearish but less intense, reflecting hourly swings.
4-Hour: Bullish 345.52 (73.4%), Bearish 344.44 (19.0%) – Flat outlook, indicating consolidation.
Daily: Bullish 391.26 (68.8%), Bearish 302.22 (31.2%) – Bullish bias from recent uptrend, bearish tempered by longer lookback.
Weekly: Bullish 414.37 (35.0%), Bearish 279.08 (41.3%) – Wide range, reflecting annual volatility.
Monthly: Bullish 396.70 (54.9%), Bearish 296.93 (10.2%) – Long-term bullish optimism.
These results align with market dynamics: short-term intervals capture volatility, while longer intervals smooth trends, providing balanced outlooks.
Notes
Accuracy: Projections are estimates based on historical data and should be used with other analysis tools. Confidence levels indicate likelihood, not certainty.
Timeframe Sensitivity: Short-term intervals (e.g., 30-minute) show larger price swings and higher confidence due to volatility, while longer intervals (e.g., monthly) are more stable.
Customization: Adjust inputs to match your trading style (e.g., shorter lookback for day trading, longer for swing trading).
Performance: Tested on volatile stocks like TSLA, NVIDIA, and others, ensuring robust performance across markets.
Limitations: May produce conservative bearish projections in strong uptrends due to momentum weighting. Adjust lookback or projection_bars for sensitivity.
Feedback
If you encounter issues (e.g., label overlap, projection mismatches), please share your timeframe, settings, or a screenshot. Suggestions for enhancements (e.g., additional filters, visual tweaks) are welcome!
Disclaimer
The Canuck Trading Projection Indicator is provided for educational and informational purposes only. It is not financial advice. Trading involves significant risks, and past performance is not indicative of future results. Always perform your own due diligence and consult a qualified financial advisor before making trading decisions.