### Install PyCharting from Source Source: https://github.com/alihaskar/pycharting/blob/master/README.md Installs the pycharting package from its source code, suitable for development. It clones the repository and installs the package using pip's editable mode. ```bash git clone https://github.com/alihaskar/pycharting.git cd pycharting pip install -e . ``` -------------------------------- ### Page Load Initialization (JavaScript) Source: https://github.com/alihaskar/pycharting/blob/master/src/pycharting/web/static/viewport-demo.html Handles the initial setup of the charting application when the page loads. It checks for an existing session ID to initialize data and chart heights, or proceeds with general chart setup if no session is found. ```javascript window.addEventListener('load', () => { const sessionId = getSessionId(); if (sessionId) { // When launched via Python API, auto-init using existing session initializeData(); initializeChartHeights(); setupHeartbeat(); } else { setupChart(); initializeChartHeights(); } }); ``` -------------------------------- ### Install PyCharting from PyPI Source: https://github.com/alihaskar/pycharting/blob/master/README.md Installs the latest released version of the pycharting package and its runtime dependencies (numpy, pandas, fastapi, uvicorn, etc.) using pip. ```bash pip install pycharting ``` -------------------------------- ### Install PyCharting with Poetry Source: https://github.com/alihaskar/pycharting/blob/master/README.md Installs the pycharting package from its source code using Poetry. This is an alternative to pip for managing dependencies and installations. ```bash git clone https://github.com/alihaskar/pycharting.git cd pycharting poetry install ``` -------------------------------- ### Initialize and Setup PyChart Source: https://github.com/alihaskar/pycharting/blob/master/src/pycharting/web/static/viewport-demo.html Initializes the PyChart instance with a specified container and height. It also includes logic for setting up the measurement tool button, ensuring it's registered and functional. ```javascript let chart = null; let viewportManager = null; // Name -> uPlot instance for indicator-style subplots let subplotCharts = {}; function getSessionId() { const params = new URLSearchParams(window.location.search); return params.get('session') || null; } // Initialize chart function setupChart() { const container = document.getElementById('chartContainer'); const height = container.offsetHeight || 500; chart = new PyChart(container, { title: '', height: height }); // Setup measurement tool button (only once) setupMeasurementButton(); } // Setup measurement tool button function setupMeasurementButton() { const measureBtn = document.getElementById('measureBtn'); if (!measureBtn) { console.error('Measurement button not found'); return; } // Remove existing listeners (if any) const newBtn = measureBtn.cloneNode(true); measureBtn.parentNode.replaceChild(newBtn, measureBtn); chart.registerMeasurementButton(newBtn); // Add click handler newBtn.addEventListener('click', (e) => { e.preventDefault(); console.log('Measurement button clicked'); if (!chart) { console.error('Chart not initialized'); return; } if (chart.measurementEnabled) { console.log('Disabling measurement tool'); chart.disableMeasurementTool(); } else { console.log('Enabling measurement tool'); chart.enableMeasurementTool(); } }); console.log('Measurement button initialized'); } ``` -------------------------------- ### GET /api/data - Retrieve Sliced OHLC Data (Bash) Source: https://context7.com/alihaskar/pycharting/llms.txt This bash command demonstrates how to fetch a specific range of OHLC data for a given session using the GET /api/data endpoint. It shows examples for fetching a subset of data, fetching all data, and an error case for a non-existent session. ```bash # Fetch data points 0-1000 from default session curl "http://127.0.0.1:8000/api/data?start_index=0&end_index=1000&session_id=default" # Fetch all data (omit end_index) curl "http://127.0.0.1:8000/api/data?session_id=my-analysis" # Error case: session not found curl "http://127.0.0.1:8000/api/data?session_id=nonexistent" ``` -------------------------------- ### GET /api/sessions - List Active Sessions (Bash) Source: https://context7.com/alihaskar/pycharting/llms.txt This bash command demonstrates how to list all currently active data sessions using the GET /api/sessions endpoint. It shows the command and the expected JSON response containing session details. ```bash curl "http://127.0.0.1:8000/api/sessions" ``` -------------------------------- ### Setup Main Chart Resizing (JavaScript) Source: https://github.com/alihaskar/pycharting/blob/master/src/pycharting/web/static/viewport-demo.html Handles the interactive resizing of the main chart container using mouse events. It listens for mousedown on a handle, tracks mouse movement to adjust the container's height, and updates the chart's dimensions accordingly. It prevents default behavior to avoid text selection during drag. ```javascript function setupMainResize() { const chartContainer = document.getElementById('chartContainer'); const handle = document.getElementById('mainResizeHandle'); let isResizing = false; let startY = 0; let startHeight = 0; handle.addEventListener('mousedown', (e) => { isResizing = true; startY = e.clientY; startHeight = chartContainer.offsetHeight; e.preventDefault(); }); document.addEventListener('mousemove', (e) => { if (!isResizing) return; const deltaY = e.clientY - startY; const newHeight = Math.max(200, startHeight + deltaY); chartContainer.style.height = newHeight + 'px'; chartContainer.style.flex = 'none'; // Resize the uPlot chart if (chart && chart.chart) { chart.setSize(chartContainer.offsetWidth, newHeight); } }); document.addEventListener('mouseup', () => { isResizing = false; }); } ``` -------------------------------- ### Setup Viewport Tracking Source: https://github.com/alihaskar/pycharting/blob/master/src/pycharting/web/static/viewport-demo.html Sets up an interval to periodically track and log the current viewport scale of the chart. This is useful for debugging or implementing features that react to viewport changes. ```javascript // Setup viewport tracking function setupViewportTracking() { if (!chart.chart) return; // Track viewport changes setInterval(() => { if (chart.chart && chart.chart.scales) { // Example: Log the current scale // console.log('Current scale:', chart.chart.scales.x.range); } }, 1000); // Check every second } ``` -------------------------------- ### Setup Main Chart Resize Handle (JavaScript) Source: https://github.com/alihaskar/pycharting/blob/master/src/pycharting/web/static/viewport-demo.html Initializes the resize functionality for the main chart container. This function selects the main resize handle and the chart container elements from the DOM and is intended to set up the necessary event listeners for resizing the main chart area. ```javascript function setupMainResize() { const handle = document.getElementById('mainResizeHandle'); const chartContainer = document.getElementById('chartContainer'); const mainContainer = document } ``` -------------------------------- ### Setup WebSocket Heartbeat (JavaScript) Source: https://github.com/alihaskar/pycharting/blob/master/src/pycharting/web/static/viewport-demo.html Establishes a WebSocket connection for a heartbeat mechanism. It connects to a '/ws/heartbeat' endpoint and sends a 'ping' every 500ms to maintain the connection. It includes error handling and cleans up the connection when the page is unloaded. ```javascript function setupHeartbeat() { const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:'; const wsUrl = `${protocol}//${window.location.host}/ws/heartbeat`; console.log('Connecting to heartbeat:', wsUrl); const ws = new WebSocket(wsUrl); ws.onopen = () => { console.log('Heartbeat connected'); // Send ping every 500ms (faster than backend timeout) const interval = setInterval(() => { if (ws.readyState === WebSocket.OPEN) { ws.send('ping'); } else { clearInterval(interval); } }, 500); // Clean up on page unload window.addEventListener('beforeunload', () => { clearInterval(interval); ws.close(); }); }; ws.onmessage = (event) => { if (event.data === 'pong') { console.debug('Heartbeat pong received'); } }; ws.onerror = (error) => { console.error('Heartbeat error:', error); }; ws.onclose = () => { console.log('Heartbeat disconnected'); }; } ``` -------------------------------- ### GET /api/sessions - List Active Sessions Source: https://context7.com/alihaskar/pycharting/llms.txt Returns all currently active data sessions with metadata about each session's data and features. ```APIDOC ## GET /api/sessions ### Description Returns all currently active data sessions with metadata about each session's data and features. ### Method GET ### Endpoint /api/sessions ### Response #### Success Response (200) - **sessions** (array) - An array of session objects. - **session_id** (string) - The identifier of the session. - **data_points** (integer) - The number of data points in the session. - **has_overlays** (boolean) - Indicates if the session has overlay data. - **has_subplots** (boolean) - Indicates if the session has subplot data. - **count** (integer) - The total number of active sessions. ### Request Example ```bash curl "http://127.0.0.1:8000/api/sessions" ``` ### Response Example ```json { "sessions": [ { "session_id": "default", "data_points": 5000, "has_overlays": true, "has_subplots": true }, { "session_id": "analysis-2", "data_points": 10000, "has_overlays": false, "has_subplots": false } ], "count": 2 } ``` ``` -------------------------------- ### GET /health - Server Health Check Source: https://context7.com/alihaskar/pycharting/llms.txt A simple endpoint to check the overall health of the server. ```APIDOC ## GET /health ### Description Provides a basic health check for the server. ### Method GET ### Endpoint /health ### Parameters #### Path Parameters None #### Query Parameters None ### Request Example ```bash curl "http://127.0.0.1:8000/health" ``` ### Response #### Success Response (200) - **status** (string) - The health status of the service (e.g., "healthy"). - **service** (string) - The name of the service being checked (e.g., "pycharting"). #### Response Example ```json {"status": "healthy", "service": "pycharting"} ``` ``` -------------------------------- ### DataManager - High-Performance Data Container (Python) Source: https://context7.com/alihaskar/pycharting/llms.txt Demonstrates the usage of the DataManager class for validating, normalizing, and storing OHLC data. It handles various input formats (lists, Pandas Series, NumPy arrays) and provides chunk-based data access. Includes examples of initialization, data retrieval, and error handling for invalid data. ```python from pycharting.data.ingestion import DataManager, DataValidationError import numpy as np import pandas as pd # Generate sample data n = 10000 index = np.arange(n) close = np.cumsum(np.random.randn(n)) + 100 open_prices = close + np.random.randn(n) * 0.5 high = np.maximum(open_prices, close) + np.abs(np.random.randn(n)) low = np.minimum(open_prices, close) - np.abs(np.random.randn(n)) overlays = {"SMA 20": np.convolve(close, np.ones(20)/20, mode="same")} subplots = {"Volume": np.abs(np.random.randn(n)) * 10000} # Create DataManager with full OHLC data dm = DataManager( index=index, open=open_prices, high=high, low=low, close=close, overlays=overlays, subplots=subplots, ) print(f"DataManager: {dm}") # DataManager(10000 points) print(f"Length: {dm.length}") # 10000 print(f"Overlays: {list(dm.overlays.keys())}") # ['SMA 20'] print(f"Subplots: {list(dm.subplots.keys())}") # ['Volume'] # Get data chunk for viewport (indices 1000-2000) chunk = dm.get_chunk(start_index=1000, end_index=2000) print(f"Chunk size: {len(chunk['index'])}") # 1000 print(f"Keys: {list(chunk.keys())}") # ['index', 'open', 'high', 'low', 'close', 'overlays', 'subplots'] # DataManager works with various input types dm_from_lists = DataManager( index=list(range(100)), close=[100 + i * 0.1 for i in range(100)], ) dm_from_pandas = DataManager( index=pd.date_range("2024-01-01", periods=100, freq="h"), close=pd.Series(np.random.randn(100).cumsum() + 100), ) # Error handling for invalid data try: DataManager( index=np.arange(100), close=np.arange(50), # Mismatched length ) except DataValidationError as e: print(f"Validation error: {e}") # Close length (50) does not match index length (100) ``` -------------------------------- ### Server Health Check Endpoint Source: https://context7.com/alihaskar/pycharting/llms.txt Provides a simple health check for the PyCharting server, indicating its operational status. Accessed via a GET request to /health. ```bash curl "http://127.0.0.1:8000/health" # Response: # {"status": "healthy", "service": "pycharting"} ``` -------------------------------- ### Setup Resize Handler for Subplot Charts (JavaScript) Source: https://github.com/alihaskar/pycharting/blob/master/src/pycharting/web/static/viewport-demo.html This function sets up event listeners for a given resize handle element to enable interactive resizing of subplot charts. It captures mouse down events to initiate resizing, tracks mouse movement to adjust height, and handles mouse up events to conclude resizing. It also updates the dimensions of the associated uPlot chart. ```javascript function setupResizeHandle(handle, wrapper, chartDiv) { let isResizing = false; let startY = 0; let startHeight = 0; handle.addEventListener('mousedown', (e) => { isResizing = true; startY = e.clientY; startHeight = wrapper.offsetHeight; e.preventDefault(); }); document.addEventListener('mousemove', (e) => { if (!isResizing) return; const deltaY = e.clientY - startY; const newHeight = Math.max(80, startHeight + deltaY); const newChartHeight = newHeight - 20; wrapper.style.height = newHeight + 'px'; chartDiv.style.height = newChartHeight + 'px'; const chartName = wrapper.dataset.name; if (subplotCharts[chartName]) { subplotCharts[chartName].setSize({ width: chartDiv.offsetWidth, height: newChartHeight }); } }); document.addEventListener('mouseup', () => { isResizing = false; }); } ``` -------------------------------- ### GET /api/status - API Health Check Source: https://context7.com/alihaskar/pycharting/llms.txt This endpoint provides a health check for the API, returning its current status and a list of available endpoints. ```APIDOC ## GET /api/status ### Description Returns the current status of the API and a dictionary of active endpoints. ### Method GET ### Endpoint /api/status ### Parameters #### Path Parameters None #### Query Parameters None ### Request Example ```bash curl "http://127.0.0.1:8000/api/status" ``` ### Response #### Success Response (200) - **status** (string) - The current health status of the API (e.g., "healthy"). - **active_sessions** (integer) - The number of currently active sessions. - **endpoints** (object) - A dictionary mapping endpoint names to their respective paths. - **data** (string) - Path to the data endpoint. - **init** (string) - Path to the data initialization endpoint. - **sessions** (string) - Path to the sessions endpoint. - **status** (string) - Path to the status endpoint. #### Response Example ```json { "status": "healthy", "active_sessions": 1, "endpoints": { "data": "/api/data", "init": "/api/data/init", "sessions": "/api/sessions", "status": "/api/status" } } ``` ``` -------------------------------- ### GET /api/data - Retrieve Sliced OHLC Data Source: https://context7.com/alihaskar/pycharting/llms.txt Fetches a specific range of OHLC data for a given session. Designed for high-performance frontend rendering where only the visible viewport data is requested. ```APIDOC ## GET /api/data ### Description Fetches a specific range of OHLC data for a given session. Designed for high-performance frontend rendering where only the visible viewport data is requested. ### Method GET ### Endpoint /api/data #### Query Parameters - **start_index** (integer) - Optional - The starting index of the data slice. - **end_index** (integer) - Optional - The ending index of the data slice. If omitted, all data from start_index is returned. - **session_id** (string) - Required - The identifier for the data session. ### Response #### Success Response (200) - **index** (array) - Array of timestamps or indices. - **open** (array) - Array of opening prices. - **high** (array) - Array of high prices. - **low** (array) - Array of low prices. - **close** (array) - Array of closing prices. - **overlays** (object) - Object containing overlay data (e.g., SMAs). - **subplots** (object) - Object containing subplot data (e.g., RSI, Volume). - **start_index** (integer) - The starting index of the returned data. - **end_index** (integer) - The ending index of the returned data. - **total_length** (integer) - The total number of data points in the session. #### Error Response (404) - **detail** (string) - Error message indicating the session was not found. ### Request Example ```bash curl "http://127.0.0.1:8000/api/data?start_index=0&end_index=1000&session_id=default" ``` ### Response Example ```json { "index": [0, 1, 2, ...], "open": [100.5, 101.2, ...], "high": [102.1, 103.0, ...], "low": [99.8, 100.1, ...], "close": [101.0, 102.5, ...], "overlays": {"SMA 50": [100.0, 100.1, ...]}, "subplots": {"RSI": [50.2, 51.3, ...]}, "start_index": 0, "end_index": 1000, "total_length": 5000 } ``` ``` -------------------------------- ### Get PyCharting Server Status Source: https://context7.com/alihaskar/pycharting/llms.txt Returns the current status of the background chart server, including connection details and active session count. This is useful for debugging and programmatic server management. ```python from pycharting import plot, get_server_status, stop_server import numpy as np # Check status before starting status = get_server_status() print(f"Running: {status['running']}") # False print(f"Active sessions: {status['active_sessions']}") # 0 # Create a chart n = 1000 plot(np.arange(n), close=np.cumsum(np.random.randn(n)) + 100, block=False) # Check status after starting status = get_server_status() print(f"Running: {status['running']}") # True print(f"Active sessions: {status['active_sessions']}") # 1 ``` -------------------------------- ### Generate Synthetic OHLC Data Source: https://github.com/alihaskar/pycharting/blob/master/src/pycharting/web/static/demo.html Creates synthetic Open, High, Low, Close (OHLC) data for a specified number of candles. It generates timestamps and price data with a defined starting price and introduces random volatility. ```javascript // Generate synthetic OHLC data function generateOHLCData(numCandles, startPrice = 100) { const timestamps = []; const open = []; const high = []; const low = []; const close = []; let currentPrice = startPrice; const startTime = Date.now() - (numCandles * 3600000); // 1 hour per candle in milliseconds for (let i = 0; i < numCandles; i++) { timestamps.push(startTime + (i * 3600000)); // milliseconds const o = currentPrice; const volatility = currentPrice * 0.02; const change = (Math.random() - 0.5) * volatility; const c = o + change; const h = Math.max(o, c) + Math.random() * volatility * 0.5; const l = Math.min(o, c) - Math.random() * volatility * 0.5; open.push(o); high.push(h); low.push(l); close.push(c); currentPrice = c; } return [timestamps, open, high, low, close]; } ``` -------------------------------- ### Generate OHLC and Line Charts with PyCharting Source: https://context7.com/alihaskar/pycharting/llms.txt Generates interactive OHLC or line charts. This function validates input data, starts a background FastAPI server, registers data, and opens the chart in the browser. It supports numeric and DatetimeIndex, candlestick and line chart types, and allows for overlays and subplots. It can operate in blocking or non-blocking modes. ```python import numpy as np import pandas as pd from pycharting import plot, stop_server # Generate synthetic OHLC data n = 5000 close = np.cumsum(np.random.randn(n)) + 100 open_prices = close + np.random.randn(n) * 0.5 high = np.maximum(open_prices, close) + np.abs(np.random.randn(n)) low = np.minimum(open_prices, close) - np.abs(np.random.randn(n)) # Calculate Simple Moving Average overlay def sma(values, window): kernel = np.ones(window) / window return np.convolve(values, kernel, mode="same") # Calculate RSI-like subplot indicator def rsi_like(values, period=14): delta = np.diff(values, prepend=values[0]) gain = np.where(delta > 0, delta, 0.0) loss = np.where(delta < 0, -delta, 0.0) avg_gain = sma(gain, period) avg_loss = sma(loss, period) rs = np.divide(avg_gain, avg_loss, out=np.zeros_like(avg_gain), where=avg_loss != 0) return 100.0 - (100.0 / (1.0 + rs)) # Create overlays (rendered on price chart) overlays = { "SMA 50": sma(close, 50), "SMA 200": sma(close, 200), } # Create subplots (rendered in separate panels) subplots = { "RSI": rsi_like(close, 14), "Volume": np.abs(np.random.randn(n)) * 10000 + 5000, } # Option 1: Numeric index with candlestick chart result = plot( index=np.arange(n), open=open_prices, high=high, low=low, close=close, overlays=overlays, subplots=subplots, session_id="analysis-1", open_browser=True, block=True, # Block until browser tab is closed ) # Output: # ✓ Chart created successfully! # URL: http://127.0.0.1:8000/static/viewport-demo.html?session=analysis-1&v=1234567890 # Data points: 5,000 print(f"Status: {result['status']}") print(f"URL: {result['url']}") print(f"Data points: {result['data_points']}") # Option 2: Pandas DatetimeIndex date_index = pd.date_range(start="2024-01-01", periods=n, freq="h") plot(date_index, open=open_prices, high=high, low=low, close=close) # Option 3: Line chart (close only) plot(np.arange(n), close=close, overlays=overlays, subplots=subplots) # Option 4: Non-blocking mode result = plot( np.arange(n), close=close, open_browser=False, # Don't auto-open browser block=False, # Don't block execution ) print(f"Open this URL manually: {result['url']}") ``` -------------------------------- ### POST /api/data/init - Initialize Demo Data Session Source: https://context7.com/alihaskar/pycharting/llms.txt Creates a demo data session with synthetic OHLC data. Primarily used for testing or standalone demo mode. ```APIDOC ## POST /api/data/init ### Description Creates a demo data session with synthetic OHLC data. Primarily used for testing or standalone demo mode. ### Method POST ### Endpoint /api/data/init #### Query Parameters - **session_id** (string) - Required - The identifier for the new demo session. ### Response #### Success Response (200) - **session_id** (string) - The identifier of the created session. - **status** (string) - The status of the initialization (e.g., "initialized"). - **data_points** (integer) - The number of data points generated for the demo session. - **message** (string) - A confirmation message. ### Request Example ```bash curl -X POST "http://127.0.0.1:8000/api/data/init?session_id=demo" ``` ### Response Example ```json { "session_id": "demo", "status": "initialized", "data_points": 1000, "message": "Demo dataset created successfully" } ``` ``` -------------------------------- ### POST /api/data/init - Initialize Demo Data Session (Bash) Source: https://context7.com/alihaskar/pycharting/llms.txt This bash command demonstrates how to initialize a demo data session using the POST /api/data/init endpoint. It shows the command to create a session named 'demo' and the expected JSON response. ```bash # Initialize demo session curl -X POST "http://127.0.0.1:8000/api/data/init?session_id=demo" ``` -------------------------------- ### Run PyCharting Demo Source: https://github.com/alihaskar/pycharting/blob/master/README.md Executes the demo script for PyCharting from the project's root directory. This script typically generates synthetic data and visualizes it using the library's features. ```bash python demo.py ``` -------------------------------- ### API Health Check Endpoint Source: https://context7.com/alihaskar/pycharting/llms.txt Checks the health status of the PyCharting API and lists available endpoints. It is accessed via a GET request to /api/status. ```bash curl "http://127.0.0.1:8000/api/status" # Response: # { # "status": "healthy", # "active_sessions": 1, # "endpoints": { # "data": "/api/data", # "init": "/api/data/init", # "sessions": "/api/sessions", # "status": "/api/status" # } # } ``` -------------------------------- ### Check Server Status and Stop Server (Python) Source: https://context7.com/alihaskar/pycharting/llms.txt This Python snippet demonstrates how to check the status of a server, including running status, server URL, and active sessions. It also shows how to stop the server. Assumes a `get_server_status` and `stop_server` function are available. ```python status = get_server_status() print(f"Running: {status['running']}") # True print(f"Server URL: http://{status['server_info']['host']}:{status['server_info']['port']}") print(f"Active sessions: {status['active_sessions']}") # 1 stop_server() ``` -------------------------------- ### run_server - Direct Server Launch Source: https://context7.com/alihaskar/pycharting/llms.txt Launches the PyCharting web server directly in the main thread, making it a blocking operation. This is suitable for development or standalone server deployments. ```APIDOC ## run_server - Direct Server Launch ### Description Launches the PyCharting web server in the current thread, blocking execution until the server is stopped. This function is ideal for development environments or when running the server as a standalone application. ### Usage ```python from pycharting.core.server import run_server, find_free_port, create_app # Find an available port within a specified range port = find_free_port(start_port=8000, end_port=9000) print(f"Found free port: {port}") # Run the server (this call blocks until shutdown) run_server( host="127.0.0.1", port=port, auto_port=True, # Automatically find another port if the specified one is busy reload=False, # Set to True for development to enable auto-reloading ) # Alternatively, create the FastAPI application instance directly # This allows for integration with custom ASGI servers like Gunicorn or Hypercorn app = create_app() # Example: app = create_app(data_managers=_data_managers) # Then run with an ASGI server: e.g., hypercorn my_module:app ``` ### Parameters - **host** (string) - The hostname for the server. Defaults to "127.0.0.1". - **port** (integer) - The port number for the server. If `auto_port` is True and this port is unavailable, an alternative will be found. - **auto_port** (boolean) - If True, the server will attempt to find and use an alternative free port if the specified `port` is already in use. Defaults to False. - **reload** (boolean) - If True, enables the auto-reloading feature, useful during development. Defaults to False. ### Functions - **find_free_port(start_port, end_port)**: Scans for and returns an available port number within the specified range. - **create_app()**: Creates and returns the FastAPI application instance used by PyCharting. ``` -------------------------------- ### run_server Function for Direct Server Launch Source: https://context7.com/alihaskar/pycharting/llms.txt Launches the PyCharting web server in the main thread, blocking execution until shutdown. It's useful for development and standalone server operations. Dependencies include pycharting.core.server. ```python from pycharting.core.server import run_server, find_free_port, create_app # Find an available port port = find_free_port(start_port=8000, end_port=9000) print(f"Found free port: {port}") # Run server (blocks until shutdown) run_server( host="127.0.0.1", port=port, auto_port=True, # Find alternative if port unavailable reload=False, # Enable for development ) # Or create the FastAPI app directly for custom deployment app = create_app() # Use with custom ASGI server (gunicorn, hypercorn, etc.) ``` -------------------------------- ### Initialize Synchronized Charts (JavaScript) Source: https://github.com/alihaskar/pycharting/blob/master/src/pycharting/web/static/multi-chart-demo.html Initializes a multi-chart manager and sets up synchronized OHLC, volume, and RSI charts. This function creates the chart containers, generates data, and configures the synchronization behavior (cursor, zoom, pan). It relies on `MultiChartManager` and `PyChart` classes, and `uPlot` for subplots. ```javascript let multiChartManager = null; // Global variable to hold the chart manager instance function initializeCharts() { const container = document.getElementById('chartsContainer'); container.innerHTML = ''; // Clear previous charts // Initialize multi-chart manager multiChartManager = new MultiChartManager(container, { mainHeight: 400, subHeight: 150, gap: 15, syncCursor: true, syncZoom: true, syncPan: true }); // Generate data const data = generateOHLCData(100); const rsi = calculateRSI(data.close); // Create main OHLC chart const mainChartDiv = document.createElement('div'); mainChartDiv.className = 'chart-section'; mainChartDiv.innerHTML = `
Main Chart - OHLC Candlesticks
`; container.appendChild(mainChartDiv); const mainChart = new PyChart(document.getElementById('mainChart'), { title: '', height: 400 }); multiChartManager.chartSync.addChart(mainChart, { id: 'main' }); mainChart.setData([data.index, data.open, data.high, data.low, data.close]); // Create Volume subplot using uPlot const volumeChartDiv = document.createElement('div'); volumeChartDiv.className = 'chart-section'; volumeChartDiv.innerHTML = `
Subplot 1 - Volume
`; container.appendChild(volumeChartDiv); const volumeChart = new uPlot({ title: '', width: mainChartDiv.offsetWidth - 40, height: 150, series: [ {}, { label: 'Volume', stroke: '#2196F3', fill: 'rgba(33, 150, 243, 0.2)', paths: uPlot.paths.bars({ size: [0.8, 100] }) } ], axes: [ {}, { label: 'Volume', labelSize: 20, } ] }, [data.index, data.volume], document.getElementById('volumeChart')); multiChartManager.chartSync.addChart(volumeChart, { id: 'volume' }); // Create RSI subplot using uPlot const rsiChartDiv = document.createElement('div'); rsiChartDiv.className = 'chart-section'; rsiChartDiv.innerHTML = `
Subplot 2 - RSI Indicator
`; container.appendChild(rsiChartDiv); const rsiChart = new uPlot({ title: '', width: mainChartDiv.offsetWidth - 40, height: 150, series: [ {}, { label: 'RSI', stroke: '#f44336', width: 2 } ], axes: [ {}, { label: 'RSI', labelSize: 20, range: [0, 100] } ], scales: { y: { range: [0, 100] } } }, [data.index, rsi], document.getElementById('rsiChart')); multiChartManager.chartSync.addChart(rsiChart, { id: 'rsi' }); } // Function to regenerate data and re-initialize charts function generateData() { if (multiChartManager) { multiChartManager.clear(); } initializeCharts(); } // Setup synchronization controls event listeners document.getElementById('syncCursor').addEventListener('change', (e) => { if (multiChartManager) { multiChartManager.getSync().setCursorSync(e.target.checked); } }); document.getElementById('syncZoom').addEventListener('change', (e) => { if (multiChartManager) { multiChartManager.getSync().setZoomSync(e.target.checked); } }); document.getElementById('syncPan').addEventListener('change', (e) => { if (multiChartManager) { multiChartManager.getSync().setPanSync(e.target.checked); } }); // Initialize charts when the window loads window.addEventListener('load', () => { initializeCharts(); }); ``` -------------------------------- ### Initialize Viewport Manager and Load Data Source: https://github.com/alihaskar/pycharting/blob/master/src/pycharting/web/static/viewport-demo.html Initializes the ViewportManager, which handles data loading and synchronization for charts. It supports both demo sessions and existing Python API sessions, updating UI elements like total points and cache information. ```javascript // Initialize viewport manager and load data async function initializeData() { if (!chart) { setupChart(); } const sessionId = getSessionId() || 'viewport-demo'; // Create viewport manager with loading callbacks viewportManager = new ViewportManager(chart, { sessionId: sessionId, bufferMargin: 0.5, debounceDelay: 300, onLoading: [updateLoadingState], onSubplotsUpdate: [updateSubplots] }); try { if (sessionId === 'viewport-demo') { // Standalone demo: create a demo session on the backend const result = await viewportManager.initializeSession(); document.getElementById('totalPoints').textContent = result.data_points.toLocaleString(); } else { // Python API path: session already exists with real user data await viewportManager.loadInitialData(); const info = viewportManager.getCacheInfo(); if (info.totalLength) { document.getElementById('totalPoints').textContent = info.totalLength.toLocaleString(); } } updateCacheInfo(); // Setup viewport tracking setupViewportTracking(); // Ensure measurement button is ready setupMeasurementButton(); } catch (error) { alert('Failed to initialize session: ' + error.message); } } ``` -------------------------------- ### HTML Structure for PyCharting Synchronization Demo Source: https://github.com/alihaskar/pycharting/blob/master/src/pycharting/web/static/multi-chart-demo.html This HTML code sets up the user interface for the PyCharting synchronization demo. It includes controls for enabling synchronization of cursor, zoom, and pan, a button to generate new data, and containers for displaying multiple charts. Basic styling is applied for layout and appearance. ```html PyCharting - Multi-Chart Synchronization Demo

PyCharting - Multi-Chart Synchronization Demo

Synchronized cursor and zoom/pan across multiple chart instances

Features:

``` -------------------------------- ### Define Overlays and Subplots for Charting Source: https://github.com/alihaskar/pycharting/blob/master/README.md Demonstrates how to define 'overlays' and 'subplots' for the plot function. Overlays are rendered on the main price chart, while subplots appear in separate panels below. ```python overlays = { "SMA_50": sma(close, 50), # rendered on top of price "EMA_200": ema(close, 200), } subplots = { "RSI_like": rsi_like_series, # rendered in its own panel below price "Stoch_like": stoch_series, } plot( index, open_, high, low, close, overlays=overlays, subplots=subplots, ) ``` -------------------------------- ### Load and Render Dataset in PyChart Source: https://github.com/alihaskar/pycharting/blob/master/src/pycharting/web/static/demo.html Loads a specified number of OHLC candles into the PyChart. It handles chart initialization if it doesn't exist and updates the chart with new data. Performance metrics are recorded and displayed. ```javascript function loadDataset(numCandles, label) { setStatus(`Generating ${label}...`, 'loading'); setTimeout(() => { const startTime = performance.now(); // Generate data currentData = generateOHLCData(numCandles); // Create or update chart const container = document.getElementById('chartContainer'); if (!chart) { chart = new PyChart(container, { title: `OHLC Chart - ${label}`, height: 500 }); } chart.setData(currentData); const renderTime = Math.round(performance.now() - startTime); setStatus(`Loaded ${numCandles} candles successfully`, 'info'); updateInfo(numCandles, renderTime); // Initialize measurement button after first chart load setupMeasurementButton(); }, 10); } ``` -------------------------------- ### Generate Sample OHLC Data (JavaScript) Source: https://github.com/alihaskar/pycharting/blob/master/src/pycharting/web/static/multi-chart-demo.html Generates sample Open, High, Low, Close (OHLC) data for financial charting. This function creates an array of data points suitable for displaying candlestick charts. It takes an optional number of data points as input. ```javascript function generateOHLCData(n = 100) { const index = []; const open = []; const high = []; const low = []; const close = []; const volume = []; let currentPrice = 100; for (let i = 0; i < n; i++) { index.push(i); const change = (Math.random() - 0.5) * 2; currentPrice += change; const o = currentPrice + (Math.random() - 0.5) * 0.5; const c = currentPrice + (Math.random() - 0.5) * 0.5; const h = Math.max(o, c) + Math.abs(Math.random()); const l = Math.min(o, c) - Math.abs(Math.random()); open.push(o); high.push(h); low.push(l); close.push(c); volume.push(Math.random() * 1000000 + 500000); } return { index, open, high, low, close, volume }; } ``` -------------------------------- ### Initialize and Register Measurement Button Source: https://github.com/alihaskar/pycharting/blob/master/src/pycharting/web/static/demo.html Sets up the measurement tool button for the chart. It ensures the button is only initialized once and registers it with the chart instance. The button's click event toggles the measurement tool's enabled state. ```javascript let chart = null; let currentData = null; let measurementButtonInitialized = false; // Setup measurement tool button function setupMeasurementButton() { if (measurementButtonInitialized) return; const measureBtn = document.getElementById('measureBtn'); if (!measureBtn || !chart) { return; } chart.registerMeasurementButton(measureBtn); measureBtn.addEventListener('click', (e) => { e.preventDefault(); console.log('Measurement button clicked'); if (chart.measurementEnabled) { chart.disableMeasurementTool(); } else { chart.enableMeasurementTool(); } }); measurementButtonInitialized = true; console.log('Measurement button initialized'); } ```