pycharting 0.2.6__tar.gz → 0.2.8__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pycharting
3
- Version: 0.2.6
3
+ Version: 0.2.8
4
4
  Summary: High-performance financial charting library for OHLC data visualization with technical indicators
5
5
  Home-page: https://github.com/alihaskar/pycharting
6
6
  License: MIT
@@ -27,6 +27,10 @@ Description-Content-Type: text/markdown
27
27
 
28
28
  # PyCharting
29
29
 
30
+ [![PyPI version](https://img.shields.io/pypi/v/pycharting.svg)](https://pypi.org/project/pycharting/)
31
+ [![Python versions](https://img.shields.io/pypi/pyversions/pycharting.svg)](https://pypi.org/project/pycharting/)
32
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
33
+
30
34
  High‑performance financial charting library for OHLC data visualization with technical indicators.
31
35
 
32
36
  ## Overview
@@ -78,6 +82,11 @@ poetry install
78
82
  ## Quick start
79
83
 
80
84
  The primary API is a single `plot` function that takes OHLC arrays (plus optional overlays and subplots), starts a local server, and opens your default browser on the interactive chart.
85
+ You normally import everything you need like this:
86
+
87
+ ```python
88
+ from pycharting import plot, stop_server, get_server_status
89
+ ```
81
90
 
82
91
  When you run this script, PyCharting will:
83
92
 
@@ -1,5 +1,9 @@
1
1
  # PyCharting
2
2
 
3
+ [![PyPI version](https://img.shields.io/pypi/v/pycharting.svg)](https://pypi.org/project/pycharting/)
4
+ [![Python versions](https://img.shields.io/pypi/pyversions/pycharting.svg)](https://pypi.org/project/pycharting/)
5
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
6
+
3
7
  High‑performance financial charting library for OHLC data visualization with technical indicators.
4
8
 
5
9
  ## Overview
@@ -51,6 +55,11 @@ poetry install
51
55
  ## Quick start
52
56
 
53
57
  The primary API is a single `plot` function that takes OHLC arrays (plus optional overlays and subplots), starts a local server, and opens your default browser on the interactive chart.
58
+ You normally import everything you need like this:
59
+
60
+ ```python
61
+ from pycharting import plot, stop_server, get_server_status
62
+ ```
54
63
 
55
64
  When you run this script, PyCharting will:
56
65
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "pycharting"
3
- version = "0.2.6"
3
+ version = "0.2.8"
4
4
  description = "High-performance financial charting library for OHLC data visualization with technical indicators"
5
5
  authors = ["ali askar <26202651+alihaskar@users.noreply.github.com>"]
6
6
  readme = "README.md"
@@ -19,13 +19,9 @@ classifiers = [
19
19
  "Topic :: Scientific/Engineering :: Visualization",
20
20
  ]
21
21
 
22
- # expose the public package as `pycharting` and ship internal modules as top-level packages
22
+ # expose the public package as `pycharting`
23
23
  packages = [
24
- { include = "pycharting", from = "src" },
25
- { include = "api", from = "src" },
26
- { include = "core", from = "src" },
27
- { include = "data", from = "src" },
28
- { include = "web", from = "src" },
24
+ { include = "pycharting", from = "src" }
29
25
  ]
30
26
 
31
27
  [tool.poetry.dependencies]
@@ -43,4 +39,4 @@ httpx = ">=0.27.0,<0.29.0"
43
39
 
44
40
  [build-system]
45
41
  requires = ["poetry-core>=1.9.0"]
46
- build-backend = "poetry.core.masonry.api"
42
+ build-backend = "poetry.core.masonry.api"
@@ -0,0 +1,49 @@
1
+ """
2
+ PyCharting: Interactive Financial Charting Library.
3
+
4
+ This package provides a high-performance, interactive charting solution for financial data
5
+ (OHLC), designed to handle large datasets efficiently. It uses a local server architecture
6
+ to render charts in the web browser, allowing for smooth zooming, panning, and analysis.
7
+
8
+ Key Features:
9
+ - **High Performance:** Capable of handling millions of data points using efficient data slicing.
10
+ - **Interactive:** Zoom, pan, and inspect data in real-time.
11
+ - **Flexible:** Support for overlays (e.g., Moving Averages) and subplots (e.g., RSI, Volume).
12
+ - **Easy to Use:** Simple Python API similar to matplotlib or plotly.
13
+
14
+ Usage:
15
+ The main entry point is the `plot` function.
16
+
17
+ ```python
18
+ from pycharting import plot, stop_server
19
+ import numpy as np
20
+
21
+ # Prepare your data (numpy arrays or pandas Series)
22
+ index = np.arange(100)
23
+ open_data = np.random.rand(100) + 100
24
+ high_data = open_data + 1
25
+ low_data = open_data - 1
26
+ close_data = open_data + 0.5
27
+
28
+ # Create and open the chart
29
+ plot(index, open_data, high_data, low_data, close_data)
30
+
31
+ # ... keep the script running if needed ...
32
+ # input("Press Enter to stop...")
33
+ # stop_server()
34
+ ```
35
+
36
+ Exports:
37
+ - `plot`: Main function to create and display charts.
38
+ - `stop_server`: Function to gracefully shut down the local chart server.
39
+ - `get_server_status`: Function to check the status of the background server.
40
+ """
41
+
42
+ from typing import Any, Dict # re-exported types are only for type checkers
43
+
44
+ from .api.interface import plot, stop_server, get_server_status # type: ignore F401
45
+
46
+ __all__ = ["plot", "stop_server", "get_server_status", "__version__"]
47
+
48
+ # Keep this in sync with pyproject.toml
49
+ __version__ = "0.2.8"
@@ -1,4 +1,19 @@
1
- """Main Python API interface for PyCharting."""
1
+ """
2
+ Main User Interface for PyCharting.
3
+
4
+ This module exposes the high-level functions that users interact with to create charts,
5
+ manage the server, and check status. It bridges the gap between the user's data (numpy/pandas)
6
+ and the internal server/data management logic.
7
+
8
+ The primary function is `plot()`, which orchestrates:
9
+ 1. Validating and ingesting user data via `DataManager`.
10
+ 2. Starting (or reusing) the background `ChartServer`.
11
+ 3. Constructing the visualization URL.
12
+ 4. Opening the chart in the user's default web browser.
13
+
14
+ It also provides utilities for manual server control (`stop_server`, `get_server_status`)
15
+ and Jupyter notebook integration.
16
+ """
2
17
 
3
18
  import webbrowser
4
19
  import time
@@ -7,9 +22,9 @@ from typing import Optional, Dict, Any, Union
7
22
  import numpy as np
8
23
  import pandas as pd
9
24
 
10
- from ..data.ingestion import DataManager
11
- from ..core.lifecycle import ChartServer
12
- from .routes import _data_managers
25
+ from pycharting.data.ingestion import DataManager
26
+ from pycharting.core.lifecycle import ChartServer
27
+ from pycharting.api.routes import _data_managers
13
28
 
14
29
  logger = logging.getLogger(__name__)
15
30
 
@@ -31,42 +46,65 @@ def plot(
31
46
  server_timeout: float = 2.0,
32
47
  ) -> Dict[str, Any]:
33
48
  """
34
- Create and display an interactive OHLC chart.
35
-
36
- This is the main entry point for PyCharting. It creates a chart server,
37
- loads your data, and opens it in your default web browser.
38
-
49
+ Generate and display an interactive OHLC (Open-High-Low-Close) financial chart.
50
+
51
+ This function is the primary interface for PyCharting. It performs the following steps:
52
+ 1. **Data Ingestion:** Converts input lists, pandas Series, or numpy arrays into optimized internal formats.
53
+ 2. **Server Management:** Checks if a background chart server is running. If not, it starts one on a separate thread.
54
+ 3. **Session Registration:** Stores the provided data under a `session_id`. This allows multiple charts to coexist
55
+ or data to be updated.
56
+ 4. **Browser Launch:** Automatically opens the default web browser to the generated chart URL.
57
+
58
+ The chart is rendered using a high-performance web frontend capable of handling millions of data points via
59
+ dynamic data slicing.
60
+
39
61
  Args:
40
- index: Time or index values for x-axis
41
- open: Opening prices
42
- high: High prices
43
- low: Low prices
44
- close: Closing prices
45
- overlays: Optional dict of overlay series (e.g., moving averages)
46
- subplots: Optional dict of subplot series (e.g., volume, indicators)
47
- session_id: Unique identifier for this chart session
48
- port: Server port (None for auto-discovery)
49
- open_browser: Whether to automatically open the browser
50
- server_timeout: Seconds to wait for server startup
51
-
62
+ index (Union[np.ndarray, pd.Series, list]): The x-axis data (timestamps or integer indices). Must have the same length as price arrays.
63
+ open (Union[np.ndarray, pd.Series, list]): Opening prices.
64
+ high (Union[np.ndarray, pd.Series, list]): Highest prices during the interval.
65
+ low (Union[np.ndarray, pd.Series, list]): Lowest prices during the interval.
66
+ close (Union[np.ndarray, pd.Series, list]): Closing prices.
67
+ overlays (Optional[Dict[str, Union[np.ndarray, pd.Series, list]]]): A dictionary of additional series to plot *over* the main price chart.
68
+ Keys are labels (e.g., "SMA 50"), values are data arrays. Useful for Moving Averages, Bollinger Bands, etc.
69
+ subplots (Optional[Dict[str, Union[np.ndarray, pd.Series, list]]]): A dictionary of series to plot in separate panels *below* the main chart.
70
+ Keys are labels (e.g., "RSI", "Volume"), values are data arrays.
71
+ session_id (str): A unique identifier for this dataset. Use different IDs to keep multiple charts active simultaneously.
72
+ Defaults to "default".
73
+ port (Optional[int]): Specific port to run the server on. If `None` (default), a free port is automatically found.
74
+ open_browser (bool): If `True` (default), automatically launches the system's default web browser to view the chart.
75
+ server_timeout (float): Maximum time (in seconds) to wait for the server to start before proceeding. Defaults to 2.0.
76
+
52
77
  Returns:
53
- Dict with server info including URL and status
54
-
78
+ Dict[str, Any]: A dictionary containing execution details:
79
+ - `status`: "success" or "error".
80
+ - `url`: The full URL to view the chart.
81
+ - `server_url`: The base URL of the server.
82
+ - `session_id`: The session ID used.
83
+ - `data_points`: Number of data points loaded.
84
+ - `server_running`: Boolean indicating if the server is active.
85
+
55
86
  Example:
56
87
  ```python
57
88
  import numpy as np
58
89
  from pycharting import plot
59
-
60
- # Generate sample data
61
- n = 100
90
+
91
+ # 1. Prepare Data
92
+ n = 1000
62
93
  index = np.arange(n)
63
94
  close = np.cumsum(np.random.randn(n)) + 100
64
- open = close + np.random.randn(n) * 0.5
65
- high = np.maximum(open, close) + np.abs(np.random.randn(n))
66
- low = np.minimum(open, close) - np.abs(np.random.randn(n))
95
+ open_p = close + np.random.randn(n) * 0.5
96
+ high = np.maximum(open_p, close) + np.abs(np.random.randn(n))
97
+ low = np.minimum(open_p, close) - np.abs(np.random.randn(n))
67
98
 
68
- # Create interactive chart
69
- plot(index, open, high, low, close)
99
+ # 2. Add Indicators
100
+ sma = np.convolve(close, np.ones(20)/20, mode='same')
101
+
102
+ # 3. Plot with Overlay
103
+ plot(
104
+ index, open_p, high, low, close,
105
+ overlays={"SMA 20": sma},
106
+ session_id="my-analysis"
107
+ )
70
108
  ```
71
109
  """
72
110
  global _active_server
@@ -177,16 +215,19 @@ def plot(
177
215
 
178
216
  def stop_server():
179
217
  """
180
- Stop the active chart server.
181
-
182
- Call this to manually stop the server when you're done viewing charts.
183
- The server also auto-stops after 5 minutes of inactivity.
184
-
218
+ Manually shut down the active chart server.
219
+
220
+ While the server has an auto-shutdown feature (triggered after a timeout when no clients are connected),
221
+ this function allows for immediate, manual cleanup. This is useful in scripts or notebooks where you want
222
+ to ensure resources are freed immediately after a session.
223
+
224
+ If no server is running, this function does nothing and prints a message.
225
+
185
226
  Example:
186
227
  ```python
187
228
  from pycharting import stop_server
188
-
189
- # When done with all charts
229
+
230
+ # ... after done with analysis ...
190
231
  stop_server()
191
232
  ```
192
233
  """
@@ -202,17 +243,23 @@ def stop_server():
202
243
 
203
244
  def get_server_status() -> Dict[str, Any]:
204
245
  """
205
- Get the status of the active chart server.
206
-
246
+ Retrieve the current status of the background chart server.
247
+
248
+ This is useful for debugging connection issues or checking if a session is still active.
249
+
207
250
  Returns:
208
- Dict with server status information
209
-
251
+ Dict[str, Any]: A dictionary containing:
252
+ - `running`: Boolean indicating if the server process is alive.
253
+ - `server_info`: Dictionary of host, port, and connection details (or None).
254
+ - `active_sessions`: Count of currently loaded datasets/sessions.
255
+
210
256
  Example:
211
257
  ```python
212
258
  from pycharting import get_server_status
213
259
 
214
260
  status = get_server_status()
215
- print(status)
261
+ if status['running']:
262
+ print(f"Server running at {status['server_info']['url']}")
216
263
  ```
217
264
  """
218
265
  global _active_server
@@ -1,4 +1,15 @@
1
- """API routes for PyCharting data fetching and control."""
1
+ """
2
+ API Routes Definition for PyCharting.
3
+
4
+ This module defines the REST API endpoints that the frontend JavaScript uses to:
5
+ 1. Fetch sliced and diced OHLC data (`/data`).
6
+ 2. Manage data sessions (`/sessions`).
7
+ 3. Check system status (`/status`).
8
+ 4. Initialize demo data (`/data/init`).
9
+
10
+ The data is served from the in-memory `_data_managers` registry, which is populated
11
+ by the main Python process via `src.api.interface.plot()`.
12
+ """
2
13
 
3
14
  from typing import Optional, Dict, Any
4
15
  from fastapi import APIRouter, HTTPException, Query
@@ -42,18 +53,25 @@ async def get_data(
42
53
  session_id: str = Query("default", description="Session identifier for data source"),
43
54
  ):
44
55
  """
45
- Fetch OHLC data chunk for the specified range.
46
-
56
+ Retrieve a specific slice of OHLC data.
57
+
58
+ This endpoint is optimized for high-performance frontend rendering. Instead of sending the full dataset
59
+ at once (which could be millions of points), the frontend requests only the necessary chunk
60
+ based on the current zoom level and viewport.
61
+
47
62
  Args:
48
- start_index: Starting index (inclusive)
49
- end_index: Ending index (exclusive), None for end of data
50
- session_id: Session identifier for data source
51
-
63
+ start_index (int): The zero-based index of the first data point to retrieve.
64
+ end_index (Optional[int]): The zero-based index of the last data point (exclusive).
65
+ If None, retrieves data until the end of the series.
66
+ session_id (str): The ID of the data session to query.
67
+
52
68
  Returns:
53
- DataResponse with OHLC data and metadata
54
-
69
+ DataResponse: A JSON object containing parallel arrays for index, open, high, low, close,
70
+ overlays, and subplots for the requested range.
71
+
55
72
  Raises:
56
- HTTPException: If session not found or invalid parameters
73
+ HTTPException(404): If the specified session_id does not exist.
74
+ HTTPException(500): If an internal error occurs during data slicing.
57
75
  """
58
76
  # Check if session exists
59
77
  if session_id not in _data_managers:
@@ -91,19 +109,19 @@ async def initialize_data(
91
109
  session_id: str = Query("default", description="Session identifier"),
92
110
  ):
93
111
  """
94
- Initialize a data session (placeholder for demo).
95
-
96
- In production, this would accept data upload or configuration.
97
- For now, it creates a demo dataset.
98
-
112
+ Initialize a demo data session.
113
+
114
+ This endpoint is primarily used for testing or the standalone demo mode.
115
+ It generates synthetic random walk data and registers it under the given session ID.
116
+
99
117
  Args:
100
- session_id: Session identifier
101
-
118
+ session_id (str): The ID to assign to the new session.
119
+
102
120
  Returns:
103
- Session information
121
+ dict: Status message and session details.
104
122
  """
105
123
  import numpy as np
106
- from ..data.ingestion import DataManager
124
+ from pycharting.data.ingestion import DataManager
107
125
 
108
126
  try:
109
127
  # Generate demo OHLC data
@@ -163,10 +181,11 @@ async def initialize_data(
163
181
  @router.get("/sessions")
164
182
  async def list_sessions():
165
183
  """
166
- List active data sessions.
167
-
184
+ List all currently active data sessions.
185
+
168
186
  Returns:
169
- List of active session IDs with metadata
187
+ dict: A dictionary containing a list of session objects, each with metadata
188
+ like the number of data points and active features (overlays, subplots).
170
189
  """
171
190
  sessions = []
172
191
  for session_id, dm in _data_managers.items():
@@ -186,16 +205,18 @@ async def list_sessions():
186
205
  @router.delete("/sessions/{session_id}")
187
206
  async def delete_session(session_id: str):
188
207
  """
189
- Delete a data session.
190
-
208
+ Remove a data session from memory.
209
+
210
+ This frees up resources associated with a specific dataset.
211
+
191
212
  Args:
192
- session_id: Session identifier to delete
193
-
213
+ session_id (str): The ID of the session to remove.
214
+
194
215
  Returns:
195
- Success message
196
-
216
+ dict: Confirmation message.
217
+
197
218
  Raises:
198
- HTTPException: If session not found
219
+ HTTPException(404): If the session ID is not found.
199
220
  """
200
221
  if session_id not in _data_managers:
201
222
  raise HTTPException(
@@ -1,4 +1,15 @@
1
- """Server lifecycle management for PyCharting."""
1
+ """
2
+ Server Lifecycle Management for PyCharting.
3
+
4
+ This module manages the background execution and lifecycle of the PyCharting server.
5
+ Since the main Python script (e.g., a data science notebook or script) needs to remain responsive,
6
+ the chart server runs in a separate background thread.
7
+
8
+ This module handles:
9
+ - **Thread Management:** Starting and stopping the server in a daemon thread.
10
+ - **Heartbeat Monitoring:** Checking for WebSocket connections from the frontend.
11
+ - **Auto-Shutdown:** Automatically stopping the server when the browser tab is closed (connection lost) to prevent orphaned processes.
12
+ """
2
13
 
3
14
  import threading
4
15
  import time
@@ -7,17 +18,25 @@ from typing import Optional, Dict, Any
7
18
  from datetime import datetime
8
19
  import uvicorn
9
20
  from fastapi import WebSocket, WebSocketDisconnect
10
- from .server import create_app, find_free_port
21
+ from pycharting.core.server import create_app, find_free_port
11
22
 
12
23
  logger = logging.getLogger(__name__)
13
24
 
14
25
 
15
26
  class ChartServer:
16
27
  """
17
- Manages the lifecycle of the PyCharting server.
18
-
19
- Runs Uvicorn in a background thread and provides auto-shutdown
20
- capability when WebSocket connections are lost.
28
+ A controller for managing the PyCharting background server.
29
+
30
+ This class encapsulates the logic for running the FastAPI/Uvicorn server in a separate thread.
31
+ It includes a heartbeat mechanism that monitors a WebSocket connection from the frontend.
32
+ If the frontend disconnects (e.g., user closes the tab), the server can automatically shut down
33
+ after a configurable timeout.
34
+
35
+ Attributes:
36
+ host (str): The hostname to bind to.
37
+ port (int): The port to bind to.
38
+ auto_shutdown_timeout (float): Time in seconds to wait before shutting down after connection loss.
39
+ app (FastAPI): The underlying FastAPI application instance.
21
40
  """
22
41
 
23
42
  def __init__(
@@ -27,12 +46,13 @@ class ChartServer:
27
46
  auto_shutdown_timeout: float = 5.0,
28
47
  ):
29
48
  """
30
- Initialize ChartServer.
31
-
49
+ Initialize the ChartServer controller.
50
+
32
51
  Args:
33
- host: Host to bind the server to
34
- port: Port to use (None for auto-discovery)
35
- auto_shutdown_timeout: Seconds to wait before auto-shutdown after disconnect
52
+ host (str): Host to bind the server to. Defaults to "127.0.0.1".
53
+ port (Optional[int]): Port to use. If None, an available port is found automatically.
54
+ auto_shutdown_timeout (float): Seconds to wait before auto-shutdown after the last client disconnects.
55
+ Defaults to 5.0 seconds.
36
56
  """
37
57
  self.host = host
38
58
  self.port = port or find_free_port()
@@ -122,13 +142,24 @@ class ChartServer:
122
142
 
123
143
  def start_server(self) -> Dict[str, Any]:
124
144
  """
125
- Start the server in a background thread.
126
-
145
+ Start the web server in a background daemon thread.
146
+
147
+ This method:
148
+ 1. Checks if the server is already running.
149
+ 2. Starts the Uvicorn server in a separate thread.
150
+ 3. Starts a monitor thread to check for WebSocket heartbeats.
151
+ 4. Waits briefly to ensure the server is up.
152
+
127
153
  Returns:
128
- Dict with server information (host, port, url)
129
-
154
+ Dict[str, Any]: A dictionary containing connection details:
155
+ - `host`: The server host.
156
+ - `port`: The server port.
157
+ - `url`: The full HTTP URL to the server.
158
+ - `ws_url`: The WebSocket URL for heartbeats.
159
+ - `running`: Boolean status.
160
+
130
161
  Raises:
131
- RuntimeError: If server is already running
162
+ RuntimeError: If the server is already running.
132
163
  """
133
164
  if self._running:
134
165
  raise RuntimeError("Server is already running")
@@ -169,7 +200,12 @@ class ChartServer:
169
200
  }
170
201
 
171
202
  def stop_server(self):
172
- """Stop the server gracefully."""
203
+ """
204
+ Gracefully stop the background server and monitor threads.
205
+
206
+ This method signals the server to shut down, closes the Uvicorn loop,
207
+ and joins the background threads. It is safe to call multiple times.
208
+ """
173
209
  if not self._running:
174
210
  logger.warning("Server is not running")
175
211
  return