- // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
- // © zanderdogz
- //@version=5
- indicator("SwingCustomAlert", overlay = true)
- //RVOL Calculation: (Credits https://www.reddit.com/user/glst0rm https://www.reddit.com/user/HSeldon2020/ /u/WorkPiece /user/HurlTeaInTheSea)
- smallSize = input.bool(defval=false, title="Small size")
- showRecentBars = input.bool(defval=true, title="Show recent bar strength?") // experimental comparison of bar heights to index
- days = input.int(20, minval=1, title="N Day Average")
- marketTicker = input.symbol(title="Market trend ticker", defval="SPY", inline = "10")
- positionInput = input.string(title='Display position',
- options=["Upper Right", "Upper Left", "Lower Right", "Lower Left"],
- defval="Upper Right")
- bgColor = input.color(title='Background color',
- defval=color.new(#03072f,0))
- position = switch positionInput
- "Upper Left" => position.top_left
- "Upper Right" => position.top_right
- "Lower Right" => position.bottom_right
- "Lower Left" => position.bottom_left
- positionInputBars = input.string(title='Display position of recent bar strength',
- options=["Upper Right", "Upper Left", "Lower Right", "Lower Left"],
- defval="Lower Right")
- positionBars = switch positionInputBars
- "Upper Left" => position.top_left
- "Upper Right" => position.top_right
- "Lower Right" => position.bottom_right
- "Lower Left" => position.bottom_left
- atrGreen = input.float(defval=.006, title="ATR green level (above)")
- atrRed = input.float(defval=.003, title="ATR red level (below)")
- rVolGreen = input.float(defval=1.0, title="RVol green level (above)")
- rVolRed = input.float(defval=.6, title="ATR red level (below)")
- typeSize = size.normal
- if smallSize
- typeSize := size.small
- var newDayBars = array.new_int()
- // ATR 14 and ATR % of price
- // ==================================
- atr = request.security(syminfo.tickerid, timeframe.period, ta.atr(14))
- // approximately five trading days
- rAtrLength = switch timeframe.period
- "1" => 500
- "5" => 600
- "15" => 160
- "30" => 80
- "60" => 40
- "120" => 20
- "240" => 10
- "1D" => 5
- => 500 // default (5m bars)
- rAtr = ta.sma(atr,600) // relative atr over last 600 periods (roughly 5 trading days)
- atrPercent = atr / close
- rAtrPercent = atr / rAtr
- atrString = "$" + str.format("{0,number}",math.round(atr, 2)) + " "
- + str.format("{0}",math.round((atr / close) * 100, 2)) + "% "
- rAtrString = str.format("{0}",math.round((rAtrPercent) * 100, 2)) + "% "
- atrColor = color.white
- if (atrPercent >= atrGreen)
- atrColor := color.green
- else if (atrPercent >= atrRed )
- atrColor := color.yellow
- else if (atrPercent < atrRed )
- atrColor := color.red
- rAtrColor = color.white
- if (rAtrPercent >= 1)
- rAtrColor := color.green
- else if (rAtrPercent >= .70 )
- rAtrColor := color.yellow
- else if (rAtrPercent < .70 )
- rAtrColor := color.red
- // Daily Volume
- // ==================================
- vol = request.security(syminfo.tickerid, "1D", volume, barmerge.gaps_off, barmerge.lookahead_on) // allow lookahead for current day open price (won't future leak)
- // RVol and RVol to SPY
- // ==================================
- // Adapted from script by /u/HurlTeaInTheSea
- // https://www.reddit.com/r/RealDayTrading/comments/ue4ujq/tostv_timebased_relative_volume_rvol_a_better/
- var cVol = 0.0
- var spyCVol = 0.0
- // detect new session of day
- isNewDay() =>
- t = time('D') // by default, time() follows symbol's session
- na(t[1]) and not na(t) or t[1] < t
- if isNewDay()
- // reset cumulative volume
- cVol := 0
- spyCVol := 0
- // save new bars in circular array of length days + 1
- array.push(newDayBars, bar_index)
- if (array.size(newDayBars) > days + 1)
- array.shift(newDayBars)
- // cumulative volume
- cVol := cVol + volume
- // cumulative spy volume
- spyCVol := spyCVol + request.security(marketTicker, timeframe.period, volume, barmerge.gaps_off, barmerge.lookahead_off)
- // calculate relative volume
- relativeVolume(cVolArray) =>
- aVol = 0.0
- // check enough days saved in history to run (current day also saved)
- len = array.size(newDayBars)
- if len >= days + 1
- // SMA of historical cumulative volume up to but not including current time of day
- for i = 0 to len - 2
- b1 = array.get(newDayBars, i)
- b2 = array.get(newDayBars, i + 1)
- // use historical date but carry over current hour, minutes, seconds (this method is exact and avoids DST bugs)
- t1 = time[bar_index - b1]
- tLookup = timestamp(year(t1), month(t1), dayofmonth(t1), hour(time), minute(time), second(time))
- // get latest bar clamped in range [b1, b2) that is equal to or precedes given time (binary search for speed)
- int lo = math.max(0, b1) - 1
- int hi = math.max(0, b2)
- while 1 + lo < hi
- int mi = lo + math.floor((hi - lo) / 2)
- if (tLookup < time[bar_index - mi])
- hi := mi
- else
- lo := mi
- lo := lo < b1 ? hi : lo
- bClosest = b1 < b2 ? lo : -1
- // add cumulative volume to SMA calculation
- tClosest = time[bar_index - bClosest]
- aVol := aVol + (tLookup >= tClosest ? cVolArray[bar_index - bClosest] / days : 0)
- rVol = aVol > 0 ? cVolArray / aVol : 0
- rVol = relativeVolume(cVol)
- spyRVol = relativeVolume(spyCVol)
- //Get SPY price
- SPY = request.security("SPY", timeframe.period, close)
- //Alert Conditions:
- SPYlimit = input(1.0)
- MinRVOL = input(1.25)
- StockPriceAlert = input(1.0)
- long = SPY > SPYlimit and rVol > MinRVOL and close > StockPriceAlert
- short = SPY < SPYlimit and rVol > MinRVOL and close < StockPriceAlert
- //Alerts:
- alertcondition(long, "LongAlert", "Long")
- alertcondition(short, "ShortAlert", "Short")
[text] CustomSwingAlert
Viewer
*** This page was generated with the meta tag "noindex, nofollow". This happened because you selected this option before saving or the system detected it as spam. This means that this page will never get into the search engines and the search bot will not crawl it. There is nothing to worry about, you can still share it with anyone.
Editor
You can edit this paste and save as new: