154 lines
5.2 KiB
Python
154 lines
5.2 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
Run interactive visualizer using PRE-CALCULATED metrics from the database.
|
|
No recalculation needed - just read and display!
|
|
"""
|
|
|
|
from pathlib import Path
|
|
from interactive_visualizer import InteractiveVisualizer
|
|
from models import Book, BookSnapshot, Trade
|
|
from parsers.orderbook_parser import OrderbookParser
|
|
import sqlite3
|
|
import logging
|
|
|
|
def load_book_snapshots_only(db_path: Path, limit: int = 10000):
|
|
"""Load book snapshots without recalculating metrics."""
|
|
book = Book()
|
|
parser = OrderbookParser()
|
|
|
|
print(f"📖 Reading book snapshots (limit: {limit})...")
|
|
|
|
# Read book data directly without triggering metric calculation
|
|
conn = sqlite3.connect(f'file:{db_path}?mode=ro', uri=True)
|
|
|
|
# Load trades first for efficiency
|
|
print(" 📈 Loading trades...")
|
|
trades_by_timestamp = {}
|
|
trade_cursor = conn.execute('SELECT id, trade_id, price, size, side, timestamp FROM trades ORDER BY timestamp')
|
|
for trade_row in trade_cursor:
|
|
timestamp = int(trade_row[5])
|
|
trade = Trade(
|
|
id=trade_row[0],
|
|
trade_id=float(trade_row[1]),
|
|
price=float(trade_row[2]),
|
|
size=float(trade_row[3]),
|
|
side=trade_row[4],
|
|
timestamp=timestamp
|
|
)
|
|
if timestamp not in trades_by_timestamp:
|
|
trades_by_timestamp[timestamp] = []
|
|
trades_by_timestamp[timestamp].append(trade)
|
|
|
|
# Get snapshots
|
|
cursor = conn.execute('''
|
|
SELECT id, instrument, bids, asks, timestamp
|
|
FROM book
|
|
ORDER BY timestamp
|
|
LIMIT ?
|
|
''', (limit,))
|
|
|
|
snapshot_count = 0
|
|
for row in cursor:
|
|
try:
|
|
row_id, instrument, bids_text, asks_text, timestamp = row
|
|
timestamp_int = int(timestamp)
|
|
|
|
# Create snapshot using the same logic as Storage._snapshot_from_row
|
|
snapshot = BookSnapshot(
|
|
id=row_id,
|
|
timestamp=timestamp_int,
|
|
bids={},
|
|
asks={},
|
|
trades=trades_by_timestamp.get(timestamp_int, []),
|
|
)
|
|
|
|
# Parse bids and asks using the parser
|
|
parser.parse_side(bids_text, snapshot.bids)
|
|
parser.parse_side(asks_text, snapshot.asks)
|
|
|
|
# Only add snapshots that have both bids and asks
|
|
if snapshot.bids and snapshot.asks:
|
|
book.add_snapshot(snapshot)
|
|
snapshot_count += 1
|
|
|
|
if snapshot_count % 1000 == 0:
|
|
print(f" 📊 Loaded {snapshot_count} snapshots...")
|
|
|
|
except Exception as e:
|
|
logging.warning(f"Error parsing snapshot {row[0]}: {e}")
|
|
continue
|
|
|
|
conn.close()
|
|
print(f"✅ Loaded {len(book.snapshots)} snapshots with trades")
|
|
return book
|
|
|
|
def main():
|
|
print("🚀 USING PRE-CALCULATED METRICS FROM DATABASE")
|
|
print("=" * 55)
|
|
|
|
# Database path
|
|
db_path = Path("../data/OKX/BTC-USDT-25-06-09.db")
|
|
|
|
if not db_path.exists():
|
|
print(f"❌ Database not found: {db_path}")
|
|
return
|
|
|
|
try:
|
|
# Load ONLY book snapshots (no metric recalculation)
|
|
book = load_book_snapshots_only(db_path, limit=5000) # Start with 5K snapshots
|
|
|
|
if not book.snapshots:
|
|
print("❌ No snapshots loaded")
|
|
return
|
|
|
|
print(f"✅ Book loaded: {len(book.snapshots)} snapshots")
|
|
print(f"✅ Time range: {book.first_timestamp} to {book.last_timestamp}")
|
|
|
|
# Create visualizer
|
|
viz = InteractiveVisualizer(
|
|
window_seconds=6*3600, # 6-hour bars
|
|
port=8050
|
|
)
|
|
|
|
# Set database path so it can load PRE-CALCULATED metrics
|
|
viz.set_db_path(db_path)
|
|
|
|
# Process book data (will load existing metrics automatically)
|
|
print("⚙️ Processing book data and loading existing metrics...")
|
|
viz.update_from_book(book)
|
|
|
|
print(f"✅ Generated {len(viz._ohlc_data)} OHLC bars")
|
|
print(f"✅ Loaded {len(viz._metrics_data)} pre-calculated metrics")
|
|
|
|
if viz._ohlc_data:
|
|
sample_bar = viz._ohlc_data[0]
|
|
print(f"✅ Sample OHLC: O={sample_bar[1]:.2f}, H={sample_bar[2]:.2f}, L={sample_bar[3]:.2f}, C={sample_bar[4]:.2f}")
|
|
|
|
print()
|
|
print("🌐 LAUNCHING INTERACTIVE DASHBOARD")
|
|
print("=" * 55)
|
|
print("🚀 Server starting at: http://127.0.0.1:8050")
|
|
print("📊 Features available:")
|
|
print(" ✅ OHLC candlestick chart")
|
|
print(" ✅ Volume bar chart")
|
|
print(" ✅ OBI line chart (from existing metrics)")
|
|
print(" ✅ CVD line chart (from existing metrics)")
|
|
print(" ✅ Synchronized zoom/pan")
|
|
print(" ✅ Professional dark theme")
|
|
print()
|
|
print("⏹️ Press Ctrl+C to stop the server")
|
|
print("=" * 55)
|
|
|
|
# Launch the dashboard
|
|
viz.show()
|
|
|
|
except KeyboardInterrupt:
|
|
print("\n⏹️ Server stopped by user")
|
|
except Exception as e:
|
|
print(f"❌ Error: {e}")
|
|
import traceback
|
|
traceback.print_exc()
|
|
|
|
if __name__ == "__main__":
|
|
main()
|