f_calculatePreMarketHighLow () => curIndex = 0 float preMarketHighF = 0 float preMarketLowF = -1 bool foundPreMarket = false while (session.isfirstbar[curIndex] == false) if session.ispremarket[curIndex] foundPreMarket := true preMarketHighF := math.max(preMarketHighF, high[curIndex]) preMarketLowF := preMarketLowF == -1 ? low[curIndex] : math.min(preMarketLowF, low[curIndex]) if not session.ispremarket[curIndex] and foundPreMarket break curIndex += 1 if curIndex > 4000 break [preMarketHighF, preMarketLowF]
type lineInfo string[] timeNames string[] infos float price int startTime int endTime color col string lStyle line zone label lbl bool disabled = false
type pivot bool isHigh = false int index float price float atr
createLineInfo (string timeName, string info, float p, int t, int tend, color col, string sty) => newLI = lineInfo.new(array.new<string>(0), array.new<string>(0), p, t, tend, col, sty) if not na(timeName) newLI.timeNames.unshift(timeName) if not na (info) newLI.infos.unshift(info) newLI
calculateLineInfos () => if allLineInfos.size() > 0 for i = 0 to allLineInfos.size() - 1 safeDeleteLineInfo(allLineInfos.get(i)) allLineInfos.clear()
if todayEnabled and not na(bInfo1) allLineInfos.unshift(createLineInfo("Today", "High", bInfo1.h, bInfo1.t, time, todayHighLineColor, todayLineStyle)) allLineInfos.unshift(createLineInfo("Today", "Low", bInfo1.l, bInfo1.t, time, todayLowLineColor, todayLineStyle)) allLineInfos.unshift(createLineInfo("Today", "Open", bInfo1.o, bInfo1.t, time, todayOpenLineColor, todayLineStyle)) if yesterdayEnabled and not na(bInfo2) allLineInfos.unshift(createLineInfo("Yesterday", "High", bInfo2.h, bInfo2.t, bInfo1.t, yesterdayHighLineColor, yesterdayLineStyle)) allLineInfos.unshift(createLineInfo("Yesterday", "Low", bInfo2.l, bInfo2.t, bInfo1.t, yesterdayLowLineColor, yesterdayLineStyle)) allLineInfos.unshift(createLineInfo("Yesterday", "Close", bInfo2.c, bInfo2.t, bInfo1.t, yesterdayCloseLineColor, yesterdayLineStyle)) if day3 and not na(bInfo3) allLineInfos.unshift(createLineInfo("3rd Day", "High", bInfo3.h, bInfo3.t, bInfo2.t, day3HighLineColor, day3LineStyle)) allLineInfos.unshift(createLineInfo("3rd Day", "Low", bInfo3.l, bInfo3.t, bInfo2.t, day3LowLineColor, day3LineStyle)) if day4 and not na(bInfo4) allLineInfos.unshift(createLineInfo("4th Day", "High", bInfo4.h, bInfo4.t, bInfo3.t, day4HighLineColor, day4LineStyle)) allLineInfos.unshift(createLineInfo("4th Day", "Low", bInfo4.l, bInfo4.t, bInfo3.t, day4LowLineColor, day4LineStyle)) if day5 and not na(bInfo5) allLineInfos.unshift(createLineInfo("5th Day", "High", bInfo5.h, bInfo5.t, bInfo4.t, day5HighLineColor, day5LineStyle)) allLineInfos.unshift(createLineInfo("5th Day", "Low", bInfo5.l, bInfo5.t, bInfo4.t, day5LowLineColor, day5LineStyle)) if day6 and not na(bInfo6) allLineInfos.unshift(createLineInfo("6th Day", "High", bInfo6.h, bInfo6.t, bInfo5.t, day6HighLineColor, day6LineStyle)) allLineInfos.unshift(createLineInfo("6th Day", "Low", bInfo6.l, bInfo6.t, bInfo5.t, day6LowLineColor, day6LineStyle)) if day7 and not na(bInfo7) allLineInfos.unshift(createLineInfo("7th Day", "High", bInfo7.h, bInfo7.t, bInfo6.t, day7HighLineColor, day7LineStyle)) allLineInfos.unshift(createLineInfo("7th Day", "Low", bInfo7.l, bInfo7.t, bInfo6.t, day7LowLineColor, day7LineStyle)) if day8 and not na(bInfo8) allLineInfos.unshift(createLineInfo("8th Day", "High", bInfo8.h, bInfo8.t, bInfo7.t, day8HighLineColor, day8LineStyle)) allLineInfos.unshift(createLineInfo("8th Day", "Low", bInfo8.l, bInfo8.t, bInfo7.t, day8LowLineColor, day8LineStyle)) if day9 and not na(bInfo9) allLineInfos.unshift(createLineInfo("9th Day", "High", bInfo9.h, bInfo9.t, bInfo8.t, day9HighLineColor, day9LineStyle)) allLineInfos.unshift(createLineInfo("9th Day", "Low", bInfo9.l, bInfo9.t, bInfo8.t, day9LowLineColor, day9LineStyle)) if day10 and not na(bInfo10) allLineInfos.unshift(createLineInfo("10th Day", "High", bInfo10.h, bInfo10.t, bInfo9.t, day10HighLineColor, day10LineStyle)) allLineInfos.unshift(createLineInfo("10th Day", "Low", bInfo10.l, bInfo10.t, bInfo9.t, day10LowLineColor, day10LineStyle)) if preMarketEnabled and not na(preMarketHigh) and not na(bInfo1) allLineInfos.unshift(createLineInfo("Pre-Market", "High", preMarketHigh, bInfo1.t, time, preMarketHighLineColor, preMarketLineStyle)) allLineInfos.unshift(createLineInfo("Pre-Market", "Low", preMarketLow, bInfo1.t, time, preMarketLowLineColor, preMarketLineStyle)) if previousMonthEnabled and not na(mInfo2) allLineInfos.unshift(createLineInfo("Previous Month", "High", mInfo2.h, mInfo2.t, mInfo1.t, monthLowLineColor, monthLineStyle)) allLineInfos.unshift(createLineInfo("Previous Month", "Low", mInfo2.l, mInfo2.t, mInfo1.t, monthHighLineColor, monthLineStyle))
calculateLineInfos()
combineLineInfos () => if allLineInfos.size() > 0 lastCombinations = 999 while lastCombinations > 0 lastCombinations := 0 for i = 0 to allLineInfos.size() - 1 curLI1 = allLineInfos.get(i) for j = 0 to allLineInfos.size() - 1 curLI2 = allLineInfos.get(j) if i == j continue if curLI1.disabled or curLI2.disabled continue if doValuesTouch(curLI1.price, curLI2.price) and extendLines curLI1.disabled := true curLI2.disabled := true newLI = createLineInfo(na, na, curLI1.price, na, na, na, na) if curLI1.timeNames.size() > 0 for a = 0 to curLI1.timeNames.size() - 1 newLI.timeNames.unshift(curLI1.timeNames.get(a)) for a = 0 to curLI1.infos.size() - 1 newLI.infos.unshift(curLI1.infos.get(a))
if curLI2.timeNames.size() > 0 for a = 0 to curLI2.timeNames.size() - 1 newLI.timeNames.unshift(curLI2.timeNames.get(a)) for a = 0 to curLI2.infos.size() - 1 newLI.infos.unshift(curLI2.infos.get(a))
renderLineInfos () => if allLineInfos.size() > 0 for i = 0 to allLineInfos.size() - 1 curLineInfo = allLineInfos.get(i) renderLineInfo(curLineInfo)
renderPivots () => if allPivots.size() > 0 for i = 0 to allPivots.size() - 1 curPivot = allPivots.get(i) safeDeletePivot(curPivot) renderPivot(curPivot)
// Input settings ccimomCross = input.string('CCI', 'Entry Signal Source', options=['CCI', 'Momentum'], tooltip='CCI or Momentum will be the final source of the Entry signal if selected.') ccimomLength = input.int(10, minval=1, title='CCI/Momentum Length') useDivergence = input.bool(true, title='Find Regular Bullish/Bearish Divergence', tooltip='If checked, it will only consider an overbought or oversold condition that has a regular bullish or bearish divergence formed inside that level.') rsiOverbought = input.int(65, minval=1, title='RSI Overbought Level', tooltip='Adjusting the level to extremely high may filter out some signals especially when the option to find divergence is checked.') rsiOversold = input.int(35, minval=1, title='RSI Oversold Level', tooltip='Adjusting this level extremely low may filter out some signals especially when the option to find divergence is checked.') rsiLength = input.int(14, minval=1, title='RSI Length') plotMeanReversion = input.bool(false, 'Plot Mean Reversion Bands on the chart', tooltip='This function doesn\'t affect the entry of signal but it suggests buying when the price is at the lower band, and then sell it on the next bounce at the higher bands.') emaPeriod = input(200, title='Lookback Period (EMA)') bandMultiplier = input.float(1.8, title='Outer Bands Multiplier', tooltip='Multiplier for both upper and lower bands')
// Entry Conditions longEntryCondition = ccimomCrossUp and oversoldAgo and (not useDivergence or bullishDivergenceCondition) shortEntryCondition = ccimomCrossDown and overboughtAgo and (not useDivergence or bearishDivergenceCondition)
// Mean Reversion Indicator meanReversion = plotMeanReversion ? ta.ema(close, emaPeriod) : na stdDev = plotMeanReversion ? ta.stdev(close, emaPeriod) : na upperBand = plotMeanReversion ? meanReversion + stdDev * bandMultiplier : na lowerBand = plotMeanReversion ? meanReversion - stdDev * bandMultiplier : na
// Marking high and low of the 1:15 PM candle var float high_115_candle = na var float low_115_candle = na if is_115_candle_current and not is_115_candle_current[1] high_115_candle := high low_115_candle := low
// Plotting high and low of the 1:15 PM candle plot(high_115_candle, color=color.red, style=plot.style_circles, linewidth=2) plot(low_115_candle, color=color.green, style=plot.style_circles, linewidth=2)
for i = 1 to Count if low <= lowestValue lowestValue := low lowestIndex := bar_index
if high >= HighValue HighValue := high HighIndex := bar_index // // M = bar_index + 135 // CC = int( (M - lowestIndex) / 2) s Value = Counter(pl) Value2 = Counter(HighValue,false) max_bars_back(Value,2000) max_bars_back(Value2,2000) for i = 1 to 20 if high >= Midhigh Midhigh := high Midindex := bar_index
step = ( HighValue-lowestValue ) / levs for i=0 to levs by 1 array.set(VPlevels,i, lowestValue + step * i)
if array.size(Lines) > 8 for i = 0 to 7 line.delete(Lines.shift())
if array.size(Labels) > 3 for i = 0 to 2 label.delete(Labels.shift())
for i=0 to array.size(SCR) -1 for x=0 to array.size(VPlevels) - 2 by 1 if low[ i + 1 ] < array.get(VPlevels,x+1) and array.get(VPlevels,x) < close array.set(ticks,x,array.get(ticks,x)+1) array.set(Volumes,x,array.get(Volumes,x)+Counter(close[x])) break
// label.new(bar_index+20 , low , str.tostring(ticks.size())) if ShowVolume for i = 0 to array.size(ticks) -2 box.delete(array.get(VPboxes,i)) array.set(VPboxes,i, box.new(sync + 170+array.get(ticks,i), array.get(VPlevels,i+1)+(band* 2), sync + 170, array.get(VPlevels,i)+(band* 2), border_color = color.from_gradient(array.get(ticks,i),0, array.max(ticks), color.new(randomcolor ? Col : Bull , 70), color.new(randomcolor ? Col : Bull , 35)), bgcolor=color.from_gradient(array.get(ticks,i),0, array.max(ticks), color.new(randomcolor ? Col : Bull , 70), color.new(randomcolor ? Col : Bull , 35)), text=array.get(Volumes,i) > 0 ? str.tostring(array.get(Volumes,i),format.volume): "", text_color=color.white))
depthTooltip = "The minimum number of bars that will be taken into account when calculating the indicator." depth = input.int(title="Depth", defval=10, minval=2, inline = "Pivots", tooltip=depthTooltip) reverse = input(false, "Reverse", display = display.data_window) var extendLeft = input(false, "Extend Left | Extend Right", inline = "Extend Lines", display = display.data_window) var extendRight = input(true, "", inline = "Extend Lines", display = display.data_window) var extending = extend.none if extendLeft and extendRight extending := extend.both if extendLeft and not extendRight extending := extend.left if not extendLeft and extendRight extending := extend.right prices = input(true, "Show Prices", display = display.data_window) levels = input(true, "Show Levels", inline = "Levels", display = display.data_window) levelsFormat = input.string("Values", "", options = ["Values", "Percent"], inline = "Levels", display = display.data_window) labelsPosition = input.string("Left", "Labels Position", options = ["Left", "Right"], display = display.data_window) backgroundTransparency = input.int(85, "Background Transparency", minval = 0, maxval = 100, display = display.data_window)
upperThreshold = 0.236 lowerThreshold = 1.0
import TradingView/ZigZag/7 as zigzag
pivots(src, length, isHigh) => if bar_index >= length price = nz(src[length]) found = true for i = 0 to length * 2 if (isHigh and src > price) or (not isHigh and src < price) found := false break if found chart.point.from_time(time[length], price)
update()=> var line lineLastHL = na var line lineLastLH = na var line lineLast = na
var chart.point[] pivotsH = array.new<chart.point>() var chart.point lastH = na var chart.point[] pivotsL = array.new<chart.point>() var chart.point lastL = na
var isHighLast = false var float startPrice = na var float endPrice = na
H = pivots(high, depth / 2, true) L = pivots(low, depth / 2, false)
if countPivotsH > 0 and countPivotsL > 0 lastH := array.get(pivotsH, countPivotsH-1) lastL := array.get(pivotsL, countPivotsL-1) isHighLast := lastH.time > lastL.time if isHighLast if not na(H) if H.price > lastH.price array.set(pivotsH, countPivotsH-1, H) H := na else if not na(L) if L.price < lastL.price array.set(pivotsL, countPivotsL-1, L) L := na
if not na(H) array.push(pivotsH, H)
if not na(L) array.push(pivotsL, L)
if barstate.islast and array.size(pivotsH) > 0 and array.size(pivotsL) > 0 pivotsHCopy = array.copy(pivotsH) pivotsLCopy = array.copy(pivotsL) while array.size(pivotsHCopy) > 0 and array.size(pivotsLCopy) > 0 lastH := array.pop(pivotsHCopy) lastL := array.pop(pivotsLCopy)
_draw_line(price, col) => var id = line.new(time, price, time, price, color=col, width=1, extend=extending, xloc = xloc.bar_time) if not na(lineLast) line.set_xy1(id, line.get_x1(lineLast), price) line.set_xy2(id, line.get_x2(lineLast), price) id
//=====Inputs //____Source Inputs allowing for non-price inputs such as an oscillator hi_ = input.source(high,"High variable input",inline="source",group="Source") lo_ = input.source(low,"Low variable input",inline="source",group="Source") track_var = input.source(hlc3,title="Value to use to locate levels",group="Source")
//____Presentation related inputs bool use_vis = input.bool(false,"Use Visible range",tooltip="Limit lines drawn to the pane visible range",group="Pivots",inline="p0") bool use_fibs = input.bool(false,"Use Fibs vs Divide by 2",tooltip="Fibs Used: 0.236, 0.382, 0.5, 0.618, 0.786",group="Pivots",inline="p0") int layer_to_show = input.int(2,"Layers",minval=0,maxval=10,group="Pivots",tooltip="Increasing will further subdivid the range")-1 int offset_lastbar = input.int(defval=5,minval=0,maxval=300,title="Offset to last bar",group="Pivots",inline="p1") int l_len = input.int(50,"Root layer length",group="Pivots",inline="p1",tooltip="Higher level lengths will be a multiple>1 of this length") bool show_labels = input.bool(false,title="Show Labels",group="Labels",inline="lbl1") bool label_info = input.bool(false,"Show value vs ratio",group="Labels",inline="lbl1") int label_layer_lim = input.int(2,title="Layer limit",group="Labels",inline="lbl2") bool show_only_50 = input.bool(false,"Show mid_points for layers above limit ",group="Labels",inline="lbl2") string label_location = input.string("Center",title="Location",options=["Left","Center","Right"],group="Labels",inline="lbl3") string label_string = input.string("Center",title="Orientation",options=["Center","Above","Below"],group="Labels",inline="lbl3") string label_txt_size = input.string('Normal',"Text Size",options=['Tiny','Small','Normal','Large'],group="Labels",inline="lbl3")
//==== UDTs and Methods
//___ Detailed layer UDT - a wrapper for a map type level map <float,float> level_data
// Function Finds levels by drilling down and iterating to desired layer // param this (cPivot) UDT for the pivots // param hi (float) high value variable // param lo (float) low value variable // param tracking_x (float) value to be used to find levels in proximity // param layer (int) drill down layer // Returns (void) all maps stored in UDT method get_levels(cPivot this,float hi,float lo,float tracking_x_, int layer)=> var Max_H=0. var Min_L=10E10 [htf_max, htf_min]=request.security(syminfo.tickerid,"W",[nz(ta.max(hi_),hi_),nz(ta.min(lo_),lo_)],lookahead=barmerge.lookahead_off) Max_H := math.max(Max_H,nz(htf_max,hi_),hi_) Min_L := math.min(Min_L,nz(htf_min,lo_),lo_) change_high = nz(ta.change(Max_H))!=0 change_low = nz(ta.change(Min_L))!=0
this.recalc := change_low or change_high or bar_index==120 top_line =0. bot_line =0.
//__If the bar_index==120 to avoid potential issues with a range of 0 at bar_index==0 //__or if there is a change in the ATH or ATL if this.recalc this.level_groups.clear() one_before_levels=map.new<float,float>()
for i=0 to layer new_levels = map.new<float,float>()
if i==0 top_line := Max_H bot_line := Min_L else levels_array = one_before_levels.values() for [idx,level_] in levels_array
if tracking_x_>= level_ bot_line := level_ if idx>0 top_line := levels_array.get(idx-1) else top_line := levels_array.get(idx) break
//Check if the tracking_x location changed to a different map and if it did then redo the lower layer maps this.new_variable_location := (tracking_x_> this.current_top or tracking_x_< this.current_bot)
// only refresh levels if the variable location change requires it if not(this.recalc) and this.new_variable_location and bar_index>120 one_before_levels = this.level_groups.get(0).level_data.copy() this.level_groups.clear() this.level_groups.put(0,level.new(one_before_levels))
for i=1 to layer new_levels = map.new<float,float>() levels_array= one_before_levels.values() for [idx,level_] in levels_array if tracking_x_>= level_ bot_line := level_ if idx>0 top_line := levels_array.get(idx-1) else top_line := levels_array.get(idx) break
// Function Method used for presentation, drawing lines and labels // param this (cPivot) UDT for the pivots // param layer (int) drill down layer // Returns (void) all drawing objects stored in UDT arrays method draw_pivots(cPivot this,int layer,vis_hi,vis_lo,vis_range_off)=> //Refresh lines and labels if either ATH/ATL changed or teh variable location moved to a new zone if bar_index>120 and (this.recalc or this.new_variable_location) label_map=map.new<float,int>() label_map.clear()
for element in this.lines_ line.delete(element) for element in this.labels_ label.delete(element)
this.lines_.clear() this.labels_.clear() for i=0 to layer j= layer - i
// Label drawing if this.show_labels for key_ in this.level_groups.get(i).level_data.keys() element = this.level_groups.get(i).level_data.get(key_) text_ = this.label_info? str.tostring(math.round_to_mintick(element)): this.level_label.get(key_) conditions_ = (i+1<= this.label_limit or (i+1> this.label_limit and show_only_50 and key_==0.5)) and (element>= 0.98*vis_lo and element<=1.02*vis_hi or vis_range_off) if na(label_map.get(element)) and conditions_ this.labels_.push(label.new(x2_lab_coord,element,text=lvl_str+text_,color=this.level_color.get(key_), textcolor=color.black,style=this.label_style,size=this.label_txt_size)) label_map.put(element,1)
// Line drawing for key_ in this.level_groups.get(j).level_data.keys() element = this.level_groups.get(j).level_data.get(key_) if (element>= 0.98*vis_lo and element<=1.02*vis_hi) or vis_range_off this.lines_.push(line.new(x1_coord,element,x2_coord,element,color=this.level_color.get(key_),width=ln_width))
//Only update the x coordinate if the levels have not changed or the variabel did not force a change if bar_index>120 and not(this.recalc) and not(this.new_variable_location) if this.show_labels for label_ in this.labels_ label_.set_x(label_.get_x()+1)
// Line drawing for line_ in this.lines_ line_.set_x1(line_.get_x1()+1) line_.set_x2(line_.get_x2()+1)
//___One time bar index at 0 execution and setup. if bar_index==0 clone_pivot.label_txt_size := switch label_txt_size "Tiny" => size.tiny "Small" => size.small "Normal"=> size.normal "Large" => size.large => size.auto
//maps are not ordered but we will put (or push in array terms) the ratios in //descending order since in the method it will be needed in that order if use_fibs clone_pivot.level_color.put(1.0,color.white) clone_pivot.level_color.put(0.7864,color.rgb(138, 141, 151)) clone_pivot.level_color.put(0.618,color.silver) clone_pivot.level_color.put(0.5,color.yellow) clone_pivot.level_color.put(0.382,color.silver) clone_pivot.level_color.put(0.236,color.rgb(138, 141, 151)) clone_pivot.level_color.put(0,color.white)
//=== Get visible chart information to limit what is drawn visible_bars = (chart.right_visible_bar_time - chart.left_visible_bar_time)/(1000*timeframe.in_seconds())
//___ Method calls on each bar clone_pivot.get_levels(hi_,lo_,track_var,layer_to_show) clone_pivot.draw_pivots(layer_to_show,visible_hi,visible_lo,not(use_vis))
// While it seemed like a nice idea at the time, having separately-configurable upper and lower bands just doesn't really seem that useful as 90% of the time the settings for both are the same. // Therefore, We're going to simplify the config to make these settings unified for both bands, as it would otherwise just add even more confusion with the addition of take-profit bands as well... // // atrMultiplierUpper = input.float(title='ATR Upper Band Scale Factor', defval=2.5, step=0.1, minval=0.01, group="ATR Upper Band Settings", tooltip="Scaling factor (aka multiplier) for the ATR to use for plotting the ATR bands. " + // "This will usually be between 1 and 3.") // srcUpper = input.source(title='ATR Upper Offset Source', defval=close, group="ATR Upper Band Settings", tooltip="This setting determines the offset point for ATR bands. " + // "For this band, 'high' and 'close' (default) are generally the most appropriate values.") // atrMultiplier = input.float(title='ATR Band Scale Factor', defval=2.5, step=0.1, minval=0.01, group="ATR Bands Standard Settings", tooltip="Scaling factor (aka multiplier) for the ATR to use for plotting the ATR bands. " + "This will usually be between 1 and 3.\n\nDefault: 2.5") // On second thought, I'm going to nix this setting and force it to be the "close" source. Having the ability to offset based on the wicks was a nice idea, but doesn't really seem to have any notable practical application. atrSourceRef = "close" //atrSourceRef = input.string(title='ATR Upper Offset Source', defval="close", options=["close","wicks"], group="ATR Bands Standard Settings", tooltip="This setting determines the offset point for ATR bands. " + // "The default value 'close' should be your go-to, but 'wicks' might provide a bit more breathing room in securities that tend to have large wicks.") // // See above - these are deprecated and no longer used... // // atrMultiplierLower = input.float(title='ATR Lower Band Scale Factor', defval=2.5, step=0.1, minval=0.01, group="ATR Lower Band Settings", tooltip="Scaling factor (aka multiplier) for the ATR to use for plotting the ATR bands. " + // "This will usually be between 1 and 3.") // srcLower = input.source(title='ATR Lower Offset Source', defval=close, group="ATR Lower Band Settings", tooltip="This setting determines the offset point for ATR bands. " + // "For this band, 'low' and 'close' (default) are generally the most appropriate values.") // // // Take-Profit band settings showTPBands = input.bool(title="Show opposite bands for take-profit zones", defval=false, tooltip="If enalbled, the existing ATR bands will be treated as 'stop-loss' bands, and 'take-profit' bands will be plotted " + "to depict potential take-profit targets that are scaled based on the 'stop-loss' band and an additional reward/risk scaling factor (see below).\n\nDefault: Unchecked", group="Take-Profit Settings") tpScaleFactor = input.float(title="Take-Profit Scale Factor", defval=1.5, minval=1, step=0.1, tooltip="This is a secondary scaling factor used based on the 'stop-loss' ATR bands to calculate and plot a potential take-profit target.\n\n" + "The easiest way to think of this is as a desired reward/risk ratio, where the primary ATR Bands