maidr 1.6.0__py3-none-any.whl → 1.6.1__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.
- maidr/__init__.py +1 -1
- maidr/core/plot/candlestick.py +107 -17
- maidr/patch/candlestick.py +27 -1
- maidr/patch/mplfinance.py +6 -3
- {maidr-1.6.0.dist-info → maidr-1.6.1.dist-info}/METADATA +1 -2
- {maidr-1.6.0.dist-info → maidr-1.6.1.dist-info}/RECORD +8 -8
- {maidr-1.6.0.dist-info → maidr-1.6.1.dist-info}/WHEEL +0 -0
- {maidr-1.6.0.dist-info → maidr-1.6.1.dist-info}/licenses/LICENSE +0 -0
maidr/__init__.py
CHANGED
maidr/core/plot/candlestick.py
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import uuid
|
|
4
|
+
from typing import Union, Dict
|
|
3
5
|
from matplotlib.axes import Axes
|
|
4
6
|
from matplotlib.patches import Rectangle
|
|
7
|
+
import numpy as np
|
|
5
8
|
|
|
6
9
|
from maidr.core.enum import PlotType
|
|
7
10
|
from maidr.core.plot import MaidrPlot
|
|
8
11
|
from maidr.core.enum.maidr_key import MaidrKey
|
|
12
|
+
from maidr.exception import ExtractionError
|
|
9
13
|
from maidr.util.mplfinance_utils import MplfinanceDataExtractor
|
|
10
14
|
|
|
11
15
|
|
|
@@ -41,23 +45,48 @@ class CandlestickPlot(MaidrPlot):
|
|
|
41
45
|
self._maidr_date_nums = kwargs.get("_maidr_date_nums", None)
|
|
42
46
|
self._maidr_original_data = kwargs.get("_maidr_original_data", None) # Store original data
|
|
43
47
|
|
|
44
|
-
# Store the GID for proper selector generation
|
|
48
|
+
# Store the GID for proper selector generation (legacy/shared)
|
|
45
49
|
self._maidr_gid = None
|
|
50
|
+
# Modern-path separate gids for body and wick
|
|
51
|
+
self._maidr_body_gid = None
|
|
52
|
+
self._maidr_wick_gid = None
|
|
46
53
|
if self._maidr_body_collection:
|
|
47
54
|
self._maidr_gid = self._maidr_body_collection.get_gid()
|
|
55
|
+
self._maidr_body_gid = self._maidr_gid
|
|
48
56
|
elif self._maidr_wick_collection:
|
|
49
57
|
self._maidr_gid = self._maidr_wick_collection.get_gid()
|
|
58
|
+
self._maidr_wick_gid = self._maidr_gid
|
|
50
59
|
|
|
51
60
|
def _extract_plot_data(self) -> list[dict]:
|
|
52
|
-
"""
|
|
61
|
+
"""
|
|
62
|
+
Extract candlestick data from the plot.
|
|
63
|
+
|
|
64
|
+
This method processes candlestick plots from both modern (mplfinance.plot) and
|
|
65
|
+
legacy (original_flavor) pipelines, extracting OHLC data and setting up
|
|
66
|
+
highlighting elements and GIDs.
|
|
67
|
+
|
|
68
|
+
Returns
|
|
69
|
+
-------
|
|
70
|
+
list[dict]
|
|
71
|
+
List of dictionaries containing candlestick data with keys:
|
|
72
|
+
- 'value': Date string
|
|
73
|
+
- 'open': Opening price (float)
|
|
74
|
+
- 'high': High price (float)
|
|
75
|
+
- 'low': Low price (float)
|
|
76
|
+
- 'close': Closing price (float)
|
|
77
|
+
- 'volume': Volume (float, typically 0 for candlestick-only plots)
|
|
78
|
+
"""
|
|
53
79
|
|
|
54
80
|
# Get the custom collections from kwargs
|
|
55
81
|
body_collection = self._maidr_body_collection
|
|
56
82
|
wick_collection = self._maidr_wick_collection
|
|
57
83
|
|
|
58
84
|
if body_collection and wick_collection:
|
|
59
|
-
# Store the
|
|
60
|
-
self.
|
|
85
|
+
# Store the GIDs from the collections (modern path)
|
|
86
|
+
self._maidr_body_gid = body_collection.get_gid()
|
|
87
|
+
self._maidr_wick_gid = wick_collection.get_gid()
|
|
88
|
+
# Keep legacy gid filled for backward compatibility
|
|
89
|
+
self._maidr_gid = self._maidr_body_gid or self._maidr_wick_gid
|
|
61
90
|
|
|
62
91
|
# Use the original collections for highlighting
|
|
63
92
|
self._elements = [body_collection, wick_collection]
|
|
@@ -86,12 +115,33 @@ class CandlestickPlot(MaidrPlot):
|
|
|
86
115
|
|
|
87
116
|
# Generate a GID for highlighting if none exists
|
|
88
117
|
if not self._maidr_gid:
|
|
89
|
-
import uuid
|
|
90
|
-
|
|
91
118
|
self._maidr_gid = f"maidr-{uuid.uuid4()}"
|
|
92
119
|
# Set GID on all rectangles
|
|
93
120
|
for rect in body_rectangles:
|
|
94
121
|
rect.set_gid(self._maidr_gid)
|
|
122
|
+
# Keep a dedicated body gid for legacy dict selectors
|
|
123
|
+
self._maidr_body_gid = getattr(self, "_maidr_body_gid", None) or self._maidr_gid
|
|
124
|
+
|
|
125
|
+
# Assign a shared gid to wick Line2D (vertical 2-point lines) on the same axis
|
|
126
|
+
wick_lines = []
|
|
127
|
+
for line in ax_ohlc.get_lines():
|
|
128
|
+
try:
|
|
129
|
+
xydata = line.get_xydata()
|
|
130
|
+
if xydata is None:
|
|
131
|
+
continue
|
|
132
|
+
xy_arr = np.asarray(xydata)
|
|
133
|
+
if xy_arr.ndim == 2 and xy_arr.shape[0] == 2 and xy_arr.shape[1] >= 2:
|
|
134
|
+
x0 = float(xy_arr[0, 0])
|
|
135
|
+
x1 = float(xy_arr[1, 0])
|
|
136
|
+
if abs(x0 - x1) < 1e-10:
|
|
137
|
+
wick_lines.append(line)
|
|
138
|
+
except Exception:
|
|
139
|
+
continue
|
|
140
|
+
if wick_lines:
|
|
141
|
+
if not getattr(self, "_maidr_wick_gid", None):
|
|
142
|
+
self._maidr_wick_gid = f"maidr-{uuid.uuid4()}"
|
|
143
|
+
for line in wick_lines:
|
|
144
|
+
line.set_gid(self._maidr_wick_gid)
|
|
95
145
|
|
|
96
146
|
# Use the utility class to extract data
|
|
97
147
|
data = MplfinanceDataExtractor.extract_rectangle_candlestick_data(
|
|
@@ -117,17 +167,57 @@ class CandlestickPlot(MaidrPlot):
|
|
|
117
167
|
x_labels = "X"
|
|
118
168
|
return {MaidrKey.X: x_labels, MaidrKey.Y: self.ax.get_ylabel()}
|
|
119
169
|
|
|
120
|
-
def _get_selector(self) -> str:
|
|
121
|
-
"""Return
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
170
|
+
def _get_selector(self) -> Union[str, Dict[str, str]]:
|
|
171
|
+
"""Return selectors for highlighting candlestick elements.
|
|
172
|
+
|
|
173
|
+
- Modern path (collections present): return a dict with separate selectors for body, wickLow, wickHigh
|
|
174
|
+
- Legacy path: return a dict with body and shared wick selectors (no open/close keys)
|
|
175
|
+
"""
|
|
176
|
+
# Modern path: build structured selectors using separate gids
|
|
177
|
+
if self._maidr_body_collection and self._maidr_wick_collection and self._maidr_body_gid and self._maidr_wick_gid:
|
|
178
|
+
# Determine candle count N
|
|
179
|
+
N = None
|
|
180
|
+
if self._maidr_original_data is not None:
|
|
181
|
+
try:
|
|
182
|
+
N = len(self._maidr_original_data)
|
|
183
|
+
except Exception:
|
|
184
|
+
N = None
|
|
185
|
+
if N is None and hasattr(self._maidr_wick_collection, "get_paths"):
|
|
186
|
+
try:
|
|
187
|
+
wick_paths = len(list(self._maidr_wick_collection.get_paths()))
|
|
188
|
+
if wick_paths % 2 == 0 and wick_paths > 0:
|
|
189
|
+
N = wick_paths // 2
|
|
190
|
+
except Exception:
|
|
191
|
+
pass
|
|
192
|
+
if N is None and hasattr(self._maidr_body_collection, "get_paths"):
|
|
193
|
+
try:
|
|
194
|
+
body_paths = len(list(self._maidr_body_collection.get_paths()))
|
|
195
|
+
if body_paths > 0:
|
|
196
|
+
N = body_paths
|
|
197
|
+
except Exception:
|
|
198
|
+
pass
|
|
199
|
+
if N is None:
|
|
200
|
+
raise ExtractionError(PlotType.CANDLESTICK, self._maidr_wick_collection)
|
|
201
|
+
|
|
202
|
+
selectors = {
|
|
203
|
+
"body": f"g[id='{self._maidr_body_gid}'] > path",
|
|
204
|
+
"wickLow": f"g[id='{self._maidr_wick_gid}'] > path:nth-child(-n+{N})",
|
|
205
|
+
"wickHigh": f"g[id='{self._maidr_wick_gid}'] > path:nth-child(n+{N + 1})",
|
|
206
|
+
}
|
|
207
|
+
return selectors
|
|
208
|
+
|
|
209
|
+
# Legacy path: build shared-id selectors; omit open/close
|
|
210
|
+
legacy_selectors = {}
|
|
211
|
+
if getattr(self, "_maidr_body_gid", None) or self._maidr_gid:
|
|
212
|
+
body_gid = getattr(self, "_maidr_body_gid", None) or self._maidr_gid
|
|
213
|
+
legacy_selectors["body"] = f"g[id='{body_gid}'] > path"
|
|
214
|
+
if getattr(self, "_maidr_wick_gid", None):
|
|
215
|
+
legacy_selectors["wick"] = f"g[id='{self._maidr_wick_gid}'] > path"
|
|
216
|
+
if legacy_selectors:
|
|
217
|
+
return legacy_selectors
|
|
218
|
+
|
|
219
|
+
# Fallback
|
|
220
|
+
return "g[maidr='true'] > path, g[maidr='true'] > rect"
|
|
131
221
|
|
|
132
222
|
def render(self) -> dict:
|
|
133
223
|
"""Initialize the MAIDR schema dictionary with basic plot information."""
|
maidr/patch/candlestick.py
CHANGED
|
@@ -2,6 +2,7 @@ import wrapt
|
|
|
2
2
|
from typing import Any, Callable, Dict, Tuple
|
|
3
3
|
from matplotlib.patches import Rectangle
|
|
4
4
|
from mplfinance import original_flavor
|
|
5
|
+
import numpy as np
|
|
5
6
|
|
|
6
7
|
from maidr.core.context_manager import ContextManager
|
|
7
8
|
from maidr.core.enum.plot_type import PlotType
|
|
@@ -46,10 +47,35 @@ def candlestick(
|
|
|
46
47
|
# Patch the plotting function.
|
|
47
48
|
plot = wrapped(*args, **kwargs)
|
|
48
49
|
|
|
50
|
+
original_data = None
|
|
51
|
+
date_nums = None
|
|
52
|
+
if len(args) >= 2:
|
|
53
|
+
try:
|
|
54
|
+
quotes = args[1]
|
|
55
|
+
if quotes is not None:
|
|
56
|
+
arr = np.asarray(quotes)
|
|
57
|
+
if arr.ndim == 2 and arr.shape[1] >= 5 and arr.size > 0:
|
|
58
|
+
date_nums = arr[:, 0].tolist()
|
|
59
|
+
original_data = {
|
|
60
|
+
"Open": arr[:, 1].tolist(),
|
|
61
|
+
"High": arr[:, 2].tolist(),
|
|
62
|
+
"Low": arr[:, 3].tolist(),
|
|
63
|
+
"Close": arr[:, 4].tolist(),
|
|
64
|
+
}
|
|
65
|
+
except Exception:
|
|
66
|
+
pass
|
|
67
|
+
|
|
49
68
|
axes = []
|
|
50
69
|
for ax in plot:
|
|
51
70
|
axes.append(FigureManager.get_axes(ax))
|
|
52
|
-
|
|
71
|
+
|
|
72
|
+
extra_kwargs: Dict[str, Any] = {}
|
|
73
|
+
if original_data is not None:
|
|
74
|
+
extra_kwargs["_maidr_original_data"] = original_data
|
|
75
|
+
if date_nums is not None:
|
|
76
|
+
extra_kwargs["_maidr_date_nums"] = date_nums
|
|
77
|
+
|
|
78
|
+
FigureManager.create_maidr(axes, PlotType.CANDLESTICK, **extra_kwargs)
|
|
53
79
|
|
|
54
80
|
return plot
|
|
55
81
|
|
maidr/patch/mplfinance.py
CHANGED
|
@@ -83,9 +83,10 @@ def mplfinance_plot_patch(wrapped, instance, args, kwargs):
|
|
|
83
83
|
)
|
|
84
84
|
|
|
85
85
|
if wick_collection and body_collection:
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
86
|
+
wick_gid = f"maidr-{uuid.uuid4()}"
|
|
87
|
+
body_gid = f"maidr-{uuid.uuid4()}"
|
|
88
|
+
wick_collection.set_gid(wick_gid)
|
|
89
|
+
body_collection.set_gid(body_gid)
|
|
89
90
|
|
|
90
91
|
candlestick_kwargs = dict(
|
|
91
92
|
kwargs,
|
|
@@ -93,6 +94,8 @@ def mplfinance_plot_patch(wrapped, instance, args, kwargs):
|
|
|
93
94
|
_maidr_body_collection=body_collection,
|
|
94
95
|
_maidr_date_nums=date_nums,
|
|
95
96
|
_maidr_original_data=data,
|
|
97
|
+
_maidr_wick_gid=wick_gid,
|
|
98
|
+
_maidr_body_gid=body_gid,
|
|
96
99
|
)
|
|
97
100
|
common(
|
|
98
101
|
PlotType.CANDLESTICK,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: maidr
|
|
3
|
-
Version: 1.6.
|
|
3
|
+
Version: 1.6.1
|
|
4
4
|
Summary: Multimodal Access and Interactive Data Representations
|
|
5
5
|
Project-URL: Homepage, https://xability.github.io/py-maidr
|
|
6
6
|
Project-URL: Repository, https://github.com/xability/py-maidr
|
|
@@ -28,7 +28,6 @@ Requires-Dist: htmltools>=0.5
|
|
|
28
28
|
Requires-Dist: lxml>=5.1.0
|
|
29
29
|
Requires-Dist: mplfinance>=0.12.10b0
|
|
30
30
|
Requires-Dist: numpy>=1.26
|
|
31
|
-
Requires-Dist: virtualenv<21,>=20.26.6
|
|
32
31
|
Requires-Dist: wrapt<2,>=1.16.0
|
|
33
32
|
Provides-Extra: jupyter
|
|
34
33
|
Requires-Dist: ipykernel>=6.0.0; extra == 'jupyter'
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
maidr/__init__.py,sha256=
|
|
1
|
+
maidr/__init__.py,sha256=n8luuuD48JSxB6D5jXxE2QsGGoeQI-3S9lM4qhb4RPI,415
|
|
2
2
|
maidr/api.py,sha256=gRNLXqUWpFGdD-I7Nu6J0_LeEni9KRAr0TBHwHaDAsc,1928
|
|
3
3
|
maidr/core/__init__.py,sha256=WgxLpSEYMc4k3OyEOf1shOxfEq0ASzppEIZYmE91ThQ,25
|
|
4
4
|
maidr/core/context_manager.py,sha256=6cT7ZGOApSpC-SLD2XZWWU_H08i-nfv-JUlzXOtvWYw,3374
|
|
@@ -12,7 +12,7 @@ maidr/core/enum/smooth_keywords.py,sha256=z2kVZZ-mETWWh5reWu_hj9WkJD6WFj7_2-6s1e
|
|
|
12
12
|
maidr/core/plot/__init__.py,sha256=xDIpRGM-4DfaSSL3nKcXrjdMecCHJ6en4K4nA_fPefQ,83
|
|
13
13
|
maidr/core/plot/barplot.py,sha256=0hBgp__putezvxXc9G3qmaktmAzze3cN8pQMD9iqktE,2116
|
|
14
14
|
maidr/core/plot/boxplot.py,sha256=i11GdNuz_c-hilmhydu3ah-bzyVdFoBkNvRi5lpMrrY,9946
|
|
15
|
-
maidr/core/plot/candlestick.py,sha256=
|
|
15
|
+
maidr/core/plot/candlestick.py,sha256=pDuO7ljGiwpqLUWpMgPYARTZGfLHdEoPVbAoNkv3lV0,9559
|
|
16
16
|
maidr/core/plot/grouped_barplot.py,sha256=_zn4XMeEnSiDHtf6t4-z9ErBqg_CijhAS2CCtlHgYIQ,2077
|
|
17
17
|
maidr/core/plot/heatmap.py,sha256=yMS-31tS2GW4peds9LtZesMxmmTV_YfqYO5M_t5KasQ,2521
|
|
18
18
|
maidr/core/plot/histogram.py,sha256=QV5W-6ZJQQcZsrM91JJBX-ONktJzH7yg_et5_bBPfQQ,1525
|
|
@@ -28,7 +28,7 @@ maidr/exception/extraction_error.py,sha256=rd37Oxa9gn2OWFWt9AOH5fv0hNd3sAWGvpDMF
|
|
|
28
28
|
maidr/patch/__init__.py,sha256=FnkoUQJC2ODhLO37GwgRVSitBCRax42Ti0e4NIAgdO0,236
|
|
29
29
|
maidr/patch/barplot.py,sha256=qdUy5Y8zkMg4dH3fFh93OYzLdar4nl1u5O2Jcw4d2zI,2433
|
|
30
30
|
maidr/patch/boxplot.py,sha256=l7wDD4pDi4ZbsL5EX5XDhPRxgtSIFSrFguMOZ7IC2eg,2845
|
|
31
|
-
maidr/patch/candlestick.py,sha256=
|
|
31
|
+
maidr/patch/candlestick.py,sha256=R2MgPX5ih9W-RBluvF6jFNJBxETH0eMt7Tzn0Ej9LoU,2652
|
|
32
32
|
maidr/patch/clear.py,sha256=2Sc4CIt5jRGkew3TxFsBZm-uowC9yDSxtraEcXZjmGw,396
|
|
33
33
|
maidr/patch/common.py,sha256=RV2NayjPmcWJVhZJV7nmBCjcH7MPDhW_fIluTOPAATk,880
|
|
34
34
|
maidr/patch/heatmap.py,sha256=uxLLg530Ql9KVC5rxk8vnwPHXBWWHwYgJRkyHY-tJzs,1048
|
|
@@ -36,7 +36,7 @@ maidr/patch/highlight.py,sha256=I1dGFHJAnVd0AHVnMJzk_TE8BC8Uv-I6fTzSrJLU5QM,1155
|
|
|
36
36
|
maidr/patch/histogram.py,sha256=k3N0RUf1SQ2402pwbaY5QyS98KnLWvr9glCHQw9NTko,2378
|
|
37
37
|
maidr/patch/kdeplot.py,sha256=qv-OKzuop2aTrkZgUe2OnLxvV-KMyeXt1Td0_uZeHzE,2338
|
|
38
38
|
maidr/patch/lineplot.py,sha256=kvTAiOddy1g5GMP456Awk21NUEZfn-vWaYXy5GTVtuA,1841
|
|
39
|
-
maidr/patch/mplfinance.py,sha256=
|
|
39
|
+
maidr/patch/mplfinance.py,sha256=FJYM5xRDMpTwaKZUzT6IjpgsR1UiVnvATZsDTyDxqmY,8154
|
|
40
40
|
maidr/patch/regplot.py,sha256=k86ekd0E4XJ_L1u85zObuDnxuXlM83z7tKtyXRTj2rI,3240
|
|
41
41
|
maidr/patch/scatterplot.py,sha256=kln6zZwjVsdQzICalo-RnBOJrx1BnIB2xYUwItHvSNY,525
|
|
42
42
|
maidr/util/__init__.py,sha256=eRJZfRpDX-n7UoV3JXw_9Lbfu_qNl_D0W1UTvLL-Iv4,81
|
|
@@ -51,7 +51,7 @@ maidr/util/mixin/extractor_mixin.py,sha256=oHtwpmS5kARvaLrSO3DKTPQxyFUw9nOcKN7rz
|
|
|
51
51
|
maidr/util/mixin/merger_mixin.py,sha256=V0qLw_6DUB7X6CQ3BCMpsCQX_ZuwAhoSTm_E4xAJFKM,712
|
|
52
52
|
maidr/widget/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
53
53
|
maidr/widget/shiny.py,sha256=wrrw2KAIpE_A6CNQGBtNHauR1DjenA_n47qlFXX9_rk,745
|
|
54
|
-
maidr-1.6.
|
|
55
|
-
maidr-1.6.
|
|
56
|
-
maidr-1.6.
|
|
57
|
-
maidr-1.6.
|
|
54
|
+
maidr-1.6.1.dist-info/METADATA,sha256=WygnnC777b2MAHatLuMFLRjtoRZIW9gc5Ft1RKHE06I,3154
|
|
55
|
+
maidr-1.6.1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
56
|
+
maidr-1.6.1.dist-info/licenses/LICENSE,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
|
|
57
|
+
maidr-1.6.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|