input timeFrame = {MINUTE, MIN2, MIN3, MIN5, MIN10, MIN15, MIN20, MIN30, MIN45, HOUR, TWOHOUR, FOURHOUR, default DAY, WEEK, MONTH, CHART};
input num1stDevUp = 1.0;
def num1stDevDn   = -num1stDevUp;
input multiplier  = 1;#Hint multiplier: Change to +/- number of "Days", "Weeks", etc
input lines       = {limited_curve, default limited_horizontal, full_curve};
def cap = GetAggregationPeriod();
def errorInAggregation =
    timeFrame == timeFrame.DAY and cap >= AggregationPeriod.WEEK or
    timeFrame == timeFrame.WEEK and cap >= AggregationPeriod.MONTH;
Assert(!errorInAggregation, "vwap timeFrame should be not less than current chart aggregation period");
def yyyyMmDd = GetYYYYMMDD();
def periodIndx;
def seconds = SecondsFromTime(0);
def day_number = DaysFromDate(First(yyyyMmDd)) + GetDayOfWeek(First(yyyyMmDd));
switch (timeFrame) {
case MINUTE:
    periodIndx = Floor(seconds / 60 + day_number * 24 * 60);
case MIN2:
    periodIndx = Floor(seconds / 120 + day_number * 24);
case MIN3:
    periodIndx = Floor(seconds / 180 + day_number * 24);
case MIN5:
    periodIndx = Floor(seconds / 300 + day_number * 24);
case MIN10:
    periodIndx = Floor(seconds / 600 + day_number * 24);
case MIN15:
    periodIndx = Floor(seconds / 900 + day_number * 24);
case MIN20:
    periodIndx = Floor(seconds / 1200 + day_number * 24);
case MIN30:
    periodIndx = Floor(seconds / 1800 + day_number * 24);
case MIN45:
    periodIndx = Floor(seconds / 2700 + day_number * 24);
case HOUR:
    periodIndx = Floor(seconds / 3600 + day_number * 24);
case TWOHOUR:
    periodIndx = Floor(seconds / 7200 + day_number * 24);
case FOURHOUR:
    periodIndx = Floor(seconds / 14400 + day_number * 24);
case DAY:
    periodIndx = CountTradingDays(Min(First(yyyyMmDd), yyyyMmDd), yyyyMmDd) - 1;
case WEEK:
    periodIndx = Floor((DaysFromDate(First(yyyyMmDd)) + GetDayOfWeek(First(yyyyMmDd))) / 7);
case MONTH:
    periodIndx = RoundDown(yyyyMmDd / 100, 0);
case CHART:
    periodIndx = 0;
}
def countindx = CompoundValue(1, if periodIndx != periodIndx[1] then (countindx[1] + periodIndx - periodIndx[1]) % multiplier else countindx[1], 0);
def isPeriodRolled = countindx < countindx[1] + periodIndx - periodIndx[1];
#def isPeriodRolled = CompoundValue(1, periodIndx != periodIndx[1], yes);
input num_vwap_displayed = 1;
def Count = num_vwap_displayed;
def cond = if isPeriodRolled
           then 1
           else Double.NaN;
def dataCount = CompoundValue(1, if !IsNaN(cond)
                                 then dataCount[1] + 1
                                 else dataCount[1], 0);
rec volumeSum;
rec volumeVwapSum;
rec 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 price = volumeVwapSum / volumeSum;
def deviation = Sqrt(Max(volumeVwap2Sum / volumeSum - Sqr(price), 0));
rec v  = if IsNaN(vwap) then v[1] else price;
rec v1 = if IsNaN(vwap) then v1[1] else price + num1stDevUp * deviation;
rec v2 = if IsNaN(vwap) then v2[1] else price - num1stDevUp * deviation;
plot VWAP;
plot FirstUpperBand;
plot FirstLowerBand;
input showlineinchartlength = 31;
input showlines = yes;
if (!errorInAggregation) and
    lines == lines.limited_curve {
    VWAP =  if IsNaN(close[-showlineinchartlength]) and
                              HighestAll(dataCount) - dataCount <= Count - 1
                      then v
                      else Double.NaN ;
    FirstUpperBand  = if IsNaN(close[-showlineinchartlength]) and
                         HighestAll(dataCount) - dataCount <= Count - 1
                      then v1
                      else Double.NaN ;
    FirstLowerBand  = if IsNaN(close[-showlineinchartlength]) and
                         HighestAll(dataCount) - dataCount <= Count - 1
                      then v2
                      else Double.NaN ;
} else if (!errorInAggregation) and
           lines == lines.full_curve {
    VWAP =            v;
    FirstUpperBand  = v1;
    FirstLowerBand  = v2;
} else if (!errorInAggregation) and
           lines == lines.limited_horizontal and IsNaN(close[-showlineinchartlength]) {
    VWAP = HighestAll(if IsNaN(close) then v else Double.NaN );
    FirstUpperBand  = HighestAll(if IsNaN(close) then v1 else Double.NaN );
    FirstLowerBand  = HighestAll(if IsNaN(close) then v2 else Double.NaN );
} else {
    VWAP = Double.NaN;
    FirstUpperBand  = Double.NaN;
    FirstLowerBand  = Double.NaN;
}
VWAP.SetDefaultColor(Color.magenta);
FirstUpperBand.SetDefaultColor(Color.cyan);
FirstLowerBand.SetDefaultColor(Color.cyan);
VWAP.SetPaintingStrategy(PaintingStrategy.LINE);
FirstUpperBand.SetStyle(Curve.SHORT_DASH);
FirstLowerBand.SetStyle(Curve.SHORT_DASH);
VWAP.SetLineWeight(2);
FirstUpperBand.SetLineWeight(1);
FirstLowerBand.SetLineWeight(1);
VWAP.HideBubble();
FirstUpperBand.HideBubble();
FirstLowerBand.HideBubble();
FirstUpperBand.sethiding(!showlines);
FirstLowerBand.sethiding(!showlines);
input showbubblesLine = yes;
input showbubblesVSTD = yes;
input bubblemoverVWAP_Labels = 15;#Hint bubblemoverVWAP_Labels: Number of Spaces bubble offset in expansion area
def n = bubblemoverVWAP_Labels;
def n1 = n + 1;
AddChartBubble(showbubblesLine and IsNaN(close[n]) and !IsNaN(close[n1]) ,
               price[n1] ,
              "V:" + Round(price[n1] , 2),
               Color.ORANGE);
AddChartBubble(showbubblesLine and IsNaN(close[n]) and !IsNaN(close[n1]) ,
               price[n1] + num1stDevUp * deviation[n1] ,
              "V1:" + Round((price[n1] + num1stDevUp * deviation[n1]), 2),
               Color.GREEN);
AddChartBubble(showbubblesLine and IsNaN(close[n]) and !IsNaN(close[n1]) ,
               price[n1] + num1stDevDn * deviation[n1] ,
              "V1:" + Round(price[n1] + num1stDevDn * deviation[n1], 2),
               Color.RED);
input showclouds = yes;
def green = if close > VWAP
            then 1
            else if green[1] == 1 and high >= VWAP
            then 1
            else 0;
def g = green;
AddCloud(if showclouds and g
         then FirstUpperBand
         else Double.NaN,
         VWAP,
         Color.Light_green, Color.Light_green);
AddCloud(if showclouds and g
         then FirstUpperBand
         else Double.NaN,
         VWAP,
         Color.Light_green, Color.Light_green);
AddCloud(if showclouds and !g
         then VWAP
         else Double.NaN,
         FirstLowerBand,
         Color.PINK, Color.PINK);