| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- """
- 生成30分钟级别市场状态识别图表
- """
- import pandas as pd
- import matplotlib.pyplot as plt
- import matplotlib.dates as mdates
- from datetime import datetime
- import warnings
- warnings.filterwarnings('ignore')
- print("="*70)
- print("生成30分钟市场状态识别图表")
- print("="*70)
- # 读取30分钟结果数据
- df = pd.read_csv('cyb50_30min_regime_result.csv', index_col='datetime', parse_dates=True)
- print(f"\n数据范围: {df.index[0]} ~ {df.index[-1]}")
- print(f"数据条数: {len(df)}个30分钟周期")
- # 设置中文字体
- plt.rcParams['font.sans-serif'] = ['SimHei', 'DejaVu Sans']
- plt.rcParams['axes.unicode_minus'] = False
- # 状态名称和颜色
- state_names = ['震荡', '趋势', '反转']
- colors = ['#2196F3', '#4CAF50', '#FF5722'] # 蓝、绿、橙
- # 创建图表
- fig, axes = plt.subplots(3, 1, figsize=(20, 14))
- # 图1: 价格走势 + 状态标记
- ax1 = axes[0]
- ax1.plot(df.index, df['close'], 'k-', alpha=0.3, linewidth=0.5, label='收盘价')
- for i, (name, color) in enumerate(zip(state_names, colors)):
- mask = df['state'] == i
- if mask.any():
- ax1.scatter(df.index[mask], df['close'][mask],
- c=color, label=name, alpha=0.6, s=20)
- ax1.set_ylabel('价格', fontsize=12)
- ax1.set_title('CYB50 30分钟市场状态识别 (2024-2026)', fontsize=14, fontweight='bold')
- ax1.legend(loc='upper left', fontsize=10)
- ax1.grid(True, alpha=0.3)
- # 格式化x轴日期
- ax1.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
- ax1.xaxis.set_major_locator(mdates.MonthLocator(interval=2))
- # 图2: 状态概率时间序列
- ax2 = axes[1]
- ax2.fill_between(df.index, 0, df['prob_ranging'],
- alpha=0.5, label='震荡', color=colors[0])
- ax2.fill_between(df.index, df['prob_ranging'],
- df['prob_ranging'] + df['prob_trend'],
- alpha=0.5, label='趋势', color=colors[1])
- ax2.fill_between(df.index,
- df['prob_ranging'] + df['prob_trend'], 1,
- alpha=0.5, label='反转', color=colors[2])
- ax2.set_ylabel('概率', fontsize=12)
- ax2.set_title('30分钟状态概率时间序列', fontsize=12)
- ax2.legend(loc='upper left', fontsize=10)
- ax2.grid(True, alpha=0.3)
- ax2.set_ylim(0, 1)
- ax2.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m'))
- ax2.xaxis.set_major_locator(mdates.MonthLocator(interval=2))
- # 图3: 状态分布统计
- ax3 = axes[2]
- state_counts = df['state'].value_counts().sort_index()
- bars = ax3.bar(range(3), state_counts.values, color=colors, alpha=0.7)
- ax3.set_xticks(range(3))
- ax3.set_xticklabels(state_names)
- ax3.set_ylabel('周期数', fontsize=12)
- ax3.set_title('30分钟状态分布统计', fontsize=12)
- # 添加数值标签
- for i, (bar, count) in enumerate(zip(bars, state_counts.values)):
- pct = count / len(df) * 100
- ax3.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 20,
- f'{count}\n({pct:.1f}%)',
- ha='center', va='bottom', fontsize=11, fontweight='bold')
- plt.tight_layout()
- plt.savefig('cyb50_30min_regime_chart.png', dpi=150, bbox_inches='tight')
- print("\n[OK] 图表已保存: cyb50_30min_regime_chart.png")
- # 生成详细报告
- print("\n" + "="*70)
- print("30分钟级别详细识别结果")
- print("="*70)
- # 按月份统计
- print("\n【月度统计 - 最近6个月】")
- print(f"{'月份':<12} {'总周期':<8} {'震荡':<8} {'趋势':<8} {'反转':<8} {'主要状态':<10}")
- print("-"*70)
- recent_months = df[df.index >= '2024-09-01'].copy()
- for year_month in sorted(recent_months.index.to_period('M').unique()):
- mask = recent_months.index.to_period('M') == year_month
- month_data = recent_months[mask]
- total = len(month_data)
- ranging = (month_data['state'] == 0).sum()
- trend = (month_data['state'] == 1).sum()
- reversal = (month_data['state'] == 2).sum()
- main_state = state_names[month_data['state'].mode()[0]]
- print(f"{str(year_month):<12} {total:<8} {ranging:<8} {trend:<8} {reversal:<8} {main_state:<10}")
- # 最近一周详细数据
- print("\n【最近一周详细数据】")
- print(f"{'日期时间':<20} {'收盘价':<10} {'状态':<8} {'震荡%':<8} {'趋势%':<8} {'反转%':<8}")
- print("-"*70)
- last_week = df.tail(40) # 约5个交易日
- for idx, row in last_week.iterrows():
- state = state_names[int(row['state'])]
- print(f"{str(idx):<20} {row['close']:<10.2f} {state:<8} "
- f"{row['prob_ranging']:<8.1%} {row['prob_trend']:<8.1%} {row['prob_reversal']:<8.1%}")
- print("\n" + "="*70)
- print("[OK] 报告生成完成!")
- print("="*70)
|