VWAP Reversals For ThinkOrSwim

wpnet50

New member
VIP
VWAPCrossovers.jpg



It produces decent signals if the market is ranging. Not so much if the market is trending.
May be you can improve it.

# sh_WP_V_MA_VWAP_Crossovers
# Created by WP 8/30/24, used some of the concepts below
# https://usethinkscript.com/threads/moving-average-crossovers-for-thinkorswim.229/
# https://usethinkscript.com/threads/vwap-volume-breakout-indicator-for-thinkorswim.573/
# https://usethinkscript.com/threads/increasing-the-value-of-a-variable.11128/#post-97465
# Prints somewhat confirmed VWAP 2SD reversals arrows based on 5, 9 TEMA corssovers (violet arrows).
# 9/20/24 Changed the reversal conditions a bit
# 10/5/24 Added RTH and volume filters 8/30/24

input valuep = close;
input sfastL = 5;
input fastL = 9;
input medL = 20;
input slowL = 50;
input displace = 0;
input showBreakoutSignals = no;

def na = Double.NaN;

# colors forceIndex moving avarages
DefineGlobalColor("sfast", CreateColor(0,204,102)); # bgreen
DefineGlobalColor("fast", CreateColor(230,138,0)); # dorange
DefineGlobalColor("med", CreateColor(45,123,199)); #BBlue
DefineGlobalColor("slow", CreateColor(51,51,0)); #gary/green

#cloor for VWAP and 1.2 and 2 SD bands
DefineGlobalColor("VWAP1", CreateColor(134,0,179));
DefineGlobalColor("VUB1", CreateColor(204,0,102));
DefineGlobalColor("VLB1", CreateColor(85,128,0));

DefineGlobalColor("VUB2", CreateColor(235,70,153));
DefineGlobalColor("VLB2", CreateColor(132,162,78));

# moving averages
input sfastAV = no;
def sfastA = TEMA(valuep, sfastL); #TripleExpotentialMA
plot SFA = If sfastAV Then sfastA else na;
SFA.SetPaintingStrategy(PaintingStrategy.LINE);
SFA.SetDefaultColor(GlobalColor("sfast"));
SFA.SetLineWeight(1);

input fastAV = no;
def fastA = TEMA(valuep, fastL); #TripleExpotentialMA
plot FAMA1 = If fastAV then fastA else na;
FAMA1.SetPaintingStrategy(PaintingStrategy.LINE);
FAMA1.SetDefaultColor(GlobalColor("fast"));
FAMA1.SetLineWeight(1);

input slowAV = yes;
plot slowA = If slowAV Then ExpAverage(valuep, slowL) else Double.NaN; #MovAvgExponential
slowA.SetPaintingStrategy(PaintingStrategy.LINE);
slowA.SetDefaultColor(GlobalColor("slow"));
slowA.SetLineWeight(2);

input medAV = yes;
plot medA = If medAV Then Average(valuep, medL) else Double.NaN; #SimpleMovingAvg
medA.SetPaintingStrategy(PaintingStrategy.LINE);
medA.SetDefaultColor(GlobalColor("med"));
medA.SetLineWeight(2);
#plot DailyVWAP = vwap(period = AggregationPeriod.DAY);

# Start VWAP
#
input numDevDn = -1.92;
input numDevUp = 1.92;
input numDevDn1 = -1.4;
input numDevUp1 = 1.4;

input timeFrame = {default DAY, WEEK, MONTH};

def cap = getAggregationPeriod();
def errorInAggregation =
timeFrame == timeFrame.DAY and cap >= AggregationPeriod.WEEK or
timeFrame == timeFrame.WEEK and cap >= AggregationPeriod.MONTH;
assert(!errorInAggregation, "timeFrame should be not less than current chart aggregation period");

def yyyyMmDd = getYyyyMmDd();
def periodIndx;
switch (timeFrame) {
case DAY:
periodIndx = yyyyMmDd;
case WEEK:
periodIndx = Floor((daysFromDate(first(yyyyMmDd)) + getDayOfWeek(first(yyyyMmDd))) / 7);
case MONTH:
periodIndx = roundDown(yyyyMmDd / 100, 0);
}
def isPeriodRolled = compoundValue(1, periodIndx != periodIndx[1], yes);

def volumeSum;
def volumeVwapSum;
def volumeVwap2Sum;

if (isPeriodRolled) {
volumeSum = volume;
volumeVwapSum = volume * vwap;
volumeVwap2Sum = volume * Sqr(vwap);
} else {
volumeSum = compoundValue(1, volumeSum[1] + volume, volume);
volumeVwapSum = compoundValue(1, volumeVwapSum[1] + volume * vwap, volume * vwap);
volumeVwap2Sum = compoundValue(1, volumeVwap2Sum[1] + volume * Sqr(vwap), volume * Sqr(vwap));
}
def priceV = volumeVwapSum / volumeSum;
def deviation = Sqrt(Max(volumeVwap2Sum / volumeSum - Sqr(priceV), 0));

plot VWAP = priceV;
VWAP.SetPaintingStrategy(PaintingStrategy.LINE);
VWAP.SetDefaultColor(GlobalColor("VWAP1"));
VWAP.SetLineWeight(1);

plot UpperBand = priceV + numDevUp * deviation;
#UpperBand.SetPaintingStrategy(PaintingStrategy.LINE);
UpperBand.SetStyle(curve.MEDIUM_DASH);
UpperBand.SetDefaultColor(GlobalColor("VUB1"));
UpperBand.SetLineWeight(1);
plot LowerBand = priceV + numDevDn * deviation;
LowerBand.setDefaultColor(GlobalColor("VLB1"));
#LowerBand.SetPaintingStrategy(PaintingStrategy.LINE);
LowerBand.SetStyle(curve.MEDIUM_DASH);
LowerBand.SetLineWeight(1);

def UBpl = no;
def UB1 = priceV + numDevUp1 * deviation;
plot UpperBand1 = If UBpl then UB1 else Double.NaN;
#UpperBand.SetPaintingStrategy(PaintingStrategy.LINE);
UpperBand1.SetStyle(curve.MEDIUM_DASH);
UpperBand1.SetDefaultColor(GlobalColor("VUB2"));
UpperBand1.SetLineWeight(1);

def LBpl = no;
def LB1 = priceV + numDevDn1 * deviation;
plot LowerBand1 = If LBpl then LB1 else Double.NaN;
LowerBand1.setDefaultColor(GlobalColor("VLB2"));
#LowerBand.SetPaintingStrategy(PaintingStrategy.LINE);
LowerBand1.SetStyle(curve.MEDIUM_DASH);
LowerBand1.SetLineWeight(1);

# RTH and Volume filter
def myRTH = secondsFromTime(0945) >= 0 and SecondsTillTime(1545) >= 0;
input length = 5;
def Vol = volume;
def VolAvg = Average(volume, length);
def abVol = Vol > VolAvg;
# Define VWAP 2SD up reversal entry
# close or high in a bullish candle must cross the LowerBand and then the sfastA and fastA moving averages should crossover and align up
# this usually happens in 3-6 periods, a longer period indicates consolidation and a possibillity of continuation (lower) in this case
# define the barNumber of the signal according to the logic presented above and and a period of maximum consolodation (barA <= then 16)
# barA indicates the distance (in periods) from LowerBand crossover to fastA and fastA moving averages crossover and up alignment
DefineGlobalColor("Green1", CreateColor(102,153,0));
def upSH = If high > LowerBand and close > LowerBand and low < LowerBand then BarNumber() else Double.NaN;
def upSH1 = If high[1] > LowerBand[1] and close[1] > LowerBand[1] and low[1] < LowerBand[1] then BarNumber() -1 else Double.NaN;
def upSH2 = If high[2] > LowerBand[2] and close[2] > LowerBand[2] and low[2] < LowerBand[2] then BarNumber() -2 else Double.NaN;
#def upMA = If sfastA > fastA and high > LowerBand and low > ((low[1]+open[1]+close[1])/3) and close > open and high < medA then BarNumber() else Double.NaN;
def upMA = If sfastA > fastA and high > LowerBand and close > LowerBand and high < medA and close > close[1] then BarNumber() else Double.NaN;


#def sUP = If !isNaN(upMA) and barA <= 2 then upMA else Double.NaN;
def sUP = If !isNaN(upMA) and !isNaN(upSH)then upMA else Double.NaN;
def sUP1 = If !isNaN(upMA) and !isNaN(upSH1)then upMA else Double.NaN;
def sUP2 = If !isNaN(upMA) and !isNaN(upSH2)then upMA else Double.NaN;

plot vwDN = if!isNaN(sUP) and myRTH and abVol then low -(5*TickSize()) else na;
vwDN.SetPaintingStrategy(PaintingStrategy.Arrow_UP);
vwDN.SetDefaultColor(GlobalColor("VWAP1"));
vwDN.SetLineWeight(5);
plot vwDN1 = if!isNaN(sUP1) and myRTH and abVol then low - (5*TickSize()) else na;
vwDN1.SetPaintingStrategy(PaintingStrategy.Arrow_UP);
vwDN1.SetDefaultColor(GlobalColor("VWAP1"));
vwDN1.SetLineWeight(5);
plot vwDN2 = if!isNaN(sUP2) and myRTH and abVol then low - (5*TickSize()) else na;
vwDN2.SetPaintingStrategy(PaintingStrategy.Arrow_UP);
vwDN2.SetDefaultColor(GlobalColor("VWAP1"));
vwDN2.SetLineWeight(5);

#AddChartBubble(sUP, low - 0.1, "VB0", GlobalColor("Green1"), no);
#AddChartBubble(sUP1, low - 0.1, "VB1", GlobalColor("Green1"), no);
# Define VWAP 2SD down entry
# First, low in a bearish candle must cross the UpperBand and then sfastA and fastA moving averages should crossover and align down
# This usually happens in 3-6 periods, a longer period indicates consolidation and a possibillity of continuation (upper) in this case
# Define the barNumber of the signal according to the logic presented above and and a period of maximum consolodation (barD <= 16)
# barD indicates the distance (in periods) from UpperBand crossover to fastA and fastA moving averages crossover and down alignment

DefineGlobalColor("Red1", CreateColor(255,26,140));
def dnSH = If low < UpperBand and close < UpperBand and high > UpperBand then BarNumber() else Double.NaN;
def dnSH1 = If low[1] < UpperBand[1] and close[1] < UpperBand[1] and high[1] > UpperBand[1] then BarNumber() -1 else Double.NaN;
def dnSH2 = If low[2] < UpperBand[2] and close[2] < UpperBand[2] and high[2] > UpperBand[2] then BarNumber() -2 else Double.NaN;

def dnMA = If sfastA < fastA and low < UpperBand and close < UpperBand and low > medA and close < close[1] then BarNumber() else Double.NaN;
#def dnMA = If sfastA < fastA and low < UpperBand and high < ((high[1]+open[1]+high[1])/3) and close < UpperBand and low > medA then BarNumber() else Double.NaN;

def sDN = If !isNan(dnMA) and !IsNaN(dnSH) then dnMA else Double.NaN;
def sDN1 = If !isNan(dnMA) and !IsNaN(dnSH1) then dnMA else Double.NaN;
def sDN2 = If !isNan(dnMA) and !IsNaN(dnSH2) then dnMA else Double.NaN;

plot vwUP = if!isNaN(sDN) and myRTH and abVol then high + (5*TickSize()) else na;
vwUP.SetPaintingStrategy(PaintingStrategy.Arrow_DOWN);
vwUP.SetDefaultColor(GlobalColor("VWAP1"));
vwUP.SetLineWeight(5);

plot vwUP1 = if!isNaN(sDN1) and myRTH and abVol then high + (5*TickSize()) else na;
vwUP1.SetPaintingStrategy(PaintingStrategy.Arrow_DOWN);
vwUP1.SetDefaultColor(GlobalColor("VWAP1"));
vwUP1.SetLineWeight(5);

plot vwUP2 = if!isNaN(sDN2) and myRTH and abVol then high + (5*TickSize()) else na;
vwUP2.SetPaintingStrategy(PaintingStrategy.Arrow_DOWN);
vwUP2.SetDefaultColor(GlobalColor("VWAP1"));
vwUP2.SetLineWeight(5);

#AddChartBubble(sDN, high + 0.1, "VS0", GlobalColor("Red1"), yes);
#AddChartBubble(sDN1, high + 0.1, "VS1", GlobalColor("Red1"), yes);
 

Attachments

  • VWAPCrossovers.jpg
    VWAPCrossovers.jpg
    428 KB · Views: 10
Last edited:

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
272 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

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?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top