// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // (c) LonesomeTheBlue //@version=5 indicator(title="Ichimoku Oscillator", shorttitle="IO", explicit_plot_zorder = true) conversionPeriods = input.int(8, minval=1, title="Conversion Line Length", group = "Setup") basePeriods = input.int(13, minval=1, title="Base Line Length", group = "Setup") laggingSpan2Periods = input.int(26, minval=1, title="Leading Span B Length", group = "Setup") displacement = input.int(13, minval=1, title="Lagging Span", group = "Setup") useatr = input.bool(defval = true, title ="Use ATR", tooltip = "Protection from Whipsaw", group = "Setup") atrlen = input.int(defval = 9, title = " Length", minval = 1, group = "Setup") atrmul = input.float(defval = 2.0, title = " Mult", minval = 0.1, step = 0.1, group = "Setup") bounceoff = input.bool(defval = false, title = "Bounce Off Support/Resistance", tooltip = "Enables the Additional Entries when price bounce off Support/Resistance Zone", group = "Setup") useema = input.bool(defval = true, title ="Show EMA", group = "Setup") emalen = input.int(defval = 9, title = " Length", minval = 1, group = "Setup") emacol = input.color(defval = #d1c4e9, title = " Color", group = "Setup") emawd = input.int(defval = 1, title = " Width", minval = 1, maxval = 5, group = "Setup") ematkpartprft = input.bool(defval = true, title = "Take Partial Profit by EMA") entexlongcol = input.color(defval = color.white, title = "Entry/Exit Colors", inline = "entcol", group = "Colors") entexshortcol = input.color(defval = color.yellow, title = "", inline = "entcol", group = "Colors") coloredbg = input.bool(defval = true, title = "Colored Background", group = "Colors") bgcolupI = input.string(defval = "Green", title = " Uptrend", options = ["Green", "Red", "Blue"], group = "Colors") bgcoldnI = input.string(defval = "Blue", title = " Downtrend", options = ["Green", "Red", "Blue"], group = "Colors") bgtransp = input.int(defval = 60, title = " Transparency", step = 10, minval = 0, maxval = 100, group = "Colors") upcol1 = input.color(defval = color.rgb(0 , 250, 0, 0), title = "Uptrend Colors", inline = "upcols", group = "Colors") upcol2 = input.color(defval = color.rgb(0 , 190, 0, 0), title = "", inline = "upcols", group = "Colors") upcol3 = input.color(defval = color.rgb(0 , 130, 0, 0), title = "", inline = "upcols", group = "Colors") upcol4 = input.color(defval = color.rgb(0 , 70, 0, 0), title = "", inline = "upcols", group = "Colors") dbcol1 = input.color(defval = color.rgb(250, 0, 0, 0), title = "Downtrend Colors", inline = "dbcols", group = "Colors") dbcol2 = input.color(defval = color.rgb(190, 0, 0, 0), title = "", inline = "dbcols", group = "Colors") dbcol3 = input.color(defval = color.rgb(130, 0, 0, 0), title = "", inline = "dbcols", group = "Colors") dbcol4 = input.color(defval = color.rgb(70, 0, 0, 0), title = "", inline = "dbcols", group = "Colors") inSRcolor = input.color(defval = #d1d4dc, title = "In Support/Resistance Zone", group = "Colors") // Alerts mainalert = input.bool(defval = true, title = "Main Buy/Sell Alert", group = "Alerts") addalert = input.bool(defval = true, title = "Additional Buy/Sell Alert", group = "Alerts") alertlongmsg = input.string(defval = "Buy / Main, Close = close", title = " Long message", group = "Alerts") alertshortmsg = input.string(defval = "Sell / Main, Close = close", title = " Short message", group = "Alerts") alertaddlongmsg = input.string(defval = "Buy / Additonal, Close = close", title = " Long message", group = "Alerts") alertaddshortmsg = input.string(defval = "Sell / Additonal, Close = close", title = " Short message", group = "Alerts") mainfrequency = input.string(defval = alert.freq_once_per_bar_close, title = " Frequency", options = [alert.freq_once_per_bar_close, alert.freq_once_per_bar], group = "Alerts") closealert = input.bool(defval = true, title = "Close Position Alert", group = "Alerts") closepartalert = input.bool(defval = true, title = "Take Partial Profit Alert", group = "Alerts") closemainmsg = input.string(defval = "Close Position, Close = close", title = " Close Position Message", group = "Alerts") closepartmsg = input.string(defval = "Take Partial Profit, Close = close", title = " Take Partial Profit Message", group = "Alerts") closefrequency = input.string(defval = alert.freq_once_per_bar, title = " Frequency", options = [alert.freq_once_per_bar_close, alert.freq_once_per_bar], group = "Alerts") // ichimoku calculation donchian(len) => math.avg(ta.lowest(len), ta.highest(len)) conversionLine = donchian(conversionPeriods) baseLine = donchian(basePeriods) leadLine1 = math.avg(conversionLine, baseLine) leadLine2 = donchian(laggingSpan2Periods) // Oscillator calculation var int mtrend = 0 var int trend = 0 cloudup = leadLine1 >= leadLine2 clouddn = leadLine1 <= leadLine2 CloudMin = math.min(leadLine1[displacement - 1], leadLine2[displacement - 1]) CloudMax = math.max(leadLine1[displacement - 1], leadLine2[displacement - 1]) inthecloud = close >= CloudMin and close <= CloudMax mtrend := close > CloudMax ? 1 : close < CloudMin ? -1 : mtrend // first layer Oscline = mtrend == 1 ? (close - CloudMin) : (close - CloudMax) Osccolor = inthecloud ? inSRcolor: close > CloudMax ? upcol1 : dbcol1 //second layer Lagging = Oscline + (mtrend == 1 ? math.max(close - CloudMax[displacement - 1], 0) : // , close - close[displacement - 1] math.min(close - CloudMin[displacement - 1], 0)) // , close - close[displacement - 1] //third layer ConvBase = Lagging + (mtrend == 1 ? math.max((conversionLine - baseLine), 0) : math.min((conversionLine -baseLine), 0)) ConvBaseColor = conversionLine >= baseLine ? upcol3 : dbcol3 // fourth layer cloud = ConvBase + (mtrend == 1 ? math.max(leadLine1 - leadLine2, 0) : math.min(leadLine1 - leadLine2, 0)) anyofthemrising = ta.change(conversionLine) > 0 or ta.change(baseLine) > 0 anyofthemfalling = ta.change(conversionLine) < 0 or ta.change(baseLine) < 0 convoverbase = conversionLine >= baseLine baseoverconv = conversionLine <= baseLine // little Protection from whipsaw tole = useatr ? ta.atr(atrlen) * atrmul : 0 // calculation of the trend and getting entry level if trend appears var float entrylevel = na if mtrend == 1 trend := mtrend[1] == -1 ? 0 : trend if trend < 4 and close > CloudMax trend := (Lagging > Oscline ? 1 : 0) + (convoverbase and anyofthemrising? 1 : 0) + (cloudup ? 1 : 0) + 1 if trend == 4 entrylevel := close else trend := (conversionLine < baseLine - tole ? 0 : trend) else if mtrend == -1 trend := mtrend[1] == 1 ? 0 : trend if trend > - 4 and close < CloudMin trend := (Lagging < Oscline ? -1 : 0) - (baseoverconv and anyofthemfalling ? 1 : 0) - (clouddn ? 1 : 0) - 1 if trend == -4 entrylevel := close else trend := (conversionLine > baseLine + tole? 0 : trend) // Background coloring if Enabled uptmult = 159 + math.pow(trend, 3) dntmult = 159 - math.pow(trend, 3) bgcolup = color.rgb(bgcolupI == "Red" ? uptmult : 0, bgcolupI == "Green" ? uptmult : 0, bgcolupI == "Blue" ? uptmult : 0, bgtransp) bgcoldn = color.rgb(bgcoldnI == "Red" ? dntmult : 0, bgcoldnI == "Green" ? dntmult : 0, bgcoldnI == "Blue" ? dntmult : 0, bgtransp) bgcolor(color = coloredbg ? trend > 0 ? bgcolup : trend < 0 ? bgcoldn : inSRcolor : na) // ploting layers plot(cloud, color = mtrend == 1 ? upcol4 : dbcol4, style = plot.style_area) plot(ConvBase, color = ConvBaseColor, style = plot.style_area) plot(Lagging, color = close > CloudMax ? upcol2 : close < CloudMin ? dbcol2 : color.new(color.white, 100), style = plot.style_area) plot(Oscline, color = Osccolor, style = plot.style_area) // convert the message getClose(message) => str.replace(message, "close", str.tostring(close)) // closing main position closetrade = ta.change(trend) != 0 and math.abs(trend[1]) == 4 plotshape(cloud, color = closetrade ? (trend[1] > 0 ? entexlongcol : entexshortcol): color.new(color.white, 100), style = shape.xcross, size = size.small, location = location.absolute) if closetrade and closealert alert(getClose(closemainmsg), closefrequency) // take long position uptrend = trend == 4 and ta.change(trend) != 0 plotshape(0, color = uptrend ? entexlongcol : color.new(color.white, 100), style = shape.triangleup, size = size.small, location = location.absolute) bouncbackup = bounceoff and trend == 4 and close > CloudMax and inthecloud[1] plotshape(0, color = bouncbackup ? entexlongcol : color.new(color.white, 100), style = shape.triangleup, size = size.tiny, location = location.absolute) // long position alerts if trend == 4 if uptrend and mainalert alert(getClose(alertlongmsg), mainfrequency) if bouncbackup and addalert alert(getClose(alertaddlongmsg), mainfrequency) // take short position downtrend = trend == -4 and ta.change(trend) != 0 plotshape(0, color = downtrend ? entexshortcol : color.new(color.white, 100), style = shape.triangledown, size = size.small, location = location.absolute) bouncbackdn = bounceoff and trend == -4 and close < CloudMin and inthecloud[1] plotshape(0, color = bouncbackdn ? entexshortcol : color.new(color.white, 100), style = shape.triangledown, size = size.tiny, location = location.absolute) // short position alerts if trend == -4 if downtrend and mainalert alert(getClose(alertshortmsg), mainfrequency) if bouncbackdn and addalert alert(getClose(alertaddshortmsg), mainfrequency) // plot ema line if enabled emaline = ta.ema(cloud, emalen) plot(emaline, linewidth = emawd, color = useema ? emacol : color.new(color.white, 100)) // possible/partially take profit if profitable convcrossbase = ta.crossover(conversionLine, baseLine) basecrosscons = ta.crossover(baseLine, conversionLine) emacrosscloud = ta.crossover(emaline, cloud) cloudcrossema = ta.crossover(cloud, emaline) profitable = trend == 4 and close > entrylevel or trend == -4 and close < entrylevel posexitcol = profitable ? trend == 4 and basecrosscons ? entexlongcol : trend == 4 and emacrosscloud and ematkpartprft ? emacol : trend == -4 and convcrossbase ? entexshortcol : trend == -4 and cloudcrossema and ematkpartprft ? emacol : color.new(color.white, 100) : color.new(color.white, 100) plotshape(cloud, color = posexitcol, location = location.absolute, style = shape.xcross, size = size.tiny) partclose = trend == 4 and basecrosscons or trend == 4 and emacrosscloud and ematkpartprft or trend == -4 and convcrossbase or trend == -4 and cloudcrossema and ematkpartprft // partially take profit alert if partclose and closepartalert alert(getClose(closepartmsg), closefrequency)