huice/demo_unified_player.py
Your Name 7f4f88e853 feat: 添加期货数据播放器及相关测试和文档
新增期货数据动态播放器功能,包括基础版和增强版实现,添加测试脚本和详细文档说明。主要变更包括:
1. 实现买卖盘深度可视化播放功能
2. 添加播放控制、速度调节和跳转功能
3. 提供统一价格轴显示优化版本
4. 添加测试脚本验证功能
5. 编写详细使用文档和README说明
2025-11-02 23:57:10 +08:00

202 lines
7.4 KiB
Python

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Quick demo for Unified Futures Data Player
快速演示统一价格轴版本的期货数据播放器
"""
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
def demo_unified_chart():
"""演示统一价格轴图表效果"""
print("=== Unified Market Depth Demo ===")
print("Creating sample visualization...")
# Load some sample data
df = pd.read_parquet('data/au2512_20251013.parquet')
# Column mapping
columns_mapping = {
'时间': 'time', '累积成交量': 'cumulative_volume', '成交价': 'price',
'买1价': 'bid1_price', '卖1价': 'ask1_price',
'买1量': 'bid1_volume', '卖1量': 'ask1_volume',
'买2价': 'bid2_price', '卖2价': 'ask2_price',
'买2量': 'bid2_volume', '卖2量': 'ask2_volume',
'买3价': 'bid3_price', '卖3价': 'ask3_price',
'买3量': 'bid3_volume', '卖3量': 'ask3_volume',
'买4价': 'bid4_price', '卖4价': 'ask4_price',
'买4量': 'bid4_volume', '卖4量': 'ask4_volume',
'买5价': 'bid5_price', '卖5价': 'ask5_price',
'买5量': 'bid5_volume', '卖5量': 'ask5_volume'
}
df = df.rename(columns=columns_mapping)
# Get a sample row
sample_row = df.iloc[1000] # Sample from middle of data
current_price = sample_row['price']
min_tick = 0.02
# Create figure
fig, ax = plt.subplots(figsize=(12, 8))
fig.suptitle('Unified Market Depth Demo - AU2512', fontsize=16, fontweight='bold')
# Collect market depth data
bid_prices = []
bid_volumes = []
ask_prices = []
ask_volumes = []
for i in range(1, 6):
bid_price = sample_row[f'bid{i}_price']
bid_volume = sample_row[f'bid{i}_volume']
ask_price = sample_row[f'ask{i}_price']
ask_volume = sample_row[f'ask{i}_volume']
if pd.notna(bid_price) and pd.notna(bid_volume) and bid_volume > 0:
bid_prices.append(bid_price)
bid_volumes.append(bid_volume)
if pd.notna(ask_price) and pd.notna(ask_volume) and ask_volume > 0:
ask_prices.append(ask_price)
ask_volumes.append(ask_volume)
print(f"Sample data at sequence 1000:")
print(f"Current price: {current_price:.2f}")
print(f"Bid prices: {[f'{p:.2f}' for p in bid_prices]}")
print(f"Ask prices: {[f'{p:.2f}' for p in ask_prices]}")
# Define volume scale points (equal spacing)
volume_scale_points = [10, 30, 60, 150, 300]
# Create unified visualization with horizontal bars
all_prices = []
all_volumes = []
all_colors = []
# Add bid data (green horizontal bars)
for bp, bv in zip(bid_prices, bid_volumes):
all_prices.append(bp)
all_volumes.append(bv)
all_colors.append('green')
# Add ask data (red horizontal bars)
for ap, av in zip(ask_prices, ask_volumes):
all_prices.append(ap)
all_volumes.append(av)
all_colors.append('red')
# Map volumes to scale positions
def map_volume_to_scale(volume):
"""Map actual volume to scale position"""
if volume <= 10:
return 10
elif volume <= 30:
return 30
elif volume <= 60:
return 60
elif volume <= 150:
return 150
elif volume <= 300:
return 300
else:
return 300 # Cap at 300 for display
# Map volumes to display scale
mapped_volumes = [map_volume_to_scale(v) for v in all_volumes]
# Create horizontal bars (volume on x-axis, price on y-axis)
bars = ax.barh(all_prices, mapped_volumes, height=min_tick * 0.8,
color=all_colors, alpha=0.7,
edgecolor='darkgreen' if 'green' in all_colors else 'darkred',
linewidth=1)
# Add volume labels on bars
for price, volume, mapped_vol in zip(all_prices, all_volumes, mapped_volumes):
if volume > 0:
ax.text(mapped_vol + 5, price, f'{int(volume):,}',
ha='left', va='center', fontsize=10, fontweight='bold')
# Set up price axis with true tick spacing
price_range = 1.0
min_price = current_price - price_range/2
max_price = current_price + price_range/2
tick_prices = np.arange(np.floor(min_price / min_tick) * min_tick,
np.ceil(max_price / min_tick) * min_tick + min_tick,
min_tick)
ax.set_xticks(tick_prices[::3]) # Show every 3rd tick
ax.set_xticklabels([f'{p:.2f}' for p in tick_prices[::3]], rotation=45)
ax.set_xlim(min_price, max_price)
# Add current price line
ax.axvline(x=current_price, color='blue', linestyle='--', alpha=0.8, linewidth=2,
label=f'Last Price: {current_price:.2f}')
# Highlight spread
if bid_prices and ask_prices:
best_bid = max(bid_prices)
best_ask = min(ask_prices)
spread = best_ask - best_bid
ax.axvspan(best_bid, best_ask, alpha=0.3, color='yellow',
label=f'Spread: {spread:.2f}')
print(f"Best bid: {best_bid:.2f}, Best ask: {best_ask:.2f}")
print(f"Bid-ask spread: {spread:.2f}")
# Set y-axis with true tick spacing (price)
ax.set_yticks(tick_prices[::3]) # Show every 3rd tick to avoid crowding
ax.set_yticklabels([f'{p:.2f}' for p in tick_prices[::3]])
ax.set_ylim(min_price, max_price)
# Set x-axis with defined volume scale points
ax.set_xticks(volume_scale_points)
ax.set_xticklabels([f'{v}' for v in volume_scale_points])
ax.set_xlim(0, max(volume_scale_points) * 1.2)
# Labels and formatting
ax.set_xlabel('Volume', fontsize=12)
ax.set_ylabel('Price (¥)', fontsize=12)
ax.set_title('Unified Market Depth View', fontsize=14)
ax.grid(True, alpha=0.3, axis='x')
# Legend
import matplotlib.patches as mpatches
bid_patch = mpatches.Patch(color='green', alpha=0.7, label='Bid Volume')
ask_patch = mpatches.Patch(color='red', alpha=0.7, label='Ask Volume')
ax.legend(handles=[bid_patch, ask_patch], loc='upper right')
# Add annotations
ax.text(0.02, 0.98, f"Time: {sample_row['time']}",
transform=ax.transAxes, fontsize=10,
verticalalignment='top',
bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.8))
ax.text(0.02, 0.92, f"Tick Size: {min_tick}",
transform=ax.transAxes, fontsize=10,
verticalalignment='top',
bbox=dict(boxstyle='round', facecolor='lightblue', alpha=0.8))
plt.tight_layout()
# Save the demo chart
output_file = 'unified_market_depth_demo.png'
plt.savefig(output_file, dpi=150, bbox_inches='tight')
print(f"\nDemo chart saved as: {output_file}")
plt.show()
print("\nThis demo shows the unified market depth visualization where:")
print("- Green horizontal bars: Bid volumes at different price levels")
print("- Red horizontal bars: Ask volumes at different price levels")
print("- Blue dashed line: Current last price (horizontal)")
print("- Yellow shaded area: Bid-ask spread (horizontal)")
print("- Price axis (vertical) shows true minimum tick spacing (0.02)")
print("- Volume axis (horizontal) uses simplified scale: 10, 30, 60, 150, 300 (equal spacing)")
print("- Volume bars extend rightward with sizes matching the scale points")
print("- Volumes larger than 300 are capped at 300 for display consistency")
if __name__ == "__main__":
demo_unified_chart()