Mobius Volume Waves

barbaros

Administrator
Staff member
Platform
  1. Thinkorswim
Direct from the author:
A very simple Volume study based on accumulation or distribution. AKA Volume Waves.

Q9cwO7u.png


Code:
# Mobius Volume Wave
# V01.2020
# Plots Volume Waves based on trend.

declare lower;

input n = 6;

DefineGlobalColor("LabelGreen",  CreateColor(0, 165, 0)) ;
def v = volume;
def accumulation = isAscending(HL2, n);
def distribution = isDescending(HL2, n);

plot scan = !distribution ;
scan.hide();

def w = if accumulation and !accumulation[1]
        then v
        else if distribution and !distribution[1]
        then v
        else w[1] + v;
plot waves = w;
     waves.SetPaintingStrategy(PaintingStrategy.Histogram);
     waves.AssignValueColor(if accumulation
                            then GlobalColor("LabelGreen")
                            else if distribution
                            then color.red
                            else color.yellow);
# End Code Mobius Volume Waves

Slight variation, SuperTrend based Volume Waves

sBxYoWq.png


Code:
# Mobius Supertrend Volume Waves
# V01.2020
# Plots Volume Waves based on trend.

declare lower;

input n = 6;
input AvgType = AverageType.HULL;
input ATRmult = .7;
input ColorCandles = yes;
def h = high;
def l = low;
def c = close;
def v = volume;
DefineGlobalColor("Ascending", Color.GREEN);
DefineGlobalColor("descending", Color.RED);
DefineGlobalColor("avg", Color.CYAN);
def ATR = MovingAverage(AvgType, TrueRange(h, c, l), n);
def DN = HL2 + (AtrMult * ATR);
def UP = HL2 + (-AtrMult * ATR);
def cond = if c < cond[1]
           then DN
           else UP;
def accumulation = cond == UP;
def distribution = cond == DN;
def w1 = if accumulation and !accumulation[1]
         then v
         else if accumulation
         then w1[1] + v
         else Double.NaN;
def w2 = if distribution and !distribution[1]
         then v
         else if distribution
         then w2[1] + v
         else Double.NaN;
plot waves1 = w1;
waves1.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
waves1.SetDefaultColor(GlobalColor("Ascending"));
plot waves2 = w2;
waves2.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
waves2.SetDefaultColor(GlobalColor("Descending"));
def SD = StDevAll(v);
plot avg = (HighestAll(w1/2)+highestAll(w2/2))/n ;
avg.SetDefaultColor(GlobalColor("avg"));
AssignPriceColor(if ColorCandles and cond == dn
                 then color.red
                 else color.green);

Latest version with high breakout and label added.
Code:
# Mobius Supertrend Volume Waves
# Plots Volume Waves based on trend.
# 20210127 - barbaros - added high lines for b4indicators.com
# 20210128 - barbaros - added label
# 20210128 - barbaros - clean up

declare lower;

input n = 6;
input AvgType = AverageType.HULL;
input ATRmult = .7;
input ColorCandles = yes;

def h = high;
def l = low;
def c = close;
def v = volume;

DefineGlobalColor("Ascending", Color.GREEN);
DefineGlobalColor("descending", Color.RED);
DefineGlobalColor("avg", Color.CYAN);

def ATR = MovingAverage(AvgType, TrueRange(h, c, l), n);
def DN = HL2 + (AtrMult * ATR);
def UP = HL2 + (-AtrMult * ATR);

def cond = if c < cond[1] then DN else UP;

def accumulation = cond == UP;
def accumulationTrigger = accumulation and !accumulation[1];
def distribution = cond == DN;
def distributionTrigger = distribution and !distribution[1];
def state = if accumulationTrigger then 1
            else if distributionTrigger then -1
            else state[1];

def w1 = if accumulationTrigger then v
         else if accumulation then w1[1] + v
         else Double.NaN;
def w2 = if distributionTrigger then v
         else if distribution then w2[1] + v
         else Double.NaN;
def w = if state == 1 then w1
        else if state == -1 then w2
        else Double.NaN;
def hhLine = if accumulationTrigger or distributionTrigger then w[1] else hhLine[1];
def percPosition = w / hhLine;

plot waves1 = w1;
waves1.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
waves1.SetDefaultColor(GlobalColor("Ascending"));

plot waves2 = w2;
waves2.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
waves2.SetDefaultColor(GlobalColor("Descending"));

plot avg = (HighestAll(w1/2)+highestAll(w2/2))/n ;
avg.SetDefaultColor(GlobalColor("avg"));

plot waveHigh = hhLine;
waveHigh.SetDefaultColor(Color.MAGENTA);
waveHigh.SetLineWeight(2);

AssignPriceColor(if ColorCandles then
                    if cond == dn then color.red
                     else color.green
                 else Color.CURRENT);


AddLabel(yes, if state == 1 then "Accumulation: " + AsPercent(percPosition)
              else if state == -1 then "Distribution: " + AsPercent(percPosition)
              else "Neutral",
              if state == 1 and percPosition >= 1 then Color.GREEN
              else if state == -1 and percPosition >= 1 then Color.RED
              else Color.GRAY);

alert(w1 crosses hhLine, "accumulation", Alert.BAR, Sound.DING);
alert(w2 crosses hhLine, "distribution", Alert.BAR, Sound.DING);
/CODE]
 
Last edited:
  • Like
Reactions: dxk

TraderRich

New member
@barbaros I came looking for help on this exact indicator which I am already using, with the exception that mine has an "Average Volume Line" which is very static (doesn't move much throughout the day) which I don't find useful with my present trading style.

However, I have noticed that when the volume wave histogram is higher than the previous move in the direction of the trend you have much better entries. Would it be possible to add a dynamic line to the Volume Waves much like the horizontal price line on our upper charts that moves as the volume bars go up or down so that we can judge if volume is making a "bigger push" than the previous move?
 

barbaros

Administrator
Staff member
@TraderRich I think I understand what you are wanting to do. Correct me if I am wrong. You want to have a line that highlights the high's of the previous move and if the current move goes over, it would be more significant. Is this correct?
 

TraderRich

New member
@TraderRich I think I understand what you are wanting to do. Correct me if I am wrong. You want to have a line that highlights the high's of the previous move and if the current move goes over, it would be more significant. Is this correct?
I think we are the same page. I'm thinking a line that "floats" above the histogram so that we know if the histogram is higher than the previous move
 

barbaros

Administrator
Staff member
I think we are the same page. I'm thinking a line that "floats" above the histogram so that we know if the histogram is higher than the previous move
Magenta line shows the previous high. Is this what you are looking for?
gEAXYdR.png

Code:
# Mobius Supertrend Volume Waves
# V01.2020
# Plots Volume Waves based on trend.
# 20210127 - barbaros - added high lines for b4indicators.com

declare lower;

input n = 6;
input AvgType = AverageType.HULL;
input ATRmult = .7;
input ColorCandles = yes;
def h = high;
def l = low;
def c = close;
def v = volume;
DefineGlobalColor("Ascending", Color.GREEN);
DefineGlobalColor("descending", Color.RED);
DefineGlobalColor("avg", Color.CYAN);
def ATR = MovingAverage(AvgType, TrueRange(h, c, l), n);
def DN = HL2 + (AtrMult * ATR);
def UP = HL2 + (-AtrMult * ATR);
def cond = if c < cond[1]
           then DN
           else UP;
def accumulation = cond == UP;
def distribution = cond == DN;
def w1 = if accumulation and !accumulation[1]
         then v
         else if accumulation
         then w1[1] + v
         else Double.NaN;
def w2 = if distribution and !distribution[1]
         then v
         else if distribution
         then w2[1] + v
         else Double.NaN;
def hh1 = if !isNaN(w1) and isNaN(w1[1]) then w1
          else if w1 > hh1[1] then w1
          else hh1[1];
def hh2 = if !isNaN(w2) and isNaN(w2[1]) then w2
          else if w2 > hh2[1] then w2
          else hh2[1];
def hhLine = if BarNumber() == 1 then 0
             else if isNaN(w1) and !isNaN(w1[1]) then hh1[1]
             else if isNaN(w2) and !isNaN(w2[1]) then hh2[1]
             else hhLine[1];
plot waves1 = w1;
waves1.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
waves1.SetDefaultColor(GlobalColor("Ascending"));
plot waves2 = w2;
waves2.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
waves2.SetDefaultColor(GlobalColor("Descending"));
def SD = StDevAll(v);
plot avg = (HighestAll(w1/2)+highestAll(w2/2))/n ;
avg.SetDefaultColor(GlobalColor("avg"));
AssignPriceColor(if ColorCandles and cond == dn
                 then color.red
                 else color.green);
plot waveHigh = hhLine;
waveHigh.SetDefaultColor(Color.MAGENTA);
waveHigh.SetLineWeight(3);
 

barbaros

Administrator
Staff member
with alerts

Code:
# Mobius Supertrend Volume Waves
# V01.2020
# Plots Volume Waves based on trend.
# 20210127 - barbaros - added high lines for b4indicators.com

declare lower;

input n = 6;
input AvgType = AverageType.HULL;
input ATRmult = .7;
input ColorCandles = yes;
def h = high;
def l = low;
def c = close;
def v = volume;
DefineGlobalColor("Ascending", Color.GREEN);
DefineGlobalColor("descending", Color.RED);
DefineGlobalColor("avg", Color.CYAN);
def ATR = MovingAverage(AvgType, TrueRange(h, c, l), n);
def DN = HL2 + (AtrMult * ATR);
def UP = HL2 + (-AtrMult * ATR);
def cond = if c < cond[1]
           then DN
           else UP;
def accumulation = cond == UP;
def distribution = cond == DN;
def w1 = if accumulation and !accumulation[1]
         then v
         else if accumulation
         then w1[1] + v
         else Double.NaN;
def w2 = if distribution and !distribution[1]
         then v
         else if distribution
         then w2[1] + v
         else Double.NaN;
def hh1 = if !isNaN(w1) and isNaN(w1[1]) then w1
          else if w1 > hh1[1] then w1
          else hh1[1];
def hh2 = if !isNaN(w2) and isNaN(w2[1]) then w2
          else if w2 > hh2[1] then w2
          else hh2[1];
def hhLine = if BarNumber() == 1 then 0
             else if isNaN(w1) and !isNaN(w1[1]) then hh1[1]
             else if isNaN(w2) and !isNaN(w2[1]) then hh2[1]
             else hhLine[1];
plot waves1 = w1;
waves1.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
waves1.SetDefaultColor(GlobalColor("Ascending"));
plot waves2 = w2;
waves2.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
waves2.SetDefaultColor(GlobalColor("Descending"));
def SD = StDevAll(v);
plot avg = (HighestAll(w1/2)+highestAll(w2/2))/n ;
avg.SetDefaultColor(GlobalColor("avg"));
AssignPriceColor(if ColorCandles and cond == dn
                 then color.red
                 else color.green);
plot waveHigh = hhLine;
waveHigh.SetDefaultColor(Color.MAGENTA);
waveHigh.SetLineWeight(3);

alert(w1 crosses hhLine, "accumulation", Alert.BAR, Sound.DING);
alert(w2 crosses hhLine, "distribution", Alert.BAR, Sound.DING);
 

barbaros

Administrator
Staff member
Added a label.

Code:
# Mobius Supertrend Volume Waves
# V01.2020
# Plots Volume Waves based on trend.
# 20210127 - barbaros - added high lines for b4indicators.com
# 20210128 - barbaros - added label

declare lower;

input n = 6;
input AvgType = AverageType.HULL;
input ATRmult = .7;
input ColorCandles = yes;
def h = high;
def l = low;
def c = close;
def v = volume;
DefineGlobalColor("Ascending", Color.GREEN);
DefineGlobalColor("descending", Color.RED);
DefineGlobalColor("avg", Color.CYAN);
def ATR = MovingAverage(AvgType, TrueRange(h, c, l), n);
def DN = HL2 + (AtrMult * ATR);
def UP = HL2 + (-AtrMult * ATR);
def cond = if c < cond[1]
           then DN
           else UP;
def accumulation = cond == UP;
def distribution = cond == DN;
def w1 = if accumulation and !accumulation[1]
         then v
         else if accumulation
         then w1[1] + v
         else Double.NaN;
def w2 = if distribution and !distribution[1]
         then v
         else if distribution
         then w2[1] + v
         else Double.NaN;
def hh1 = if !isNaN(w1) and isNaN(w1[1]) then w1
          else if w1 > hh1[1] then w1
          else hh1[1];
def hh2 = if !isNaN(w2) and isNaN(w2[1]) then w2
          else if w2 > hh2[1] then w2
          else hh2[1];
def hhLine = if BarNumber() == 1 then 0
             else if isNaN(w1) and !isNaN(w1[1]) then hh1[1]
             else if isNaN(w2) and !isNaN(w2[1]) then hh2[1]
             else hhLine[1];
plot waves1 = w1;
waves1.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
waves1.SetDefaultColor(GlobalColor("Ascending"));
plot waves2 = w2;
waves2.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
waves2.SetDefaultColor(GlobalColor("Descending"));
def SD = StDevAll(v);
plot avg = (HighestAll(w1/2)+highestAll(w2/2))/n ;
avg.SetDefaultColor(GlobalColor("avg"));
AssignPriceColor(if ColorCandles and cond == dn
                 then color.red
                 else color.green);
plot waveHigh = hhLine;
waveHigh.SetDefaultColor(Color.MAGENTA);
waveHigh.SetLineWeight(2);

alert(w1 crosses hhLine, "accumulation", Alert.BAR, Sound.DING);
alert(w2 crosses hhLine, "distribution", Alert.BAR, Sound.DING);

def w = if !isNaN(w1) then w1 else if !isNaN(w2) then w2 else Double.NaN;
AddLabel(yes, if !isNaN(w1) then "Accumulation" else if !isNaN(w2) then "Distribution" else "Neutral",
              if w >= waveHigh then Color.WHITE else Color.GRAY);
 

Keith_J

New member
Added a label.

Code:
# Mobius Supertrend Volume Waves
# V01.2020
# Plots Volume Waves based on trend.
# 20210127 - barbaros - added high lines for b4indicators.com
# 20210128 - barbaros - added label

declare lower;

input n = 6;
input AvgType = AverageType.HULL;
input ATRmult = .7;
input ColorCandles = yes;
def h = high;
def l = low;
def c = close;
def v = volume;
DefineGlobalColor("Ascending", Color.GREEN);
DefineGlobalColor("descending", Color.RED);
DefineGlobalColor("avg", Color.CYAN);
def ATR = MovingAverage(AvgType, TrueRange(h, c, l), n);
def DN = HL2 + (AtrMult * ATR);
def UP = HL2 + (-AtrMult * ATR);
def cond = if c < cond[1]
           then DN
           else UP;
def accumulation = cond == UP;
def distribution = cond == DN;
def w1 = if accumulation and !accumulation[1]
         then v
         else if accumulation
         then w1[1] + v
         else Double.NaN;
def w2 = if distribution and !distribution[1]
         then v
         else if distribution
         then w2[1] + v
         else Double.NaN;
def hh1 = if !isNaN(w1) and isNaN(w1[1]) then w1
          else if w1 > hh1[1] then w1
          else hh1[1];
def hh2 = if !isNaN(w2) and isNaN(w2[1]) then w2
          else if w2 > hh2[1] then w2
          else hh2[1];
def hhLine = if BarNumber() == 1 then 0
             else if isNaN(w1) and !isNaN(w1[1]) then hh1[1]
             else if isNaN(w2) and !isNaN(w2[1]) then hh2[1]
             else hhLine[1];
plot waves1 = w1;
waves1.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
waves1.SetDefaultColor(GlobalColor("Ascending"));
plot waves2 = w2;
waves2.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
waves2.SetDefaultColor(GlobalColor("Descending"));
def SD = StDevAll(v);
plot avg = (HighestAll(w1/2)+highestAll(w2/2))/n ;
avg.SetDefaultColor(GlobalColor("avg"));
AssignPriceColor(if ColorCandles and cond == dn
                 then color.red
                 else color.green);
plot waveHigh = hhLine;
waveHigh.SetDefaultColor(Color.MAGENTA);
waveHigh.SetLineWeight(2);

alert(w1 crosses hhLine, "accumulation", Alert.BAR, Sound.DING);
alert(w2 crosses hhLine, "distribution", Alert.BAR, Sound.DING);

def w = if !isNaN(w1) then w1 else if !isNaN(w2) then w2 else Double.NaN;
AddLabel(yes, if !isNaN(w1) then "Accumulation" else if !isNaN(w2) then "Distribution" else "Neutral",
              if w >= waveHigh then Color.WHITE else Color.GRAY);
The "AssignPriceColor" statement will show green if cond == up, regardless if ColorCandles is yes or no.

AssignPriceColor(if ColorCandles and cond == dn
then color.red
else color.green);

I made the following adjustment for your review. There is probably a better way to do this but this was quick and easy.

AssignPriceColor(if ColorCandles and cond == dn
then color.red
else if ColorCandles and cond == up then color.green
else color.current);
 

barbaros

Administrator
Staff member
The "AssignPriceColor" statement will show green if cond == up, regardless if ColorCandles is yes or no.

AssignPriceColor(if ColorCandles and cond == dn
then color.red
else color.green);

I made the following adjustment for your review. There is probably a better way to do this but this was quick and easy.

AssignPriceColor(if ColorCandles and cond == dn
then color.red
else if ColorCandles and cond == up then color.green
else color.current);
good catch.
 

barbaros

Administrator
Staff member
Here is more clean up
Code:
# Mobius Supertrend Volume Waves
# Plots Volume Waves based on trend.
# 20210127 - barbaros - added high lines for b4indicators.com
# 20210128 - barbaros - added label
# 20210128 - barbaros - clean up

declare lower;

input n = 6;
input AvgType = AverageType.HULL;
input ATRmult = .7;
input ColorCandles = yes;

def h = high;
def l = low;
def c = close;
def v = volume;

DefineGlobalColor("Ascending", Color.GREEN);
DefineGlobalColor("descending", Color.RED);
DefineGlobalColor("avg", Color.CYAN);

def ATR = MovingAverage(AvgType, TrueRange(h, c, l), n);
def DN = HL2 + (AtrMult * ATR);
def UP = HL2 + (-AtrMult * ATR);

def cond = if c < cond[1] then DN else UP;

def accumulation = cond == UP;
def accumulationTrigger = accumulation and !accumulation[1];
def distribution = cond == DN;
def distributionTrigger = distribution and !distribution[1];
def state = if accumulationTrigger then 1 
            else if distributionTrigger then -1
            else state[1];

def w1 = if accumulationTrigger then v
         else if accumulation then w1[1] + v
         else Double.NaN;
def w2 = if distributionTrigger then v
         else if distribution then w2[1] + v
         else Double.NaN;
def w = if state == 1 then w1 
        else if state == -1 then w2 
        else Double.NaN;
def hhLine = if accumulationTrigger or distributionTrigger then w[1] else hhLine[1];
def percPosition = w / hhLine;

plot waves1 = w1;
waves1.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
waves1.SetDefaultColor(GlobalColor("Ascending"));

plot waves2 = w2;
waves2.SetPaintingStrategy(PaintingStrategy.HISTOGRAM);
waves2.SetDefaultColor(GlobalColor("Descending"));

plot avg = (HighestAll(w1/2)+highestAll(w2/2))/n ;
avg.SetDefaultColor(GlobalColor("avg"));

plot waveHigh = hhLine;
waveHigh.SetDefaultColor(Color.MAGENTA);
waveHigh.SetLineWeight(2);

AssignPriceColor(if ColorCandles then 
                    if cond == dn then color.red
                     else color.green
                 else Color.CURRENT);


AddLabel(yes, if state == 1 then "Accumulation: " + AsPercent(percPosition)
              else if state == -1 then "Distribution: " + AsPercent(percPosition)
              else "Neutral",
              if state == 1 and percPosition >= 1 then Color.GREEN 
              else if state == -1 and percPosition >= 1 then Color.RED
              else Color.GRAY);

alert(w1 crosses hhLine, "accumulation", Alert.BAR, Sound.DING);
alert(w2 crosses hhLine, "distribution", Alert.BAR, Sound.DING);
 
Last edited:

TraderRich

New member
@barbaros Awesome...this is what I was looking for. I traded my 10 tick charts today using your first version and my theory was largely correct, that if volume makes a higher move than the previous move you have a valid trade
 

barbaros

Administrator
Staff member
@barbaros Awesome...this is what I was looking for. I traded my 10 tick charts today using your first version and my theory was largely correct, that if volume makes a higher move than the previous move you have a valid trade
Excellent. I'm glad to hear it. Do you find tick charts working better than minute charts?
 

TraderRich

New member
Excellent. I'm glad to hear it. Do you find tick charts working better than minute charts?
I think Tick charts (whether you are trading range ticks or volume ticks) are much more reliable than time based candles for the following reasons:
1.) Reduces noise
2.) Easier to analyze when back testing...say you are looking at a 3m chart and you see an entry at 10am, well that candle didn't actually close until 10:03...the move may have been over and then you are trading into the end of the run

Why do we want to be in a trade just because you moved a little around the sun, shouldn't we be looking at a trade based on the movement of the market instead?

I've got a really consistent set up, but one aspect of it involves a BTD indicator...I believe you have BTD and I'd be willing to go over my chart with you, and perhaps you could duplicate this small aspect of the overall indicator for use on B4
 

barbaros

Administrator
Staff member
I think Tick charts (whether you are trading range ticks or volume ticks) are much more reliable than time based candles for the following reasons:
1.) Reduces noise
2.) Easier to analyze when back testing...say you are looking at a 3m chart and you see an entry at 10am, well that candle didn't actually close until 10:03...the move may have been over and then you are trading into the end of the run

Why do we want to be in a trade just because you moved a little around the sun, shouldn't we be looking at a trade based on the movement of the market instead?

I've got a really consistent set up, but one aspect of it involves a BTD indicator...I believe you have BTD and I'd be willing to go over my chart with you, and perhaps you could duplicate this small aspect of the overall indicator for use on B4
Sure. Let me know and we can connect on Discord.

By the way, BTD indicator is not original work of the author. It is freely available to anyone. It is pretty much a name branding.
 

apuwdb12

New member
Sure. Let me know and we can connect on Discord.

By the way, BTD indicator is not original work of the author. It is freely available to anyone. It is pretty much a name branding.
do you mind sharing the name of the “original” btd script that is available for free..
 
Top