TRENDESPRESSO


Professional Python, PineScript, and JavaScript coder.
Full-time espresso fanatic and part-time trader.

contact@trendespresso.com



Below is a (nearly) exhaustive list of PineScript Financial Analysis Indicators I've made. Feel free to visit any individual indicator by clicking on the title. A coder at heart, I've lifted some of my favorite passages and put them on this page hoping to inspire and educate any one else interested in trading, PineScript, or general coding. To talk trading, coding, or all things coffee, join my Discord!


TE A (Affogato)

Automated trading made easy.
Seamlessly webhook your trading style.
Use with TE SW to check historical results.
Based on Supertrend (additional filtering added).

// FUNCTION: Determine if the given Trend Line has an uptrend, downtrend, or no trend
f_uptrend_dntrend ( _trend_line, _tsi, _tsi_signal, _volatility, _sidechain1_line, _sidechain2_line, _sidechain3_line, _sidechain4_line, _trend_state, _strong_state, _tsi_state, _slopes_state, _trend_count, _candle_count1, _candle_count2, _candle_count3, _crossover_state, _recent_highs, _recent_lows ) =>
    _trend_line_change      = f_pct_change ( _trend_line )
    _tsi_change             = f_pct_change ( _tsi )
    _price_distance_away    = ( ( ohlc4_HA - _trend_line ) / _trend_line ) * 100
    _count1_out             = f_calculate_candle_count ( _trend_line,       _candle_count1 )
    _count2_out             = f_calculate_candle_count ( _sidechain1_line,  _candle_count2 )
    _count3_out             = f_calculate_candle_count ( _sidechain2_line,  _candle_count3 )
    
    _bearish_crossover =     _sidechain1_line    < _trend_line
                     and     _sidechain4_line    > _trend_line
                     and     _sidechain4_line    < _sidechain3_line
                     and ( ( _sidechain3_line    > _trend_line
                     and     _sidechain3_line[1] < _trend_line[1] )
                     or    ( _sidechain3_line    < _sidechain3_line[1]
                     and     _trend_line         < _trend_line[1] ) )

    _bullish_crossover =     _sidechain1_line    > _trend_line
                     and     _sidechain4_line    < _trend_line
                     and     _sidechain4_line    > _sidechain3_line
                     and ( ( _sidechain3_line    < _trend_line
                     and     _sidechain3_line[1] > _trend_line[1] )
                     or    ( _sidechain3_line    > _sidechain3_line[1]
                     and     _trend_line         > _trend_line[1] ) )
    
    _crossover = _bearish_crossover ? -1 : _bullish_crossover ? 1 : nz ( _crossover_state )
    
    _sidechn1  = f_calculate_trend_conditions ( _sidechain1_line,   _count2_out,             1,            5,            10, _trend_line_change, _price_distance_away, _recent_highs, _recent_lows )
    _conds_met = f_calculate_trend_conditions ( _trend_line,        _count1_out, i_min_candles, i_min_change, i_min_farAway, _trend_line_change, _price_distance_away, _recent_highs, _recent_lows ) +
                 f_calculate_trend_conditions ( _sidechain2_line,   _count3_out,             1,            5,            10, _trend_line_change, _price_distance_away, _recent_highs, _recent_lows ) +
                 ( _crossover > 0 ? 2 : _crossover < 0 ? -2 : 0 ) + _sidechn1
    
    _conds_required  = open_HA > keltner_upper or open_HA < keltner_lower ? i_total_conds - 2 : i_total_conds
    _trend_count_out = _conds_met >= _conds_required      ? nz ( _trend_count ) + 1 :
                       _conds_met <= _conds_required * -1 ? nz ( _trend_count ) - 1 : 0

    _tsi_condition = _tsi > -10 and _tsi[1] < -10 and f_continuous_slope ( _tsi, ">", -30, -1 ) and _tsi > _tsi_signal ?  1 :
                     _tsi <  10 and _tsi[1] >  10 and f_continuous_slope ( _tsi, "<",  30, -1 ) and _tsi < _tsi_signal ? -1 :
                     _tsi >  25 and _tsi > _tsi_signal ?  1 :
                     _tsi < -25 and _tsi < _tsi_signal ? -1 :
                     _tsi_state > 0 and _tsi < 0 ? 0 :
                     _tsi_state < 0 and _tsi > 0 ? 0 :
                     nz ( _tsi_state )
    
    _slopes_are_up  = _tsi > _tsi[1] and _tsi > _tsi_signal
    _slopes_are_dn  = _tsi < _tsi[1] and _tsi < _tsi_signal
    varip _midbound =   0
    varip _hi_alert =  25
    varip _lo_alert = -25
    varip _vol_limi =  65
    
    if _slopes_are_up
        tmp_cnt_up        = 0
        tmp_cnt_up       += _tsi_signal > _tsi_signal[1] ? 1 : 0
        tmp_cnt_up       += _tsi        < _hi_alert      ? 1 : 0
        tmp_cnt_up       += _tsi_signal > _midbound      ? 1 : 0
        _slopes_are_up   := _volatility < _vol_limi      ?  ( _tsi > _midbound or
                             f_continuous_slope ( _tsi, "up", _tsi[ barssince ( divFind_bullCond ) + divFind_lbR ], barssince ( divFind_bullCond ) + divFind_lbR ) )
                             and tmp_cnt_up >= 2 : tmp_cnt_up >= 1
    
    if _slopes_are_dn
        tmp_cnt_dn        = 0
        tmp_cnt_dn       -= _tsi_signal < _tsi_signal[1] ? 1 : 0
        tmp_cnt_dn       -= _tsi        > _lo_alert      ? 1 : 0
        tmp_cnt_dn       -= _tsi_signal < _midbound      ? 1 : 0
        _slopes_are_dn   := _volatility < _vol_limi      ? ( _tsi < _midbound or
                             f_continuous_slope ( _tsi, "dn", _tsi[ barssince ( divFind_bearCond ) + divFind_lbR ], barssince ( divFind_bearCond ) + divFind_lbR ) )
                             and tmp_cnt_dn <= -2 : tmp_cnt_dn <= -1
    
    _slopes_condition     = _slopes_are_up ? 1 : _slopes_are_dn ? -1 : nz ( _slopes_state )
    
    
    
    breakout_L            = high_HA > _trend_line and close_HA > _recent_highs
    breakout_S            = low_HA  < _trend_line and close_HA < _recent_lows
    
    _uptrend = ( ( _trend_state and ( _tsi_condition > 0 or _slopes_are_up ) ) or ( ( _slopes_are_up or _crossover > 0 ) and _trend_count_out >= i_min_range      ) or breakout_L or breakout_L[1] ) and _sidechn1 > -2 and _sidechn1[1] > -2 and _trend_line_change > -0.1
    _dntrend = ( ( _trend_state and ( _tsi_condition < 0 or _slopes_are_dn ) ) or ( ( _slopes_are_dn or _crossover < 0 ) and _trend_count_out <= i_min_range * -1 ) or breakout_S or breakout_S[1] ) and _sidechn1 <  2 and _sidechn1[1] <  2 and _trend_line_change <  0.1
    _trend_condition = _uptrend ? 1 : _dntrend ? -1 : 0
    
    varip _strong_trend_num_back = 5
    varip _bad_threshold         = 2
    _strong_trend_condition      = nz ( _strong_state )
    
    if _trend_line_change > 0 and price_change > 0 and _strong_trend_condition <= 0
        bad_count = 0
        for i = 1 to _strong_trend_num_back
            if i == _strong_trend_num_back
                _strong_trend_condition :=  1
            if _trend_line[i] > _trend_line[i + 1] and low_HA[i] > keltner_upper[i] and _tsi_signal[i] < _tsi[i] and _uptrend
                continue
            else
                bad_count += 1
                if bad_count >= _bad_threshold
                    if _strong_trend_condition >= 0
                        _strong_trend_condition := 0
                    break
                else
                    continue
    else if _trend_line_change < 0 and price_change < 0 and _strong_trend_condition >= 0
        bad_count = 0
        for i = 1 to _strong_trend_num_back
            if i == _strong_trend_num_back
                _strong_trend_condition := -1
            if _trend_line[i] < _trend_line[i + 1] and high_HA[i] < keltner_lower[i] and _tsi_signal[i] > _tsi[i] and _dntrend
                continue
            else
                bad_count += 1
                if bad_count >= _bad_threshold
                    if _strong_trend_condition <= 0
                        _strong_trend_condition := 0
                    break
                else
                    continue
    
    if ( _strong_trend_condition > 0 and _tsi_condition <= 0 and _trend_count_out <= 0 and _tsi_change <= 0 and price_change <= 0 ) or
      ( _strong_trend_condition < 0 and _tsi_condition >= 0 and _trend_count_out >= 0 and _tsi_change >= 0 and price_change >= 0 )
        _strong_trend_condition := 0
    
    if      _strong_trend_condition > 0 and ( _tsi_signal > _tsi and ( _trend_line_change < -0.03 or ( price_change < -0.15 and ( low_HA  < keltner_lower or open_HA < _trend_line ) ) ) )
        _strong_trend_condition := 0
    else if _strong_trend_condition < 0 and ( _tsi_signal < _tsi and ( _trend_line_change >  0.03 or ( price_change >  0.15 and ( high_HA > keltner_upper or open_HA > _trend_line ) ) ) )
        _strong_trend_condition := 0
    
    // condition = 1 Uptrend, -1 Downtrend, or 0 no trend
    // counts = number of candles that do not touch the given moving average
    [ _trend_condition, _strong_trend_condition, _tsi_condition, _slopes_condition, _trend_count_out, _count1_out, _count2_out, _count3_out, _crossover ]


for i = 0 to ( num_lines - 1 )
    _B = array.get ( arr_trend_line,    i )
    _C = array.get ( arr_tsi_line,      i )
    _D = array.get ( arr_tsi_sig_line,  i )
    _E = array.get ( arr_volatility,    i )
    _F = array.get ( arr_sideLine1,     i )
    _G = array.get ( arr_sideLine2,     i )
    _H = array.get ( arr_sideLine3,     i )
    _I = array.get ( arr_sideLine4,     i )
    _J = array.get ( arr_trend_state,   i )
    _K = array.get ( arr_strong_state,  i )
    _L = array.get ( arr_tsi_state,     i )
    _M = array.get ( arr_slopes_state,  i )
    _N = array.get ( arr_trend_count,   i )
    _O = array.get ( arr_candle_count1, i )
    _P = array.get ( arr_candle_count2, i )
    _Q = array.get ( arr_candle_count3, i )
    _R = array.get ( arr_crossovers,    i )
    _S = highest ( 10 )[1] * 1.05
    _T = lowest  ( 10 )[1] * 0.95
    [ _f, _g, _h, _i, _j, _k, _l, _m, _r ]
     = f_uptrend_dntrend ( _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T )
    array.set ( arr_trend_state,   i, _f )
    array.set ( arr_strong_state,  i, _g )
    array.set ( arr_tsi_state,     i, _h )
    array.set ( arr_slopes_state,  i, _i )
    array.set ( arr_trend_count,   i, _j )
    array.set ( arr_candle_count1, i, _k )
    array.set ( arr_candle_count2, i, _l )
    array.set ( arr_candle_count3, i, _m )
    array.set ( arr_crossovers,    i, _r )

strong_state = array.get ( arr_strong_state, 0 )
tsi_state    = array.get ( arr_tsi_state,    0 )
calc_state   = array.get ( arr_trend_state,  0 )
		


TE B (Breva)

Manual trading made fantastic.
Navigate choppy markets with confidence.

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
///
// if you want to reach me and I do not respond on TradingView, google my username/
// /
// I also have other private Indicators I'm always working on/
// Feel free to reach out to me here or via the Trendespresso website for info and links!/
///
// All comments, bugfixes, and suggestions welcome :)/
///
// © trendespresso/
//@version=4/

varip ver_num               = "4.7"
varip script_long_ver       = "v" + ver_num
varip script_short_ver      =       ver_num
varip script_abrev          = "TE B"
varip script_long_title     = "Trendespresso Breva" + " [ " + script_long_ver + " ]"
varip script_short_title    = script_abrev          + " [ " + script_short_ver + " ]"




study ( script_long_title, script_short_title, true, max_bars_back = 600, max_lines_count = 140, max_labels_count = 35, explicit_plot_zorder = true )




/////////////////////////////////////////////////////////////////////////////////
// VERSION + DEBUG

varip version               = script_long_ver + "\nPublished October 2, 2021\nby Trendespresso"

//
// Variables in Pine v4:
//
//      Writing a variable in global scope without 'var' or 'varip' will force
//      the variable to be continously recalcuated in realtime.
//
//      Writing a variable within a function will only update the variable when
//      the function is called. Using global variable names within a function
//      will not work since Pine will grab the value of the global variable.
//      However variables initialized and used within a function are local scope
//      only meaning they cannot be accessed in global scope unless passed out
//      of the function via return. Multiple variables can be returned from a
//      function via tuple: [ return1, return2 ] = function ( arg1, arg2 )
//      The number of returned variables and number of arguments need not match
//      with a function. Also of note is that the 'security' call in Pine is
//      technically a function and thus multiple variables can be returned
//      via tuple from a single 'security call' – pretty cool!
//
//      Writing a variable in global scope with 'var' permits the variable to
//      maintain its value across bars until an update is issues (ex. := or += )
//
//      Writing a variable in global scope with 'varip' forces the variable to
//      maintain its value across bars. Updating the variable in any later bar
//      will not affect a variable initialized with 'varip' for any future bar.
//
//      Common sense thus suggests that variables should be initialized without
//      'var' or 'varip' if you desire them to be updated on every bar. Variables
//      should be initialized with 'var' if you desire them to be updated
//      occasionally but hold their value between changes; this setting thus assists
//      in reducing runtime and system resources since the variable is not
//      typically re-calculated on every bar. Lastly, variables should only be
//      initialized with 'varip' if you desire them to retain their value across
//      the entire script with no re-calculating required going forward; this
//      setting greatly reduces runtime since variables are only calculated once.
//      I've tried to write thie script to take advantage of these runtime
//      reductions, especially since every 'security' call – every additional
//      timeframe – results in immense increases in runtime and system resources.
//      Anything I can do to increase efficiency is good in my book!
//
//      Also of note, most text and string variables are initialized with 'varip'
//      since they do not change across bars. Pretty nifty especially if you want
//      to change the text! Instead of using 'Replace All' which sometimes has
//      unintended consequences, or trying to find each instance yourself which
//      is a total pain, now the text is easily changeable from one place.
//

//
// If you find this script helpful, educational, or otherwise engaging, please
// leave a comment or drop me a line! Cheers
//




//
// COLORS
//

varip color_bull            = color.new ( #0097A7,  0 )
varip color_bear            = color.new ( #D16A00,  0 )
varip color_faded_bull      = color.new ( color_bull, 47 )
varip color_faded_bear      = color.new ( color_bear, 47 )
varip color_bg_bull         = color.new ( color_bull, 93 )
varip color_bg_bear         = color.new ( color_bear, 93 )
varip color_neutral         = color.gray

varip c_lime                = color.new ( color.lime, 50 )
varip c_red                 = color.new ( color.red,  50 )
varip c_gray                = color.new ( color.gray, 50 )

varip green                 = color.new ( #388e3c, 0 )
varip red                   = color.new ( #d32f2f, 0 )
varip orange                = color.new ( #C66909, 0 )
varip teal                  = color.new ( #178793 ,0 )

varip darkGreen             = color.new ( green, 40 )
varip darkRed               = color.new ( red, 40 )
varip darkOrange            = color.new ( orange, 40 )

varip transparentGreen      = color.new ( green, 80 )
varip transparentRed        = color.new ( red, 80 )
varip transparentOrange     = color.new ( orange, 80 )

varip color_none            = color.new ( #2a2e39,  100 )
varip color_off             = color.new ( color.white, 100 )

varip groupGlobal           = "Global"
varip groupData             = "Data Parameters"
varip groupTrend            = "Trend Line"
varip groupKeltner          = "Keltner Channel"
varip groupLabel            = "Trend Line Label"
varip groupConditions       = "Conditions Label"
varip groupBB               = "Bollinger Bands"
varip groupAlerts           = "Combined Alerts"
varip groupTP               = "Take Profit"
varip groupTSI              = "True Strength Index"
varip groupPivots           = "Pivots"
varip str_supres            = "Support & Resistance"
varip groupSupRes           = groupPivots + " | " + str_supres
varip groupPOC              = "Point of Control"
varip groupVP               = "Volume Profile"
varip str_TSI               = "TSI"
varip str_TSI_Signal        = "TSI Signal"
varip str_Momentum          = "Momentum"
varip str_exit              = "Exit"
varip str_SL                = "Stop Loss"
varip str_TP                = "Take Profit"
varip str_triangle          = "Triangle"
varip str_entry             = "Entry"
varip str_supertrend        = "Supertrend"
varip str_strat             = "Strategy"
varip groupStrat            = str_strat + " (" + str_supertrend + ")"
varip groupStratPct         = str_strat + " (" + str_TP + " & " + str_SL + ")"
varip groupStratFilt        = str_strat + " (Filtering)"
varip groupStratIcons       = "On-Chart Volatility"
varip groupStratTest        = str_strat + " Tester"



//
// ALERT TEXT
//
varip str_long              = "Long"
varip str_shrt              = "Short"

varip str_pivot_high        = "High Pivot"
varip str_pivot_low         = "Low Pivot"

varip alert_prefix          = "{{ticker}} {{interval}} "
varip str_sep               = ": "

varip str_uptrend           = "Uptrend"
varip str_dntrend           = "Downtrend"
varip str_aboveKC           = "Above KC"
varip str_belowKC           = "Below KC"
varip str_BBsqueeze         = groupBB + " are squeezed"

varip str_enter_long        = str_strat + " " + str_long + " " + str_entry
varip str_enter_short       = str_strat + " " + str_shrt + " " + str_entry
varip str_exit_long         = str_strat + " " + str_long + " " + str_exit
varip str_exit_short        = str_strat + " " + str_shrt + " " + str_exit
varip str_TP_long           = str_strat + " " + str_long + " " + groupTP
varip str_TP_short          = str_strat + " " + str_shrt + " " + groupTP

varip alert_enter_long      = script_abrev + str_sep + str_enter_long
varip alert_enter_short     = script_abrev + str_sep + str_enter_short
varip alert_SL_L            = script_abrev + str_sep + str_exit_long
varip alert_SL_S            = script_abrev + str_sep + str_exit_short
varip alert_tpStrat_L       = script_abrev + str_sep + str_TP_long
varip alert_tpStrat_S       = script_abrev + str_sep + str_TP_short
varip alert_uptrend         = script_abrev + str_sep + str_uptrend
varip alert_dntrend         = script_abrev + str_sep + str_dntrend
varip alert_strong_up       = script_abrev + str_sep + "Strong " + str_uptrend
varip alert_strong_dn       = script_abrev + str_sep + "Strong " + str_dntrend
varip alert_above_kc        = script_abrev + str_sep + str_aboveKC
varip alert_below_kc        = script_abrev + str_sep + str_belowKC
varip alert_tp_long         = script_abrev + str_sep + groupTP + " (" + str_long  + ")"
varip alert_tp_short        = script_abrev + str_sep + groupTP + " (" + str_shrt + ")"
varip alert_BB_squeeze      = script_abrev + str_sep + str_BBsqueeze



//
// STATIC TEXT
//
varip str_spc               = " "
varip str_none              = "None"
varip str_usr               = "User"
varip str_lbl               = "Label"
varip str_enable            = "ENABLE"
varip str_disable           = "DISABLE"

varip str_price             = "Price"
varip str_pct               = "Percent"
varip str_1000s_k           = "Show 1000's as 'k'"
varip str_txt               = "Text"
varip str_offset            = "Offset"
varip str_ext_len           = "Extension Length"

varip str_solid             = "Solid"
varip str_dotted            = "Dotted"
varip str_dashed            = "Dashed"

varip lbl_pct_tt            = "Distance in percentage to Price."

varip str_up                = "Up"
varip str_down              = "Down"
varip str_left              = "Left"
varip str_center            = "Center"
varip str_right             = "Right"
varip str_tiny              = "Tiny"
varip str_small             = "Small"
varip str_normal            = "Normal"
varip str_large             = "Large"
varip str_huge              = "Huge"
varip str_upper             = "Lower"
varip str_lower             = "Upper"


/////////////////////////////////////////////////////////////////////////////////
// RIBBON

varip str_ema   = "EMA"
varip str_hma   = "HMA"
varip str_sma   = "SMA"
varip str_wma   = "WMA"
varip str_alma  = "ALMA"
varip str_vwma  = "VWMA"

varip str_trnd1 = "Display Trend"
varip str_trn1S = groupTrend // "Disp Trend"
varip str_trnd2 = "Sidechain 1"
varip str_trnd3 = "Sidechain 2"
varip str_trnd4 = groupTrend // "Calc Trend"
varip str_color = "Line Colors"

varip conds_tt  = "There are four total conditions\nto establish or continue a given\nTrend.\n\nThis is the number of total\nconditions between all lines\nrequired to add color\nto the primary Trend."
varip trend1_tt = "Trend is established if this\nnumber of candles are fully\nabove or below the Trend\n without any touches."
varip trend2_tt = "Trend is established if this\nnumber of trend line ticks\nare continously in one direction."
varip trend3_tt = "Trend continues if this\nchange measured in 0.01%'s\ntakes place between any two candles."
varip trend4_tt = "Trend is established or\ncontinues if `ohlc4` is this\nfar away from the Trend,\nmeasured in 0.01%'s."

varip str_checklist     = "Checklist Conditions"
varip str_tri_tt        = "Do not blindly trade\nthe triangles!\n\nIncorporate your own\ntechnical analysis\nand market structure\nunderstanding."
varip str_checklist_tt  = "When enabled, the indicator\nattempts to apply the checklist\nconditions to the L / S triangles.\n\nOtherwise, the indicator inspects\nonly Trend Line conditions."

varip SL_tight  = "Opposing Candle"
varip SL_KC     = "Keltner (Blue Cloud)"
varip SL_methods_tt = SL_tight +":\nIf any candle closes completely\non the opposite side of the Entr\ncandle, print an X exit signal." + "\n\n" +
                      SL_KC + ":\nIf any candle closes outside the\nopposite side of the " + groupKeltner + ".\n\n" +
                      str_checklist + ":\nShow using the " + str_checklist + "."
varip str_use_native_tt = "Changes the data used from\nHeikin Ashi candles to data\nfrom the currently selected\nChart Style (ex. Regular Candles).\n\n" +
                      "Disabling this option means the\nindicator will work very differently\ndepending on the current Chart Style.\n\n" +
                      "Enabling this option will still return\naccurate and reliable backtest data\nin the Strategy Tester.\n\n" +
                      "Indicators = Use Heikin Ashi candle\ndata for the indicators such as\nthe " + script_abrev + str_spc + str_supertrend +
                      "\nor the " + groupTrend + ".\n\n" +
                      "Price Action = Use Open, High,\nLow, and Close prices from\nHeikin Ashi candles."

varip str_txt_color_bull    = string ( na )
varip str_txt_color_bear    = string ( na )
varip str_txt_color_tt      = " Bull Text Color | Bear Text Color"

varip str_tri_trnd = "Trend line used for\ninternal calculations, such\nas signals and coloration.\n\nSelecting 'None' will use the\nTrend Line selection below\nfor internal calculations."





///////////////////////////////////////////////////////////////////////////////
// master timeframe and data grab

varip str_ext_data  = "External Data"
varip str_NT        = "Native"
varip str_HA        = "Heikin Ashi"
varip str_RN        = "Renko"
varip str_LB        = "Line Break"
varip str_KG        = "Kagi"
varip str_PF        = "Point Figure"
varip str_ATR       = "ATR"
varip str_Trad      = "Traditional"

varip ext_pri       = str_HA + " (Price Action)"
varip ext_ind       = str_HA + " (Indicators)"
varip str_full      = "Full"
varip str_exch_tt   = "Leave blank to disable.\n\nOverride the current chart's" +
                      "\nexchange with the given.\n\nMust be in all caps." +
                      "\n\nYou may also write in\na full ticker as well\n" +
                      "to use as a data source\nif you enable '" + str_full + "'.\nEx: COINBASE:BTCUSD"

i_trendespresso_tf  = input (     '',   "Master Timeframe", input.resolution,   group = groupGlobal, tooltip = version )
i_HA_prices         = input (   false,  ext_pri ,           input.bool,         group = groupGlobal, tooltip = str_use_native_tt ) // , options = [ str_NT, str_HA, str_RN, str_LB, str_KG, str_PF ] )
i_HA_data           = input (   true,   ext_ind,            input.bool,         group = groupGlobal, tooltip = str_use_native_tt ) // , options = [ str_NT, str_HA, str_RN, str_LB, str_KG, str_PF ] )
i_alt_exchange      = input ( 'COINBASE',   "Ticker Override",      input.string,       group = groupGlobal, tooltip = str_exch_tt, inline = str_exch_tt )
i_alt_exchange_bool = input (      false,   str_full,               input.bool,         group = groupGlobal, tooltip = str_exch_tt, inline = str_exch_tt )



varip timeframe     = ( i_trendespresso_tf == string ( na ) or i_trendespresso_tf == '' ) ? timeframe.period : i_trendespresso_tf
varip ticker        = i_alt_exchange_bool                              ? i_alt_exchange   :
                      i_alt_exchange == '' or syminfo.type != 'crypto' ? syminfo.tickerid :
                      i_alt_exchange + ":" + syminfo.basecurrency + 'USD'



varip str_clratn    = "Color Method"
varip str_col1      = "Trend Analysis"
varip str_col2      = "MA Crossover"
varip str_wide_kc   = "Wide Keltner Channel"
varip str_crs_ma1   = "Bull Signal MA"
varip str_crs_ma2   = "Bear Signal MA"
varip str_clratn_tt = "Color the Trend Line\ndepending on the\nselected method.\n\nDefault is '" + str_col1 +
                      "'\nwith other options listed.\nMA Crossover colors the line\ndepending on which moving\naverage has a greater value." +
                      "\n\nNote:\nMoving Averages from different\ntimeframes may be implemented\nvia timeframe multiplier:\n4 x 15 = 60m = 1h\n50-Bar 1h EMA ≈ 200-Bar 15m EMA" +
                      "\n\nWarning:\nSelecting '" + str_col1 + "' will\nresult in different Entry, Exit,\nStop Loss, and Take Profit\nsignals since it overrides\nthe Calc Trend analysis\nfor uptrends and downtrends."

varip str_TFil1     = "Trend Filtering"
varip trf1_tt       = "Copies the 'Trend Line'\ncoloration method.\nOnly looks for Longs\nwhen the " + str_trnd4 + "\nis colored bullish (teal)\nand only looks for Shorts\nwhen colored bearish\n(orange). '" +
                       str_col2 + "' uses\nthe '" + str_crs_ma1 + "' &\n'" + str_crs_ma2 + "' options.\n\nSelecting '" + str_none + 
                       "' simply uses\nthe slope of the line to\ndetermine color."

i_ma_input1calc     = input ( str_wma,      str_trn1S,          input.string,                   group = groupTrend, inline = str_trnd1, tooltip = "Displayed\nTE A Trend Line", options = [ str_ema, str_hma, str_sma, str_wma, str_alma, str_vwma, str_none ] )
i_ma_input1         = input (     18 ,      string ( na ),      input.integer,                  group = groupTrend, inline = str_trnd1, minval = 1 )

i_sTrend1           = input ( str_col1,     str_TFil1,          input.string,                   group = groupTrend, tooltip = trf1_tt,      inline = str_TFil1,     options = [ str_col1, str_col2, str_none ] )

i_crossover_ma1_c   = input ( str_none,     str_crs_ma1,        input.string,                   group = groupTrend,                         inline = str_crs_ma1,   options = [ str_ema, str_hma, str_sma, str_wma, str_alma, str_vwma, str_none ] )
i_crossover_ma1_l   = input (      1  ,     string ( na ),      input.integer,  minval = 1,     group = groupTrend,                         inline = str_crs_ma1 )
i_crossover_ma2_c   = input ( str_none,     str_crs_ma2,        input.string,                   group = groupTrend,                         inline = str_crs_ma2,   options = [ str_ema, str_hma, str_sma, str_wma, str_alma, str_vwma, str_none ] )
i_crossover_ma2_l   = input (      1  ,     string ( na ),      input.integer,  minval = 1,     group = groupTrend,                         inline = str_crs_ma2 )





/////////////////////////////////////////////////////////////////////////////////
// TREND LINE LABEL

varip MA_tf_tt      = "Hover your mouse cursor over\nthe Moving Average label to\nsee the exact price for that\nMoving Average and the distance\nin percentage to current price."
varip lbl_chg_tt    = "Change of Trend line value\nfrom the previous tick.\nHelpful for showing slope."

varip str_text_col  = str_txt + " Color"
varip str_LL        = str_lower + str_spc + str_left
varip str_UL        = str_upper + str_spc + str_left
varip str_LR        = str_lower + str_spc + str_right
varip str_UR        = str_upper + str_spc + str_right
varip txt_bull_col  = color.new ( #2eaddc, 0 )
varip txt_bear_col  = color.new ( #ff7f00, 0 )
varip ma_lbl_offX2  = "X " + str_offset + " (" + str_triangle + ")"
varip str_txtsize   = str_txt + " Size"
varip str_change    = "Change"

i_showTrendLabel        = input ( true,             str_enable,                     input.bool, tooltip = MA_tf_tt,                                                     group = groupLabel )
i_ma_lbl_offsetX        = input ( 2,                "X " + str_offset,              input.integer, minval = -100, maxval = 100,                                         group = groupLabel )
i_ma_lbl_offsetX2       = input ( 0,                ma_lbl_offX2,                   input.integer, minval = -100, maxval = 100,                                         group = groupLabel )
i_ma_lbl_offsetY        = input ( 0,                "Y " + str_offset,              input.integer, minval = -1000, maxval = 1000,                                       group = groupLabel )
i_ma_lbl_arrow          = input ( str_left,         "Arrow",        options = [ str_left, str_right, str_up, str_down, str_center, str_LL, str_UL, str_LR, str_UR ],    group = groupLabel )
i_ma_lbl_txt_size       = input ( str_normal,       str_txtsize,    options = [ str_tiny, str_small, str_normal, str_large, str_huge ],                                 group = groupLabel )
i_ma_lbl_txt_color_bull = input ( txt_bull_col,     str_text_col,                   input.color,                                                                        group = groupLabel, inline = str_text_col )
i_ma_lbl_txt_color_bear = input ( txt_bear_col,     "",                             input.color,                                                                        group = groupLabel, inline = str_text_col )
i_ma_lbl_txt_color      = input ( #D1D4DC,          "",                             input.color,                                                                        group = groupLabel, inline = str_text_col )
i_ma_lbl_txt_color_dyn  = input ( true,             "Dynamic",                      input.bool,                                                                         group = groupLabel, inline = str_text_col )
i_ma_lbl_col_bg         = input ( color_none,       "Background",                   input.color,                                                                        group = groupLabel )
i_ma_lbl_price          = input ( false,            str_price,                      input.bool,                                                                         group = groupLabel )
i_ma_lbl_percent        = input ( false,            str_pct,                        input.bool,                                                                         group = groupLabel, tooltip = lbl_pct_tt )
i_ma_lbl_change         = input ( true,             str_change,                     input.bool,                                                                         group = groupLabel, tooltip = lbl_chg_tt )
i_ma_lbl_slope          = input ( true,             "Slope (Triangle)",             input.bool,                                                                         group = groupLabel )
i_ma_lbl_k_val          = input ( true,             str_1000s_k,                    input.bool,                                                                         group = groupLabel )





/////////////////////////////////////////////////////////////////////////////////
// TAKE PROFIT

i_wide_KC           = input (    false,     str_wide_kc,        input.bool,                 group = groupStratIcons )
i_showBB            = input (    false,     groupBB,            input.bool,                 group = groupStratIcons )

i_tp_col_txt_Bu     = input ( color_off,    string ( na ),      input.color,        group = groupStratIcons, inline = groupTP,      tooltip = str_txt_color_tt )
i_tp_col_txt_Be     = input ( color_off,    string ( na ),      input.color,        group = groupStratIcons, inline = groupTP )
i_tp_icn            = input (    false,     groupTP + " Icons", input.bool,         group = groupStratIcons, inline = groupTP )





///////////////////////////////////////////////////////////////////////////////
// Trend line inputs



varip i_total_conds     = 11
varip i_min_candles     = 3
varip i_min_range       = 2
varip i_min_change      = timeframe.isdwm ?   72 : timeframe.multiplier * 0.05
varip i_min_farAway     = timeframe.isdwm ? 1000 : timeframe.multiplier * 0.75
varip i_ma_input2calc   = str_ema
varip i_ma_input2       = 12
varip i_ma_input3calc   = str_hma
varip i_ma_input3       = 64     
varip i_ma_input4calc   = str_sma
varip i_ma_input4       = 4
varip i_ma_input5calc   = str_sma
varip i_ma_input5       = 2





/////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS

// FUNCTION: Return the given moving average
f_wave_calc ( source, length, calculation ) =>
    wave = float ( na )
    if calculation == str_hma
        wave := hma ( source, length )
    else
        if calculation == str_ema
            wave := ema ( source, length )
        else
            if calculation == str_sma
                wave := sma ( source, length)
            else
                if calculation == str_wma
                    wave := wma ( source, length )
                else
                    if calculation == str_alma
                        wave := alma ( source, length, 0.85, 21 )
                    else
                        if calculation == str_vwma
                            wave := vwma ( source, length )
    wave



// FUNCTION: Was the given oscillator ">" or "<" than the area within the past few bars
f_osc_was_inside ( osc, operation, area, bars_to_scan ) =>
    return = false
    for i = 0 to bars_to_scan
        if i == bars_to_scan
            break
        else
            if not return
                if operation == ">"
                    return := osc[i] >= area
                else if operation == "<"
                    return := osc[i] <= area
                else
                    return := osc[i] == area
                continue
            else
                break
    return



// FUNCTION: Determine the % change between any two bars
f_pct_change ( source ) => ( ( source - source[1] ) / source[1] ) * 100



// FUNCTION: Return the cumulative percentage change over time
f_osc_pct_change_over_time ( osc, bars_to_scan ) =>
    return = 0.
    for i = 0 to bars_to_scan
        return += f_pct_change ( osc[i] )
    return



// FUNCTION: Determine if there has been a continuous slope based on the given
//           operation, looking back a static number of bars or bars since the
//           given indicator ( 'osc' ) was above/below the
//           given threshold ( 'alert_zone' ).
//           Set 'lookback_bars' to 0 for the inverse of the logical function.
//           Example: Running f_continuous_slope ( rsi, '<', 80, -1 )
//                    will analyze for downward slope for barssince ( rsi > 80 )
//                    whereas f_continuous_slope ( rsi, '<', 80, 0 )
//                    will analyze for downward slope for barssince ( rsi < 80 )
f_continuous_slope ( osc, operation, alert_zone, lookback_bars ) =>
    continuous_slope = bool ( na )
    end              = lookback_bars
    threshold        = alert_zone < 0 ? osc[1] : alert_zone
    if operation == ">" or operation == "up"
        if      end == 0
            end := barssince ( osc > threshold )
        else if end < 0
            end := barssince ( osc < threshold )
        continuous_slope := osc > osc[1]
        if continuous_slope and end > 0
            for i = 1 to end
                if i == end
                    break
                else if continuous_slope
                    continuous_slope := osc[i] > osc[i + 1]
                    continue
                else
                    break
    else if operation == "<" or operation == "dn" or operation == "down"
        if      end == 0
            end := barssince ( osc < threshold )
        else if end < 0
            end := barssince ( osc > threshold )
        continuous_slope := osc < osc[1]
        if continuous_slope and end > 0
            for i = 1 to end
                if i == end
                    break
                else if continuous_slope
                    continuous_slope := osc[i] < osc[i + 1]
                    continue
                else
                    break
    continuous_slope



// FUNCTION: See if the given 'cond' occurred within the most recent number of 'bars'
f_find ( cond, bars ) =>
    return = cond
    for i = 0 to bars
        if return
            break
        else
            return := cond[i]
            continue
    return





/////////////////////////////////////////////////////////////////////////////////
//------------------------------------------------------------------------------
// TSI Range bound

varip i_TSI_short     =  5
varip i_TSI_long      = 12
varip i_TSI_Signal    = 10

f_TSI_Helper ( price_change, long, short ) => ema ( ema ( price_change, long ), short )

// FUNCTION: Return the TSI Momentum Oscillator
f_TSI ( i_priceSrc, i_TSI_short, i_TSI_long ) =>
    price_change            = change ( i_priceSrc )
    double_smoothed_pc      = f_TSI_Helper (       price_change,   i_TSI_long, i_TSI_short )
    double_smoothed_abs_pc  = f_TSI_Helper ( abs ( price_change ), i_TSI_long, i_TSI_short )
    ( double_smoothed_pc / double_smoothed_abs_pc ) * 100



//------------------------------------------------------------------------------
// KELTNER CHANNEL


varip keltner_atr           = "Average True Range"
varip keltner_true_range    = "True Range"
varip keltner_range         = "Range"
varip keltner_bands_style   = "Bands Style"


varip i_keltner_MA_calc     = str_sma
varip i_keltner_BandsType   = keltner_atr
varip i_keltner_length      = i_wide_KC ? 330 : 22 
varip i_keltner_multi       = i_wide_KC ? 3.5 : 1.0
varip i_keltner_BandsLength = i_wide_KC ? 330 : 22


// FUNCTION: Calculate the Keltner Channel width between basis and each edge band
f_keltner_width ( range_type, range_length ) =>
    channel_width = float ( na )
    if      range_type == keltner_atr
        channel_width := atr ( range_length )
    else if range_type == keltner_true_range
        channel_width := rma ( tr ( true ), range_length )
    else if range_type == keltner_range
        channel_width := rma ( high - low, range_length )
    channel_width



//------------------------------------------------------------------------------
// BOLLINGER BANDS


varip BB_length   = 20   //input ( 20,    "BB - Length", input.integer, minval = 1,                group = groupBB )
varip BB_mult     = 2.0  //input ( 2.0,   "BB - StdDev", input.float, minval = 0.001, maxval = 50, group = groupBB )

f_bb_basis ( source        ) => sma ( source, BB_length )
f_bb_upper ( source, basis ) => basis + ( BB_mult * stdev ( source, BB_length ) )
f_bb_lower ( source, basis ) => basis - ( BB_mult * stdev ( source, BB_length ) )



//------------------------------------------------------------------------------
// HVP

// original version by:
// (c) bolipour, 2019
// https://www.tradingview.com/script/QM23PXyq-BA-Historical-Volatility-Percentile-SMA/
//
//
// open source version by:
// (c) Franklin Moormann (cheatcountry), 2019
// Historical Volatility Percentile + SMA script may be freely distributed under the MIT license.
// https://www.tradingview.com/script/WQEK8atJ-Historical-Volatility-Percentile-SMA/
//
//
// edited by:
// (c) Trendespresso, 2021
// if you want to reach me and I do not respond on TradingView, google my username
// https://www.tradingview.com/u/trendespresso/

varip i_hvp_len       =   10
varip i_hvp_ann       =  252

f_HVP ( source, len_hvp, len_ann ) =>
    // the reason why I don't use the pinescript stddev function below is because we are doing sample std deviation not population
    r    = log ( source / nz ( source[1], source ) )
    rAvg = sma ( r, len_hvp )
    hv   = sqrt ( sum ( pow ( r - rAvg, 2 ), len_hvp ) / ( len_hvp - 1 ) ) * sqrt ( len_ann )
    // loop through each percentile
    count = 0.
    for i = 0 to len_ann - 1
        count += (nz(hv[i]) < hv ? 1 : 0 )
    ( count / len_ann ) * 100



//------------------------------------------------------------------------------
// BB Width

//
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// @version = 4
// @author  = The_Caretaker
// © The_Caretaker
//
// Much respect to John A Bollinger the creator of Bollinger Bands® and Bollinger Band Width indicators.
// 
// Feel free to reuse or develop this script further, please drop me a note below if you find it useful.
//

f_bbwp ( price, bbwLen, bbwpLen, type ) =>
    basis   = f_wave_calc ( price, bbwLen, type )
    dev     = stdev ( price, bbwLen )
    _bbw    = ( ( basis + dev ) - ( basis - dev ) ) / basis
    _bbwSum = 0
    for i = 1 to bbwpLen
        _bbwSum += ( _bbw [i] > _bbw ? 0 : 1 )
    ( _bbwSum / bbwpLen ) * 100



//------------------------------------------------------------------------------
// SECURITY CALLS


varip security_syminfo_indics = i_HA_data   ? heikinashi ( ticker ) : ticker
varip security_syminfo_prices = i_HA_prices ? heikinashi ( ticker ) : ticker


[ ohlc4_HA,
  hlc3_HA, 
  open_HA, 
  high_HA, 
  low_HA, 
  close_HA,
  price_change,
  price_change_HL ]
 = security ( security_syminfo_prices, timeframe,
  [ ohlc4, hlc3, open, high, low, close,
  f_pct_change ( close ),
  f_pct_change ( hl2 ) ] )

[ keltner_basis,
  BB_basis ]
 = security ( security_syminfo_indics, timeframe, [
  f_wave_calc ( ohlc4, i_keltner_length, i_keltner_MA_calc ),
  f_bb_basis  ( close ) ] )

[ keltner_upper, 
  keltner_lower, 
  BB_upper, 
  BB_lower ]
 = security ( security_syminfo_indics, timeframe, [
  keltner_basis + ( f_keltner_width ( i_keltner_BandsType, i_keltner_BandsLength ) * i_keltner_multi ),
  keltner_basis - ( f_keltner_width ( i_keltner_BandsType, i_keltner_BandsLength ) * i_keltner_multi ),
  f_bb_upper ( close, BB_basis ),
  f_bb_lower ( close, BB_basis ) ] )

[ crossover_bull,
  crossover_bear ]
 = security ( security_syminfo_indics, timeframe, [
  i_crossover_ma1_c != str_none ? f_wave_calc ( close, i_crossover_ma1_l, i_crossover_ma1_c ) : na,
  i_crossover_ma2_c != str_none ? f_wave_calc ( close, i_crossover_ma2_l, i_crossover_ma2_c ) : na ] )




/////////////////////////////////////////////////////////////////////////////////
// UPTREND / DOWNTREND

varip num_lines         = 1

var arr_trend_line      = array.new_float   ( num_lines )
var arr_tsi_line        = array.new_float   ( num_lines )
var arr_tsi_sig_line    = array.new_float   ( num_lines )
var arr_tsi_momen       = array.new_float   ( num_lines )
var arr_volatility      = array.new_float   ( num_lines )
var arr_sideLine1       = array.new_float   ( num_lines )
var arr_sideLine2       = array.new_float   ( num_lines )
var arr_sideLine3       = array.new_float   ( num_lines )
var arr_sideLine4       = array.new_float   ( num_lines )
var arr_trend_change    = array.new_float   ( num_lines )
var arr_trend_state     = array.new_int     ( num_lines )
var arr_strong_state    = array.new_int     ( num_lines )
var arr_tsi_state       = array.new_int     ( num_lines )
var arr_slopes_state    = array.new_int     ( num_lines )
var arr_trend_count     = array.new_int     ( num_lines )
var arr_candle_count1   = array.new_int     ( num_lines )
var arr_candle_count2   = array.new_int     ( num_lines )
var arr_candle_count3   = array.new_int     ( num_lines )
var arr_crossovers      = array.new_int     ( num_lines )


f_array_data ( _index, _timeframe, _trend_line_len, _trend_line_calc, _tsi_short_len, _tsi_long_len, _tsi_sig_len, _hvp_len, _hvp_ann, _bb_len, _bb_ann ) =>
    
    [ _trend_line, _tsi ]
     = security ( security_syminfo_indics, _timeframe, [
      f_wave_calc ( close, _trend_line_len, _trend_line_calc ),
      f_TSI       ( close, _tsi_short_len, _tsi_long_len ) ] )
    
    [ _tsi_signal, _volatility ]
     = security ( security_syminfo_indics, _timeframe, [
      ema ( _tsi, _tsi_sig_len ),
      avg ( f_HVP ( ohlc4, _hvp_len, _hvp_ann ), f_bbwp ( hlc3, _bb_len, _bb_ann, str_sma ) ) ] )
    
    _tsi_momentum = _tsi - _tsi_signal
    
    [ _sidechain1_line, _sidechain2_line, _sidechain3_line, _sidechain4_line ]
     = security ( security_syminfo_indics, _timeframe, [
     f_wave_calc ( close,       i_ma_input2, i_ma_input2calc ),
     f_wave_calc ( close,       i_ma_input3, i_ma_input3calc ),
     f_wave_calc ( _trend_line, i_ma_input4, i_ma_input4calc ),
     f_wave_calc ( _trend_line, i_ma_input5, i_ma_input5calc ) ] )
    
    array.set ( arr_trend_line,    _index, _trend_line )
    array.set ( arr_trend_change,  _index, f_pct_change ( _trend_line ) )
    array.set ( arr_tsi_line,      _index, _tsi )
    array.set ( arr_tsi_sig_line,  _index, _tsi_signal )
    array.set ( arr_tsi_momen,     _index, _tsi_momentum )
    array.set ( arr_volatility,    _index, _volatility )
    array.set ( arr_sideLine1,     _index, _sidechain1_line )
    array.set ( arr_sideLine2,     _index, _sidechain2_line )
    array.set ( arr_sideLine3,     _index, _sidechain3_line )
    array.set ( arr_sideLine4,     _index, _sidechain4_line )
    
    //[ _trend_line, _tsi, _tsi_signal, _tsi_momentum, _volatility, _sidechain1_line, _sidechain2_line, _sidechain3_line, _sidechain4_line ]



for i = 0 to ( num_lines - 1 )
    _A = timeframe
    _D = i_TSI_short
    _E = i_TSI_long
    _F = i_TSI_Signal
    _G = i_hvp_len
    _H = i_hvp_ann
    f_array_data ( i, _A, i_ma_input1, i_ma_input1calc, _D, _E, _F, _G, _H, _G, _H )
    
    



calcTrend   = array.get ( arr_trend_line,   0 )
calcTrendCg = array.get ( arr_trend_change, 0 )
TSI         = array.get ( arr_tsi_line,     0 )
TSI_Signal  = array.get ( arr_tsi_sig_line, 0 )
TSI_hist    = array.get ( arr_tsi_momen,    0 )
volatility  = array.get ( arr_volatility,   0 )
disp_trend  = calcTrend
// disp_trend   = i_tri_calc != str_none ?
//               array.get ( arr_trend_line,   1 ) : calcTrend




/////////////////////////////////////////////////////////////////////////////////
// DIVERGENCES
varip divFind_lbL                 =  5
varip divFind_lbR                 =  2
varip divFind_rangeLower          =  5
varip divFind_rangeUpper          = 32
varip i_divFind_drives_TSI        =  2


_inRange_divHunt ( cond ) =>
	divFind_bars = barssince ( cond == true )
	divFind_rangeLower <= divFind_bars and divFind_bars <= divFind_rangeUpper


f_conds_for_bars ( cond, bars ) =>
    continuous = barssince ( cond ) < bars ? true : cond
    for i = 1 to bars
        if continuous or i == bars
            break
        else
            continuous := cond[i]
            continue
    continuous


... [some code omitted]


/////////////////////////////////////////////////////////////////////////////////
// PLOT SIDECHAIN TRENDLINES

// trnd_line_color2 = dntrnd2 ? i_color_bear : uptrnd2 ? i_color_bull : i_color_neutral
// plot ( sidechain1_line, str_trnd2, color = trnd_line_color2, linewidth = 4, display = display.all )

// var trnd_count3 = 0
// trnd_conds3  = f_calculate_trend_conditions ( sidechain2_line,   candle_count3,             1,            5,            10 )
// trnd_count3 := trnd_conds3 >=  2 ? trnd_count3 + 1 :
//               trnd_conds3 <= -2 ? trnd_count3 - 1 : 0

// uptrnd3 = trnd_count3 >=  2
// dntrnd3 = trnd_count3 <= -2

// trnd_line_color3 = dntrnd3 ? i_color_bear : uptrnd3 ? i_color_bull : i_color_neutral
// plot ( sidechain2_line, str_trnd3, color = trnd_line_color3, linewidth = 4, display = display.all )
// plot ( ohlc4_HA )
// plot ( signal_line, "Signal Line", color.yellow, 4, display = display.all )





/////////////////////////////////////////////////////////////////////////////////
// BOLLINGER BAND fill


bbU = plot ( i_showBB ? BB_upper : na, string ( na ), color ( na ), editable = false )
bbL = plot ( i_showBB ? BB_lower : na, string ( na ), color ( na ), editable = false )
fill ( bbU, bbL, #198787, 85, groupBB )





///////////////////////////////////////////////////////////////////////////////
// KELTNER fill

varip kc_blue   = color.new ( #5A7CB0, 80 )
varip kc_yellow = color.new ( color.yellow, 80 )
varip kc_orange = color.new ( color.orange, 80 )
varip kc_red    = color.new ( color.red, 80 )


kcU = plot ( keltner_upper, string ( na ), color ( na ), editable = false )
kcL = plot ( keltner_lower, string ( na ), color ( na ), editable = false )
fill ( kcU, kcL, kc_blue, 0, "Keltner Channel" ) // used to be #0094FF, 90





///////////////////////////////////////////////////////////////////////////////
// BB + KC plots
plot ( BB_basis, groupBB + " Basis",   #872323,    display = display.none )
plot ( BB_upper, groupBB + " Upper",   color.teal, display = display.none )
plot ( BB_lower, groupBB + " Lower",   color.teal, display = display.none )
plot ( keltner_upper, "Keltner Upper", #345589,    display = display.none )
plot ( keltner_basis, "Keltner Basis", #0094FF,    display = display.none )
plot ( keltner_lower, "Keltner Lower", #345589,    display = display.none )





///////////////////////////////////////////////////////////////////////////////
// MA Crossover plots

plot ( crossover_bull, str_crs_ma1, color_bull, 2, display = display.none )
plot ( crossover_bear, str_crs_ma2, color_bear, 2, display = display.none )





///////////////////////////////////////////////////////////////////////////////
// Strategy

f_continuous ( cond, bars ) =>
    continuous = cond
    for i = 1 to bars
        if not continuous or i == bars
            break
        else
            continuous := cond[i]
            continue
    continuous



// Take Profit
strat_RR_L              = calc_state > 0 and ( ohlc4_HA > BB_upper or close_HA > BB_upper ) and ( ohlc4_HA > keltner_upper or close_HA > keltner_upper )
strat_RR_S              = calc_state < 0 and ( ohlc4_HA < BB_lower or close_HA < BB_lower ) and ( ohlc4_HA < keltner_lower or close_HA < keltner_lower )

strat_continuous_TP_L   = f_continuous ( strat_RR_L, 4 )
strat_continuous_TP_S   = f_continuous ( strat_RR_S, 4 )

trend_color             = i_sTrend1 == str_col1 ? calc_state :
                          i_sTrend1 == str_col2 and
                          i_crossover_ma1_c != str_none and
                          i_crossover_ma2_c != str_none ? crossover_bull >= crossover_bear ? 1 : -1 :
                          calcTrend >= calcTrend[1] ? 1 : -1

var enter_cond          = 0
enter_long              = trend_color > 0 and trend_color[1] <= 0 and enter_cond <= 0
enter_short             = trend_color < 0 and trend_color[1] >= 0 and enter_cond >= 0
enter_cond             := enter_long ? 1 : enter_short ? -1 : enter_cond

take_profit_long        = strat_RR_L and not strat_continuous_TP_L and not enter_long
take_profit_short       = strat_RR_S and not strat_continuous_TP_S and not enter_short

var strat_SL            = float ( na )
strat_SL               := enter_long  ? lowest  ( low_HA,  10 ) :
                          enter_short ? highest ( high_HA, 10 ) : strat_SL

continuous_gray         = f_continuous ( trend_color == 0, 6 )

var exit_cond           = int ( na )
exit_cond              := enter_long ? 1 : enter_short ? -1 : exit_cond
exit_long               = exit_cond > 0 and enter_cond > 0 and calcTrend < calcTrend[1] and ( close_HA <= strat_SL or trend_color < 0 or continuous_gray )
exit_short              = exit_cond < 0 and enter_cond < 0 and calcTrend > calcTrend[1] and ( close_HA >= strat_SL or trend_color > 0 or continuous_gray )
exit_cond              := exit_long or exit_short ? 0 : exit_cond
enter_cond             := exit_long or exit_short ? 0 : enter_cond

var strat_TP            = float ( na )
strat_TP               := strat_continuous_TP_L[1] ? high_HA :
                          strat_continuous_TP_S[1] ? low_HA  :
                          enter_long  ? max ( close_HA + ( ( open_HA - close_HA ) * 5 ), highest ( high_HA, 10 ) * 1.1 ) :
                          enter_short ? min ( close_HA - ( ( open_HA - close_HA ) * 5 ), lowest  ( low_HA,  10 ) * 0.9 ) :
                          strat_TP

trend_line_color = trend_color > 0 ? color_bull : trend_color < 0 ? color_bear : color_neutral
bubbles_offset   = percentile_linear_interpolation ( abs ( calcTrendCg / 20 ), 150, 50 )
plot ( strong_state > 0 ? disp_trend * ( 1 - bubbles_offset ) : strong_state < 0 ? disp_trend * ( 1 + bubbles_offset ) : disp_trend, "Strong Trend Dots", strong_state > 0 ? color_faded_bull : strong_state < 0 ? color_faded_bear : color_none, 4, plot.style_circles, display = display.none )
plot ( disp_trend, groupTrend, trend_line_color, 4 )


// plotshape ( i_triangles and enter_long,  "Enter " + str_long, shape.triangleup,   location.belowbar, color_bull, text = "L", textcolor = i_tri_txt_col_L, size = size.tiny, display = display.all )
// plotshape ( i_triangles and enter_short, "Enter " + str_shrt, shape.triangledown, location.abovebar, color_bear, text = "S", textcolor = i_tri_txt_col_S, size = size.tiny, display = display.all )


// plotshape ( i_small_SL and exit_long, "Exit " + str_long,  shape.xcross, location.abovebar, color_bull, text = "XL", textcolor = i_sl_col_txt_Bu, size = size.tiny, display = display.all )
// plotshape ( i_small_SL and exit_short, "Exit " + str_shrt,  shape.xcross, location.belowbar, color_bear, text = "XS", textcolor = i_sl_col_txt_Be, size = size.tiny, display = display.all )


plotshape ( i_tp_icn and take_profit_long,    groupTP + " (" + str_long + ")", shape.diamond, location.abovebar, color_faded_bull,   text = "TP", textcolor = i_tp_col_txt_Bu,   size = size.tiny, display = display.all )
plotshape ( i_tp_icn and take_profit_short,   groupTP + " (" + str_shrt + ")", shape.diamond, location.belowbar, color_faded_bear,   text = "TP", textcolor = i_tp_col_txt_Be,   size = size.tiny, display = display.all )





/////////////////////////////////////////////////////////////////////////////////
// TREND LINE LABEL

i_ma_lbl_txt_size      := i_ma_lbl_txt_size == str_tiny ? size.tiny : i_ma_lbl_txt_size == str_small ? size.small : i_ma_lbl_txt_size == str_normal ? size.normal : i_ma_lbl_txt_size == str_large ? size.large : size.huge


i_ma_lbl_arrow         := i_ma_lbl_arrow == str_left ? label.style_label_left : i_ma_lbl_arrow == str_right ? label.style_label_right : i_ma_lbl_arrow == str_down ? label.style_label_down : i_ma_lbl_arrow == str_up ?
                             label.style_label_up : i_ma_lbl_arrow == str_center ? label.style_label_center : i_ma_lbl_arrow == str_LL ? label.style_label_lower_left : i_ma_lbl_arrow == str_UL ? label.style_label_upper_left :
                             i_ma_lbl_arrow == str_LR ? label.style_label_lower_right : i_ma_lbl_arrow == str_UR ? label.style_label_upper_right : i_ma_lbl_arrow

// no 'var' on purpose; want a full re-draw on each bar
f_label_X_Loc ( multi ) => time_close + ( multi * ( time_close - time_close[1] ) )
f_avg_price ( length )  => abs ( percentile_linear_interpolation ( ohlc4_HA, length, 50 ) )

label_tt_price = float ( na )
if bar_index % 50 == 0 or bar_index <= 10
    label_tt_price := f_avg_price ( 50 )
else if ohlc4_HA >= 1000 and na ( label_tt_price[1] )
    label_tt_price := 1001
else
    label_tt_price := label_tt_price[1]



ma_label_Y_Loc          = 1 + ( i_ma_lbl_offsetY / 1000 )



// HELPER FUNCTION: Split the timeframe string into an integer number and its last letter
f_split_tf_string ( tf_str ) =>
    str_num         = 1
    str_last_char   = ""
    // split the string into an array with each chracter separated
    str_as_array    = str.split  ( tf_str, "" )
    str_length      = array.size ( str_as_array ) - 1
    str_last_char  := array.get  ( str_as_array, str_length )
    if na ( tonumber ( str_last_char ) )
        // remove the last character of the string array if the 'str' is not an integer only
        array.pop  ( str_as_array )
        str_num         := str_last_char != tf_str ? ceil ( tonumber ( array.join ( str_as_array, ""  ) ) ) : 1      //str_length > 1 ? ceil ( tonumber ( array.join ( str_as_array, ""  ) ) ) : 1
    else
        str_num         := ceil ( tonumber ( tf_str ) )
    [ str_num, str_last_char ]


// HELPER FUNCTION: Convert Months and Weeks and Days into Minutes
f_convert_to_minutes ( tf_str ) =>
    [ str_num, str_last_char ]  = f_split_tf_string ( tf_str )
    m                           = 0
    d                           = 0.0
    if      str_last_char == "M"
        d := 30.4167 * str_num
    else if str_last_char == "W"
        d := 7       * str_num
    else if str_last_char == "D"
        d :=           str_num
    // now figure out the days into minutes or return minutes
    m := d > 0 ? ceil ( d * 24 * 60 ) : str_num


// HELPER FUNCTION: Convert the default timeframe string into a more
//                  readable 0h 00m form
f_convert_minutes_to_hours ( tf_str, tf_mins ) =>
    h       = 0
    m       = tf_mins
    rtn_h   = string(na)
    rtn_m   = string(na)
    if m >= 1440 and tf_str != "1440"
        rtn_h := " " + tf_str
    else
        for i = 0 to m
            if m >=  60
                h := h +  1
                m := m - 60
                pine_limitation = ""
        if h > 0
            rtn_h := " " + tostring(h) + "h"
        if m != 0
            if m < 10
                rtn_m := " 0" + tostring(m) + "m"
            else
                rtn_m :=  " " + tostring(m) + "m"
    [ rtn_h, rtn_m ]


// HELPER FUNCTION: Add the correct negative or positive sign to the given string (requires the original value/number obviously)
f_add_sign ( value, number_as_string ) => value < 0 ? "–" + number_as_string : "+" + number_as_string


// FUNCTION: Convert the goven oscillator or number into a readable output
//           with proper sign, decimal places, and zeroes.
f_osc_as_text ( input_osc, input_decimals ) =>
    extra_zeroes = 0
    // extra_zeroes is usually an input argument
    osc         = input_osc < 0 ? abs ( input_osc ) : input_osc
    //osc        := dynamic_decimals ? osc * label_tt_multi : osc
    num         = floor ( osc )
    decimals    = input_decimals >= 0 ? input_decimals : label_tt_price >= 1000 ? 0 : label_tt_price >= 100 ? 1 : label_tt_price >= 1 ? 2 : label_tt_price >= 0.1 ? 3 : label_tt_price >= 0.01 ? 4 : 5
    factor      = pow ( 10, decimals )
    dec         = floor ( ( round ( osc - num, 6 ) ) * factor ) / factor
    return      = tostring ( num + dec )
    if num < 10.0 and extra_zeroes > 0
        for i = 1 to extra_zeroes
            return := "0" + return
    if decimals > 0
        z = decimals
        if ( num > 0.0 and ( osc % 1 == 0.0 or dec == 0.0 ) ) or ( num + dec ) == 0.0
            return += "."
        else
            d = dec
            for i = 1 to decimals
                if d % 1 != 0.0
                    d *= 10
                    z -= 1
                    continue
                else
                    break
            pine = string ( na ) // Pine limitation
        if z > 0
            for i = 1 to z
                return += "0"
    return


// HELPER FUNCTION: Hover mouse cursor over label to see % increase or decrease
//                  required for price to match or cross the line
f_ma_label_percent ( number ) =>
    raw     = ( ( number - close ) / close ) * 100
    return  = f_add_sign ( raw, f_osc_as_text ( raw, 2 ) ) + " %"


// FUNCTION: Return the Moving Average price, optionally appending ' K ' if >1000
f_ma_label_price ( number, k_condition ) =>
    return      = string ( na )
    if k_condition and label_tt_price >= 1000
        return := f_osc_as_text ( number / 1000,  1 ) + "k"
    else
        return := f_osc_as_text ( number,        -1 )
    return


// FUNCTION: Convert the Moving Average into readable label text
f_ma_label_text ( ma, k_condition, price_cond, pct_cond ) =>
    return = string ( na )
    //if i_ma_lbl_length
    if price_cond
        if not na ( return ) or return != ""
            return += "\n"
        return += f_ma_label_price ( ma, k_condition )
    if pct_cond
        if not na ( return ) or return != ""
            return += "\n"
        return += f_ma_label_percent ( ma )
    return

f_label_change ( ma ) =>
    prev = ( ( ma - ma[1] ) / ma[1] ) * 100
    text = f_add_sign ( prev, f_osc_as_text ( prev, 2 ) ) + " %"
    [ prev, text ]

f_label_trend_line ( ma, price_cond, pct_cond ) =>
    text = f_ma_label_text ( ma, i_ma_lbl_k_val, price_cond, pct_cond )
    tt   = f_ma_label_text ( ma, i_ma_lbl_k_val, true,       true     )
    [ prev, text_tmp ] = f_label_change ( ma )
    if na ( text ) or text == ''
        text := text_tmp
    else
        text += "\n\n" + text_tmp
    tt   += "\n\n" + str_change + ":\n" + text_tmp
    [ prev, text, tt ]

varip enable_ma1_label = i_showTrendLabel and i_ma_input1calc != str_none


// ma_label1_text  = enable_ma1_label ? f_ma_label_text ( disp_trend, i_ma_lbl_k_val, i_ma_lbl_price, i_ma_lbl_percent ) : string ( na )
// ma_label1_tt    = enable_ma1_label ? f_ma_label_price ( disp_trend, i_ma_lbl_k_val ) + "\n" + f_ma_label_percent ( disp_trend ) : string ( na )
// ma_label1       = enable_ma1_label ? label.new ( f_label_X_Loc ( i_ma_lbl_offsetX ), disp_trend * ma_label_Y_Loc, ma_label1_text,  xloc.bar_time, yloc.price, i_ma_lbl_col_bg, i_ma_lbl_arrow, i_ma_lbl_txt_color, i_ma_lbl_txt_size, text.align_center, ma_label1_tt ) : label ( na )
// label.delete    ( ma_label1[1] )

[ ma1_prev, ma_label1_textC, ma_label1_tt ] = f_label_trend_line ( disp_trend, i_ma_lbl_price, i_ma_lbl_percent )
// if i_ma_lbl_change and ( i_ma_lbl_price or i_ma_lbl_percent )
//     spacing_req          = "\n\n\n\n"
//     if i_ma_lbl_price and i_ma_lbl_percent
//         spacing_req     += "\n"
//     ma_label1_textC := spacing_req + ma_label1_textC


// include Strong Trend
if i_ma_lbl_change and ( strong_state != 0 or tsi_state != 0 )
    ma_label1_textC += "\n"
    if strong_state > 0 or tsi_state > 0
        if strong_state > 0
            ma_label1_textC += "Strong "
        else
            ma_label1_textC += "Weak "
        ma_label1_textC += "Up"
    else if strong_state < 0 or tsi_state < 0
        if strong_state < 0
            ma_label1_textC += "Strong "
        else
            ma_label1_textC += "Weak "
        ma_label1_textC += "Down"
    else
        ma_label1_textC += "Sideways"
    ma_label1_textC += " Trend"


// print the slope % label
ma_label1C_text_color = i_ma_lbl_change ?
                         i_ma_lbl_txt_color_dyn ?
                             trend_color > 0 ?
                             ma1_prev > 0 ?
                             i_ma_lbl_txt_color_bull : i_ma_lbl_txt_color :
                             trend_color < 0 ?
                             ma1_prev < 0 ?
                             i_ma_lbl_txt_color_bear : i_ma_lbl_txt_color :
                             i_ma_lbl_txt_color      : i_ma_lbl_txt_color : color ( na )
ma_label1C      = enable_ma1_label ? label.new ( f_label_X_Loc ( i_ma_lbl_offsetX ), disp_trend * ma_label_Y_Loc, ma_label1_textC,  xloc.bar_time, yloc.price, i_ma_lbl_col_bg, i_ma_lbl_arrow, ma_label1C_text_color, i_ma_lbl_txt_size, text.align_center, ma_label1_tt ) : label ( na )
label.delete    ( ma_label1C[1] )







////////////////////////////////////////////////////////////////////////////////
// Triangle Label

varip arw_up        = "▲"
varip arw_dn        = "▼"
varip arw_na        = ""
trade_state_L       = calcTrendCg > 0 and close_HA > disp_trend
trade_state_S       = calcTrendCg < 0 and close_HA < disp_trend
label_triangle_tt   = ma_label1_tt
label_triangle      = label.new ( f_label_X_Loc ( i_ma_lbl_offsetX2 ),
                                  disp_trend * ma_label_Y_Loc, 
                                  trade_state_L ? arw_up : trade_state_S ? arw_dn : arw_na, 
                                  xloc.bar_time, 
                                  yloc.price, 
                                  color_none, 
                                  label.style_label_left, 
                                  enable_ma1_label and i_ma_lbl_slope ? 
                                   trade_state_L ? i_ma_lbl_txt_color_bull : 
                                   trade_state_S ? i_ma_lbl_txt_color_bear : 
                                   i_ma_lbl_txt_color : color_none,
                                  i_ma_lbl_txt_size, 
                                  text.align_center,
                                  label_triangle_tt )
label.delete ( label_triangle[1] )











/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////

varip groupMA           = "Moving Averages"
varip groupMAL          = "Moving Average Labels"

/////////////////////////////////////////////////////////////////////////////////
// MOVING AVERAGES

varip bigMA_tf_tt  = "Hover your mouse cursor over\neach Moving Average label to\nsee the exact price for that\nMoving Average."
varip bigMA_tt     = "Enable up to 5 Moving Averages\non any other Timeframe.\n\nDaily, Weekly, or Monthly are recommended.\n\n" + MA_tf_tt

i_showMA        = input ( false,    str_enable,                       group = groupMA, tooltip = bigMA_tt )
MA_tf           = input ( "D",      "MA Timeframe", input.resolution, group = groupMA, tooltip = bigMA_tf_tt, inline = bigMA_tf_tt )

varip ma1_line  = "MA 1"
varip ma2_line  = "MA 2"
varip ma3_line  = "MA 3"
varip ma4_line  = "MA 4"
varip ma5_line  = "MA 5"
varip ma6_line  = "MA 6"

i_bigma_input1calc  = input ( str_ema,  ma1_line, options = [ str_ema, str_hma, str_sma, str_wma, str_alma, str_vwma, str_none ],   group = groupMA, inline = ma1_line )
i_bigma_input1len   = input (   50,     "",                                                                                         group = groupMA, inline = ma1_line )
i_bigma_input2calc  = input ( str_ema,  ma2_line, options = [ str_ema, str_hma, str_sma, str_wma, str_alma, str_vwma, str_none ],   group = groupMA, inline = ma2_line )
i_bigma_input2len   = input (  147,     "",                                                                                         group = groupMA, inline = ma2_line )
i_bigma_input3calc  = input ( str_ema,  ma3_line, options = [ str_ema, str_hma, str_sma, str_wma, str_alma, str_vwma, str_none ],   group = groupMA, inline = ma3_line )
i_bigma_input3len   = input (  350,     "",                                                                                         group = groupMA, inline = ma3_line )
i_bigma_input4calc  = input ( str_ema,  ma4_line, options = [ str_ema, str_hma, str_sma, str_wma, str_alma, str_vwma, str_none ],   group = groupMA, inline = ma4_line )
i_bigma_input4len   = input (  700,     "",                                                                                         group = groupMA, inline = ma4_line )
i_bigma_input5calc  = input ( str_ema,  ma5_line, options = [ str_ema, str_hma, str_sma, str_wma, str_alma, str_vwma, str_none ],   group = groupMA, inline = ma5_line )
i_bigma_input5len   = input ( 1050,     "",                                                                                         group = groupMA, inline = ma5_line )
i_bigma_input6calc  = input ( str_ema,  ma6_line, options = [ str_ema, str_hma, str_sma, str_wma, str_alma, str_vwma, str_none ],   group = groupMA, inline = ma6_line )
i_bigma_input6len   = input ( 1400,     "",                                                                                         group = groupMA, inline = ma6_line )





/////////////////////////////////////////////////////////////////////////////////
// MOVING AVERAGE LABELS

i_showMALabels              = input ( false,            str_enable,                     input.bool, tooltip = MA_tf_tt,                                                     group = groupMAL )
i_bigma_lbl_offsetX         = input ( 0,                "X " + str_offset,              input.integer, minval = -100, maxval = 100,                                         group = groupMAL )
i_bigma_lbl_offsetY         = input ( 0,                "Y " + str_offset,              input.integer, minval = -1000, maxval = 1000,                                       group = groupMAL )
i_bigma_lbl_arrow           = input ( str_left,         "Arrow",        options = [ str_left, str_right, str_up, str_down, str_center, str_LL, str_UL, str_LR, str_UR ],    group = groupMAL )
i_bigma_lbl_txt_size        = input ( str_normal,       str_txtsize,    options = [ str_tiny, str_small, str_normal, str_large, str_huge ],                                 group = groupMAL )
i_bigma_lbl_txt_color       = input ( #D1D4DC,          "Text Color",                   input.color,                                                                        group = groupMAL )
i_bigma_lbl_col_bg          = input ( color_none,       "Background",                   input.color,                                                                        group = groupMAL )
i_bigma_lbl_length          = input ( true,             "Length",                       input.bool,                                                                         group = groupMAL )
i_bigma_lbl_price           = input ( true,             str_price,                      input.bool,                                                                         group = groupMAL )
i_bigma_lbl_percent         = input ( false,            str_pct,                        input.bool,                                                                         group = groupMAL )
i_bigma_lbl_k_val           = input ( true,             str_1000s_k,                    input.bool,                                                                         group = groupMAL )




/////////////////////////////////////////////////////////////////////////////////
// MOVING AVERAGES plots



f_moving_averages ( ) =>
    [ line1, line2, line3, line4, line5, line6 ] =
     security ( security_syminfo_indics, MA_tf, [
     f_wave_calc ( close, i_bigma_input1len, i_bigma_input1calc ),
     f_wave_calc ( close, i_bigma_input2len, i_bigma_input2calc ),
     f_wave_calc ( close, i_bigma_input3len, i_bigma_input3calc ),
     f_wave_calc ( close, i_bigma_input4len, i_bigma_input4calc ),
     f_wave_calc ( close, i_bigma_input5len, i_bigma_input5calc ),
     f_wave_calc ( close, i_bigma_input6len, i_bigma_input6calc ) ] )

f_population_moving_averages ( enable ) =>
    generic_return = float ( na )
    return1 = generic_return
    return2 = generic_return
    return3 = generic_return
    return4 = generic_return
    return5 = generic_return
    return6 = generic_return
    if enable
        [ line1, line2, line3, line4, line5, line6 ] = f_moving_averages ( )
        return1 := line1
        return2 := line2
        return3 := line3
        return4 := line4
        return5 := line5
        return6 := line6
    [ return1, return2, return3, return4, return5, return6 ]

[ ma1, ma2, ma3, ma4, ma5, ma6 ] = f_population_moving_averages ( i_showMA or i_showMALabels )

plot ( i_showMA ? ma1 : na, "Moving Average 1", color.gray, 2 )
plot ( i_showMA ? ma2 : na, "Moving Average 2", #7B1FA2,    2 )
plot ( i_showMA ? ma3 : na, "Moving Average 3", #B74747,    2 )
plot ( i_showMA ? ma4 : na, "Moving Average 4", #3179F5,    2 )
plot ( i_showMA ? ma5 : na, "Moving Average 5", #A17813,    2 )
plot ( i_showMA ? ma6 : na, "Moving Average 6", #1B5E20,    2 )



// FUNCTION: Convert the Moving Average into readable label text
f_bigma_label_text ( enable_output, ma, length, tf_mins, tf_str ) =>
    return1             = string ( na )
    return2             = string ( na )
    if enable_output
        label_price_text    = f_ma_label_price ( ma, i_bigma_lbl_k_val )
        label_percent_text  = f_ma_label_percent ( ma )
        if tf_mins >= 1440 or na ( tonumber ( MA_tf ) )
            return1 := tostring ( length ) + str_spc + MA_tf
            if MA_tf == "D" or MA_tf == "1D"
                if ( length % 30 ) == 0
                    return1 := tostring ( length / 30 ) + " M"
                else if ( length % 7 ) == 0
                    return1 := tostring ( length / 7 ) + " W"
                else
                    return1 := tostring ( length ) + " D"
            else if MA_tf == "W" or MA_tf == "1W"
                if ( length % 4 ) == 0
                    return1 := tostring ( length / 4 ) + " M"
        else
            return1 := tf_str
        if i_bigma_lbl_length
            return2 := return1
        if i_bigma_lbl_price
            if not na ( return2 ) or return2 != ""
                return2 += "\n"
            return2 += label_price_text
        if i_bigma_lbl_percent
            if not na ( return2 ) or return2 != ""
                return2 += "\n"
            return2 += label_percent_text
        return1 += "\n" + label_price_text + "\n" + label_percent_text
    [ return1, return2 ]



if i_showMALabels

    bigma_lbl_txt_size         = i_bigma_lbl_txt_size == str_tiny ? size.tiny : i_bigma_lbl_txt_size == str_small ? size.small : i_bigma_lbl_txt_size == str_normal ? size.normal : i_bigma_lbl_txt_size == str_large ? size.large : size.huge
    
    
    bigma_lbl_arrow            = i_bigma_lbl_arrow == str_left ? label.style_label_left : i_bigma_lbl_arrow == str_right ? label.style_label_right : i_bigma_lbl_arrow == str_down ? label.style_label_down : i_bigma_lbl_arrow == str_up ?
                                 label.style_label_up : i_bigma_lbl_arrow == str_center ? label.style_label_center : i_bigma_lbl_arrow == str_LL ? label.style_label_lower_left : i_bigma_lbl_arrow == str_UL ? label.style_label_upper_left :
                                 i_bigma_lbl_arrow == str_LR ? label.style_label_lower_right : i_bigma_lbl_arrow == str_UR ? label.style_label_upper_right : i_bigma_lbl_arrow
    
    // no 'var' on purpose; want a full re-draw on each bar
    bigma_label_X_Loc          = f_label_X_Loc ( i_bigma_lbl_offsetX )
    bigma_label_Y_Loc          = 1 + ( i_bigma_lbl_offsetY / 1000 )
    
    varip MA_tf_mins        = f_convert_to_minutes ( MA_tf == '' or MA_tf == timeframe.period ? timeframe.period : MA_tf )
    [ MA_tf_h, MA_tf_m ]    = f_convert_minutes_to_hours ( MA_tf, MA_tf_mins )
    varip MA_tf_string      = MA_tf_h + MA_tf_m
    
    varip enable_bigma1_label = i_bigma_input1calc != str_none
    varip enable_bigma2_label = i_bigma_input2calc != str_none
    varip enable_bigma3_label = i_bigma_input3calc != str_none
    varip enable_bigma4_label = i_bigma_input4calc != str_none
    varip enable_bigma5_label = i_bigma_input5calc != str_none
    varip enable_bigma6_label = i_bigma_input6calc != str_none
    
    [ bigma_label1_tt, bigma_label1_text ] = f_bigma_label_text ( enable_bigma1_label, ma1, i_bigma_input1len, MA_tf_mins, MA_tf_string )
    bigma_label1       = enable_bigma1_label ? label.new ( bigma_label_X_Loc, ma1 * bigma_label_Y_Loc, bigma_label1_text,  xloc.bar_time, yloc.price, i_bigma_lbl_col_bg, bigma_lbl_arrow, i_bigma_lbl_txt_color, bigma_lbl_txt_size, text.align_center, bigma_label1_tt ) : label ( na )
    label.delete    ( bigma_label1[1] )
    
    [ bigma_label2_tt, bigma_label2_text ] = f_bigma_label_text ( enable_bigma2_label, ma2, i_bigma_input2len, MA_tf_mins, MA_tf_string )
    bigma_label2       = enable_bigma2_label ? label.new ( bigma_label_X_Loc, ma2 * bigma_label_Y_Loc, bigma_label2_text,  xloc.bar_time, yloc.price, i_bigma_lbl_col_bg, bigma_lbl_arrow, i_bigma_lbl_txt_color, bigma_lbl_txt_size, text.align_center, bigma_label2_tt ) : label ( na )
    label.delete    ( bigma_label2[1] )
    
    [ bigma_label3_tt, bigma_label3_text ] = f_bigma_label_text ( enable_bigma3_label, ma3, i_bigma_input3len, MA_tf_mins, MA_tf_string )
    bigma_label3       = enable_bigma3_label ? label.new ( bigma_label_X_Loc, ma3 * bigma_label_Y_Loc, bigma_label3_text,  xloc.bar_time, yloc.price, i_bigma_lbl_col_bg, bigma_lbl_arrow, i_bigma_lbl_txt_color, bigma_lbl_txt_size, text.align_center, bigma_label3_tt ) : label ( na )
    label.delete    ( bigma_label3[1] )
    
    [ bigma_label4_tt, bigma_label4_text ] = f_bigma_label_text ( enable_bigma4_label, ma4, i_bigma_input4len, MA_tf_mins, MA_tf_string )
    bigma_label4       = enable_bigma4_label ? label.new ( bigma_label_X_Loc, ma4 * bigma_label_Y_Loc, bigma_label4_text,  xloc.bar_time, yloc.price, i_bigma_lbl_col_bg, bigma_lbl_arrow, i_bigma_lbl_txt_color, bigma_lbl_txt_size, text.align_center, bigma_label4_tt ) : label ( na )
    label.delete    ( bigma_label4[1] )
    
    [ bigma_label5_tt, bigma_label5_text ] = f_bigma_label_text ( enable_bigma5_label, ma5, i_bigma_input5len, MA_tf_mins, MA_tf_string )
    bigma_label5       = enable_bigma5_label ? label.new ( bigma_label_X_Loc, ma5 * bigma_label_Y_Loc, bigma_label5_text,  xloc.bar_time, yloc.price, i_bigma_lbl_col_bg, bigma_lbl_arrow, i_bigma_lbl_txt_color, bigma_lbl_txt_size, text.align_center, bigma_label5_tt ) : label ( na )
    label.delete    ( bigma_label5[1] )
    
    [ bigma_label6_tt, bigma_label6_text ] = f_bigma_label_text ( enable_bigma6_label, ma6, i_bigma_input6len, MA_tf_mins, MA_tf_string )
    bigma_label6       = enable_bigma6_label ? label.new ( bigma_label_X_Loc, ma6 * bigma_label_Y_Loc, bigma_label6_text,  xloc.bar_time, yloc.price, i_bigma_lbl_col_bg, bigma_lbl_arrow, i_bigma_lbl_txt_color, bigma_lbl_txt_size, text.align_center, bigma_label6_tt ) : label ( na )
    label.delete    ( bigma_label6[1] )
    






///////////////////////////////////////////////////////////////////////////////
// Alerts



// Combined Alerts

varip str_stratAlrt = str_strat + " ( Entry / Exit / SL / TP )"

varip alert_header          = script_abrev + ":"
varip str_alert_header      = "Alert Header"

i_alert_header      = input ( alert_header, str_alert_header,   input.string,   group = groupAlerts )
free_alert_text     = i_alert_header

i_CmbAlrt_strat     = input ( true,     str_stratAlrt,  input.bool, group = groupAlerts )

i_CmbAlrt_uptrend   = input ( true,     str_uptrend,    input.bool, group = groupAlerts )
i_CmbAlrt_dntrend   = input ( true,     str_dntrend,    input.bool, group = groupAlerts )
i_CmbAlrt_aboveKC   = input ( true,     str_aboveKC,    input.bool, group = groupAlerts )
i_CmbAlrt_belowKC   = input ( true,     str_belowKC,    input.bool, group = groupAlerts )

i_CmbAlrt_BBsqeez   = input ( true,     str_BBsqueeze,  input.bool, group = groupAlerts )

// i_CmbAlrt_regBull   = input ( true,     str_reg_bull,   input.bool, group = groupAlerts )
// i_CmbAlrt_hidBull   = input ( true,     str_hid_bull,   input.bool, group = groupAlerts )
// i_CmbAlrt_regBear   = input ( true,     str_reg_bear,   input.bool, group = groupAlerts )
// i_CmbAlrt_hidBear   = input ( true,     str_hid_bear,   input.bool, group = groupAlerts )

// i_CmbAlrt_pivotH    = input ( true,     str_pivot_high, input.bool, group = groupAlerts )
// i_CmbAlrt_pivotL    = input ( true,     str_pivot_low,  input.bool, group = groupAlerts )


// Alert Logic

close_above_kc  = ohlc4_HA > keltner_upper or close_HA > keltner_upper
close_below_kc  = ohlc4_HA < keltner_lower or close_HA < keltner_lower
BB_squeeze      = BB_upper < keltner_upper and BB_lower > keltner_lower





strat_trigger        = 0.
var strat_trigger_SL = 0.
var strat_trigger_TP = 0.

if      enter_long
    strat_trigger   :=  1
    if i_CmbAlrt_strat
        free_alert_text += "\n" + str_enter_long  + "\n( SL: " + tostring ( strat_SL ) + " | TP: " + tostring ( strat_TP ) + " )"
else if enter_short
    strat_trigger   := -1
    if i_CmbAlrt_strat
        free_alert_text += "\n" + str_enter_short + "\n( SL: " + tostring ( strat_SL ) + " | TP: " + tostring ( strat_TP ) + " )"
else if exit_long
    strat_trigger   :=  2
    if i_CmbAlrt_strat
        free_alert_text += "\n" + str_exit_long
else if exit_short
    strat_trigger   := -2
    if i_CmbAlrt_strat
        free_alert_text += "\n" + str_exit_short
else if take_profit_long
    strat_trigger   :=  3
    if i_CmbAlrt_strat
        free_alert_text += "\n" + str_TP_long
else if take_profit_short
    strat_trigger   := -3
    if i_CmbAlrt_strat
        free_alert_text += "\n" + str_TP_short
else if strat_RR_L and strat_continuous_TP_L
    strat_trigger   :=  4
    string ( na ) // Pine limitation
else if strat_RR_S and strat_continuous_TP_S
    strat_trigger   := -4
    string ( na ) // Pine limitation
else if strat_trigger[1] !=  strat_SL and ( enter_long[1] or enter_short[1] or  strat_SL != strat_trigger_SL )
    strat_trigger    :=  strat_SL
    strat_trigger_SL :=  strat_SL
    string ( na ) // Pine limitation
else if strat_trigger[1] != -strat_TP and ( enter_long[3] or enter_short[3] or -strat_TP != strat_trigger_TP )
    strat_trigger    := -strat_TP
    strat_trigger_TP := -strat_TP
    string ( na ) // Pine limitation

plot ( strat_trigger, "Strategy Trigger", na, editable = false, display = display.none )




uptrend_began   = calc_state > 0 and calc_state[1] <= 0
dntrend_began   = calc_state < 0 and calc_state[1] >= 0
above_KC        = close_above_kc and not close_above_kc[1]
below_KC        = close_below_kc and not close_below_kc[1]
BB_squeezed     = BB_squeeze and not BB_squeeze[1]

if      uptrend_began
    if i_CmbAlrt_uptrend
        free_alert_text += "\n" + str_uptrend
else if dntrend_began
    if i_CmbAlrt_dntrend
        free_alert_text += "\n" + str_dntrend

if      above_KC
    if i_CmbAlrt_aboveKC
        free_alert_text += "\n" + str_aboveKC
else if below_KC
    if i_CmbAlrt_belowKC
        free_alert_text += "\n" + str_belowKC

if BB_squeezed
    if i_CmbAlrt_BBsqeez
        free_alert_text += "\n" + str_BBsqueeze

// if      pivots_ph
//     if i_CmbAlrt_pivotH
//         free_alert_text += "\n" + str_pivot_high
// else if pivots_pl
//     if i_CmbAlrt_pivotL
//         free_alert_text += "\n" + str_pivot_low

// if      div_reg_bull
//     if i_CmbAlrt_regBull
//         free_alert_text += "\n" + str_reg_bull
// else if div_reg_bear
//     if i_CmbAlrt_regBear
//         free_alert_text += "\n" + str_reg_bear
// else if div_hid_bull
//     if i_CmbAlrt_hidBull
//         free_alert_text += "\n" + str_hid_bull
// else if div_hid_bear
//     if i_CmbAlrt_hidBear
//         free_alert_text += "\n" + str_hid_bear




if ( i_CmbAlrt_uptrend and uptrend_began ) or
  ( i_CmbAlrt_dntrend and dntrend_began ) or
  ( i_CmbAlrt_aboveKC and above_KC ) or
  ( i_CmbAlrt_belowKC and below_KC ) or
  ( i_CmbAlrt_BBsqeez and BB_squeezed ) or
  ( i_CmbAlrt_strat and strat_trigger % 1 == 0 and strat_trigger != 0 and strat_trigger <= 3 and strat_trigger >= -3 )
    alert ( free_alert_text, alert.freq_once_per_bar_close )



alertcondition ( enter_long,        alert_enter_long,   alert_prefix + alert_enter_long )
alertcondition ( enter_short,       alert_enter_short,  alert_prefix + alert_enter_short )
alertcondition ( exit_long,         alert_SL_L,         alert_prefix + alert_SL_L )
alertcondition ( exit_short,        alert_SL_S,         alert_prefix + alert_SL_S )
alertcondition ( take_profit_long,  alert_tpStrat_L,    alert_prefix + alert_tpStrat_L )
alertcondition ( take_profit_short, alert_tpStrat_S,    alert_prefix + alert_tpStrat_S )
alertcondition ( uptrend_began,     alert_uptrend,      alert_prefix + alert_uptrend )
alertcondition ( dntrend_began,     alert_dntrend,      alert_prefix + alert_dntrend )
alertcondition ( above_KC,          alert_above_kc,     alert_prefix + alert_above_kc )
alertcondition ( below_KC,          alert_below_kc,     alert_prefix + alert_below_kc )
alertcondition ( BB_squeezed,       alert_BB_squeeze,   alert_prefix + alert_BB_squeeze )
// alertcondition ( div_reg_bull,      alert_div_reg_bull, alert_prefix + alert_div_reg_bull )
// alertcondition ( div_reg_bear,      alert_div_reg_bear, alert_prefix + alert_div_reg_bear )
// alertcondition ( div_hid_bull,      alert_div_hid_bull, alert_prefix + alert_div_hid_bull )
// alertcondition ( div_hid_bear,      alert_div_hid_bear, alert_prefix + alert_div_hid_bear )

// alertcondition ( pivots_ph,         alert_pivot_high,   alert_prefix + alert_pivot_high )
// alertcondition ( pivots_pl,         alert_pivot_low,    alert_prefix + alert_pivot_low )





///////////////////////////////////////////////////////////////////////////////
// (c) 2021, Trendespresso

		


TE C (Cappuccino)

For when you need a shot of clarity.
Based on TSI, BBWP, and HVP.
Momentum + Volatility.

f_momentum_colored_candles ( up, down ) => TSI_hist >= midbound ? up : down
barcolor ( i_momen_cand    ? f_momentum_colored_candles ( i_c_MoCand_UP, i_c_MoCand_DN ) : na, editable = false )
barcolor ( candles_vol_col ? VOLATILITY3 : na, editable = false )


varip def_linewidth = 4

plot ( show_volatility ? volatility : na,
       str_vol,
       VOLATILITY2,
       def_linewidth,
       plot.style_columns,
       histbase = 0,
       display  = display.all,
       editable = false )

plot ( volatility,
       str_vol,
       VOLATILITY1,
       def_linewidth,
       plot.style_stepline,
       histbase = 0,
       display  = display.none )

plot ( i_fill_vol ? FILL_VOL : na,
       str_vol + str_spc + str_fill,
       VOLATILITY2,
       def_linewidth,
       plot.style_columns,
       histbase = zero_line,
       display  = display.all,
       editable = false )

plot ( hvp,
       str_hvp + str_spc + str_fill,
       f_hvpColorVolatility1 ( hvp ),
       def_linewidth,
       plot.style_columns,
       histbase = 0,
       display  = display.none )

plot ( hvp,
       str_hvp,
       grayLine,
       def_linewidth,
       plot.style_line,
       histbase = 0,
       display  = display.none )

plot ( bbwp,
       str_bb + str_spc + str_fill,
       f_hvpColorVolatility1 ( bbwp ),
       def_linewidth,
       plot.style_columns,
       histbase = 0,
       display  = display.none )

plot ( bbwp,
       str_bb,
       grayLine,
       def_linewidth,
       plot.style_line,
       histbase = 0,
       display  = display.none )

plot ( not i_fill_vol or i_fill_vol_wave != str_mom ? TSI_hist : na,
      str_mom + str_spc + str_fill,
      color_momentum_fill,
      def_linewidth,
      plot.style_area,
      histbase = zero_line,
      display = display.none )

plot ( not i_line_vol or i_line_vol_wave != str_mom ? TSI_hist : na,
      str_mom,
      color_momentum_line,
      def_linewidth,
      plot.style_line,
      histbase = zero_line,
      display = display.none )

plot ( not i_fill_vol or i_fill_vol_wave != str_trnd ? TSI : na,
       str_trnd + str_spc + str_fill,
       color.new ( #154650, 47 ),
       def_linewidth,
       plot.style_area,
       histbase = zero_line,
       display = display.all )

plot ( not i_line_vol or i_line_vol_wave != str_trnd ? TSI : na,
       str_trnd,
       color_bull,
       def_linewidth,
       plot.style_line,
       histbase = zero_line,
       display  = display.all )

plot ( not i_fill_vol or i_fill_vol_wave != str_trnd + str_spc + str_sig ? TSI_Signal : na ,
      str_trnd + str_spc + str_sig + str_spc + str_fill,
      color.new ( #57330D, 70 ),
      def_linewidth,
      plot.style_area,
      histbase = zero_line,
      display  = display.all )

plot ( not i_line_vol or i_line_vol_wave != str_trnd + str_spc + str_sig ? TSI_Signal : na,
      str_trnd + str_spc + str_sig,
      #9C550C,
      def_linewidth,
      plot.style_line,
      histbase = zero_line,
      display  = display.all )

plot ( i_line_vol ? LINE_VOL : na,
       str_vol,
       VOLATILITY1,
       def_linewidth,
       plot.style_line,
       histbase = 0,
       display  = display.all,
       editable = false )




bandH   =   hline   ( high_alert,   str_hialert,        color.new ( color_bull,    50 ),    hline.style_dashed, 2 )
bandL   =   hline   ( low_alert,   str_loalert,        color.new ( color_bear,    50 ),    hline.style_dashed, 2 )
bandZ   =   hline   ( zero_line,  str_midbound,       color.new ( color.silver,  70 ),    hline.style_dashed, 2 )
bandT   =   hline   ( bound,        "Absolute Top",     color.new ( color_bull,    80 ),    hline.style_solid,  2 )
bandB   =   hline   ( 0,            "Absolute Bottom",  color.new ( color_bear,    80 ),    hline.style_solid,  2 )
fill                ( bandH,        bandT,              color.new ( color_bull,   100 ), 100, str_hialert + " Zone" )
fill                ( bandB,        bandL,              color.new ( color_bear,   100 ), 100, str_loalert + " Zone" )






// Set Label offset
f_label_X_Loc ( i ) => time_close + ( ( time_close - time_close[1] ) * i )
varip label_Y_Loc   = midbound


// Create background label
varip lbl_dbl_vol_space = str_ln + str_ln + str_ln + str_ln
var lbl_avg_used        = ( i_lbl_mode == ( str_hvp + str_avg ) ) or ( i_lbl_mode == ( str_bb + str_avg ) ) or ( i_lbl_mode == str_all_avgv ) or ( i_lbl_mode == str_fill and fill == str_all_avgv )
var lbl_double          = i_lbl_mode == str_all_vol or i_lbl_mode == str_all_avgv or ( i_lbl_mode == str_fill and fill == str_all_avgv )


f_lbl_mode_text () =>
    return = string ( na )
    d = str_ln + "00.00" + str_pct
    if lbl_avg_used
        d +=" " + str_avg
    if lbl_double or i_lbl_mode == str_hvp or i_lbl_mode == ( str_hvp + str_avg )
        return := i_lbl_longName ? str_hvp : str_sht_hvp
    else if i_lbl_mode == str_fill
        return := fill == str_hvp or ( lbl_avg_used and fill == str_all_avgv ) ? i_lbl_longName ? str_hvp : str_sht_hvp : fill == str_bb ? i_lbl_longName ? str_bb : str_sht_bb : str_disp
    else if i_lbl_mode == str_bb or i_lbl_mode == ( str_bb + str_avg )
        return := i_lbl_longName ? str_bb : str_sht_bb
    else
        return := str_disp
    return += d


labelbg = i_lbl_mode != str_none ? label.new ( f_label_X_Loc ( i_lbl_offset          ), label_Y_Loc, f_lbl_mode_text () + ( lbl_double ? lbl_dbl_vol_space : string ( na ) ), xloc.bar_time, yloc.price, i_lbl_col_bg, label.style_label_left, color_none, lbl_txtsize1, i_lbl_txt_align ) : label ( na )
label.delete ( labelbg[1] )


f_avg_price ( length ) => abs ( percentile_linear_interpolation ( ohlc4_HA, length, 50 ) )

label_tt_price = float ( na )
if bar_index % 50 == 0 or bar_index <= 10
    label_tt_price := f_avg_price ( 50 )
else if ohlc4_HA >= 1000 and na ( label_tt_price[1] )
    label_tt_price := 1001
else
    label_tt_price := label_tt_price[1]



f_osc_as_text ( input_osc, input_decimals, extra_zeroes ) =>
    osc         = input_osc < 0 ? abs ( input_osc ) : input_osc
    num         = floor ( osc )
    decimals    = input_decimals >= 0 ? input_decimals : label_tt_price >= 1000 ? 0 : label_tt_price >= 100 ? 1 : label_tt_price >= 1 ? 2 : label_tt_price >= 0.1 ? 3 : label_tt_price >= 0.01 ? 4 : 5
    factor      = pow ( 10, decimals )
    // there is a bug in Pine v4 !
    // taking a number such as 99.6 and multiplying it by 100 then dividing it by 100
    // does NOT return 99.6
    // technically it returns 99.59999999999999430
    // to get around this BUG, we must round to the 10th decimal place only
    // the bug starts to occur around the 12th decimal place
    dec         = floor ( ( round ( osc - num, 6 ) ) * factor ) / factor
    return      = tostring ( num + dec )
    if num < 10.0 and extra_zeroes > 0
        for i = 1 to extra_zeroes
            return := "0" + return
    if decimals > 0
        z = decimals
        if ( num > 0.0 and ( osc % 1 == 0.0 or dec == 0.0 ) ) or ( num + dec ) == 0.0
            return += "."
        else
            d = dec
            for i = 1 to decimals
                if d % 1 != 0.0
                    d *= 10
                    z -= 1
                    continue
                else
                    break
            pine = string ( na ) // Pine limitation
        if z > 0
            for i = 1 to z
                return += "0"
    return := input_osc < 0 ? "–" + return : return


// HELPER FUNCTION: Convert the given TSI value into the correct price
f_label_tsi_price ( number ) =>
    return      = string ( na )
    if number < 0
        return := "– Inf"
    else if number <= 99999999
        if i_lbl_tsi_k_val and label_tt_price >= 1000
            return := f_osc_as_text ( number / 1000, 1, 0 ) + "k"
        else
            return := f_osc_as_text ( number,       -1, 0 )
    else
        return := "+ Inf"
    return
    

// hover over shows % increase or decrease needed
f_label_tsi_percent ( number ) =>
    raw     = ( ( number - ohlc4_HA ) / ohlc4_HA ) * 100
    value   = ( raw > -100.0 and number <= 99999999 ? f_osc_as_text ( raw, 2, 0 ) : " Inf" ) + str_pct
    return  =   raw >=   0.0 ? "+" + value : value


f_label_tsi_text ( number, on_label ) =>
    return = string ( na )
    if i_lbl_tsi_txt_mthd == lbl_tsi_val
        if on_label
            return := f_label_tsi_price ( number )
        else
            return := f_label_tsi_percent ( number )
    else if i_lbl_tsi_txt_mthd == lbl_tsi_pct
        if on_label
            return := f_label_tsi_percent ( number )
        else
            return := f_label_tsi_price ( number )
    else
        if on_label
            return := f_label_tsi_price ( number ) + "\n\n" + f_label_tsi_percent ( number )
        else
            return := f_label_tsi_price ( number ) + "\n" + f_label_tsi_percent ( number )
    return


varip lbl_tsi_align_txt = i_lbl_tsi_txt_mthd == lbl_tsi_val or i_lbl_tsi_txt_mthd == lbl_tsi_pct ? text.align_left : text.align_center


f_lbl_color ( osc, threshold, under, over ) => osc < threshold ? under : over

f_lbl_tsi_txt_color ( cross_line ) =>
    return = color ( na )
    if cross_line == "zero"
        return := f_lbl_color ( TSI,        zero_line,        i_lbl_tsi_txt_colUP, i_lbl_tsi_txt_colDN )
    else if cross_line == "low"  or cross_line == "lo"
        return := f_lbl_color ( TSI,        low_alert,         i_lbl_tsi_txt_colUP, i_lbl_tsi_txt_colDN )
    else if cross_line == "high" or cross_line == "hi"
        return := f_lbl_color ( TSI,        high_alert,         i_lbl_tsi_txt_colUP, i_lbl_tsi_txt_colDN )
    else if cross_line == "signal" or cross_line == "sig"
        if i_TSI_user_crx < 0
            return := f_lbl_color ( TSI_hist,   zero_line,    i_lbl_tsi_txt_colUP, i_lbl_tsi_txt_colDN )
        else
            return := f_lbl_color ( TSI - user_TSI, 0,          i_lbl_tsi_txt_colUP, i_lbl_tsi_txt_colDN )
    return

label_tsi_hi = i_lbl_incl_tsi  ? label.new ( f_label_X_Loc ( i_lbl_offset_tsi  ), high_alert,  f_label_tsi_text ( TSI_hiLine_cross,   true ), xloc.bar_time, yloc.price, i_lbl_tsi_col_bg, label.style_label_left, f_lbl_tsi_txt_color ( "high" ),  lbl_txtsize1, lbl_tsi_align_txt, f_label_tsi_text ( TSI_hiLine_cross,   false ) ) : label ( na )
label_tsi_lo = i_lbl_incl_tsi  ? label.new ( f_label_X_Loc ( i_lbl_offset_tsi  ), low_alert,  f_label_tsi_text ( TSI_loLine_cross,   true ), xloc.bar_time, yloc.price, i_lbl_tsi_col_bg, label.style_label_left, f_lbl_tsi_txt_color ( "low" ),   lbl_txtsize1, lbl_tsi_align_txt, f_label_tsi_text ( TSI_loLine_cross,   false ) ) : label ( na )
label_tsi_zr = i_lbl_incl_tsi  ? label.new ( f_label_X_Loc ( i_lbl_offset_tsi  ), zero_line, f_label_tsi_text ( TSI_zeroLine_cross, true ), xloc.bar_time, yloc.price, i_lbl_tsi_col_bg, label.style_label_left, f_lbl_tsi_txt_color ( "zero"),   lbl_txtsize1, lbl_tsi_align_txt, f_label_tsi_text ( TSI_zeroLine_cross, false ) ) : label ( na )


label.delete ( label_tsi_hi[1] )
label.delete ( label_tsi_lo[1] )
label.delete ( label_tsi_zr[1] )
		


TE D (Doppio)

Divergences made crystal clear.
Apply to TE C and see magic happen.
The next move has never been so obvious.

divFind_plFound_pnt = na ( pivotlow ( divFind_print, divFind_lbL, i_divFind_lbR ) ) ? false : true divFind_phFound_pnt = na ( pivothigh ( divFind_print, divFind_lbL, i_divFind_lbR ) ) ? false : true
divFind_bullCond = false
divFind_bearCond = false

f_divergence_finder ( osc, print_on, avg_price, loww, highh, lookback, pivotlow, pivothigh, iteration, req_confirmed, _trend_line ) =>
    // general osc and price values
    divOsc      = osc[lookback]
    divOsc_L    = valuewhen ( pivotlow,  divOsc, iteration )
    divOsc_H    = valuewhen ( pivothigh, divOsc, iteration )
    avgLB       = avg_price[lookback]
    avgLB_L     = valuewhen ( pivotlow,  avgLB,  iteration )
    avgLB_H     = valuewhen ( pivothigh, avgLB,  iteration )
    lowLB       = loww[lookback]
    lowLB_L     = valuewhen ( pivotlow,  lowLB,  iteration )
    highLB      = highh[lookback]
    highLB_H    = valuewhen ( pivothigh, highLB, iteration )
    // allow divergences?
    bar_indexLB = bar_index - lookback
    pl_barindex = valuewhen ( pivotlow,  bar_indexLB, iteration )
    ph_barindex = valuewhen ( pivothigh, bar_indexLB, iteration )
    allow_bull  = bar_indexLB - pl_barindex <= i_divFind_rangeUpper and bar_indexLB - pl_barindex >= i_divFind_rangeLower
    allow_bear  = bar_indexLB - ph_barindex <= i_divFind_rangeUpper and bar_indexLB - ph_barindex >= i_divFind_rangeLower
    // find osc divergences
    oscLL       = divOsc < divOsc_L
    oscHL       = divOsc > divOsc_L
    oscHH       = divOsc > divOsc_H
    oscLH       = divOsc < divOsc_H
    // find price divergences
    priceLL     = avgLB < avgLB_L or lowLB  < lowLB_L
    priceHL     = avgLB > avgLB_L or lowLB  > lowLB_L
    priceHH     = avgLB > avgLB_H or highLB > highLB_H
    priceLH     = avgLB < avgLB_H or highLB < highLB_H
    // eliminate invalid hidden divergences
    filter_line = _trend_line[lookback]
    filter_prev = valuewhen ( pivotlow, filter_line, iteration )
    allow_Hull  = true // filter_line > filter_prev
    allow_Hear  = true // filter_line < filter_prev
    // return regular bull, hidden bull, regular bear, hidden bear
    [ allow_bull and priceLL and oscHL and ( req_confirmed ? pivotlow  : true ),
      allow_bull and priceHL and oscLL and ( req_confirmed ? pivotlow  : true ) and allow_Hull, 
      allow_bear and priceHH and oscLH and ( req_confirmed ? pivothigh : true ), 
      allow_bear and priceLH and oscHH and ( req_confirmed ? pivothigh : true ) and allow_Hear,
      pl_barindex,
      ph_barindex,
      valuewhen ( pivotlow,  print_on[lookback], iteration ),
      valuewhen ( pivothigh, print_on[lookback], iteration ) ]

varip divFind_total_drives = i_divFind_drives

divFind_regBullDivs = array.new_bool  ( divFind_total_drives )
divFind_hidBullDivs = array.new_bool  ( divFind_total_drives )
divFind_regBearDivs = array.new_bool  ( divFind_total_drives )
divFind_hidBearDivs = array.new_bool  ( divFind_total_drives )



f_populate_divergence_array ( osc, index, pivotlow, pivothigh, low_src, high_src ) =>
    [ reg_bull,
      hid_bull, 
      reg_bear, 
      hid_bear,
      pl_barindex,
      ph_barindex,
      pl_osc,
      ph_osc ] 
      = f_divergence_finder ( osc, divFind_print, ohlc4_HA, low_src, high_src, i_divFind_lbR, pivotlow, pivothigh, index + 1, true, divFind_MAfilter )
    array.set ( divFind_regBullDivs, index, reg_bull )
    array.set ( divFind_hidBullDivs, index, hid_bull )
    bull_line = f_plot_div_line ( pl_barindex, pl_osc, divFind_print, i_divFind_lbR, -displayOffset, reg_bull ? i_divFind_lineColor_bull : i_divFind_lineColor_hiddenBull, line.style_solid )
    line.delete ( reg_bull or hid_bull      ? line ( na )   : bull_line )
    line.delete (     divFind_bullCond[1]   ? bull_line     : line ( na ) )
    line.delete ( divFind_enable            ? line ( na )   : bull_line )
    array.set ( divFind_regBearDivs, index, reg_bear )
    array.set ( divFind_hidBearDivs, index, hid_bear )
    bear_line = f_plot_div_line ( ph_barindex, ph_osc, divFind_print, i_divFind_lbR,  displayOffset, divFind_bearCond[1] ? color_none : reg_bear ? i_divFind_lineColor_bear : i_divFind_lineColor_hiddenBear, line.style_solid )
    line.delete ( reg_bear or hid_bear      ? line ( na )   : bear_line )
    line.delete (     divFind_bearCond[1]   ? bear_line     : line ( na ) )
    line.delete ( divFind_enable            ? line ( na )   : bear_line )


divFind_lowClosures  = close_HA // lowest  ( close_HA, i_divFind_rangeUpper )
divFind_highClosures = close_HA // highest ( close_HA, i_divFind_rangeUpper )


// Multiple drives of divergence
f_divFind ( num ) =>
    if i_divFind_drives >= num
        index = num - 1
        f_populate_divergence_array     ( divFind_print, index, divFind_plFound_pnt, divFind_phFound_pnt, low_HA,              high_HA )
        if not array.get ( divFind_regBullDivs, index ) and
           not array.get ( divFind_hidBullDivs, index ) and
           not array.get ( divFind_regBearDivs, index ) and
           not array.get ( divFind_hidBearDivs, index )
            f_populate_divergence_array ( divFind_print, index, divFind_plFound_pnt, divFind_phFound_pnt, divFind_lowClosures, divFind_highClosures )
f_divFind ( 1 )
f_divFind ( 2 )
f_divFind ( 3 )
f_divFind ( 4 )
f_divFind ( 5 )
f_divFind ( 6 )
f_divFind ( 7 )
f_divFind ( 8 )



div_reg_bull            = array.includes ( divFind_regBullDivs, true )
div_reg_bear            = array.includes ( divFind_regBearDivs, true )
div_hid_bull            = array.includes ( divFind_hidBullDivs, true )
div_hid_bear            = array.includes ( divFind_hidBearDivs, true )

divFind_bullCond       := div_reg_bull or div_hid_bull
divFind_bearCond       := div_reg_bear or div_hid_bear

pivot_but_no_bullDiv    = divFind_plFound_pnt and ( ( not divFind_bullCond and not divFind_bullCond[1] and not divFind_bullCond[2] ) or not divFind_enable )
pivot_but_no_bearDiv    = divFind_phFound_pnt and ( ( not divFind_bearCond and not divFind_bearCond[1] and not divFind_bearCond[2] ) or not divFind_enable )

divFind_bullIcon        = ( divFind_onChart ? low  [ i_divFind_lbR ] : divFind_print [ i_divFind_lbR ] ) - displayOffsetIcon
divFind_bearIcon        = ( divFind_onChart ? high [ i_divFind_lbR ] : divFind_print [ i_divFind_lbR ] ) + displayOffsetIcon



plotshape (
	 pivot_but_no_bearDiv ? divFind_bearIcon : na,
	 "Pivot High",
	 shape.triangledown,
	 location.absolute,
	 color.new ( grayLine, 70 ),
	 offset     = -i_divFind_lbR,
	 size       = size.tiny,
	 display    = display.all
	 )

plotshape (
	 pivot_but_no_bullDiv ? divFind_bullIcon : na,
	 "Pivot Low",
	 shape.triangleup,
	 location.absolute,
	 color.new ( grayLine, 70 ),
	 offset     = -i_divFind_lbR,
	 size       = size.tiny,
	 display    = display.all
	 )






// with `line` we have to delete it if there's no forming
// divergence because for some strange reason it won't
// print if we make the initial `line.new` call conditional
// doing `potential_bearish_div ? line.new ( ... ) : line ( na )
// returns no line at all


f_print_forming_divergence ( osc, pivotlow, pivothigh, iteration, price_low, price_high ) =>
    [ reg_bull_forming, 
      hid_bull_forming, 
      reg_bear_forming, 
      hid_bear_forming,
      pl_barindex,
      ph_barindex,
      divOsc_L,
      divOsc_H ] 
      = f_divergence_finder ( osc, divFind_print, ohlc4_HA, price_low, price_high, i_divFind_lbR, pivotlow, pivothigh, iteration, false, divFind_MAfilter )
    
    bearish_div_forming = reg_bear_forming or hid_bear_forming
    bullish_div_forming = reg_bull_forming or hid_bull_forming
    
    
    forming_bear_div1 = line.new ( ph_barindex, divOsc_H + displayOffset,
                                   bar_index, divFind_print + displayOffset,
                                   xloc.bar_index, extend.none,
                                   hid_bear_forming ? i_divFind_lineColor_hiddenBear : i_divFind_lineColor_bear,
                                   line.style_dotted, 2 )
    line.delete ( forming_bear_div1[1] )
    line.delete ( bearish_div_forming ? line ( na ) : forming_bear_div1 )
    
    
    forming_bear_div2 = bearish_div_forming ?
                         label.new (
                         bar_index,
                         divFind_print + ( displayOffset * 0.225 ),
                         arw_dn,
                         xloc.bar_index,
                         yloc.price,
                         color_none,
                         label.style_label_down,
                         hid_bear_forming ? i_divFind_hiddenBearColor : i_divFind_bearColor,
                         size.normal,
                         text.align_center,
                         string ( na ) ) : label ( na )
    label.delete ( forming_bear_div2[1] )
    
    forming_bull_div1 = line.new ( pl_barindex, divOsc_L - displayOffset,
                                   bar_index, divFind_print - displayOffset,
                                   xloc.bar_index, extend.none,
                                   hid_bull_forming ? i_divFind_lineColor_hiddenBull : i_divFind_lineColor_bull,
                                   line.style_dotted, 2 )
    line.delete ( forming_bull_div1[1] )
    line.delete ( bullish_div_forming ? line ( na ) : forming_bull_div1 )
    
    forming_bull_div2 = bullish_div_forming ?
                         label.new (
                         bar_index,
                         divFind_print - ( displayOffset * 0.225 ),
                         arw_up,
                         xloc.bar_index,
                         yloc.price,
                         color_none,
                         label.style_label_up,
                         hid_bull_forming ? i_divFind_hiddenBullColor : i_divFind_bullColor,
                         size.normal,
                         text.align_center,
                         string ( na ) ) : label ( na )
    label.delete ( forming_bull_div2[1] )
    
    bearish_div_forming or bullish_div_forming
		


TE SW (Strategy Wrapper)

Backtest your expected return. TE A's right-hand.

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
//
// if you want to reach me and I do not respond on TradingView, google my username
// 
// I also have other private Indicators I'm always working on
// Feel free to reach out to me here or via the Trendespresso website for info and links!
//
// All comments, bugfixes, and suggestions welcome :)
//
// © trendespresso
//@version=4




varip ver_num               = "1.4"
varip script_long_ver       = "v" + ver_num
varip script_short_ver      =       ver_num
varip script_abrev          = "TE SW"
varip script_long_title     = "Trendespresso Strategy Wrapper" + " [ " + script_long_ver  + " ]"
varip script_short_title    = script_abrev                     + " [ " + script_short_ver + " ]"



strategy ( script_long_title, script_short_title, true, max_bars_back = 600, max_lines_count = 140, max_labels_count = 35,
          process_orders_on_close = true, backtest_fill_limits_assumption = 10, default_qty_type = strategy.percent_of_equity,
          default_qty_value = 100, slippage = 20, commission_type = strategy.commission.percent, commission_value = 0.1,
          initial_capital = 1000 )

// study ( script_long_title, script_short_title, true, max_bars_back = 600, max_lines_count = 140, max_labels_count = 35 )




/////////////////////////////////////////////////////////////////////////////////
// VERSION + DEBUG

varip version               = script_long_ver + "\nPublished January 2, 2022\nby Trendespresso"

//
// Variables in Pine v4:
//
//      Writing a variable in global scope without 'var' or 'varip' will force
//      the variable to be continously recalcuated in realtime.
//
//      Writing a variable within a function will only update the variable when
//      the function is called. Using global variable names within a function
//      will not work since Pine will grab the value of the global variable.
//      However variables initialized and used within a function are local scope
//      only meaning they cannot be accessed in global scope unless passed out
//      of the function via return. Multiple variables can be returned from a
//      function via tuple: [ return1, return2 ] = function ( arg1, arg2 )
//      The number of returned variables and number of arguments need not match
//      with a function. Also of note is that the 'security' call in Pine is
//      technically a function and thus multiple variables can be returned
//      via tuple from a single 'security call' – pretty cool!
//
//      Writing a variable in global scope with 'var' permits the variable to
//      maintain its value across bars until an update is issues (ex. := or += )
//
//      Writing a variable in global scope with 'varip' forces the variable to
//      maintain its value across bars. Updating the variable in any later bar
//      will not affect a variable initialized with 'varip' for any future bar.
//
//      Common sense thus suggests that variables should be initialized without
//      'var' or 'varip' if you desire them to be updated on every bar. Variables
//      should be initialized with 'var' if you desire them to be updated
//      occasionally but hold their value between changes; this setting thus assists
//      in reducing runtime and system resources since the variable is not
//      typically re-calculated on every bar. Lastly, variables should only be
//      initialized with 'varip' if you desire them to retain their value across
//      the entire script with no re-calculating required going forward; this
//      setting greatly reduces runtime since variables are only calculated once.
//      I've tried to write thie script to take advantage of these runtime
//      reductions, especially since every 'security' call – every additional
//      timeframe – results in immense increases in runtime and system resources.
//      Anything I can do to increase efficiency is good in my book!
//
//      Also of note, most text and string variables are initialized with 'varip'
//      since they do not change across bars. Pretty nifty especially if you want
//      to change the text! Instead of using 'Replace All' which sometimes has
//      unintended consequences, or trying to find each instance yourself which
//      is a total pain, now the text is easily changeable from one place.
//

//
// If you find this script helpful, educational, or otherwise engaging, please
// leave a comment or drop me a line! Cheers
//




//
// COLORS
//

varip color_bull            = color.new ( #0097A7,  0 )
varip color_bear            = color.new ( #D16A00,  0 )
varip color_faded_bull      = color.new ( color_bull, 47 )
varip color_faded_bear      = color.new ( color_bear, 47 )

varip color_none            = color.new ( #2a2e39,  100 )
varip color_white_off       = color.new ( color.white, 100 )

varip groupGlobal           = "Global"
varip groupTP               = "Take Profit"
varip str_exit              = "Exit"
varip str_SL                = "Stop Loss"
varip str_triangle          = "Triangle"
varip str_entry             = "Entry"
varip str_supertrend        = "Supertrend"
varip str_strat             = "Strategy"
varip groupStrat            = str_strat + " (" + str_supertrend + ")"
varip groupStratPct         = str_strat + " (Take Profit & Stop Loss)"
varip groupStratFilt        = str_strat + " (Filtering)"
varip groupStratIcons       = str_strat + " (Icons & Labels)"
varip groupStratTest        = str_strat + " Tester"



//
// ALERT TEXT
//
varip str_long          = "Long"
varip str_shrt          = "Short"

varip str_pivot_high    = "High Pivot"
varip str_pivot_low     = "Low Pivot"

varip alert_prefix      = "{{ticker}} {{interval}} "
varip str_sep           = ": "

varip alert_enter_long  = script_abrev + str_sep + str_strat + " " + str_long + " " + str_entry
varip alert_enter_short = script_abrev + str_sep + str_strat + " " + str_shrt + " " + str_entry
varip alert_SL_L        = script_abrev + str_sep + str_strat + " " + str_long + " " + str_exit
varip alert_SL_S        = script_abrev + str_sep + str_strat + " " + str_shrt + " " + str_exit
varip alert_tpStrat_L   = script_abrev + str_sep + str_strat + " " + str_long + " " + groupTP
varip alert_tpStrat_S   = script_abrev + str_sep + str_strat + " " + str_shrt + " " + groupTP
varip alert_tp_long     = script_abrev + str_sep + groupTP + " (" + str_long  + ")"
varip alert_tp_short    = script_abrev + str_sep + groupTP + " (" + str_shrt + ")"



varip str_tri_tt            = "Do not blindly trade\nthe triangles!\n\nIncorporate your own\ntechnical analysis\nand market structure\nunderstanding."
varip str_txt_color_tt      = " Bull Text Color | Bear Text Color"




i_src = input ( close, "Select TE 'Strategy Trigger' Plot", input.source, group = groupGlobal, tooltip = version )




// - - - - STRATEGY TESTER - - - -
varip strat_start_date  = timestamp ( "01 Jan 2021 00:00 +0000" )
varip str_start_date    = "Start Date"
varip str_end_date      = "End Date"

i_strat_startTime       = input ( strat_start_date,                         str_start_date, input.time,     group = groupStratTest, inline = str_start_date )
i_strat_endTime         = input ( timestamp ( "31 Dec 2029 00:00 +0000" ),  str_end_date,   input.time,     group = groupStratTest, inline = str_end_date )
i_strat_enable_L        = input (  true, "Long Trades",                                     input.bool,     group = groupStratTest )
i_strat_enable_S        = input (  true, "Short Trades",                                    input.bool,     group = groupStratTest )

f_inDateRange ( start, end ) => time >= start and time <= end
inDateRange = f_inDateRange ( i_strat_startTime, i_strat_endTime )
// - - - -    *   *   *    - - - -




// strings
varip str_TP_inv    = "Invert"


varip std_step      = 0.05
varip max_TP_inv    = 0.50
varip max_TP_inv_tt = "50"



// tooltips
varip tp_pct_tt     = "Percentage of the\nremaining open position\nto close on each diamond\nwhen in profit.\n\n" +
                       str_TP_inv + ":\nTake more profit\nas additional TP\ntargets are achieved\nrather than taking\nmore profit on the\nbeginning targets\nby reserving at least\n" +
                       max_TP_inv_tt + "% of the original\nposition for the Exit.\n\nEach Take Profit hit will\nbe calculated as such:\n% TP * # TP\n\n\n" +
                       str_TP_inv + " example using 15%:\n\n15% * 1st TP Target =\nTP 15% of remaining position\n\n15% * 2nd TP Target =\nTP 30% of remaining position\n\n15% * 3rd TP Target =\nTP 45% of remaining position\n\netc"



i_TP_pct            = input (     0,    "% TP Each Diamond",    input.float,    minval = 0,         group = groupStratPct,  tooltip = tp_pct_tt,    step = 0.5,      maxval = 100,  inline = tp_pct_tt )
i_TP_inv            = input ( false,    str_TP_inv,             input.bool,                         group = groupStratPct,                                                          inline = tp_pct_tt )




///////////////////////////////////////////////////////////////////////////////
// Entry Triangles

i_tri_txt_col_L     = input ( color.white,  string ( na ),      input.color,    group = groupStratIcons, inline = str_entry )
i_tri_txt_col_S     = input ( color.white,  string ( na ),      input.color,    group = groupStratIcons, inline = str_entry )

i_triangles         = input (  true,        "Entry Icons",      input.bool,     group = groupStratIcons, inline = str_entry, tooltip = str_tri_tt + "\n\n" + str_txt_color_tt )





///////////////////////////////////////////////////////////////////////////////
// Exit X's


i_sl_col_txt_Bu     = input ( color_white_off,  string ( na ),  input.color,    group = groupStratIcons, inline = str_exit, tooltip = str_txt_color_tt )
i_sl_col_txt_Be     = input ( color_white_off,  string ( na ),  input.color,    group = groupStratIcons, inline = str_exit )

i_small_SL          = input (  true,            "Exit Icons",   input.bool,     group = groupStratIcons, inline = str_exit )





///////////////////////////////////////////////////////////////////////////////
// Take Profit Diamonds

i_tp_col_txt_Bu     = input ( color_white_off,      string ( na ),                              input.color,    group = groupStratIcons, inline = groupTP,      tooltip = str_txt_color_tt )
i_tp_col_txt_Be     = input ( color_white_off,      string ( na ),                              input.color,    group = groupStratIcons, inline = groupTP )
i_tp_icn            = input (  true,                groupTP + " Icons",                         input.bool,     group = groupStratIcons, inline = groupTP )









///////////////////////////////////////////////////////////////////////////////
// Calculations

var trade_cond = 0


strat_trigger   = i_src
enter_long      = strat_trigger ==  1 and   inDateRange
enter_short     = strat_trigger == -1 and   inDateRange
exit_long       = strat_trigger ==  2 and ( inDateRange or trade_cond > 0 )
exit_short      = strat_trigger == -2 and ( inDateRange or trade_cond < 0 )
tp_long         = strat_trigger ==  3 and i_TP_pct > 0
tp_short        = strat_trigger == -3 and i_TP_pct > 0
tp_long_cont    = strat_trigger ==  4 and i_TP_pct > 0
tp_short_cont   = strat_trigger == -4 and i_TP_pct > 0
var strat_SL    = 0.
var strat_TP    = 0.


trade_cond    := enter_long ? 1 : enter_short ? -1 :
                 exit_long  ? 0 : exit_short  ?  0 :
                 trade_cond


if      strat_trigger % 1 != 0 and strat_trigger >= 0
    strat_SL   :=  strat_trigger
else if strat_trigger % 1 != 0 and strat_trigger <= 0
    strat_TP   := -strat_trigger

plot ( strat_SL, "Stop Loss",   color.gray, display = display.none )
plot ( strat_TP, "Take Profit", color.gray, display = display.none )


// strategy calculations 1
var strat_entry_price = float ( na )
strat_entry_price    := enter_long or enter_short ? close : strat_entry_price



// Complicated Invert Take Profit
var TP_count      = 1
strat_valid_TP    = bool ( na )


if i_TP_pct > 0
    
    var strat_original_position_size  = float ( na )
    var strat_position_size           = float ( na )
    
    if enter_long[1]
        strat_original_position_size :=  10000 //strategy.position_size
        strat_position_size          :=  strat_original_position_size
    else if enter_short[1]
        strat_original_position_size := -10000
        strat_position_size          :=  strat_original_position_size
    
    strat_TP_amount   = i_TP_pct * TP_count
    strat_TP_pct      = strat_TP_amount / 100
    TP_amount         = strat_position_size * strat_TP_pct
    strat_valid_TP   := strat_original_position_size * max_TP_inv < strat_position_size - ( strat_position_size * strat_TP_pct )
    
    if i_TP_inv
        if enter_long or enter_short or strat_trigger == 0
            TP_count := 1
        
        if strat_valid_TP
            if      strat_trigger ==  3 and strat_position_size > 0 and strat_position_size - TP_amount > strat_original_position_size * max_TP_inv
                TP_count += 1
                strat_position_size -= TP_amount
            else if strat_trigger == -3 and strat_position_size < 0 and strat_position_size - TP_amount < strat_original_position_size * max_TP_inv
                TP_count += 1
                strat_position_size += abs ( TP_amount )
            strategy.close ( str_long,          when = tp_long,  qty_percent = strat_TP_amount, comment = alert_tpStrat_L, alert_message = alert_prefix + alert_tpStrat_L )
            strategy.close ( str_shrt,          when = tp_short, qty_percent = strat_TP_amount, comment = alert_tpStrat_S, alert_message = alert_prefix + alert_tpStrat_S )
    else
        if strat_valid_TP
            strategy.close ( str_long,          when = tp_long  or tp_long_cont,  qty_percent = strat_TP_amount, comment = alert_tpStrat_L, alert_message = alert_prefix + alert_tpStrat_L )
            strategy.close ( str_shrt,          when = tp_short or tp_short_cont, qty_percent = strat_TP_amount, comment = alert_tpStrat_S, alert_message = alert_prefix + alert_tpStrat_S )




strategy.entry ( str_long, true,    when = i_strat_enable_L and enter_long,  comment = alert_enter_long,  alert_message = alert_prefix + alert_enter_long )
strategy.entry ( str_shrt, false,   when = i_strat_enable_S and enter_short, comment = alert_enter_short, alert_message = alert_prefix + alert_enter_short )
strategy.close ( str_long,          when = exit_long  or enter_short, qty_percent = 100, comment = alert_SL_L, alert_message = alert_prefix + alert_SL_L )
strategy.close ( str_shrt,          when = exit_short or enter_long,  qty_percent = 100, comment = alert_SL_S, alert_message = alert_prefix + alert_SL_S )




// Plot shapes

plotshape ( i_triangles and enter_long,  "Enter " + str_long,             shape.triangleup,   location.belowbar, color_bull,       text = "L",  textcolor = i_tri_txt_col_L, size = size.tiny, display = display.all )
plotshape ( i_triangles and enter_short, "Enter " + str_shrt,             shape.triangledown, location.abovebar, color_bear,       text = "S",  textcolor = i_tri_txt_col_S, size = size.tiny, display = display.all )

plotshape ( i_small_SL  and exit_long,   "Exit " + str_long,              shape.xcross,       location.abovebar, color_bull,       text = "XL", textcolor = i_sl_col_txt_Bu, size = size.tiny, display = display.all )
plotshape ( i_small_SL  and exit_short,  "Exit " + str_shrt,              shape.xcross,       location.belowbar, color_bear,       text = "XS", textcolor = i_sl_col_txt_Be, size = size.tiny, display = display.all )

plotshape ( i_tp_icn    and tp_long,     groupTP + " (" + str_long + ")", shape.diamond,      location.abovebar, color_faded_bull, text = "TP", textcolor = i_tp_col_txt_Bu, size = size.tiny, display = display.all )
plotshape ( i_tp_icn    and tp_short,    groupTP + " (" + str_shrt + ")", shape.diamond,      location.belowbar, color_faded_bear, text = "TP", textcolor = i_tp_col_txt_Be, size = size.tiny, display = display.all )










///////////////////////////////////////////////////////////////////////////////
// (c) 2021, Trendespresso

		


TE MTF PS (Multi-Timeframe Potato Signal)

Born out of respect and awe for The Baked Potato's Triple Confirmation Strategy.
In a single window see Triple Confirmations across multiple timeframes.
Open in TradingView and hover over the label for even greater detail.

// HELPER FUNCTION: Smooth Average Range (for Potato Signal)
smoothrng ( x, t, m ) =>
wper =t * 2 - 1
avrng=ema ( abs ( x - x[1] ), t )
rtn_smooth=ema ( avrng, wper ) * m

// HELPER FUNCTION: Range Filter (for Potato Signal)
rngfilt ( x, r ) =>
    rngfilt =x
    rngfilt := x > nz ( rngfilt[1] ) ? x - r < nz ( rngfilt[1] ) ? nz ( rngfilt[1] ) : x - r : 
       x + r > nz ( rngfilt[1] ) ? nz ( rngfilt[1] ) : x + r


// FUNCTION: Original Potato Signal
f_PotatoSignal ( src ) =>
    smrng=smoothrng ( src, per, mult )
    filt =rngfilt ( src, smrng )


// FUNCTION: Standard Wolfpack ema 3 - ema 8 using 'close' from 'security' as the Source
//           Wolfpack employs the Taylor Series
f_wolfpack ( src ) =>
    WP=ema ( src, 3 ) - ema ( src, 8 )
    WPc=WP + ( WP / 1001.00000 ) + ( WP / 1002000.000 ) + ( WP / 1003000000 ) + ( WP / 1004000000000 )


// FUNCTION: Calculate the MLB waves using 'hlc3' from 'security' and output if it changes
f_MLBwaves ( hlc ) =>
    n1 = 7      //input ( 8, "Channel Length") // 8
    n2 =10      //input ( 10, "Average Length") // 10
    n3 = 4
    esa=ema ( hlc, n1 )
    d2 =ema ( abs ( hlc - esa ), n1 )
    ci =( hlc - esa ) / (0.015 * d2 )
    tci=ema ( ci, n2 )
    wt1=tci
    wt2=sma ( wt1, n3 )
    // if wt1 is greater than wt2, BUY signal is given
    MLB=wt1 - wt2
		


TE MA (Moving Averages)

Easily see the short-term, medium-term, and long-term outlook.

// Initiate Empty Array
varip total_MAs = 6
arr_MAs = array.new_float ( total_MAs )
arr_types = array.new_string ( total_MAs )
arr_lens = array.new_int ( total_MAs )
// String definitions
varip grp_MAs = "Moving Averages"
varip inp_MA1 = "MA 1"
varip inp_MA2 = "MA 2"
varip inp_MA3 = "MA 3"
varip inp_MA4 = "MA 4"
varip inp_MA5 = "MA 5"
varip inp_MA6 = "MA 6"
varip str_ema = "EMA"
varip str_sma = "SMA"
varip str_wma = "WMA"
varip str_hma = "HMA"

// Inputs (Populate Arrays)
array.set ( arr_types, 1,
 input.string ( str_ema, inp_MA1,
 [ str_ema, str_sma, str_wma, str_hma ],
 string ( na ), inp_MA1, grp_MAs ) )

array.set ( arr_types, 2,
 input.string ( str_ema, inp_MA2,
 [ str_ema, str_sma, str_wma, str_hma ],
 string ( na ), inp_MA2, grp_MAs ) )

array.set ( arr_types, 3,
 input.string ( str_ema, inp_MA3,
 [ str_ema, str_sma, str_wma, str_hma ],
 string ( na ), inp_MA3, grp_MAs ) )

array.set ( arr_types, 4,
input.string ( str_ema, inp_MA4,
 [ str_ema, str_sma, str_wma, str_hma ],
 string ( na ), inp_MA4, grp_MAs ) )

array.set ( arr_types, 5,
input.string ( str_ema, inp_MA5,
 [ str_ema, str_sma, str_wma, str_hma ],
 string ( na ), inp_MA5, grp_MAs ) )

array.set ( arr_types, 6,
input.string ( str_ema, inp_MA6,
 [ str_ema, str_sma, str_wma, str_hma ],
 string ( na ), inp_MA6, grp_MAs ) )

array.set ( arr_types, 1, input.int ( 21, string ( na ), inline = inp_MA1, group = grp_MAs ) )
array.set ( arr_types, 2, input.int ( 55, string ( na ), inline = inp_MA2, group = grp_MAs ) )
array.set ( arr_types, 3, input.int ( 100, string ( na ),inline = inp_MA3, group = grp_MAs ) )
array.set ( arr_types, 4, input.int ( 150, string ( na ),inline = inp_MA4, group = grp_MAs ) )
array.set ( arr_types, 5, input.int ( 200, string ( na ),inline = inp_MA5, group = grp_MAs ) )
array.set ( arr_types, 6, input.int ( 500, string ( na ),inline = inp_MA6, group = grp_MAs ) )


// Calculate the given Moving Average
f_calc_ma ( _type, _len ) = switch _type
    'EMA' => ta.ema ( close, _len )
    'SMA' => ta.sma ( close, _len )
    'WMA' => ta.wma ( close, _len )
    'HMA' => ta.hma ( close, _len )

// Return the given Moving Average value
f_ma_value ( num ) =>
	_type = array.get ( arr_types, num )
	_len  = array.get ( arr_lens, num )
	array.set ( MAs, num, f_calc_ma ( _type, _len ) )

// Plot all 6 Moving Averages
plot ( array.get ( arr_MAs, 1 ), inp_MA1, color.yellow, 2, plot.style_line )
plot ( array.get ( arr_MAs, 2 ), inp_MA2, color.blue,   2, plot.style_line )
plot ( array.get ( arr_MAs, 3 ), inp_MA3, color.orange, 2, plot.style_line )
plot ( array.get ( arr_MAs, 4 ), inp_MA4, color.purple, 2, plot.style_line )
plot ( array.get ( arr_MAs, 5 ), inp_MA5, color.red,    2, plot.style_line )
plot ( array.get ( arr_MAs, 6 ), inp_MA6, color.green, 2, plot.style_line )
		


TE S (Supertrend)

The origin and inspiration of Affogato.

// inputs
i_trendespresso_tf = input ( '', "Master Timeframe", input.resolution, group = groupGlobal, tooltip = version )
i_alt_exchange = input ( 'COINBASE', "Ticker Override", input.string, group = groupGlobal, tooltip = str_exch_tt, inline = str_exch_tt )
i_alt_exchange_bool = input ( false, str_full, input.bool, group = groupGlobal, tooltip = str_exch_tt, inline = str_exch_tt )
varip timeframe     = ( i_trendespresso_tf == string ( na ) or i_trendespresso_tf == '' ) ? timeframe.period : i_trendespresso_tf
varip ticker        = i_alt_exchange_bool                              ? i_alt_exchange   :
                      i_alt_exchange == '' or syminfo.type != 'crypto' ? syminfo.tickerid :
                      i_alt_exchange + ":" + syminfo.basecurrency + 'USD'

i_atrPeriod     = input ( 12,       "ATR Length",       input.integer,  minval = 1,     group = groupSuper,     tooltip = atr_tt )
i_factor        = input ( 3.05,     "Factor",           input.float,    minval = 0.01,  group = groupSuper,     tooltip = fac_tt,   step = 0.05 )
i_RR            = input ( 15.5,     str_TP_t,           input.float,    minval = 0,     group = groupSuper,     tooltip = rr_tt,    step = 0.1  )
i_TSI_ON        = input ( true,     "TSI Filtering",    input.bool,                     group = groupSuper,     tooltip = str_TSI_tt )
i_TSI_Short     = input ( 12,       "TSI Short",        input.integer,  minval = 1,     group = groupSuper,     tooltip = TSI_S )
i_TSI_Long      = input ( 24,       "TSI Long",         input.integer,  minval = 1,     group = groupSuper,     tooltip = TSI_L )
i_MA_ON         = input ( true,     "MA Filtering",     input.bool,                     group = groupSuper,     tooltip = str_ma_tt )
i_MA_calc       = input ( str_wma,  str_ma,             input.string,                   group = groupSuper,     inline = str_ma,    options = [ str_ema, str_hma, str_sma, str_wma, str_alma, str_vwma, str_none ] )
i_MA_len        = input ( 150,      string ( na ),      input.integer,  minval = 1,     group = groupSuper,     inline = str_ma )


// FUNCTION: Return the given moving average
f_wave_calc ( source, length, calculation ) =>
    wave = float ( na )
    if calculation == str_hma
        wave := hma ( source, length )
    else
        if calculation == str_ema
            wave := ema ( source, length )
        else
            if calculation == str_sma
                wave := sma ( source, length)
            else
                if calculation == str_wma
                    wave := wma ( source, length )
                else
                    if calculation == str_alma
                        wave := alma ( source, length, 0.85, 21 )
                    else
                        if calculation == str_vwma
                            wave := vwma ( source, length )
    wave



// generate the supertrend
[ supertrend, direction ]   = security ( heikinashi ( ticker ), timeframe, supertrend ( i_factor, i_atrPeriod ) )
[ TSI, MA ]                 = security ( heikinashi ( ticker ), timeframe, [ tsi ( close, i_TSI_Short, i_TSI_Long ), f_wave_calc ( close, i_MA_len, i_MA_calc ) ] )


// plots
bodyMiddle  = plot ( ( open + close ) / 2,            string ( na ), color ( na ), editable = false, display = display.none )
upTrend     = plot ( direction < 0 ? supertrend : na, string ( na ), color ( na ), editable = false, display = display.none )
downTrend   = plot ( direction < 0 ? na : supertrend, string ( na ), color ( na ), editable = false, display = display.none )
		


TE OI (Open Interest)

See a core piece of underlying market dynamics directly inside TradingView.
Gauge institutional interest and see when the market is overheated.

f_security_wrap_L ( symbol ) => security ( symbol + "LONGS", timeframe.period, close )
f_security_wrap_S ( symbol ) => security ( symbol + "SHORTS", timeframe.period, close )
longs   = f_security_wrap_L ( i_enable_sym ? i_sym + "USD" : syminfo.ticker )
shorts  = f_security_wrap_S ( i_enable_sym ? i_sym + "USD" : syminfo.ticker )
oi      = longs - shorts
ma1     = f_wave_calc ( oi, i_ma1_len, i_ma1_calc )
ma2     = f_wave_calc ( oi, i_ma2_len, i_ma2_calc )

varip c_oi_bull = color.new ( color_bull, 60 )
varip c_oi_bear = color.new ( color_bear, 60 )

bullish = ma1 >= ma2

plot ( longs,    "Bitfinex Longs",                   color_bull,                 display = display.none )
plot ( shorts,   "Bitfinex Shorts",                               color_bear,    display = display.none )
plot ( oi,       "Bitfinex Open Interest", oi >= 0 ? c_oi_bull  : c_oi_bear,  2, plot.style_columns     )
m1 = plot ( ma1, str_trnd1,                bullish ? c_oi_bull  : c_oi_bear,  2, display = display.all )
m2 = plot ( ma2, str_trnd2,                bullish ? c_oi_bear  : c_oi_bull,  2, display = display.all )
fill ( m1, m2, bullish ? color.new ( color_bull, 15 ) : color.new ( color_bear, 15 ), title = "MA Fill" )
		
	


TE PA (Price Alert)

Set a TradingView alert to send a push notification
to your phone. Keep your head out of the charts.

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © trendespresso

//@version=5

varip ver_num               = "1.1"
varip script_long_ver       = "v" + ver_num
varip script_short_ver      =       ver_num
varip script_abrev          = "TE PA"
varip script_long_title     = "Trendespresso Price Alert" + " [ " + script_long_ver  + " ]"
varip script_short_title    = script_abrev                + " [ " + script_short_ver + " ]"



indicator ( script_long_title, script_short_title, false, max_bars_back = 600, max_lines_count = 500, max_labels_count = 25 )




/////////////////////////////////////////////////////////////////////////////////
// VERSION + DEBUG

varip version   = script_long_ver + "\nPublished October 8, 2021\nby Trendespresso"


plot ( float ( na ), string ( na ), color ( na ), editable = false, display = display.none )

varip str_header = script_abrev + ':'
varip thresh_tt  = "If the current candle changes\n" +
                   "by the given %, send an\n" +
                   "early Alert in addition to\n" +
                   "each one on candle close.\n\n" +
                   "Set to 0 to disable."
varip thresh_head_tt = "Header on any 'Threshold Alert'\n" +
                       "as defined and explained above.\n\n" +
                       "Read the above tooltip."

i_src               = input.source ( close,         "Source",               tooltip = version )
i_thresh            = input.float  (  2. ,          "% Change Threshold",   tooltip = thresh_tt, minval  = 0 )
i_thresh_header     = input.string ( "!!!! ",       "Threshold Header",     tooltip = thresh_head_tt )
i_header            = input.string ( str_header,    "Alert Header" )
i_footer            = input.string ( '30m',         "Alert Footer" )



// calculations
f_label_X_Loc ( multi ) => time_close + ( multi * ( time_close - time_close[1] ) )
f_avg_price ( length )  => math.abs ( ta.percentile_linear_interpolation ( ohlc4, length, 50 ) )

label_tt_price = float ( na )
if bar_index % 50 == 0 or bar_index <= 10
    label_tt_price := f_avg_price ( 50 )
else if ohlc4 >= 1000 and na ( label_tt_price[1] )
    label_tt_price := 1001
else
    label_tt_price := label_tt_price[1]


// FUNCTION: Convert the goven oscillator or number into a readable output
//           with proper sign, decimal places, and zeroes.
f_osc_as_text ( input_osc, input_decimals ) =>
    extra_zeroes = 0
    // extra_zeroes is usually an input argument
    osc         = input_osc < 0 ? math.abs ( input_osc ) : input_osc
    //osc        := dynamic_decimals ? osc * label_tt_multi : osc
    num         = math.floor ( osc )
    decimals    = input_decimals >= 0 ? input_decimals : label_tt_price >= 1000 ? 0 : label_tt_price >= 100 ? 1 : label_tt_price >= 1 ? 2 : label_tt_price >= 0.1 ? 3 : label_tt_price >= 0.01 ? 4 : 5
    factor      = math.pow ( 10, decimals )
    dec         = math.floor ( ( math.round ( osc - num, 6 ) ) * factor ) / factor
    str_out     = str.tostring ( num + dec )
    if num < 10.0 and extra_zeroes > 0
        for i = 1 to extra_zeroes
            str_out := "0" + str_out
    if decimals > 0
        z = decimals
        if ( num > 0.0 and ( osc % 1 == 0.0 or dec == 0.0 ) ) or ( num + dec ) == 0.0
            str_out += "."
        else
            d = dec
            for i = 1 to decimals
                if d % 1 != 0.0
                    d *= 10
                    z -= 1
                    continue
                else
                    break
            pine = string ( na ) // Pine limitation
        if z > 0
            for i = 1 to z
                str_out += "0"
    str_out


// FUNCTION: Determine the % change between any two bars
f_pct_change ( source ) => ( ( source - source[1] ) / source[1] ) * 100


// HELPER FUNCTION: Add the correct negative or positive sign to the given string (requires the original value/number obviously)
f_add_sign ( value, number_as_string ) => value < 0 ? "–" + number_as_string : "+" + number_as_string


f_alert_text ( source, header, footer ) =>
    str_out = string ( na )
    if header != '' or not na ( header )
        str_out := header + "\n"
    str_out += f_osc_as_text ( source, -1 ) + "\n"
    pct_chg  = ( math.round ( f_pct_change ( source ) * 10 ) ) / 10
    str_out += f_add_sign ( pct_chg, str.tostring ( math.abs ( pct_chg ) ) ) + " %"
    if footer != '' or not na ( footer )
        str_out += "\n" + footer
    [ str_out, pct_chg ]


[ change_str, change_num ] = f_alert_text ( i_src, i_header, i_footer )

if i_thresh > 0 and ( change_num >= i_thresh or -change_num >= i_thresh )
    alert ( i_thresh_header + change_str, alert.freq_once_per_bar )
else
    alert ( change_str, alert.freq_once_per_bar_close )

t = label.new ( time, 0, str.tostring ( ( math.round ( f_pct_change ( i_src ) * 10 ) ) / 10 ), xloc.bar_time, yloc.price, color.gray, textcolor = color.white )
label.delete ( t[1] )


///////////////////////////////////////////////////////////////////////////////
// (c) 2021, Trendespresso

		




Website written from scratch in 3 days without a template.
(c) , Trendespresso