Poly Cycle [Loxx]This is an example of what can be done by combining Legendre polynomials and analytic signals. I get a way of determining a smooth period and relative adaptive strength indicator without adding time lag.
This indicator displays the following:
The Least Squares fit of a polynomial to a DC subtracted time series - a best fit to a cycle.
The normalized analytic signal of the cycle (signal and quadrature).
The Phase shift of the analytic signal per bar.
The Period and HalfPeriod lengths, in bars of the current cycle.
A relative strength indicator of the time series over the cycle length. That is, adaptive relative strength over the cycle length.
The Relative Strength Indicator, is adaptive to the time series, and it can be smoothed by increasing the length of decreasing the number of degrees of freedom.
Other adaptive indicators based upon the period and can be similarly constructed.
There is some new math here, so I have broken the story up into 5 Parts:
Part 1:
Any time series can be decomposed into a orthogonal set of polynomials .
This is just math and here are some good references:
Legendre polynomials - Wikipedia, the free encyclopedia
Peter Seffen, "On Digital Smoothing Filters: A Brief Review of Closed Form Solutions and Two New Filter Approaches", Circuits Systems Signal Process, Vol. 5, No 2, 1986
I gave some thought to what should be done with this and came to the conclusion that they can be used for basic smoothing of time series. For the analysis below, I decompose a time series into a low number of degrees of freedom and discard the zero mode to introduce smoothing.
That is:
time series => c_1 t + c_2 t^2 ... c_Max t^Max
This is the cycle. By construction, the cycle does not have a zero mode and more physically, I am defining the "Trend" to be the zero mode.
The data for the cycle and the fit of the cycle can be viewed by setting
ShowDataAndFit = TRUE;
There, you will see the fit of the last bar as well as the time series of the leading edge of the fits. If you don't know what I mean by the "leading edge", please see some of the postings in . The leading edges are in grayscale, and the fit of the last bar is in color.
I have chosen Length = 17 and Degree = 4 as the default. I am simply making sure by eye that the fit is reasonably good and degree 4 is the lowest polynomial that can represent a sine-like wave, and 17 is the smallest length that lets me calculate the Phase Shift (Part 3 below) using the Hilbert Transform of width=7 (Part 2 below).
Depending upon the fit you make, you will capture different cycles in the data. A fit that is too "smooth" will not see the smaller cycles, and a fit that is too "choppy" will not see the longer ones. The idea is to use the fit to try to suppress the smaller noise cycles while keeping larger signal cycles.
Part 2:
Every time series has an Analytic Signal, defined by applying the Hilbert Transform to it. You can think of the original time series as amplitude * cosine(theta) and the transformed series, called the quadrature, can be thought of as amplitude * sine(theta). By taking the ratio, you can get the angle theta, and this is exactly what was done by John Ehlers in . It lets you get a frequency out of the time series under consideration.
Amazon.com: Rocket Science for Traders: Digital Signal Processing Applications (9780471405672): John F. Ehlers: Books
It helps to have more references to understand this. There is a nice article on Wikipedia on it.
Read the part about the discrete Hilbert Transform:
en.wikipedia.org
If you really want to understand how to go from continuous to discrete, look up this article written by Richard Lyons:
www.dspguru.com
In the indicator below, I am calculating the normalized analytic signal, which can be written as:
s + i h where i is the imagery number, and s^2 + h^2 = 1;
s= signal = cosine(theta)
h = Hilbert transformed signal = quadrature = sine(theta)
The angle is therefore given by theta = arctan(h/s);
The analytic signal leading edge and the fit of the last bar of the cycle can be viewed by setting
ShowAnalyticSignal = TRUE;
The leading edges are in grayscale fit to the last bar is in color. Light (yellow) is the s term, and Dark (orange) is the quadrature (hilbert transform). Note that for every bar, s^2 + h^2 = 1 , by construction.
I am using a width = 7 Hilbert transform, just like Ehlers. (But you can adjust it if you want.) This transform has a 7 bar lag. I have put the lag into the plot statements, so the cycle info should be quite good at displaying minima and maxima (extrema).
Part 3:
The Phase shift is the amount of phase change from bar to bar.
It is a discrete unitary transformation that takes s + i h to s + i h
explicitly, T = (s+ih)*(s -ih ) , since s *s + h *h = 1.
writing it out, we find that T = T1 + iT2
where T1 = s*s + h*h and T2 = s*h -h*s
and the phase shift is given by PhaseShift = arctan(T2/T1);
Alas, I have no reference for this, all I doing is finding the rotation what takes the analytic signal at bar to the analytic signal at bar . T is the transfer matrix.
Of interest is the PhaseShift from the closest two bars to the present, given by the bar and bar since I am using a width=7 Hilbert transform, bar is the earliest bar with an analytic signal.
I store the phase shift from bar to bar as a time series called PhaseShift. It basically gives you the (7-bar delayed) leading edge the amount of phase angle change in the series.
You can see it by setting
ShowPhaseShift=TRUE
The green points are positive phase shifts and red points are negative phase shifts.
On most charts, I have looked at, the indicator is mostly green, but occasionally, the stock "retrogrades" and red appears. This happens when the cycle is "broken" and the cycle length starts to expand as a trend occurs.
Part 4:
The Period:
The Period is the number of bars required to generate a sum of PhaseShifts equal to 360 degrees.
The Half-period is the number of bars required to generate a sum of phase shifts equal to 180 degrees. It is usually not equal to 1/2 of the period.
You can see the Period and Half-period by setting
ShowPeriod=TRUE
The code is very simple here:
Value1=0;
Value2=0;
while Value1 < bar_index and math.abs(Value2) < 360 begin
Value2 = Value2 + PhaseShift ;
Value1 = Value1 + 1;
end;
Period = Value1;
The period is sensitive to the input length and degree values but not overly so. Any insight on this would be appreciated.
Part 5:
The Relative Strength indicator:
The Relative Strength is just the current value of the series minus the minimum over the last cycle divided by the maximum - minimum over the last cycle, normalized between +1 and -1.
RelativeStrength = -1 + 2*(Series-Min)/(Max-Min);
It therefore tells you where the current bar is relative to the cycle. If you want to smooth the indicator, then extend the period and/or reduce the polynomial degree.
In code:
NewLength = floor(Period + HilbertWidth+1);
Max = highest(Series,NewLength);
Min = lowest(Series,NewLength);
if Max>Min then
Note that the variable NewLength includes the lag that comes from the Hilbert transform, (HilbertWidth=7 by default).
Conclusion:
This is an example of what can be done by combining Legendre polynomials and analytic signals to determine a smooth period without adding time lag.
________________________________
Changes in this one : instead of using true/false options for every single way to display, use Type parameter as following :
1. The Least Squares fit of a polynomial to a DC subtracted time series - a best fit to a cycle.
2. The normalized analytic signal of the cycle (signal and quadrature).
3. The Phase shift of the analytic signal per bar.
4. The Period and HalfPeriod lengths, in bars of the current cycle.
5. A relative strength indicator of the time series over the cycle length. That is, adaptive relative strength over the cycle length.
Cerca negli script per "bar"
statisticsLibrary "statistics"
General statistics library.
erf(x) The "error function" encountered in integrating the normal
distribution (which is a normalized form of the Gaussian function).
Parameters:
x : The input series.
Returns: The Error Function evaluated for each element of x.
erfc(x)
Parameters:
x : The input series
Returns: The Complementary Error Function evaluated for each alement of x.
sumOfReciprocals(src, len) Calculates the sum of the reciprocals of the series.
For each element 'elem' in the series:
sum += 1/elem
Should the element be 0, the reciprocal value of 0 is used instead
of NA.
Parameters:
src : The input series.
len : The length for the sum.
Returns: The sum of the resciprocals of 'src' for 'len' bars back.
mean(src, len) The mean of the series.
(wrapper around ta.sma).
Parameters:
src : The input series.
len : The length for the mean.
Returns: The mean of 'src' for 'len' bars back.
average(src, len) The mean of the series.
(wrapper around ta.sma).
Parameters:
src : The input series.
len : The length for the average.
Returns: The average of 'src' for 'len' bars back.
geometricMean(src, len) The Geometric Mean of the series.
The geometric mean is most important when using data representing
percentages, ratios, or rates of change. It cannot be used for
negative numbers
Since the pure mathematical implementation generates a very large
intermediate result, we performed the calculation in log space.
Parameters:
src : The input series.
len : The length for the geometricMean.
Returns: The geometric mean of 'src' for 'len' bars back.
harmonicMean(src, len) The Harmonic Mean of the series.
The harmonic mean is most applicable to time changes and, along
with the geometric mean, has been used in economics for price
analysis. It is more difficult to calculate; therefore, it is less
popular than eiter of the other averages.
0 values are ignored in the calculation.
Parameters:
src : The input series.
len : The length for the harmonicMean.
Returns: The harmonic mean of 'src' for 'len' bars back.
median(src, len) The median of the series.
(a wrapper around ta.median)
Parameters:
src : The input series.
len : The length for the median.
Returns: The median of 'src' for 'len' bars back.
variance(src, len, biased) The variance of the series.
Parameters:
src : The input series.
len : The length for the variance.
biased : Wether to use the biased calculation (for a population), or the
unbiased calculation (for a sample set). .
Returns: The variance of 'src' for 'len' bars back.
stdev(src, len, biased) The standard deviation of the series.
Parameters:
src : The input series.
len : The length for the stdev.
biased : Wether to use the biased calculation (for a population), or the
unbiased calculation (for a sample set). .
Returns: The standard deviation of 'src' for 'len' bars back.
skewness(src, len) The skew of the series.
Skewness measures the amount of distortion from a symmetric
distribution, making the curve appear to be short on the left
(lower prices) and extended to the right (higher prices). The
extended side, either left or right is called the tail, and a
longer tail to the right is called positive skewness. Negative
skewness has the tail extending towards the left.
Parameters:
src : The input series.
len : The length for the skewness.
Returns: The skewness of 'src' for 'len' bars back.
kurtosis(src, len) The kurtosis of the series.
Kurtosis describes the peakedness or flatness of a distribution.
This can be used as an unbiased assessment of whether prices are
trending or moving sideways. Trending prices will ocver a wider
range and thus a flatter distribution (kurtosis < 3; negative
kurtosis). If prices are range-bound, there will be a clustering
around the mean and we have positive kurtosis (kurtosis > 3)
Parameters:
src : The input series.
len : The length for the kurtosis.
Returns: The kurtosis of 'src' for 'len' bars back.
excessKurtosis(src, len) The normalized kurtosis of the series.
kurtosis > 0 --> positive kurtosis --> trending
kurtosis < 0 --> negative krutosis --> range-bound
Parameters:
src : The input series.
len : The length for the excessKurtosis.
Returns: The excessKurtosis of 'src' for 'len' bars back.
normDist(src, len, value) Calculates the probability mass for the value according to the
src and length. It calculates the probability for value to be
present in the normal distribution calculated for src and length.
Parameters:
src : The input series.
len : The length for the normDist.
value : The series of values to calculate the normal distance for
Returns: The normal distance of 'value' to 'src' for 'len' bars back.
normDistCumulative(src, len, value) Calculates the cumulative probability mass for the value according
to the src and length. It calculates the cumulative probability for
value to be present in the normal distribution calculated for src
and length.
Parameters:
src : The input series.
len : The length for the normDistCumulative.
value : The series of values to calculate the cumulative normal distance
for
Returns: The cumulative normal distance of 'value' to 'src' for 'len' bars
back.
zScore(src, len, value) Returns then z-score of objective to the series src.
It returns the number of stdev's the objective is away from the
mean(src, len)
Parameters:
src : The input series.
len : The length for the zScore.
value : The series of values to calculate the cumulative normal distance
for
Returns: The z-score of objectiv with respect to src and len.
er(src, len) Calculates the efficiency ratio of the series.
It measures the noise of the series. The lower the number, the
higher the noise.
Parameters:
src : The input series.
len : The length for the efficiency ratio.
Returns: The efficiency ratio of 'src' for 'len' bars back.
efficiencyRatio(src, len) Calculates the efficiency ratio of the series.
It measures the noise of the series. The lower the number, the
higher the noise.
Parameters:
src : The input series.
len : The length for the efficiency ratio.
Returns: The efficiency ratio of 'src' for 'len' bars back.
fractalEfficiency(src, len) Calculates the efficiency ratio of the series.
It measures the noise of the series. The lower the number, the
higher the noise.
Parameters:
src : The input series.
len : The length for the efficiency ratio.
Returns: The efficiency ratio of 'src' for 'len' bars back.
mse(src, len) Calculates the Mean Squared Error of the series.
Parameters:
src : The input series.
len : The length for the mean squared error.
Returns: The mean squared error of 'src' for 'len' bars back.
meanSquaredError(src, len) Calculates the Mean Squared Error of the series.
Parameters:
src : The input series.
len : The length for the mean squared error.
Returns: The mean squared error of 'src' for 'len' bars back.
rmse(src, len) Calculates the Root Mean Squared Error of the series.
Parameters:
src : The input series.
len : The length for the root mean squared error.
Returns: The root mean squared error of 'src' for 'len' bars back.
rootMeanSquaredError(src, len) Calculates the Root Mean Squared Error of the series.
Parameters:
src : The input series.
len : The length for the root mean squared error.
Returns: The root mean squared error of 'src' for 'len' bars back.
mae(src, len) Calculates the Mean Absolute Error of the series.
Parameters:
src : The input series.
len : The length for the mean absolute error.
Returns: The mean absolute error of 'src' for 'len' bars back.
meanAbsoluteError(src, len) Calculates the Mean Absolute Error of the series.
Parameters:
src : The input series.
len : The length for the mean absolute error.
Returns: The mean absolute error of 'src' for 'len' bars back.
BE_CustomFx_LibraryLibrary "BE_CustomFx_Library"
A handful collection of regular functions, Custom Tools & Utility Functions could be used in regular Scripts. hope these functions can be understood by a non programmer like me too.
G_TextValOfNumber(ValueToConvert, RequiredDecimalPlaces, BeginingChar, EndChar) Function to return the String Value of Number with decimal precision with the prefix and suffix characters provided
Parameters:
ValueToConvert : = Number to Convert
RequiredDecimalPlaces : = No of Decimal values Required. supports to a max of 5 decimals else defaults to 2
BeginingChar : = Prefix character which is needed.
EndChar : = Suffix character which is needed.
Returns: Returns Out put with formated value of Given Number for the specified deicimal values with Prefix and suffix string
G_TradableValue(ValueToConvert, NeedCustomization, RequiredDecimalPlaces) Function to return the Tradable Value of Number
Parameters:
ValueToConvert : = Number to Convert
NeedCustomization : = set to 1 if you want to customize the decimal percision values. default is No customization needed, which provides output equalent to round_to_mintick
RequiredDecimalPlaces : = if NeedCustomization is set to 1 mention the decimal percision value required. max supported decimal is 5 else defaults to 2
Returns: Returns Out put with formated value of Given Number
G_TxtSizeForLables(SizeValue) Function to Get size Value for text values used in Lables
Parameters:
SizeValue : = auto, tiny, small, normal, large, huge. specify either of these values or default value Normal will be displayed as output
Returns: Returns Respective Text size
G_Reg_LineType(LineType) Function to Get Line Style Value for text values used in Lines
Parameters:
LineType : = 'solid (─)', 'dotted (┈)', 'dashed (╌)', 'arrow left (←)', 'arrow right (→)', 'arrows both (↔)' or default line style 'dotted (┈)' will be the output
Returns: Returns Respective Line style
G_ShapeTypeForLables(ShapeType) Function to Get Shape Style Value for text values used in plot shapes
Parameters:
ShapeType : = 'XCross', 'Cross', 'Triangle Up', 'Triangle Down', 'Flag', 'Circle','Arrow Up', 'Arrow Down','Lable Up', 'Lable Down' or default shpae style Triangle Up will be the output
Returns: Returns Respective Shape style
G_Indicator_Val(string, float, int, int) Gets Output of the technical analyis indicator which has length Parameter. RSI, ATR, EMA, SMA, HMA, WMA, VWMA, 'CMO', 'MOM', 'ROC','VWAP'
Parameters:
string : IndicatorName to be specified
float : SrcVal for the TA indicator default is close
int : Length for the TA indicator
int : DecimalValue optional to specify if required formatted output with decimal percision
Returns: Value with the given parameters
G_CandleInfo(string, bool, float, bool) function to get Candle Informarion such as both wicksize, top wick size , bottom wick size, full candle size and body size in default points
Parameters:
string : WhatCandleInfo, string input with either of these options "Wick" , "TWick" , "BWick" , "Candle", "Body" , "BearfbVal", "BullfbVal" , "CandleOpen" ,"CandleClose", "CandleHigh" , "CandleLow", "BodyPct"
bool : RepaintingVersion, set to true if required data on the realtime bar else default is set to false
float : FibValueOfCandle, set the fibo value to extract fibvalue of the candle else default is set to 38.2%
bool : AccountforGaps, set to true if required data on considering the gap between previous and current bar else default is set to false
Returns: Returns Respective values for the candles
G_BullBearBarCount(int, int) Counts how many green & red bars have printed recently (ie. pullback count)
Parameters:
int : HowManyCandlesToCheck The lookback period to look back over
int : BullBear The color of the bar to count (1 = Bull, -1 = Bear), Open = close candles are ignored
Returns: The bar count of how many candles have retraced over the given lookback with specific candles
BarToStartYourCalculation(Int) function to get candle co-ordinate in order to use it further for calculating your analysis work . "Heart full Thanks to 3 Pine motivators (LonesomeTheBlue, Myank & Sriki) who helped me cracking this logic"
Parameters:
Int : SelectedCandleNumber (default=450) How many candles you would need to anlysie in your script from the right.
Returns: A boolean - output is returned to say the starting point and continue to diplay true for the future candles
isHammer(float, bool, bool) Checks if the current bar is a hammer candle based on the given parameters
Parameters:
float : fib (default=0.382) The fib to base candle body on
bool : colorMatch (default=false) Does the candle need to be green? (true/false)
bool : NeedRepainting (default=false) Specify True if you need them to calculate on the realtime bars
Returns: A boolean - true if the current bar matches the requirements of a hammer candle
isStar(float, bool, bool) Checks if the current bar is a shooting star candle based on the given parameters
Parameters:
float : fib (default=0.382) The fib to base candle body on
bool : colorMatch (default=false) Does the candle need to be red? (true/false)
bool : NeedRepainting (default=false) Specify True if you need them to calculate on the realtime bars
Returns: A boolean - true if the current bar matches the requirements of a shooting star candle
isDoji(float, float, bool) Checks if the current bar is a doji candle based on the given parameters
Parameters:
float : _wickSize (default=1.5 times) The maximum allowed times can be top wick size compared to the bottom (and vice versa)
float : _bodySize (default= 5 percent to be mentioned as 0.05) The maximum body size as a percentage compared to the entire candle size
bool : NeedRepainting (default=false) Specify true if you need them to calculate on the realtime bars
Returns: A boolean - true if the current bar matches the requirements of a doji candle
isBullishEC(float, float, bool, bool) Checks if the current bar is a bullish engulfing candle
Parameters:
float : _allowance (default=0) How many POINTS to allow the open to be off by (useful for markets with micro gaps)
float : _rejectionWickSize (default=disabled) The maximum rejection wick size compared to the body as a percentage
bool : _engulfWick (default=false) Does the engulfing candle require the wick to be engulfed as well?
bool : NeedRepainting (default=false) Specify True if you need them to calculate on the realtime bars
Returns: A boolean - true if the current bar matches the requirements of a bullish engulfing candle
isBearishEC(float, float, bool, bool) Checks if the current bar is a bearish engulfing candle
Parameters:
float : _allowance (default=0) How many POINTS to allow the open to be off by (useful for markets with micro gaps)
float : _rejectionWickSize (default=disabled) The maximum rejection wick size compared to the body as a percentage
bool : _engulfWick (default=false) Does the engulfing candle require the wick to be engulfed as well?
bool : NeedRepainting (default=false) Specify True if you need them to calculate on the realtime bars
Returns: A boolean - true if the current bar matches the requirements of a bearish engulfing candle
Plot_TrendLineAtDegree(float, float, int, string, bool) helps you to plot the Trendlines based on the specified angle at the defined price to bar ratio
Parameters:
float : Degree (default=14) angle at which Trendline to be plot
float : price2bar_ratio (default=1e-10) The maximum rejection wick size compared to the body as a percentage
int : Bars2Plot (default=6) Does the engulfing candle require the wick to be engulfed as well?
string : LineStyle = 'solid (─)', 'dotted (┈)', 'dashed (╌)', 'arrow left (←)', 'arrow right (→)', 'arrows both (↔)' or default line style 'dotted (┈)' will be the output
bool : PlotOnOpen_Close (default=false) Specify True if you need them to calculate on the Open\Close Values
Returns: plot the Trendlines based on the specified angle at the defined price to bar ratio
How to avoid repainting when NOT using security()Even when your code does not use security() calls, repainting dynamics still come into play in the realtime bar. Script coders and users must understand them and, if they choose to avoid repainting, need to know how to do so. This script demonstrates three methods to avoid repainting when NOT using the security() function.
Note that repainting dynamics when not using security() usually only come into play in the realtime bar, as historical data is fixed and thus cannot cause repainting, except in situations related to stock splits or dividend adjustments.
For those who don’t want to read
Configure your alerts to trigger “Once Per Bar Close” and you’re done.
For those who want to understand
Put this indicator on a 1 minute or seconds chart with a live symbol. As price changes you will see four of this script’s MAs (all except the two orange ones) move in the realtime bar. You are seeing repainting in action. When the current realtime bar closes and becomes a historical bar, the lines on the historical bars will no longer move, as the bar’s OHLC values are fixed. Note that you may need to refresh your chart to see the correct historical OHLC values, as exchange feeds sometimes produce very slight variations between the end values of the realtime bar and those of the same bar once it becomes a historical bar.
Some traders do not use signals generated by a script but simply want to avoid seeing the lines plotted by their scripts move during the realtime bar. They are concerned with repainting of the lines .
Other traders use their scripts to evaluate conditions, which they use to either plot markers on the chart, trigger alerts, or both. They may not care about the script’s plotted lines repainting, but do not want their markers to appear/disappear on the chart, nor their alerts to trigger for a condition that becomes true during the realtime bar but is no longer true once it closes. Those traders are more concerned with repainting of signals .
For each of the three methods shown in this script’s code, comments explain if its lines, markers and alerts will repaint or not. Through the Settings/Inputs you will be able to control plotting of lines and markers corresponding to each method, as well as experiment with the option, for method 2, of disabling only the lines plotting in the realtime bar while still allowing the markers and alerts to be generated.
An unavoidable fact is that non-repainting lines, markers or alerts are always late compared to repainting ones. The good news is that how late they are will in many cases be insignificant, so that the added reliability of the information they provide will largely offset the disadvantages of waiting.
Method 1 illustrates the usual way of going about things in a script. Its gray lines and markers will always repaint but repainting of the alerts the marker conditions generate can be avoided by configuring alerts to trigger “Once Per Bar Close”. Because this gray marker repaints, you will occasionally see it appear/disappear during the realtime bar when the gray MAs cross/un-cross.
Method 2 plots the same MAs as method 1, but in green. The difference is that it delays its marker condition by one bar to ensure it does not repaint. Its lines will normally repaint but its markers will not, as they pop up after the condition has been confirmed on the bar preceding the realtime bar. Its markers appear at the beginning of the realtime bar and will never disappear. When using this method alerts can be configured to trigger “Once Per Bar” so they fire the moment the marker appears on the chart at the beginning of the realtime bar. Note that the delay incurred between methods 1 and 2 is merely the instant between the close of a realtime bar and the beginning of the next one—a delay measured in milliseconds. Method 2 also allows its lines to be hidden in the realtime bar with the corresponding option in the script’s Settings/Inputs . This will be useful to those wishing to eliminate unreliable lines from the realtime bar. Commented lines in method 2 provide for a 2b option, which is to delay the calculation of the MAs rather than the cross condition. It has the obvious inconvenient of plotting delayed MAs, but may come in handy in some situations.
Method 3 is not the best solution when using MAs because it uses the open of bars rather than their close to calculate the MAs. While this provides a way of avoiding repainting, it is not ideal in the case of MA calcs but may come in handy in other cases. The orange lines and markers of method 3 will not repaint because the value of open cannot change in the realtime bar. Because its markers do not repaint, alerts may be configured using “Once Per Bar”.
Spend some time playing with the different options and looking at how this indicator’s lines plot and behave when you refresh you chart. We hope everything you need to understand and prevent repainting when not using security() is there.
Look first. Then leap.
Delta Volume Columns [LucF]Displays delta volume columns using intrabar volume information. Each volume column is divided into three sections: buying, selling and neutral volume. Volume for each section is determined from the volume and price movement of each intrabar at a user-selected lower resolution.
Features include:
- Choice of color themes for either dark or light chart backgrounds
- Delta volume columns
- Volume Balance displayed as the difference between the MAs of buying and selling volume
- Display of divergences between a bar’s volume balance and the bar’s price movement (example: buying volume > selling volume but close < open). Divergences can be shown in 2 different color schemes (including green/red showing a tentative direction), on volume columns and/or on chart bars
- Display of bar by bar volume balance with highlighting of above average volume
- Display of the usual total volume MA
- Choice of the lower resolution used to retrieve intrabar information
- Alerts configurable on any combination of the markers, with control over long/short direction
- Choice of 3 different markers:
1. Double bumps: two consecutive bars where buying or selling volume is in the same direction and where volume > volume MA
2. Divergence confirmations: direction of the price bar following a price/volume balance divergence
3. Volume balance shifts: zero level crossings of the volume balance MA delta
The chart shows the two main modes of display:
- Top pane : shows the stacked volume columns with divergences in orange and the flattened volume balance MAs delta at the bottom of the volume columns. This volume balance is the same shown in the bottom pane. The top pane also shows the instant volume balance strip above the volume columns. The strip’s colors show which of the buying or selling volume was greater, and colors are brighter if the total volume was above the total volume MA.
- Bottom pane : shows the volume balance MAs delta with markers 1 and 2. Given that this graphic has no price momentum component, I find quite eerie how it often looks like a momentum-based signal.
The default 5 minute intrabar resolution is used in combination with the weekly chart, which is excessive.
This script uses a special characteristic of the security() function’s behavior when it is sent to a resolution lower than the chart’s resolution. Details are given in the script’s comments. This method has the advantage of working under more circumstances than some of the other loop-based methods, but it also has its limits.
IMPORTANT
This is what you need to know:
- The method used does not work on the realtime bar—only on historical bars. Consequently, the volume column shown on the realtime bar is a normal volume column plotted in green or red, following price movement. The column will only show delta volume information after it closes and becomes a historical bar.
- The indicator only works on some chart resolutions: 5, 10, 15 and 30 minutes, 1, 2, 4, 6, and 12 hours, 1 day, 1 week and 1 month. The script’s code can be modified to run on other resolutions, but chart resolutions must be divisible by the lower resolution used for intrabars.
- Intrabar resolutions can be selected from 1, 5, 15, 30, 45 minutes, 1, 2, 3, 4 hours, 1 day, 1 week and 1 month. The intrabar resolution must of course be smaller than the chart’s resolution.
- Contrary to my other indicators where alerts must be configured to trigger “Once Per Bar Close” in order to avoid false triggers (or repainting), all this indicator’s alerts are designed to trigger using previous bar information since the indicator’s calculations in the realtime bar are not exact. Markers are not plotted with a negative offset; they appear at the beginning of the realtime bar following confirmation of the marker’s condition on the previous bar. Alerts for this indicator should thus be configured to trigger “Once Per Bar” so they trigger at the beginning of the realtime bar. Note that the penalty is not that great, as it is simply the instant between the close of the previous realtime bar and the opening of the next. The advantage of using this technique is that the indicator does not repaint; a marker that appears at the beginning of the realtime bar will never disappear.
- The script only plots information that is reliable in the realtime bar, i.e., total volume and markers. All other plots are set to n/a to prevent misleading traders.
- When the difference between the chart’s resolution and the lower resolution is too important, volume columns will not calculate for all bars in the dataset.
On Delta Volume
Buying or selling volume are misnomers, as every unit of volume transacted is both bought and sold by 2 different traders. There is no such thing as “buy only” or “sell only” volume, but trader lingo is riddled with original fabulations.
Without access to order book information, traders work with the assumption that when price moves up during a bar, there was more buying pressure than selling pressure. The built-in volume indicator available on TradingView uses this logic to color the volume columns green or red. While this script’s numbers are more precise because it analyses a number of intrabars to calculate its information, it uses the exact same imperfect logic to calculate its buying/selling/neutral sections.
Until Pine scripts can have access to how much volume was transacted at the bid/ask prices, our so-called buying/selling volume information will always be a mere proxy.
Divergences
You may wonder how there can be divergences between buying/selling volume information and price movement. This will sometimes be due to the methodology’s shortcomings we have just discussed, but divergences may also occur in instances where because of order book structure, it takes less volume to increase the price of an asset than it takes to decrease it.
As usual, divergences are points of interest because they reveal imbalances, which may or may not become turning points. I do not share the overwhelming enthusiasm traders have for divergences. To your pattern-hungry brain, the orange bars this indicator shows on chart will—as divergences on other indicators do–appear to often indicate turnarounds. My opinion is that reality is generally quite sobering, as many who have tried building automated rules based on divergences will tell you. I do not have hard numbers on the lack of performance of divergences—only many failed attempts to make them perform, which a few experienced strategy modelers I know share with me. Please don’t try to read too much into them. While they look great on past data, I find they are often difficult to use in realtime to make bets with good odds.
Thanks to:
- A guy called Kuan who commented on a Backtest Rookies presentation of an intrabar delta volume indicator using a for loop. The heart of “my” indicator is code borrowed from Kuan; I just built a hopefully useful wrapper around it.
- @theheirophant, my partner in the exploration of the sometimes weird abysses of security() ’s behavior at lower resolutions.
How to avoid repainting when using security() - PineCoders FAQNOTE
The non-repainting technique in this publication that relies on bar states is now deprecated, as we have identified inconsistencies that undermine its credibility as a universal solution. The outputs that use the technique are still available for reference in this publication. However, we do not endorse its usage. See this publication for more information about the current best practices for requesting HTF data and why they work.
This indicator shows how to avoid repainting when using the security() function to retrieve information from higher timeframes.
What do we mean by repainting?
Repainting is used to describe three different things, in what we’ve seen in TV members comments on indicators:
1. An indicator showing results that change during the realtime bar, whether the script is using the security() function or not, e.g., a Buy signal that goes on and then off, or a plot that changes values.
2. An indicator that uses future data not yet available on historical bars.
3. An indicator that uses a negative offset= parameter when plotting in order to plot information on past bars.
The repainting types we will be discussing here are the first two types, as the third one is intentional—sometimes even intentionally misleading when unscrupulous script writers want their strategy to look better than it is.
Let’s be clear about one thing: repainting is not caused by a bug ; it is caused by the different context between historical bars and the realtime bar, and script coders or users not taking the necessary precautions to prevent it.
Why should repainting be avoided?
Repainting matters because it affects the behavior of Pine scripts in the realtime bar, where the action happens and counts, because that is when traders (or our systems) take decisions where odds must be in our favor.
Repainting also matters because if you test a strategy on historical bars using only OHLC values, and then run that same code on the realtime bar with more than OHLC information, scripts not properly written or misconfigured alerts will alter the strategy’s behavior. At that point, you will not be running the same strategy you tested, and this invalidates your test results , which were run while not having the additional price information that is available in the realtime bar.
The realtime bar on your charts is only one bar, but it is a very important bar. Coding proper strategies and indicators on TV requires that you understand the variations in script behavior and how information available to the script varies between when the script is running on historical and realtime bars.
How does repainting occur?
Repainting happens because of something all traders instinctively crave: more information. Contrary to trader lure, more information is not always better. In the realtime bar, all TV indicators (a.k.a. studies ) execute every time price changes (i.e. every tick ). TV strategies will also behave the same way if they use the calc_on_every_tick = true parameter in their strategy() declaration statement (the parameter’s default value is false ). Pine coders must decide if they want their code to use the realtime price information as it comes in, or wait for the realtime bar to close before using the same OHLC values for that bar that would be used on historical bars.
Strategy modelers often assume that using realtime price information as it comes in the realtime bar will always improve their results. This is incorrect. More information does not necessarily improve performance because it almost always entails more noise. The extra information may or may not improve results; one cannot know until the code is run in realtime for enough time to provide data that can be analyzed and from which somewhat reliable conclusions can be derived. In any case, as was stated before, it is critical to understand that if your strategy is taking decisions on realtime tick data, you are NOT running the same strategy you tested on historical bars with OHLC values only.
How do we avoid repainting?
It comes down to using reliable information and properly configuring alerts, if you use them. Here are the main considerations:
1. If your code is using security() calls, use the syntax we propose to obtain reliable data from higher timeframes.
2. If your script is a strategy, do not use the calc_on_every_tick = true parameter unless your strategy uses previous bar information to calculate.
3. If your script is a study and is using current timeframe information that is compared to values obtained from a higher timeframe, even if you can rely on reliable higher timeframe information because you are correctly using the security() function, you still need to ensure the realtime bar’s information you use (a cross of current close over a higher timeframe MA, for example) is consistent with your backtest methodology, i.e. that your script calculates on the close of the realtime bar. If your system is using alerts, the simplest solution is to configure alerts to trigger Once Per Bar Close . If you are not using alerts, the best solution is to use information from the preceding bar. When using previous bar information, alerts can be configured to trigger Once Per Bar safely.
What does this indicator do?
It shows results for 9 different ways of using the security() function and illustrates the simplest and most effective way to avoid repainting, i.e. using security() as in the example above. To show the indicator’s lines the most clearly, price on the chart is shown with a black line rather than candlesticks. This indicator also shows how misusing security() produces repainting. All combinations of using a 0 or 1 offset to reference the series used in the security() , as well as all combinations of values for the gaps= and lookahead= parameters are shown.
The close in the call labeled “BEST” means that once security has reached the upper timeframe (1 day in our case), it will fetch the previous day’s value.
The gaps= parameter is not specified as it is off by default and that is what we need. This ensures that the value returned by security() will not contain na values on any of our chart’s bars.
The lookahead security() to use the last available value for the higher timeframe bar we are using (the previous day, in our case). This ensures that security() will return the value at the end of the higher timeframe, even if it has not occurred yet. In our case, this has no negative impact since we are requesting the previous day’s value, with has already closed.
The indicator’s Settings/Inputs allow you to set:
- The higher timeframe security() calls will use
- The source security() calls will use
- If you want identifying labels printed on the lines that have no gaps (the lines containing gaps are plotted using very thick lines that appear as horizontal blocks of one bar in length)
For the lines to be plotted, you need to be on a smaller timeframe than the one used for the security() calls.
Comments in the code explain what’s going on.
Look first. Then leap.
BACAP PRICE STRUCTURE 21 EMA TREND21dma-STRUCTURE
Overview
The 21dma-STRUCTURE indicator is a sophisticated overlay indicator that visualizes price action relative to a triple 21-period exponential moving average structure. Originally developed by BalarezoCapital and enhanced by PrimeTrading, this indicator provides clear visual cues for trend direction and momentum through dynamic bar coloring and EMA structure analysis.
Key Features
Triple EMA Structure
- 21 EMA High: Tracks the exponential moving average of high prices
- 21 EMA Close: Tracks the exponential moving average of closing prices
- 21 EMA Low: Tracks the exponential moving average of low prices
- Dynamic Cloud: Gray fill between high and low EMAs for visual structure reference
Smart Bar Coloring System
- Blue Bars: Price closes above all three EMAs (strong bullish momentum)
- Pink Bars: Daily high falls below the lowest EMA (strong bearish signal)
- Gray Bars: Neutral conditions or transitional phases
- Color Memory: Maintains previous color until new condition is met
Dynamic Center Line
- Trend-Following Color: Green when all EMAs are rising, red when all are falling
- Color Persistence: Maintains trend color during sideways movement
- Visual Clarity: Thicker center line for easy trend identification
Customizable Visual Elements
- Adjustable line thickness for all EMA plots
- Customizable colors for bullish and bearish conditions
- Configurable trend colors for uptrend and downtrend phases
- Optional bar color changes with toggle control
How to Use
Trend Identification
- Rising Green Center Line: All EMAs trending upward (bullish structure)
- Falling Red Center Line: All EMAs trending downward (bearish structure)
- Flat Center Line: Maintains last trend color during consolidation
Momentum Analysis
- Blue Bars: Strong bullish momentum with price above entire EMA structure
- Pink Bars: Strong bearish momentum with high below lowest EMA
- Gray Bars: Neutral or transitional momentum phases
Entry and Exit Signals
- Bullish Setup: Look for blue bars during green center line periods
- Bearish Setup: Look for pink bars during red center line periods
- Exit Consideration: Watch for color changes as potential momentum shifts
Structure Trading
- Support/Resistance: Use EMA cloud as dynamic support and resistance zones
- Breakout Confirmation: Bar color changes can confirm structure breakouts
- Trend Continuation: Color persistence suggests ongoing momentum
Settings
Visual Customization
- Change Bar Color: Toggle to enable/disable bar coloring
- Line Size: Adjust thickness of EMA lines (default: 3)
- Bullish Candle Color: Customize blue bar color
- Bearish Candle Color: Customize pink bar color
Trend Colors
- Uptrend Color: Color for rising EMA center line (default: green)
- Downtrend Color: Color for falling EMA center line (default: red)
- Cloud Color: Fill color between high and low EMAs (default: gray)
Advanced Features
Modified Bar Logic
Unlike traditional EMA systems, this indicator uses refined conditions:
- Bullish signals require close above ALL three EMAs
- Bearish signals require high below the LOWEST EMA
- Enhanced precision reduces false signals compared to single EMA systems
Trend Memory System
- Intelligent color persistence during sideways movement
- Reduces noise from minor EMA fluctuations
- Maintains trend context during consolidation periods
Performance Optimization
- Efficient calculation methods for real-time performance
- Clean visual design that doesn't clutter charts
- Compatible with all timeframes and instruments
Best Practices
Multi-Timeframe Analysis
- Use higher timeframes to identify overall trend direction
- Apply on multiple timeframes for confluence
- Combine with weekly/monthly charts for position trading
Risk Management
- Use bar color changes as early warning signals
- Consider position sizing based on EMA structure strength
- Set stops relative to EMA support/resistance levels
Combination Strategies
- Pair with volume indicators for confirmation
- Use alongside RSI or MACD for momentum confirmation
- Combine with key support/resistance levels
Market Context
- More effective in trending markets than choppy conditions
- Consider overall market environment and sector strength
- Adjust expectations during high volatility periods
Technical Specifications
- Based on 21-period exponential moving averages
- Uses Pine Script v6 for optimal performance
- Overlay indicator that works with any chart type
- Maximum 500 lines for clean performance
Ideal Applications
- Swing trading on daily charts
- Position trading on weekly charts
- Intraday momentum trading (adjust timeframe accordingly)
- Trend following strategies
- Structure-based trading approaches
Disclaimer
This indicator is for educational and informational purposes only. It should not be used as the sole basis for trading decisions. Always combine with other forms of analysis, proper risk management, and consider your individual trading plan and risk tolerance.
Compatible with Pine Script v6 | Works on all timeframes | Optimized for trending markets
Pullback Candle (Bullish & Bearish, No EMA)🔍 Purpose
This indicator detects simple pullback reversal patterns based on price action and swing highs/lows — without any moving average or trend filters.
It highlights:
Bullish pullbacks (potential bounce/long setups)
Bearish pullbacks (potential rejection/short setups)
📈 Bullish Pullback Criteria
Three-bar pattern:
Bar 3: Highest close
Bar 2: Lower close
Bar 1: Even lower close
Current bar closes above previous bar (bullish reversal)
One of the last two candles is the lowest low of the past 6 bars (swing low)
📍 Result: A small green cross is plotted below the bar, and the bar is colored green.
📉 Bearish Pullback Criteria
Three-bar pattern:
Bar 3: Lowest close
Bar 2: Higher close
Bar 1: Even higher close
Current bar closes below previous bar (bearish reversal)
One of the last two candles is the highest high of the past 10 bars (swing high)
📍 Result: A small red cross is plotted above the bar, and the bar is colored red.
🔔 Alerts
One alert condition each for bullish and bearish pullback detection.
Can be used to trigger TradingView alerts.
🛠️ Customization
No inputs — fully automated logic
Clean, minimal, and fast
Can be extended with labels, alert sounds, or signals
Uptrick: Fisher Eclipse1. Name and Purpose
Uptrick: Fisher Eclipse is a Pine version 6 extension of the basic Fisher Transform indicator that focuses on highlighting potential turning points in price data. Its purpose is to allow traders to spot shifts in momentum, detect divergence, and adapt signals to different market environments. By combining a core Fisher Transform with additional signal processing, divergence detection, and customizable aggressiveness settings, this script aims to help users see when a price move might be losing momentum or gaining strength.
2. Overview
This script uses a Fisher Transform calculation on the average of each bar’s high and low (hl2). The Fisher Transform is designed to amplify price extremes by mapping data into a different scale, making potential reversals more visible than they might be with standard oscillators. Uptrick: Fisher Eclipse takes this concept further by integrating a signal line, divergence detection, bar coloring for momentum intensity, and optional thresholds to reduce unwanted noise.
3. Why Use the Fisher Transform
The Fisher Transform is known for converting relatively smoothed price data into a more pronounced scale. This transformation highlights where markets may be overextended. In many cases, standard oscillators move gently, and traders can miss subtle hints that a reversal might be approaching. The Fisher Transform’s mathematical approach tightens the range of values and sharpens the highs and lows. This behavior can allow traders to see clearer peaks and troughs in momentum. Because it is often quite responsive, it can help anticipate areas where price might change direction, especially when compared to simpler moving averages or traditional oscillators. The result is a more evident signal of possible overbought or oversold conditions.
4. How This Extension Improves on the Basic Fisher Transform
Uptrick: Fisher Eclipse adds multiple features to the classic Fisher framework in order to address different trading styles and market behaviors:
a) Divergence Detection
The script can detect bullish or bearish divergences between price and the oscillator over a chosen lookback period, helping traders anticipate shifts in market direction.
b) Bar Coloring
When momentum exceeds a certain threshold (default 3), bars can be colored to highlight surges of buying or selling pressure. This quick visual reference can assist in spotting periods of heightened activity. After a bar color like this, usually, there is a quick correction as seen in the image below.
c) Signal Aggressiveness Levels
Users can choose between conservative, moderate, or aggressive signal thresholds. This allows them to tune how quickly the indicator flags potential entries or exits. Aggressive settings might suit scalpers who need rapid signals, while conservative settings may benefit swing traders preferring fewer, more robust indications.
d) Minimum Movement Filter
A configurable filter can be set to ensure that the Fisher line and its signal have a sufficient gap before triggering a buy or sell signal. This step is useful for traders seeking to minimize signals during choppy or sideways markets. This can be used to eliminate noise as well.
By combining all these elements into one package, the indicator attempts to offer a comprehensive toolkit for those who appreciate the Fisher Transform’s clarity but also desire more versatility.
5. Core Components
a) Fisher Transform
The script calculates a Fisher value using normalized price over a configurable length, highlighting potential peaks and troughs.
b) Signal Line
The Fisher line is smoothed using a short Simple Moving Average. Crossovers and crossunders are one of the key ways this indicator attempts to confirm momentum shifts.
c) Divergence Logic
The script looks back over a set number of bars to compare current highs and lows of both price and the Fisher oscillator. When price and the oscillator move in opposing directions, a divergence may occur, suggesting a possible upcoming reversal or weakening trend.
d) Thresholds for Overbought and Oversold
Horizontal lines are drawn at user-chosen overbought and oversold levels. These lines help traders see when momentum readings reach particular extremes, which can be especially relevant when combined with crossovers in that region.
e) Intensity Filter and Bar Coloring
If the magnitude of the change in the Fisher Transform meets or exceeds a specified threshold, bars are recolored. This provides a visual cue for significant momentum changes.
6. User Inputs
a) length
Defines how many bars the script looks back to compute the highest high and lowest low for the Fisher Transform. A smaller length reacts more quickly but can be noisier, while a larger length smooths out the indicator at the cost of responsiveness.
b) signal aggressiveness
Adjusts the buy and sell thresholds for conservative, moderate, and aggressive trading styles. This can be key in matching the indicator to personal risk preferences or varying market conditions. Conservative will give you less signals and aggressive will give you more signals.
c) minimum movement filter
Specifies how far apart the Fisher line and its signal line must be before generating a valid crossover signal.
d) divergence lookback
Controls how many bars are examined when determining if price and the oscillator are diverging. A larger setting might generate fewer signals, while a smaller one can provide more frequent alerts.
e) intensity threshold
Determines how large a change in the Fisher value must be for the indicator to recolor bars. Strong momentum surges become more noticeable.
f) overbought level and oversold level
Lets users define where they consider market conditions to be stretched on the upside or downside.
7. Calculation Process
a) Price Input
The script uses the midpoint of each bar’s high and low, sometimes referred to as hl2.
hl2 = (high + low) / 2
b) Range Normalization
Determine the maximum (maxHigh) and minimum (minLow) values over a user-defined lookback period (length).
Scale the hl2 value so it roughly fits between -1 and +1:
value = 2 * ((hl2 - minLow) / (maxHigh - minLow) - 0.5)
This step highlights the bar’s current position relative to its recent highs and lows.
c) Fisher Calculation
Convert the normalized value into the Fisher Transform:
fisher = 0.5 * ln( (1 + value) / (1 - value) ) + 0.5 * fisher_previous
fisher_previous is simply the Fisher value from the previous bar. Averaging half of the new transform with half of the old value smooths the result slightly and can prevent erratic jumps.
ln is the natural logarithm function, which compresses or expands values so that market turns often become more obvious.
d) Signal Smoothing
Once the Fisher value is computed, a short Simple Moving Average (SMA) is applied to produce a signal line. In code form, this often looks like:
signal = sma(fisher, 3)
Crossovers of the fisher line versus the signal line can be used to hint at changes in momentum:
• A crossover occurs when fisher moves from below to above the signal.
• A crossunder occurs when fisher moves from above to below the signal.
e) Threshold Checking
Users typically define oversold and overbought levels (often -1 and +1).
Depending on aggressiveness settings (conservative, moderate, aggressive), these thresholds are slightly shifted to filter out or include more signals.
For example, an oversold threshold of -1 might be used in a moderate setting, whereas -1.5 could be used in a conservative setting to require a deeper dip before triggering.
f) Divergence Checks
The script looks back a specified number of bars (divergenceLookback). For both price and the fisher line, it identifies:
• priceHigh = the highest hl2 within the lookback
• priceLow = the lowest hl2 within the lookback
• fisherHigh = the highest fisher value within the lookback
• fisherLow = the lowest fisher value within the lookback
If price forms a lower low while fisher forms a higher low, it can signal a bullish divergence. Conversely, if price forms a higher high while fisher forms a lower high, a bearish divergence might be indicated.
g) Bar Coloring
The script monitors the absolute change in Fisher values from one bar to the next (sometimes called fisherChange):
fisherChange = abs(fisher - fisher )
If fisherChange exceeds a user-defined intensityThreshold, bars are recolored to highlight a surge of momentum. Aqua might indicate a strong bullish surge, while purple might indicate a strong bearish surge.
This color-coding provides a quick visual cue for traders looking to spot large momentum swings without constantly monitoring indicator values.
8. Signal Generation and Filtering
Buy and sell signals occur when the Fisher line crosses the signal line in regions defined as oversold or overbought. The optional minimum movement filter prevents triggering if Fisher and its signal line are too close, reducing the chance of small, inconsequential price fluctuations creating frequent signals. Divergences that appear in oversold or overbought regions can serve as additional evidence that momentum might soon shift.
9. Visualization on the Chart
Uptrick: Fisher Eclipse plots two lines: the Fisher line in one color and the signal line in a contrasting shade. The chart displays horizontal dashed lines where the overbought and oversold levels lie. When the Fisher Transform experiences a sharp jump or drop above the intensity threshold, the corresponding price bars may change color, signaling that momentum has undergone a noticeable shift. If the indicator detects bullish or bearish divergence, dotted lines are drawn on the oscillator portion to connect the relevant points.
10. Market Adaptability
Because of the different aggressiveness levels and the optional minimum movement filter, Uptrick: Fisher Eclipse can be tailored to multiple trading styles. For instance, a short-term scalper might select a smaller length and more aggressive thresholds, while a swing trader might choose a longer length for smoother readings, along with conservative thresholds to ensure fewer but potentially stronger signals. During strongly trending markets, users might rely more on divergences or large intensity changes, whereas in a range-bound market, oversold or overbought conditions may be more frequent.
11. Risk Management Considerations
Indicators alone do not ensure favorable outcomes, and relying solely on any one signal can be risky. Using a stop-loss or other protections is often suggested, especially in fast-moving or unpredictable markets. Divergence can appear before a market reversal actually starts. Similarly, a Fisher Transform can remain in an overbought or oversold region for extended periods, especially if the trend is strong. Cautious interpretation and confirmation with additional methods or chart analysis can help refine entry and exit decisions.
12. Combining with Other Tools
Traders can potentially strengthen signals from Uptrick: Fisher Eclipse by checking them against other methods. If a moving average cross or a price pattern aligns with a Fisher crossover, the combined evidence might provide more certainty. Volume analysis may confirm whether a shift in market direction has participation from a broad set of traders. Support and resistance zones could reinforce overbought or oversold signals, particularly if price reaches a historical boundary at the same time the oscillator indicates a possible reversal.
13. Parameter Customization and Examples
Some short-term traders run a 15-minute chart, with a shorter length setting, aggressively tight oversold and overbought thresholds, and a smaller divergence lookback. This approach produces more frequent signals, which may appeal to those who enjoy fast-paced trading. More conservative traders might apply the indicator to a daily chart, using a larger length, moderate threshold levels, and a bigger divergence lookback to focus on broader market swings. Results can differ, so it may be helpful to conduct thorough historical testing to see which combination of parameters aligns best with specific goals.
14. Realistic Expectations
While the Fisher Transform can reveal potential turning points, no mathematical tool can predict future price behavior with full certainty. Markets can behave erratically, and a period of strong trending may see the oscillator pinned in an extreme zone without a significant reversal. Divergence signals sometimes appear well before an actual trend change occurs. Recognizing these limitations helps traders manage risk and avoids overreliance on any one aspect of the script’s output.
15. Theoretical Background
The Fisher Transform uses a logarithmic formula to map a normalized input, typically ranging between -1 and +1, into a scale that can fluctuate around values like -3 to +3. Because the transformation exaggerates higher and lower readings, it becomes easier to spot when the market might have stretched too far, too fast. Uptrick: Fisher Eclipse builds on that foundation by adding a series of practical tools that help confirm or refine those signals.
16. Originality and Uniqueness
Uptrick: Fisher Eclipse is not simply a duplicate of the basic Fisher Transform. It enhances the original design in several ways, including built-in divergence detection, bar-color triggers for momentum surges, thresholds for overbought and oversold levels, and customizable signal aggressiveness. By unifying these concepts, the script seeks to reduce noise and highlight meaningful shifts in market direction. It also places greater emphasis on helping traders adapt the indicator to their specific style—whether that involves frequent intraday signals or fewer, more robust alerts over longer timeframes.
17. Summary
Uptrick: Fisher Eclipse is an expanded take on the original Fisher Transform oscillator, including divergence detection, bar coloring based on momentum strength, and flexible signal thresholds. By adjusting parameters like length, aggressiveness, and intensity thresholds, traders can configure the script for day-trading, swing trading, or position trading. The indicator endeavors to highlight where price might be shifting direction, but it should still be combined with robust risk management and other analytical methods. Doing so can lead to a more comprehensive view of market conditions.
18. Disclaimer
No indicator or script can guarantee profitable outcomes in trading. Past performance does not necessarily suggest future results. Uptrick: Fisher Eclipse is provided for educational and informational purposes. Users should apply their own judgment and may want to confirm signals with other tools and methods. Deciding to open or close a position remains a personal choice based on each individual’s circumstances and risk tolerance.
PIP Algorithm
# **Script Overview (For Non-Coders)**
1. **Purpose**
- The script tries to capture the essential “shape” of price movement by selecting a limited number of “key points” (anchors) from the latest bars.
- After selecting these anchors, it draws straight lines between them, effectively simplifying the price chart into a smaller set of points without losing major swings.
2. **How It Works, Step by Step**
1. We look back a certain number of bars (e.g., 50).
2. We start by drawing a straight line from the **oldest** bar in that range to the **newest** bar—just two points.
3. Next, we find the bar whose price is *farthest away* from that straight line. That becomes a new anchor point.
4. We “snap” (pin) the line to go exactly through that new anchor. Then we re-draw (re-interpolate) the entire line from the first anchor to the last, in segments.
5. We repeat the process (adding more anchors) until we reach the desired number of points. Each time, we choose the biggest gap between our line and the actual price, then re-draw the entire shape.
6. Finally, we connect these anchors on the chart with red lines, visually simplifying the price curve.
3. **Why It’s Useful**
- It highlights the most *important* bends or swings in the price over the chosen window.
- Instead of plotting every single bar, it condenses the information down to the “key turning points.”
4. **Key Takeaway**
- You’ll see a small number of red line segments connecting the **most significant** points in the price data.
- This is especially helpful if you want a simplified view of recent price action without minor fluctuations.
## **Detailed Logic Explanation**
# **Script Breakdown (For Coders)**
//@version=5
indicator(title="PIP Algorithm", overlay=true)
// 1. Inputs
length = input.int(50, title="Lookback Length")
num_points = input.int(5, title="Number of PIP Points (≥ 3)")
// 2. Helper Functions
// ---------------------------------------------------------------------
// reInterpSubrange(...):
// Given two “anchor” indices in `linesArr`, linearly interpolate
// the array values in between so that the subrange forms a straight line
// from linesArr to linesArr .
reInterpSubrange(linesArr, segmentLeft, segmentRight) =>
float leftVal = array.get(linesArr, segmentLeft)
float rightVal = array.get(linesArr, segmentRight)
int segmentLen = segmentRight - segmentLeft
if segmentLen > 1
for i = segmentLeft + 1 to segmentRight - 1
float ratio = (i - segmentLeft) / segmentLen
float interpVal = leftVal + (rightVal - leftVal) * ratio
array.set(linesArr, i, interpVal)
// reInterpolateAllSegments(...):
// For the entire “linesArr,” re-interpolate each subrange between
// consecutive breakpoints in `lineBreaksArr`.
// This ensures the line is globally correct after each new anchor insertion.
reInterpolateAllSegments(linesArr, lineBreaksArr) =>
array.sort(lineBreaksArr, order.asc)
for i = 0 to array.size(lineBreaksArr) - 2
int leftEdge = array.get(lineBreaksArr, i)
int rightEdge = array.get(lineBreaksArr, i + 1)
reInterpSubrange(linesArr, leftEdge, rightEdge)
// getMaxDistanceIndex(...):
// Return the index (bar) that is farthest from the current “linesArr.”
// We skip any indices already in `lineBreaksArr`.
getMaxDistanceIndex(linesArr, closeArr, lineBreaksArr) =>
float maxDist = -1.0
int maxIdx = -1
int sizeData = array.size(linesArr)
for i = 1 to sizeData - 2
bool isBreak = false
for b = 0 to array.size(lineBreaksArr) - 1
if i == array.get(lineBreaksArr, b)
isBreak := true
break
if not isBreak
float dist = math.abs(array.get(linesArr, i) - array.get(closeArr, i))
if dist > maxDist
maxDist := dist
maxIdx := i
maxIdx
// snapAndReinterpolate(...):
// "Snap" a chosen index to its actual close price, then re-interpolate the entire line again.
snapAndReinterpolate(linesArr, closeArr, lineBreaksArr, idxToSnap) =>
if idxToSnap >= 0
float snapVal = array.get(closeArr, idxToSnap)
array.set(linesArr, idxToSnap, snapVal)
reInterpolateAllSegments(linesArr, lineBreaksArr)
// 3. Global Arrays and Flags
// ---------------------------------------------------------------------
// We store final data globally, then use them outside the barstate.islast scope to draw lines.
var float finalCloseData = array.new_float()
var float finalLines = array.new_float()
var int finalLineBreaks = array.new_int()
var bool didCompute = false
var line pipLines = array.new_line()
// 4. Main Logic (Runs Once at the End of the Current Bar)
// ---------------------------------------------------------------------
if barstate.islast
// A) Prepare closeData in forward order (index 0 = oldest bar, index length-1 = newest)
float closeData = array.new_float()
for i = 0 to length - 1
array.push(closeData, close )
// B) Initialize linesArr with a simple linear interpolation from the first to the last point
float linesArr = array.new_float()
float firstClose = array.get(closeData, 0)
float lastClose = array.get(closeData, length - 1)
for i = 0 to length - 1
float ratio = (length > 1) ? (i / float(length - 1)) : 0.0
float val = firstClose + (lastClose - firstClose) * ratio
array.push(linesArr, val)
// C) Initialize lineBreaks with two anchors: 0 (oldest) and length-1 (newest)
int lineBreaks = array.new_int()
array.push(lineBreaks, 0)
array.push(lineBreaks, length - 1)
// D) Iteratively insert new breakpoints, always re-interpolating globally
int iterationsNeeded = math.max(num_points - 2, 0)
for _iteration = 1 to iterationsNeeded
// 1) Re-interpolate entire shape, so it's globally up to date
reInterpolateAllSegments(linesArr, lineBreaks)
// 2) Find the bar with the largest vertical distance to this line
int maxDistIdx = getMaxDistanceIndex(linesArr, closeData, lineBreaks)
if maxDistIdx == -1
break
// 3) Insert that bar index into lineBreaks and snap it
array.push(lineBreaks, maxDistIdx)
array.sort(lineBreaks, order.asc)
snapAndReinterpolate(linesArr, closeData, lineBreaks, maxDistIdx)
// E) Save results into global arrays for line drawing outside barstate.islast
array.clear(finalCloseData)
array.clear(finalLines)
array.clear(finalLineBreaks)
for i = 0 to array.size(closeData) - 1
array.push(finalCloseData, array.get(closeData, i))
array.push(finalLines, array.get(linesArr, i))
for b = 0 to array.size(lineBreaks) - 1
array.push(finalLineBreaks, array.get(lineBreaks, b))
didCompute := true
// 5. Drawing the Lines in Global Scope
// ---------------------------------------------------------------------
// We cannot create lines inside barstate.islast, so we do it outside.
array.clear(pipLines)
if didCompute
// Connect each pair of anchors with red lines
if array.size(finalLineBreaks) > 1
for i = 0 to array.size(finalLineBreaks) - 2
int idxLeft = array.get(finalLineBreaks, i)
int idxRight = array.get(finalLineBreaks, i + 1)
float x1 = bar_index - (length - 1) + idxLeft
float x2 = bar_index - (length - 1) + idxRight
float y1 = array.get(finalCloseData, idxLeft)
float y2 = array.get(finalCloseData, idxRight)
line ln = line.new(x1, y1, x2, y2, extend=extend.none)
line.set_color(ln, color.red)
line.set_width(ln, 2)
array.push(pipLines, ln)
1. **Data Collection**
- We collect the **most recent** `length` bars in `closeData`. Index 0 is the oldest bar in that window, index `length-1` is the newest bar.
2. **Initial Straight Line**
- We create an array called `linesArr` that starts as a simple linear interpolation from `closeData ` (the oldest bar’s close) to `closeData ` (the newest bar’s close).
3. **Line Breaks**
- We store “anchor points” in `lineBreaks`, initially ` `. These are the start and end of our segment.
4. **Global Re-Interpolation**
- Each time we want to add a new anchor, we **re-draw** (linear interpolation) for *every* subrange ` [lineBreaks , lineBreaks ]`, ensuring we have a globally consistent line.
- This avoids the “local subrange only” approach, which can cause clustering near existing anchors.
5. **Finding the Largest Distance**
- After re-drawing, we compute the vertical distance for each bar `i` that isn’t already a line break. The bar with the biggest distance from the line is chosen as the next anchor (`maxDistIdx`).
6. **Snapping and Re-Interpolate**
- We “snap” that bar’s line value to the actual close, i.e. `linesArr = closeData `. Then we globally re-draw all segments again.
7. **Repeat**
- We repeat these insertions until we have the desired number of points (`num_points`).
8. **Drawing**
- Finally, we connect each consecutive pair of anchor points (`lineBreaks`) with a `line.new(...)` call, coloring them red.
- We offset the line’s `x` coordinate so that the anchor at index 0 lines up with `bar_index - (length - 1)`, and the anchor at index `length-1` lines up with `bar_index` (the current bar).
**Result**:
You get a simplified representation of the price with a small set of line segments capturing the largest “jumps” or swings. By re-drawing the entire line after each insertion, the anchors tend to distribute more *evenly* across the data, mitigating the issue where anchors bunch up near each other.
Enjoy experimenting with different `length` and `num_points` to see how the simplified lines change!
William Fractals + SignalsWilliams Fractals + Trading Signals
This indicator identifies Williams Fractals and generates trading signals based on price sweeps of these fractal levels.
Williams Fractals are specific candlestick patterns that identify potential market turning points. Each fractal requires a minimum of 5 bars (2 before, 1 center, 2 after), though this indicator allows you to customize the number of bars checked.
Up Fractal (High Point) forms when you have a center bar whose HIGH is higher than the highs of 'n' bars before and after it. For example, with n=2, you'd see a pattern where the center bar's high is higher than 2 bars before and 2 bars after it. The indicator also recognizes patterns where up to 4 bars after the center can have equal highs before requiring a lower high.
Down Fractal (Low Point) forms when you have a center bar whose LOW is lower than the lows of 'n' bars before and after it. For example, with n=2, you'd see a pattern where the center bar's low is lower than 2 bars before and 2 bars after it. The indicator also recognizes patterns where up to 4 bars after the center can have equal lows before requiring a higher low.
Trading Signals:
The indicator generates signals when price "sweeps" these fractal levels:
Buy Signal (Green Triangle) triggers when price sweeps a down fractal. This requires price to go BELOW the down fractal's low level and then CLOSE ABOVE it . This pattern often indicates a failed breakdown and potential reversal upward.
Sell Signal (Red Triangle) triggers when price sweeps an up fractal. This requires price to go ABOVE the up fractal's high level and then CLOSE BELOW it. This pattern often indicates a failed breakout and potential reversal downward.
Customizable Settings:
1. Periods (default: 10) - How many bars to check before and after the center bar (minimum value: 2)
2. Maximum Stored Fractals (default: 1) - How many fractal levels to keep in memory. Older levels are removed when this limit is reached to prevent excessive signals and maintain indicator performance.
Important Notes:
• The indicator checks the actual HIGH and LOW prices of each bar, not just closing prices
• Fractal levels are automatically removed after generating a signal to prevent repeated triggers
• Signals are only generated on bar close to avoid false triggers
• Alerts include the ticker symbol and the exact price level where the sweep occurred
Common Use Cases:
• Identifying potential reversal points
• Finding stop-hunt levels where price might reverse
• Setting stop-loss levels above up fractals or below down fractals
• Trading failed breakouts/breakdowns at fractal levels
[Defaust] Fractals Fractals Indicator
Overview
The Fractals Indicator is a technical analysis tool designed to help traders identify potential reversal points in the market by detecting fractal patterns. This indicator is a fork of the original fractals indicator, with adjustments made to the plotting for enhanced visual clarity and usability.
What Are Fractals?
In trading, a fractal is a pattern consisting of five consecutive bars (candlesticks) that meet specific conditions:
Up Fractal (Potential Sell Signal): Occurs when a high point is surrounded by two lower highs on each side.
Down Fractal (Potential Buy Signal): Occurs when a low point is surrounded by two higher lows on each side.
Fractals help traders identify potential tops and bottoms in the market, signaling possible entry or exit points.
Features of the Indicator
Customizable Periods (n): Allows you to define the number of periods to consider when detecting fractals, offering flexibility to adapt to different trading strategies and timeframes.
Enhanced Plotting Adjustments: This fork introduces adjustments to the plotting of fractal signals for better visual representation on the chart.
Visual Signals: Plots up and down triangles on the chart to signify down fractals (potential bullish signals) and up fractals (potential bearish signals), respectively.
Overlay on Chart: The fractal signals are overlaid directly on the price chart for immediate visualization.
Adjustable Precision: You can set the precision of the plotted values according to your needs.
Pine Script Code Explanation
Below is the Pine Script code for the Fractals Indicator:
//@version=5 indicator(" Fractals", shorttitle=" Fractals", format=format.price, precision=0, overlay=true)
// User input for the number of periods to consider for fractal detection n = input.int(title="Periods", defval=2, minval=2)
// Initialize flags for up fractal detection bool upflagDownFrontier = true bool upflagUpFrontier0 = true bool upflagUpFrontier1 = true bool upflagUpFrontier2 = true bool upflagUpFrontier3 = true bool upflagUpFrontier4 = true
// Loop through previous and future bars to check conditions for up fractals for i = 1 to n // Check if the highs of previous bars are less than the current bar's high upflagDownFrontier := upflagDownFrontier and (high < high ) // Check various conditions for future bars upflagUpFrontier0 := upflagUpFrontier0 and (high < high ) upflagUpFrontier1 := upflagUpFrontier1 and (high <= high and high < high ) upflagUpFrontier2 := upflagUpFrontier2 and (high <= high and high <= high and high < high ) upflagUpFrontier3 := upflagUpFrontier3 and (high <= high and high <= high and high <= high and high < high ) upflagUpFrontier4 := upflagUpFrontier4 and (high <= high and high <= high and high <= high and high <= high and high < high )
// Combine the flags to determine if an up fractal exists flagUpFrontier = upflagUpFrontier0 or upflagUpFrontier1 or upflagUpFrontier2 or upflagUpFrontier3 or upflagUpFrontier4 upFractal = (upflagDownFrontier and flagUpFrontier)
// Initialize flags for down fractal detection bool downflagDownFrontier = true bool downflagUpFrontier0 = true bool downflagUpFrontier1 = true bool downflagUpFrontier2 = true bool downflagUpFrontier3 = true bool downflagUpFrontier4 = true
// Loop through previous and future bars to check conditions for down fractals for i = 1 to n // Check if the lows of previous bars are greater than the current bar's low downflagDownFrontier := downflagDownFrontier and (low > low ) // Check various conditions for future bars downflagUpFrontier0 := downflagUpFrontier0 and (low > low ) downflagUpFrontier1 := downflagUpFrontier1 and (low >= low and low > low ) downflagUpFrontier2 := downflagUpFrontier2 and (low >= low and low >= low and low > low ) downflagUpFrontier3 := downflagUpFrontier3 and (low >= low and low >= low and low >= low and low > low ) downflagUpFrontier4 := downflagUpFrontier4 and (low >= low and low >= low and low >= low and low >= low and low > low )
// Combine the flags to determine if a down fractal exists flagDownFrontier = downflagUpFrontier0 or downflagUpFrontier1 or downflagUpFrontier2 or downflagUpFrontier3 or downflagUpFrontier4 downFractal = (downflagDownFrontier and flagDownFrontier)
// Plot the fractal symbols on the chart with adjusted plotting plotshape(downFractal, style=shape.triangleup, location=location.belowbar, offset=-n, color=color.gray, size=size.auto) plotshape(upFractal, style=shape.triangledown, location=location.abovebar, offset=-n, color=color.gray, size=size.auto)
Explanation:
Input Parameter (n): Sets the number of periods for fractal detection. The default value is 2, and it must be at least 2 to ensure valid fractal patterns.
Flag Initialization: Boolean variables are used to store intermediate conditions during fractal detection.
Loops: Iterate through the specified number of periods to evaluate the conditions for fractal formation.
Conditions:
Up Fractals: Checks if the current high is greater than previous highs and if future highs are lower or equal to the current high.
Down Fractals: Checks if the current low is lower than previous lows and if future lows are higher or equal to the current low.
Flag Combination: Logical and and or operations are used to combine the flags and determine if a fractal exists.
Adjusted Plotting:
The plotting of fractal symbols has been adjusted for better alignment and visual clarity.
The offset parameter is set to -n to align the plotted symbols with the correct bars.
The color and size have been fine-tuned for better visibility.
How to Use the Indicator
Adding the Indicator to Your Chart
Open TradingView:
Go to TradingView.
Access the Chart:
Click on "Chart" to open the main charting interface.
Add the Indicator:
Click on the "Indicators" button at the top.
Search for " Fractals".
Select the indicator from the list to add it to your chart.
Configuring the Indicator
Periods (n):
Default value is 2.
Adjust this parameter based on your preferred timeframe and sensitivity.
A higher value of n considers more bars for fractal detection, potentially reducing the number of signals but increasing their significance.
Interpreting the Signals
– Up Fractal (Downward Triangle): Indicates a potential price reversal to the downside. May be used as a signal to consider exiting long positions or tightening stop-loss orders.
– Down Fractal (Upward Triangle): Indicates a potential price reversal to the upside. May be used as a signal to consider entering long positions or setting stop-loss orders for short positions.
Trading Strategy Suggestions
Up Fractal Detection:
The high of the current bar (n) is higher than the highs of the previous two bars (n - 1, n - 2).
The highs of the next bars meet certain conditions to confirm the fractal pattern.
An up fractal symbol (downward triangle) is plotted above the bar at position n - n (due to the offset).
Down Fractal Detection:
The low of the current bar (n) is lower than the lows of the previous two bars (n - 1, n - 2).
The lows of the next bars meet certain conditions to confirm the fractal pattern.
A down fractal symbol (upward triangle) is plotted below the bar at position n - n.
Benefits of Using the Fractals Indicator
Early Signals: Helps in identifying potential reversal points in price movements.
Customizable Sensitivity: Adjusting the n parameter allows you to fine-tune the indicator based on different market conditions.
Enhanced Visuals: Adjustments to plotting improve the clarity and readability of fractal signals on the chart.
Limitations and Considerations
Lagging Indicator: Fractals require future bars to confirm the pattern, which may introduce a delay in the signals.
False Signals: In volatile or ranging markets, fractals may produce false signals. It's advisable to use them in conjunction with other analysis tools.
Not a Standalone Tool: Fractals should be part of a broader trading strategy that includes other indicators and fundamental analysis.
Best Practices for Using This Indicator
Combine with Other Indicators: Use in combination with trend indicators, oscillators, or volume analysis to confirm signals.
Backtesting: Before applying the indicator in live trading, backtest it on historical data to understand its performance.
Adjust Periods Accordingly: Experiment with different values of n to find the optimal setting for the specific asset and timeframe you are trading.
Disclaimer
The Fractals Indicator is intended for educational and informational purposes only. Trading involves significant risk, and you should be aware of the risks involved before proceeding. Past performance is not indicative of future results. Always conduct your own analysis and consult with a professional financial advisor before making any investment decisions.
Credits
This indicator is a fork of the original fractals indicator, with adjustments made to the plotting for improved visual representation. It is based on standard fractal patterns commonly used in technical analysis and has been developed to provide traders with an effective tool for detecting potential reversal points in the market.
GL Gann Swing IndicatorIntroduction
The GL Gann Swing Indicator is a versatile tool designed to help traders identify market trends, support and resistance areas, and potential reversals. This indicator applies the principles of Gann Swing Charts, a technique developed by W.D. Gann, which focuses on market swings to determine the overall direction and turning points of price action. Gann Swing Charts are a time-tested method of technical analysis that simplifies price action by focusing on significant highs and lows, thereby eliminating market noise and providing a clearer view of the trend.
By analyzing price action and determining swing directions and turning points, the indicator filters out market noise using four distinct bar types:
Up Bar: Higher High, Higher Low
Down Bar: Lower High, Lower Low
Inside Bar: Lower High, Higher Low
Outside Bar: Higher High, Lower Low
This approach helps traders to:
Identify the primary trend direction.
Determine key support and resistance levels.
Recognize potential reversal points.
Filter out minor price fluctuations that do not affect the overall trend.
Features
Bar Types: Display bar types by checking the Show Bar Type box in the indicator's settings. Up bars appear as green upward-pointing triangles, down bars as red downward-pointing triangles, inside bars as grey circles, and outside bars as blue diamonds. These visual aids help traders quickly identify the type of bar and its significance.
Break Lines: These lines highlight when the price rises above a previous swing high or falls below a prior swing low. Green lines indicate breaks of swing highs, while red lines indicate breaks of swing lows. Break lines are enabled by default but can be turned off in the indicator's settings. Break lines provide visual confirmation of trend continuation or reversal.
Bar Count: Bar counts help determine if a swing is overextended and if a reversal is likely. This feature is off by default but can be enabled in the indicator's settings. Users can set a minimum bar count to focus on significant swings. Analyzing the number of bars in a swing can help traders gauge the strength and potential exhaustion of a trend.
Swing MA (Moving Averages): This feature plots the average of a user-defined number of previous swing highs and lows. Options are available to add two moving averages, allowing for both fast and slow averages. Swing MAs can be enabled in the indicator's settings. These moving averages smooth out the price data, making it easier to identify the underlying trend direction.
Why This Indicator is Useful
The GL Gann Swing Indicator is particularly useful for several reasons:
Trend Identification: By focusing on significant price swings, the indicator helps traders identify the primary trend direction, making it easier to align trades with the overall market movement.
Noise Reduction: The indicator filters out minor price fluctuations, allowing traders to focus on meaningful market movements and avoid being misled by short-term volatility.
Support and Resistance Levels: By highlighting key swing highs and lows, the indicator helps traders identify crucial support and resistance levels, which are essential for making informed trading decisions.
Potential Reversals: The indicator's ability to identify overextended swings and potential reversal points can help traders anticipate market turning points and adjust their strategies accordingly.
Customizability: With options to display bar types, break lines, bar counts, and swing moving averages, traders can customize the indicator to suit their specific trading style and preferences.
By incorporating Gann Swing principles, the GL Gann Swing Indicator offers traders a powerful tool to enhance their technical analysis, improve their trading decisions, and ultimately achieve better trading outcomes.
D9 IndicatorD9 Indicator
Category
Technical Indicators
Overview
The D9 Indicator is designed to identify potential trend reversals by counting the number of consecutive closes that are higher or lower than the close four bars earlier. This indicator highlights key moments in the price action where a trend might be exhausting and potentially reversing, providing valuable insights for traders.
Features
Up Signal: Plots a downward triangle or a cross above the bar when the count of consecutive closes higher than the close four bars earlier reaches 7, 8, or 9.
Down Signal: Plots an upward triangle or a checkmark below the bar when the count of consecutive closes lower than the close four bars earlier reaches 7, 8, or 9.
Visual Signals
Red Downward Triangle (7): Indicates the seventh consecutive bar with a higher close.
Red Downward Triangle (8): Indicates the eighth consecutive bar with a higher close.
Red Cross (❌): Indicates the ninth consecutive bar with a higher close, suggesting a potential bearish reversal.
Green Upward Triangle (7): Indicates the seventh consecutive bar with a lower close.
Green Upward Triangle (8): Indicates the eighth consecutive bar with a lower close.
Green Checkmark (✅): Indicates the ninth consecutive bar with a lower close, suggesting a potential bullish reversal.
Usage
The D9 Indicator is useful for traders looking for visual cues to identify potential trend exhaustion and reversals. It can be applied to any market and timeframe, providing flexibility in various trading strategies.
How to Read
When a red cross (❌) appears above a bar, it may signal an overextended uptrend and a potential bearish reversal.
When a green checkmark (✅) appears below a bar, it may signal an overextended downtrend and a potential bullish reversal.
Example
When the price has consecutively closed higher than four bars ago for nine bars, a red cross (❌) will appear above the ninth bar. This suggests that the uptrend might be exhausting, and traders could look for potential short opportunities. Conversely, when the price has consecutively closed lower than four bars ago for nine bars, a green checkmark (✅) will appear below the ninth bar, indicating a potential buying opportunity.
chrono_utilsLibrary "chrono_utils"
Collection of objects and common functions that are related to datetime windows session days and time
ranges. The main purpose of this library is to handle time-related functionality and make it easy to reason about a
future bar checking if it will be part of a predefined session and/or inside a datetime window. All existing session
functionality I found in the documentation e.g. "not na(time(timeframe, session, timezone))" are not suitable for
strategy scripts, since the execution of the orders is delayed by one bar, due to the script execution happening at
the bar close. Moreover, a history operator with a negative value that looks forward is not allowed in any pinescript
expression. So, a prediction for the next bar using the bars_back argument of "time()"" and "time_close()" was
necessary. Thus, I created this library to overcome this small but very important limitation. In the meantime, I
added useful functionality to handle session-based behavior. An interesting utility that emerged from this
development is the data anomaly detection where a comparison between the prediction and the actual value is happening.
If those two values are different then a data inconsistency happened between the prediction bar and the actual bar
(probably due to a holiday, half session day, a timezone change etc..)
exTimezone(timezone)
exTimezone - Convert extended timezone to timezone string
Parameters:
timezone (simple string) : - The timezone or a special string
Returns: string representing the timezone
nameOfDay(day)
nameOfDay - Convert the day id into a short nameOfDay
Parameters:
day (int) : - The day id to convert
Returns: - The short name of the day
today()
today - Get the day id of this day
Returns: - The day id
nthDayAfter(day, n)
nthDayAfter - Get the day id of n days after the given day
Parameters:
day (int) : - The day id of the reference day
n (int) : - The number of days to go forward
Returns: - The day id of the day that is n days after the reference day
nextDayAfter(day)
nextDayAfter - Get the day id of next day after the given day
Parameters:
day (int) : - The day id of the reference day
Returns: - The day id of the next day after the reference day
nthDayBefore(day, n)
nthDayBefore - Get the day id of n days before the given day
Parameters:
day (int) : - The day id of the reference day
n (int) : - The number of days to go forward
Returns: - The day id of the day that is n days before the reference day
prevDayBefore(day)
prevDayBefore - Get the day id of previous day before the given day
Parameters:
day (int) : - The day id of the reference day
Returns: - The day id of the previous day before the reference day
tomorrow()
tomorrow - Get the day id of the next day
Returns: - The next day day id
normalize(num, min, max)
normalizeHour - Check if number is inthe range of
Parameters:
num (int)
min (int)
max (int)
Returns: - The normalized number
normalizeHour(hourInDay)
normalizeHour - Check if hour is valid and return a noralized hour range from
Parameters:
hourInDay (int)
Returns: - The normalized hour
normalizeMinute(minuteInHour)
normalizeMinute - Check if minute is valid and return a noralized minute from
Parameters:
minuteInHour (int)
Returns: - The normalized minute
monthInMilliseconds(mon)
monthInMilliseconds - Calculate the miliseconds in one bar of the timeframe
Parameters:
mon (int) : - The month of reference to get the miliseconds
Returns: - The number of milliseconds of the month
barInMilliseconds()
barInMilliseconds - Calculate the miliseconds in one bar of the timeframe
Returns: - The number of milliseconds in one bar
method to_string(this)
to_string - Formats the time window into a human-readable string
Namespace types: DateTimeWindow
Parameters:
this (DateTimeWindow) : - The time window object with the from and to datetimes
Returns: - The string of the time window
method to_string(this)
to_string - Formats the session days into a human-readable string with short day names
Namespace types: SessionDays
Parameters:
this (SessionDays) : - The session days object with the day selection
Returns: - The string of the session day short names
method to_string(this)
to_string - Formats the session time into a human-readable string
Namespace types: SessionTime
Parameters:
this (SessionTime) : - The session time object with the hour and minute of the time of the day
Returns: - The string of the session time
method to_string(this)
to_string - Formats the session time into a human-readable string
Namespace types: SessionTimeRange
Parameters:
this (SessionTimeRange) : - The session time range object with the start and end time of the daily session
Returns: - The string of the session time
method to_string(this)
to_string - Formats the session into a human-readable string
Namespace types: Session
Parameters:
this (Session) : - The session object with the day and the time range selection
Returns: - The string of the session
method init(this, fromDateTime, toDateTime)
init - Initialize the time window object from boolean values of each session day
Namespace types: DateTimeWindow
Parameters:
this (DateTimeWindow) : - The time window object that will hold the from and to datetimes
fromDateTime (int) : - The starting datetime of the time window
toDateTime (int) : - The ending datetime of the time window
Returns: - The time window object
method init(this, refTimezone, chTimezone, fromDateTime, toDateTime)
init - Initialize the time window object from boolean values of each session day
Namespace types: DateTimeWindow
Parameters:
this (DateTimeWindow) : - The time window object that will hold the from and to datetimes
refTimezone (simple string) : - The timezone of reference of the 'from' and 'to' dates
chTimezone (simple string) : - The target timezone to convert the 'from' and 'to' dates
fromDateTime (int) : - The starting datetime of the time window
toDateTime (int) : - The ending datetime of the time window
Returns: - The time window object
method init(this, sun, mon, tue, wed, thu, fri, sat)
init - Initialize the session days object from boolean values of each session day
Namespace types: SessionDays
Parameters:
this (SessionDays) : - The session days object that will hold the day selection
sun (bool) : - Is Sunday a trading day?
mon (bool) : - Is Monday a trading day?
tue (bool) : - Is Tuesday a trading day?
wed (bool) : - Is Wednesday a trading day?
thu (bool) : - Is Thursday a trading day?
fri (bool) : - Is Friday a trading day?
sat (bool) : - Is Saturday a trading day?
Returns: - The session days object
method init(this, unixTime)
init - Initialize the object from the hour and minute of the session time in exchange timezone (syminfo.timezone)
Namespace types: SessionTime
Parameters:
this (SessionTime) : - The session time object with the hour and minute of the time of the day
unixTime (int) : - The unix time
Returns: - The session time object
method init(this, hourInDay, minuteInHour)
init - Initialize the object from the hour and minute of the session time in exchange timezone (syminfo.timezone)
Namespace types: SessionTime
Parameters:
this (SessionTime) : - The session time object with the hour and minute of the time of the day
hourInDay (int) : - The hour of the time
minuteInHour (int) : - The minute of the time
Returns: - The session time object
method init(this, hourInDay, minuteInHour, refTimezone)
init - Initialize the object from the hour and minute of the session time
Namespace types: SessionTime
Parameters:
this (SessionTime) : - The session time object with the hour and minute of the time of the day
hourInDay (int) : - The hour of the time
minuteInHour (int) : - The minute of the time
refTimezone (string) : - The timezone of reference of the 'hour' and 'minute'
Returns: - The session time object
method init(this, startTime, endTime)
init - Initialize the object from the start and end session time in exchange timezone (syminfo.timezone)
Namespace types: SessionTimeRange
Parameters:
this (SessionTimeRange) : - The session time range object that will hold the start and end time of the daily session
startTime (SessionTime) : - The time the session begins
endTime (SessionTime) : - The time the session ends
Returns: - The session time range object
method init(this, startTimeHour, startTimeMinute, endTimeHour, endTimeMinute, refTimezone)
init - Initialize the object from the start and end session time
Namespace types: SessionTimeRange
Parameters:
this (SessionTimeRange) : - The session time range object that will hold the start and end time of the daily session
startTimeHour (int) : - The time hour the session begins
startTimeMinute (int) : - The time minute the session begins
endTimeHour (int) : - The time hour the session ends
endTimeMinute (int) : - The time minute the session ends
refTimezone (string)
Returns: - The session time range object
method init(this, days, timeRanges)
init - Initialize the session object from session days and time range
Namespace types: Session
Parameters:
this (Session) : - The session object that will hold the day and the time range selection
days (SessionDays) : - The session days object that defines the days the session is happening
timeRanges (array) : - The array of all the session time ranges during a session day
Returns: - The session object
method init(this, days, timeRanges, names, colors)
init - Initialize the session object from session days and time range
Namespace types: SessionView
Parameters:
this (SessionView) : - The session view object that will hold the session, the names and the color selections
days (SessionDays) : - The session days object that defines the days the session is happening
timeRanges (array) : - The array of all the session time ranges during a session day
names (array) : - The array of the names of the sessions
colors (array) : - The array of the colors of the sessions
Returns: - The session object
method get_size_in_secs(this)
get_size_in_secs - Count the seconds from start to end in the given timeframe
Namespace types: DateTimeWindow
Parameters:
this (DateTimeWindow) : - The time window object with the from and to datetimes
Returns: - The number of seconds inside the time widow for the given timeframe
method get_size_in_secs(this)
get_size_in_secs - Calculate the seconds inside the session
Namespace types: SessionTimeRange
Parameters:
this (SessionTimeRange) : - The session time range object with the start and end time of the daily session
Returns: - The number of seconds inside the session
method get_size_in_bars(this)
get_size_in_bars - Count the bars from start to end in the given timeframe
Namespace types: DateTimeWindow
Parameters:
this (DateTimeWindow) : - The time window object with the from and to datetimes
Returns: - The number of bars inside the time widow for the given timeframe
method get_size_in_bars(this)
get_size_in_bars - Calculate the bars inside the session
Namespace types: SessionTimeRange
Parameters:
this (SessionTimeRange) : - The session time range object with the start and end time of the daily session
Returns: - The number of bars inside the session for the given timeframe
method is_bar_included(this, offset_forward)
is_bar_included - Check if the given bar is between the start and end dates of the window
Namespace types: DateTimeWindow
Parameters:
this (DateTimeWindow) : - The time window object with the from and to datetimes
offset_forward (simple int) : - The number of bars forward. Default is 1
Returns: - Whether the current bar is inside the datetime window
method is_bar_included(this, offset_forward)
is_bar_included - Check if the given bar is inside the session as defined by the input params (what "not na(time(timeframe.period, this.to_sess_string()) )" should return if you could write it
Namespace types: Session
Parameters:
this (Session) : - The session with the day and the time range selection
offset_forward (simple int) : - The bar forward to check if it is between the from and to datetimes. Default is 1
Returns: - Whether the current time is inside the session
method to_sess_string(this)
to_sess_string - Formats the session days into a session string with day ids
Namespace types: SessionDays
Parameters:
this (SessionDays) : - The session days object
Returns: - The string of the session day ids
method to_sess_string(this)
to_sess_string - Formats the session time into a session string
Namespace types: SessionTime
Parameters:
this (SessionTime) : - The session time object with the hour and minute of the time of the day
Returns: - The string of the session time
method to_sess_string(this)
to_sess_string - Formats the session time into a session string
Namespace types: SessionTimeRange
Parameters:
this (SessionTimeRange) : - The session time range object with the start and end time of the daily session
Returns: - The string of the session time
method to_sess_string(this)
to_sess_string - Formats the session into a session string
Namespace types: Session
Parameters:
this (Session) : - The session object with the day and the time range selection
Returns: - The string of the session
method from_sess_string(this, sess)
from_sess_string - Initialize the session days object from the session string
Namespace types: SessionDays
Parameters:
this (SessionDays) : - The session days object that will hold the day selection
sess (string) : - The session string part that represents the days
Returns: - The session days object
method from_sess_string(this, sess)
from_sess_string - Initialize the session time object from the session string in exchange timezone (syminfo.timezone)
Namespace types: SessionTime
Parameters:
this (SessionTime) : - The session time object that will hold the hour and minute of the time
sess (string) : - The session string part that represents the time HHmm
Returns: - The session time object
method from_sess_string(this, sess, refTimezone)
from_sess_string - Initialize the session time object from the session string
Namespace types: SessionTime
Parameters:
this (SessionTime) : - The session time object that will hold the hour and minute of the time
sess (string) : - The session string part that represents the time HHmm
refTimezone (simple string) : - The timezone of reference of the 'hour' and 'minute'
Returns: - The session time object
method from_sess_string(this, sess)
from_sess_string - Initialize the session time range object from the session string in exchange timezone (syminfo.timezone)
Namespace types: SessionTimeRange
Parameters:
this (SessionTimeRange) : - The session time range object that will hold the start and end time of the daily session
sess (string) : - The session string part that represents the time range HHmm-HHmm
Returns: - The session time range object
method from_sess_string(this, sess, refTimezone)
from_sess_string - Initialize the session time range object from the session string
Namespace types: SessionTimeRange
Parameters:
this (SessionTimeRange) : - The session time range object that will hold the start and end time of the daily session
sess (string) : - The session string part that represents the time range HHmm-HHmm
refTimezone (simple string) : - The timezone of reference of the time ranges
Returns: - The session time range object
method from_sess_string(this, sess)
from_sess_string - Initialize the session object from the session string in exchange timezone (syminfo.timezone)
Namespace types: Session
Parameters:
this (Session) : - The session object that will hold the day and the time range selection
sess (string) : - The session string that represents the session HHmm-HHmm,HHmm-HHmm:ddddddd
Returns: - The session time range object
method from_sess_string(this, sess, refTimezone)
from_sess_string - Initialize the session object from the session string
Namespace types: Session
Parameters:
this (Session) : - The session object that will hold the day and the time range selection
sess (string) : - The session string that represents the session HHmm-HHmm,HHmm-HHmm:ddddddd
refTimezone (simple string) : - The timezone of reference of the time ranges
Returns: - The session time range object
method nth_day_after(this, day, n)
nth_day_after - The nth day after the given day that is a session day (true) in the object
Namespace types: SessionDays
Parameters:
this (SessionDays) : - The session days object with the day selection
day (int) : - The day id of the reference day
n (int) : - The number of days after
Returns: - The day id of the nth session day of the week after the given day
method nth_day_before(this, day, n)
nth_day_before - The nth day before the given day that is a session day (true) in the object
Namespace types: SessionDays
Parameters:
this (SessionDays) : - The session days object with the day selection
day (int) : - The day id of the reference day
n (int) : - The number of days after
Returns: - The day id of the nth session day of the week before the given day
method next_day(this)
next_day - The next day that is a session day (true) in the object
Namespace types: SessionDays
Parameters:
this (SessionDays) : - The session days object with the day selection
Returns: - The day id of the next session day of the week
method previous_day(this)
previous_day - The previous day that is session day (true) in the object
Namespace types: SessionDays
Parameters:
this (SessionDays) : - The session days object with the day selection
Returns: - The day id of the previous session day of the week
method get_sec_in_day(this)
get_sec_in_day - Count the seconds since the start of the day this session time represents
Namespace types: SessionTime
Parameters:
this (SessionTime) : - The session time object with the hour and minute of the time of the day
Returns: - The number of seconds passed from the start of the day until that session time
method get_ms_in_day(this)
get_ms_in_day - Count the milliseconds since the start of the day this session time represents
Namespace types: SessionTime
Parameters:
this (SessionTime) : - The session time object with the hour and minute of the time of the day
Returns: - The number of milliseconds passed from the start of the day until that session time
method is_day_included(this, day)
is_day_included - Check if the given day is inside the session days
Namespace types: SessionDays
Parameters:
this (SessionDays) : - The session days object with the day selection
day (int) : - The day to check if it is a trading day
Returns: - Whether the current day is included in the session days
DateTimeWindow
DateTimeWindow - Object that represents a datetime window with a beginning and an end
Fields:
fromDateTime (series int) : - The beginning of the datetime window
toDateTime (series int) : - The end of the datetime window
SessionDays
SessionDays - Object that represent the trading days of the week
Fields:
days (map) : - The map that contains all days of the week and their session flag
SessionTime
SessionTime - Object that represents the time (hour and minutes)
Fields:
hourInDay (series int) : - The hour of the day that ranges from 0 to 24
minuteInHour (series int) : - The minute of the hour that ranges from 0 to 59
minuteInDay (series int) : - The minute of the day that ranges from 0 to 1440. They will be calculated based on hourInDay and minuteInHour when method is called
SessionTimeRange
SessionTimeRange - Object that represents a range that extends from the start to the end time
Fields:
startTime (SessionTime) : - The beginning of the time range
endTime (SessionTime) : - The end of the time range
isOvernight (series bool) : - Whether or not this is an overnight time range
Session
Session - Object that represents a session
Fields:
days (SessionDays) : - The map of the trading days
timeRanges (array) : - The array with all time ranges of the session during the trading days
SessionView
SessionView - Object that visualize a session
Fields:
sess (Session) : - The Session object to be visualized
names (array) : - The names of the session time ranges
colors (array) : - The colors of the session time ranges
Bilson Gann CountGann counting is a method for identifying swing points,trends, and overall market structure. It simplifies price action by drawing short trend lines that summarize moves.
There's essentially 4 types of bar/candle.
Up bar - Higher high and higher low than previous bar
Down bar - Lower high and lower low than previous bar
Inside bar - Lower high and higher low than previous bar
Outside bar - Higher high and lower low than previous bar
We use these determinations to decide how the trendline moves through the candles.
Up bars we join to the high, down bars we join to the low, inside bars are ignored.
There are other indicators that already exist which do this, the difference here is how we handle outside bars.
Other gann counting methods skip outside bars, this method determines how to handle the outside bar after the outside bar is broken.
examples
UP -> OUTSIDE -> UP = Outside bar treated as swing low
UP -> OUTSIDE -> DOWN = Outside bar treated as swing high
DOWN -> OUTSIDE -> UP = Outside bar treated as swing low
DOWN -> OUTSIDE -> DOWN = Outside bar treated as swing high
[TTI] High Volume Close (HVC) Setup📜 ––––HISTORY & CREDITS––––
The High Volume Close (HVC) Setup is a specialised indicator designed for the TradingView platform used to identify specific bar. This tool was developed with the objective of identifying a technical pattern that trades have claimed is significant trading opportunities through a unique blend of volume analysis and price action strategies. It is based on the premise that high-volume bars, when combined with specific price action criteria, can signal key market movements.
The HVC is applicable both for swing and longer term trading and as a technical tool it can be used by traders of any asset type (stocks, ETF, crypto, forex etc).
🦄 –––UNIQUENESS–––
The uniqueness of the HVC Setup lies in its flexibility to determine an important price level based on historically important bar. The idea is to identify significant bars (e.g. those who have created the HIGHEST VOLUME: Ever, Yearly, Quarterly and meet additional criteria from the settings) and plot on the chart the close on that day as a significant level as well as theoretical stop loss and target levels. This approach allows traders to discern high volume bars that are contextually significant — a method not commonly found in standard trading tools.
🎯 ––––WHAT IT DOES––––
The HVC Setup indicator performs a series of calculations to identify high volume close bars/bar (HVC bars) based on the user requirements.
These bars are determined based on the highest volume recorded within a user-inputs:
👉 Period (Ever, Yearly, Quarterly) and must meet additional criteria such as:
👉 a minimum percentage Price Change (change is calculated based on a close/close) and
👉 specific Closing Range requirements for the HVC da.
The theory is that this is a significant bar that is important to know where it is on the chart.
The script includes a comparative analysis of the HVC bar's price against historical price highs (all-time, yearly, quarterly), which provides further context and significance to the identified bars. All of these USER input requirement are then taken into account as a condition to identity the High Volume Close Bar (HVC).
The visual representation includes color-coded bar (default is yellow) and lines to delineate these key trading signals. It then draws a blue line for the place where the close ofthe bar is, a red line that would signify a stop loss and 2 target profit levels equal to 2R and 3R of the risked level (close-stop loss). Additional lines can be turned on/off with their coresponding checkboxes in the settings.
If the user chooses "Ever" for Period - the script will look at the first available bar ever in Tradingview - this is generally the IPO bar;
If the users chooses "Yearly" - the script would look at the highest available bar for a completed year;
If the users chooses "Quarterly" - it would do the same for the quarter. (works on daily timeframe only);
While we have not backtested the performance of the script, this methodology has been widely publicised.
🛠️ ––––HOW TO USE IT––––
To utilize the HVC Setup effectively:
👉Customize Input Settings: Choose the HVC period, percentage change threshold, closing range, stop loss distance, and target multiples according to your trading strategy. Use the tick boxes to enable and disable if a given condition is used within the calculation.
👉Identify HVC Bars: The script highlights HVC bars, indicating potential opportunities based on volume and price action analysis.
👉Interpret Targets and Stop Losses: Use the color-coded lines (green for targets, red for stop losses) to guide your trade entries and exits.
👉Contextual Analysis: Always consider the HVC bar signals in conjunction with overall market trends and additional technical indicators for comprehensive trading decisions.
This script is designed to assist traders in identifying high-potential trading setups by using a combination of volume and price analysis, enhancing traditional methods with a unique, algorithmically driven approach.
MW Volume ImpulseMW Volume Impulse
Settings
* Moving Average Period: The moving average period used to generate the moving average line for the bar chart. Default=14
* Dot Size: The size of the dot that indicates when the moving average of the CVD is breached. Default=10
* Dot Transparency: The transparency of the dot that indicates when the moving average of the CVD is breached. Default=50
* EMA: The exponential moving average that the price must break through, in addition to the CVD moving
* Accumulation Length: Period used to generate the Cumulative Volume Delta (CVD) for the bar chart. Default=14
Introduction
Velocity = Change in Position over time
Acceleration = Change in Velocity over time
For this indicator, Position is synonymous with the Cumulative Volume Delta (CVD) value. What the indicator attempts to do is to determine when the rate of acceleration of buying or selling volume is changing in either or buying or selling direction in a meaningful way.
Calculations
The CVD, upon which these changes is calculated using candle bodies and wicks. For a red candle, buying volume is calculated by multiplying the volume by the spread percentage of the average of the top and bottom wicks, while Selling Volume is calculated multiplying the volume by the spread percentage of the average of the top and bottom wicks - in addition to the spread percentage of the candle body.
For a green candle, buying volume is calculated by multiplying the volume by the spread percentage of the average of the top and bottom wicks - plus the spread percentage of the candle body - while Selling Volume is calculated using only the spread percentage average of the top and bottom wicks.
How to Interpret
The difference between the buying volume and selling volume is the source of what generates the red and green bars on the indicator. But, more specifically, this indicator uses an exponential moving average of these volumes (14 EMA by default) to determine that actual bar size. The change in this value indicates the velocity of volume and, ultimately, the red and green bars on the indicator.
- When the bar height is zero, that means that there is no velocity, which indicates either a balance between buyers and sellers, or very little volume.
- When the bar height remains largely unchanged from period to period - and not zero - it means that the velocity of volume is constant in one direction. That direction is indicated by the color of the bar. Buyers are dominating when the bars are green, and sellers are dominating when the bars are red.
- When the bar height increases, regardless of bar color, it means that volume is accelerating in a buying direction.
- When the bar height decreases, regardless of bar color, it means that volume is accelerating in a selling direction.
The white line represents the moving average of the bar values, while the red and white - and green and white - dots show when the moving average has been breached by the Cumulative Volume Delta value AND the price has broken the 7 EMA (which is user editable). As with most moving averages, a breach can indicate a move in a bearish or bullish direction, and the sensitivity can be adjusted for differing market conditions
Other Usage Notes and Limitations
For better use of the signal, consider the following,
1. Volume moving below the moving average can indicate that the volume may be ready to exit an overbought condition, especially if the bars were making lower highs prior to the signal - regardless of bar color.
3. Volume moving above the moving average can indicate that the volume may be ready to exit an oversold condition, especially if the bars were making higher lows prior to the signal - regardless of bar color.
Additionally, a green dot that occurs with a positive (green) Cumulative Volume Delta can indicate a buying condition, while a red dot that occurs with a negative (red) Cumulative Volume Delta can indicate a selling condition. What this means is that buying or selling momentum briefly went against the direction of buying or selling Cumulative Volume Delta , but was not strong enough to change the buying or selling direction. In cases like this, once the volume begins to accelerate again in the direction of the buying or selling volume - indicated by a red or green dot - then the price is more likely to favor the direction of the Cumulative Volume Delta and its corresponding acceleration.
Although a red or green signal can indicate a change in direction, this script cannot predict the magnitude or duration of the change. It is best used with accompanying indicators that can be used to confirm a direction change, such as a moving average, or a supply or demand range.
loggerLibrary "logger"
◼ Overview
A dual logging library for developers. Tradingview lacks logging capability. This library provides logging while developing your scripts and is to be used by developers when developing and debugging their scripts.
Using this library would potentially slow down you scripts. Hence, use this for debugging only. Once your code is as you would like it to be, remove the logging code.
◼︎ Usage (Console):
Console = A sleek single cell logging with a limit of 4096 characters. When you dont need a large logging capability.
//@version=5
indicator("demo.Console", overlay=true)
plot(na)
import GETpacman/logger/1 as logger
var console = logger.log.new()
console.init() // init() should be called as first line after variable declaration
console.FrameColor:=color.green
console.log('\n')
console.log('\n')
console.log('Hello World')
console.log('\n')
console.log('\n')
console.ShowStatusBar:=true
console.StatusBarAtBottom:=true
console.FrameColor:=color.blue //settings can be changed anytime before show method is called. Even twice. The last call will set the final value
console.ShowHeader:=false //this wont throw error but is not used for console
console.show(position=position.bottom_right) //this should be the last line of your code, after all methods and settings have been dealt with.
◼︎ Usage (Logx):
Logx = Multiple columns logging with a limit of 4096 characters each message. When you need to log large number of messages.
//@version=5
indicator("demo.Logx", overlay=true)
plot(na)
import GETpacman/logger/1 as logger
var logx = logger.log.new()
logx.init() // init() should be called as first line after variable declaration
logx.FrameColor:=color.green
logx.log('\n')
logx.log('\n')
logx.log('Hello World')
logx.log('\n')
logx.log('\n')
logx.ShowStatusBar:=true
logx.StatusBarAtBottom:=true
logx.ShowQ3:=false
logx.ShowQ4:=false
logx.ShowQ5:=false
logx.ShowQ6:=false
logx.FrameColor:=color.olive //settings can be changed anytime before show method is called. Even twice. The last call will set the final value
logx.show(position=position.top_right) //this should be the last line of your code, after all methods and settings have been dealt with.
◼︎ Fields (with default settings)
▶︎ IsConsole = True Log will act as Console if true, otherwise it will act as Logx
▶︎ ShowHeader = True (Log only) Will show a header at top or bottom of logx.
▶︎ HeaderAtTop = True (Log only) Will show the header at the top, or bottom if false, if ShowHeader is true.
▶︎ ShowStatusBar = True Will show a status bar at the bottom
▶︎ StatusBarAtBottom = True Will show the status bar at the bottom, or top if false, if ShowHeader is true.
▶︎ ShowMetaStatus = True Will show the meta info within status bar (Current Bar, characters left in console, Paging On Every Bar, Console dumped data etc)
▶︎ ShowBarIndex = True Logx will show column for Bar Index when the message was logged. Console will add Bar index at the front of logged messages
▶︎ ShowDateTime = True Logx will show column for Date/Time passed with the logged message logged. Console will add Date/Time at the front of logged messages
▶︎ ShowLogLevels = True Logx will show column for Log levels corresponding to error codes. Console will log levels in the status bar
▶︎ ReplaceWithErrorCodes = True (Log only) Logx will show error codes instead of log levels, if ShowLogLevels is switched on
▶︎ RestrictLevelsToKey7 = True Log levels will be restricted to Ley 7 codes - TRACE, DEBUG, INFO, WARNING, ERROR, CRITICAL, FATAL
▶︎ ShowQ1 = True (Log only) Show the column for Q1
▶︎ ShowQ2 = True (Log only) Show the column for Q2
▶︎ ShowQ3 = True (Log only) Show the column for Q3
▶︎ ShowQ4 = True (Log only) Show the column for Q4
▶︎ ShowQ5 = True (Log only) Show the column for Q5
▶︎ ShowQ6 = True (Log only) Show the column for Q6
▶︎ ColorText = True Log/Console will color text as per error codes
▶︎ HighlightText = True Log/Console will highlight text (like denoting) as per error codes
▶︎ AutoMerge = True (Log only) Merge the queues towards the right if there is no data in those queues.
▶︎ PageOnEveryBar = True Clear data from previous bars on each new bar, in conjuction with PageHistory setting.
▶︎ MoveLogUp = True Move log in up direction. Setting to false will push logs down.
▶︎ MarkNewBar = True On each change of bar, add a marker to show the bar has changed
▶︎ PrefixLogLevel = True (Console only) Prefix all messages with the log level corresponding to error code.
▶︎ MinWidth = 40 Set the minimum width needed to be seen. Prevents logx/console shrinking below these number of characters.
▶︎ TabSizeQ1 = 0 If set to more than one, the messages on Q1 or Console messages will indent by this size based on error code (Max 4 used)
▶︎ TabSizeQ2 = 0 If set to more than one, the messages on Q2 will indent by this size based on error code (Max 4 used)
▶︎ TabSizeQ3 = 0 If set to more than one, the messages on Q2 will indent by this size based on error code (Max 4 used)
▶︎ TabSizeQ4 = 0 If set to more than one, the messages on Q2 will indent by this size based on error code (Max 4 used)
▶︎ TabSizeQ5 = 0 If set to more than one, the messages on Q2 will indent by this size based on error code (Max 4 used)
▶︎ TabSizeQ6 = 0 If set to more than one, the messages on Q2 will indent by this size based on error code (Max 4 used)
▶︎ PageHistory = 0 Used with PageOnEveryBar. Determines how many historial pages to keep.
▶︎ HeaderQbarIndex = 'Bar#' (Logx only) The header to show for Bar Index
▶︎ HeaderQdateTime = 'Date' (Logx only) The header to show for Date/Time
▶︎ HeaderQerrorCode = 'eCode' (Logx only) The header to show for Error Codes
▶︎ HeaderQlogLevel = 'State' (Logx only) The header to show for Log Level
▶︎ HeaderQ1 = 'h.Q1' (Logx only) The header to show for Q1
▶︎ HeaderQ2 = 'h.Q2' (Logx only) The header to show for Q2
▶︎ HeaderQ3 = 'h.Q3' (Logx only) The header to show for Q3
▶︎ HeaderQ4 = 'h.Q4' (Logx only) The header to show for Q4
▶︎ HeaderQ5 = 'h.Q5' (Logx only) The header to show for Q5
▶︎ HeaderQ6 = 'h.Q6' (Logx only) The header to show for Q6
▶︎ Status = '' Set the status to this text.
▶︎ HeaderColor Set the color for the header
▶︎ HeaderColorBG Set the background color for the header
▶︎ StatusColor Set the color for the status bar
▶︎ StatusColorBG Set the background color for the status bar
▶︎ TextColor Set the color for the text used without error code or code 0.
▶︎ TextColorBG Set the background color for the text used without error code or code 0.
▶︎ FrameColor Set the color for the frame around Logx/Console
▶︎ FrameSize = 1 Set the size of the frame around Logx/Console
▶︎ CellBorderSize = 0 Set the size of the border around cells.
▶︎ CellBorderColor Set the color for the border around cells within Logx/Console
▶︎ SeparatorColor = gray Set the color of separate in between Console/Logx Attachment
◼︎ Methods (summary)
● init ▶︎ Initialise the log
● log ▶︎ Log the messages. Use method show to display the messages
● page ▶︎ Clear messages from previous bar while logging messages on this bar.
● show ▶︎ Shows a table displaying the logged messages
● clear ▶︎ Clears the log of all messages
● resize ▶︎ Resizes the log. If size is for reduction then oldest messages are lost first.
● turnPage ▶︎ When called, all messages marked with previous page, or from start are cleared
● dateTimeFormat ▶︎ Sets the date time format to be used when displaying date/time info.
● resetTextColor ▶︎ Reset Text Color to library default
● resetTextBGcolor ▶︎ Reset Text BG Color to library default
● resetHeaderColor ▶︎ Reset Header Color to library default
● resetHeaderBGcolor ▶︎ Reset Header BG Color to library default
● resetStatusColor ▶︎ Reset Status Color to library default
● resetStatusBGcolor ▶︎ Reset Status BG Color to library default
● setColors ▶︎ Sets the colors to be used for corresponding error codes
● setColorsBG ▶︎ Sets the background colors to be used for corresponding error codes. If not match of error code, then text color used.
● setColorsHC ▶︎ Sets the highlight colors to be used for corresponding error codes.If not match of error code, then text bg color used.
● resetColors ▶︎ Reset the colors to library default (Total 36, not including error code 0)
● resetColorsBG ▶︎ Reset the background colors to library default
● resetColorsHC ▶︎ Reset the highlight colors to library default
● setLevelNames ▶︎ Set the log level names to be used for corresponding error codes. If not match of error code, then empty string used.
● resetLevelNames ▶︎ Reset the log level names to library default. (Total 36) 1=TRACE, 2=DEBUG, 3=INFO, 4=WARNING, 5=ERROR, 6=CRITICAL, 7=FATAL
● attach ▶︎ Attaches a console to an existing Logx, allowing to have dual logging system independent of each other
● detach ▶︎ Detaches an already attached console from Logx
method clear(this)
Clears all the queue, including bar_index and time queues, of existing messages
Namespace types: log
Parameters:
this (log)
method resize(this, rows)
Resizes the message queues. If size is decreased then removes the oldest messages
Namespace types: log
Parameters:
this (log)
rows (int) : The new size needed for the queues. Default value is 40.
method dateTimeFormat(this, format)
Re/set the date time format used for displaying date and time. Default resets to dd.MMM.yy HH:mm
Namespace types: log
Parameters:
this (log)
format (string)
method resetTextColor(this)
Resets the text color of the log to library default.
Namespace types: log
Parameters:
this (log)
method resetTextColorBG(this)
Resets the background color of the log to library default.
Namespace types: log
Parameters:
this (log)
method resetHeaderColor(this)
Resets the color used for Headers, to library default.
Namespace types: log
Parameters:
this (log)
method resetHeaderColorBG(this)
Resets the background color used for Headers, to library default.
Namespace types: log
Parameters:
this (log)
method resetStatusColor(this)
Resets the text color of the status row, to library default.
Namespace types: log
Parameters:
this (log)
method resetStatusColorBG(this)
Resets the background color of the status row, to library default.
Namespace types: log
Parameters:
this (log)
method resetFrameColor(this)
Resets the color used for the frame around the log table, to library default.
Namespace types: log
Parameters:
this (log)
method resetColorsHC(this)
Resets the color used for the highlighting when Highlight Text option is used, to library default
Namespace types: log
Parameters:
this (log)
method resetColorsBG(this)
Resets the background color used for setting the background color, when the Color Text option is used, to library default
Namespace types: log
Parameters:
this (log)
method resetColors(this)
Resets the color used for respective error codes, when the Color Text option is used, to library default
Namespace types: log
Parameters:
this (log)
method setColors(this, c)
Sets the colors corresponding to error codes
Index 0 of input array c is color is reserved for future use.
Index 1 of input array c is color for debug code 1.
Index 2 of input array c is color for debug code 2.
There are 2 modes of coloring
1 . Using the Foreground color
2 . Using the Foreground color as background color and a white/black/gray color as foreground color
This is denoting or highlighting. Which effectively puts the foreground color as background color
Namespace types: log
Parameters:
this (log)
c (color ) : Array of colors to be used for corresponding error codes. If the corresponding code is not found, then text color is used
method setColorsHC(this, c)
Sets the highlight colors corresponding to error codes
Index 0 of input array c is color is reserved for future use.
Index 1 of input array c is color for debug code 1.
Index 2 of input array c is color for debug code 2.
There are 2 modes of coloring
1 . Using the Foreground color
2 . Using the Foreground color as background color and a white/black/gray color as foreground color
This is denoting or highlighting. Which effectively puts the foreground color as background color
Namespace types: log
Parameters:
this (log)
c (color ) : Array of highlight colors to be used for corresponding error codes. If the corresponding code is not found, then text color BG is used
method setColorsBG(this, c)
Sets the highlight colors corresponding to debug codes
Index 0 of input array c is color is reserved for future use.
Index 1 of input array c is color for debug code 1.
Index 2 of input array c is color for debug code 2.
There are 2 modes of coloring
1 . Using the Foreground color
2 . Using the Foreground color as background color and a white/black/gray color as foreground color
This is denoting or highlighting. Which effectively puts the foreground color as background color
Namespace types: log
Parameters:
this (log)
c (color ) : Array of background colors to be used for corresponding error codes. If the corresponding code is not found, then text color BG is used
method resetLevelNames(this, prefix, suffix)
Resets the log level names used for corresponding error codes
With prefix/suffix, the default Level name will be like => prefix + Code + suffix
Namespace types: log
Parameters:
this (log)
prefix (string) : Prefix to use when resetting level names
suffix (string) : Suffix to use when resetting level names
method setLevelNames(this, names)
Resets the log level names used for corresponding error codes
Index 0 of input array names is reserved for future use.
Index 1 of input array names is name used for error code 1.
Index 2 of input array names is name used for error code 2.
Namespace types: log
Parameters:
this (log)
names (string ) : Array of log level names be used for corresponding error codes. If the corresponding code is not found, then an empty string is used
method init(this, rows, isConsole)
Sets up data for logging. It consists of 6 separate message queues, and 3 additional queues for bar index, time and log level/error code. Do not directly alter the contents, as library could break.
Namespace types: log
Parameters:
this (log)
rows (int) : Log size, excluding the header/status. Default value is 50.
isConsole (bool) : Whether to init the log as console or logx. True= as console, False = as Logx. Default is true, hence init as console.
method log(this, ec, m1, m2, m3, m4, m5, m6, tv, log)
Logs messages to the queues , including, time/date, bar_index, and error code
Namespace types: log
Parameters:
this (log)
ec (int) : Error/Code to be assigned.
m1 (string) : Message needed to be logged to Q1, or for console.
m2 (string) : Message needed to be logged to Q2. Not used/ignored when in console mode
m3 (string) : Message needed to be logged to Q3. Not used/ignored when in console mode
m4 (string) : Message needed to be logged to Q4. Not used/ignored when in console mode
m5 (string) : Message needed to be logged to Q5. Not used/ignored when in console mode
m6 (string) : Message needed to be logged to Q6. Not used/ignored when in console mode
tv (int) : Time to be used. Default value is time, which logs the start time of bar.
log (bool) : Whether to log the message or not. Default is true.
method page(this, ec, m1, m2, m3, m4, m5, m6, tv, page)
Logs messages to the queues , including, time/date, bar_index, and error code. All messages from previous bars are cleared
Namespace types: log
Parameters:
this (log)
ec (int) : Error/Code to be assigned.
m1 (string) : Message needed to be logged to Q1, or for console.
m2 (string) : Message needed to be logged to Q2. Not used/ignored when in console mode
m3 (string) : Message needed to be logged to Q3. Not used/ignored when in console mode
m4 (string) : Message needed to be logged to Q4. Not used/ignored when in console mode
m5 (string) : Message needed to be logged to Q5. Not used/ignored when in console mode
m6 (string) : Message needed to be logged to Q6. Not used/ignored when in console mode
tv (int) : Time to be used. Default value is time, which logs the start time of bar.
page (bool) : Whether to log the message or not. Default is true.
method turnPage(this, turn)
Set the messages to be on a new page, clearing messages from previous page.
This is not dependent on PageHisotry option, as this method simply just clears all the messages, like turning old pages to a new page.
Namespace types: log
Parameters:
this (log)
turn (bool)
method show(this, position, hhalign, hvalign, hsize, thalign, tvalign, tsize, show, attach)
Display Message Q, Index Q, Time Q, and Log Levels
All options for postion/alignment accept TV values, such as position.bottom_right, text.align_left, size.auto etc.
Namespace types: log
Parameters:
this (log)
position (string) : Position of the table used for displaying the messages. Default is Bottom Right.
hhalign (string) : Horizontal alignment of Header columns
hvalign (string) : Vertical alignment of Header columns
hsize (string) : Size of Header text Options
thalign (string) : Horizontal alignment of all messages
tvalign (string) : Vertical alignment of all messages
tsize (string) : Size of text across the table
show (bool) : Whether to display the logs or not. Default is true.
attach (log) : Console that has been attached via attach method. If na then console will not be shown
method attach(this, attach, position)
Attaches a console to Logx, or moves already attached console around Logx
All options for position/alignment accept TV values, such as position.bottom_right, text.align_left, size.auto etc.
Namespace types: log
Parameters:
this (log)
attach (log) : Console object that has been previously attached.
position (string) : Position of Console in relation to Logx. Can be Top, Right, Bottom, Left. Default is Bottom. If unknown specified then defaults to bottom.
method detach(this, attach)
Detaches the attached console from Logx.
All options for position/alignment accept TV values, such as position.bottom_right, text.align_left, size.auto etc.
Namespace types: log
Parameters:
this (log)
attach (log) : Console object that has been previously attached.
Weis V5 zigzag jayySomehow, I deleted version 5 of the zigzag script. Same name. I have added some older notes describing how the Weis Wave works.
I have also changed the date restriction that stopped the script from working after Dec 31, 2022.
What you see here is the Weis zigzag wave plotted directly on the price chart. This script is the companion to the Weis cumulative wave volume script.
What is a Weis wave? David Weis has been recognized as a Wyckoff method analyst he has written two books one of which, Trades About to Happen, describes the evolution of the now-popular Weis wave. The method employed by Weis is to identify waves of price action and to compare the strength of the waves on characteristics of wave strength. Chief among the characteristics of strength is the cumulative volume of the wave. There are other markers that Weis uses as well for example how the actual price difference between the start of the Weis wave from start to finish. Weis also uses time, particularly when using a Renko chart
David Weis did a futures io video which is a popular source of information about his method. (Search David Weis and futures.io. I strongly suggest you also read “Trades About to Happen” by David Weis.
This will get you up and running more quickly when studying charts. However, you should choose the Traditional method to be true to David Weis technique as described in his book "Trades About to Happen" and in the Futures IO Webcast featuring David Weis
. The Weis pip zigzag wave shows how far in terms of bar close price a Weis wave has traveled through the duration of a Weis wave. The Weis zigzag wave is used in combination with the Weis cumulative volume wave. The two waves should be set to the same "wave size".
To use this script, you must set the wave size: Using the traditional Weis method simply enter the desired wave size in the box "How should wave size be calculated", in this example I am using a traditional wave size of .25. Each wave for each security and each timeframe requires its own wave size. Although not the traditional method devised by David Weis a more automatic way to set wave size would be to use Average True Range (ATR). Using ATR is not the true Weis method but it does give you similar waves and, importantly, without the hassle described above. Once the Weis wave size is set then the zigzag wave will be shown with volume. Because Weis used the closing price of a wave to define waves a line Bar highs and bar lows are not captured by the Weis Wave. The default script setting is now cumulative volume waves using an ATR of 7 and a multiplication factor of .5.
To display volume in a way that does not crowd out neighbouring volumes Weis displayed volume as a maximum of 3 digits (usually). Consider two Weis Wave volumes 176,895,570 and 2,654,763,889. To display wave volume as three digits it is necessary to take a number such as 176,895,570 and truncate it. 176,895,570 can be represented as 177 X 10 to the power of 6. The number displayed must also be relative to other numbers in the field. If the highest volume on the page is: 2,654,763,889 and with only three numbers available to display the result the value shown must be 265 (265 X 10 to the power of 7). Since 176,895,570 is an order of magnitude smaller than 2,654,763,889 therefore 175,895,570 must be shown as 18 instead of 177. In this way, the relative magnitudes of the two volumes can be understood. All numbers in the field of view must be truncated by the same order of magnitude to make the relative volumes understandable. The script attempts to calculate the order of magnitude value automatically. If you see a red number in the field of view it means the script has failed to do the calculation automatically and you should use the manual method – use the dialogue box “Calculate truncated wave value automatically or manually”. Scroll down from the automatic method and select manual. Once "manual" is selected the values displayed become the power values or multipliers for each wave.
Using the manual method you will select a “Multiplier” in the next dialogue box. Scan the field and select the largest value in the field of view (visible chart) is the multiplier of interest. If you select a lower number than the maximum value will see at least one red “up”. If you are too high you will see at least one red “down”. Scroll in the direction recommended or the values on the screen will be totally incorrect. With volume truncated to the highest order values, the eye can quickly get a feel for relative volumes. It also reduces the crowding and overlapping of values on the screen. You can opt to show the full volume to help get a sense of the magnitude of the true volumes.
How does the script determine if a Weis wave is continuing to grow or not?
The script evaluates the closing price of each new bar relative to the "Weis wave size". Suppose the current bar closes at a new low close, within the current down wave, at $30.00. If the Weis wave size is $0.10 then the algorithm will remember the $30.00 close and compare it to the close of the next bar. If the bar close price does not close equal to or lower than $30.00 or close equal to or higher than $30.10 then the wave is still a down wave with a current low of $30.00. This is true even if the bar low is less than $30.00 or the bar high is greater than 30.10 – only the bar’s closing price matters. If a bar's closing price climbs back up to a close of $30.11 then because the closing price has moved more than $0.10 (the Weis wave size) then that is a wave reversal with a new up-trending wave. In the above example if there was currently a downward trending wave and the bar closes were as follows $30.00, $30.09, $30.01, $30.05, $30.10 The wave direction would continue to stay downward trending until the close of $30.10 was achieved. As such $30.00 would be the low and the following closes $30.09, $30.01, $30.05 would be allocated to the new upward-trending wave. If however There was a series of bar closes like this $30.00, $30.09, $30.01, $30.05, $29.99 since none of the closes was equal to above the 10-cent reversal target of $30.10 but instead, a new Weis wave low was achieved ($29.99). As such the closes of $30.09, $30.01, $30.05 would all be attributed to the continued down-trending wave with a current low of $29.99, even though the closing price for the interim bars was above $30.00. Now that the Weis Wave low is now 429.99 then, in order to reverse this continued downtrend price will need to close at or above $30.09 on subsequent bar closes assuming now new low bar close is achieved. With large wave sizes, wave direction can be in limbo for many bars before a close either renews wave direction or reverses it and confirms wave direction as either a reversal or a continuation. On the zig-zag, a wave line and its volume will not be "printed" until a wave reversal is confirmed.
The wave attribution is similar when using other methods to define wave size. If ATR is used for wave size instead of a traditional wave constant size such as $0.10 or $2 or 2000 pips or ... then the wave size is calculated based on current ATR instead of the Weis wave constant (Traditional selected value).
I have the option to display pseudo-Ord volume. In truth, Ord used more traditional zig-zag pivots of bar highs and lows. Waves using closes as pivots can have some significant differences. This difference can be lessened by using smaller time frames and larger wave sizes.
There are other options such to display the delta price or pip size of a Weis Wave, the number of bars in a wave, and a few other options.
Candlestick Pattern Criteria and Analysis Indicator█ OVERVIEW
Define, then locate the presence of a candle that fits a specific criteria. Run a basic calculation on what happens after such a candle occurs.
Here, I’m not giving you an edge, but I’m giving you a clear way to find one.
IMPORTANT NOTE: PLEASE READ:
THE INDICATOR WILL ALWAYS INITIALLY LOAD WITH A RUNTIME ERROR. WHEN INITIALLY LOADED THERE NO CRITERIA SELECTED.
If you do not select a criteria or run a search for a criteria that doesn’t exist, you will get a runtime error. If you want to force the chart to load anyway, enable the debug panel at the bottom of the settings menu.
Who this is for:
- People who want to engage in TradingView for tedious and challenging data analysis related to candlestick measurement and occurrence rate and signal bar relationships with subsequent bars. People who don’t know but want to figure out what a strong bullish bar or a strong bearish bar is.
Who this is not for:
- People who want to be told by an indicator what is good or bad or buy or sell. Also, not for people that don’t have any clear idea on what they think is a strong bullish bar or a strong bearish bar and aren’t willing to put in the work.
Recommendation: Use on the candle resolution that accurately reflects your typical holding period. If you typically hold a trade for 3 weeks, use 3W candles. If you hold a trade for 3 minutes, use 3m candles.
Tldr; Read the tool tips and everything above this line. Let me know any issues that arise or questions you have.
█ CONCEPTS
Many trading styles indicate that a certain candle construct implies a bearish or bullish future for price. That said, it is also common to add to that idea that the context matters. Of course, this is how you end up with all manner of candlestick patterns accounting for thousands of pages of literature. No matter the context though, we can distill a discretionary trader's decision to take a trade based on one very basic premise: “A trader decides to take a trade on the basis of the rightmost candle's construction and what he/she believes that candle construct implies about the future price.” This indicator vets that trader’s theory in the most basic way possible. It finds the instances of any candle construction and takes a look at what happens on the next bar. This current bar is our “Signal Bar.”
█ GUIDE
I said that we vet the theory in the most basic way possible. But, in truth, this indicator is very complex as a result of there being thousands of ways to define a ‘strong’ candle. And you get to define things on a very granular level with this indicator.
Features:
1. Candle Highlighting
When the user’s criteria is met, the candle is highlighted on the chart.
The following candle is highlighted based on whether it breaks out, breaks down, or is an inside bar.
2. User-Defined Criteria
Criteria that you define include:
Candle Type: Bull bars, Bear bars, or both
Candle Attributes
Average Size based on Standard Deviation or Average of all potential bars in price history
Search within a specific price range
Search within a specific time range
Clarify time range using defined sessions and with or without weekends
3. Strike Lines on Candle
Often you want to know how price reacts when it gets back to a certain candle. Also it might be true that candle types cluster in a price region. This can be identified visually by adding lines that extend right on candles that fit the criteria.
4. User-Defined Context
Labeled “Alternative Criteria,” this facet of the script allows the user to take the context provided from another indicator and import it into the indicator to use as a overriding criteria. To account for the fact that the external indicator must be imported as a float value, true (criteria of external indicator is met) must be imported as 1 and false (criteria of external indicator is not met) as 0. Basically a binary Boolean. This can be used to create context, such as in the case of a traditional fractal, or can be used to pair with other signals.
If you know how to code in Pinescript, you can save a copy and simply add your own code to the section indicated in the code and set your bull and bear variables accordingly and the code should compile just fine with no further editing needed.
Included with the script to maximize out-of-the-box functionality, there is preloaded as alternative criteria a code snippet. The criteria is met on the bull side when the current candle close breaks out above the prior candle high. The bear criteria is met when the close breaks below the prior candle. When Alternate Criteria is run by itself, this is the only criteria set and bars are highlighted when it is true. You can qualify these candles by adding additional attributes that you think would fit well.
Using Alternative Criteria, you are essentially setting a filter for the rest of the criteria.
5. Extensive Read Out in the Data Window (right side bar pop out window).
As you can see in the thumbnail, there is pasted a copy of the Data Window Dialogue. I am doubtful I can get the thumbnail to load up perfectly aligned. Its hard to get all these data points in here. It may be better suited for a table at this point. Let me know what you think.
The primary, but not exclusive, purpose of what is in the Data Window is to talk about how often your criteria happens and what happens on the next bar. There are a lot of pieces to this.
Red = Values pertaining to the size of the current bar only
Blue = Values pertaining or related to the total number of signals
Green = Values pertaining to the signal bars themselves, including their measurements
Purple = Values pertaining to bullish bars that happen after the signal bar
Fuchsia = Values pertaining to bearish bars that happen after the signal bar
Lime = Last four rows which are your percentage occurrence vs total signals percentages
The best way I can explain how to understand parts you don’t understand otherwise in the data window is search the title of the row in the code using ‘ctrl+f’ and look at it and see if it makes more sense.
█ [b}Available Candle Attributes
Candle attributes can be used in any combination. They include:
[*}Bodies
[*}High/Low Range
[*}Upper Wick
[*}Lower Wick
[*}Average Size
[*}Alternative Criteria
Criteria will evaluate each attribute independently. If none is set for a particular attribute it is bypassed.
Criteria Quantity can be in Ticks, Points, or Percentage. For percentage keep in mind if using anything involving the candle range will not work well with percentage.
Criteria Operators are “Greater Than,” “Less Than,” and “Threshold.” Threshold means within a range of two numbers.
█ Problems with this methodology and opportunities for future development:
#1 This kind of work is hard.
If you know what you’re doing you might be able to find success changing out the inputs for loops and logging results in arrays or matrices, but to manually go through and test various criteria is a lot of work. However, it is rewarding. At the time of publication in early Oct 2022, you will quickly find that you get MUCH more follow through on bear bars than bull bars. That should be obvious because we’re in the middle of a bear market, but you can still work with the parameters and contextual inputs to determine what maximizes your probability. I’ve found configurations that yield 70% probability across the full series of bars. That’s an edge. That means that 70% of the time, when this criteria is met, the next bar puts you in profit.
#2 The script is VERY heavy.
Takes an eternity to load. But, give it a break, it’s doing a heck of a lot! There is 10 unique arrays in here and a loop that is a bit heavy but gives us the debug window.
#3 If you don’t have a clear idea its hard to know where to start.
There are a lot of levers to pull on in this script. Knowing which ones are useful and meaningful is very challenging. Combine that with long load times… its not great.
#4 Your brain is the only thing that can optimize your results because the criteria come from your mind.
Machine learning would be much more useful here, but for now, you are the machine. Learn.
#5 You can’t save your settings.
So, when you find a good combo, you’ll have to write it down elsewhere for future reference. It would be nice if we could save templates on custom indicators like we can on some of the built in drawing tools, but I’ve had no success in that. So, I recommend screenshotting your settings and saving them in Notion.so or some other solid record keeping database. Then you can go back and retrieve those settings.
#6 no way to export these results into conditions that can be copy/pasted into another script.
Copy/Paste of labels or tables would be the best feature ever at this point. Because you could take the criteria and put it in a label, copy it and drop it into another strategy script or something. But… men can dream.
█ Opportunities to PineCoders Learn:
1. In this script I’m importing libraries, showing some of my libraries functionality. Hopefully that gives you some ideas on how to use them too.
The price displacement library (which I love!)
Creative and conventional ways of using debug()
how to display arrays and matrices on charts
I didn’t call in the library that holds the backtesting function. But, also demonstrating, you can always pull the library up and just copy/paste the function out of there and into your script. That’s fine to do a lot of the time.
2. I am using REALLY complicated logic in this script (at least for me). I included extensive descriptions of this ? : logic in the text of the script. I also did my best to bracket () my logic groups to demonstrate how they fit together, both for you and my future self.
3. The breakout, built-in, “alternative criteria” is actually a small bit of genius built in there if you want to take the time to understand that block of code and think about some of the larger implications of the method deployed.
As always, a big thank you to TradingView and the Pinescript community, the Pinescript pros who have mentored me, and all of you who I am privileged to help in their Pinescripting journey.
"Those who stay will become champions" - Bo Schembechler
Real Woodies CCIAs always, this is not financial advice and use at your own risk. Trading is risky and can cost you significant sums of money if you are not careful. Make sure you always have a proper entry and exit plan that includes defining your risk before you enter a trade.
Ken Wood is a semi-famous trader that grew in popularity in the 1990s and early 2000s due to the establishment of one of the earliest trading forums online. This forum grew into "Woodie's CCI Club" due to Wood's love of his modified Commodity Channel Index (CCI) that he used extensively. From what I can tell, the website is still active and still follows the same core principles it did in the early days, the CCI is used for entries, range bars are used to help trader's cut down on the noise, and the optional addition of Woodie's Pivot Points can be used as further confirmation of support and resistance. This is my take on his famous "Woodie's CCI" that has become standard on many charting packages through the years, including a TradingView sponsored version as one of the many stock indicators provided by TradingView. Woodie has updated his CCI through the years to include several very cool additions outside of the standard CCI. I will have to say, I am a bit biased, but I think this is hands down one of the best indicators I have ever used, and I am far too young to have been part of the original CCI Club. Being a daytrader primarily, this fits right in my timeframe wheel house. Woodie designed this indicator to work on a day-trading time scale and he frequently uses this to trade futures and commodity contracts on the 30 minute, often even down to the one minute timeframe. This makes it unique in that it is probably one of the only daytrading-designed indicators out there that I am aware of that was not a popular indicator, like the MACD or RSI, that was just adopted by daytraders.
The CCI was originally created by Donald Lambert in 1980. Over time, it has become an extremely popular house-hold indicator, like the Stochastics, RSI, or MACD. However, like the RSI and Stochastics, there are extensive debates on how the CCI is actually meant to be used. Some trade it like a reversal indicator, where values greater than 100 or less than -100 are considered overbought or oversold, respectively. Others trade it like a typical zero-line cross indicator, where once the value goes above or below the zero-line, a trade should be considered in that direction. Lastly, some treat it as strictly a momentum indicator, where values greater than 100 or less than -100 are seen as strong momentum moves and when these values are reached, a new strong trend is establishing in the direction of the move. The CCI itself is nothing fancy, it just visualizes the distance of the closing price away from a user-defined SMA value and plots it as a line. However, Woodie's CCI takes this simple concept and adds to it with an indicator with 5 pieces to it designed to help the trader enter into the highest probability setups. Bear with me, it initially looks super complicated, but I promise it is pretty straight-forward and a fun indicator to use.
1) The CCI Histogram. This is your standard CCI value that you would find on the normal CCI. Woodie's CCI uses a value of 14 for most trades and a value of 20 when the timeframe is equal to or greater than 30minutes. I personally use this as a 20-period CCI on all time frames, simply for the fact that the 20 SMA is a very popular moving average and I want to know what the crowd is doing. This is your coloured histogram with 4 colours. A gray colouring is for any bars above or below the zero line for 1-4 bars. A yellow bar is a "trend bar", where the long period CCI has been above/below the zero line for 5 consecutive bars, indicating that a trend in the current direction has been established. Blue bars above and red bars below are simply 6+n number of bars above or below the zero line confirming trend. These are used for the Zero-Line Reject Trade (explained below). The CCI Histogram has a matching long-period CCI line that is painted the same colour as the histogram, it is the same thing but is used just to outline the Histogram a bit better.
2) The CCI Turbo line. This is a sped-up 6 period CCI. This is to be used for the Zero-Line Reject trades, trendline breaks, and to identify shorter term overbought/oversold conditions against the main trend. This is coloured as the white line.
3) The Least Squares Moving Average Baseline (LSMA) Zero Line. You will notice that the Zero Line of the indicator is either green or red. This is based on when price is above or below the 25-period LSMA on the chart. The LSMA is a 25 period linear regression moving average and is one of the best moving averages out there because it is more immune to noise than a typical MA. Statistically, an LSMA is designed to find the line of best fit across the lookback periods and identify whether price is advancing, declining, or flat, without the whipsaw that other MAs can be privy to. The zero line of the indicator will turn green when the close candle is over the LSMA or red when it is below the LSMA. This is meant to be a confirmation tool only and the CCI Histogram and Turbo Histogram can cross this zero line without any corresponding change in the colour of the zero line on that immediate candle.
4) The +100 and -100 lines are used in two ways. First, they can be used by the CCI Histogram and CCI Turbo as a sort of minor price resistance and if the CCI values cannot get through these, it is considered weakness in that trade direction until they do so. You will notice that both of these lines are multi-coloured. They have been plotted with the ChopZone Indicator, another TradingView built-in indicator. The ChopZone is a trend identification tool that uses the slope and the direction of a 34-period EMA to identify when price is trending or range bound. While there are ~10 different colours, the main two a trader needs to pay attention to are the turquoise/cyan blue, which indicates price is in an uptrend, and dark red, which indicates price is in a downtrend based on the slope and direction of the 34 EMA. All other colours indicate "chop". These colours are used solely for the Zero-Line Reject and pattern trades discussed below. They are plotted both above and below so you can easily see the colouring no matter what side of the zero line the CCI is on.
5) The +200 and -200 lines are also used in two ways. First, they are considered overbought/oversold levels where if price exceeds these lines then it has moved an extreme amount away from the average and is likely to experience a pullback shortly. This is more useful for the CCI Histogram than the Turbo CCI, in all honesty. You will also notice that these are coloured either red, green, or yellow. This is the Sidewinder indicator portion. The documentation on this is extremely sparse, only pointing to a "relationship between the LSMA and the 34 EMA" (see here: tlc.thinkorswim.com). Since I am not a member of Woodie's CCI Club and never intend to be I took some liberty here and decided that the most likely relationship here was the slope of both moving averages. Therefore, the Sidewinder will be green when both the LSMA and the 34 EMA are rising, red when both are falling, and yellow when they are not in agreement with one another (i.e. one rising/flat while the other is flat/falling). I am a big fan of Dr. Alexander Elder as those who follow me know, so consider this like Woodie's version of the Elder Impulse System. I will fully admit that this version of the Sidewinder is a guess and may not represent the real Sidewinder indicator, but it is next to impossible to find any information on this, so I apologize, but my version does do something useful anyways. This is also to be used only with the Zero-Line Reject trades. They are plotted both above and below so you can easily see the colouring no matter what side of the zero line the CCI is on.
How to Trade It According to Woodie's CCI Club:
Now that I have all of my components and history out of the way, this is what you all care about. I will only provide a brief overview of the trades in this system, but there are quite a few more detailed descriptions listed in the Woodie's CCI Club pamphlet. I have had little success trading the "patterns" but they do exist and do work on occasion. I just prefer to trade with the flow of the markets rather than getting overly scalpy. If you are interested in these patterns, see the pamphlet here (www.trading-attitude.com), hop into the forums and see for yourself, or check out a couple of the YouTube videos.
1) Zero line cross. As simple as any other momentum oscillator out there. When the long period CCI crosses above or below the zero line open a trade in that direction. Extra confirmation can be had when the CCI Turbo has already broken the +100/-100 line "resistance or support". Trend traders may wish to wait until the yellow "trend confirmation bar" has been printed.
2) Zero Line Reject. This is when the CCI Turbo heads back down to the zero line and then bounces back in the same direction of the prevailing trend. These are fantastic continuation trades if you missed the initial entry either on the zero line cross or on the trend bar establishment. ZLR trades are only viable when you have the ChopZone indicator showing a trend (turquoise/cyan for uptrend, dark red for downtrend), the LSMA line is green for an uptrend or red for a downtrend, and the SideWinder is either green confirming the uptrend or red confirming the downtrend.
3) Hook From Extreme. This is the exact same as the Zero Line Reject trade, however, the CCI Turbo now goes to the +100/-100 line (whichever is opposite the currently established trend) and then hooks back into the established trend direction. Ideally the HFE trade needs to have the Long CCI Histogram above/below the corresponding 100 level and the CCI Turbo both breaks the 100 level on the trend side and when it does break it has increased ~20 points from the previous value (i.e. CCI Histogram = +150 with LSMA, CZ, and SW all matching up and trend bars printed on CCI Histogram, CCI Turbo went to -120 and bounced to +80 on last 2 bars, current bar closes with CCI Turbo closing at +110).
4) Trend Line Break. Either the CCI Turbo or CCI Histogram, whichever you prefer (I find the Turbo a bit more accurate since its a faster value) creates a series of higher highs/lows you can draw a trend line linking them. When the line breaks the trendline that is your signal to take a counter trade position. For example, if the CCI Turbo is making consistently higher lows and then breaks the trendline through the zero line, you can then go short. This is a good continuation trade.
5) The Tony Trade. Consider this like a combination zero line reject, trend line break, and weak zero line cross all in one. The idea is that the SW, CZ, and LSMA values are all established in one direction. The CCI Histogram should be in an established trend and then cross the zero line but never break the 100 level on the new side as long as it has not printed more than 9 bars on the new side. If the CCI Histogram prints 9 or less bars on the new side and then breaks the trendline and crosses back to the original trend side, that is your signal to take a reversal trade. This is best used in the Elder Triple Screen method (discussed in final section) as a failed dip or rip.
6) The GB100 Trade. This is a similar trade as the Tony Trade, however, the CCI Histogram can break the 100 level on the new side but has to have made less than 6 bars on the new side. A trendline break is not necessary here either, it is more of a "pop and drop" or "momentum failure" trade trying in the new direction.
7) The Famir Trade. This is a failed CCI Long Histogram ZLR trade and is quite complicated. I have never traded this but it is in the pamphlet. Essentially you have a typical ZLR reject (i.e. all components saying it is likely a long/short continuation trade), but the ZLR only stays around the 50 level, goes back to the trend side, fails there as well immediately after 1 bar and then rebreaks to the new side. This is important to be considered with the LSMA value matching the side of the trade, so if the Famir says to go long, you need the LSMA indicator to also say to go long.
8) The Vegas Trade. This is essentially a trend-reversal trade that takes into account the LSMA and a cup and handle formation on the CCI Long Histogram after it has reached an extreme value (+200/-200). You will see the CCI Histogram hit the extreme value, head towards the zero line, and then sort of round out back in the direction of the extreme price. The low point where it reversed back in the direction of the extreme can be considered support or resistance on the CCI and once the CCI Long Histogram breaks this level again, with LSMA confirmation, you can take a counter trend trade with a stop under/over the highest/lowest point of the last 2 bars as you want to be out quickly if you are wrong without much damage but can get a huge win if you are right and add later to the position once a new trade has formed.
9) The Ghost Trade. This is nothing more than a(n) (inverse) head and shoulders pattern created on the CCI. Draw a trend line connecting the head and shoulders and trade a reversal trade once the CCI Long Histogram breaks the trend line. Same deal as the Vegas Trade, stop over/under the most recent 2 bar high/low and add later if it is a winner but cut quickly if it is a loser.
Like I said, this is a complicated system and could quite literally take years to master if you wanted to go into the patterns and master them. I prefer to trade it in a much simpler format, using the Elder Triple Screen System. First, since I am a day trader, I look to use the 20 period Woodie's on the hourly and look at the CZ, SW, and LSMA values to make sure they all match the direction of the CCI Long Histogram (a trend establishment is not necessary here). It shows you the hourly trend as your "tide". I then drill down to the 15 minute time frame and use the Turbo CCI break in the opposite direction of the trend as my "wave" and to indicate when there is a dip or rip against the main trend. Lastly, I drill down to a 3 minute time frame and enter when the CCI Long Histogram turns back to match the main trend ("ripple") as long as the CCI Turbo has broken the 100 level in the matched direction.
Enjoy, and please read the pamphlet if you have any questions about the patterns as they are not how I use these and will not be able to answer those questions.
tunnel trading betaThe original author of the tunnel trading system: youtuber:Teacher Jin
This is a set of indicators system that trades completely based on the moving average. It belongs to the right trading. The idea is as follows:
(1) Basic trend (major trend)
When the short-term moving average is higher than the long-term moving average, it is an upward trend; otherwise, it is a downward trend.
The tentative short-term moving average is ema12, and the long-term moving average is ema169.
(2) The first type of buying point (or short point): trend establishment
Starting from the bar where the uptrend is established, the first outgoing bar is the first buying point. (Outgoing means that the closing price is higher than the opening price and higher than the high point of the previous bar)
Starting from the bar where the downtrend is established, the first bar to fall is the first shorting point. (Fall means that the closing price is lower than the opening price and lower than the low point of the previous bar)
(3) The second type of buying point (or short point): the buying point when pulling back (or the short point when rebounding)
The buying point at the time of pullback (callback) means that the general trend is up, but the small trend is down. You can buy when it is clear that the down trend is over.
Two concepts need to be defined here: "pullback (callback)" and "end of down trend". The definition of pullback is that when the general trend is rising, bar falls below the long-term moving average, and at this time the short-term moving average is still higher than the long-term moving average; The definition of the end of a down trend is that it is outgoing and ema12 is on the rise.
In the same way, we can know what is the "short point when rebounding":
The big trend is down, but the small trend is up. When it is clear that the rise is over, you can go short.
(4) Setting of Stop Loss and Take Profit
When going long:
Stop Loss Price: The low point of a bar before the buying point.
Stop-profit price: After the stop-loss price is determined, the profit-loss ratio is 3:1 to determine the stop-profit price. (The default value is 3, the user can modify it)
When shorting:
Stop Loss Price: The high point of a bar before the purchase point.
Stop-profit price: After the stop-loss price is determined, the profit-loss ratio is 3:1 to determine the stop-profit level. (The default value is 3, the user can modify it)
Chinese introduction:
隧道交易体系的原作者:油管金老师看盘室
这是一套完全根据均线进行交易的指标体系,属于右侧交易,思路如下:
(1) 基本趋势(大趋势)
短期均线高于长期均线时,是上涨趋势;反之,是下降趋势。
暂定短期均线为ema12,长期均线为ema169。
(2) 第一种买入点(或做空点):趋势确立
从上涨趋势确立的那根bar开始,第一个出头的bar,是第一买入点。(出头,是指收盘价高于开盘价,且高于前一根bar的高点)
从下降趋势确立的那根bar开始,第一个落尾的bar,是第一做空点。(落尾,是指收盘价低于开盘价,且低于前一根bar的低点)
(3) 第二种买入点(或做空点):拉回时的买入点(或反弹时的做空点)
拉回时(回调时)的买入点,是指大趋势是上涨,但小趋势是下跌,当明确下跌结束时,可以买入。
这里需要定义2个概念:“拉回(回调)”和“下跌结束”。拉回的定义是,大趋势是上涨时,bar跌破长期均线,此时短期均线仍高于长期均线;下跌结束的定义是,出头且ema12在上升。
同理可知什么是“反弹时的做空点”:
大趋势是下跌,但小趋势是上涨,当明确上涨结束时,可以做空。
(4) 止损位和止盈位的设置
做多时:
止损位:买入点前一根bar的低点。
止盈位:止损位确定后,按盈亏比3:1确定止盈位。(默认值为3,用户可以修改)
做空时:
止损位:买入点前一根bar的高点。
止盈位:止损位确定后,按盈亏比3:1确定止盈位。(默认值为3,用户可以修改)