Professional Documents
Culture Documents
Simple System by LEO 2@free_fx_pro
Simple System by LEO 2@free_fx_pro
0
at https://mozilla.org/MPL/2.0/
// © leandrolopezf1920
//@version=5
indicator("Simple System by LEO 2", overlay = true, max_lines_count = 500,
max_labels_count = 500, max_boxes_count = 500, max_bars_back = 1000)
//------------------------------------------------------------------------------
// === Range Detector ===
//------------------------------------------------------------------------------
//Style
upCss = input(#089981, 'Broken Upward', group = 'Style')
dnCss = input(#f23645, 'Broken Downward', group = 'Style')
unbrokenCss = input(#2157f3, 'Unbroken', group = 'Style')
//-----------------------------------------------------------------------------}
//Detect and highlight ranges
//-----------------------------------------------------------------------------{
//Ranges drawings
var box bx = na
var line lvl = na
//Extensions
var float max2 = na
var float min2 = na
var os = 0
color detect_css = na
else if count == 0
bx.set_right(n)
lvl.set_x2(n)
//Set color
if close > bx.get_top()
bx.set_bgcolor(color.new(#ff5252, 100))
lvl.set_color(upCss)
os := 1
else if close < bx.get_bottom()
bx.set_bgcolor(color.new(#ff5252, 100))
lvl.set_color(dnCss)
os := -1
//-----------------------------------------------------------------------------}
//Plots
//-----------------------------------------------------------------------------{
//Range detection bgcolor
bgcolor(detect_css)
//-----------------------------------------------------------------------------}
//-----------------------------------------------------------------------------}
//INPUTS
cooldownPeriod = input.int(10,title="Cooldown Period", minval=0, group =
"Settings")
lbLeft = 20
lbRight = 20
//FUNCTIONS
lineStyle(s) =>
if s == 'Solid'
line.style_solid
else if s == 'Dotted'
line.style_dotted
else
line.style_dashed
//VARS
var int bullSignalIndex = 0
var int bearSignalIndex = 0
//CALCULATIONS
pLow = ta.pivotlow(low, lbLeft, lbRight)
pHigh = ta.pivothigh(high, lbLeft, lbRight)
lp = ta.lowest(low, lbLeft)
hp = ta.highest(high, lbLeft)
bullishSFP = low < pLowVal and close > pLowVal and open > pLowVal and low == lp and
lowestClose >= pLowVal
bearishSFP = high > pHighVal and close < pHighVal and open < pHighVal and high ==
hp and highestClose <= pHighVal
bullCond = bullishSFP[3] and (close > pLowVal) and (close[1] > pLowVal[1]) and
(close[2] > pLowVal[2]) and bar_index >= bullSignalIndex + cooldownPeriod
bearCond = bearishSFP[3] and (close < pHighVal) and (close[1] < pHighVal[1]) and
(close[2] < pHighVal[2]) and bar_index >= bearSignalIndex + cooldownPeriod
//Check Swing H/L Stopper
var int swingLowCounter = 0
var int swingHighCounter = 0
var bool isSwingLowCheck = false
var bool isSwingHighCheck = false
var bool stopPrintingLow = false
var bool stopPrintingHigh = false
if bearCond
bearSignalIndex := bar_index
bearLine := line.new(prevHighIndex, pHighVal, bar_index-3, pHighVal,
color=bearColor, width=bearWidth, style=lineStyle(bearStyle))
if array.size(swingHighArr) >= 3
label.delete(array.shift(swingHighArr))
label.delete(array.shift(swingHighTextArr))
if array.size(swingLowArr) >= 3
label.delete(array.shift(swingLowArr))
label.delete(array.shift(swingLowTextArr))
//PLOTS
plotshape(bullCond, text='Sweep', color=bullColor, textcolor=bullColor,
location=location.belowbar, offset = -3)
plotshape(bearCond, text='Sweep', color=bearColor, textcolor=bearColor,
location=location.abovebar, offset = -3)
//ALERTS
alertcondition(bullishSFP, title='Bullish Sweep', message='{{ticker}} Bullish
Sweep, Price:{{close}}')
alertcondition(bearishSFP, title='Bearish Sweep', message='{{ticker}} Bearish
Sweep, Price:{{close}}')
//------------------------------------------------------------------------------
// === Zig Zag Channels ===
//------------------------------------------------------------------------------
length1 = input(100)
extend = input(true,'Extend To Last Bar')
show_ext = input(true,'Show Extremities')
show_labels = input(true,'Show Labels')
//Style
//------------------------------------------------------------------------------
upper = ta.highest(src1,length1)
lower = ta.lowest(src1,length1)
os1 := src1[length1] > upper ? 0 : src1[length1] < lower ? 1 : os1[1]
//------------------------------------------------------------------------------
btm_n = ta.valuewhen(btm,n,0)
top_n = ta.valuewhen(top,n,0)
len = math.abs(btm_n - top_n)
if btm
max_diff_up = 0.
max_diff_dn = 0.
valbtm := low[length1]
for i = 0 to len-1
point = low[length1] + i/(len-1)*(valtop - low[length1])
max_diff_up := math.max(math.max(src1[length1+i],open[length1+i]) -
point,max_diff_up)
max_diff_dn := math.max(point -
math.min(src1[length1+i],open[length1+i]),max_diff_dn)
line.new(n[len+length1],valtop,n[length1],low[length1],color=midcol)
if show_ext
line.new(n[len+length1],valtop+max_diff_up,n[length1],low[length1]+max_diff_up
,color=upcol,style=line.style_dotted)
line.new(n[len+length1],valtop-max_diff_dn,n[length1],low[length1]-
max_diff_dn
,color=dncol,style=line.style_dotted)
if show_labels
label.new(n[length1],low[length1],str.tostring(low[length1],'#.####'),color=#000000
00
,style=label.style_label_up,textcolor=dncol,textalign=text.align_left,siz
e=size.small)
if top
max_diff_up = 0.
max_diff_dn = 0.
valtop := high[length1]
for i = 0 to len-1
point = high[length1] + i/(len-1)*(valbtm - high[length1])
max_diff_up := math.max(math.max(src1[length1+i],open[length1+i]) -
point,max_diff_up)
max_diff_dn := math.max(point -
math.min(src1[length1+i],open[length1+i]),max_diff_dn)
line.new(n[len+length1],valbtm,n[length1],high[length1],color=midcol)
if show_ext
line.new(n[len+length1],valbtm+max_diff_up,n[length1],high[length1]+max_diff_up
,color=upcol,style=line.style_dotted)
line.new(n[len+length1],valbtm-max_diff_dn,n[length1],high[length1]-
max_diff_dn
,color=dncol,style=line.style_dotted)
if show_labels
label.new(n[length1],high[length1],str.tostring(high[length1],'#.####'),color=#0000
0000
,style=label.style_label_down,textcolor=upcol,textalign=text.align_left,s
ize=size.small)
if os1 == 1
x1 := btm_n-length1
y1 := valbtm
for i = 0 to n-btm_n+length1-1
point = src1 + i/(n-btm_n+length1-1)*(valbtm - src1)
max_diff_up := math.max(math.max(src1[i],open[i]) - point,max_diff_up)
max_diff_dn := math.max(point - math.min(src1[i],open[i]),max_diff_dn)
else
x1 := top_n-length1
y1 := valtop
for i = 0 to n-top_n+length1-1
point = src1 + i/(n-top_n+length1-1)*(valtop - src1)
max_diff_up := math.max(math.max(src1[i],open[i]) - point,max_diff_up)
max_diff_dn := math.max(point - math.min(src1[i],open[i]),max_diff_dn)
line.delete(line.new(x1,y1,n,src1,color=midcol,extend=extend.right)[1])
if show_ext
line.delete(line.new(x1,y1+max_diff_up,n,src1+max_diff_up
,color=upcol,style=line.style_dotted,extend=extend.right)[1])
line.delete(line.new(x1,y1-max_diff_dn,n,src1-max_diff_dn
,color=dncol,style=line.style_dotted,extend=extend.right)[1])
//------------------------------------------------------------------------------
plot(btm ? low[length1] : top ? high[length1] : na,'Circles'
,color = btm ? dncol : upcol
,style=plot.style_circles
,offset=-length1)
//-----------------------------------------------------------------------------}
//--------------//
C_DownTrend = true
C_UpTrend = true
var trendRule1 = "SMA50"
var trendRule2 = "SMA50, SMA200"
var trendRule = input.string(trendRule1, "Detect Trend Based On",
options=[trendRule1, trendRule2, "No detection"])
if trendRule == trendRule1
priceAvg = ta.sma(close, 50)
C_DownTrend := close < priceAvg
C_UpTrend := close > priceAvg
if trendRule == trendRule2
sma200 = ta.sma(close, 200)
sma50 = ta.sma(close, 50)
C_DownTrend := close < sma50 and sma50 < sma200
C_UpTrend := close > sma50 and sma50 > sma200
C_EngulfingBullishNumberOfCandles = 2
C_EngulfingBullish = C_DownTrend and C_WhiteBody and C_LongBody and C_BlackBody[1]
and C_SmallBody[1] and close >= open[1] and open <= close[1] and ( close > open[1]
or open < close[1] )
alertcondition(C_EngulfingBullish, title = "New pattern detected", message = "New
Engulfing – Bullish pattern detected")
if C_EngulfingBullish
var ttBullishEngulfing = "Engulfing\nAt the end of a given downward trend,
there will most likely be a reversal pattern. To distinguish the first day, this
candlestick pattern uses a small body, followed by a day where the candle body
fully overtakes the body from the day before, and closes in the trend’s opposite
direction. Although similar to the outside reversal chart pattern, it is not
essential for this pattern to completely overtake the range (high to low), rather
only the open and the close."
label.new(bar_index, patternLabelPosLow, text="BE", style=label.style_label_up,
color = label_color_bullish, textcolor=color.white, tooltip = ttBullishEngulfing)
C_EngulfingBearishNumberOfCandles = 2
C_EngulfingBearish = C_UpTrend and C_BlackBody and C_LongBody and C_WhiteBody[1]
and C_SmallBody[1] and close <= open[1] and open >= close[1] and ( close < open[1]
or open > close[1] )
alertcondition(C_EngulfingBearish, title = "New pattern detected", message = "New
Engulfing – Bearish pattern detected")
if C_EngulfingBearish
var ttBearishEngulfing = "Engulfing\nAt the end of a given uptrend, a reversal
pattern will most likely appear. During the first day, this candlestick pattern
uses a small body. It is then followed by a day where the candle body fully
overtakes the body from the day before it and closes in the trend’s opposite
direction. Although similar to the outside reversal chart pattern, it is not
essential for this pattern to fully overtake the range (high to low), rather only
the open and the close."
label.new(bar_index, patternLabelPosHigh, text="BE",
style=label.style_label_down, color = label_color_bearish, textcolor=color.white,
tooltip = ttBearishEngulfing)
//-----------------------------------------------------------------------------}
//SUPPORT AND RESISTANCE MTF
//-----------------------------------------------------------------------------{
const bool DEBUG = false
const int timeframeCount = 3
const float touchATR = 1.0 / 30.0
const float retestATR = 1.0 / 30.0
const float labelOffsetY = 1.5
const int labelOffsetsXIndex = 30
const int maxPivotsBackSR = 15
const int retestLabelEveryXBars = 3
const int maxTraverse = 250 // Affects bar history limit. Default value 250.
const int maxRetestLabels = 100
const int maxSupports = 3
const int maxResistances = 3
const int debug_maxPivotLabels = 25
atr1 = ta.atr(30)
createRSLabel () =>
label.new(na, na, "", style = label.style_none, textcolor = textColor)
type customPoint
int t
float price
type RSInfo
bool isBroken = na
int brokenTime = na
string RSType = na
float price = na
line line = na
box box = na
label priceLabel = na
customPoint[] points = na
label[] debugPoints = na
label breakLabel = na
label[] retestLabels = na
line breakLine = na
box breakBox = na
curTR = ta.tr(true)
lowPivot = ta.pivotlow(low, pivotRange, pivotRange)
highPivot = ta.pivothigh(high, pivotRange, pivotRange)
pivotTime = time[pivotRange]
newRSInfoF
newRS.debugPoints := array.new<label>(0)
newRS.retestLabels := array.new<label>(0)
newRS.points := array.new<customPoint>(0)
if enableZones
newRS.box := createRSBox(RSType == "Resistance" ? resistanceColor :
supportColor, xloc.bar_time)
moveRSInfoBox(newRS.box, startTime, newRS.price, endTime)
box.set_extend(newRS.box, expandLines ? extend.both : extend.none)
box.set_text(newRS.box, histText)
else
newRS.line := line.copy(RSInfoF.line)
moveLine(newRS.line, startTime, newRS.price, endTime)
line.set_extend(newRS.line, expandLines ? extend.both : extend.none)
newRS.priceLabel := label.copy(RSInfoF.priceLabel)
label.set_text(newRS.priceLabel, histText)
label.set_xloc(newRS.priceLabel, (startTime + endTime) / 2, xloc.bar_time)
if not na(newRS.breakLabel)
newRS.breakLabel := label.copy(RSInfoF.breakLabel)
newRS
if RSInfoF.debugPoints.size() > 0
for i = 0 to RSInfoF.debugPoints.size() - 1
label.delete(RSInfoF.debugPoints.get(i))
if RSInfoF.retestLabels.size() > 0
for i = 0 to RSInfoF.retestLabels.size() - 1
label.delete(RSInfoF.retestLabels.get(i))
label.delete(RSInfoF.breakLabel)
line.delete(RSInfoF.breakLine)
box.delete(RSInfoF.breakBox)
type timeframeInfo
int index = na
string timeframeStr = na
bool isEnabled = false
RSInfo[] resistances = na
RSInfo[] supports = na
float[] highPivots = na
float[] highTRs = na
int[] highTimes = na
float[] lowPivots = na
float[] lowTRs = na
int[] lowTimes = na
newTFInfo.resistances := array.new<RSInfo>(debug_lastXResistances)
newTFInfo.supports := array.new<RSInfo>(debug_lastXSupports)
newTFInfo.highPivots := array.new<float>()
newTFInfo.highTRs := array.new<float>()
newTFInfo.highTimes := array.new<int>()
newTFInfo.lowPivots := array.new<float>()
newTFInfo.lowTRs := array.new<float>()
newTFInfo.lowTimes := array.new<int>()
newTFInfo
doValuesTouch (float value1, float value2, float tr, float customATRRatio) =>
if math.abs(value1 - value2) <= tr * customATRRatio
true
else
false
index = pivotsCount - i - 1
occurances = 0
invalidValue = false
pivotValue1 = pivots.get(index)
if bannedValues.size() > 0
for a = 0 to bannedValues.size() - 1
if doValuesTouch(pivotValue1, bannedValues.get(a),
trs.get(index))
invalidValue := true
break
if invalidValue
continue
for j = 0 to pivotsCount - 1
if j >= maxTraverse
break
index2 = pivotsCount - j - 1
pivotValue2 = pivots.get(index2)
if doValuesTouch(pivotValue1, pivotValue2, trs.get(index))
occurances += 1
if not na(latestRSF)
break
if not na(latestRSF)
cnt = 0
if pivotsCount > 0
for i = 0 to pivotsCount - 1
if i >= maxTraverse
break
index = pivotsCount - i - 1
pivotValue = pivots.get(index)
if doValuesTouch(pivotValue, latestRSF.price, trs.get(index))
labelTime = times.get(index)
latestRSF.points.push(customPoint.new(labelTime, pivotValue))
cnt += 1
if cnt == strength
break
curIndex = 0
float foundBreakLevel = na
int foundBreakTime = na
float foundBreakTR = na
while true
if curIndex >= maxTraverse
break
isBarBreak = rsInfo.RSType == "Resistance" ? (close[curIndex + 1] <=
rsInfo.price and close[curIndex] > rsInfo.price) : (close[curIndex + 1] >=
rsInfo.price and close[curIndex] < rsInfo.price)
if isBarBreak
isTrueBreakout = true
if avoidFalseBreaks
shortTerm = 2
longTerm = 15
shortSum = 0.0
longSum = 0.0
for i = 0 to shortTerm
shortSum += volume[curIndex + i]
for i = 0 to longTerm
longSum += volume[curIndex + i]
curIndex += 1
if time[curIndex] <= rsInfo.points.get(rsInfo.points.size() - 1).t
break
[foundBreakLevel, foundBreakTime, foundBreakTR]
curIndex = 0
lastRetestIndex = -999
int[] retestTimes = array.new<int>()
float[] retestLevels = array.new<float>()
float[] retestTRs = array.new<float>()
while true
if curIndex >= maxTraverse
break
if retestLevels.size() == maxRetestLabels
break
if rsInfo.isBroken and time[curIndex] >= rsInfo.brokenTime
curIndex += 1
continue
tr = high[curIndex] - low[curIndex]
isRetest = (rsInfo.RSType == "Resistance" ? (doValuesTouch(rsInfo.price,
close[curIndex], tr, retestATR) or doValuesTouch(rsInfo.price, high[curIndex], tr,
retestATR)) : (doValuesTouch(rsInfo.price, close[curIndex], tr, retestATR) or
doValuesTouch(rsInfo.price, low[curIndex], tr, retestATR)))
if isRetest and curIndex - lastRetestIndex >= retestLabelEveryXBars
retestLevels.push(rsInfo.RSType == "Resistance" ? high[curIndex] :
low[curIndex])
retestTimes.push(time[curIndex])
retestTRs.push(high[curIndex] - low[curIndex])
lastRetestIndex := curIndex
curIndex += 1
if time[curIndex] <= rsInfo.points.get(rsInfo.points.size() - 1).t
break
[retestLevels, retestTimes, retestTRs]
if not na(foundBreakLevel)
if showBreaks
if na(RSInfoF.breakLabel)
RSInfoF.breakLabel := createBreakLabel(RSInfoF.RSType)
label.set_xy(RSInfoF.breakLabel, foundBreakTime, foundBreakLevel +
(RSInfoF.RSType == "Resistance" ? (-foundBreakTR / labelOffsetY) : foundBreakTR /
labelOffsetY))
if expandLines
if na(RSInfoF.breakLine) and enableZones == false
RSInfoF.breakLine := createRSLine(color.black)
if not enableZones
line.set_extend(RSInfoF.breakLine, extend.right)
else
box.set_extend(RSInfoF.breakBox, extend.right)
if showRetests
[retestLevels, retestTimes, retestTRs] = getRetests(RSInfoF)
if expandLines
if not enableZones
line.set_extend(RSInfoF.line, (na(foundBreakTime)) ? extend.both :
extend.left)
else
box.set_extend(RSInfoF.box, (na(foundBreakTime)) ? extend.both :
extend.left)
else
if not enableZones
line.set_extend(RSInfoF.line, na(foundBreakTime) ? extend.right :
extend.none)
else
box.set_extend(RSInfoF.box, na(foundBreakTime) ? extend.right :
extend.none)
if not enableZones
label.set_text(RSInfoF.priceLabel, enableZones ? "" : labelTitle)
label.set_y(RSInfoF.priceLabel, RSInfoF.price)
else
box.set_text(RSInfoF.box, (RSInfoF.isBroken and expandLines) ? "" :
labelTitle)
box.set_text(RSInfoF.breakBox, labelTitle)
timeframeInfoF.lowPivots.clear()
timeframeInfoF.highPivots.clear()
timeframeInfoF.lowTimes.clear()
timeframeInfoF.highTimes.clear()
timeframeInfoF.lowTRs.clear()
timeframeInfoF.highTRs.clear()
timeframeInfoF.lowPivots := lowPivots
timeframeInfoF.highPivots := highPivots
timeframeInfoF.lowTimes := lowTimes
timeframeInfoF.highTimes := highTimes
timeframeInfoF.lowTRs := lowTRs
timeframeInfoF.highTRs := highTRs
if timeframeInfoF.resistances.size() > 0
for j = 0 to timeframeInfoF.resistances.size() - 1
RSInfo RSInfoF = timeframeInfoF.resistances.get(j)
if not na(RSInfoF)
if debug_enabledHistory
if checkIfArrHasRS(oldRSList, RSInfoF) == false
oldRSList.push(RSInfoF)
oldRetestsCount += RSInfoF.retestLabels.size()
oldBreaksCount += RSInfoF.isBroken ? 1 : 0
derenderRSInfo(RSInfoF)
if timeframeInfoF.supports.size() > 0
for j = 0 to timeframeInfoF.supports.size() - 1
RSInfo RSInfoF = timeframeInfoF.supports.get(j)
if not na(RSInfoF)
if debug_enabledHistory
if checkIfArrHasRS(history, RSInfoF) == false
oldRSList.push(RSInfoF)
oldRetestsCount += RSInfoF.retestLabels.size()
oldBreaksCount += RSInfoF.isBroken ? 1 : 0
derenderRSInfo(RSInfoF)
timeframeInfoF.resistances.clear()
timeframeInfoF.supports.clear()
[oldRetestsCount, oldBreaksCount]
if count > 0
for j = 0 to count - 1
foundRS = findLatestNthRS(timeframeInfoF, RSType, pivots, times, trs, j
+ 1)
if not na(foundRS)
notDuplicate = true
for a = 0 to timeframeInfos.size() - 1
aInfo = timeframeInfos.get(a)
if na(aInfo) or aInfo.isEnabled == false
continue
otherTimeframeArray = (RSType == "Resistance" ?
aInfo.resistances : aInfo.supports)
if otherTimeframeArray.size() > 0
for b = 0 to otherTimeframeArray.size() - 1
if checkIfRSAreSame(foundRS,
otherTimeframeArray.get(b))
notDuplicate := false
break
if notDuplicate == false
break
if notDuplicate or not debug_removeDuplicateRS
arr.push(foundRS)
if arr.size() > 0
for j = 0 to arr.size() - 1
curRS = arr.get(j)
if not na(curRS)
handleRSInfo(timeframeInfoF, curRS, j, RSType)
curRetestsCount += curRS.retestLabels.size()
curBreaksCount += curRS.isBroken ? 1 : 0
[curRetestsCount, curBreaksCount]
if not na(lowPivot)
allLowPivots.push(lowPivot)
allLowTimes.push(pivotTime)
allLowTR.push(curTR[pivotRange])
if allLowPivots.size() > maxPivotsAllowed
allLowPivots.remove(0)
allLowTimes.remove(0)
allLowTR.remove(0)
if not na(highPivot)
allHighPivots.push(highPivot)
allHighTimes.push(pivotTime)
allHighTR.push(curTR[pivotRange])
if allHighPivots.size() > maxPivotsAllowed
allHighPivots.remove(0)
allHighTimes.remove(0)
allHighTR.remove(0)
//plot(nz(na,timeframeInfos.get(0).highPivots.size() > 0 ?
timeframeInfos.get(0).highPivots.get(timeframeInfos.get(0).highPivots.size() - 1) :
0), color = color.blue, title = "High Pivots")
//plot(nz(na,timeframeInfos.get(0).lowPivots.size() > 0 ?
timeframeInfos.get(0).lowPivots.get(timeframeInfos.get(0).lowPivots.size() - 1) :
0), color = color.fuchsia, title = "Low Pivots")
int enabledTimeframeCount = 0
for i = 0 to timeframeCount - 1
timeframeInfo curInfo = timeframeInfos.get(i)
if curInfo.isEnabled
enabledTimeframeCount += 1
int oldRetestsCount = 0
int curRetestsCount = 0
int oldBreaksCount = 0
int curBreaksCount = 0
for i = 0 to timeframeCount - 1
timeframeInfo curInfo = timeframeInfos.get(i)
if not curInfo.isEnabled
continue
if debug_enabledHistory
historyIndexesToDelete = array.new<int>(0)
if history.size() > 0
for i = 0 to history.size() - 1
if checkIfArrHasRS(curRSList, history.get(i))
historyIndexesToDelete.push(i)
if historyIndexesToDelete.size() > 0
for i = 0 to historyIndexesToDelete.size() - 1
deleteIndex =
historyIndexesToDelete.get(historyIndexesToDelete.size() - i - 1)
safeDeleteRSInfo(history.get(deleteIndex))
history.remove(deleteIndex)
if oldRSList.size() > 0
for i = 0 to oldRSList.size() - 1
curRS = oldRSList.get(i)
if checkIfArrHasRS(curRSList, curRS) == false
history.push(histRSInfo(curRS))
if history.size() > debug_maxHistoryRecords
safeDeleteRSInfo(history.get(0))
history.remove(0)
if oldRSList.size() > 0
for i = 0 to oldRSList.size() - 1
safeDeleteRSInfo(oldRSList.get(i))
curRSList.clear()
oldRSList.clear()
if DEBUG
log.info("History Size : " + str.tostring(history.size()))
log.info("Label Count : " + str.tostring(label.all.size()))
log.info("Line Count : " + str.tostring(line.all.size()))
log.info("Box Count : " + str.tostring(box.all.size()))
initRun := false