xmd79

RedK Effort Versus Results Explorer

Mar 14th, 2023
486
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.23 KB | None | 0 0
  1. // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
  2. // © RedKTrader - March 2023
  3.  
  4. //@version=5
  5.  
  6. // ******************************
  7. // to-do list
  8.  
  9.  
  10.  
  11. // inspecting the effort vs result concept by plotting volume vs. price change
  12. // this is like looking at distance versus fuel consumption - but comparing a normalized average of each
  13. // to help reveal areas of volume & price action anomalies, contraction & expansion
  14.  
  15.  
  16. indicator('RedK Effort Versus Results Explorer', 'RedK EVEREX v1.0', precision = 0,
  17. timeframe = '', timeframe_gaps = false, explicit_plot_zorder = true)
  18.  
  19. // ***********************************************************************************************************
  20. // This function calcualtes a selectable average type
  21. GetAverage(_data, _len, MAOption) =>
  22. value = switch MAOption
  23. 'SMA' => ta.sma(_data, _len)
  24. 'EMA' => ta.ema(_data, _len)
  25. 'HMA' => ta.hma(_data, _len)
  26. 'RMA' => ta.rma(_data, _len)
  27. =>
  28. ta.wma(_data, _len)
  29. // ***********************************************************************************************************
  30.  
  31. // ========================================================================================
  32. // Normalization function - Normalizes values that are not restricted within a zero to 100 range
  33. // This technique provides a scale that is closer to a "human" estimation of value in "bands"
  34. // as in: low, below average, average, above average, high, super high
  35. // this also avoids the issue of extreme values when using the stoch() -based technique
  36. // these values are subjective, and can be changed - but slight changes here won't lead to major changes in outcome
  37. // since all is relative to the same data series.
  38. //
  39. Normalize(_Value, _Avg) =>
  40.  
  41. _X = _Value / _Avg
  42.  
  43. _Nor =
  44. _X > 1.50 ? 1.00 :
  45. _X > 1.20 ? 0.90 :
  46. _X > 1.00 ? 0.80 :
  47. _X > 0.80 ? 0.70 :
  48. _X > 0.60 ? 0.60 :
  49. _X > 0.40 ? 0.50 :
  50. _X > 0.20 ? 0.25 :
  51. 0.1
  52. // ===================================================================================
  53.  
  54.  
  55. // ===========================================================================================================
  56. // Inputs
  57. // ===========================================================================================================
  58. grp_1 = 'Rate of FLow (RoF)'
  59. grp_2 = 'Lookback Parameters'
  60. grp_3 = 'Bias / Sentiment'
  61. grp_4 = 'EVEREX Bands'
  62.  
  63. length = input.int(10, minval = 1, inline = 'ROF', group = grp_1)
  64. MA_Type = input.string(defval = 'WMA', title = 'MA type',
  65. options = ['WMA', 'EMA', 'SMA', 'HMA', 'RMA'], inline = 'ROF', group = grp_1)
  66. smooth = input.int(defval = 3, title = 'Smooth', minval = 1, inline = 'ROF', group = grp_1)
  67.  
  68. //src = input.source(close, title = "Source (for 2-Bar Shift)", group = grp_1)
  69.  
  70. sig_length = input.int(5, 'Signal Length', minval = 1, inline = 'Signal', group = grp_1)
  71. S_Type = input.string(defval = 'WMA', title = 'Signal Type',
  72. options = ['WMA', 'EMA', 'SMA', 'HMA', 'RMA'], inline = 'Signal', group = grp_1)
  73.  
  74. lookback = input.int(defval = 20, title = 'Length', minval = 1, inline = 'Lookback', group = grp_2)
  75. lkbk_Calc = input.string(defval = 'Simple', title = 'Averaging',
  76. options = ['Simple', 'Same as RRoF'], inline='Lookback', group = grp_2 )
  77.  
  78. showBias = input.bool(defval = false, title = 'Bias Plot ? -- ', inline = 'Bias', group = grp_3)
  79. B_Length = input.int(defval = 30, title = 'Length', minval = 1, inline = 'Bias', group = grp_3)
  80. B_Type = input.string(defval = 'WMA', title = 'MA type',
  81. options = ['WMA', 'EMA', 'SMA', 'HMA', 'RMA'], inline = 'Bias', group = grp_3)
  82.  
  83. showEVEREX = input.bool(true, 'Show EVEREX Bands ? -- ', inline = 'EVEREX', group = grp_4)
  84. // a simple mechanism to control/change the strength band scale for improving visualization
  85. // applies only to the "bands" and the level hlines
  86. bandscale = str.tonumber(input.string("100", title = "Band Scale",
  87. options = ['100', '200', '400'], inline = 'EVEREX', group = grp_4))
  88.  
  89. DispBias = showBias ? display.pane : display.none
  90. DispBands = showEVEREX ? display.pane : display.none
  91. showhlines = showEVEREX ? display.all : display.none
  92.  
  93.  
  94. // ===========================================================================================================
  95. // Calculations
  96. // ===========================================================================================================
  97.  
  98. // Volume "effort" Calculation -- will revert to no volume acceleration for instruments with no volume data
  99.  
  100. v = na(volume) ? 1 : volume // this part ensures we're not hit with calc issues due to NaN's
  101. NoVol_Flag = na(volume) ? true : false // this is a flag to use later
  102.  
  103. lkbk_MA_Type = lkbk_Calc == 'Simple' ? 'SMA' : MA_Type
  104.  
  105. Vola = GetAverage(v, lookback, lkbk_MA_Type)
  106. Vola_n_pre = Normalize(v, Vola) * 100
  107.  
  108. //Now trap the case of no volume data - ensure final calculation not impacted
  109. Vola_n = NoVol_Flag ? 100 : Vola_n_pre
  110. //plot(Vola_n , "Volume Normalized", color = color.white, display = display.none)
  111.  
  112. // ===============================================================================================================
  113. // Price "result" calculation
  114. // we'll consider "result" (strength or weakness) to be the outcome (average) of 6 elements:
  115. // Same (in-)Bar strength elements:
  116. // 1 - Bar Closing: the closing within the bar --> this will be a direct +100 / -100 value
  117. // 2 - Spread to range: the spread to range ratio (that's BoP formula) --> direct +100 / -100 value
  118. // 3 - Relative Spread: spread relative to average spread during lookback period --> normalized
  119. // 2-bar strength elements:
  120. // 4 - 2-bar closing: the closing within 2-bar range (that accomodates open gap effect)
  121. // 5 - 2-bar Closing Shift to Range: Change in close relative to the 2-bar range
  122. // 6 - 2-bar Relative Shift: the 2-bar Close (or source price) shift - relative to the average 2-bar shift during lookback period --> normalized
  123.  
  124.  
  125. BarSpread = close - open
  126. BarRange = high - low
  127. R2 = ta.highest(2) - ta.lowest(2)
  128. SrcShift = ta.change(close)
  129. //TR = ta.tr(true)
  130.  
  131. sign_shift = math.sign(SrcShift)
  132. sign_spread = math.sign(BarSpread)
  133. // =========================================================================================================
  134. // in-bar assessments
  135. // =========================================================================================================
  136. // 1. Calculate closing within bar - should be max value at either ends of the bar range
  137. barclosing = 2 * (close - low) / BarRange * 100 - 100
  138. //plot(barclosing, "Bar Closing %" , color=color.fuchsia, display = display.none)
  139.  
  140. // 2. caluclate spread to range ratio
  141. s2r = BarSpread / BarRange * 100
  142. //plot(s2r, "Spread:Range", color = color.lime, display = display.none)
  143.  
  144. // 3. Calculate relative spread compared to average spread during lookback
  145. BarSpread_abs = math.abs(BarSpread)
  146. BarSpread_avg = GetAverage(BarSpread_abs, lookback, lkbk_MA_Type)
  147. BarSpread_ratio_n = Normalize(BarSpread_abs, BarSpread_avg) * 100 * sign_spread
  148. //plot(BarSpread_ratio_n, "Bar Spread Ratio", color=color.orange, display=display.none)
  149. // =========================================================================================================
  150. // 2-bar assessments
  151. // =========================================================================================================
  152. // 4. Calculate closing within 2 bar range - should be max value at either ends of the 2-bar range
  153. barclosing_2 = 2 * (close - ta.lowest(2)) / R2 * 100 - 100
  154. //plot(barclosing_2, "2-Bar Closing %" , color=color.navy, display = display.none)
  155.  
  156. // 5. calculate 2-bar shift to range ratio
  157. Shift2Bar_toR2 = SrcShift / R2 * 100
  158. //plot(Shift2Bar_toR2, "2-bar Shift vs 2R", color=color.yellow, display = display.none)
  159.  
  160.  
  161. // 6. Calculate 2-bar Relative Shift
  162. SrcShift_abs = math.abs(SrcShift)
  163. srcshift_avg = GetAverage(SrcShift_abs, lookback, lkbk_MA_Type)
  164. srcshift_ratio_n = Normalize(SrcShift_abs, srcshift_avg) * 100 * sign_shift
  165. //plot(srcshift_ratio_n, "2-bar Shift vs Avg", color=color.white, display = display.none)
  166. // ===============================================================================
  167.  
  168. // =========================================================================================
  169. // Relative Price Strength combining all strength elements
  170.  
  171. Pricea_n = (barclosing + s2r + BarSpread_ratio_n + barclosing_2 + Shift2Bar_toR2 + srcshift_ratio_n) / 6
  172. //plot(Pricea_n, "Price Normalized", color=color.orange, display = display.none)
  173.  
  174.  
  175. //Let's take Bar Flow as the combined price strength * the volume:avg ratio
  176. // this works in a similar way to a volume-weighted RSI
  177. bar_flow = Pricea_n * Vola_n / 100
  178. //plot(bar_flow, 'bar_flow', color=color.green, display = display.none)
  179.  
  180. // calc avergae relative rate of flow, then smooth the resulting average
  181. // classic formula would be this
  182. //RROF = f_ma(bar_flow, length, MA_Type)
  183. //
  184. // or we can create a relative index by separating bulls from bears, like in an RSI - my preferred method
  185. // here we have an added benefit of plotting the (average) bulls vs bears separately - as an option
  186. bulls = math.max(bar_flow, 0)
  187. bears = -1 * math.min(bar_flow, 0)
  188.  
  189. bulls_avg = GetAverage(bulls, length, MA_Type)
  190. bears_avg = GetAverage(bears, length, MA_Type)
  191.  
  192. dx = bulls_avg / bears_avg
  193. RROF = 2 * (100 - 100 / (1 + dx)) - 100
  194. RROF_s = ta.wma(RROF, smooth)
  195.  
  196. Signal = GetAverage(RROF_s, sig_length, S_Type)
  197.  
  198. // Calculate Bias / sentiment on longer length
  199. dx_b = GetAverage(bulls, B_Length, B_Type) / GetAverage(bears, B_Length, B_Type)
  200. RROF_b = 2 * (100 - 100 / (1 + dx_b)) - 100
  201. RROF_bs = ta.wma(RROF_b, smooth)
  202.  
  203. // ===========================================================================================================
  204. // Colors & plots
  205. // ===========================================================================================================
  206.  
  207. c_zero = color.new(#1163f6, 25)
  208. c_band = color.new(color.yellow, 40)
  209.  
  210. c_up = color.aqua
  211. c_dn = color.orange
  212.  
  213. c_sup = color.new(#00aa00, 70)
  214. c_sdn = color.new(#ff180b, 70)
  215.  
  216. up = RROF_s >= 0
  217. s_up = RROF_bs >=0
  218.  
  219. // ==================================== Plots ==========================================================
  220.  
  221. // // Display the ATR & VOl Ratio values only on the indicator status line & in the Data Window
  222. // plotchar(shift, title = "Shift", char = "", color = color.white, editable=false, display=display.status_line + display.data_window)
  223. // plotchar(lbk_tr, title = "Avg Shift", char = "", color = color.aqua, editable=false, display=display.status_line + display.data_window)
  224. // plotchar(vola/lbk_vola, title = "Vol Ratio", char = "", color = color.yellow, editable=false, display=display.status_line + display.data_window)
  225.  
  226.  
  227. hline(0, 'Zero Line', c_zero, linestyle = hline.style_solid)
  228. // plot the band scale guide lines -- these lines will show/hide along with the EVEREX "Equalizer Bands Plot"
  229. hline(0.25 * bandscale, title = '1/4 Level', color=c_band, linestyle = hline.style_dotted, display = showhlines)
  230. hline(0.50 * bandscale, title = '2/4 Level', color=c_band, linestyle = hline.style_dotted, display = showhlines)
  231. hline(0.75 * bandscale, title = '3/4 Level', color=c_band, linestyle = hline.style_dotted, display = showhlines)
  232. hline(bandscale, title = '4/4 Level', color=c_band, linestyle = hline.style_dotted, display = showhlines)
  233.  
  234. // Plot Bulls & Bears - these are optional plots and hidden by default - adjust this section later
  235. plot(ta.wma(bulls_avg, smooth), "Bulls", color = #11ff20, linewidth = 2, display = display.none)
  236. plot(ta.wma(bears_avg, smooth), "Bears", color = #d5180b, linewidth = 2, display = display.none)
  237. // =============================================================================
  238. // Plot Bias / Sentiment
  239.  
  240. plot (RROF_bs, "Bias / Sentiment", style=plot.style_area,
  241. color = s_up ? c_sup : c_sdn, linewidth = 4, display = DispBias )
  242.  
  243. // =============================================================================
  244. // Plot Price Strength & Relative Volume as stacked "equalizer bands"
  245.  
  246. nPrice = math.max(math.min(Pricea_n, 100), -100)
  247. nVol = math.max(math.min(Vola_n, 100), -100)
  248.  
  249. bar = bar_flow
  250.  
  251. c_vol_grn = color.new(#26a69a, 75)
  252. c_vol_red = color.new(#ef5350, 75)
  253.  
  254. cb_vol_grn = color.new(#26a69a, 20)
  255. cb_vol_red = color.new(#ef5350, 20)
  256.  
  257. c_vol = bar > 0 ? c_vol_grn : c_vol_red
  258. cb_vol = bar > 0 ? cb_vol_grn : cb_vol_red
  259.  
  260. vc_lo = 0, vc_hi = nVol * bandscale / 100 / 2
  261.  
  262. plotcandle(vc_lo, vc_hi, vc_lo, vc_hi , "Volume Band", c_vol, c_vol, bordercolor = cb_vol, display = DispBands)
  263.  
  264. c_pri_grn = color.new(#3ed73e, 75)
  265. c_pri_red = color.new(#ff870a, 75)
  266.  
  267. cb_pri_grn = color.new(#3ed73e, 20)
  268. cb_pri_red = color.new(#ff870a, 20)
  269.  
  270. c_pri = bar > 0 ? c_pri_grn : c_pri_red
  271. cb_pri = bar > 0 ? cb_pri_grn : cb_pri_red
  272.  
  273. pc_lo = vc_hi, pc_hi = vc_hi + math.abs(nPrice) * bandscale / 100 / 2
  274.  
  275. plotcandle(pc_lo, pc_hi, pc_lo ,pc_hi , "Price Band", c_pri, c_pri, bordercolor = cb_pri, display = DispBands)
  276.  
  277. // =============================================================================
  278.  
  279. // =============================================================================
  280. // Plot main plot, smoothed plot and signal line
  281.  
  282. plot(RROF, 'RROF Raw', color.new(#2470f0, 9), display=display.none)
  283. plot(RROF_s, 'RROF Smooth', color = color.new(#b2b5be,40), linewidth = 2)
  284. plot(Signal, "Signal Line", up ? c_up : c_dn, 3)
  285.  
  286. // ===========================================================================================================
  287. // basic alerts
  288. // ===========================================================================================================
  289.  
  290. Alert_up = ta.crossover(RROF_s,0)
  291. Alert_dn = ta.crossunder(RROF_s,0)
  292. Alert_swing = ta.cross(RROF_s,0)
  293.  
  294. // "." in alert title for the alerts to show in the right order up/down/swing
  295. alertcondition(Alert_up, ". RROF Crossing 0 Up", "RROF Up - Buying Action Detected!")
  296. alertcondition(Alert_dn, ".. RROF Crossing 0 Down", "RROF Down - Selling Action Detected!")
  297. alertcondition(Alert_swing, "... RROF Crossing 0", "RROF Swing - Possible Reversal")
  298.  
  299.  
Advertisement
Add Comment
Please, Sign In to add comment