pfund-plot 0.0.1.dev3__tar.gz → 0.0.3__tar.gz
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.
- pfund_plot-0.0.3/PKG-INFO +146 -0
- pfund_plot-0.0.3/README.md +97 -0
- pfund_plot-0.0.3/pyproject.toml +85 -0
- pfund_plot-0.0.3/src/pfund_plot/__init__.py +178 -0
- pfund_plot-0.0.3/src/pfund_plot/__main__.py +9 -0
- {pfund_plot-0.0.1.dev3 → pfund_plot-0.0.3/src}/pfund_plot/cli/__init__.py +1 -2
- pfund_plot-0.0.3/src/pfund_plot/cli/commands/gallery/__init__.py +15 -0
- pfund_plot-0.0.3/src/pfund_plot/cli/commands/gallery/gallery_marimo.py +477 -0
- pfund_plot-0.0.3/src/pfund_plot/cli/commands/serve.py +21 -0
- pfund_plot-0.0.3/src/pfund_plot/cli/main.py +20 -0
- pfund_plot-0.0.3/src/pfund_plot/config.py +97 -0
- pfund_plot-0.0.3/src/pfund_plot/enums/__init__.py +16 -0
- {pfund_plot-0.0.1.dev3/pfund_plot/const → pfund_plot-0.0.3/src/pfund_plot}/enums/dataframe_backend.py +2 -2
- {pfund_plot-0.0.1.dev3/pfund_plot/const → pfund_plot-0.0.3/src/pfund_plot}/enums/display_mode.py +1 -1
- pfund_plot-0.0.3/src/pfund_plot/enums/panel_design.py +8 -0
- pfund_plot-0.0.3/src/pfund_plot/enums/panel_theme.py +6 -0
- pfund_plot-0.0.3/src/pfund_plot/enums/plotting_backend.py +12 -0
- pfund_plot-0.0.3/src/pfund_plot/js_tap/components/candlestick.js +9566 -0
- pfund_plot-0.0.3/src/pfund_plot/mixins/streaming_market_feed_mixin.py +162 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/altair.py +32 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/area/__init__.py +82 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/area/bokeh.py +151 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/bar/__init__.py +80 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/bar/bokeh.py +128 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/bokeh.py +32 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/candlestick/__init__.py +77 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/candlestick/bokeh.py +124 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/candlestick/svelte.py +163 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/holoviews.py +32 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/label/__init__.py +43 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/label/bokeh.py +89 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/layout/__init__.py +98 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/layout/layout.py +116 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/layout/panel.py +51 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/layout/tabs/__init__.py +36 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/layout/tabs/panel.py +51 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/lazy.py +408 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/line/__init__.py +37 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/line/bokeh.py +137 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/matplotlib.py +32 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/plot.py +1135 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/plotly.py +32 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/scatter/__init__.py +62 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/scatter/bokeh.py +158 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/scatter/marker.py +107 -0
- pfund_plot-0.0.3/src/pfund_plot/plots/ta.py +6 -0
- pfund_plot-0.0.3/src/pfund_plot/renderers/base.py +86 -0
- pfund_plot-0.0.3/src/pfund_plot/renderers/browser.py +28 -0
- pfund_plot-0.0.3/src/pfund_plot/renderers/desktop.py +109 -0
- pfund_plot-0.0.3/src/pfund_plot/renderers/notebook.py +92 -0
- pfund_plot-0.0.3/src/pfund_plot/typing.py +29 -0
- pfund_plot-0.0.3/src/pfund_plot/utils/__init__.py +176 -0
- pfund_plot-0.0.3/src/pfund_plot/utils/bokeh.py +177 -0
- pfund_plot-0.0.3/src/pfund_plot/widgets/base.py +76 -0
- pfund_plot-0.0.3/src/pfund_plot/widgets/datetime_widget.py +221 -0
- pfund_plot-0.0.3/src/pfund_plot/widgets/ticker_widget.py +82 -0
- pfund_plot-0.0.1.dev3/LICENSE +0 -201
- pfund_plot-0.0.1.dev3/PKG-INFO +0 -101
- pfund_plot-0.0.1.dev3/README.md +0 -54
- pfund_plot-0.0.1.dev3/pfund_plot/__init__.py +0 -35
- pfund_plot-0.0.1.dev3/pfund_plot/cli/__pycache__/__init__.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/cli/__pycache__/main.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/cli/commands/__pycache__/config.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/cli/commands/__pycache__/plot.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/cli/commands/config.py +0 -81
- pfund_plot-0.0.1.dev3/pfund_plot/cli/commands/plot.py +0 -7
- pfund_plot-0.0.1.dev3/pfund_plot/cli/main.py +0 -20
- pfund_plot-0.0.1.dev3/pfund_plot/composites/composite.py +0 -13
- pfund_plot-0.0.1.dev3/pfund_plot/config_handler.py +0 -136
- pfund_plot-0.0.1.dev3/pfund_plot/const/__pycache__/paths.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/const/enums/__init__.py +0 -6
- pfund_plot-0.0.1.dev3/pfund_plot/const/enums/__pycache__/__init__.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/const/enums/__pycache__/dashboard_type.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/const/enums/__pycache__/data_type.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/const/enums/__pycache__/dataframe_backend.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/const/enums/__pycache__/display_mode.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/const/enums/__pycache__/notebook_type.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/const/enums/__pycache__/plotting_backend.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/const/enums/dashboard_type.py +0 -8
- pfund_plot-0.0.1.dev3/pfund_plot/const/enums/data_type.py +0 -6
- pfund_plot-0.0.1.dev3/pfund_plot/const/enums/notebook_type.py +0 -7
- pfund_plot-0.0.1.dev3/pfund_plot/const/enums/plotting_backend.py +0 -6
- pfund_plot-0.0.1.dev3/pfund_plot/const/paths.py +0 -15
- pfund_plot-0.0.1.dev3/pfund_plot/exports/__init__.py +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/layout.py +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/main.py +0 -18
- pfund_plot-0.0.1.dev3/pfund_plot/mosaic.py +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/plots/__pycache__/candlestick.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/plots/__pycache__/dataframe.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/plots/__pycache__/line.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/plots/candlestick.py +0 -234
- pfund_plot-0.0.1.dev3/pfund_plot/plots/dataframe.py +0 -159
- pfund_plot-0.0.1.dev3/pfund_plot/plots/line.py +0 -2
- pfund_plot-0.0.1.dev3/pfund_plot/plots/orderbook.py +0 -47
- pfund_plot-0.0.1.dev3/pfund_plot/renderer.py +0 -143
- pfund_plot-0.0.1.dev3/pfund_plot/templates/__init__.py +0 -2
- pfund_plot-0.0.1.dev3/pfund_plot/templates/dashboard.py +0 -13
- pfund_plot-0.0.1.dev3/pfund_plot/templates/notebook.py +0 -15
- pfund_plot-0.0.1.dev3/pfund_plot/templates/spreadsheet.py +0 -1
- pfund_plot-0.0.1.dev3/pfund_plot/templates/template.py +0 -10
- pfund_plot-0.0.1.dev3/pfund_plot/types/__pycache__/core.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/types/__pycache__/literals.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/types/core.py +0 -11
- pfund_plot-0.0.1.dev3/pfund_plot/types/literals.py +0 -6
- pfund_plot-0.0.1.dev3/pfund_plot/utils/__pycache__/utils.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/utils/__pycache__/validate.cpython-311.pyc +0 -0
- pfund_plot-0.0.1.dev3/pfund_plot/utils/utils.py +0 -42
- pfund_plot-0.0.1.dev3/pfund_plot/utils/validate.py +0 -50
- pfund_plot-0.0.1.dev3/pyproject.toml +0 -82
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: pfund-plot
|
|
3
|
+
Version: 0.0.3
|
|
4
|
+
Summary: A library for financial data visualization
|
|
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
|
+
[](https://discord.gg/vqpS94tpdp)
|
|
53
|
+
[](https://x.com/pfund_ai)
|
|
54
|
+
[](https://pepy.tech/project/pfund-plot)
|
|
55
|
+
[](https://pypi.org/project/pfund-plot)
|
|
56
|
+

|
|
57
|
+
[](https://afterpython.org)
|
|
58
|
+
[](https://github.com/PFund-Software-Ltd/pfund-plot/discussions)
|
|
59
|
+
[](https://jupyter.org)
|
|
60
|
+
[](https://marimo.io)
|
|
61
|
+
[](https://deepwiki.com/PFund-Software-Ltd/pfund-plot)
|
|
62
|
+
[](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
|
+
<!--  -->
|
|
64
|
+
<!--  -->
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
## TL;DR: pfund-plot handles the plotting libraries, so traders just get charts that work
|
|
68
|
+
|
|
69
|
+
## Problem
|
|
70
|
+
Traders often need to quickly visualize their data without investing time in learning new tools.
|
|
71
|
+
For example, plotting a candlestick should be as simple as writing a single line of code.
|
|
72
|
+
|
|
73
|
+
## Solution
|
|
74
|
+
We created a high-level financial visualization layer that combines the best features from existing plotting libraries into an easy-to-use interface.
|
|
75
|
+
|
|
76
|
+
---
|
|
77
|
+
<img src="afterpython/static/candlestick.gif" alt="pfund-plot candlestick streaming example" width="450">
|
|
78
|
+
|
|
79
|
+
---
|
|
80
|
+
|
|
81
|
+
`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.
|
|
82
|
+
|
|
83
|
+
## Core Features
|
|
84
|
+
- [x] Multi-Display Mode: support displaying plots in a *Jupyter notebook*, *Marimo notebook*, *browser* and *desktop window*
|
|
85
|
+
- [x] Intuitive & Chainable API: `plt.ohlc(df).style(...).control(...).mode(...).show()`
|
|
86
|
+
- [x] Streaming Plots: support streaming data in real-time
|
|
87
|
+
- [x] DataFrame Agnostic: support pandas, polars, and dask
|
|
88
|
+
- [x] Financial Plots: plot financial data by just one function call
|
|
89
|
+
- [x] Combine multiple plots into a dashboard quickly for visualization
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
## Installation
|
|
93
|
+
```bash
|
|
94
|
+
pip install pfund-plot
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Quickstart
|
|
98
|
+
### 1. Plotting in a Jupyter or Marimo Notebook
|
|
99
|
+
> 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]"`
|
|
100
|
+
```python
|
|
101
|
+
import pfeed as pe
|
|
102
|
+
import pfund_plot as plt
|
|
103
|
+
|
|
104
|
+
feed = pe.Bybit().market_feed
|
|
105
|
+
result = feed.download(product='BTC_USDT_PERP', resolution='1h', rollback_period='1d')
|
|
106
|
+
df = result.data.collect()
|
|
107
|
+
|
|
108
|
+
# Notebook mode:
|
|
109
|
+
plt.ohlc(df)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### 2. Plotting in a Python Script
|
|
113
|
+
```python
|
|
114
|
+
# Browser mode:
|
|
115
|
+
plt.ohlc(df).mode('browser').show()
|
|
116
|
+
|
|
117
|
+
# Desktop mode:
|
|
118
|
+
if __name__ == "__main__": # Required because desktop mode uses multiprocessing.
|
|
119
|
+
plt.ohlc(df).mode('desktop').show()
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### 3. Streaming a Plot
|
|
123
|
+
```python
|
|
124
|
+
# Streaming requires pipeline_mode=True.
|
|
125
|
+
feed = pe.Bybit(pipeline_mode=True).market_feed
|
|
126
|
+
feed.stream(product='BTC_USDT_PERP', resolution='1s')
|
|
127
|
+
|
|
128
|
+
# In a Python script:
|
|
129
|
+
plt.ohlc(feed).control(update_interval=1000).mode('browser') # or mode('desktop') under if __name__ == "__main__"
|
|
130
|
+
|
|
131
|
+
# In a notebook environment (not recommended to start streaming in a notebook unless you know what you're doing):
|
|
132
|
+
# await plt.ohlc(feed).control(update_interval=1000).show_async()
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## Tapping into the JavaScript World
|
|
138
|
+
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:
|
|
139
|
+
```python
|
|
140
|
+
plt.ohlc(df).backend('svelte')
|
|
141
|
+
```
|
|
142
|
+
This renders the following chart using TradingView's [Lightweight Charts](https://github.com/tradingview/lightweight-charts):
|
|
143
|
+
|
|
144
|
+
<img src="afterpython/static/tradingview.png" alt="pfund-plot TradingView Lightweight Charts example" width="450">
|
|
145
|
+
|
|
146
|
+
> 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,97 @@
|
|
|
1
|
+
# `pfund-plot`: Financial Charts in One Line of Code
|
|
2
|
+
|
|
3
|
+
[](https://discord.gg/vqpS94tpdp)
|
|
4
|
+
[](https://x.com/pfund_ai)
|
|
5
|
+
[](https://pepy.tech/project/pfund-plot)
|
|
6
|
+
[](https://pypi.org/project/pfund-plot)
|
|
7
|
+

|
|
8
|
+
[](https://afterpython.org)
|
|
9
|
+
[](https://github.com/PFund-Software-Ltd/pfund-plot/discussions)
|
|
10
|
+
[](https://jupyter.org)
|
|
11
|
+
[](https://marimo.io)
|
|
12
|
+
[](https://deepwiki.com/PFund-Software-Ltd/pfund-plot)
|
|
13
|
+
[](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)
|
|
14
|
+
<!--  -->
|
|
15
|
+
<!--  -->
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
## TL;DR: pfund-plot handles the plotting libraries, so traders just get charts that work
|
|
19
|
+
|
|
20
|
+
## Problem
|
|
21
|
+
Traders often need to quickly visualize their data without investing time in learning new tools.
|
|
22
|
+
For example, plotting a candlestick should be as simple as writing a single line of code.
|
|
23
|
+
|
|
24
|
+
## Solution
|
|
25
|
+
We created a high-level financial visualization layer that combines the best features from existing plotting libraries into an easy-to-use interface.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
<img src="afterpython/static/candlestick.gif" alt="pfund-plot candlestick streaming example" width="450">
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
`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.
|
|
33
|
+
|
|
34
|
+
## Core Features
|
|
35
|
+
- [x] Multi-Display Mode: support displaying plots in a *Jupyter notebook*, *Marimo notebook*, *browser* and *desktop window*
|
|
36
|
+
- [x] Intuitive & Chainable API: `plt.ohlc(df).style(...).control(...).mode(...).show()`
|
|
37
|
+
- [x] Streaming Plots: support streaming data in real-time
|
|
38
|
+
- [x] DataFrame Agnostic: support pandas, polars, and dask
|
|
39
|
+
- [x] Financial Plots: plot financial data by just one function call
|
|
40
|
+
- [x] Combine multiple plots into a dashboard quickly for visualization
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
```bash
|
|
45
|
+
pip install pfund-plot
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Quickstart
|
|
49
|
+
### 1. Plotting in a Jupyter or Marimo Notebook
|
|
50
|
+
> 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]"`
|
|
51
|
+
```python
|
|
52
|
+
import pfeed as pe
|
|
53
|
+
import pfund_plot as plt
|
|
54
|
+
|
|
55
|
+
feed = pe.Bybit().market_feed
|
|
56
|
+
result = feed.download(product='BTC_USDT_PERP', resolution='1h', rollback_period='1d')
|
|
57
|
+
df = result.data.collect()
|
|
58
|
+
|
|
59
|
+
# Notebook mode:
|
|
60
|
+
plt.ohlc(df)
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### 2. Plotting in a Python Script
|
|
64
|
+
```python
|
|
65
|
+
# Browser mode:
|
|
66
|
+
plt.ohlc(df).mode('browser').show()
|
|
67
|
+
|
|
68
|
+
# Desktop mode:
|
|
69
|
+
if __name__ == "__main__": # Required because desktop mode uses multiprocessing.
|
|
70
|
+
plt.ohlc(df).mode('desktop').show()
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 3. Streaming a Plot
|
|
74
|
+
```python
|
|
75
|
+
# Streaming requires pipeline_mode=True.
|
|
76
|
+
feed = pe.Bybit(pipeline_mode=True).market_feed
|
|
77
|
+
feed.stream(product='BTC_USDT_PERP', resolution='1s')
|
|
78
|
+
|
|
79
|
+
# In a Python script:
|
|
80
|
+
plt.ohlc(feed).control(update_interval=1000).mode('browser') # or mode('desktop') under if __name__ == "__main__"
|
|
81
|
+
|
|
82
|
+
# In a notebook environment (not recommended to start streaming in a notebook unless you know what you're doing):
|
|
83
|
+
# await plt.ohlc(feed).control(update_interval=1000).show_async()
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
---
|
|
87
|
+
|
|
88
|
+
## Tapping into the JavaScript World
|
|
89
|
+
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:
|
|
90
|
+
```python
|
|
91
|
+
plt.ohlc(df).backend('svelte')
|
|
92
|
+
```
|
|
93
|
+
This renders the following chart using TradingView's [Lightweight Charts](https://github.com/tradingview/lightweight-charts):
|
|
94
|
+
|
|
95
|
+
<img src="afterpython/static/tradingview.png" alt="pfund-plot TradingView Lightweight Charts example" width="450">
|
|
96
|
+
|
|
97
|
+
> 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,85 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "pfund-plot"
|
|
3
|
+
version = "0.0.3"
|
|
4
|
+
description = "A library for financial data visualization"
|
|
5
|
+
license = "Apache-2.0"
|
|
6
|
+
authors = [
|
|
7
|
+
{name = "Stephen Yau", email = "softwareentrepreneer+pfund-plot@gmail.com"}
|
|
8
|
+
]
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
keywords = ["financial data", "plotting", "dashboards", "charts", "data visualization", "graphs", "plots"]
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Operating System :: OS Independent",
|
|
13
|
+
"Intended Audience :: Developers",
|
|
14
|
+
"Intended Audience :: Science/Research",
|
|
15
|
+
"Intended Audience :: Financial and Insurance Industry",
|
|
16
|
+
"Intended Audience :: Information Technology",
|
|
17
|
+
"Topic :: Office/Business :: Financial :: Investment",
|
|
18
|
+
"Topic :: Scientific/Engineering :: Visualization",
|
|
19
|
+
"Topic :: Software Development :: Libraries",
|
|
20
|
+
"Typing :: Typed",
|
|
21
|
+
"Programming Language :: Python :: 3.11",
|
|
22
|
+
"Programming Language :: Python :: 3.12",
|
|
23
|
+
"Programming Language :: Python :: 3.13",
|
|
24
|
+
]
|
|
25
|
+
requires-python = ">=3.11"
|
|
26
|
+
dependencies = [
|
|
27
|
+
"pfeed>=0.0.15",
|
|
28
|
+
"panel>=1.9.3",
|
|
29
|
+
"hvplot>=0.12.2",
|
|
30
|
+
"dayplot>=0.5.1",
|
|
31
|
+
"anywidget>=0.11.0 ; sys_platform != 'emscripten'",
|
|
32
|
+
"ipywidgets-bokeh>=1.7.0 ; sys_platform != 'emscripten'",
|
|
33
|
+
"pywebview>=6.2.1 ; sys_platform != 'emscripten'",
|
|
34
|
+
"datashader>=0.19.1 ; sys_platform != 'emscripten'",
|
|
35
|
+
]
|
|
36
|
+
|
|
37
|
+
[project.optional-dependencies]
|
|
38
|
+
marimo = ["marimo[recommended,lsp]>=0.23.9"]
|
|
39
|
+
jupyter = [
|
|
40
|
+
"jupyter-bokeh>=4.0.5",
|
|
41
|
+
"notebook>=7.5.7",
|
|
42
|
+
"papermill>=2.7.0",
|
|
43
|
+
"voila>=0.5.12",
|
|
44
|
+
]
|
|
45
|
+
matplotlib = ["matplotlib>=3.10.9"]
|
|
46
|
+
plotly = ["plotly>=6.8.0"]
|
|
47
|
+
altair = [
|
|
48
|
+
"altair>=6.1.0",
|
|
49
|
+
"vegafusion>=2.0.3",
|
|
50
|
+
"vl-convert-python>=1.9.0.post1",
|
|
51
|
+
]
|
|
52
|
+
|
|
53
|
+
[project.scripts]
|
|
54
|
+
plt = "pfund_plot.__main__:run_cli"
|
|
55
|
+
|
|
56
|
+
[project.entry-points."pfund_shell.commands"]
|
|
57
|
+
plt = "pfund_plot.cli:pfund_plot_group"
|
|
58
|
+
|
|
59
|
+
[project.urls]
|
|
60
|
+
homepage = "https://pfund-plot.pfund.ai"
|
|
61
|
+
repository = "https://github.com/PFund-Software-Ltd/pfund-plot"
|
|
62
|
+
documentation = "https://pfund-plot.pfund.ai/doc"
|
|
63
|
+
|
|
64
|
+
[build-system]
|
|
65
|
+
requires = ["uv_build>=0.11.19,<0.12.0"]
|
|
66
|
+
build-backend = "uv_build"
|
|
67
|
+
|
|
68
|
+
[tool.pyright]
|
|
69
|
+
# typeCheckingMode = "basic"
|
|
70
|
+
reportAny = false
|
|
71
|
+
reportExplicitAny = false
|
|
72
|
+
reportUnnecessaryIsInstance = false
|
|
73
|
+
reportIncompatibleVariableOverride = false
|
|
74
|
+
reportIncompatibleMethodOverride = false
|
|
75
|
+
reportRedeclaration = false
|
|
76
|
+
reportUnreachable = false
|
|
77
|
+
reportImportCycles = false
|
|
78
|
+
reportPrivateUsage = false
|
|
79
|
+
reportMissingTypeStubs = false
|
|
80
|
+
reportUnannotatedClassAttribute = false
|
|
81
|
+
reportImplicitOverride = false
|
|
82
|
+
|
|
83
|
+
[tool.uv.build-backend]
|
|
84
|
+
module-name = "pfund_plot"
|
|
85
|
+
module-root = "src"
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import TYPE_CHECKING
|
|
4
|
+
|
|
5
|
+
if TYPE_CHECKING:
|
|
6
|
+
from pfund_plot.plots.altair import (
|
|
7
|
+
Altair as altair,
|
|
8
|
+
)
|
|
9
|
+
from pfund_plot.plots.altair import (
|
|
10
|
+
Altair as vega,
|
|
11
|
+
)
|
|
12
|
+
from pfund_plot.plots.area import (
|
|
13
|
+
Area as area,
|
|
14
|
+
)
|
|
15
|
+
from pfund_plot.plots.bar import (
|
|
16
|
+
Bar as bar,
|
|
17
|
+
)
|
|
18
|
+
from pfund_plot.plots.bokeh import (
|
|
19
|
+
Bokeh as bokeh,
|
|
20
|
+
)
|
|
21
|
+
from pfund_plot.plots.candlestick import (
|
|
22
|
+
Candlestick as candlestick,
|
|
23
|
+
)
|
|
24
|
+
from pfund_plot.plots.candlestick import (
|
|
25
|
+
Candlestick as kline,
|
|
26
|
+
)
|
|
27
|
+
from pfund_plot.plots.candlestick import (
|
|
28
|
+
Candlestick as ohlc,
|
|
29
|
+
)
|
|
30
|
+
from pfund_plot.plots.holoviews import (
|
|
31
|
+
Holoviews as holoviews,
|
|
32
|
+
)
|
|
33
|
+
from pfund_plot.plots.holoviews import (
|
|
34
|
+
Holoviews as hv,
|
|
35
|
+
)
|
|
36
|
+
from pfund_plot.plots.label import (
|
|
37
|
+
Label as label,
|
|
38
|
+
)
|
|
39
|
+
from pfund_plot.plots.layout import (
|
|
40
|
+
Layout as layout,
|
|
41
|
+
)
|
|
42
|
+
from pfund_plot.plots.layout.tabs import (
|
|
43
|
+
Tabs as tabs,
|
|
44
|
+
)
|
|
45
|
+
from pfund_plot.plots.line import (
|
|
46
|
+
Line as line,
|
|
47
|
+
)
|
|
48
|
+
from pfund_plot.plots.matplotlib import (
|
|
49
|
+
Matplotlib as matplotlib,
|
|
50
|
+
)
|
|
51
|
+
from pfund_plot.plots.matplotlib import (
|
|
52
|
+
Matplotlib as mpl,
|
|
53
|
+
)
|
|
54
|
+
from pfund_plot.plots.plotly import (
|
|
55
|
+
Plotly as plotly,
|
|
56
|
+
)
|
|
57
|
+
from pfund_plot.plots.scatter import (
|
|
58
|
+
Scatter as scatter,
|
|
59
|
+
)
|
|
60
|
+
from pfund_plot.plots.scatter.marker import (
|
|
61
|
+
Marker as marker,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
# NOTE: data update in anywidget (backend=svelte) may have issues (especially in marimo) after loading panel extensions
|
|
65
|
+
# if anywidget+svelte backend is not working, try to comment this out
|
|
66
|
+
#
|
|
67
|
+
# plotly/vega resolve to panel.models.* (bundled with Panel) — they don't import the
|
|
68
|
+
# plotly/altair libs, so they're safe even when those optional extras aren't installed.
|
|
69
|
+
# "ipywidgets" pulls in panel.io.ipywidget -> ipywidgets_bokeh, which is absent in WASM
|
|
70
|
+
# (and where the anywidget/svelte backend isn't available anyway), so guard only that one.
|
|
71
|
+
import importlib.util
|
|
72
|
+
|
|
73
|
+
import panel as pn
|
|
74
|
+
|
|
75
|
+
from pfund_plot.config import configure, get_config
|
|
76
|
+
|
|
77
|
+
_panel_extensions = ["plotly", "vega"]
|
|
78
|
+
if importlib.util.find_spec("ipywidgets_bokeh") is not None:
|
|
79
|
+
_panel_extensions.append("ipywidgets")
|
|
80
|
+
pn.extension(*_panel_extensions)
|
|
81
|
+
# NOTE: this MUST be True, otherwise, some widgets won't work properly, e.g. candlestick widgets, slider and input will both trigger each other due to panel's async update, which leads to infinite loop.
|
|
82
|
+
pn.config.throttled = (
|
|
83
|
+
True # If panel sliders and inputs should be throttled until release of mouse.
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def __getattr__(name: str):
|
|
88
|
+
if name == "__version__":
|
|
89
|
+
from importlib.metadata import version
|
|
90
|
+
|
|
91
|
+
return version("pfund_plot")
|
|
92
|
+
elif name == "plotly":
|
|
93
|
+
from pfund_plot.plots.plotly import Plotly
|
|
94
|
+
|
|
95
|
+
return Plotly
|
|
96
|
+
elif name in ("candlestick", "ohlc", "kline"):
|
|
97
|
+
from pfund_plot.plots.candlestick import Candlestick
|
|
98
|
+
|
|
99
|
+
return Candlestick
|
|
100
|
+
elif name == "line":
|
|
101
|
+
from pfund_plot.plots.line import Line
|
|
102
|
+
|
|
103
|
+
return Line
|
|
104
|
+
elif name == "area":
|
|
105
|
+
from pfund_plot.plots.area import Area
|
|
106
|
+
|
|
107
|
+
return Area
|
|
108
|
+
elif name == "layout":
|
|
109
|
+
from pfund_plot.plots.layout import Layout
|
|
110
|
+
|
|
111
|
+
return Layout
|
|
112
|
+
elif name == "tabs":
|
|
113
|
+
from pfund_plot.plots.layout.tabs import Tabs
|
|
114
|
+
|
|
115
|
+
return Tabs
|
|
116
|
+
elif name == "scatter":
|
|
117
|
+
from pfund_plot.plots.scatter import Scatter
|
|
118
|
+
|
|
119
|
+
return Scatter
|
|
120
|
+
elif name == "marker":
|
|
121
|
+
from pfund_plot.plots.scatter.marker import Marker
|
|
122
|
+
|
|
123
|
+
return Marker
|
|
124
|
+
elif name == "label":
|
|
125
|
+
from pfund_plot.plots.label import Label
|
|
126
|
+
|
|
127
|
+
return Label
|
|
128
|
+
elif name == "bar":
|
|
129
|
+
from pfund_plot.plots.bar import Bar
|
|
130
|
+
|
|
131
|
+
return Bar
|
|
132
|
+
elif name in ("altair", "vega"):
|
|
133
|
+
from pfund_plot.plots.altair import Altair
|
|
134
|
+
|
|
135
|
+
return Altair
|
|
136
|
+
elif name in ("matplotlib", "mpl"):
|
|
137
|
+
from pfund_plot.plots.matplotlib import Matplotlib
|
|
138
|
+
|
|
139
|
+
return Matplotlib
|
|
140
|
+
elif name == "bokeh":
|
|
141
|
+
from pfund_plot.plots.bokeh import Bokeh
|
|
142
|
+
|
|
143
|
+
return Bokeh
|
|
144
|
+
elif name in ("holoviews", "hv"):
|
|
145
|
+
from pfund_plot.plots.holoviews import Holoviews
|
|
146
|
+
|
|
147
|
+
return Holoviews
|
|
148
|
+
else:
|
|
149
|
+
raise AttributeError(f"'{__name__}' has no attribute '{name}'")
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
__all__ = (
|
|
153
|
+
"altair",
|
|
154
|
+
"area",
|
|
155
|
+
"bar",
|
|
156
|
+
"bokeh",
|
|
157
|
+
"candlestick",
|
|
158
|
+
"configure",
|
|
159
|
+
"get_config",
|
|
160
|
+
"holoviews",
|
|
161
|
+
"hv",
|
|
162
|
+
"kline",
|
|
163
|
+
"label",
|
|
164
|
+
"layout",
|
|
165
|
+
"line",
|
|
166
|
+
"marker",
|
|
167
|
+
"matplotlib",
|
|
168
|
+
"mpl",
|
|
169
|
+
"ohlc",
|
|
170
|
+
"plotly",
|
|
171
|
+
"scatter",
|
|
172
|
+
"tabs",
|
|
173
|
+
"vega",
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
def __dir__():
|
|
178
|
+
return sorted(__all__)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import sys
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
import click
|
|
6
|
+
|
|
7
|
+
GALLERY_DIR = Path(__file__).parent
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@click.command(hidden=True)
|
|
11
|
+
def gallery():
|
|
12
|
+
"""Open the gallery to visually verify all supported plots."""
|
|
13
|
+
script = GALLERY_DIR / "gallery_marimo.py"
|
|
14
|
+
result = subprocess.run(["marimo", "edit", str(script)], check=False)
|
|
15
|
+
sys.exit(result.returncode)
|