Advanced Volume Zone Oscillator
We'll take the basic VZO indicator in ThinkOrSwim and extract meaningful patterns to turn it into a useful trend trading tool
Welcome to the 14th episode of “How to thinkScript”.
In this video, we’re going to take the basic Volume Zone Oscillator that’s built into ThinkOrSwim , and turn it into something like this:
Most of this is going to be just some formatting tricks, using the basic indicator. But, we’ll use some ThinkOrSwim documentation, along with some research, to make the VZO more advanced, and complete.
The custom code written for the Advanced VZO Indicator is available for free download below.
We are TOS Indicators.com, home of the Volatility Box.
Our Futures Volatility Box gave us an incredible entry to get long Gold, and play not only this nice burst move up higher, but also a longer time frame trade.
- Price fell into our Volatility Box
- We even had an Edge Signals confirmation arrow
- And we can see what ended up happening to price
If we zoom out, out on the Daily chart, we can see there’s a nice daily squeeze happening on Gold. Now, we have a risk-free trade in Gold, to see how high is high, AND we’ve already hit our first and second targets.
For anyone interested in using the Volatility Box to trade either Futures or Stock, we’re offering a bundle discount for a limited time.
If you’d like more information, send us an e-mail at [email protected].
That’s the power of being able to use Volatility Models and Price Movement Ranges that you can trust.
In this tutorial, we’re going to cover a handful of concepts.
We’ll talk about reading ThinkOrSwim documentation, and translating their insights into actual code.
Once we have that, we will spend some time going over formatting tips and tricks for ThinkOrSwim studies, to show relevant information only.
And finally, we’ll use the lower VZO Indicator that we build, to quickly build out an upper VZO indicator as well, with colored candles and arrows.
Let’s get started.
Before we write any code to build the VZO Indicator, let’s first understand what it even is.
VZO stands for “Volume Zone Oscillator”
Let’s take a look to see how the ThinkOrSwim documentation defines VZO:
The Volume Zone Oscillator (VZO) is a technical indicator analyzing volume changes in relation to certain levels (zones). Unlike VolumeOsc, the VZO uses price data along with volume.
Two averages are calculated for the VZO: the first one is price related EMA of volume, the second is general EMA of volume. The first EMA takes into account volume with sign like OnBalanceVolume: the volume is considered negative when the Close price of the corresponding bar is lower than that of the previous bar, and positive otherwise. Once these averages are calculated, their percentage ratio is the resulting plot.
Several levels are introduced to analyze the VZO plot: "+60", "+40", "+15", "-5", "-40", and "-60". These numbers represent corresponding percentage values. For additional confirmation, it is suggested that the VZO plot be accompanied with 60 period EMA and 14 period ADX. These two studies are used for checking trend existence and direction. ADX values higher than 18 suggest that the market is trending, otherwise the non-trending mode is spotted. When the market is trending, the trend direction can be defined using the EMA: the price crossing above the EMA suggests the uptrend, otherwise the downtrend is detected. When the trend mode and direction are defined, use the crossovers of the VZO with corresponding levels as Buy and Sell signals for long and short positions (see plots' descriptions for details).
Let's summarize the takeaways.
So the key points to highlight here that there are two moving averages that go into the calculation:
- Price related EMA of Volume
- General EMA of Volume
The VZO line that plots in the indicator is the percentage ratio of both the price related volume EMA, and the general volume EMA. And we can see that there are different levels based on this percentage, which is what all of the different sections in the indicator are… green, yellow, red, etc.
Let’s keep reading.
Ah – ThinkOrSwim even gives us some hints.
For additional confirmation of the VZO indicator, they suggest using the 60 period EMA and 14 period ADX. So we might be able to use this for arrows on the chart.
And we see that both of these indicators help validate that the trend actually exists, and what direction it’s headed in.
- 14-period ADX condition: ADX value above 18 suggests that the market is trending. So trend existence.
- 60-period EMA condition:Price crossing above the EMA suggests an uptrend. Otherwise we are in a down trend.
And our final hint is when the trend exists, and we know the direction, then use the VZO crossovers with the levels as buy and sell signals.
Let’s start writing some code.
So the built-in study is going to be our base. It seems to match even the settings from the screenshot of a 14-period oscillator.
And for the rest of it, we’re going to use the hints given to us by ThinkOrSwim.
So let’s create a new study. We’ll call it “TI_AdvancedVZO_Lower”
In it, let’s start by bringing over all the existing plots from the built-in indicator inside of ThinkOrSwim.
declare lower; input length = 14; def VP = ExpAverage(Sign(close - close) * volume, length); def TV = ExpAverage(volume, length); plot VZO = 100 * VP / TV; plot "+60" = 60; plot "+40" = 40; plot "+15" = 15; plot "-5" = -5; plot "-40" = -40; plot "-60" = -60; plot ZeroLine = 0; VZO.SetDefaultColor(GetColor(1)); "+60".SetDefaultColor(GetColor(6)); "+40".SetDefaultColor(GetColor(6)); "+15".SetDefaultColor(GetColor(3)); "-5".SetDefaultColor(GetColor(3)); "-40".SetDefaultColor(GetColor(5)); "-60".SetDefaultColor(GetColor(5)); ZeroLine.SetDefaultColor(GetColor(4));=
Ok – that’s a good baseline. Now let’s start by going through our ThinkOrSwim hints.
Let’s go ahead and create two new variables, that brings in our 14 period ADX and our 60 period EMA indicators.
def ADX = ADX (14); def EMA60 = ExpAverage(close, 60);
Next, let’s define the trigger criteria condition for each of these:
def trendExistence = ADX > 18; # 1 = cross above, 2 = stays above, 3 = crosses below, 4 = stays below def direction = if close > EMA60 and close <= EMA60 then 1 else if close > EMA60 and close >= EMA60 then 2 else if close < EMA60 and close >= EMA60 then 3 else 4;
Now, we need to bring everything together.
Let’s now start to define what an VZO crossover looks like:
def bullishCrossover = if VZO >= +40 and VZO < +40 then 1 else 0; def bearishCrossover = if VZO <= -40 and VZO > -40 then 1 else 0; plot bullSignal = if trendExistence == 1 and direction == 1 and bullishCrossover then 1 else 0; bullSignal.setPaintingStrategy(PaintingStrategy.ARROW_UP); plot bearSignal = if trendExistence == 1 and direction == 3 and bearishCrossover then 1 else 0; bearSignal.setPaintingStrategy(PaintingStrategy.Boolean_ARROW_DOWN);
Fantastic. That works like we expected it to. There aren’t a ton of signals that are populating on the charts, which is the point of all of our confirmation signals.
Let’s complete the funnel now with a list of top holdings.
The first thing is lines. There’s too many of them. Let’s clean that up.
We’ll comment out the –5 and 15.
We can also turn the top and bottom levels into a cloud, similar to our Volatility Box.
Let’s change their line plots to the following:
AddCloud(40, 60, color.green, color.green); Addcloud (-40,-60, color.red, color.red);
It would also be cool if the VZO Indicator line changed colors based on which zone we are in. Let’s do that. We’ll use the AssignValueColor function for that.
Another thing, to achieve this effect of having dots and lines, we’ll duplicate the plot of the VZO, so we can have one draw using dots. The other using a line.
However, we will use the same logic for coloring on both, to make our jobs easy.
Plot VZO_Dots = 100 * VP / TV; VZO.setLineWeight(3); VZO_Dots.setPaintingStrategy(PaintingStrategy.POINTS); VZO_Dots.setLineWeight(3);
Now, let’s set the logic for the VZO Indicator’s colors.
VZO.AssignValueColor(if VZO > 15 then color.green else if VZO > -5 then color.yellow else color.red);
And we’ll copy paste this one more time, for our dots.
VZO_Dots.AssignValueColor(if VZO > 15 then color.green else if VZO > -5 then color.yellow else color.red);
Click save, and voila!
That’s it folks. You have a fancy new VZO Indicator to trade momentum and trends.
Once we copy paste all of the code, we’ll change the top to declare upper, instead of the lower.
And we already have the arrows declared in our code, from our initial work.
The only step left is to define the colors of the candles. Let’s do that. We’ll change the AssignValueColors on VZO to be for the candles instead. So we’ll replace that with AssignPriceColors.
And let’s make our arrows stand out a bit more. Here is the final code for the TI_AdvancedVZO_Upper study:
declare upper; input length = 14; def VP = ExpAverage(Sign(close - close) * volume, length); def TV = ExpAverage(volume, length); def VZO = 100 * VP / TV; def ADX = ADX(14); def EMA60 = ExpAverage(close, 60); def trendExistence = ADX > 18; #1 - crosses above EMA60, 2 - above EMA60, 3 - crossing below EMA60, 4 - below EMA60 def direction = if close > EMA60 and close <= EMA60 then 1 else if close > EMA60 and close >= EMA60 then 2 else if close < EMA60 and close >= EMA60 then 3 else 4; def bullishCrossover = if VZO >= 40 and VZO < 40 then 1 else 0; def bearishCrossover = if VZO <= -40 and VZO > -40 then 1 else 0; plot bullSignal = if trendExistence == 1 and direction == 1 and bullishCrossover then 1 else 0; bullSignal.setPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP); bullSignal.SetLineWeight(5); plot bearSignal = if trendExistence == 1 and direction == 3 and bearishCrossover then 1 else 0; bearSignal.setPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN); bearSignal.SetLineWeight(5); AssignPriceColor(if VZO > 15 then color.green else if VZO > -5 then color.yellow else color.red);
Click the button below to download the code for the Advanced Volume Zone Oscillator (VZO) Indicator.