From 9854addca13525aaa628ed63c8f532cedb691fae Mon Sep 17 00:00:00 2001 From: David Brazda Date: Fri, 18 Oct 2024 14:32:26 +0200 Subject: [PATCH] fix --- setup.py | 2 +- tests/cuvwap.ipynb | 76 ------------------------------------ tests/test_ntb.ipynb | 66 +++++++++++++++++++++++++++++++ ttools/indicators/CUVWAP.py | 8 ++-- ttools/indicators/DIVRELN.py | 59 ++++++++++++++++++++++++++++ 5 files changed, 129 insertions(+), 82 deletions(-) delete mode 100644 tests/cuvwap.ipynb create mode 100644 tests/test_ntb.ipynb create mode 100644 ttools/indicators/DIVRELN.py diff --git a/setup.py b/setup.py index cf1a940..a7fdbaa 100644 --- a/setup.py +++ b/setup.py @@ -2,7 +2,7 @@ from setuptools import setup, find_packages setup( name='ttools', - version='0.2.9', + version='0.3.0', packages=find_packages(), install_requires=[ 'vectorbtpro', diff --git a/tests/cuvwap.ipynb b/tests/cuvwap.ipynb deleted file mode 100644 index ebbf018..0000000 --- a/tests/cuvwap.ipynb +++ /dev/null @@ -1,76 +0,0 @@ -{ - "cells": [ - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "The autoreload extension is already loaded. To reload it, use:\n", - " %reload_ext autoreload\n" - ] - }, - { - "ename": "ModuleNotFoundError", - "evalue": "No module named 'indicators'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[4], line 5\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mvectorbtpro\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mvbt\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mttools\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mvbtindicators\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m register_custom_inds\n\u001b[0;32m----> 5\u001b[0m \u001b[43mregister_custom_inds\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43;01mNone\u001b[39;49;00m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43moverride\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 6\u001b[0m \u001b[38;5;66;03m#chopiness = vbt.indicator(\"technical:CHOPINESS\").run(s12_data.open, s12_data.high, s12_data.low, s12_data.close, s12_data.volume, window = 100)\u001b[39;00m\n\u001b[1;32m 7\u001b[0m \u001b[38;5;66;03m#vwap_cum_roll = vbt.indicator(\"technical:ROLLING_VWAP\").run(s12_data.open, s12_data.high, s12_data.low, s12_data.close, s12_data.volume, window = 100, min_periods = 5)\u001b[39;00m\n\u001b[1;32m 8\u001b[0m \u001b[38;5;66;03m#vwap_cum_d = vbt.indicator(\"ttools:CUVWAP\").run(s12_data.high, s12_data.low, s12_data.close, s12_data.volume, anchor=\"D\", drag=50)\u001b[39;00m\n\u001b[1;32m 9\u001b[0m \u001b[38;5;66;03m#vwap_lin_angle = vbt.indicator(\"talib:LINEARREG_ANGLE\").run(vwap_cum_d.vwap, timeperiod=2)\u001b[39;00m\n\u001b[1;32m 11\u001b[0m vbt\u001b[38;5;241m.\u001b[39mIF\u001b[38;5;241m.\u001b[39mlist_indicators(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mttools\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n", - "File \u001b[0;32m~/Documents/Development/python/ttools/ttools/vbtindicators.py:28\u001b[0m, in \u001b[0;36mregister_custom_inds\u001b[0;34m(indicator_name, if_exists)\u001b[0m\n\u001b[1;32m 26\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m file_name\u001b[38;5;241m.\u001b[39mendswith(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m.py\u001b[39m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m file_name\u001b[38;5;241m.\u001b[39mstartswith(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m_\u001b[39m\u001b[38;5;124m\"\u001b[39m):\n\u001b[1;32m 27\u001b[0m module_name \u001b[38;5;241m=\u001b[39m file_name[:\u001b[38;5;241m-\u001b[39m\u001b[38;5;241m3\u001b[39m]\n\u001b[0;32m---> 28\u001b[0m module \u001b[38;5;241m=\u001b[39m \u001b[43mimportlib\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mimport_module\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43mf\u001b[39;49m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[38;5;124;43mindicators.\u001b[39;49m\u001b[38;5;132;43;01m{\u001b[39;49;00m\u001b[43mfile_name\u001b[49m\u001b[43m[\u001b[49m\u001b[43m:\u001b[49m\u001b[38;5;241;43m-\u001b[39;49m\u001b[38;5;241;43m3\u001b[39;49m\u001b[43m]\u001b[49m\u001b[38;5;132;43;01m}\u001b[39;49;00m\u001b[38;5;124;43m\"\u001b[39;49m\u001b[43m)\u001b[49m\n\u001b[1;32m 29\u001b[0m \u001b[38;5;28;01mfor\u001b[39;00m var_name, var_value \u001b[38;5;129;01min\u001b[39;00m \u001b[38;5;28mvars\u001b[39m(module)\u001b[38;5;241m.\u001b[39mitems():\n\u001b[1;32m 30\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m var_name\u001b[38;5;241m.\u001b[39mstartswith(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mIND_\u001b[39m\u001b[38;5;124m\"\u001b[39m) \u001b[38;5;129;01mand\u001b[39;00m \u001b[38;5;28misinstance\u001b[39m(var_value, vbt\u001b[38;5;241m.\u001b[39mIndicatorFactory):\n", - "File \u001b[0;32m/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/importlib/__init__.py:126\u001b[0m, in \u001b[0;36mimport_module\u001b[0;34m(name, package)\u001b[0m\n\u001b[1;32m 124\u001b[0m \u001b[38;5;28;01mbreak\u001b[39;00m\n\u001b[1;32m 125\u001b[0m level \u001b[38;5;241m+\u001b[39m\u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[0;32m--> 126\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_bootstrap\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_gcd_import\u001b[49m\u001b[43m(\u001b[49m\u001b[43mname\u001b[49m\u001b[43m[\u001b[49m\u001b[43mlevel\u001b[49m\u001b[43m:\u001b[49m\u001b[43m]\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpackage\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mlevel\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m:1050\u001b[0m, in \u001b[0;36m_gcd_import\u001b[0;34m(name, package, level)\u001b[0m\n", - "File \u001b[0;32m:1027\u001b[0m, in \u001b[0;36m_find_and_load\u001b[0;34m(name, import_)\u001b[0m\n", - "File \u001b[0;32m:992\u001b[0m, in \u001b[0;36m_find_and_load_unlocked\u001b[0;34m(name, import_)\u001b[0m\n", - "File \u001b[0;32m:241\u001b[0m, in \u001b[0;36m_call_with_frames_removed\u001b[0;34m(f, *args, **kwds)\u001b[0m\n", - "File \u001b[0;32m:1050\u001b[0m, in \u001b[0;36m_gcd_import\u001b[0;34m(name, package, level)\u001b[0m\n", - "File \u001b[0;32m:1027\u001b[0m, in \u001b[0;36m_find_and_load\u001b[0;34m(name, import_)\u001b[0m\n", - "File \u001b[0;32m:1004\u001b[0m, in \u001b[0;36m_find_and_load_unlocked\u001b[0;34m(name, import_)\u001b[0m\n", - "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'indicators'" - ] - } - ], - "source": [ - "%load_ext autoreload\n", - "%autoreload 2\n", - "import vectorbtpro as vbt\n", - "from ttools.vbtindicators import register_custom_inds\n", - "from ttools.indicators import CUVWAP\n", - "\n", - "\n", - "register_custom_inds(None, \"override\")\n", - "#chopiness = vbt.indicator(\"technical:CHOPINESS\").run(s12_data.open, s12_data.high, s12_data.low, s12_data.close, s12_data.volume, window = 100)\n", - "#vwap_cum_roll = vbt.indicator(\"technical:ROLLING_VWAP\").run(s12_data.open, s12_data.high, s12_data.low, s12_data.close, s12_data.volume, window = 100, min_periods = 5)\n", - "#vwap_cum_d = vbt.indicator(\"ttools:CUVWAP\").run(s12_data.high, s12_data.low, s12_data.close, s12_data.volume, anchor=\"D\", drag=50)\n", - "#vwap_lin_angle = vbt.indicator(\"talib:LINEARREG_ANGLE\").run(vwap_cum_d.vwap, timeperiod=2)\n", - "\n", - "vbt.IF.list_indicators(\"ttools\")\n" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": ".venv", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.10.11" - } - }, - "nbformat": 4, - "nbformat_minor": 2 -} diff --git a/tests/test_ntb.ipynb b/tests/test_ntb.ipynb new file mode 100644 index 0000000..1c9168f --- /dev/null +++ b/tests/test_ntb.ipynb @@ -0,0 +1,66 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The autoreload extension is already loaded. To reload it, use:\n", + " %reload_ext autoreload\n" + ] + }, + { + "data": { + "text/plain": [ + "['CUVWAP']" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "%load_ext autoreload\n", + "%autoreload 2\n", + "import vectorbtpro as vbt\n", + "from ttools.vbtindicators import register_custom_inds\n", + "from ttools.indicators import CUVWAP\n", + "\n", + "\n", + "register_custom_inds(None, \"override\")\n", + "#chopiness = vbt.indicator(\"technical:CHOPINESS\").run(s12_data.open, s12_data.high, s12_data.low, s12_data.close, s12_data.volume, window = 100)\n", + "#vwap_cum_roll = vbt.indicator(\"technical:ROLLING_VWAP\").run(s12_data.open, s12_data.high, s12_data.low, s12_data.close, s12_data.volume, window = 100, min_periods = 5)\n", + "#vwap_cum_d = vbt.indicator(\"ttools:CUVWAP\").run(s12_data.high, s12_data.low, s12_data.close, s12_data.volume, anchor=\"D\", drag=50)\n", + "#vwap_lin_angle = vbt.indicator(\"talib:LINEARREG_ANGLE\").run(vwap_cum_d.vwap, timeperiod=2)\n", + "\n", + "vbt.IF.list_indicators(\"ttools\")\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.11" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/ttools/indicators/CUVWAP.py b/ttools/indicators/CUVWAP.py index 8a9038d..916a424 100644 --- a/ttools/indicators/CUVWAP.py +++ b/ttools/indicators/CUVWAP.py @@ -6,11 +6,9 @@ from vectorbtpro.base.wrapping import ArrayWrapper from vectorbtpro.utils.template import RepFunc """ -Contains custom indicators for vectorbtpro. - -import and run register_custom_inds() to register all custom indicators. - -They are available under `vbt.IF.list_indicators("ttols")` +Cumulative Anchored VWAP indicator on HLCC4 price, anchor = "D", "h", or "min" ... +drag = 0 - overlap with previous group. takes into account last N elements from previous group +when calculating (simulating v2realbot logic) """ def substitute_anchor(wrapper: ArrayWrapper, anchor: tp.Optional[tp.FrequencyLike]) -> tp.Array1d: diff --git a/ttools/indicators/DIVRELN.py b/ttools/indicators/DIVRELN.py new file mode 100644 index 0000000..b8feb41 --- /dev/null +++ b/ttools/indicators/DIVRELN.py @@ -0,0 +1,59 @@ +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 + +""" +DIVERGENCE - of two time series, same like in v2realbot + + if mode == "abs": + val = round(abs(float(source1_series[-1]) - float(source2_series[-1])),4) + elif mode == "absn": + val = round((abs(float(source1_series[-1]) - float(source2_series[-1])))/float(source1_series[-1]),4) + elif mode == "rel": + val = round(float(source1_series[-1]) - float(source2_series[-1]),4) + elif mode == "reln": #div = a+b / a-b will give value between -1 and 1 + val = round((float(source1_series[-1]) - float(source2_series[-1]))/(float(source1_series[-1])+float(source2_series[-1])),4) + elif mode == "pctabs": + val = pct_diff(num1=float(source1_series[-1]),num2=float(source2_series[-1]), absolute=True) + elif mode == "pct": + val = pct_diff(num1=float(source1_series[-1]),num2=float(source2_series[-1])) +""" + + +@jit(nopython=True) +def divergence(series1, series2, divtype): + print(divtype) + #div = a+b / a-b will give value between -1 and 1 + if divtype == "reln": + return (series1 - series2) / (series1 + series2) + elif divtype == "rel": + return series1 - series2 + elif divtype == "abs": + return np.abs(series1 - series2) + elif divtype == "absn": + return np.abs(series1 - series2) / series1 + elif divtype == "pctabs": + return np.abs(((series1 - series2) / series1) * 100) + elif divtype == "pct": + return ((series1 - series2) / series1) * 100 + else: + return np.full_like(series1, np.nan) + +""" +Divergence indicator - various divergences between two series +""" +IND_DIVRELN = vbt.IF( + class_name='DIVRELN', + module_name='ttools', + input_names=['series1', 'series2'], + param_names=["divtype"], + output_names=['div'] +).with_apply_func(divergence, + takes_1d=True, + param_settings=dict( + ), + divtype="reln" + ) \ No newline at end of file