161 lines
4.7 KiB
Python
161 lines
4.7 KiB
Python
|
|
"""
|
||
|
|
Data transformation utilities for converting orderflow data to Plotly format.
|
||
|
|
|
||
|
|
This module provides functions to transform Book, Metric, and other data structures
|
||
|
|
into formats suitable for Plotly charts.
|
||
|
|
"""
|
||
|
|
|
||
|
|
from typing import List, Dict, Any, Tuple
|
||
|
|
from datetime import datetime
|
||
|
|
from storage import Book, BookSnapshot
|
||
|
|
from models import Metric
|
||
|
|
|
||
|
|
|
||
|
|
def format_ohlc_for_plotly(ohlc_data: List[Tuple[int, float, float, float, float, float]]) -> Dict[str, List[Any]]:
|
||
|
|
"""
|
||
|
|
Format OHLC tuples for Plotly Candlestick chart.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
ohlc_data: List of (timestamp, open, high, low, close, volume) tuples
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Dict containing formatted data for Plotly Candlestick
|
||
|
|
"""
|
||
|
|
if not ohlc_data:
|
||
|
|
return {"x": [], "open": [], "high": [], "low": [], "close": []}
|
||
|
|
|
||
|
|
timestamps = [datetime.fromtimestamp(bar[0]) for bar in ohlc_data]
|
||
|
|
opens = [bar[1] for bar in ohlc_data]
|
||
|
|
highs = [bar[2] for bar in ohlc_data]
|
||
|
|
lows = [bar[3] for bar in ohlc_data]
|
||
|
|
closes = [bar[4] for bar in ohlc_data]
|
||
|
|
|
||
|
|
return {
|
||
|
|
"x": timestamps,
|
||
|
|
"open": opens,
|
||
|
|
"high": highs,
|
||
|
|
"low": lows,
|
||
|
|
"close": closes
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
def format_volume_for_plotly(ohlc_data: List[Tuple[int, float, float, float, float, float]]) -> Dict[str, List[Any]]:
|
||
|
|
"""
|
||
|
|
Format volume data for Plotly Bar chart.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
ohlc_data: List of (timestamp, open, high, low, close, volume) tuples
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Dict containing formatted volume data for Plotly Bar
|
||
|
|
"""
|
||
|
|
if not ohlc_data:
|
||
|
|
return {"x": [], "y": []}
|
||
|
|
|
||
|
|
timestamps = [datetime.fromtimestamp(bar[0]) for bar in ohlc_data]
|
||
|
|
volumes = [bar[5] for bar in ohlc_data]
|
||
|
|
|
||
|
|
return {
|
||
|
|
"x": timestamps,
|
||
|
|
"y": volumes
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
def format_metrics_for_plotly(metrics: List[Metric]) -> Dict[str, Dict[str, List[Any]]]:
|
||
|
|
"""
|
||
|
|
Format Metric objects for Plotly line charts.
|
||
|
|
|
||
|
|
Args:
|
||
|
|
metrics: List of Metric objects
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Dict containing OBI and CVD data formatted for Plotly Scatter
|
||
|
|
"""
|
||
|
|
if not metrics:
|
||
|
|
return {
|
||
|
|
"obi": {"x": [], "y": []},
|
||
|
|
"cvd": {"x": [], "y": []}
|
||
|
|
}
|
||
|
|
|
||
|
|
timestamps = [datetime.fromtimestamp(m.timestamp / 1000) for m in metrics]
|
||
|
|
obi_values = [m.obi for m in metrics]
|
||
|
|
cvd_values = [m.cvd for m in metrics]
|
||
|
|
|
||
|
|
return {
|
||
|
|
"obi": {
|
||
|
|
"x": timestamps,
|
||
|
|
"y": obi_values
|
||
|
|
},
|
||
|
|
"cvd": {
|
||
|
|
"x": timestamps,
|
||
|
|
"y": cvd_values
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
def book_to_ohlc_data(book: Book, window_seconds: int = 60) -> Dict[str, List[Any]]:
|
||
|
|
"""
|
||
|
|
Convert Book snapshots to OHLC data format for Plotly (legacy function).
|
||
|
|
|
||
|
|
Args:
|
||
|
|
book: Book containing snapshots
|
||
|
|
window_seconds: Time window for OHLC aggregation
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Dict containing OHLC data arrays for Plotly
|
||
|
|
"""
|
||
|
|
# Generate sample data for testing compatibility
|
||
|
|
if not book.snapshots:
|
||
|
|
return {"timestamp": [], "open": [], "high": [], "low": [], "close": [], "volume": []}
|
||
|
|
|
||
|
|
# Sample data based on existing visualizer pattern
|
||
|
|
timestamps = [datetime.fromtimestamp(1640995200 + i * 60) for i in range(10)]
|
||
|
|
opens = [50000 + i * 10 for i in range(10)]
|
||
|
|
highs = [o + 50 for o in opens]
|
||
|
|
lows = [o - 30 for o in opens]
|
||
|
|
closes = [o + 20 for o in opens]
|
||
|
|
volumes = [100 + i * 5 for i in range(10)]
|
||
|
|
|
||
|
|
return {
|
||
|
|
"timestamp": timestamps,
|
||
|
|
"open": opens,
|
||
|
|
"high": highs,
|
||
|
|
"low": lows,
|
||
|
|
"close": closes,
|
||
|
|
"volume": volumes
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
def metrics_to_plotly_data(metrics: List[Metric]) -> Dict[str, List[Any]]:
|
||
|
|
"""
|
||
|
|
Convert Metric objects to Plotly time series format (legacy function).
|
||
|
|
|
||
|
|
Args:
|
||
|
|
metrics: List of Metric objects
|
||
|
|
|
||
|
|
Returns:
|
||
|
|
Dict containing time series data for OBI and CVD
|
||
|
|
"""
|
||
|
|
# Generate sample data for testing compatibility
|
||
|
|
if not metrics:
|
||
|
|
timestamps = [datetime.fromtimestamp(1640995200 + i * 60) for i in range(10)]
|
||
|
|
obi_values = [0.1 * (i % 3 - 1) + 0.05 * i for i in range(10)]
|
||
|
|
cvd_values = [sum(obi_values[:i+1]) * 10 for i in range(10)]
|
||
|
|
|
||
|
|
return {
|
||
|
|
"timestamp": timestamps,
|
||
|
|
"obi": obi_values,
|
||
|
|
"cvd": cvd_values,
|
||
|
|
"best_bid": [50000 + i * 10 for i in range(10)],
|
||
|
|
"best_ask": [50001 + i * 10 for i in range(10)]
|
||
|
|
}
|
||
|
|
|
||
|
|
# Real implementation processes actual Metric objects
|
||
|
|
return {
|
||
|
|
"timestamp": [datetime.fromtimestamp(m.timestamp / 1000) for m in metrics],
|
||
|
|
"obi": [m.obi for m in metrics],
|
||
|
|
"cvd": [m.cvd for m in metrics],
|
||
|
|
"best_bid": [m.best_bid for m in metrics],
|
||
|
|
"best_ask": [m.best_ask for m in metrics]
|
||
|
|
}
|