From ef2be16d9703e8d7da5428c54eee3e2b6b9d58c0 Mon Sep 17 00:00:00 2001 From: Tyler Goodlet Date: Tue, 10 Nov 2020 20:16:24 -0500 Subject: [PATCH] Add initial tina (ohl3) vwap fsp --- piker/fsp/_volume.py | 60 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 piker/fsp/_volume.py diff --git a/piker/fsp/_volume.py b/piker/fsp/_volume.py new file mode 100644 index 00000000..138effed --- /dev/null +++ b/piker/fsp/_volume.py @@ -0,0 +1,60 @@ +# piker: trading gear for hackers +# Copyright (C) 2018-present Tyler Goodlet (in stewardship of piker0) + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +from typing import AsyncIterator + +import numpy as np + +from ..data._normalize import iterticks + + +async def _tina_vwap( + source, #: AsyncStream[np.ndarray], + ohlcv: np.ndarray, # price time-frame "aware" +) -> AsyncIterator[np.ndarray]: # maybe something like like FspStream? + """Streaming volume weighted moving average. + + + Calling this "tina" for now since we're using OHL3 instead of tick. + + """ + # TODO: anchor to session start + + a = ohlcv.array + ohl3 = (a['open'] + a['high'] + a['low']) / 3 + + v = a['volume'] + cum_v = np.cumsum(v) + cum_weights = np.cumsum(ohl3 * v) + + vwap = cum_weights / cum_v + + # deliver historical output as "first yield" + yield vwap + + weights_tot = cum_weights[-1] + v_tot = cum_v[-1] + + async for quote in source: + + for tick in iterticks(quote, types=['trade']): + + o, h, l, v = ohlcv.array[-1][ + ['open', 'high', 'low', 'volume'] + ] + v_tot += v + + yield ((((o + h + l) / 3) * v) + weights_tot) / v_tot