一个监控ETF收益并发邮件的脚本

一个监控ETF收益并发邮件的脚本

import pandas as pd
import akshare as ak
import yagmail
from datetime import datetime, timedelta

# QQ 邮箱配置
QQ_EMAIL = "xx@qq.com"  # 发件人邮箱
QQ_PASSWORD ="xx"  # 发件人邮箱密码或授权码
TO_EMAIL = "xx@qq.com"  # 收件人邮箱


# ETF代码与名称的映射
etf_names = {
    '510300': '300ETF',
    '159915': '创业板',
    '513050': '中概互联网ETF',
    '159941': '纳指ETF',
    '518880': '黄金ETF',
    '511090': '30年国债ETF',
    '512890': '红利低波'
}

# 获取ETF数据的函数
def fetch_etf_data(symbol="510300"):
    # 使用 akshare 的 fund_etf_hist_em 接口获取 ETF 数据
    df = ak.fund_etf_hist_em(symbol=symbol, period="daily", adjust='qfq')

    # 转换日期格式
    df['日期'] = pd.to_datetime(df['日期'])  # 假设日期列名为 '日期'
    df.set_index('日期', inplace=True)

    # 重命名列以符合标准格式
    df.rename(columns={
        '开盘': 'Open',
        '最高': 'High',
        '最低': 'Low',
        '收盘': 'Close',
        '成交量': 'Volume'
    }, inplace=True)

    return df

# 计算收益率
def calculate_return(df, period):
    if period == '1w':
        start_date = datetime.now() - timedelta(days=7)
    elif period == '1m':
        start_date = datetime.now() - timedelta(days=30)
    elif period == '1y':
        start_date = datetime.now() - timedelta(days=365)
    elif period == '3y':
        start_date = datetime.now() - timedelta(days=365*3)
    else:
        raise ValueError("Invalid period")

    start_date = start_date.strftime('%Y-%m-%d')
    end_date = datetime.now().strftime('%Y-%m-%d')

    start_price = df.loc[start_date:end_date, 'Close'].iloc[0]
    end_price = df.loc[start_date:end_date, 'Close'].iloc[-1]

    return (end_price - start_price) / start_price

# 获取所有ETF的收益率
def get_etf_returns(etf_list):
    etf_returns = []
    for symbol in etf_list:
        df = fetch_etf_data(symbol)
        returns = {
            '1w': calculate_return(df, '1w'),
            '1m': calculate_return(df, '1m'),
            '1y': calculate_return(df, '1y'),
            '3y': calculate_return(df, '3y')
        }
        etf_returns.append((symbol, etf_names[symbol], returns))
    return etf_returns

# 按照最近一个月的收益率排序
def sort_etfs_by_1m_return(etf_returns):
    return sorted(etf_returns, key=lambda x: x[2]['1m'], reverse=True)

# 发送邮件
def send_email(etf_returns, today):
    try:
        # 邮件主题
        subject = f"ETF监控率报告 ({today})"

        # 邮件正文内容
        text_content = f"""
        日期: {today}
        以下是今日ETF的收益率分析(按近一个月收益率排序):
        """
        for symbol, name, returns in etf_returns:
            text_content += f"\n{symbol} ({name})\n"
            text_content += f"近一周收益率: {returns['1w']:.2%}\n"
            text_content += f"近一个月收益率: {returns['1m']:.2%}\n"
            text_content += f"近一年收益率: {returns['1y']:.2%}\n"
            text_content += f"近三年收益率: {returns['3y']:.2%}\n"

        # 初始化 yagmail
        yag = yagmail.SMTP(user=QQ_EMAIL, password=QQ_PASSWORD, host='smtp.qq.com', port=465, smtp_ssl=True)

        # 发送邮件
        yag.send(to=TO_EMAIL, subject=subject, contents=[text_content])

        print("邮件发送成功")
    except Exception as e:
        print(f"邮件发送失败: {e}")

# 主函数
def main():
    # 获取当前日期
    today = datetime.now().strftime("%Y-%m-%d")

    # ETF列表
    etf_list = ['510300', '159915', '513050', '159941', '518880','512890']

    # 获取所有ETF的收益率
    etf_returns = get_etf_returns(etf_list)

    # 按照最近一个月的收益率排序
    etf_returns_sorted = sort_etfs_by_1m_return(etf_returns)

    # 发送邮件
    send_email(etf_returns_sorted, today)

# 运行主函数
if __name__ == "__main__":
    main()
<think>好的,用户想要了解如何在聚宽平台上编写一个ETF轮动策略。首先,我需要回忆一下ETF轮动策略的基本概念。这类策略通常是通过在不同ETF之间切换,选择表现较好的标的,以获取超额收益。常见的轮动方法包括动量策略、均值回归等。 接下来,我需要考虑聚宽平台的特点。聚宽是基于Python的量化平台,所以策略需要用Python编写,并且要符合聚宽的API规范,比如handle_data函数、order_target等交易函数。同时,回测需要设置初始资金、起止时间等参数。 用户可能对ETF轮动策略的具体实现步骤不太清楚,需要分步骤解释。比如,如何选择ETF、确定轮动周期、计算指标、执行交易逻辑等。此外,用户可能关心如何衡量策略的有效性,比如风险控制、回撤等,但作为初步介绍,可能先聚焦在基础框架上。 需要确保示例代码的正确性,比如正确获取历史数据、计算动量指标、处理订单等。同时,要提醒用户这只是一个简单示例,实际应用中需要考虑更多因素,比如手续费、滑点、止盈止损等。 用户可能的疑问包括:如何选择适合的ETF品种?动量周期设置多长比较合适?是否需要进行参数优化?以及策略的风险在哪里?但在当前问题中,用户主要需求是策略的编写方法,因此可以先提供基础代码,再简要说明优化方向。 最后,要检查代码是否符合聚宽的环境要求,避免使用未来函数,确保回测逻辑正确。可能需要提到平台的数据获取方式,比如history函数的使用,以及order_target百分比的含义。</think>以下是一个基于动量效应的ETF轮动策略示例框架,采用聚宽平台实现。该策略通过比较不同ETF的短期收益率,持续持有表现最好的标的: ```python # 导入聚宽函数库 from jqdata import * # 初始化策略 def initialize(context): # 设置参数 set_parameters() # 参数配置 set_backtest() # 回测设置 def set_parameters(): # ETF列表(需替换为实际可交易的ETF代码) g.etf_list = ['510300.XSHG', '510500.XSHG', '159915.XSHE'] g.hold_num = 1 # 持仓数量 g.momentum_day = 20 # 动量计算周期 def set_backtest(): set_option('use_real_price', True) # 使用真实价格 set_order_cost(OrderCost(open_tax=0, close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5), type='stock') # 设置手续费 set_benchmark('000300.XSHG') # 设定基准 log.set_level('order', 'error') # 设置日志级别 # 每个交易日运行 def handle_data(context, data): # 每月第一个交易日调仓 if not is_trade_day(context.current_dt): return # 获取动量排名 momentum_rank = get_momentum_rank(g.etf_list, g.momentum_day) # 确定持仓标的 to_hold = momentum_rank[:g.hold_num] # 执行调仓 adjust_position(context, to_hold) # 计算动量排名 def get_momentum_rank(etf_list, period): momentum_dict = {} for etf in etf_list: # 获取历史价格 prices = attribute_history(etf, period, fields='close') # 计算收益率 returns = (prices['close'][-1] - prices['close'][0])/prices['close'][0] momentum_dict[etf] = returns # 按收益率降序排序 return sorted(momentum_dict.keys(), key=lambda x: momentum_dict[x], reverse=True) # 调整持仓 def adjust_position(context, to_hold): # 卖出当前持仓中不在目标列表的标的 for etf in context.portfolio.positions: if etf not in to_hold: order_target_value(etf, 0) # 买入目标标的 position_value = context.portfolio.total_value / len(to_hold) for etf in to_hold: order_target_value(etf, position_value) # 判断是否为调仓日 def is_trade_day(dt): # 示例为每月首个交易日调仓 today = dt.date() last_day = (dt - relativedelta(months=1)).date() return today.month != last_day.month ``` 策略核心逻辑: 1. **动量计算**:通过`get_momentum_rank`函数计算各ETF在过去N日的收益率 2. **定期调仓**:每月首个交易日执行调仓操作(可通过`is_trade_day`调整频率) 3. **持仓调整**:卖出非优选标的,等权重买入动量排名靠前的ETF 优化方向建议: 1. **标的池选择**:建议选择低相关性的ETF(如沪深300ETF、中证500ETF、创业板ETF) 2. **动量周期优化**:可测试不同周期(如10日/20日/60日)的收益表现 3. **风险控制**: - 添加最大回撤止损机制 - 设置单品种持仓上限 - 加入波动率过滤条件 4. **交易优化**: - 考虑交易成本的影响 - 添加滑点控制 - 设置最小交易量阈值 注意事项: 1. 实际使用需替换为当前可交易的ETF代码 2. 建议在模拟盘测试后再实盘运行 3. 需定期检查ETF的流动性和折溢价情况 4. 历史回测不代表未来表现,需持续跟踪策略有效性 该策略属于趋势跟踪型策略,在延续趋势的市场环境中表现较好,但在震荡市中可能出现频繁交易损耗。建议结合其他指标(如波动率、市场情绪等)构建复合策略。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鸭梨山大哎

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值