// @version=5 // @Author andre_007 // @Thanks and credits: // - TradingView and PineCoders: for SMI, Moving Averages and MFI // - allanster: for Dynamic Zones // @description Stochastic Momentum Index (SMI) of Money Flow Index (MFI). // The Stochastic Momentum Index (SMI) is a technical analysis indicator that uses the difference between the current // closing price and the high or low price over a specific time period to measure price momentum. On the other hand, // the Money Flow Index (MFI) is an indicator that uses volume and price to measure buying and selling pressure. // When these two indicators are combined, they can provide a more comprehensive view of price direction and market strength. indicator(title="Stochastic Momentum Index (SMI) of Money Flow Index (MFI)", shorttitle="SMI MFI TTP", format=format.price, precision=2) import andre_007/MomentumIndicators/1 as MI import andre_007/Utils/11 as UTIL import HoanGhetti/SimpleTrendlines/3 as TL // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— { // #region Constants var string TYPE_MA_TOOLTIP = '1 - Simple Moving Average\n' + '2 - Exponential Moving Average\n' + '3 - Weighted Moving Average\n' + '4 - Volume Weighted Moving Average\n' + '5 - Arnaud Legoux Moving Average\n' + '6 - Hull Moving Average\n' + '7 - Least Squares Moving Average\n' + '8 - Relative Moving Average\n' + '9 - Median' var string THEME_TOOLTIP = '1 = User defined\n' + '2 = User defined with gradient\n' + '10 to 15 → Spectrum Blue-Green-Red\n' + '20 to 21 → Monokai\n' + '30 to 31 → Spectrum White-Green-Red\n' + '40 to 41 → Green-Purple\n' + '50 to 51 → Blue-Red\n' + '60 to 61 → Blue-Yellow\n' + '70 to 71 → Green-Red\n' + '80 to 81 → Green\n' + '90 to 91 → Purple\n' + '100 to 107 → Blue\n' + '120 to 123 → Blue-Aqua\n' + '130 to 137 → Blue-Green\n' + '140 to 153 → Red\n' + '160 to 165 → Red-Yellow\n' + '170 to 171 → Red-White\n' + '180 to 185 → White-Black\n' + '190 to 200 → Spectrum Blue-Red' var string TRANSPARENCY_TOOLTIP = 'To not use the color fill between the TSI and the Signal, leave this value at 100.\n' + 'The closer to zero, the greater the intensity of the filled color.' // #endregion // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— } // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— { // #region Inputs bool useTimeFrame = input.bool(false, title='Use a different timeframe?', group='Timeframe', inline='1') string timeframe = input.timeframe(defval='1D', title='     Timeframe', group='Timeframe', inline='1') bool repaint = input.bool(title="Allow Repainting?", defval=false, tooltip='Prints the indicator in real time even if the bar has not yet closed. This produces more signals.', group='Timeframe', inline='2') // #region SMI var string GRP_SMI = 'Stochastic Momentum Index' float mfiSourceInput = input.source(close, "MFI Source", group=GRP_SMI, inline='MFI') int mfiLengthInput = input.int(13, minval=1, title="MFI Length", group=GRP_SMI, inline='MFI') int stochLongLen = input.int(13, minval=1, title="TSI Long Length", group=GRP_SMI, inline='TSI') int stochShortLen = input.int(8, minval=1, title="TSI Short Length", group=GRP_SMI, inline='TSI') int stochSigLen = input.int(8, minval=1, title="Signal Length", group=GRP_SMI, inline='Signal') int maTypeTSI = input.int(defval=2, title='Type of Smoothing (TSI)', options=[1, 2, 3, 4, 5, 6, 7, 8, 9], tooltip=TYPE_MA_TOOLTIP, group=GRP_SMI, inline='Smooth1') int maTypeSignal = input.int(defval=2, title='Type of Smoothing (Signal)', options=[1, 2, 3, 4, 5, 6, 7, 8, 9], tooltip=TYPE_MA_TOOLTIP, group=GRP_SMI, inline='Smooth2') // #endregion // #region Histogram var string GRP_HISTOGRAM = 'Histogram' float lenMultiplier = input.float(4, minval=1, title="Multiplier", group="Histogram", inline='m') float mfiSourceInputHistogram = input.source(hl2, "MFI Source", group="Histogram", inline='MFI') int mfiLengthInputHistogram = input.int(55, minval=1, title="MFI Length", group="Histogram", inline='MFI') int stochLongLenHistogram = input.int(55, minval=1, title="TSI Long Length", group=GRP_HISTOGRAM, inline='TSI') int stochShortLenHistogram = input.int(8, minval=1, title="TSI Short Length", group=GRP_HISTOGRAM, inline='TSI') int stochSigLenHistogram = input.int(8, minval=1, title="Signal Length", group=GRP_HISTOGRAM, inline='Signal') int maTypeTSIHistogram = input.int(defval=2, title='Type of Smoothing (TSI)', options=[1, 2, 3, 4, 5, 6, 7, 8, 9], tooltip=TYPE_MA_TOOLTIP, group=GRP_HISTOGRAM, inline='Smooth1') int maTypeSignalHistogram = input.int(defval=2, title='Type of Smoothing (Signal)', options=[1, 2, 3, 4, 5, 6, 7, 8, 9], tooltip=TYPE_MA_TOOLTIP, group=GRP_HISTOGRAM, inline='Smooth2') // #endregion // #region Theme for TSI var string GRP_THEME_TSI = 'Theme for TSI' int themeStoch_1 = input.int(defval=10, title='Theme', options=[ 1, // User defined 2, // User defined with gradient 10, 11, 12, 13, 14, 15, // Spectrum Blue-Green-Red 20, 21, // Monokai 30, 31, // Spectrum White-Green-Red 40, 41, // Green-Purple 50, 51, // Blue-Red 60, 61, // Blue-Yellow 70, 71, // Green-Red 80, 81, // Green 90, 91, // Purple 100, 101, 102, 103, 104, 105, 106, 107, // Blue 120, 121, 122, 123, // Blue-Aqua 130, 131, 132, 133, 134, 135, 136, 137, // Blue-Green 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, // Red 160, 161, 162, 163, 164, 165, // Red-Yellow 170, 171, // Red-White 180, 181, 182, 183, 184, 185, // White-Black 190, 191 // Spectrum Blue-Red ], inline='61', group=GRP_THEME_TSI, tooltip=THEME_TOOLTIP) color colorUpStoch_1 = input.color(color.blue, title='Bull', group=GRP_THEME_TSI, inline='61') color colorDownStoch_1 = input.color(color.rgb(255, 0, 0), title='Bear', group=GRP_THEME_TSI, inline='61') int transparencyStoch_1 = input.int(0, minval=0, maxval=100, inline='62', title='Transparency', group=GRP_THEME_TSI) // #endregion // #region Theme for Stoch Signal var string GRP_THEME_SIGNAL = 'Theme for Signal' int themeStoch_2 = input.int(defval=1, title='Theme', options=[ 1, // User defined 2, // User defined with gradient 10, 11, 12, 13, 14, 15, // Spectrum Blue-Green-Red 20, 21, // Monokai 30, 31, // Spectrum White-Green-Red 40, 41, // Green-Purple 50, 51, // Blue-Red 60, 61, // Blue-Yellow 70, 71, // Green-Red 80, 81, // Green 90, 91, // Purple 100, 101, 102, 103, 104, 105, 106, 107, // Blue 120, 121, 122, 123, // Blue-Aqua 130, 131, 132, 133, 134, 135, 136, 137, // Blue-Green 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, // Red 160, 161, 162, 163, 164, 165, // Red-Yellow 170, 171, // Red-White 180, 181, 182, 183, 184, 185, // White-Black 190, 191 // Spectrum Blue-Red ], inline='63', group=GRP_THEME_SIGNAL, tooltip=THEME_TOOLTIP) color colorUpStoch_2 = input.color(color.blue, title='Bull', group=GRP_THEME_SIGNAL, inline='63') color colorDownStoch_2 = input.color(color.rgb(255, 0, 0), title='Bear', group=GRP_THEME_SIGNAL, inline='63') int transparencyStoch_2 = input.int(0, minval=0, maxval=100, inline='64', title='Transparency', group=GRP_THEME_SIGNAL) int transparencyStoch_3 = input.int(30, minval=0, maxval=100, inline='64', title='Transparency for fill', group=GRP_THEME_SIGNAL, tooltip=TRANSPARENCY_TOOLTIP) // #endregion // #region Theme for Histogram above 0 var string GRP_THEME_HISTOGRAM_ABOVE = 'Theme for Histogram above 0' int themeHistoP = input.int(defval=100, title='Theme', options=[ 1, // User defined 2, // User defined with gradient 10, 11, 12, 13, 14, 15, // Spectrum Blue-Green-Red 20, 21, // Monokai 30, 31, // Spectrum White-Green-Red 40, 41, // Green-Purple 50, 51, // Blue-Red 60, 61, // Blue-Yellow 70, 71, // Green-Red 80, 81, // Green 90, 91, // Purple 100, 101, 102, 103, 104, 105, 106, 107, // Blue 120, 121, 122, 123, // Blue-Aqua 130, 131, 132, 133, 134, 135, 136, 137, // Blue-Green 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, // Red 160, 161, 162, 163, 164, 165, // Red-Yellow 170, 171, // Red-White 180, 181, 182, 183, 184, 185, // White-Black 190, 191 // Spectrum Blue-Red ], inline='1', group='Theme for Histogram above 0', tooltip=THEME_TOOLTIP) int transparencyHistogramUp = input.int(0, minval=0, maxval=100, inline='1', title='Transparency', group=GRP_THEME_HISTOGRAM_ABOVE) color colorHistogramUp_1 = input.color(color.new(#1c3bfb, 0), "", inline="2", group=GRP_THEME_HISTOGRAM_ABOVE) color colorHistogramUp_2 = input.color(color.new(#2855fc, 0), "", inline="2", group=GRP_THEME_HISTOGRAM_ABOVE) color colorHistogramUp_3 = input.color(color.new(#346ffd, 0), "", inline="2", group=GRP_THEME_HISTOGRAM_ABOVE) color colorHistogramUp_4 = input.color(color.new(#4078fe, 0), "", inline="2", group=GRP_THEME_HISTOGRAM_ABOVE) color colorHistogramUp_5 = input.color(color.new(#5b9bf9, 0), "", inline="2", group=GRP_THEME_HISTOGRAM_ABOVE) color colorHistogramUp_6 = input.color(color.new(#72b6fc, 0), "", inline="2", group=GRP_THEME_HISTOGRAM_ABOVE) // #endregion // #region Theme for Histogram below 0 var string GRP_THEME_HISTOGRAM_BELOW = 'Theme for Histogram below 0' int themeHistoN = input.int(defval=140, title='Theme', options=[ 1, // User defined 2, // User defined with gradient 10, 11, 12, 13, 14, 15, // Spectrum Blue-Green-Red 20, 21, // Monokai 30, 31, // Spectrum White-Green-Red 40, 41, // Green-Purple 50, 51, // Blue-Red 60, 61, // Blue-Yellow 70, 71, // Green-Red 80, 81, // Green 90, 91, // Purple 100, 101, 102, 103, 104, 105, 106, 107, // Blue 120, 121, 122, 123, // Blue-Aqua 130, 131, 132, 133, 134, 135, 136, 137, // Blue-Green 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, // Red 160, 161, 162, 163, 164, 165, // Red-Yellow 170, 171, // Red-White 180, 181, 182, 183, 184, 185, // White-Black 190, 191 // Spectrum Blue-Red ], inline='1', group='Theme for Histogram below 0') int transparencyHistogramDown = input.int(0, minval=0, maxval=100, inline='1', title='Transparency', group=GRP_THEME_HISTOGRAM_BELOW) color colorHistogramDown_1 = input.color(color.rgb(255, 0, 0), "", inline="2", group=GRP_THEME_HISTOGRAM_BELOW) color colorHistogramDown_2 = input.color(color.rgb(255, 30, 30), "", inline="2", group=GRP_THEME_HISTOGRAM_BELOW) color colorHistogramDown_3 = input.color(color.rgb(255, 60, 60), "", inline="2", group=GRP_THEME_HISTOGRAM_BELOW) color colorHistogramDown_4 = input.color(color.rgb(255, 90, 90), "", inline="2", group=GRP_THEME_HISTOGRAM_BELOW) color colorHistogramDown_5 = input.color(color.rgb(255, 120, 120), "", inline="2", group=GRP_THEME_HISTOGRAM_BELOW) color colorHistogramDown_6 = input.color(color.rgb(255, 150, 150), "", inline="2", group=GRP_THEME_HISTOGRAM_BELOW) // #endregion // #region Dynamic Zone var string GRP_DZ = 'Dynamic Zones' int dataSmple = input.int(defval=200, title="Sample Length", minval=1, group=GRP_DZ, inline='1') float pcntAbove = input.float(defval=90, title="High is Above X% of Sample", minval=0, maxval=100, step=1.0, group=GRP_DZ, inline='2') float pcntBelow = input.float(defval=90, title="Low is Below X% of Sample", minval=0, maxval=100, step=1.0, group=GRP_DZ, inline='2') color lineDzoneTop = input.color(#7e58c0, 'Upper Line of Dynamic Zone', inline='3', group=GRP_DZ) color lineDzoneBottom = input.color(#7e58c0, 'Lower Line of Dynamic Zone', inline='3', group=GRP_DZ) color fillDzoneAbove = input.color(color.new(#3064fc, 50), 'Fill outside of DZone when above', inline='4', group=GRP_DZ) color fillDzoneAbove2 = input.color(color.new(#3064fc, 80), 'Fill entire chart when above', inline='4', group=GRP_DZ) color fillDzoneInside = input.color(color.new(#7e58c0, 100), 'Dynamic Zone', inline='5', group=GRP_DZ) color fillDzoneBelow = input.color(color.new(#3064fc, 50), 'Fill outside of DZone when below', inline='6', group=GRP_DZ) color fillDzoneBelow2 = input.color(color.new(#f03449, 80), 'Fill entire chart when below', inline='6', group=GRP_DZ) var string centerLineOptA = 'Center of Dynamic Zone (x = 50%)' var string centerLineOptB = '50' string centerLine = input.string(defval=centerLineOptA, title='Center Line', options=[centerLineOptA, centerLineOptB], group=GRP_DZ, inline='7') color lineDzoneCenter = input.color(color.new(color.gray, 0), 'Center Line', inline='7', group=GRP_DZ) int lineDzoneCenterDensity = input.int(defval=2, title='Density', options=[1, 2, 3, 4, 5], inline='7', group=GRP_DZ, tooltip='Density for line.\n' + '1 = 100% density (continuous line)\n' + '2 = Dotted line flashing every 2 bars\n' + '3 = Dotted line flashing every 3 bars\n' + '4 = Dotted line flashing every 4 bars\n' + '5 = Dotted line flashing every 5 bars') // #endregion // #region Cross Alerts 1 var string CROSS_ALERTS_1 = 'Cross Alerts 1' string showAlerts1 = input.string(title='Show alerts for cross?', defval='Show alerts with shape', options=['Don\'t show alerts', 'Show alerts with char', 'Show alerts with shape'], group=CROSS_ALERTS_1, inline='A') color colorAlertBull1 = input.color(color.new(#14e024, 0), title='Bull', group=CROSS_ALERTS_1, inline='B') color colorAlertBear1 = input.color(color.new(#ff0000, 0), title='Bear', group=CROSS_ALERTS_1, inline='B') float topAlertLine1 = input.float(-100, title='Above', inline='B', group=CROSS_ALERTS_1, minval=-100, maxval=100) float bottomAlertLine1 = input.float(100, title='Below', inline='B', group=CROSS_ALERTS_1, minval=-100, maxval=100, tooltip='Alerts at the cross between the Oscillator and the Signal.\n\n' + '🔻 Above: cross under alert will only appear when the oscillator is above this level.\n\n' + '🔺 Below : Cross over alert will only appear when the oscillator is below this level.\n\n' + 'To show alerts for all intersections, put the maximum values within the limits:\n' + '-100 for Above and 100 for Below') bool onlyOutsideDZ = input.bool(true, title='Only outside DZ?', group=CROSS_ALERTS_1, inline='O', tooltip='Only alerts when the cross occurs outside the Dynamic Zone') bool showBarColorsCross1 = input.bool(true, title='Colorize bars?', group=CROSS_ALERTS_1, inline='C') color colorBarSignal1 = input.color(color.new(#ffffff, 0), title='', group=CROSS_ALERTS_1, inline='C') // #endregion // #region Cross Alerts 2 var string CROSS_ALERTS_2 = 'Cross Alerts 2' string showAlerts2 = input.string(title='Show alerts for cross?', defval='Show alerts with shape', options=['Don\'t show alerts', 'Show alerts with char', 'Show alerts with shape'], group=CROSS_ALERTS_2, inline='A') color colorAlertBull2 = input.color(color.new(#2962ff, 0), title='Bull', group=CROSS_ALERTS_2, inline='B') color colorAlertBear2 = input.color(color.new(color.orange, 0), title='Bear', group=CROSS_ALERTS_2, inline='B') float topAlertLine2 = input.float(-100, title='Above', inline='B', group=CROSS_ALERTS_2, minval=-100, maxval=100) float bottomAlertLine2 = input.float(100, title='Below', inline='B', group=CROSS_ALERTS_2, minval=-100, maxval=100, tooltip='Alerts at the cross between the Oscillator and the Signal.\n\n' + '🔻 Above: cross under alert will only appear when the oscillator is above this level.\n\n' + '🔺 Below : Cross over alert will only appear when the oscillator is below this level.\n\n' + 'To show alerts for all intersections, put the maximum values within the limits:\n' + '-100 for Above and 100 for Below') bool onlyInsideDZ = input.bool(true, title='Only inside DZ?', group=CROSS_ALERTS_2, inline='I', tooltip='Only alerts when the cross occurs within the Dynamic Zone') bool showBarColorsCross2 = input.bool(false, title='Colorize bars?', group=CROSS_ALERTS_2, inline='C') color colorBarSignal2 = input.color(color.new(color.yellow, 0), title='', group=CROSS_ALERTS_2, inline='C') // #endregion // #region Trend Alerts var string TREND_ALERTS = 'Trend Alerts' bool showBarColorsTrendHisto = input.bool(true, title='Colorize bars for histogram?', group=TREND_ALERTS, inline='A') color colorBarTrendBullHisto = input.color(color.new(color.blue, 0), title='', group=TREND_ALERTS, inline='A') color colorBarTrendBearHisto = input.color(color.new(#ff1000, 0), title='', group=TREND_ALERTS, inline='A', tooltip='When Histogram above or below 0') bool barColorsTrendHistoTheme = input.bool(true, title='Use same theme of Histogram?', group=TREND_ALERTS, inline='B', tooltip='Only applies when the above checkbox is checked') bool showBarColorsTrendTSI = input.bool(false, title='Colorize bars for TSI?', group=TREND_ALERTS, inline='C') color colorBarTrendBullTSI = input.color(color.new(color.blue, 0), title='', group=TREND_ALERTS, inline='C') color colorBarTrendBearTSI = input.color(color.new(#ff1000, 0), title='', group=TREND_ALERTS, inline='C', tooltip='When TSI above or below Signal') bool barColorsTrendTsiTheme = input.bool(false, title='Use same theme of TSI?', group=TREND_ALERTS, inline='D', tooltip='Only applies when the above checkbox is checked') bool showBarColorsTrendSignal = input.bool(false, title='Colorize bars for Signal?', group=TREND_ALERTS, inline='E') color colorBarTrendBullSignal = input.color(color.new(color.blue, 0), title='', group=TREND_ALERTS, inline='E') color colorBarTrendBearSignal = input.color(color.new(#ff1000, 0), title='', group=TREND_ALERTS, inline='E', tooltip='When Signal above or below TSI') bool barColorsTrendSignalTheme = input.bool(false, title='Use same theme of Signal?', group=TREND_ALERTS, inline='F', tooltip='Only applies when the above checkbox is checked') // #endregion // #region Custom Levels for TSI\'s Theme int level1TSI = input.int(defval=5, title="Level 1", minval=0, maxval=100, group='Custom Levels for TSI\'s Theme', inline='1') int level2TSI = input.int(defval=10, title="Level 2", minval=0, maxval=100, group='Custom Levels for TSI\'s Theme', inline='1') int level3TSI = input.int(defval=30, title="Level 3", minval=0, maxval=100, group='Custom Levels for TSI\'s Theme', inline='1') int level4TSI = input.int(defval=50, title="Level 4", minval=0, maxval=100, group='Custom Levels for TSI\'s Theme', inline='2') int level5TSI = input.int(defval=70, title="Level 5", minval=0, maxval=100, group='Custom Levels for TSI\'s Theme', inline='2') // #endregion // #region Custom Levels for TSI\'s Gradient Theme float levelTSIgrB = input.float(defval=-50, title="Bottom position ", minval=-100, maxval=100, group='Custom Levels for TSI\'s Gradient Theme (26)', inline='3') float levelTSIgrT = input.float(defval=50, title="Top position", minval=-100, maxval=100, group='Custom Levels for TSI\'s Gradient Theme (26)', inline='3') // #endregion // #region Custom Levels for Signal\'s Theme int level1Signal = input.int(defval=5, title="Level 1", minval=0, maxval=100, group='Custom Levels for Signal\'s Theme', inline='1') int level2Signal = input.int(defval=10, title="Level 2", minval=0, maxval=100, group='Custom Levels for Signal\'s Theme', inline='1') int level3Signal = input.int(defval=30, title="Level 3", minval=0, maxval=100, group='Custom Levels for Signal\'s Theme', inline='1') int level4Signal = input.int(defval=50, title="Level 4", minval=0, maxval=100, group='Custom Levels for Signal\'s Theme', inline='2') int level5Signal = input.int(defval=70, title="Level 5", minval=0, maxval=100, group='Custom Levels for Signal\'s Theme', inline='2') // #endregion // #region Custom Levels for Signal\'s Gradient Theme float levelSignalgrB = input.float(defval=-50, title="Bottom position ", minval=-100, maxval=100, group='Custom Levels for Signal\'s Gradient Theme (26)', inline='3') float levelSignalgrT = input.float(defval=50, title="Top position", minval=-100, maxval=100, group='Custom Levels for Signal\'s Gradient Theme (26)', inline='3') // #endregion // #region Custom Levels for Histogram\'s Theme int level1Histogram = input.int(defval=6, title="Level 1", minval=0, maxval=100, group='Custom Levels for Histogram\'s Theme', inline='1') int level2Histogram = input.int(defval=12, title="Level 2", minval=0, maxval=100, group='Custom Levels for Histogram\'s Theme', inline='1') int level3Histogram = input.int(defval=18, title="Level 3", minval=0, maxval=100, group='Custom Levels for Histogram\'s Theme', inline='1') int level4Histogram = input.int(defval=24, title="Level 4", minval=0, maxval=100, group='Custom Levels for Histogram\'s Theme', inline='2') int level5Histogram = input.int(defval=30, title="Level 5", minval=0, maxval=100, group='Custom Levels for Histogram\'s Theme', inline='2') // #endregion // #region Alert Messages bool showMsgAlert_1 = input.bool(false, title='TSI crossing above Signal when within limits (alert 1)', group='Alert Messages', tooltip="Crossing considering the levels defined in the 'Cross Alerts' section, alert 1") bool showMsgAlert_2 = input.bool(false, title='TSI crossing below the Signal when within limits (alert 1)', group='Alert Messages', tooltip="Crossing considering the levels defined in the 'Cross Alerts' section, alert 1") bool showMsgAlert_3 = input.bool(false, title='TSI exiting the Dynamic Zone at the top', group='Alert Messages') bool showMsgAlert_4 = input.bool(false, title='TSI entering the Dynamic Zone at the top', group='Alert Messages') bool showMsgAlert_5 = input.bool(false, title='TSI exiting the Dynamic Zone at the bottom', group='Alert Messages') bool showMsgAlert_6 = input.bool(false, title='TSI entering the Dynamic Zone at the bottom', group='Alert Messages') bool showMsgAlert_7 = input.bool(false, title='TSI crossing above the centerline', group='Alert Messages') bool showMsgAlert_8 = input.bool(false, title='TSI crossing below the centerline', group='Alert Messages') bool showMsgAlert_9 = input.bool(false, title='TSI crossing above Signal when within limits (alert 2)', group='Alert Messages', tooltip="Crossing considering the levels defined in the 'Cross Alerts' section, alert 2") bool showMsgAlert_10 = input.bool(false, title='TSI crossing below the Signal when within limits (alert 2)', group='Alert Messages', tooltip="Crossing considering the levels defined in the 'Cross Alerts' section, alert 2") // #endregion // #region Trend Lines with Breakout var string G_TRENDLINES = 'Trend Lines with Breakout' bool input_showLines = input.bool(defval = false, title = 'Show Trend Lines', group = G_TRENDLINES, inline='0') string sourceTrendLine = input.string(defval = 'TSI', title = 'Source for Trend Lines', options = ['Histogram', 'TSI'], group = G_TRENDLINES) int input_pLen = input.int(defval = 8, title = 'Lookback Range', minval = 1, group = G_TRENDLINES, tooltip = 'How many bars to determine when a swing high/low is detected.') int input_tsiDiff = input.int(defval = 3, title = 'Difference', group = G_TRENDLINES, tooltip = 'The difference between the current Oscillator value and the breakout value.\n\nHow much higher in value should the current Oscillator be compared to the breakout value in order to detect a breakout?') int input_width = input.int(defval = 2, title = 'Line Width', minval = 1, group = G_TRENDLINES) string input_lblType = input.string(defval = 'Simple', title = 'Label Type', group = G_TRENDLINES, options = ['Full', 'Simple']) string input_lblSize = input.string(defval = size.small, title = 'Label Size', group = G_TRENDLINES, options = [size.huge, size.large, size.normal, size.small, size.tiny]) color input_pLowCol = input.color(defval = #ff1000, title = 'Pivot Low', inline = 'col', group = G_TRENDLINES) color input_pHighCol = input.color(defval = #14e024, title = 'Pivot High', inline = 'col', group = G_TRENDLINES) bool input_override = input.bool(defval = false, title = 'Override Text Color', group = G_TRENDLINES, inline = 'override') color input_overCol = input.color(defval = color.white, title = ' ', group = G_TRENDLINES, inline = 'override') // #endregion // #region Divergence Detector sourceDivergence = input.string(defval='TSI', title='Source for Divergence', options=['Histogram', 'TSI'], group='Divergence Detector', inline='0') lbR = input.int(title="Pivot Lookback Right", defval=13, group="Divergence Detector", inline="1") lbL = input.int(title="Pivot Lookback Left", defval=13, group="Divergence Detector", inline="1") rangeUpper = input.int(title="Max of Lookback Range", defval=60, group="Divergence Detector", inline="2") rangeLower = input.int(title="Min of Lookback Range", defval=8, group="Divergence Detector", inline="2") plotBull = input.bool(title="Plot Bullish", defval=false, group="Divergence Detector", inline="3") bullColor = input.color(title="", defval=#14e024, group="Divergence Detector", inline="3") plotHiddenBull = input.bool(title="Plot Hidden Bullish", defval=false, group="Divergence Detector", inline="4") hiddenBullColor = input.color(title="", defval=#2962ff, group="Divergence Detector", inline="4") plotBear = input.bool(title="Plot Bearish", defval=false, group="Divergence Detector", inline="5") bearColor = input.color(title="", defval=#ff1000, group="Divergence Detector", inline="5") plotHiddenBear = input.bool(title="Plot Hidden Bearish", defval=false, group="Divergence Detector", inline="6") hiddenBearColor = input.color(title="", defval=color.orange, group="Divergence Detector", inline="6") textColor = input.color(title="Text Color", defval=color.rgb(0, 0, 0), group="Divergence Detector", inline="7") // #endregion // #endregion // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— } // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— { // #region Calculations // Repaint or Not Repaint // Credits: // How to avoid repainting when using security() - PineCoders FAQ // https://www.tradingview.com/script/cyPWY96u-How-to-avoid-repainting-when-using-security-PineCoders-FAQ/ f_security(_symbol, _res, _src, _repaint) => request.security(_symbol, _res, _src[_repaint ? 0 : barstate.isrealtime ? 1 : 0])[_repaint ? 0 : barstate.isrealtime ? 0 : 1] // SMI of MFI float _mfiSourceInput = f_security(syminfo.tickerid, (useTimeFrame ? timeframe : timeframe.period), mfiSourceInput, repaint) [tsi, signal, _histogram] = MI.smiMFI(source=_mfiSourceInput, length=mfiLengthInput, shortLengthTSI=stochShortLen, longLengthTSI=stochLongLen, maTypeTSI=maTypeTSI, maTypeSignal=maTypeSignal, smoothingLengthSignal=stochSigLen) // Histogram float _mfiSourceInputHistogram = f_security(syminfo.tickerid, (useTimeFrame ? timeframe : timeframe.period), mfiSourceInputHistogram, repaint) [_tsi, _signal, histogram] = MI.smiMFI(source=_mfiSourceInputHistogram, length=mfiLengthInputHistogram, shortLengthTSI=stochShortLenHistogram, longLengthTSI=stochLongLenHistogram, maTypeTSI=maTypeTSIHistogram, maTypeSignal=maTypeSignalHistogram, smoothingLengthSignal=stochSigLenHistogram) histogram *= lenMultiplier // Dynamic Zones float dZoneAbove = ta.percentile_nearest_rank(tsi, dataSmple, pcntAbove) float dZoneBelow = ta.percentile_nearest_rank(tsi, dataSmple, 100 - pcntBelow) float dZoneCenter = ta.percentile_nearest_rank(tsi, dataSmple, 100 - 50) // #endregion // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— } // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— { // #region Theme for Histogram color colorHistogram = if (histogram >= 0) if (themeHistoP == 1) // User defined vcHistogramUp = UTIL.valueColorSpectrum.new() UTIL.setCustomLevels(vcHistogramUp, level1Histogram, level2Histogram, level3Histogram, level4Histogram, level5Histogram) UTIL.setTheme(vcHistogramUp, colorHistogramUp_1, colorHistogramUp_2, colorHistogramUp_3, colorHistogramUp_4, colorHistogramUp_5, colorHistogramUp_6) vcHistogramUp.currentValue := histogram vcHistogramUp.previousValue := histogram[1] UTIL.setCurrentColorValue(vcHistogramUp) vcHistogramUp.currentColorValue else if (themeHistoP == 2) // User defined with gradient vcHistogramUp = UTIL.valueColor.new() vcHistogramUp.currentValue := histogram vcHistogramUp.previousValue := histogram[1] vcHistogramUp.colorUp := colorHistogramUp_1 vcHistogramUp.colorDown := colorHistogramUp_6 UTIL.setCurrentColorValue(vcHistogramUp, true, 0, level5Histogram) vcHistogramUp.currentColorValue else // Theme with predefined colors vcHistogramUp = UTIL.valueColorSpectrum.new() UTIL.setCustomLevels(vcHistogramUp, level1Histogram, level2Histogram, level3Histogram, level4Histogram, level5Histogram) UTIL.setTheme(vcHistogramUp, themeHistoP) vcHistogramUp.currentValue := histogram vcHistogramUp.previousValue := histogram[1] UTIL.setCurrentColorValue(vcHistogramUp) vcHistogramUp.currentColorValue else if (themeHistoN == 1) // User defined vcHistogramDown = UTIL.valueColorSpectrum.new() UTIL.setCustomLevels(vcHistogramDown, level1Histogram, level2Histogram, level3Histogram, level4Histogram, level5Histogram) UTIL.setTheme(vcHistogramDown, colorHistogramDown_1, colorHistogramDown_2, colorHistogramDown_3, colorHistogramDown_4, colorHistogramDown_5, colorHistogramDown_6) vcHistogramDown.currentValue := histogram vcHistogramDown.previousValue := histogram[1] UTIL.setCurrentColorValue(vcHistogramDown) vcHistogramDown.currentColorValue else if (themeHistoN == 2) // User defined with gradient vcHistogramDown = UTIL.valueColor.new() vcHistogramDown.currentValue := math.abs(histogram) vcHistogramDown.previousValue := math.abs(histogram[1]) vcHistogramDown.colorUp := colorHistogramDown_1 vcHistogramDown.colorDown := colorHistogramDown_6 UTIL.setCurrentColorValue(vcHistogramDown, true, 0, level5Histogram) vcHistogramDown.currentColorValue else // Theme with predefined colors vcHistogramDown = UTIL.valueColorSpectrum.new() UTIL.setCustomLevels(vcHistogramDown, level1Histogram, level2Histogram, level3Histogram, level4Histogram, level5Histogram) UTIL.setTheme(vcHistogramDown, themeHistoN) vcHistogramDown.currentValue := histogram vcHistogramDown.previousValue := histogram[1] UTIL.setCurrentColorValue(vcHistogramDown) vcHistogramDown.currentColorValue // #endregion // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— } // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— { // #region Theme for Oscillator color colorStoch = if (themeStoch_1 >= 3) // Theme with 5 colors vcOscillator = UTIL.valueColorSpectrum.new() UTIL.setCustomLevels(vcOscillator, level1TSI, level2TSI, level3TSI, level4TSI, level5TSI) vcOscillator.currentValue := tsi vcOscillator.previousValue := tsi[1] UTIL.setTheme(vcOscillator, themeStoch_1) UTIL.setCurrentColorValue(vcOscillator) color.new(vcOscillator.currentColorValue, transparencyStoch_1) else // Theme with 2 colors ('User defined' or 'User defined with gradient') vcOscillator = UTIL.valueColor.new() vcOscillator.currentValue := tsi vcOscillator.previousValue := tsi[1] vcOscillator.colorUp := colorUpStoch_1 vcOscillator.colorDown := colorDownStoch_1 UTIL.setCurrentColorValue(vcOscillator, (themeStoch_1 == 2), levelTSIgrB, levelTSIgrT) color.new(vcOscillator.currentColorValue, transparencyStoch_1) // #endregion // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— } // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— { // #region Theme for Signal color colorMaStoch = if (themeStoch_2 >= 3) // Theme with 5 colors vcSignal = UTIL.valueColorSpectrum.new() UTIL.setCustomLevels(vcSignal, level1Signal, level2Signal, level3Signal, level4Signal, level5Signal) vcSignal.currentValue := signal vcSignal.previousValue := signal[1] UTIL.setTheme(vcSignal, themeStoch_2) UTIL.setCurrentColorValue(vcSignal) color.new(vcSignal.currentColorValue, transparencyStoch_2) else // Theme with 2 colors ('User defined' or 'User defined with gradient') vcSignal = UTIL.valueColor.new() vcSignal.currentValue := signal vcSignal.previousValue := signal[1] vcSignal.colorUp := colorUpStoch_2 vcSignal.colorDown := colorDownStoch_2 UTIL.setCurrentColorValue(vcSignal, (themeStoch_2 == 2), levelSignalgrB, levelSignalgrT) color.new(vcSignal.currentColorValue, transparencyStoch_2) // #endregion // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— } // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— { // #region Theme for fill between Oscillator and Signal color colorFill = if (themeStoch_2 >= 3) // Theme with 5 colors vcFillOscillator = UTIL.valueColorSpectrum.new() UTIL.setCustomLevels(vcFillOscillator, level1Signal, level2Signal, level3Signal, level4Signal, level5Signal) vcFillOscillator.currentValue := tsi vcFillOscillator.previousValue := signal UTIL.setTheme(vcFillOscillator, themeStoch_2) UTIL.setCurrentColorValue(vcFillOscillator) color.new(vcFillOscillator.currentColorValue, transparencyStoch_3) else // Theme with 2 colors ('User defined' or 'User defined with gradient') vcFillOscillator = UTIL.valueColor.new() vcFillOscillator.currentValue := tsi vcFillOscillator.previousValue := signal vcFillOscillator.colorUp := colorUpStoch_2 vcFillOscillator.colorDown := colorDownStoch_2 UTIL.setCurrentColorValue(vcFillOscillator, (themeStoch_2 == 2), levelSignalgrB, levelSignalgrT) color.new(vcFillOscillator.currentColorValue, transparencyStoch_3) // #endregion // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— } // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— { // #region Plots // #region Histogram plot(histogram, color=color.new(colorHistogram, histogram >= 0 ? transparencyHistogramUp : transparencyHistogramDown), style=plot.style_histogram, title="SMI Ergodic Histogram") // #endregion // #region Stoch p_tsi = plot(tsi, title="TSI", color=colorStoch, linewidth=2) p_signal = plot(signal, title="Signal", color=colorMaStoch) fill(p_tsi, p_signal, color=colorFill, title='Fill beetween Stoch and Signal', display=(transparencyStoch_3 < 100 ? display.all : display.none) ) // #endregion // #region Dynamic Zones hline(0, color = lineDzoneCenter, title="Fixed Center Line", linewidth=1, linestyle=hline.style_dashed, display=(centerLine==centerLineOptB ? display.all : display.none)) plot(dZoneCenter, title="Dynamic Zone: Center Line", color=UTIL.getPeriodicColor(lineDzoneCenter, lineDzoneCenterDensity), linewidth=1, style=plot.style_line, display=(centerLine==centerLineOptA ? display.all : display.none)) above = plot(tsi > dZoneAbove ? tsi : dZoneAbove, title = "", color = color(na)) probOB = plot(dZoneAbove, title = "Dynamic Zone: Top Line", color = lineDzoneTop, linewidth=1) probOS = plot(dZoneBelow, title = "Dynamic Zone: Bottom Line", color = lineDzoneBottom, linewidth=1) below = plot(tsi < dZoneBelow ? tsi : dZoneBelow, title = "", color = color(na)) fill(above, probOB, color = fillDzoneAbove) fill(probOB, probOS, color = fillDzoneInside) fill(below, probOS, color = fillDzoneBelow) top = hline(100, "Top", color=color.red, linestyle=hline.style_solid, display=display.none) bottom = hline(-100, "Bottom", color=color.blue, linestyle=hline.style_solid, display=display.none) fill(top, bottom, tsi < dZoneBelow ? fillDzoneBelow2 : na, 'Fill background when below Dynamic Zone', display=display.all) fill(top, bottom, tsi > dZoneAbove ? fillDzoneAbove2 : na, 'Fill background when above Dynamic Zone', display=display.all) // #endregion // #endregion // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— } // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— { // #region Trend Alerts _barcolor = (showBarColorsTrendHisto and (histogram >= 0) ? (barColorsTrendHistoTheme ? colorHistogram : colorBarTrendBullHisto) : na) _barcolor := (showBarColorsTrendHisto and (histogram < 0) ? (barColorsTrendHistoTheme ? colorHistogram : colorBarTrendBearHisto) : _barcolor) _barcolor := (showBarColorsTrendTSI and (tsi >= signal) ? (barColorsTrendTsiTheme ? colorStoch : colorBarTrendBullTSI) : _barcolor) _barcolor := (showBarColorsTrendTSI and (tsi < signal) ? (barColorsTrendTsiTheme ? colorStoch : colorBarTrendBearTSI) : _barcolor) _barcolor := (showBarColorsTrendSignal and (tsi >= signal) ? (barColorsTrendSignalTheme ? colorMaStoch : colorBarTrendBullSignal) : _barcolor) _barcolor := (showBarColorsTrendSignal and (tsi < signal) ? (barColorsTrendSignalTheme ? colorMaStoch : colorBarTrendBearSignal) : _barcolor) // #endregion // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— } // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— { // #region Cross Alerts // Cross Alerts 1 tsiOutside = if onlyOutsideDZ (tsi[1] < dZoneBelow or tsi[1] > dZoneAbove) else true bool crossUp1 = (tsi[1] <= bottomAlertLine1) and tsiOutside and ta.crossover(tsi, signal) bool crossDown1 = (tsi[1] >= topAlertLine1) and tsiOutside and ta.crossunder(tsi, signal) plotchar(showAlerts1 == 'Show alerts with char' ? crossUp1 : na, title="[Alert 1] Crossing up char", char='↑', location=location.bottom, color=colorAlertBull1, size=size.small, offset=0) plotchar(showAlerts1 == 'Show alerts with char' ? crossDown1 : na, title="[Alert 1] Crossing down char",char='↓', location=location.top, color=colorAlertBear1, size=size.small, offset=0) plotshape(showAlerts1 == 'Show alerts with shape' and crossUp1 ? signal : na, title="[Alert 1] Crossing up shape", location=location.bottom, style=shape.circle, size=size.tiny, color=colorAlertBull1, offset=0) plotshape(showAlerts1 == 'Show alerts with shape' and crossDown1 ? signal : na, title="[Alert 1] Crossing down shape", location=location.top, style=shape.circle, size=size.tiny, color=colorAlertBear1, offset=0) _barcolor := (showBarColorsCross1 and (crossUp1 or crossDown1) ? colorBarSignal1 : _barcolor) // Cross Alerts 2 tsiInside = if onlyInsideDZ (tsi[1] >= dZoneBelow and tsi[1] <= dZoneAbove) else true bool crossUp2 = (tsi[1] <= bottomAlertLine2) and tsiInside and ta.crossover(tsi, signal) bool crossDown2 = (tsi[1] >= topAlertLine2) and tsiInside and ta.crossunder(tsi, signal) plotchar(showAlerts2 == 'Show alerts with char' ? crossUp2 : na, title="[Alert 2] Crossing up char", char='↑', location=location.bottom, color=colorAlertBull2, size=size.small, offset=0) plotchar(showAlerts2 == 'Show alerts with char' ? crossDown2 : na, title="[Alert 2] Crossing down char",char='↓', location=location.top, color=colorAlertBear2, size=size.small, offset=0) plotshape(showAlerts2 == 'Show alerts with shape' and crossUp2 ? signal : na, title="[Alert 2] Crossing up shape", location=location.bottom, style=shape.diamond, size=size.tiny, color=colorAlertBull2, offset=0) plotshape(showAlerts2 == 'Show alerts with shape' and crossDown2 ? signal : na, title="[Alert 2] Crossing down shape", location=location.top, style=shape.diamond, size=size.tiny, color=colorAlertBear2, offset=0) _barcolor := (showBarColorsCross2 and (crossUp2 or crossDown2) ? colorBarSignal2 : _barcolor) // barcolor(_barcolor) // #endregion // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— } // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— { // #region Alert variables // Dynamic Zone: Top bool tsiExitingDynamicZoneTop = ta.crossover(tsi, dZoneAbove) bool tsiEnteringDynamicZoneTop = ta.crossunder(tsi, dZoneAbove) // Dynamic Zone: Bottom bool tsiExitingDynamicZoneBottom = ta.crossunder(tsi, dZoneBelow) bool tsiEnteringDynamicZoneBottom = ta.crossover(tsi, dZoneBelow) // Dynamic Zone: Center bool tsiCrossOverCentral = ta.crossover(tsi, dZoneCenter) bool tsiCrossUnderCentral = ta.crossunder(tsi, dZoneCenter) // #endregion // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— } // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— { // #region Alert Conditions // The alert() function is the most recent addition to Pine Script™. // It more or less supersedes alertcondition(), and when used in strategies, provides a useful complement to alerts on order fill events. // [...] // The alertcondition() function remains in Pine Script™ for backward compatibility, but it can also be used advantageously // to generate distinct alerts available for selection as individual items in the “Create Alert” dialog box’s “Condition” field. // #region TSI crossover\crossunder Signal // alertcondition(crossUp1, title="TSI crossing above Signal when within limits (alert 1)", // message="TSI crossed above the Signal.\nSymbol: {{ticker}}\nPrice: {{close}}") // alertcondition(crossDown1, title="TSI crossing below the Signal when within limits (alert 1)", // message="TSI crossed below the Signal.\nSymbol: {{ticker}}\nPrice: {{close}}") // alertcondition(crossUp2, title="TSI crossing above Signal when within limits (alert 2)", // message="TSI crossed above the Signal.\nSymbol: {{ticker}}\nPrice: {{close}}") // alertcondition(crossDown2, title="TSI crossing below the Signal when within limits (alert 2)", // message="TSI crossed below the Signal.\nSymbol: {{ticker}}\nPrice: {{close}}") // // #endregion // #region Dynamic Zone: Top // alertcondition(tsiExitingDynamicZoneTop, title="TSI exiting the Dynamic Zone at the top", // message="TSI exiting the Dynamic Zone at the top.\nSymbol: {{ticker}}\nPrice: {{close}}") // alertcondition(tsiEnteringDynamicZoneTop, title="TSI entering the Dynamic Zone at the top", // message="TSI entering the Dynamic Zone at the top.\nSymbol: {{ticker}}\nPrice: {{close}}") // #endregion // #region Dynamic Zone: Bottom // alertcondition(tsiExitingDynamicZoneBottom, title="TSI exiting the Dynamic Zone at the bottom", // message="TSI exiting the Dynamic Zone at the bottom.\nSymbol: {{ticker}}\nPrice: {{close}}") // alertcondition(tsiEnteringDynamicZoneBottom, title="TSI entering the Dynamic Zone at the bottom", // message="TSI entering the Dynamic Zone at the bottom.\nSymbol: {{ticker}}\nPrice: {{close}}") // #endregion // #region Dynamic Zone: Center // alertcondition(tsiCrossOverCentral, title="TSI crossing above the centerline", // message="TSI crossing above the centerline.\nSymbol: {{ticker}}\nPrice: {{close}}") // alertcondition(tsiCrossUnderCentral, title="TSI crossing below the centerline", // message="TSI crossing below the centerline.\nSymbol: {{ticker}}\nPrice: {{close}}") // #endregion // #endregion // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— } // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— { // #region Alert Messages // #region TSI crossover\crossunder Signal if showMsgAlert_1 and crossUp1 alert("TSI crossing above Signal within limits " + str.tostring(bottomAlertLine1) + " and " + str.tostring(topAlertLine1) + ".\n" + "TSI value: " + str.tostring(tsi, "#.##") + "\n" + "Price: " + str.tostring(close)) if showMsgAlert_2 and crossDown1 alert("TSI crossing below Signal within limits " + str.tostring(bottomAlertLine1) + " and " + str.tostring(topAlertLine1) + ".\n" + "TSI value: " + str.tostring(tsi, "#.##") + "\n" + "Price: " + str.tostring(close)) if showMsgAlert_9 and crossUp2 alert("TSI crossing above Signal within limits " + str.tostring(bottomAlertLine2) + " and " + str.tostring(topAlertLine2) + ".\n" + "TSI value: " + str.tostring(tsi, "#.##") + "\n" + "Price: " + str.tostring(close)) if showMsgAlert_10 and crossDown2 alert("TSI crossing below Signal within limits " + str.tostring(bottomAlertLine2) + " and " + str.tostring(topAlertLine2) + ".\n" + "TSI value: " + str.tostring(tsi, "#.##") + "\n" + "Price: " + str.tostring(close)) // #endregion // #region Dynamic Zone: Top if showMsgAlert_3 and tsiExitingDynamicZoneTop alert("TSI exiting the Dynamic Zone at the top.\n" + "TSI value: " + str.tostring(tsi, "#.##") + "\n" + "Price: " + str.tostring(close)) if showMsgAlert_4 and tsiEnteringDynamicZoneTop alert("TSI entering the Dynamic Zone at the top.\n" + "TSI value: " + str.tostring(tsi, "#.##") + "\n" + "Price: " + str.tostring(close)) // #endregion // #region Dynamic Zone: Bottom if showMsgAlert_5 and tsiExitingDynamicZoneBottom alert("TSI exiting the Dynamic Zone at the bottom.\n" + "TSI value: " + str.tostring(tsi, "#.##") + "\n" + "Price: " + str.tostring(close)) if showMsgAlert_6 and tsiEnteringDynamicZoneBottom alert("TSI entering the Dynamic Zone at the bottom.\n" + "TSI value: " + str.tostring(tsi, "#.##") + "\n" + "Price: " + str.tostring(close)) // #endregion // #region Dynamic Zone: Center if showMsgAlert_7 and tsiCrossOverCentral alert("TSI crossing above the centerline.\n" + "TSI value: " + str.tostring(tsi, "#.##") + "\n" + "Price: " + str.tostring(close)) if showMsgAlert_8 and tsiCrossUnderCentral alert("TSI crossing below the centerline.\n" + "TSI value: " + str.tostring(tsi, "#.##") + "\n" + "Price: " + str.tostring(close)) // #endregion // #endregion // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— } // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— { // #region Trend Lines with Breakout srcTrendLine = (sourceTrendLine == 'Histogram' ? histogram : tsi) lblText = switch input_lblType 'Simple' => 'Br' 'Full' => 'Break' pl = fixnan(ta.pivotlow(srcTrendLine, 1, input_pLen)) ph = fixnan(ta.pivothigh(srcTrendLine, 1, input_pLen)) pivot(float pType) => pivot = pType == pl ? pl : ph xAxis = ta.valuewhen(ta.change(pivot), bar_index, 0) - ta.valuewhen(ta.change(pivot), bar_index, 1) prevPivot = ta.valuewhen(ta.change(pivot), pivot, 1) pivotCond = ta.change(pivot) and (pType == pl ? pivot > prevPivot : pivot < prevPivot) pData = TL.new(x_axis = xAxis, offset = input_pLen, strictMode = true, strictType = pType == pl ? 0 : 1) if input_showLines pData.drawLine(pivotCond, prevPivot, pivot, srcTrendLine) pData breakout(TL.Trendline this, float pType) => var bool hasCrossed = false if ta.change(this.lines.startline.get_y1()) hasCrossed := false if input_showLines this.drawTrendline(not hasCrossed) condType = (pType == pl ? srcTrendLine < this.lines.trendline.get_y2() - input_tsiDiff : srcTrendLine > this.lines.trendline.get_y2() + input_tsiDiff) and not hasCrossed if condType and input_showLines hasCrossed := true this.lines.startline.set_xy2(this.lines.trendline.get_x2(), this.lines.trendline.get_y2()) this.lines.trendline.set_xy2(na, na) this.lines.startline.copy() label.new( bar_index, this.lines.startline.get_y2(), text = lblText, color = pType == pl ? color.new(input_pLowCol, 50) : color.new(input_pHighCol, 50), size = input_lblSize, style = pType == pl ? label.style_label_lower_left : label.style_label_upper_left, textcolor = pType == pl ? (input_override ? input_overCol : input_pLowCol) : input_override ? input_overCol : input_pHighCol ) hasCrossed method style(TL.Trendline this, color col) => this.lines.startline.set_color(col) this.lines.startline.set_width(input_width) this.lines.trendline.set_color(col) this.lines.trendline.set_width(input_width) this.lines.trendline.set_style(line.style_dashed) plData = pivot(pl) phData = pivot(ph) plData.style(input_pLowCol) phData.style(input_pHighCol) cu = breakout(plData, pl) co = breakout(phData, ph) alertcondition(ta.change(plData.lines.startline.get_y1()), 'New Pivot Low Trendline') alertcondition(ta.change(cu) and cu, 'Pivot Low Breakout') alertcondition(ta.change(phData.lines.startline.get_y1()), 'New Pivot High Trendline') alertcondition(ta.change(co) and co, 'Pivot High Breakout') // #endregion // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— } // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— { // #region Divergence Detector var color NONE_COLOR = color.new(color.white, 100) // Oscillator for divergence osc = sourceDivergence == 'TSI' ? tsi : histogram plFound = na(ta.pivotlow(osc, lbL, lbR)) ? false : true phFound = na(ta.pivothigh(osc, lbL, lbR)) ? false : true _inRange(cond) => bars = ta.barssince(cond == true) rangeLower <= bars and bars <= rangeUpper //------------------------------------------------------------------------------ // Regular Bullish // Osc: Higher Low oscHL = osc[lbR] > ta.valuewhen(plFound, osc[lbR], 1) and _inRange(plFound[1]) // Price: Lower Low priceLL = low[lbR] < ta.valuewhen(plFound, low[lbR], 1) bullCond = plotBull and priceLL and oscHL and plFound plot( plFound ? osc[lbR] : na, offset=-lbR, title="Regular Bullish", linewidth=2, color=(bullCond ? bullColor : NONE_COLOR) ) plotshape( bullCond ? osc[lbR] : na, offset=-lbR, title="Regular Bullish Label", text=" Bull ", style=shape.labelup, location=location.absolute, color=bullColor, textcolor=textColor ) //------------------------------------------------------------------------------ // Hidden Bullish // Osc: Lower Low oscLL = osc[lbR] < ta.valuewhen(plFound, osc[lbR], 1) and _inRange(plFound[1]) // Price: Higher Low priceHL = low[lbR] > ta.valuewhen(plFound, low[lbR], 1) hiddenBullCond = plotHiddenBull and priceHL and oscLL and plFound plot( plFound ? osc[lbR] : na, offset=-lbR, title="Hidden Bullish", linewidth=2, color=(hiddenBullCond ? hiddenBullColor : NONE_COLOR) ) plotshape( hiddenBullCond ? osc[lbR] : na, offset=-lbR, title="Hidden Bullish Label", text=" H Bull ", style=shape.labelup, location=location.absolute, color=hiddenBullColor, textcolor=textColor ) //------------------------------------------------------------------------------ // Regular Bearish // Osc: Lower High oscLH = osc[lbR] < ta.valuewhen(phFound, osc[lbR], 1) and _inRange(phFound[1]) // Price: Higher High priceHH = high[lbR] > ta.valuewhen(phFound, high[lbR], 1) bearCond = plotBear and priceHH and oscLH and phFound plot( phFound ? osc[lbR] : na, offset=-lbR, title="Regular Bearish", linewidth=2, color=(bearCond ? bearColor : NONE_COLOR) ) plotshape( bearCond ? osc[lbR] : na, offset=-lbR, title="Regular Bearish Label", text=" Bear ", style=shape.labeldown, location=location.absolute, color=bearColor, textcolor=textColor ) //------------------------------------------------------------------------------ // Hidden Bearish // Osc: Higher High oscHH = osc[lbR] > ta.valuewhen(phFound, osc[lbR], 1) and _inRange(phFound[1]) // Price: Lower High priceLH = high[lbR] < ta.valuewhen(phFound, high[lbR], 1) hiddenBearCond = plotHiddenBear and priceLH and oscHH and phFound plot( phFound ? osc[lbR] : na, offset=-lbR, title="Hidden Bearish", linewidth=2, color=(hiddenBearCond ? hiddenBearColor : NONE_COLOR) ) plotshape( hiddenBearCond ? osc[lbR] : na, offset=-lbR, title="Hidden Bearish Label", text=" H Bear ", style=shape.labeldown, location=location.absolute, color=hiddenBearColor, textcolor=textColor ) // #endregion // ———————————————————————————————————————————————————————————————————————————————————————————————————————————— } plot(crossUp1 ? 1 : crossDown1 ? 2 : 0 , "SMI MFI cross 1")