OBV Histogram with Paintbars for ThinkorSwim

Welkin

Welkin

Member
VIP
I modeled this after playing around with MACD in thinkscript. This script calculates On Balance Volume and applies a fast and slow MA, takes the difference and plots a histogram. also has some lines that plot on the histogram edges that show divergence when price is going up and the OBV is going down and vice versa.

Code:
declare lower;

def NA = Double.NaN;
def POBVC = TotalSum(if close > close[1] then + volume else - volume);
def NOBVC = TotalSum(if close < close[1] then - volume else + volume);
plot WelkinOBVAvgVal = (POBVC + NOBVC) / 2;
#The below commented out plot essentially does the same as the above POBVC and NOBVC (positive and negative calculations and then averaged together), but I've found the above to provide better response signals. swap #'s to test.
#plot WelkinOBVAvgVal = Average(TotalSum(if close > close[1] then + volume else - volume));

WelkinOBVAvgVal.Hide();

input paintbars = no;
input AvgFastLength = 4;
input AvgSlowLength = 9;

def AvgF = Average(WelkinOBVAvgVal, "length" = AvgFastLength);
def AvgS = Average(WelkinOBVAvgVal, "length" = AvgSlowLength);


plot WelkinOBV = AvgF - AvgS;
plot ObvDivergeLine1 = if high < high[1] and WelkinOBV > WelkinOBV[1] then WelkinOBV else NA;
plot ObvDivergeLine2 = if low > low[1] and WelkinOBV < WelkinOBV[1] then WelkinOBV else NA;


plot zeroline = 0;

WelkinOBV.SetPaintingStrategy(PaintingStrategy.SQUARED_HISTOGRAM);

ObvDivergeLine1.SetLineWeight(4);
ObvDivergeLine2.SetLineWeight(4);

WelkinOBV.DefineColor("Positive and Up", Color.GREEN);
WelkinOBV.DefineColor("Positive and Down", Color.DARK_GREEN);
WelkinOBV.DefineColor("Negative and Down", Color.RED);
WelkinOBV.DefineColor("Negative and Up", Color.YELLOW);

WelkinOBV.AssignValueColor(if WelkinOBV >= 0 then if WelkinOBV > WelkinOBV[1] then WelkinOBV.Color("Positive and Up") else WelkinOBV.Color("Positive and Down") else if WelkinOBV < WelkinOBV[1] then WelkinOBV.Color("Negative and Down") else WelkinOBV.Color("Negative and Up"));

AssignPriceColor(if !paintbars then Color.CURRENT else if WelkinOBV >= 0 then if WelkinOBV > WelkinOBV[1] then color.GREEN else  color.DARK_GREEN else if WelkinOBV < WelkinOBV[1] then color.RED else  color.YELLOW);

ObvDivergeLine1.DefineColor("UpDiv", Color.BLUE);
ObvDivergeLine2.DefineColor("DownDiv", Color.DARK_ORANGE);
ObvDivergeLine1.DefineColor("Neutral", Color.GRAY);
ObvDivergeLine2.DefineColor("Neutral", Color.GRAY);

ObvDivergeLine1.AssignValueColor(if high < high[1] and WelkinOBV > WelkinOBV[1] then ObvDivergeLine1.Color("UpDiv") else ObvDivergeLine1.Color("Neutral"));

ObvDivergeLine2.AssignValueColor(if low > low[1] and WelkinOBV < WelkinOBV[1] then ObvDivergeLine2.Color("DownDiv") else ObvDivergeLine2.Color("Neutral"));

zeroline.SetLineWeight(2);

zeroline.SetDefaultColor(Color.GRAY);
http://tos.mx/6OSwy73
 
Last edited:
S

Schminga

New member
@Welkin: Do you, by any chance, have this coded for a Thinkorswim Watchlist (reflecting the various colors of red, yellow and green)?
 
Last edited by a moderator:
S

Schminga

New member
Aloha Sir @Welkin from Hawaii. I will have a look and know that others will also find value in your watchlist contribution. Stay safe and thrive! Mahalo!
 
Welkin

Welkin

Member
VIP
Aloha Sir @Welkin from Hawaii. I will have a look and know that others will also find value in your watchlist contribution. Stay safe and thrive! Mahalo!
Made a quick improvement
save multiple custom quotes with the same code under a different name (obv0,obv1,obv2) etc... make sure the aggregations match(5 min, 30 min, daily or whatever) and edit the first line that says input lookback = 0 to 1,2,3,... for every custom quote you created.
then it should display like this:

make sure the columns are arranged in the correct lookback order..., 4, 3, 2, 1, 0
http://tos.mx/RHrkYBc

Code:
input lookback = 0;

def NA = Double.NaN;
def POBVC = TotalSum(if close > close[1] then + volume else - volume);
def NOBVC = TotalSum(if close < close[1] then - volume else + volume);
def WelkinOBVAvgVal = (POBVC + NOBVC) / 2;

input AvgFastLength = 3;
input AvgSlowLength = 7;

def AvgF = Average(WelkinOBVAvgVal, "length" = AvgFastLength);
def AvgS = Average(WelkinOBVAvgVal, "length" = AvgSlowLength);


def WelkinOBV = AvgF - AvgS;
def ObvDivergeLine1 = if high < high[1] and WelkinOBV > WelkinOBV[1] then WelkinOBV else NA;
def ObvDivergeLine2 = if low > low[1] and WelkinOBV < WelkinOBV[1] then WelkinOBV else NA;

def zeroline = 0;

AddLabel(1, " ", Color.BLACK );

AssignBackgroundColor(if WelkinOBV >= 0 then if WelkinOBV[lookback] > WelkinOBV[1+lookback] then Color.GREEN else Color.DARK_GREEN else if WelkinOBV[lookback] < WelkinOBV[1+lookback] then Color.RED else Color.YELLOW);
 
Last edited:
S

Schminga

New member
Thank you. I liked the first version with the up and down arrows within the color (ie, ... WelkinOBV[1] then "^ "). Should the new version have the same up and down arrows?
 
Welkin

Welkin

Member
VIP
Thank you. I liked the first version with the up and down arrows within the color (ie, ... WelkinOBV[1] then "^ "). Should the new version have the same up and down arrows?
on line 21 replace
Code:
AddLabel(1, " ", Color.BLACK );
with
Code:
AddLabel(1, if WelkinOBV >= 0 then if WelkinOBV[lookback] > WelkinOBV[1+lookback] then "^ " else "v " else if WelkinOBV[lookback] < WelkinOBV[1+lookback] then "v " else "^ ", Color.BLACK );
I've found that it takes a little longer for it to refresh if you use this.
the lime green and yellow are "^" white the dark green and red are "v", so as long as you understand that they really aren't necessary
 

Top