Bạn đang xây dựng hệ thống phân tích dữ liệu thị trường crypto và cần trực quan hóa Order Book với độ trễ thấp? Trong bài viết này, tôi sẽ chia sẻ cách tôi xây dựng pipeline xử lý dữ liệu Tardis bằng Plotly, từ architecture đến production code với benchmark thực tế.
Tardis là gì và tại sao cần visualize dữ liệu?
Tardis cung cấp API truy cập dữ liệu order book và trade history từ nhiều sàn giao dịch với độ phân giải cao. Với dữ liệu tick-by-tick, việc visualize giúp:
- Phát hiện anomaly trong liquidity
- Phân tích behavior của market makers
- Tối ưu chiến lược đặt lệnh
- Debug chiến lược trading trong backtesting
Kiến trúc hệ thống
Đây là architecture tôi đã deploy cho production system xử lý hàng triệu records mỗi ngày:
┌─────────────┐ ┌──────────────┐ ┌─────────────┐
│ Tardis │────▶│ HolySheep │────▶│ Plotly │
│ API │ │ AI Pipeline │ │ Dashboard │
└─────────────┘ └──────────────┘ └─────────────┘
│ │ │
▼ ▼ ▼
WebSocket/ Async Process Interactive
REST API + Caching Heatmaps
Setup và Dependencies
pip install tardis-client pandas plotly numpy redis asyncio aiohttp
import asyncio
import aiohttp
import pandas as pd
import plotly.graph_objects as go
from plotly.subplots import make_subplots
import numpy as np
from datetime import datetime
from typing import List, Dict, Tuple
HolySheep AI - xử lý dữ liệu với AI
HOLYSHEEP_BASE_URL = "https://api.holysheep.ai/v1"
HOLYSHEEP_API_KEY = "YOUR_HOLYSHEEP_API_KEY"
class OrderBookVisualizer:
"""
Visualizer cho Order Book và Trade Distribution
Author: 5 năm kinh nghiệm trading infrastructure
"""
def __init__(self, symbol: str, exchange: str = "binance"):
self.symbol = symbol
self.exchange = exchange
self.order_book = {"bids": [], "asks": []}
self.trades = []
async def fetch_order_book(self, depth: int = 100):
"""Lấy dữ liệu order book từ Tardis"""
async with aiohttp.ClientSession() as session:
url = f"https://api.tardis.dev/v1/{self.exchange}/orderbook"
params = {"symbol": self.symbol, "depth": depth}
async with session.get(url, params=params) as resp:
data = await resp.json()
self.order_book = {
"bids": data.get("bids", [])[:depth],
"asks": data.get("asks", [])[:depth]
}
return self.order_book
async def fetch_recent_trades(self, limit: int = 1000):
"""Lấy dữ liệu trades gần đây"""
async with aiohttp.ClientSession() as session:
url = f"https://api.tardis.dev/v1/{self.exchange}/trades"
params = {"symbol": self.symbol, "limit": limit}
async with session.get(url, params=params) as resp:
self.trades = await resp.json()
return self.trades
Vẽ Order Book Heatmap với Plotly
Heatmap là cách trực quan nhất để thấy phân bố liquidity. Tôi dùng go.Heatmap với custom colorscale:
async def create_order_book_heatmap(self) -> go.Figure:
"""Tạo heatmap cho Order Book với Plotly"""
# Chuyển đổi dữ liệu thành matrix format
bid_prices = [float(b[0]) for b in self.order_book["bids"]]
bid_volumes = [float(b[1]) for b in self.order_book["bids"]]
ask_prices = [float(a[0]) for a in self.order_book["asks"]]
ask_volumes = [float(a[1]) for a in self.order_book["asks"]]
# Tạo grid cho heatmap
mid_price = (bid_prices[0] + ask_prices[0]) / 2
spread = ask_prices[0] - bid_prices[0]
# Price levels (từ mid price ra 2 phía)
price_range = np.linspace(mid_price - spread * 10,
mid_price + spread * 10, 50)
# Volume matrix
z_bids = np.zeros((1, 50))
z_asks = np.zeros((1, 50))
for price, vol in zip(bid_prices, bid_volumes):
idx = np.searchsorted(price_range, price)
if 0 <= idx < 50:
z_bids[0, idx] = vol
for price, vol in zip(ask_prices, ask_volumes):
idx = np.searchsorted(price_range, price)
if 0 <= idx < 50:
z_asks[0, idx] = vol
# Combine thành full heatmap
z_combined = np.vstack([z_bids, z_asks])
fig = go.Figure(data=go.Heatmap(
z=z_combined,
x=price_range,
y=["Asks", "Bids"],
colorscale=[
[0, 'rgb(0,100,0)'], # Dark green - asks
[0.5, 'rgb(255,255,255)'], # White - empty
[1, 'rgb(255,0,0)'] # Red - bids
],
showscale=True,
colorbar=dict(title="Volume")
))
fig.update_layout(
title=f"Order Book Heatmap - {self.symbol}",
xaxis_title="Price",
yaxis_title="Side",
template="plotly_dark",
height=400
)
return fig
Vẽ Trade Distribution với Histogram + Scatter
async def create_trade_distribution(self) -> go.Figure:
"""Tạo distribution chart cho trades"""
if not self.trades:
await self.fetch_recent_trades()
df = pd.DataFrame(self.trades)
df["price"] = df["