Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Calculating stocks's On Balance Volume (OBV) in python

Tags:

python

pandas

I am doing my first project in python. I have a pandas dataframe called df with two columns "close" and "volume". I want to calculate/obtain OBV column based on first two columns. The formula is given below;

If the close is above the prior close then: Current OBC = Previous OBC + Current Volume

If the closing price is below the prior close price then: Current OBV = Previous OBV - Current Volume

If the closing prices equals the prior close price then: Current OBV = Previous OBV (no change)

close volume  OBC
30    2500    nan
32    3000    5500
25    2700    2800
35    4000    6800
20    1000    5800

I am using this code:

for i in df.close[1:]:
    if i > df.close.shift(-1):
        df["OBC"] = df.volume + df.OBC.shift(-1) 
    elif i < df.close.shift(-1):
        df["OBC"] = df.OBC.shift(-1) - df.volume
    else:
        df["OBC"] = df.OBC

and i get this error:

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

I have looked at this question but didn't get any help. Truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all()

Beyond this error, I feel that code may run into trouble in calculating correct OBV. Any help will be of great value.

like image 837
user113321 Avatar asked Sep 11 '25 13:09

user113321


2 Answers

I'm basing this on Olli's answer, but I think it's a slightly cleaner solution:

obv = (np.sign(df['close'].diff()) * df['volume']).fillna(0).cumsum()
like image 166
SuperCodeBrah Avatar answered Sep 13 '25 02:09

SuperCodeBrah


I dont know why you are getting the error but here is a solution to get OBV:

np.where(df['close'] > df['close'].shift(1), df['volume'], 
np.where(df['close'] < df['close'].shift(1), -df['volume'], 0)).cumsum()

It is also faster, which is good if you are gonna do many iterations!

like image 25
Olli Avatar answered Sep 13 '25 03:09

Olli