Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add vwap stdev bands indicator #220

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion ta/momentum.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"""
import numpy as np
import pandas as pd

from ta.utils import IndicatorMixin, _ema


Expand Down
1 change: 0 additions & 1 deletion ta/others.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"""
import numpy as np
import pandas as pd

from ta.utils import IndicatorMixin


Expand Down
1 change: 0 additions & 1 deletion ta/trend.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"""
import numpy as np
import pandas as pd

from ta.utils import IndicatorMixin, _ema, _get_min_max, _sma


Expand Down
1 change: 0 additions & 1 deletion ta/volatility.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
"""
import numpy as np
import pandas as pd

from ta.utils import IndicatorMixin


Expand Down
61 changes: 55 additions & 6 deletions ta/volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@

"""

from typing import List

import numpy as np
import pandas as pd

from ta.utils import IndicatorMixin, _ema


Expand Down Expand Up @@ -423,6 +424,7 @@ class VolumeWeightedAveragePrice(IndicatorMixin):
volume(pandas.Series): dataset 'Volume' column.
window(int): n period.
fillna(bool): if True, fill nan values.
custom_typical_price(pandas.Series): custom typical price.

Returns:
pandas.Series: New feature generated.
Expand All @@ -436,21 +438,27 @@ def __init__(
volume: pd.Series,
window: int = 14,
fillna: bool = False,
custom_typical_price: pd.Series = None,
):
self._high = high
self._low = low
self._close = close
self._volume = volume
self._window = window
self._fillna = fillna
self._custom_typical_price = custom_typical_price
self._run()

def _run(self):
# 1 typical price
typical_price = (self._high + self._low + self._close) / 3.0
self._typical_price = (
self._custom_typical_price
if self._custom_typical_price is not None
else (self._high + self._low + self._close) / 3.0
)

# 2 typical price * volume
typical_price_volume = typical_price * self._volume
typical_price_volume = self._typical_price * self._volume

# 3 total price * volume
min_periods = 0 if self._fillna else self._window
Expand All @@ -459,9 +467,11 @@ def _run(self):
).sum()

# 4 total volume
total_volume = self._volume.rolling(self._window, min_periods=min_periods).sum()
self._total_volume = self._volume.rolling(
self._window, min_periods=min_periods
).sum()

self.vwap = total_pv / total_volume
self.vwap = total_pv / self._total_volume

def volume_weighted_average_price(self) -> pd.Series:
"""Volume Weighted Average Price (VWAP)
Expand All @@ -472,6 +482,37 @@ def volume_weighted_average_price(self) -> pd.Series:
vwap = self._check_fillna(self.vwap)
return pd.Series(vwap, name=f"vwap_{self._window}")

def stdev_bands(
self,
bands: list,
) -> List[pd.Series]:
"""VWAP Standard Deviation Bands

Args:
bands(Sequence): list of N's where N denotes deviations count.

Returns:
Sequence(pandas.Series): list of new features.
"""
if not bands:
bands = [2, -2]

volume_sqr_vwap = self._volume * self._typical_price.pow(2)
min_periods = 0 if self._fillna else self._window
volume_sqr_vwap_sum = volume_sqr_vwap.rolling(
self._window, min_periods=min_periods
).sum()
sqr_price = volume_sqr_vwap_sum / self._total_volume - self.vwap.pow(2)
sqr_price = sqr_price.clip(0.0)
deviation = sqr_price.pow(1 / 2.0)

band_series = [self._check_fillna(self.vwap + n * deviation) for n in bands]
result = [
band.rename(f"vwap_{self._window}_{bands[i]}stdev")
for i, band in enumerate(band_series)
]
return result


def acc_dist_index(high, low, close, volume, fillna=False):
"""Accumulation/Distribution Index (ADI)
Expand Down Expand Up @@ -711,6 +752,7 @@ def volume_weighted_average_price(
volume: pd.Series,
window: int = 14,
fillna: bool = False,
custom_typical_price: pd.Series = None,
):
"""Volume Weighted Average Price (VWAP)

Expand All @@ -729,12 +771,19 @@ def volume_weighted_average_price(
volume(pandas.Series): dataset 'Volume' column.
window(int): n period.
fillna(bool): if True, fill nan values.
custom_typical_price(pandas.Series): custom typical price.

Returns:
pandas.Series: New feature generated.
"""

indicator = VolumeWeightedAveragePrice(
high=high, low=low, close=close, volume=volume, window=window, fillna=fillna
high=high,
low=low,
close=close,
volume=volume,
window=window,
fillna=fillna,
custom_typical_price=custom_typical_price,
)
return indicator.volume_weighted_average_price()
1 change: 0 additions & 1 deletion ta/wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"""

import pandas as pd

from ta.momentum import (
AwesomeOscillatorIndicator,
KAMAIndicator,
Expand Down
62 changes: 31 additions & 31 deletions test/data/cs-vwap.csv
Original file line number Diff line number Diff line change
@@ -1,31 +1,31 @@
,Date,High,Low,Close,Typical Price,Volume,vwap
0,3-Dec-10,24.8283,24.3205,24.7486,24.63247,18730.144,24.632466666666662
1,6-Dec-10,24.7586,24.5993,24.7088,24.6889,12271.74,24.654805154030853
2,7-Dec-10,25.1568,24.7785,25.0373,24.99087,24691.414,24.80379676048873
3,8-Dec-10,25.5848,24.9477,25.545,25.359170000000002,18357.606,24.941475861906202
4,9-Dec-10,25.6844,24.8083,25.0672,25.186629999999997,22964.08,24.999506235713717
5,10-Dec-10,25.336,25.0572,25.107,25.166729999999998,15918.948,25.023078243028557
6,13-Dec-10,25.2862,24.8482,24.888,25.00747,16067.044,25.021133824528068
7,14-Dec-10,25.1269,24.7496,24.9975,24.958000000000002,16568.487,25.013948032058988
8,15-Dec-10,25.2762,24.9278,25.0473,25.08377,16018.729,25.02086936568546
9,16-Dec-10,25.3857,25.0274,25.336,25.2497,9773.569,25.033920655429075
10,17-Dec-10,25.5351,25.0473,25.0572,25.2132,22572.712000000003,25.054787605744547
11,20-Dec-10,25.6048,25.0622,25.4455,25.370829999999998,12986.669,25.074623090960745
12,21-Dec-10,25.7441,25.5351,25.5649,25.6147,10906.659,25.10166479387297
13,22-Dec-10,25.7242,25.4554,25.555,25.5782,5799.259,25.11402265022072
14,23-Dec-10,25.6744,25.2862,25.4057,25.45543,7395.274,25.168402599215423
15,27-Dec-10,25.4455,25.1667,25.3658,25.326,5818.161999999999,25.201444302952908
16,28-Dec-10,25.3161,24.9178,25.0373,25.0904,7164.726,25.224830276069333
17,29-Dec-10,25.2563,24.9079,24.9178,25.02733,5672.914000000001,25.204409310250934
18,30-Dec-10,25.0373,24.8283,24.878,24.91453,5624.741999999999,25.196687502882995
19,31-Dec-10,25.0074,24.7088,24.9676,24.8946,5023.469,25.189626838746538
20,3-Jan-11,25.3061,25.0274,25.0473,25.126929999999998,7457.090999999999,25.20734712046974
21,4-Jan-11,25.116999999999997,24.3404,24.45,24.6358,11798.008999999998,25.187857717587416
22,5-Jan-11,24.6889,24.2708,24.5694,24.5097,12366.132,25.13631726721325
23,6-Jan-11,24.5495,23.8925,24.0219,24.154629999999997,13294.865,25.030555113789646
24,7-Jan-11,24.2708,23.778000000000002,23.8825,23.9771,9256.87,24.91547606305806
25,10-Jan-11,24.2708,23.7232,24.2011,24.06503,9690.604,24.794771487236023
26,11-Jan-11,24.5993,24.2011,24.2807,24.36037,8870.318000000001,24.68372645384523
27,12-Jan-11,24.4798,24.2409,24.3305,24.3504,7168.965,24.618745747839238
28,13-Jan-11,24.5595,23.4345,24.44,24.14467,11356.18,24.52276889908593
29,14-Jan-11,25.16,24.27,25.0,24.81,13379.374,24.51628803159466
,Date,High,Low,Close,Typical Price,Volume,vwap,vwap_2stdev,vwap_-2stdev
0,2010-12-03,24.8283,24.3205,24.7486,24.63247,18730.144,24.632466666666666,24.632466666666662,24.632466666666662
1,2010-12-06,24.7586,24.5993,24.7088,24.6889,12271.74,24.654805154030853,24.71000034533528,24.599609962726426
2,2010-12-07,25.1568,24.7785,25.0373,24.99087,24691.414,24.80379676048873,25.140223920731994,24.467369600245465
3,2010-12-08,25.5848,24.9477,25.545,25.35917,18357.606,24.9414758619062,25.502861378042404,24.38009034577
4,2010-12-09,25.6844,24.8083,25.0672,25.18663,22964.08,24.99950623571372,25.532414278378035,24.4665981930494
5,2010-12-10,25.336,25.0572,25.107,25.16673,15918.948,25.02307824302856,25.53052786548367,24.515628620573445
6,2010-12-13,25.2862,24.8482,24.888,25.00747,16067.044,25.021133824528068,25.496043511132505,24.54622413792363
7,2010-12-14,25.1269,24.7496,24.9975,24.958,16568.487,25.013948032058988,25.462809721807695,24.56508634231028
8,2010-12-15,25.2762,24.9278,25.0473,25.08377,16018.729,25.020869365685463,25.448940784559365,24.592797946811555
9,2010-12-16,25.3857,25.0274,25.336,25.2497,9773.569,25.03392065542907,25.462941168391286,24.604900142466864
10,2010-12-17,25.5351,25.0473,25.0572,25.2132,22572.712000000003,25.054787605744554,25.47414152565047,24.635433685838624
11,2010-12-20,25.6048,25.0622,25.4455,25.37083,12986.669,25.074623090960745,25.508584520598532,24.64066166132296
12,2010-12-21,25.7441,25.5351,25.5649,25.6147,10906.659,25.101664793872967,25.585799669777597,24.617529917968344
13,2010-12-22,25.7242,25.4554,25.555,25.5782,5799.259,25.11402265022072,25.615274327006222,24.612770973435214
14,2010-12-23,25.6744,25.2862,25.4057,25.45543,7395.274,25.168402599215426,25.60111772887163,24.735687469559217
15,2010-12-27,25.4455,25.1667,25.3658,25.326,5818.161999999998,25.20144430295291,25.571205925454088,24.831682680451728
16,2010-12-28,25.3161,24.9178,25.0373,25.0904,7164.726,25.224830276069326,25.57962732059043,24.870033231548238
17,2010-12-29,25.2563,24.9079,24.9178,25.02733,5672.914000000002,25.20440931025093,25.56607077707847,24.8427478434234
18,2010-12-30,25.0373,24.8283,24.878,24.91453,5624.741999999998,25.196687502882995,25.592476558669752,24.800898447096237
19,2010-12-31,25.0074,24.7088,24.9676,24.8946,5023.469,25.189626838746534,25.613988291424807,24.76526538606827
20,2011-01-03,25.3061,25.0274,25.0473,25.12693,7457.0909999999985,25.207347120469738,25.62624723114063,24.78844700979885
21,2011-01-04,25.117,24.3404,24.45,24.6358,11798.008999999998,25.187857717587413,25.702145480396673,24.67356995477816
22,2011-01-05,24.6889,24.2708,24.5694,24.5097,12366.132,25.13631726721325,25.79241066525781,24.480223869168693
23,2011-01-06,24.5495,23.8925,24.0219,24.15463,13294.865,25.03055511378965,25.89856317362721,24.162547053952082
24,2011-01-07,24.2708,23.778,23.8825,23.9771,9256.87,24.91547606305806,25.964058276814093,23.866893849302024
25,2011-01-10,24.2708,23.7232,24.2011,24.06503,9690.604,24.794771487236023,25.89902091884207,23.690522055629977
26,2011-01-11,24.5993,24.2011,24.2807,24.36037,8870.318000000001,24.683726453845228,25.681309464048176,23.686143443642287
27,2011-01-12,24.4798,24.2409,24.3305,24.3504,7168.965,24.618745747839235,25.532390203812742,23.705101291865734
28,2011-01-13,24.5595,23.4345,24.44,24.14467,11356.18,24.522768899085932,25.34944515779455,23.69609264037731
29,2011-01-14,25.16,24.27,25.0,24.81,13379.374,24.51628803159466,25.26472975048104,23.767846312708276
1 change: 0 additions & 1 deletion test/integration/wrapper.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import unittest

import pandas as pd

import ta


Expand Down
1 change: 0 additions & 1 deletion test/unit/momentum.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import unittest

import pandas as pd

from ta.momentum import (
KAMAIndicator,
PercentagePriceOscillator,
Expand Down
1 change: 0 additions & 1 deletion test/unit/trend.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import unittest

import pandas as pd

from ta.trend import (
MACD,
ADXIndicator,
Expand Down
1 change: 0 additions & 1 deletion test/unit/volatility.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import unittest

import pandas as pd

from ta.volatility import (
AverageTrueRange,
BollingerBands,
Expand Down
10 changes: 9 additions & 1 deletion test/unit/volume.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import unittest

import pandas as pd

from ta.volume import (
AccDistIndexIndicator,
EaseOfMovementIndicator,
Expand Down Expand Up @@ -253,6 +252,15 @@ def test_vwap2(self):
self._df[target].tail(), result.tail(), check_names=False
)

def test_vwap_stdev_bands(self):
bands = self._indicator.stdev_bands([2, -2])
pd.testing.assert_series_equal(
self._df["vwap_2stdev"].tail(), bands[0].tail(), check_names=False
)
pd.testing.assert_series_equal(
self._df["vwap_-2stdev"].tail(), bands[1].tail(), check_names=False
)


if __name__ == "__main__":
unittest.main()