From 817eada70d03309dc79b9d58802c6512bb25159d Mon Sep 17 00:00:00 2001 From: David Brazda Date: Fri, 18 Oct 2024 11:31:31 +0200 Subject: [PATCH] cu_vwap_ind added --- setup.py | 2 +- tests/vbt-anchored.py | 7 ++++-- ttools/__init__.py | 3 ++- ttools/vbtindicators.py | 56 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 ttools/vbtindicators.py diff --git a/setup.py b/setup.py index ff923f7..2b9511d 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name='ttools', - version='0.1.9', + version='0.2.0', packages=find_packages(), install_requires=[ 'vectorbtpro', diff --git a/tests/vbt-anchored.py b/tests/vbt-anchored.py index 32ce7e5..e2e4fc2 100644 --- a/tests/vbt-anchored.py +++ b/tests/vbt-anchored.py @@ -1,3 +1,6 @@ -import ttools +import ttools as tts + +#ttools.AnchoredIndicator("talib:MOM") + +from ttools import cu_vwap_ind -#ttools.AnchoredIndicator("talib:MOM") \ No newline at end of file diff --git a/ttools/__init__.py b/ttools/__init__.py index 6ee21d5..773b736 100644 --- a/ttools/__init__.py +++ b/ttools/__init__.py @@ -1 +1,2 @@ -from .vbtutils import AnchoredIndicator, create_mask_from_window, isrising, isfalling \ No newline at end of file +from .vbtutils import AnchoredIndicator, create_mask_from_window, isrising, isfalling +from .vbtindicators import cu_vwap_ind \ No newline at end of file diff --git a/ttools/vbtindicators.py b/ttools/vbtindicators.py new file mode 100644 index 0000000..db220f2 --- /dev/null +++ b/ttools/vbtindicators.py @@ -0,0 +1,56 @@ +import numpy as np +from numba import jit +import vectorbtpro as vbt +from vectorbtpro import _typing as tp +from vectorbtpro.base.wrapping import ArrayWrapper +from vectorbtpro.utils.template import RepFunc + +def substitute_anchor(wrapper: ArrayWrapper, anchor: tp.Optional[tp.FrequencyLike]) -> tp.Array1d: + """Substitute reset frequency by group lens. It is array of number of elements of each group.""" + if anchor is None: + return np.array([wrapper.shape[0]]) + return wrapper.get_index_grouper(anchor).get_group_lens() + +@jit(nopython=True) +def vwap_cum(high, low, close, volume, group_lens): + #anchor based grouping - prepare group indexes + group_end_idxs = np.cumsum(group_lens) + group_start_idxs = group_end_idxs - group_lens + + #prepare output + out = np.full(volume.shape, np.nan, dtype=np.float_) + + hlcc4 = (high + low + close + close) / 4 + + #iterate over groups + for group in range(len(group_lens)): + from_i = group_start_idxs[group] + to_i = group_end_idxs[group] + nom_cumsum = 0 + denum_cumsum = 0 + #for each group do this (it is just np.cumsum(hlcc4 * volume) / np.sum(volume) iteratively) + for i in range(from_i, to_i): + nom_cumsum += volume[i] * hlcc4[i] + denum_cumsum += volume[i] + if denum_cumsum == 0: + out[i] = np.nan + else: + out[i] = nom_cumsum / denum_cumsum + return out + +#cumulative anchored vwap on HLCC4 price +cu_vwap_ind = vbt.IF( + class_name='CUVWAP', + input_names=['high', 'low', 'close', 'volume'], + param_names=['anchor'], + output_names=['vwap'] +).with_apply_func(vwap_cum, + takes_1d=True, + param_settings=dict( + anchor=dict(template=RepFunc(substitute_anchor)), + ), + anchor="D", + ) + +#vwap_cum = vwap_ind.run(s12_data.high, s12_data.low, s12_data.close, s12_data.volume, anchor="min") +vbt.IF.register_custom_indicator(cu_vwap_ind) \ No newline at end of file