0% found this document useful (0 votes)
21 views13 pages

Ver 5

The document outlines a Pine Script for a LOWESS Oscillator Indicator designed for use in trading analysis. It includes inputs for date range, LOWESS parameters, oscillator settings, and conditions for long and short entries and exits. Additionally, it features alert conditions for overbought/oversold levels and volume spikes, along with pivot point calculations.

Uploaded by

Đức Anh Lê
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
21 views13 pages

Ver 5

The document outlines a Pine Script for a LOWESS Oscillator Indicator designed for use in trading analysis. It includes inputs for date range, LOWESS parameters, oscillator settings, and conditions for long and short entries and exits. Additionally, it features alert conditions for overbought/oversold levels and volume spikes, along with pivot point calculations.

Uploaded by

Đức Anh Lê
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 13

//@version=5

indicator("LOWESS Oscillator Indicator", overlay=true, shorttitle="L.O.S


Indicator")

//
-----------------------------------------------------------------------------------
----------------------------------
// Inputs for Date Range
//
-----------------------------------------------------------------------------------
----------------------------------
start_date = input.time(timestamp("2024-10-10 00:00 +0000"), "Start Date",
group="Date Range")
end_date = input.time(timestamp("2069-01-01 00:00 +0000"), "End Date", group="Date
Range")

// Ensure that the indicator only runs within the specified date range
in_date_range = (time >= start_date and time <= end_date)

//
-----------------------------------------------------------------------------------
----------------------------------
// Inputs
//
-----------------------------------------------------------------------------------
----------------------------------
// LOWESS Inputs
length_lowess = input.int(30, minval=1, title="LOWESS Length", group="LOWESS")
color_up = input.color(#60befd, "Upward Movement Color", group="LOWESS Colors")
color_down = input.color(#ab61ff, "Downward Movement Color", group="LOWESS Colors")

// Oscillator Inputs
sourceType = input.string('rsi', 'Oscillator Source', ['rsi', 'cci', 'cmo', 'cog',
'mfi', 'roc', 'price'], group='Oscillator')
osc_length = input.int(14, 'Oscillator Length', minval=5, group='Oscillator')
bandType = input.string('bb', 'OB/OS Method', ['bb', 'kc', 'dc1', 'dc2'],
group='Bands')
bandLength = input.int(20, 'Band Length', minval=5, group='Bands')
multiplier = input.float(2, 'Band Multiplier', minval=0.5, group='Bands')

//
-----------------------------------------------------------------------------------
----------------------------------
// LOWESS Calculation
//
-----------------------------------------------------------------------------------
----------------------------------
lowess(src, length) =>
sum_w = 0.0
sum_wx = 0.0
sum_wy = 0.0
for i = 0 to length - 1
w = math.pow(1 - math.pow(i / length, 3), 3)
sum_w += w
sum_wx += w * i
sum_wy += w * src[i]
a = sum_wy / sum_w
b = sum_wx / sum_w
a + b / (length - 1) / 2000
smoothed_lowess = lowess(close, length_lowess)
lowess_up = smoothed_lowess > smoothed_lowess[2]
lowess_down = smoothed_lowess < smoothed_lowess[2]
smoothedColor = lowess_up ? color_up : color_down

plot(smoothed_lowess, "LOWESS", smoothedColor)

//
-----------------------------------------------------------------------------------
----------------------------------
// Oscillator Calculation
//
-----------------------------------------------------------------------------------
----------------------------------
oscillator(simple string oscillatorType="rsi", float source, int length=14) =>
switch oscillatorType
"cci" => ta.cci(source, length)
"cmo" => ta.cmo(source, length)
"cog" => ta.cog(source, length)
"mfi" => ta.mfi(source, length)
"roc" => ta.roc(source, length)
"rsi" => ta.rsi(source, length)
=> ta.rsi(source, length)

osc = sourceType == 'price' ? close : oscillator(sourceType, close, osc_length)

//
-----------------------------------------------------------------------------------
----------------------------------
// Keltner Channel (kc) Function
//
-----------------------------------------------------------------------------------
----------------------------------
kc(source, highSource, lowSource, length, multiplier) =>
tr = math.max(source, highSource, lowSource) - math.min(source, highSource,
lowSource)
atr = ta.sma(tr, length)
mid = ta.sma(source, length)
[mid, mid + atr * multiplier, mid - atr * multiplier]

//
-----------------------------------------------------------------------------------
----------------------------------
// Donchian Channel (dc) Function
//
-----------------------------------------------------------------------------------
----------------------------------
dc(source, highSource, lowSource, length) =>
[ta.highest(highSource, length), ta.lowest(osc, length)]

//
-----------------------------------------------------------------------------------
----------------------------------
// Determine Overbought & Oversold Levels
//
-----------------------------------------------------------------------------------
----------------------------------
[middle, overbought, oversold] = switch bandType
'bb' => ta.bb(osc, bandLength, multiplier)
'kc' => kc(osc, high, low, bandLength, multiplier)
'dc1' =>
high_dc = ta.highest(osc, bandLength)
low_dc = ta.lowest(osc, bandLength)
[na, high_dc, low_dc]
'dc2' =>
high_dc2 = ta.highest(osc, bandLength)
low_dc2 = ta.lowest(osc, bandLength)
[na, high_dc2, low_dc2]
=> [na, na, na] // Default case

//
-----------------------------------------------------------------------------------
----------------------------------
// Over and Under Labels (Alertable Text)
//
-----------------------------------------------------------------------------------
----------------------------------
over_condition = osc > 81
under_condition = osc < 19

plotshape(series=over_condition, location=location.abovebar, color=color.purple,


style=shape.labeldown, title="Over", text=">", textcolor=color.yellow,
size=size.small)
plotshape(series=under_condition, location=location.belowbar, color=color.yellow,
style=shape.labelup, title="Under", text="<", textcolor=color.purple,
size=size.small)

//
-----------------------------------------------------------------------------------
----------------------------------
// Long Entry Condition
//
-----------------------------------------------------------------------------------
----------------------------------
long_condition = close < smoothed_lowess and osc <= oversold and osc < 22

//
-----------------------------------------------------------------------------------
----------------------------------
// Short Entry Condition
//
-----------------------------------------------------------------------------------
----------------------------------
short_condition = close > smoothed_lowess and ta.crossover(osc, overbought) and osc
> 79

//
-----------------------------------------------------------------------------------
----------------------------------
// Long Exit Condition
//
-----------------------------------------------------------------------------------
----------------------------------
exit_long_condition = osc >= overbought and osc > 80

//
-----------------------------------------------------------------------------------
----------------------------------
// Short Exit Condition
//
-----------------------------------------------------------------------------------
----------------------------------
exit_short_condition = osc <= oversold and osc < 39

//
-----------------------------------------------------------------------------------
----------------------------------
// Plot Entry/Exit Signals with Text (Buy/Sell instead of shapes)
//
-----------------------------------------------------------------------------------
----------------------------------
plotchar(series=long_condition, location=location.belowbar, color=color.green,
size=size.tiny, offset=-1)
plotchar(series=short_condition, location=location.abovebar, color=color.red,
size=size.tiny, offset=1)

//
-----------------------------------------------------------------------------------
----------------------------------
// Consolidated Alert Condition for Over and Under
//
-----------------------------------------------------------------------------------
----------------------------------
mixed_over_under_alert = over_condition or under_condition
alertcondition(mixed_over_under_alert, title="Mixed Over/Under Alert",
message="{{ticker}} Over/Under!")

//
-----------------------------------------------------------------------------------
----------------------------------
// Other Alert Conditions
//
-----------------------------------------------------------------------------------
----------------------------------
alertcondition(close < osc, title="Trend Change", message="{{ticker}} below
Oscillator Trend.")
alertcondition(long_condition, title="Long Entry", message="{{ticker}}: Long
entry.")
alertcondition(short_condition, title="Short Entry", message="{{ticker}}: Short
entry.")
alertcondition(exit_long_condition, title="Exit Long", message="{{ticker}}: Exit
Long.")
alertcondition(exit_short_condition, title="Exit Short", message="{{ticker}}: Exit
Short.")
// Volume Spike Detection
highVolumeDistanceThreshold = input.int(90, "High Volume Distance Threshold (%)",
5, 100, 5)
volumeSpikeThreshold = input.int(85, "Volume Spike Threshold (%)", 5, 100, 5)

// Price range calculations


price_range = high - low
max_price_range = ta.highest(high - low, 50)
scaled_volume = volume * (price_range / max_price_range)

// Helper Function: Find Distance Percentile


lastHighDistance(float source) =>
var sourceArray = array.new<float>()
array.push(sourceArray, source)
var lastHighIndex = 0
currentLastHighIndex = source < nz(source[1]) ? array.size(sourceArray) - 2 :
lastHighIndex
while (source > array.get(sourceArray, currentLastHighIndex) and
currentLastHighIndex > 0)
currentLastHighIndex -= 1
lastHighIndex := currentLastHighIndex == 0 ? array.size(sourceArray) - 1 :
currentLastHighIndex
lastHighDistance = array.size(sourceArray) - lastHighIndex - 1
lastHighDistance

// Detect volume spike


volumeLastHighDistance = lastHighDistance(volume)
highlight = volumeLastHighDistance >= highVolumeDistanceThreshold

// Store indices for proper candle tracking


var int spikeIndex = na
var int afterSpikeIndex = na
var int priorCandleIndex = na
var float lowest_zone_price = na
var int lowest_zone_index = na
var box spikeBox = na // Box variable for extending highlight

// If a spike occurs, store the indices for highlight


if highlight
spikeIndex := bar_index
priorCandleIndex := bar_index - 1
afterSpikeIndex := bar_index + 1
lowest_zone_price := close[1]
lowest_zone_index := bar_index - 1

// Create a semi-transparent rectangle covering the high-low range


spikeBox := box.new(left=bar_index, right=bar_index + 20, top=high, bottom=low,
border_color=color.new(#EE82EE, 80), bgcolor=color.new(#EE82EE, 88))

// Extend the box dynamically as new bars appear


if not na(spikeBox) and bar_index > spikeIndex
box.set_right(spikeBox, bar_index + 60)

// 🔥 Highlight Current (Spike) & Post-Spike Candle


sBlockCandle = bar_index == spikeIndex
afterSpikeCandle = bar_index == afterSpikeIndex

// Assign colors to highlight the correct candles


lavenderColor = color.new(#FFA500, 0) // Bright Lavender (0 = fully visible)
barColor = sBlockCandle ? lavenderColor : afterSpikeCandle ? color.rgb(255, 171,
255) : na
barcolor(barColor)

// 🔥 Fix: Ensure the Prior (-1) Candle is Highlighted


priorCandle = bar_index == priorCandleIndex

// 🚀 ALERT CONDITION for Spike Event


alertcondition(highlight, title="Spike Alert", message="{{ticker}}: Volume Spike!")

PP = input.int(2 , 'Pivot Period' , minval = 2)


Open = open
High = high
Low = low
Close = close
Bar_Index = bar_index

var ArrayType = array.new_string()


var ArrayValue = array.new_float()
var ArrayIndex = array.new_int()
var Line = array.new_line()

HighPivot = ta.pivothigh(PP,PP)
LowPivot = ta.pivotlow(PP,PP)

HighValue = ta.valuewhen(HighPivot ,high[PP], 0)


LowValue = ta.valuewhen(LowPivot ,low[PP], 0)

HighIndex = ta.valuewhen(HighPivot ,bar_index[PP], 0)


LowIndex = ta.valuewhen(LowPivot ,bar_index[PP], 0)

Correct_HighPivot = 0.0
Correct_LowPivot = 0.0

PASS = 0

if HighPivot and LowPivot


if ArrayType.size() == 0
PASS := 1
else if ArrayType.size() >= 1
if ((ArrayType.get(ArrayType.size() - 1)) == "L" or
(ArrayType.get(ArrayType.size() - 1)) == "LL")
if LowPivot < ArrayValue.get(ArrayType.size() - 1)
array.remove(ArrayType,ArrayType.size() - 1)
array.remove(ArrayValue,ArrayValue.size() - 1)
array.remove(ArrayIndex,ArrayIndex.size() - 1)
array.push(ArrayType,ArrayType.size()>2?
ArrayValue.get(ArrayType.size() - 2) < LowValue ? "HL" : "LL" :
"L")///////////////////////////////Here
array.push(ArrayValue, LowValue)
array.push(ArrayIndex, LowIndex)
Correct_LowPivot := LowValue
else
array.push(ArrayType,ArrayType.size()>2?
ArrayValue.get(ArrayType.size() - 2) < HighValue ? "HH" : "LH" :
"H" ) ///////////////////////////////Here
array.push(ArrayValue, HighValue)
array.push(ArrayIndex, HighIndex)
Correct_HighPivot := HighValue
else if (ArrayType.get(ArrayType.size() - 1)) == "H" or
(ArrayType.get(ArrayType.size() - 1)) == "HH"
if HighPivot > ArrayValue.get(ArrayType.size() - 1)
array.remove(ArrayType,ArrayType.size() - 1)
array.remove(ArrayValue,ArrayValue.size() - 1)
array.remove(ArrayIndex,ArrayIndex.size() - 1)
array.push(ArrayType,ArrayType.size()>2?
ArrayValue.get(ArrayType.size() - 2) < HighValue ? "HH" : "LH" :
"H")///////////////////////////////Here
array.push(ArrayValue, HighValue)
array.push(ArrayIndex, HighIndex)
Correct_HighPivot := HighValue
else
array.push(ArrayType,ArrayType.size()>2?
ArrayValue.get(ArrayType.size() - 2) < LowValue ? "HL" : "LL" :
"L")///////////////////////////////Here
array.push(ArrayValue, LowValue)
array.push(ArrayIndex, LowIndex)
Correct_LowPivot := LowValue
else if (ArrayType.get(ArrayType.size() - 1)) == "LH"
if HighPivot < ArrayValue.get(ArrayType.size() - 1)
array.push(ArrayType,ArrayType.size()>2?
ArrayValue.get(ArrayType.size() - 2) < LowValue ? "HL" : "LL" :
"L")///////////////////////////////Here
array.push(ArrayValue, LowValue)
array.push(ArrayIndex, LowIndex)
Correct_LowPivot := LowValue
else if HighPivot > ArrayValue.get(ArrayType.size() - 1)
if close < ArrayValue.get(ArrayType.size() - 1)
array.remove(ArrayType,ArrayType.size() - 1)
array.remove(ArrayValue,ArrayValue.size() - 1)
array.remove(ArrayIndex,ArrayIndex.size() - 1)
array.push(ArrayType,ArrayType.size()>2?
ArrayValue.get(ArrayType.size() - 2) < HighValue ? "HH" : "LH" :
"H")///////////////////////////////Here
array.push(ArrayValue, HighValue)
array.push(ArrayIndex, HighIndex)
Correct_HighPivot := HighValue
else if close > ArrayValue.get(ArrayType.size() - 1)
array.push(ArrayType,ArrayType.size()>2?
ArrayValue.get(ArrayType.size() - 2) < LowValue ? "HL" : "LL" :
"L")///////////////////////////////Here
array.push(ArrayValue, LowValue)
array.push(ArrayIndex, LowIndex)
Correct_LowPivot := LowValue
else if (ArrayType.get(ArrayType.size() - 1)) == "HL"
if LowPivot > ArrayValue.get(ArrayType.size() - 1)
array.push(ArrayType,ArrayType.size()>2?
ArrayValue.get(ArrayType.size() - 2) < HighValue ? "HH" : "LH" :
"H" ) ///////////////////////////////Here
array.push(ArrayValue, HighValue)
array.push(ArrayIndex, HighIndex)
Correct_HighPivot := HighValue
else if LowPivot < ArrayValue.get(ArrayType.size() - 1)
if close > ArrayValue.get(ArrayType.size() - 1)
array.remove(ArrayType,ArrayType.size() - 1)
array.remove(ArrayValue,ArrayValue.size() - 1)
array.remove(ArrayIndex,ArrayIndex.size() - 1)
array.push(ArrayType,ArrayType.size()>2?
ArrayValue.get(ArrayType.size() - 2) < LowValue ? "HL" : "LL" :
"L")///////////////////////////////Here
array.push(ArrayValue, LowValue)
array.push(ArrayIndex, LowIndex)
Correct_LowPivot := LowValue
else if close < ArrayValue.get(ArrayType.size() - 1)
array.push(ArrayType,ArrayType.size()>2?
ArrayValue.get(ArrayType.size() - 2) < HighValue ? "HH" : "LH" :
"H")///////////////////////////////Here
array.push(ArrayValue, HighValue)
array.push(ArrayIndex, HighIndex)
Correct_HighPivot := HighValue
else if HighPivot
if ArrayType.size() == 0
array.insert(ArrayType, 0, "H")
array.insert(ArrayValue, 0, HighValue)
array.insert(ArrayIndex, 0, HighIndex)
Correct_HighPivot := HighValue
else if ArrayType.size() >= 1
if ((ArrayType.get(ArrayType.size() - 1)) == "L" or
(ArrayType.get(ArrayType.size() - 1)) == "HL" or
(ArrayType.get(ArrayType.size() - 1)) == "LL")
if HighPivot > ArrayValue.get(ArrayType.size() - 1)
array.push(ArrayType,ArrayType.size()>2?
ArrayValue.get(ArrayType.size() - 2) < HighValue ? "HH" : "LH" :
"H" ) ///////////////////////////////Here
array.push(ArrayValue, HighValue)
array.push(ArrayIndex, HighIndex)
Correct_HighPivot := HighValue
else if HighPivot < ArrayValue.get(ArrayType.size() - 1)
array.remove(ArrayType,ArrayType.size() - 1)
array.remove(ArrayValue,ArrayValue.size() - 1)
array.remove(ArrayIndex,ArrayIndex.size() - 1)
array.push(ArrayType,ArrayType.size()>2?
ArrayValue.get(ArrayType.size() - 2) < LowValue ? "HL" : "LL" :
"L")///////////////////////////////Here
array.push(ArrayValue, LowValue)
array.push(ArrayIndex, LowIndex)
Correct_LowPivot := LowValue
else if (ArrayType.get(ArrayType.size() - 1)) == "H" or
(ArrayType.get(ArrayType.size() - 1)) == "HH" or
(ArrayType.get(ArrayType.size() - 1)) == "LH"
if (ArrayValue.get(ArrayValue.size() - 1)) < HighValue
array.remove(ArrayType,ArrayType.size() - 1)
array.remove(ArrayValue,ArrayValue.size() - 1)
array.remove(ArrayIndex,ArrayIndex.size() - 1)
array.push(ArrayType,ArrayType.size()>2?
ArrayValue.get(ArrayType.size() - 2) < HighValue ? "HH" : "LH" :
"H")///////////////////////////////Here
array.push(ArrayValue, HighValue)
array.push(ArrayIndex, HighIndex)
Correct_HighPivot := HighValue
else if LowPivot
if ArrayType.size() == 0
array.insert(ArrayType, 0, "L")
array.insert(ArrayValue, 0, LowValue)
array.insert(ArrayIndex, 0, LowIndex)
Correct_LowPivot := LowValue
else if ArrayType.size() >= 1
if (ArrayType.get(ArrayType.size() - 1)) == "H" or
(ArrayType.get(ArrayType.size() - 1)) == "HH" or
(ArrayType.get(ArrayType.size() - 1)) == "LH"
if LowPivot < ArrayValue.get(ArrayType.size() - 1)
array.push(ArrayType,ArrayType.size()>2?
ArrayValue.get(ArrayType.size() - 2) < LowValue ? "HL" : "LL" :
"L")///////////////////////////////Here
array.push(ArrayValue, LowValue)
array.push(ArrayIndex, LowIndex)
Correct_LowPivot := LowValue
else if LowPivot > ArrayValue.get(ArrayType.size() - 1)
array.remove(ArrayType,ArrayType.size() - 1)
array.remove(ArrayValue,ArrayValue.size() - 1)
array.remove(ArrayIndex,ArrayIndex.size() - 1)
array.push(ArrayType,ArrayType.size()>2?
ArrayValue.get(ArrayType.size() - 2) < HighValue ? "HH" : "LH" :
"H")///////////////////////////////Here
array.push(ArrayValue, HighValue)
array.push(ArrayIndex, HighIndex)
Correct_HighPivot := HighValue
else if (ArrayType.get(ArrayType.size() - 1)) == "L" or
(ArrayType.get(ArrayType.size() - 1)) == "HL" or
(ArrayType.get(ArrayType.size() - 1)) == "LL"
if (ArrayValue.get(ArrayValue.size() - 1)) > LowValue
array.remove(ArrayType,ArrayType.size() - 1)
array.remove(ArrayValue,ArrayValue.size() - 1)
array.remove(ArrayIndex,ArrayIndex.size() - 1)
array.push(ArrayType,ArrayType.size()>2?
ArrayValue.get(ArrayType.size() - 2) < LowValue ? "HL" : "LL" :
"L")///////////////////////////////Here
array.push(ArrayValue, LowValue)
array.push(ArrayIndex, LowIndex)
Correct_LowPivot := LowValue

// get data

var bool Bearish3Drive = false


var bool Be3Druntime = true

var bool Bullish3Drive = false


var bool Bu3Druntime = true

var string PT1 = ''


var string PT2 = ''
var string PT3 = ''
var string PT4 = ''
var string PT5 = ''

var float PV1 = 0.0


var float PV2 = 0.0
var float PV3 = 0.0
var float PV4 = 0.0
var float PV5 = 0.0

var int PI1 = 0


var int PI3 = 0
var int PI5 = 0

if ArrayType.size() > 6
PT1 := ArrayType.get(ArrayType.size() - 1)
PT2 := ArrayType.get(ArrayType.size() - 2)
PT3 := ArrayType.get(ArrayType.size() - 3)
PT4 := ArrayType.get(ArrayType.size() - 4)
PT5 := ArrayType.get(ArrayType.size() - 5)
PV1 := ArrayValue.get(ArrayType.size() - 1)
PV2 := ArrayValue.get(ArrayType.size() - 2)
PV3 := ArrayValue.get(ArrayType.size() - 3)
PV4 := ArrayValue.get(ArrayType.size() - 4)
PV5 := ArrayValue.get(ArrayType.size() - 5)
PI1 := ArrayIndex.get(ArrayType.size() - 1)
PI3 := ArrayIndex.get(ArrayType.size() - 3)
PI5 := ArrayIndex.get(ArrayType.size() - 5)

//global condition
X = math.ceil((PI1 - PI5))
INF = math.floor((PI5 + X*0.375))
SUP = math.ceil((PI5 + X*0.625))
global_condition = PI3 > INF and PI3 < SUP
// Bearish 3 Drive

BeCondition1 = PT1 == 'HH' and PT2 == 'HL' and PT3 == 'HH' and PT4 == 'HL' and
PT5 == 'HH'
BeCondition2 = (PV3-PV2) / (PV1-PV3) > 1 and
(PV5-PV4) / (PV3-PV5) > 1 and
(PV1 - PV3) / (PV3 - PV5) > 1 and
global_condition

if BeCondition1 and BeCondition2 and Be3Druntime


Bearish3Drive := true
Be3Druntime := false
else if PI1 != PI1[1] and PT1 == 'HH'
Be3Druntime := true
else
Bearish3Drive := false

// Bullish 3 Drive
BuCondition1 = PT1 == 'LL' and PT2 == 'LH' and PT3 == 'LL' and PT4 == 'LH' and
PT5 == 'LL'
BuCondition2 = (PV2-PV3) / (PV3-PV1) > 1 and
(PV4-PV5) / (PV5-PV3) > 1 and
(PV3 - PV1) / (PV5 - PV3) > 1 and
global_condition

if BuCondition1 and BuCondition2 and Bu3Druntime


Bullish3Drive := true
Bu3Druntime := false
else if PI1 != PI1[1] and PT1 == 'LL'
Bu3Druntime := true
else
Bullish3Drive := false

plotshape(Bearish3Drive ,
'Bearish 3 Drive' ,
style = shape.arrowdown ,
location = location.abovebar ,
color = color.red ,
textcolor = color.red)

plotshape(Bullish3Drive ,
'Bullish 3 Drive' ,
style = shape.arrowup ,
location = location.belowbar ,
color = color.green ,
textcolor = color.green )

Drawing(bullCond , bearCond) =>


var line BullLine = na
var line BearLine = na
BullCond = bullCond
BearCond = bearCond

if BullCond
BullLine := line.new(PI5 , PV5 , PI1 , PV1 , color = color.rgb(35, 124, 38)
, style = line.style_dashed)
label.new(PI5 , PV5 , '1' , color = color.rgb(35, 124, 38) , textcolor =
color.white , size = size.small , style = label.style_label_up)
label.new(PI3 , line.get_price(BullLine, PI3) , '2' , color =
color.rgb(35, 124, 38) , textcolor = color.white , size = size.small , style =
label.style_label_up)
label.new(PI1 , PV1 , '3' , color = color.rgb(35, 124, 38) , textcolor =
color.white , size = size.small , style = label.style_label_up)

if BearCond
BearLine := line.new(PI5 , PV5 , PI1 , PV1 , color = color.rgb(212, 16, 16)
, style = line.style_dashed)
label.new(PI5 , PV5 , '1' , color = color.rgb(212, 16, 16) , textcolor =
color.white , size = size.small , style = label.style_label_down)
label.new(PI3 , line.get_price(BearLine, PI3) , '2' , color =
color.rgb(212, 16, 16) , textcolor = color.white , size = size.small , style =
label.style_label_down)
label.new(PI1 , PV1 , '3' , color = color.rgb(212, 16, 16) , textcolor =
color.white , size = size.small , style = label.style_label_down)

Drawing(Bullish3Drive , Bearish3Drive)

// Define Big Mover as a Non-Doji Solid Candle that Engulfs the Previous One
bodySize3 = math.abs(close[3] - open[3])
range3 = high[3] - low[3]
bodySize4 = math.abs(close[4] - open[4])

nonDoji = bodySize3 >= range3 * 0.6 // Body is at least 60% of total range
engulfing = (open[3] < close[4] and close[3] > open[4]) or (open[3] > close[4] and
close[3] < open[4]) // Fully engulfs previous candle

bigCandle = nonDoji and engulfing

// Ensure the 3 consecutive candles are the same color


threeBearish = close[2] < open[2] and close[1] < open[1] and close[0] < open[0] //
All Red
threeBullish = close[2] > open[2] and close[1] > open[1] and close[0] > open[0] //
All Green

// Ensure their Closes stay inside the range of Big Mover


withinRange = close[2] <= high[3] and close[2] >= low[3] and close[1] <= high[3]
and close[1] >= low[3] and close[0] <= high[3] and close[0] >= low[3]
// Falling Three (Big Bullish + 3 Consecutive Bearish Candles) - Now on 3rd candle
fallingThree = bigCandle and close[3] > open[3] and threeBearish and withinRange

// Rising Three (Big Bearish + 3 Consecutive Bullish Candles) - Now on 3rd candle
risingThree = bigCandle and close[3] < open[3] and threeBullish and withinRange

// Plot "R3" ABOVE the bar


plotchar(risingThree, char="③", location=location.abovebar, color=#f06292,
size=size.tiny)

// Plot "F3" BELOW the bar


plotchar(fallingThree, char="③", location=location.belowbar, color=color.rgb(82,
255, 125), size=size.tiny)

// Alert Conditions
alertcondition(risingThree, title="Rising-3 Signal", message="Rising Three pattern
detected!")
alertcondition(fallingThree, title="Falling-3 Signal", message="Falling Three
pattern detected!")

// Inputs for Chaikin Money Flow (CMF) and Multi-Timeframe


//------------------------------------------------------------------------------
cmfLength = input.int(20, minval=1, title="CMF Length")
rsiLength = input.int(14, title="RSI Length")
rsiOverSold = input.int(30, title="RSI Oversold Level")

// Timeframe settings
tfH4 = "240" // 4-hour timeframe
tfH1 = "60" // 1-hour timeframe

//------------------------------------------------------------------------------
// CMF and RSI Calculations for H4
//------------------------------------------------------------------------------
highH4 = request.security(syminfo.tickerid, tfH4, high)
lowH4 = request.security(syminfo.tickerid, tfH4, low)
closeH4 = request.security(syminfo.tickerid, tfH4, close)
volumeH4 = request.security(syminfo.tickerid, tfH4, volume)

adH4 = closeH4 == highH4 and closeH4 == lowH4 or highH4 == lowH4 ? 0 : ((2 *


closeH4 - lowH4 - highH4) / (highH4 - lowH4)) * volumeH4
mfH4 = math.sum(adH4, cmfLength) / math.sum(volumeH4, cmfLength)

rsiH4 = ta.rsi(closeH4, rsiLength)


isRSIOSH4 = rsiH4 <= rsiOverSold
bullishCandleH4 = closeH4 >= open and close[1] < open[1] // Bullish candle in
current chart

// CMF Long Entry Condition for H4


chaikinLongH4 = isRSIOSH4 and bullishCandleH4 and mfH4 > 0

//------------------------------------------------------------------------------
// CMF and RSI Calculations for H1 (Evaluated Globally)
//------------------------------------------------------------------------------
highH1 = request.security(syminfo.tickerid, tfH1, high)
lowH1 = request.security(syminfo.tickerid, tfH1, low)
closeH1 = request.security(syminfo.tickerid, tfH1, close)
volumeH1 = request.security(syminfo.tickerid, tfH1, volume)

adH1 = closeH1 == highH1 and closeH1 == lowH1 or highH1 == lowH1 ? 0 : ((2 *


closeH1 - lowH1 - highH1) / (highH1 - lowH1)) * volumeH1
mfH1 = math.sum(adH1, cmfLength) / math.sum(volumeH1, cmfLength)

rsiH1 = ta.rsi(closeH1, rsiLength)


isRSIOSH1 = rsiH1 <= rsiOverSold
bullishCandleH1 = closeH1 >= open and close[1] < open[1] // Bullish candle in
current chart

// CMF Long Entry Condition for H1


chaikinLongH1 = isRSIOSH1 and bullishCandleH1 and mfH1 > 0

//------------------------------------------------------------------------------
// Visualizations with Text Bubble (Using plotchar)
//------------------------------------------------------------------------------

// Display a bubble for H1 Chaikin Long Entry (Visible on All Charts)


plotchar(chaikinLongH1, title="Chaikin H1 Signal", char="$",
location=location.belowbar,
color=color.green, size=size.small)

// Display a bubble for H4 Chaikin Long Entry (Only on H4 Chart)


isH4Chart = timeframe.isminutes and timeframe.multiplier == 240
plotchar(isH4Chart and chaikinLongH4 ? 1 : na, title="Chaikin H4 Signal", char="$",
location=location.abovebar,
color=color.teal, size=size.small, text="Chaikin H4")

//------------------------------------------------------------------------------
// Alert Conditions
//------------------------------------------------------------------------------
alertcondition(chaikinLongH1, title="H1 Chaikin Signal",
message="{{ticker}}, Chaikin H1 Price: {{close}}")

alertcondition(chaikinLongH4, title="H4 Chaikin Signal",


message="{{ticker}}, Chaikin H4 Price: {{close}}")

You might also like