pfund-plot 0.0.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.
Files changed (57) hide show
  1. pfund_plot/__init__.py +183 -0
  2. pfund_plot/__main__.py +9 -0
  3. pfund_plot/cli/__init__.py +3 -0
  4. pfund_plot/cli/commands/gallery/__init__.py +15 -0
  5. pfund_plot/cli/commands/gallery/gallery_marimo.py +462 -0
  6. pfund_plot/cli/commands/serve.py +21 -0
  7. pfund_plot/cli/main.py +20 -0
  8. pfund_plot/config.py +109 -0
  9. pfund_plot/enums/__init__.py +16 -0
  10. pfund_plot/enums/dataframe_backend.py +6 -0
  11. pfund_plot/enums/display_mode.py +7 -0
  12. pfund_plot/enums/panel_design.py +8 -0
  13. pfund_plot/enums/panel_theme.py +6 -0
  14. pfund_plot/enums/plotting_backend.py +12 -0
  15. pfund_plot/js_tap/components/candlestick.js +9566 -0
  16. pfund_plot/mixins/streaming_market_feed_mixin.py +162 -0
  17. pfund_plot/plots/altair.py +32 -0
  18. pfund_plot/plots/area/__init__.py +82 -0
  19. pfund_plot/plots/area/bokeh.py +151 -0
  20. pfund_plot/plots/bar/__init__.py +80 -0
  21. pfund_plot/plots/bar/bokeh.py +128 -0
  22. pfund_plot/plots/bokeh.py +32 -0
  23. pfund_plot/plots/candlestick/__init__.py +77 -0
  24. pfund_plot/plots/candlestick/bokeh.py +124 -0
  25. pfund_plot/plots/candlestick/svelte.py +161 -0
  26. pfund_plot/plots/holoviews.py +32 -0
  27. pfund_plot/plots/label/__init__.py +43 -0
  28. pfund_plot/plots/label/bokeh.py +89 -0
  29. pfund_plot/plots/layout/__init__.py +98 -0
  30. pfund_plot/plots/layout/layout.py +116 -0
  31. pfund_plot/plots/layout/panel.py +51 -0
  32. pfund_plot/plots/layout/tabs/__init__.py +36 -0
  33. pfund_plot/plots/layout/tabs/panel.py +51 -0
  34. pfund_plot/plots/lazy.py +408 -0
  35. pfund_plot/plots/line/__init__.py +37 -0
  36. pfund_plot/plots/line/bokeh.py +137 -0
  37. pfund_plot/plots/matplotlib.py +32 -0
  38. pfund_plot/plots/plot.py +1131 -0
  39. pfund_plot/plots/plotly.py +32 -0
  40. pfund_plot/plots/scatter/__init__.py +62 -0
  41. pfund_plot/plots/scatter/bokeh.py +158 -0
  42. pfund_plot/plots/scatter/marker.py +107 -0
  43. pfund_plot/plots/ta.py +6 -0
  44. pfund_plot/renderers/base.py +84 -0
  45. pfund_plot/renderers/browser.py +28 -0
  46. pfund_plot/renderers/desktop.py +109 -0
  47. pfund_plot/renderers/notebook.py +92 -0
  48. pfund_plot/typing.py +29 -0
  49. pfund_plot/utils/__init__.py +176 -0
  50. pfund_plot/utils/bokeh.py +177 -0
  51. pfund_plot/widgets/base.py +76 -0
  52. pfund_plot/widgets/datetime_widget.py +221 -0
  53. pfund_plot/widgets/ticker_widget.py +82 -0
  54. pfund_plot-0.0.1.dist-info/METADATA +148 -0
  55. pfund_plot-0.0.1.dist-info/RECORD +57 -0
  56. pfund_plot-0.0.1.dist-info/WHEEL +4 -0
  57. pfund_plot-0.0.1.dist-info/entry_points.txt +6 -0
@@ -0,0 +1,82 @@
1
+ # VIBE-CODED
2
+ # pyright: reportUnknownMemberType=false, reportUnknownVariableType=false, reportUnknownArgumentType=false
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Callable
6
+ from typing import TYPE_CHECKING, Any
7
+
8
+ if TYPE_CHECKING:
9
+ from pfund_plot.plots.plot import MessageKey, StreamingDfs
10
+
11
+ import panel as pn
12
+
13
+ from pfund_plot.widgets.base import BaseStreamingWidget
14
+
15
+
16
+ class TickerSelectWidget(BaseStreamingWidget):
17
+ """Dropdown for switching between streaming tickers (products).
18
+
19
+ Auto-created when a streaming feed has multiple products.
20
+ Switches the active msg_key on the plot so the pane displays
21
+ a different product's data. All streams continue in the
22
+ background; this widget only controls which one is shown.
23
+ """
24
+
25
+ def __init__(
26
+ self,
27
+ streaming_dfs: StreamingDfs,
28
+ active_key: MessageKey,
29
+ update_callback: Callable[[MessageKey], None],
30
+ ):
31
+ super().__init__(streaming_dfs, active_key, update_callback)
32
+ msg_keys = list(streaming_dfs.keys())
33
+ self._select = pn.widgets.Select(
34
+ name="Ticker",
35
+ options=self._build_options(msg_keys),
36
+ value=active_key,
37
+ )
38
+ self._watcher = self._select.param.watch(self._on_select, "value")
39
+
40
+ @staticmethod
41
+ def _build_options(msg_keys: list[MessageKey]) -> dict[str, MessageKey]:
42
+ """Build {display_label: msg_key} dict for the Select widget."""
43
+ resolutions = {res for _, res in msg_keys}
44
+ if len(resolutions) == 1:
45
+ # All same resolution — just show the product name
46
+ return {product: (product, res) for product, res in msg_keys}
47
+ # Mixed resolutions — disambiguate with "(resolution)"
48
+ return {f"{product} ({res})": (product, res) for product, res in msg_keys}
49
+
50
+ def _fan_out_to_overlays(self, msg_key: MessageKey) -> None:
51
+ """Switch each overlay widget's active stream to the same msg_key.
52
+ Must be called BEFORE the parent's _update_callback so the DynamicMap re-render
53
+ picks up the updated overlay dfs.
54
+ """
55
+ for overlay_widget in self._overlays:
56
+ overlay_widget._update_callback(msg_key)
57
+
58
+ def _on_select(self, event: Any) -> None:
59
+ self._fan_out_to_overlays(event.new)
60
+ self._update_callback(event.new)
61
+
62
+ def update_streaming_state(self, streaming_dfs: StreamingDfs) -> None:
63
+ """Update dropdown options when new products start streaming."""
64
+ msg_keys = list(streaming_dfs.keys())
65
+ current_keys = (
66
+ set(self._select.options.values())
67
+ if isinstance(self._select.options, dict)
68
+ else set()
69
+ )
70
+ if set(msg_keys) == current_keys:
71
+ return
72
+ current_value = self._select.value
73
+ self._select.param.unwatch(self._watcher)
74
+ try:
75
+ self._select.options = self._build_options(msg_keys)
76
+ if current_value in self._select.options.values():
77
+ self._select.value = current_value
78
+ finally:
79
+ self._watcher = self._select.param.watch(self._on_select, "value")
80
+
81
+ def get_panel_objects(self) -> list[pn.widgets.Widget]:
82
+ return [self._select]
@@ -0,0 +1,148 @@
1
+ Metadata-Version: 2.4
2
+ Name: pfund-plot
3
+ Version: 0.0.1
4
+ Summary: A library for financial data visualization, dashboard creation, and template sharing.
5
+ Keywords: financial data,plotting,dashboards,charts,data visualization,graphs,plots
6
+ Author: Stephen Yau
7
+ Author-email: Stephen Yau <softwareentrepreneer+pfund-plot@gmail.com>
8
+ License-Expression: Apache-2.0
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Intended Audience :: Science/Research
12
+ Classifier: Intended Audience :: Financial and Insurance Industry
13
+ Classifier: Intended Audience :: Information Technology
14
+ Classifier: Topic :: Office/Business :: Financial :: Investment
15
+ Classifier: Topic :: Scientific/Engineering :: Visualization
16
+ Classifier: Topic :: Software Development :: Libraries
17
+ Classifier: Typing :: Typed
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Requires-Dist: pfeed>=0.0.15
22
+ Requires-Dist: panel>=1.9.3
23
+ Requires-Dist: hvplot>=0.12.2
24
+ Requires-Dist: dayplot>=0.5.1
25
+ Requires-Dist: anywidget>=0.11.0 ; sys_platform != 'emscripten'
26
+ Requires-Dist: ipywidgets-bokeh>=1.7.0 ; sys_platform != 'emscripten'
27
+ Requires-Dist: pywebview>=6.2.1 ; sys_platform != 'emscripten'
28
+ Requires-Dist: datashader>=0.19.1 ; sys_platform != 'emscripten'
29
+ Requires-Dist: altair>=6.1.0 ; extra == 'altair'
30
+ Requires-Dist: vegafusion>=2.0.3 ; extra == 'altair'
31
+ Requires-Dist: vl-convert-python>=1.9.0.post1 ; extra == 'altair'
32
+ Requires-Dist: jupyter-bokeh>=4.0.5 ; extra == 'jupyter'
33
+ Requires-Dist: notebook>=7.5.7 ; extra == 'jupyter'
34
+ Requires-Dist: papermill>=2.7.0 ; extra == 'jupyter'
35
+ Requires-Dist: voila>=0.5.12 ; extra == 'jupyter'
36
+ Requires-Dist: marimo[recommended,lsp]>=0.23.9 ; extra == 'marimo'
37
+ Requires-Dist: matplotlib>=3.10.9 ; extra == 'matplotlib'
38
+ Requires-Dist: plotly>=6.8.0 ; extra == 'plotly'
39
+ Requires-Python: >=3.11
40
+ Project-URL: homepage, https://pfund-plot.pfund.ai
41
+ Project-URL: repository, https://github.com/PFund-Software-Ltd/pfund-plot
42
+ Project-URL: documentation, https://pfund-plot.pfund.ai/doc
43
+ Provides-Extra: altair
44
+ Provides-Extra: jupyter
45
+ Provides-Extra: marimo
46
+ Provides-Extra: matplotlib
47
+ Provides-Extra: plotly
48
+ Description-Content-Type: text/markdown
49
+
50
+ # PFund-Plot: Financial Charts in One Line of Code
51
+
52
+ [![Discord](https://img.shields.io/badge/Discord-%235865F2.svg?logo=discord&logoColor=white)](https://discord.gg/vqpS94tpdp)
53
+ [![X](https://img.shields.io/twitter/follow/pfund_ai?style=social)](https://x.com/pfund_ai)
54
+ [![Downloads](https://static.pepy.tech/badge/pfund-plot/month)](https://pepy.tech/project/pfund-plot)
55
+ [![PyPI](https://img.shields.io/pypi/v/pfund-plot.svg?cacheSeconds=300)](https://pypi.org/project/pfund-plot)
56
+ ![PyPI - Support Python Versions](https://img.shields.io/pypi/pyversions/pfund-plot?cacheSeconds=300)
57
+ [![afterpython](https://afterpython.org/shield.svg)](https://afterpython.org)
58
+ [![Discussions](https://img.shields.io/badge/Discussions-Let's%20Chat-green)](https://github.com/PFund-Software-Ltd/pfund-plot/discussions)
59
+ [![Jupyter Notebook](https://img.shields.io/badge/jupyter-notebook-orange?logo=jupyter)](https://jupyter.org)
60
+ [![Marimo](https://marimo.io/shield.svg)](https://marimo.io)
61
+ [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/PFund-Software-Ltd/pfund-plot)
62
+ [![View Code Wiki](https://assets.codewiki.google/readme-badge/static.svg)](https://codewiki.google/github.com/pfund-software-ltd/pfund-plot?utm_source=badge&utm_medium=github&utm_campaign=github.com/pfund-software-ltd/pfund-plot)
63
+ <!-- ![PyPI downloads](https://img.shields.io/pypi/dm/pfund-plot?label=downloads&cacheSeconds=86400) -->
64
+ <!-- ![GitHub stars](https://img.shields.io/github/stars/PFund-Software-Ltd/pfund-plot?style=social) -->
65
+
66
+
67
+ > **This library is NOT ready for use, please wait for 0.1.0 release.**
68
+
69
+ ## TL;DR: pfund-plot handles the plotting libraries, so traders just get charts that work
70
+
71
+ ## Problem
72
+ Traders often need to quickly visualize their data without investing time in learning new tools.
73
+ For example, plotting a candlestick should be as simple as writing a single line of code.
74
+
75
+ ## Solution
76
+ We created a high-level financial visualization layer that combines the best features from existing plotting libraries into an easy-to-use interface.
77
+
78
+ ---
79
+ <img src="afterpython/static/candlestick.gif" alt="pfund-plot candlestick streaming example" width="450">
80
+
81
+ ---
82
+
83
+ `pfund-plot` is a financial visualization layer on top of existing plotting libraries, giving traders a simple, domain-specific interface for plotting and streaming market data.
84
+
85
+ ## Core Features
86
+ - [x] Multi-Display Mode: support displaying plots in a *Jupyter notebook*, *Marimo notebook*, *browser* and *desktop window*
87
+ - [x] Intuitive & Chainable API: `plt.ohlc(df).style(...).control(...).mode(...).show()`
88
+ - [x] Streaming Plots: support streaming data in real-time
89
+ - [x] DataFrame Agnostic: support pandas, polars, and dask
90
+ - [x] Financial Plots: plot financial data by just one function call
91
+ - [x] Combine multiple plots into a dashboard quickly for visualization
92
+
93
+
94
+ ## Installation
95
+ ```bash
96
+ pip install pfund-plot
97
+ ```
98
+
99
+ ## Quickstart
100
+ ### 1. Plotting in a Jupyter or Marimo Notebook
101
+ > To use data sources other than Bybit, please go to [pfeed](https://github.com/PFund-Software-Ltd/pfeed) and install the corresponding extras. For example: `pip install "pfeed[data_source1, data_source2]"`
102
+ ```python
103
+ import pfeed as pe
104
+ import pfund_plot as plt
105
+
106
+ feed = pe.Bybit().market_feed
107
+ result = feed.download(product='BTC_USDT_PERP', resolution='1h', rollback_period='1d')
108
+ df = result.data.collect()
109
+
110
+ # Notebook mode:
111
+ plt.ohlc(df)
112
+ ```
113
+
114
+ ### 2. Plotting in a Python Script
115
+ ```python
116
+ # Browser mode:
117
+ plt.ohlc(df).mode('browser').show()
118
+
119
+ # Desktop mode:
120
+ if __name__ == "__main__": # Required because desktop mode uses multiprocessing.
121
+ plt.ohlc(df).mode('desktop').show()
122
+ ```
123
+
124
+ ### 3. Streaming a Plot
125
+ ```python
126
+ # Streaming requires pipeline_mode=True.
127
+ feed = pe.Bybit(pipeline_mode=True).market_feed
128
+ feed.stream(product='BTC_USDT_PERP', resolution='1s')
129
+
130
+ # In a Python script:
131
+ plt.ohlc(feed).control(update_interval=1000).mode('browser') # or mode('desktop') under if __name__ == "__main__"
132
+
133
+ # In a notebook environment (not recommended to start streaming in a notebook unless you know what you're doing):
134
+ # await plt.ohlc(feed).control(update_interval=1000).show_async()
135
+ ```
136
+
137
+ ---
138
+
139
+ ## Tapping into the JavaScript World
140
+ Python developers sometimes envy the JavaScript visualization ecosystem for its rich set of interactive charts and dashboards. With `pfund-plot`, they can still enjoy the benefits of the JavaScript world while keeping the same Python-first API. For example:
141
+ ```python
142
+ plt.ohlc(df).backend('svelte')
143
+ ```
144
+ This renders the following chart using TradingView's [Lightweight Charts](https://github.com/tradingview/lightweight-charts):
145
+
146
+ <img src="afterpython/static/tradingview.png" alt="pfund-plot TradingView Lightweight Charts example" width="450">
147
+
148
+ > This is meant as a showcase rather than a core direction: `pfund-plot` remains Python-first, and JavaScript-backed charts are supported where they fit naturally. If you want to bring more useful JavaScript visualizations into `pfund-plot`, contributions are welcome.
@@ -0,0 +1,57 @@
1
+ pfund_plot/__init__.py,sha256=On1DfzajMgq1TArL-v6GiPaYWKQ_88elwsxcMLAwVzg,4957
2
+ pfund_plot/__main__.py,sha256=VAtd0NeGkClK2TPPn2aHpBFfhS_UP5VTz_iFSlzZqCM,178
3
+ pfund_plot/cli/__init__.py,sha256=gQsdBdJT07D6qyG0nfzuqAjpi8-08tRfXBeNlgLtbGQ,81
4
+ pfund_plot/cli/commands/gallery/__init__.py,sha256=7P2ge98c4jAaiNw3FWq6F1kHNew6IYVY1J59WdnubcM,370
5
+ pfund_plot/cli/commands/gallery/gallery_marimo.py,sha256=BTzCScvJtv06QenWRi7YDQ-wE0xPqS6u-QG50QjQSsU,9793
6
+ pfund_plot/cli/commands/serve.py,sha256=Kuc7huA5t7dOLGFmi3FjR4LlhKJgmMUv8f6LktgOUQM,427
7
+ pfund_plot/cli/main.py,sha256=_0HF3GWc2GcsGugfvmhrRuIoLqtKZEsaiih_EBbVpEo,639
8
+ pfund_plot/config.py,sha256=pWsufaqMbGHKz0bbHYRB5Ir-p5wxHi08UIoP5Xzm9fw,3355
9
+ pfund_plot/enums/__init__.py,sha256=eOauJK7Tc8y2ci3IXCNYUpia8UiNVfkRJgAOD4tIKjM,480
10
+ pfund_plot/enums/dataframe_backend.py,sha256=iTgYoF3Q3byfqvG-Vcb9xwIT2XkOnzmfd8-SONp3XuQ,120
11
+ pfund_plot/enums/display_mode.py,sha256=1PnXq754nzK5m6TvO39T9ViUbNxyBVYEmnwZy7FLtOc,129
12
+ pfund_plot/enums/panel_design.py,sha256=cJugsV6K6FHLdhylp9-mKZFnXgFoR23Qte5GNjkZ-2I,149
13
+ pfund_plot/enums/panel_theme.py,sha256=bLFMIrmSJYSL22OQjLERAu6B5BUxZRVwNCrrHREU4SU,104
14
+ pfund_plot/enums/plotting_backend.py,sha256=m8vmHPHmtMQgvnm12CHecrMZZR3Xlvi1bRCjai2iYvY,416
15
+ pfund_plot/js_tap/components/candlestick.js,sha256=ek8c_-Xo5cSXwuUX30aGXtPg3dcpaGz7lyIs_spMitM,266608
16
+ pfund_plot/mixins/streaming_market_feed_mixin.py,sha256=XdA_s1BoJodyTPV7J82bMxbJeXQKgzFC2sefIHuiMOA,7198
17
+ pfund_plot/plots/altair.py,sha256=KHP-j2Oe_rvL6Y4npeP-ZO3TgfU3VWF3zw297EOcssk,1061
18
+ pfund_plot/plots/area/__init__.py,sha256=bnqGWZHgGGvZnf7ffVi5gzWJjlqg7RJgJnIv8RiOSSY,3219
19
+ pfund_plot/plots/area/bokeh.py,sha256=oKcVuTg3T0pb1UqhYSHSAle9xepKV9fmnIsDWmgbAo8,5115
20
+ pfund_plot/plots/bar/__init__.py,sha256=D1aY8Cmkqe9p9LdwInMA-NvuzR8BSY_4qLsFxgC8shk,3091
21
+ pfund_plot/plots/bar/bokeh.py,sha256=IK3GsMjfcchc0GCvDtX-Z7KyCI6y_0hl5dQWqloXb3w,4171
22
+ pfund_plot/plots/bokeh.py,sha256=sZLb6l354JaYzKZSAjVWXEcH51mjyTygOJoOs6oczMI,1059
23
+ pfund_plot/plots/candlestick/__init__.py,sha256=VOXykzBN3LB_4zl2_VSyCMUSeiCBQIkfQUWXL9JIxVM,3315
24
+ pfund_plot/plots/candlestick/bokeh.py,sha256=NNanskAhZoYweaY8QxLWra4KAJYaeYjpCT3lgWK9Ccw,4342
25
+ pfund_plot/plots/candlestick/svelte.py,sha256=_-y06cPdYXnwX_xLh2SlOPGCzVQzMQvTFh1zMYgcrIs,6613
26
+ pfund_plot/plots/holoviews.py,sha256=Flz59vHuyu6zh9MCYyhKKMBky5AR9YPx_JGG6P0gnSo,1082
27
+ pfund_plot/plots/label/__init__.py,sha256=SeX85UErHpOk0kfZPEuR_8gdi0U6Wht9MS6bueyDxsk,1227
28
+ pfund_plot/plots/label/bokeh.py,sha256=LLnTKhm1EDfCkD8HMLKsv_R5eCiYkTZ5VErSq82wEmM,2295
29
+ pfund_plot/plots/layout/__init__.py,sha256=1uxGTMILHUhlPq4rdLcUJAJSSVLb8p0y3tmP-SVDZ4s,3856
30
+ pfund_plot/plots/layout/layout.py,sha256=6pCEdbRQV56wE1j__jMvsdXujAbN3Yd1IECISBSnsfk,4421
31
+ pfund_plot/plots/layout/panel.py,sha256=pcJoIzigrlF09XyEitPtg_FV4ihD-HboDeFjVk7yJYk,1372
32
+ pfund_plot/plots/layout/tabs/__init__.py,sha256=jVBQsPSzKYrRW5sCaB2_m9tQUkNEE5sEMvbDILMVJjE,965
33
+ pfund_plot/plots/layout/tabs/panel.py,sha256=-GrhwAqvmMTaGFH9ztjvUBTKYx_ry1rtatSZFfopkDU,1284
34
+ pfund_plot/plots/lazy.py,sha256=mej-aNLwc5Nw10IbNk0gACd-vSuJj4orYvf5BTPsZPU,13602
35
+ pfund_plot/plots/line/__init__.py,sha256=li-tVoCDnxlFrQqKrjASbaAOgkSVE_HfoCM2TKuS9qE,1248
36
+ pfund_plot/plots/line/bokeh.py,sha256=Xx_F0c9T8h6gHxaTC_zOvUaaeoCfyu6F-AmhEfG3Jvo,4381
37
+ pfund_plot/plots/matplotlib.py,sha256=91PnrlY6S_Fdww5HSWokFzEp7SVWgzODnaCkXmNWSE4,1110
38
+ pfund_plot/plots/plot.py,sha256=G-yT4H-7bl2crje1azEv6s9ChzAFh-QiFD_zvbcIuSg,46459
39
+ pfund_plot/plots/plotly.py,sha256=nJI-9XauOIeWK711DfMhuiKP_0KVW00fVyPqBdPWvZI,1081
40
+ pfund_plot/plots/scatter/__init__.py,sha256=g8qGh8Sik8GL5gYMKi63yzOlTFboIu9KX2TNZcs4qLI,2084
41
+ pfund_plot/plots/scatter/bokeh.py,sha256=FSwasRlN_EICACmYLmyxHMnXCyq0ePx6xuca4RaxZPs,4540
42
+ pfund_plot/plots/scatter/marker.py,sha256=mCyV7xoHnf8ejH6rVmJeUZ-OkLaQQ0txU4DAlzA2ZYE,3619
43
+ pfund_plot/plots/ta.py,sha256=rYtjCLl27Q5kc8ezrzQGI0px2ZHHlbSUjjx7eMZxemo,200
44
+ pfund_plot/renderers/base.py,sha256=bpqTI2tGJHonl8JRWlKFfs2Q_7yOi762cY8ythua9HA,2668
45
+ pfund_plot/renderers/browser.py,sha256=RKFO2aQmC4brWucG6mWaT9LWnEOuP5lDgBrTwoojURg,960
46
+ pfund_plot/renderers/desktop.py,sha256=8qQGjKk58_tJPqpV8ZzxhkFQ41shkZIC0_pG9ZkBFoM,3444
47
+ pfund_plot/renderers/notebook.py,sha256=PeihwoiwbC146SCOgefiHTZTwPY8Z8tuI9bqaP-Sjkc,3871
48
+ pfund_plot/typing.py,sha256=7ZHKx7kKURZahGeRxbDMPjDYHCl9KCxkkAI96PX3i4U,1315
49
+ pfund_plot/utils/__init__.py,sha256=MztA91kb24iI3qMh3CUGsI4Rso6xdcImEK4QQXpWYHM,5259
50
+ pfund_plot/utils/bokeh.py,sha256=OE4XpNA2zMUKMScyOzYROySz1LpkGqEa3BaC9kVc8oc,6252
51
+ pfund_plot/widgets/base.py,sha256=UQ4PtLylgbmrfmJpCPx4X9nEfBQ1Kdcz8m6FzAFNRRg,2586
52
+ pfund_plot/widgets/datetime_widget.py,sha256=YHj1A4gzX-kukPiEK79l7nCWl5WsyyVLILeX_l5pCM4,9520
53
+ pfund_plot/widgets/ticker_widget.py,sha256=ODwLgjiDatQrevqORnlkJVTLE8U7MMjdC3XKDwtHHcs,3223
54
+ pfund_plot-0.0.1.dist-info/WHEEL,sha256=wXwAVsgVaOZ_pwDFqQm5Rd6PID-Fc74nkLc8X8gHiDo,81
55
+ pfund_plot-0.0.1.dist-info/entry_points.txt,sha256=5eMaY95w6_xcnxsQbbd3vSzYqMzyeKtrW1WOwAOyzJ8,115
56
+ pfund_plot-0.0.1.dist-info/METADATA,sha256=w5lF-bWiudbfkGkSQCsL2nVNu3x8xW29sxYofD0WmCc,7267
57
+ pfund_plot-0.0.1.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: uv 0.11.19
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,6 @@
1
+ [console_scripts]
2
+ plt = pfund_plot.__main__:run_cli
3
+
4
+ [pfund_shell.commands]
5
+ plt = pfund_plot.cli:pfund_plot_group
6
+