flowbars 0.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- flowbars/__init__.py +163 -0
- flowbars/_version.py +8 -0
- flowbars/adapters/__init__.py +29 -0
- flowbars/adapters/polars.py +1115 -0
- flowbars/bars/__init__.py +3 -0
- flowbars/bars/accumulators.py +731 -0
- flowbars/bars/constructor.py +1254 -0
- flowbars/bars/information/__init__.py +41 -0
- flowbars/bars/information/imbalance_dollar_bars.py +200 -0
- flowbars/bars/information/imbalance_tick_bars.py +206 -0
- flowbars/bars/information/imbalance_volume_bars.py +200 -0
- flowbars/bars/information/run_dollar_bars.py +225 -0
- flowbars/bars/information/run_tick_bars.py +231 -0
- flowbars/bars/information/run_volume_bars.py +225 -0
- flowbars/bars/minute/__init__.py +99 -0
- flowbars/bars/minute/accumulators.py +303 -0
- flowbars/bars/minute/engine.py +244 -0
- flowbars/bars/minute/information.py +622 -0
- flowbars/bars/minute/numba.py +1043 -0
- flowbars/bars/minute/registry.py +22 -0
- flowbars/bars/minute/standard.py +261 -0
- flowbars/bars/minute/structural.py +474 -0
- flowbars/bars/numba_backend.py +1227 -0
- flowbars/bars/output.py +106 -0
- flowbars/bars/registry.py +47 -0
- flowbars/bars/spec.py +367 -0
- flowbars/bars/standard/__init__.py +17 -0
- flowbars/bars/standard/dollar_bars.py +168 -0
- flowbars/bars/standard/tick_bars.py +166 -0
- flowbars/bars/standard/time_bars.py +192 -0
- flowbars/bars/standard/volume_bars.py +168 -0
- flowbars/benchmarks.py +420 -0
- flowbars/calendars.py +368 -0
- flowbars/core.py +109 -0
- flowbars/py.typed +0 -0
- flowbars/quality.py +393 -0
- flowbars/sample_data/__init__.py +28 -0
- flowbars/sample_data/tick_data.csv +501 -0
- flowbars/schema.py +476 -0
- flowbars/thresholds.py +1167 -0
- flowbars/tick_rule.py +89 -0
- flowbars-0.1.0.dist-info/METADATA +650 -0
- flowbars-0.1.0.dist-info/RECORD +46 -0
- flowbars-0.1.0.dist-info/WHEEL +5 -0
- flowbars-0.1.0.dist-info/licenses/LICENSE +21 -0
- flowbars-0.1.0.dist-info/top_level.txt +1 -0
flowbars/tick_rule.py
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""Tick rule — derive trade direction from consecutive price moves.
|
|
2
|
+
|
|
3
|
+
Per AFML: sign(price_t − price_{t-1}), with equal-price carry-forward.
|
|
4
|
+
First tick has no sign (NaN). This is a well-known subtlety that existing
|
|
5
|
+
open implementations get wrong.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
import numpy.typing as npt
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def derive_tick_sign(prices: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:
|
|
15
|
+
"""Derive trade signs from a price series using the tick rule.
|
|
16
|
+
|
|
17
|
+
Parameters
|
|
18
|
+
----------
|
|
19
|
+
prices : ndarray of float64
|
|
20
|
+
1-D array of trade prices in chronological order.
|
|
21
|
+
|
|
22
|
+
Returns
|
|
23
|
+
-------
|
|
24
|
+
ndarray of float64
|
|
25
|
+
Array of signs: ``+1.0`` (buy / uptick), ``-1.0`` (sell / downtick),
|
|
26
|
+
or ``NaN`` (undetermined — first tick, or carry-forward from first
|
|
27
|
+
tick when all early prices are equal).
|
|
28
|
+
|
|
29
|
+
Rule
|
|
30
|
+
----
|
|
31
|
+
- First tick: ``NaN`` (no previous price to compare against).
|
|
32
|
+
- ``price_t > price_{t-1}`` → ``+1.0``
|
|
33
|
+
- ``price_t < price_{t-1}`` → ``-1.0``
|
|
34
|
+
- ``price_t == price_{t-1}`` → carry forward the previous tick's sign.
|
|
35
|
+
"""
|
|
36
|
+
n = len(prices)
|
|
37
|
+
signs = np.empty(n, dtype=np.float64)
|
|
38
|
+
|
|
39
|
+
if n == 0:
|
|
40
|
+
return signs
|
|
41
|
+
|
|
42
|
+
# First tick has no sign
|
|
43
|
+
signs[0] = np.nan
|
|
44
|
+
|
|
45
|
+
if n == 1:
|
|
46
|
+
return signs
|
|
47
|
+
|
|
48
|
+
# Compute differences and assign signs
|
|
49
|
+
for i in range(1, n):
|
|
50
|
+
diff = prices[i] - prices[i - 1]
|
|
51
|
+
if diff > 0.0:
|
|
52
|
+
signs[i] = 1.0
|
|
53
|
+
elif diff < 0.0:
|
|
54
|
+
signs[i] = -1.0
|
|
55
|
+
else:
|
|
56
|
+
# Equal price → carry forward previous sign (which may be NaN)
|
|
57
|
+
signs[i] = signs[i - 1]
|
|
58
|
+
|
|
59
|
+
return signs
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def resolve_tick_signs(
|
|
63
|
+
prices: npt.NDArray[np.float64],
|
|
64
|
+
supplied_sides: npt.NDArray[np.float64] | None,
|
|
65
|
+
) -> npt.NDArray[np.float64]:
|
|
66
|
+
"""Resolve trade signs: use supplied side column if provided, otherwise derive.
|
|
67
|
+
|
|
68
|
+
Parameters
|
|
69
|
+
----------
|
|
70
|
+
prices : ndarray of float64
|
|
71
|
+
1-D array of trade prices in chronological order.
|
|
72
|
+
supplied_sides : ndarray of float64 or None
|
|
73
|
+
User-supplied side values (+1, -1, NaN). If provided, returned as-is.
|
|
74
|
+
Values must already be validated (SchemaMapping handles this).
|
|
75
|
+
|
|
76
|
+
Returns
|
|
77
|
+
-------
|
|
78
|
+
ndarray of float64
|
|
79
|
+
Resolved signs array (same length as ``prices``).
|
|
80
|
+
"""
|
|
81
|
+
if supplied_sides is not None:
|
|
82
|
+
if len(supplied_sides) != len(prices):
|
|
83
|
+
raise ValueError(
|
|
84
|
+
f"supplied_sides length ({len(supplied_sides)}) "
|
|
85
|
+
f"does not match prices length ({len(prices)})"
|
|
86
|
+
)
|
|
87
|
+
return supplied_sides.copy()
|
|
88
|
+
|
|
89
|
+
return derive_tick_sign(prices)
|