ETF阶段涨幅计算

代码如下

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


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

# 获取ETF历史数据的函数
def fetch_etf_data(symbol, start_date, end_date):
    df = ak.fund_etf_hist_em(symbol=symbol, period="daily", start_date=start_date, end_date=end_date, 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_price_change(df, current_price):
    if df.empty:
        return None, None

    last_year_high = df['High'].max()
    last_year_low = df['Low'].min()

    fall_from_high = ((last_year_high - current_price) / last_year_high) * 100 if last_year_high > 0 else None
    rise_from_low = ((current_price - last_year_low) / last_year_low) * 100 if last_year_low > 0 else None

    return fall_from_high, rise_from_low

# 发送邮件的函数
def send_email(html_content, today):
    try:
        subject = f"ETF涨跌幅分析报告({today})"
        yag = yagmail.SMTP(user=os.getenv('from_email'), password=os.getenv('password'), host='smtp.qq.com', port=465, smtp_ssl=True)
        yag.send(to=os.getenv('to_email'), subject=subject, contents=[html_content])
        print("邮件发送成功")
    except Exception as e:
        print(f"邮件发送失败: {e}")

# 主程序
if __name__ == "__main__":
    today = datetime.today()
    last_year_today = (today - timedelta(days=365)).strftime('%Y%m%d')
    today_str = today.strftime('%Y%m%d')

    results = []

    for symbol, name in etf_names.items():
        print(f"正在处理 {name} ({symbol})...")

        df = fetch_etf_data(symbol, start_date=last_year_today, end_date=today_str)
        current_price = df['Close'].iloc[-1] if not df.empty else None

        if current_price is not None:
            fall_from_high, rise_from_low = calculate_price_change(df, current_price)
            results.append({
                'ETF名称': name,
                '代码': symbol,
                '当前价格': round(current_price, 2),
                '相比去年最高点跌幅 (%)': round(fall_from_high, 2) if fall_from_high is not None else "N/A",
                '相比去年最低点涨幅 (%)': round(rise_from_low, 2) if rise_from_low is not None else "N/A"
            })
        else:
            print(f"未获取到 {name} ({symbol}) 的数据。")

    # 将结果转换为DataFrame
    results_df = pd.DataFrame(results)

    # 仅按“相比去年最低点涨幅 (%)”降序排列
    results_df.sort_values(by=['相比去年最低点涨幅 (%)'], ascending=False, inplace=True)

    # 生成简单的HTML表格
    html_content = f"""
    <html>
    <body>
    <h1>ETF涨跌幅分析报告</h1>
    <p>报告日期:{today.strftime('%Y-%m-%d')}</p>
    <table border="1">
        <tr>
            <th>ETF名称</th>
            <th>代码</th>
            <th>当前价格</th>
            <th>相比去年最高点跌幅 (%)</th>
            <th>相比去年最低点涨幅 (%)</th>
        </tr>
    """

    for _, row in results_df.iterrows():
        # 设置颜色:涨幅为红色,跌幅为蓝色
        fall_color = "blue" if isinstance(row['相比去年最高点跌幅 (%)'], (int, float)) and row['相比去年最高点跌幅 (%)'] < 0 else "black"
        rise_color = "red" if isinstance(row['相比去年最低点涨幅 (%)'], (int, float)) and row['相比去年最低点涨幅 (%)'] > 0 else "black"

        html_content += f"""
        <tr>
            <td>{row['ETF名称']}</td>
            <td>{row['代码']}</td>
            <td>{row['当前价格']}</td>
            <td style="color:{fall_color}">{row['相比去年最高点跌幅 (%)']}</td>
            <td style="color:{rise_color}">{row['相比去年最低点涨幅 (%)']}</td>
        </tr>
        """

    html_content += """
    </table>
    </body>
    </html>
    """

    # 发送邮件
    send_email(html_content, today.strftime('%Y-%m-%d'))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

鸭梨山大哎

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

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

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

打赏作者

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

抵扣说明:

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

余额充值