#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 创业板50指数 - 自动化交易报告系统 基于 cyb50_30min_dual_direction.py 完整策略 """ import sys sys.path.insert(0, '/root/.openclaw/workspace/cat-fly') import pandas as pd import numpy as np from datetime import datetime, timedelta import smtplib import ssl from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.header import Header import warnings warnings.filterwarnings('ignore') # 导入原版策略模块 from cyb50_30min_dual_direction import ( ConfigManager, IntradayDataFetcher, DualDirectionSignalGenerator, DualDirectionExecutor ) # ==================== 邮件配置 ==================== EMAIL_CONFIG = { "smtp_server": "localhost", "smtp_port": 25, "sender_email": "catfly@erwin.wang", "receiver_emails": ["380880504@qq.com", "695047456@qq.com"] } def send_email(subject, html_content, text_content=""): """发送邮件""" try: msg = MIMEMultipart('alternative') msg['Subject'] = Header(subject, 'utf-8') msg['From'] = EMAIL_CONFIG['sender_email'] msg['To'] = ', '.join(EMAIL_CONFIG['receiver_emails']) text_part = MIMEText(text_content, 'plain', 'utf-8') msg.attach(text_part) html_part = MIMEText(html_content, 'html', 'utf-8') msg.attach(html_part) with smtplib.SMTP(EMAIL_CONFIG['smtp_server'], EMAIL_CONFIG['smtp_port']) as server: server.sendmail( EMAIL_CONFIG['sender_email'], EMAIL_CONFIG['receiver_emails'], msg.as_string() ) print(f"✅ 邮件发送成功: {subject}") return True except Exception as e: print(f"❌ 邮件发送失败: {e}") return False def check_today_trades(trades_df): """检查当天是否有交易 返回: has_today_trade: bool, 当天是否有交易 today_trades: DataFrame, 当天的交易记录 """ if len(trades_df) == 0: return False, pd.DataFrame() # 获取今天的日期 today = datetime.now().date() # 检查是否有今天的交易 today_trades = trades_df[ (pd.to_datetime(trades_df['开仓时间']).dt.date == today) | (pd.to_datetime(trades_df['平仓时间']).dt.date == today) ] has_today_trade = len(today_trades) > 0 if has_today_trade: print(f"📊 当天交易数量: {len(today_trades)}笔") for _, trade in today_trades.iterrows(): print(f" {trade['交易方向']} | {trade['开仓时间']} → {trade['平仓时间']} | {trade['盈亏金额']:+.0f}元") else: print("📭 当天无交易") return has_today_trade, today_trades def is_post_close_time(): """检查当前是否是盘后时间(15:00-15:30)""" now = datetime.now() return now.hour == 15 and now.minute >= 0 and now.minute <= 30 def generate_report(trades_df, results_df, initial_capital=1000000): """生成交易报告""" if len(trades_df) == 0: final_capital = initial_capital total_return = 0 html = f"""
生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
数据区间: 近2个月
近2个月无交易信号触发
初始资金: {initial_capital:,.0f}元
最终资金: {final_capital:,.0f}元
收益率: {total_return:+.2f}%
""" text = f"近2个月无交易信号\n初始资金: {initial_capital:,.0f}元\n最终资金: {final_capital:,.0f}元" return html, text, final_capital # 计算统计数据 final_capital = results_df['net_value'].iloc[-1] total_return = (final_capital - initial_capital) / initial_capital * 100 total_trades = len(trades_df) winning_trades = trades_df[trades_df['盈亏金额'] > 0] losing_trades = trades_df[trades_df['盈亏金额'] < 0] win_rate = len(winning_trades) / total_trades * 100 if total_trades > 0 else 0 total_profit = winning_trades['盈亏金额'].sum() if len(winning_trades) > 0 else 0 total_loss = abs(losing_trades['盈亏金额'].sum()) if len(losing_trades) > 0 else 0 profit_factor = total_profit / total_loss if total_loss > 0 else 0 long_trades = trades_df[trades_df['交易方向'] == '做多'] short_trades = trades_df[trades_df['交易方向'] == '做空'] # HTML报告 html = f"""生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
数据区间: 近2个月
| 指标 | 数值 |
|---|---|
| 初始资金 | {initial_capital:,.0f}元 |
| 最终资金 | {final_capital:,.0f}元 |
| 总收益率 | {total_return:+.2f}% |
| 总交易次数 | {total_trades}笔 |
| 胜率 | {win_rate:.1f}% |
| 盈亏比 | {profit_factor:.2f} |
| 方向 | 交易次数 | 胜率 | 总盈亏 |
|---|---|---|---|
| 做多 | {len(long_trades)}笔 | {(len(long_trades[long_trades['盈亏金额']>0])/len(long_trades)*100 if len(long_trades)>0 else 0):.1f}% | {long_trades['盈亏金额'].sum():+,.0f}元 |
| 做空 | {len(short_trades)}笔 | {(len(short_trades[short_trades['盈亏金额']>0])/len(short_trades)*100 if len(short_trades)>0 else 0):.1f}% | {short_trades['盈亏金额'].sum():+,.0f}元 |
| 方向 | 开仓时间 | 平仓时间 | 开仓价 | 平仓价 | 盈亏 | 退出原因 |
|---|---|---|---|---|---|---|
| {trade['交易方向']} | {trade['开仓时间']} | {trade['平仓时间']} | {trade['开仓价格']:.2f} | {trade['平仓价格']:.2f} | {trade['盈亏金额']:+.0f} | {trade['退出原因']} |