#!/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()