// 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 )
// 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
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] )
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
// 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
// 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
// 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 )
// 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 )
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" )
// 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