# Volume Positive-Negative (VPN) indicator

#### gravityflyer

##### New member
Hi all,

Just wondering if anyone has converted Markos Katsanos' new VPN indicator into a ToS script? He just released the indicator in this month's issue of Stocks & Commodities and he has provided the open source script for Amibroker on his website:

Code:
// VPN Indicator
// Created by Markos Katsanos

Period = Param(“VP Period”, 30, 5, 100, 10 );
SMOOTH=Param( “SMOOTH”, 3, 1, 10, 1 );
VPNCRIT=Param( “VPNCRIT”, 10, 0, 40, 5 );
MAB=Param( “MA BARS”, 30, 10, 200, 10 );
MAV=MA(V,PERIOD);MAV=IIF(MAV>0,MAV,1);
MF = Avg – Ref( Avg, -1 );MC=.1*ATR(PERIOD);
VMP = IIf( MF > MC, V, 0 ) ;
VP = Sum( VMP , PERIOD);
VMN = IIf( MF < -MC, V, 0 ) ;
VN = Sum( VMN , PERIOD);
VPN=(VP-VN)/MAV/PERIOD*100;
VPN=EMA(VPN,SMOOTH);MAVPN=MA(VPN,MAB);
dynamic_color = IIf( VPN >= VPNCRIT, colorGreen, colorRED ) ;
Plot( VPN, “VPN(” + PERIOD + “)”, DYNAMIC_COLOR , STYLETHICK );
Plot( MAVPN, “MA”,colorGREEN, styleDashed );
Plot(VPNCRIT,”CRIT”,colorBLUE);

Any help for use in ToS would be greatly appreciated!

I am not good at this but I tried to do it. let me know what you think

Code:
input length = 50;

def O = open;
def c = close;
def v = volume;

def v_up = if close >= close[1] then Volume else 0;
def v_down = if close < close [1] then Volume else 0;

def volavg = average (volume, length);

def vp = sum(v_up, length);
def vn = sum(v_down, length);

plot VPN = (VP-VN)/volavg/length*100;

plot zeroline = 0;

I am not good at this but I tried to do it. let me know what you think

Code:
input length = 50;

def O = open;
def c = close;
def v = volume;

def v_up = if close >= close[1] then Volume else 0;
def v_down = if close < close [1] then Volume else 0;

def volavg = average (volume, length);

def vp = sum(v_up, length);
def vn = sum(v_down, length);

plot VPN = (VP-VN)/volavg/length*100;

plot zeroline = 0;
Going over it again, I saw that the definition of up and down days is flawed. It needs to be corrected to include the ATR and the use of average daily price. Ill try to figure out how to do that.

A version of the indicator is available here:
No code on page, but a ToS link to it

-mashume

I DID NOT WRITE THIS AND DO NOT CLAIM TO HAVE DONE SO.
Reproduced here with citation to the original source. Please do not pirate someone else's code.
Code:
declare lower;

input length = 30;
input emaLength = 3;
input averageLength = 30;
input factor = 0.1;
input criticalValue = 10;
input averageType = AverageType.EXPONENTIAL;

def atr = WildersAverage(TrueRange(high,  close,  low), length);
def diff = hlc3 - hlc3[1];
def vp = Sum(if diff > factor * atr then volume else 0, length);
def vn = Sum(if diff < -factor * atr then volume else 0, length);

plot VPN = ExpAverage(100 * (vp - vn) / Sum(volume, length), emaLength);
plot VPNAvg = MovingAverage(averageType, VPN, averageLength);
plot CriticalLevel = criticalValue;

VPN.DefineColor("Above", Color.UPTICK);
VPN.DefineColor("Below", Color.DOWNTICK);
VPN.AssignValueColor(if VPN > CriticalLevel then VPN.Color("Above") else VPN.Color("Below"));
VPNAvg.SetDefaultColor(GetColor(7));
CriticalLevel.SetDefaultColor(GetColor(1));

EDIT
I tried to implement the strategy from the easylanguage code on the page shown above. It plots sell signals, but I haven't seen a buy signal. Perhaps I got something wrong...
Code:
declare lower;

input Period = 30;
input Smooth = 3;
input VPNCrit = 10;
input MAB = 30;
input MinC = 1;
input MinVol = 100000;
input MinVolAvgLen = 5;
input VolAvgLen = 50;
input MinVC = 0.5;
input VolDivisor = 100000;
input RSIMaxVal = 90;
input RSILen = 5;

def RSIVal = RSI( RSILen );

input length = 30;
input emaLength = 3;
input averageLength = 30;
input factor = 0.1;
input criticalValue = 10;
input averageType = AverageType.EXPONENTIAL;

def atr = WildersAverage(TrueRange(high,  close,  low), length);
def diff = hlc3 - hlc3[1];
def vp = Sum(if diff > factor * atr then volume else 0, length);
def vn = Sum(if diff < -factor * atr then volume else 0, length);

plot VPN = ExpAverage(100 * (vp - vn) / Sum(volume, length), emaLength);
plot VPNAvg = MovingAverage(averageType, VPN, averageLength);
plot CriticalLevel = criticalValue;

VPN.DefineColor("Above", Color.UPTICK);
VPN.DefineColor("Below", Color.DOWNTICK);
VPN.AssignValueColor(if VPN > CriticalLevel then VPN.Color("Above") else VPN.Color("Below"));
VPNAvg.SetDefaultColor(GetColor(7));
CriticalLevel.SetDefaultColor(GetColor(1));

def VPN_2 = MovAvgExponential(price = VPN, length = Smooth );
def MAVPN = SimpleMovingAvg( VPN_2, MAB );

def LQD = CLOSE > MinC
and SimpleMovingAvg(VOLUME, MinVolAvgLen) > MinVol
and SimpleMovingAvg(CLOSE * VOLUME, MinVolAvgLen) / VolDivisor > MinVC;

SimpleMovingAvg(VOLUME, VolAvgLen) >
SimpleMovingAvg(VOLUME, VolAvgLen)[50];

and VPN crosses above VPNCrit
and RSIVal < RSIMaxVal
and Close > SimpleMovingAvg( Close, Period ) then VPN else double.nan;

plot sell = if VPN crosses below MAVPN
and Close < Highest( Close, 5 )
- 3 * ATR( Period ) then VPN else double.nan;

Second Edit
Removing the BuyCond1 from the buy plot allowed the script to mark some entry points for me on the /es futures. But then again, I'm not worried about liquidity for that particular product.

Last edited:
@jckhoury / @mashume -- Awesome! I'm sure myself and other members of this community will really be eager to explore Katsanos' new indicator. I believe his other indicators have been use by many other traders in the past, and curious to see how this performs!

Below is the correct code from TASC. I added the Bollinger Bands.

You can get TOS codes each month using the following - just change the date each month. It is best to read and understand the indicator from the author before using. TASC is a great investment, been reading it for years.

Code:
declare lower;

input length = 30;
input emaLength = 3;
input averageLength = 30;
input factor = 0.1;
input criticalValue = 10;
input averageType = AverageType.EXPONENTIAL;

def atr = WildersAverage(TrueRange(high,  close,  low), length);
def diff = hlc3 - hlc3[1];
def vp = Sum(if diff > factor * atr then volume else 0, length);
def vn = Sum(if diff < -factor * atr then volume else 0, length);

plot VPN = ExpAverage(100 * (vp - vn) / Sum(volume, length), emaLength);
plot VPNAvg = MovingAverage(averageType, VPN, averageLength);
plot CriticalLevel = criticalValue;

VPN.DefineColor("Above", Color.UPTICK);
VPN.DefineColor("Below", Color.DOWNTICK);
VPN.AssignValueColor(if VPN > CriticalLevel then VPN.Color("Above") else VPN.Color("Below"));
VPNAvg.SetDefaultColor(GetColor(7));
CriticalLevel.SetDefaultColor(GetColor(1));

#Bollinger Bands added by mc01439 on 3.28.2021

input displace = 0;
input bblength = 120;#Hint #Use 4 to 4.5 times indicator lenght
input Num_Dev_Dn = -2.0;
input Num_Dev_up = 2.0;
input averageTypebb = AverageType.Simple;

def sDev = stdev(data = VPN[-displace], length = bblength);

def MidLine = MovingAverage(averageTypebb, data = VPN[-displace], length = bblength);
plot LowerBand = MidLine + num_Dev_Dn * sDev;
plot UpperBand = MidLine + num_Dev_Up * sDev;

LowerBand.SetDefaultColor(GetColor(4));
#MidLine.SetDefaultColor(GetColor(1));
UpperBand.SetDefaultColor(GetColor(4));

Below is the correct code from TASC. I added the Bollinger Bands.

You can get TOS codes each month using the following - just change the date each month. It is best to read and understand the indicator from the author before using. TASC is a great investment, been reading it for years.

Code:
declare lower;

input length = 30;
input emaLength = 3;
input averageLength = 30;
input factor = 0.1;
input criticalValue = 10;
input averageType = AverageType.EXPONENTIAL;

def atr = WildersAverage(TrueRange(high,  close,  low), length);
def diff = hlc3 - hlc3[1];
def vp = Sum(if diff > factor * atr then volume else 0, length);
def vn = Sum(if diff < -factor * atr then volume else 0, length);

plot VPN = ExpAverage(100 * (vp - vn) / Sum(volume, length), emaLength);
plot VPNAvg = MovingAverage(averageType, VPN, averageLength);
plot CriticalLevel = criticalValue;

VPN.DefineColor("Above", Color.UPTICK);
VPN.DefineColor("Below", Color.DOWNTICK);
VPN.AssignValueColor(if VPN > CriticalLevel then VPN.Color("Above") else VPN.Color("Below"));
VPNAvg.SetDefaultColor(GetColor(7));
CriticalLevel.SetDefaultColor(GetColor(1));

#Bollinger Bands added by mc01439 on 3.28.2021

input displace = 0;
input bblength = 120;#Hint #Use 4 to 4.5 times indicator lenght
input Num_Dev_Dn = -2.0;
input Num_Dev_up = 2.0;
input averageTypebb = AverageType.Simple;

def sDev = stdev(data = VPN[-displace], length = bblength);

def MidLine = MovingAverage(averageTypebb, data = VPN[-displace], length = bblength);
plot LowerBand = MidLine + num_Dev_Dn * sDev;
plot UpperBand = MidLine + num_Dev_Up * sDev;

LowerBand.SetDefaultColor(GetColor(4));
#MidLine.SetDefaultColor(GetColor(1));
UpperBand.SetDefaultColor(GetColor(4));
Nice work ! How would you Mod the code so that it only turned green once both lines have past above to filter out false signals?

Below is the correct code from TASC. I added the Bollinger Bands.

You can get TOS codes each month using the following - just change the date each month. It is best to read and understand the indicator from the author before using. TASC is a great investment, been reading it for years.

Code:
declare lower;

input length = 30;
input emaLength = 3;
input averageLength = 30;
input factor = 0.1;
input criticalValue = 10;
input averageType = AverageType.EXPONENTIAL;

def atr = WildersAverage(TrueRange(high,  close,  low), length);
def diff = hlc3 - hlc3[1];
def vp = Sum(if diff > factor * atr then volume else 0, length);
def vn = Sum(if diff < -factor * atr then volume else 0, length);

plot VPN = ExpAverage(100 * (vp - vn) / Sum(volume, length), emaLength);
plot VPNAvg = MovingAverage(averageType, VPN, averageLength);
plot CriticalLevel = criticalValue;

VPN.DefineColor("Above", Color.UPTICK);
VPN.DefineColor("Below", Color.DOWNTICK);
VPN.AssignValueColor(if VPN > CriticalLevel then VPN.Color("Above") else VPN.Color("Below"));
VPNAvg.SetDefaultColor(GetColor(7));
CriticalLevel.SetDefaultColor(GetColor(1));

#Bollinger Bands added by mc01439 on 3.28.2021

input displace = 0;
input bblength = 120;#Hint #Use 4 to 4.5 times indicator lenght
input Num_Dev_Dn = -2.0;
input Num_Dev_up = 2.0;
input averageTypebb = AverageType.Simple;

def sDev = stdev(data = VPN[-displace], length = bblength);

def MidLine = MovingAverage(averageTypebb, data = VPN[-displace], length = bblength);
plot LowerBand = MidLine + num_Dev_Dn * sDev;
plot UpperBand = MidLine + num_Dev_Up * sDev;

LowerBand.SetDefaultColor(GetColor(4));
#MidLine.SetDefaultColor(GetColor(1));
UpperBand.SetDefaultColor(GetColor(4));
Code:
declare lower;

input length = 30;
input emaLength = 3;
input averageLength = 30;
input factor = 0.1;
input criticalValue = 10;
input averageType = AverageType.EXPONENTIAL;

def atr = WildersAverage(TrueRange(high,  close,  low), length);
def diff = hlc3 - hlc3[1];
def vp = Sum(if diff > factor * atr then volume else 0, length);
def vn = Sum(if diff < -factor * atr then volume else 0, length);

plot VPN = ExpAverage(100 * (vp - vn) / Sum(volume, length), emaLength);
plot VPNAvg = MovingAverage(averageType, VPN, averageLength);
plot CriticalLevel = criticalValue;

VPN.DefineColor("Above", Color.UPTICK);
VPN.DefineColor("Below", Color.DOWNTICK);
VPN.AssignValueColor(if VPN > CriticalLevel then VPN.Color("Above") else VPN.Color("Below"));
VPNAvg.SetDefaultColor(GetColor(7));
CriticalLevel.SetDefaultColor(GetColor(1));

#Bollinger Bands added by mc01439 on 3.28.2021

input displace = 0;
input bblength = 120;#Hint #Use 4 to 4.5 times indicator lenght
input Num_Dev_Dn = -2.0;
input Num_Dev_up = 2.0;
input averageTypebb = AverageType.Simple;

def sDev = stdev(data = VPN[-displace], length = bblength);

def MidLine = MovingAverage(averageTypebb, data = VPN[-displace], length = bblength);
plot LowerBand = MidLine + num_Dev_Dn * sDev;
plot UpperBand = MidLine + num_Dev_Up * sDev;

LowerBand.SetDefaultColor(GetColor(4));
#MidLine.SetDefaultColor(GetColor(1));
UpperBand.SetDefaultColor(GetColor(4));

#ARROWS
input arrows1 = No;
input arrows2 = No;
input arrows3 = No;
input DotSize = 3;
plot ArrowDown = if arrows1 and (VPN Crosses below VPNAvg) then VPNAvg else double.nan;
ArrowDown.setpaintingStrategy(paintingStrategy.Arrow_Down);
ArrowDown.setDefaultColor(color.Magenta);
ArrowDown.setLineWeight(dotsize-1);

plot ArrowUp = if arrows1 and (VPN crosses above VPNAvg ) then VPNAvg else double.nan;
ArrowUp.setpaintingStrategy(paintingStrategy.Arrow_Up);
ArrowUp.setDefaultColor(color.Cyan);
ArrowUp.setLineWeight(dotsize-1);

plot ArrowDownb=if arrows2 and (VPN Crosses below CriticalLevel) then CriticalLevel else double.nan;
ArrowDownb.setpaintingStrategy(paintingStrategy.Arrow_Down);
ArrowDownb.setDefaultColor(color.Magenta);
ArrowDownb.setLineWeight(dotsize+1);

plot ArrowUpb = if arrows2 and (VPN crosses above CriticalLevel) then CriticalLevel else double.nan;
ArrowUpb.setpaintingStrategy(paintingStrategy.Arrow_Up);
ArrowUpb.setDefaultColor(color.Cyan);
ArrowUpb.setLineWeight(dotsize+1);

plot ArrowDownc=if arrows3 and (VPN Crosses below UpperBand) then UpperBand else double.nan;
ArrowDownc.setpaintingStrategy(paintingStrategy.Arrow_Down);
ArrowDownc.setDefaultColor(color.Yellow);
ArrowDownc.setLineWeight(dotsize);

plot ArrowUpc = if arrows3 and (VPN crosses above LowerBand) then LowerBand else double.nan;
ArrowUpc.setpaintingStrategy(paintingStrategy.Arrow_Up);
ArrowUpc.setDefaultColor(color.Yellow);
ArrowUpc.setLineWeight(dotsize);

thank you!!

We can take any indicator that can be imagined, code it, redefine it, add features, signals, clouds, bubbles, change the colorization of lines, Color prices, add multi time frame capabilities, create systems and scans.

It just starts with an idea.

Can you give me a scanner for this

Can you give me a scanner for this
If you put it into a custom scan , look for arrowUp equals true

87k+ Posts
411 Online

## The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
• Exclusive indicators
• Proven strategies & setups
• Private Discord community
• Exclusive members-only content
• 1 full year of unlimited support

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?