-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathvolume_indicators.py
165 lines (121 loc) · 4.94 KB
/
volume_indicators.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# -*- coding: utf-8 -*-
"""
Created on Sun Nov 22 18:56:14 2020
@author: Benjamin Lee
"""
import pandas as pd
import yfinance as yf
import datetime
import numpy as np
import matplotlib.pyplot as plt
import utils
from scipy import stats
# The following is a class that helps the user create technical indicators for analysis
class volume_indicators():
def __init__(self, data):
self.data = data
def force_index(self):
'''
Force Index
Indicates how strong the actual buying or selling pressure is.
High = Rising Trend
Low = Downward Trend
ref: https://school.stockcharts.com/doku.php?id=technical_indicators:force_index
'''
fi = (self.data.Close - self.data.Close.shift(1)) * self.data.Volume
return utils.ema(fi)
def vwap(self, n):
'''
Volume Weighted Average Price
Is the dollar value of all trading periods divided by total volume of current day
The calculation starts/ends with the market
It is usually used for intraday tading
ref: https://school.stockcharts.com/doku.php?id=technical_indicators:vwap_intraday
'''
# Usual Price
up = (self.data.High + self.data.Low + self.data.Close) / 3
# Usual Volume Price
vup = (up * self.data.Volume)
# Total Volume Price
total_vup = vup.rolling(n).sum()
# Total Voume
tv = self.data.Volume.rolling(n).sum()
return total_vup / tv
def obv(self):
'''
On Balance Volume
Running total of positive and negative volume
ref: https://school.stockcharts.com/doku.php?id=technical_indicators:on_balance_volume_obv
'''
obv = np.where(self.data.Close < self.data.Close.shift(1), -self.data.Volume, self.data.Volume)
return pd.Series(obv, index = self.data.index).cumsum()
def adi(self):
'''
Accumulation Distribution Index
Originally referred as Cumulative Money Flow Line
Calculate money flow multiplier
Multiply by volume
Caculate running sum
ref: https://school.stockcharts.com/doku.php?id=technical_indicators:accumulation_distribution_line
'''
clv = ((self.data.Close - self.data.Low) - (self.data.High - self.data.Close)) / (self.data.High - self.data.Low)
clv = clv.fillna(0.0)
ad = self.data.Volume * clv
return ad.cumsum()
def cmf(self, n):
'''
Chaikin Money Flow
Indicates sum of Money Flow Volume for a specific look-back period
ref: https://school.stockcharts.com/doku.php?id=technical_indicators:chaikin_money_flow_cmf
'''
mfv = ((self.data.Close - self.data.Low) - (self.data.High - self.data.Close)) / (self.data.High - self.data.Low)
mfv = mfv.fillna(0.0)
mfv = mfv * self.data.Volume
return mfv.rolling(n).sum() / self.data.Volume.rolling(n).sum()
def eom(self):
'''
Ease of Movement
Indicates an price change to the volume
Particularly useful for assessing the trend
ref: https://school.stockcharts.com/doku.php?id=technical_indicators:ease_of_movement_emv
'''
distance = ((self.data.High + self.data.Low) / 2) - (self.data.High.diff(1) + self.data.Low.diff(1) / 2)
boxratio = (self.data.Volume / 100000000) / (self.data.High - self.data.Low)
return distance / boxratio
if __name__ == "__main__":
# Download Stock Data
spy = yf.download('SPY', '1990-01-01')
# Initial Indicator object
ta = volume_indicators(spy)
# Get Force Index
fi = ta.force_index()
# Get Volume Weighted Average Price
vwap = ta.vwap(300)
# Get On Balance Volume
obv = ta.obv()
# Get adi
adi = ta.adi()
# Get Chaikin Money Flow
cmf = ta.cmf(300)
# Get Ease of Movment
eom = ta.eom()
ind_data = pd.DataFrame({'spy': spy.Close,
'fi': fi,
'vwap': vwap,
'obv': obv,
'cmf': cmf,
'eom': eom})
plt.hist(spy.Close)
plt.hist(ind_data.fi)
plt.hist(ind_data.vwap)
plt.hist(obv)
plt.hist(adi)
plt.hist(cmf)
plt.hist(eom)
utils.normaltest(spy.Close, 0.05)
utils.normaltest(fi, 0.05)
utils.normaltest(vwap, 0.05)
utils.normaltest(obv, 0.05)
utils.normaltest(adi, 0.05)
utils.normaltest(cmf, 0.05)
utils.normaltest(eom, 0.05)