代码如下
import akshare as ak
import pandas as pd
import numpy as np
import yagmail
import os
from datetime import datetime
# ETF代码与名称的映射
etf_names = {
'510300': '300ETF',
'159915': '创业板',
'513050': '中概互联网ETF',
'159941': '纳指ETF',
'518880': '黄金ETF',
'511090': '30年国债ETF'
}
# 获取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
# 计算BIAS指标的函数
def calculate_bias(df, window=12):
# 计算移动平均线
df['MA'] = df['Close'].rolling(window=window).mean()
# 计算BIAS,并保留两位小数,加上百分号
df['BIAS'] = ((df['Close'] - df['MA']) / df['MA'] * 100).round(2).astype(str) + '%'
return df
# 生成交易信号的函数
def generate_signals(df, buy_threshold=-6, sell_threshold=6):
df['信号'] = '无信号'
df.loc[df['BIAS'].str.rstrip('%').astype(float) < buy_threshold, '信号'] = '买入信号'
df.loc[df['BIAS'].str.rstrip('%').astype(float) > sell_threshold, '信号'] = '卖出信号'
return df
# 发送邮件的函数
def send_email(html_content, today, attachment_path=None):
try:
# 邮件主题
subject = f"ETF BIAS分析报告({today})"
# 初始化 yagmail
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], attachments=attachment_path)
print("邮件发送成功")
except Exception as e:
print(f"邮件发送失败: {e}")
# 生成简单HTML表格的函数
def generate_simple_html_table(df, name, symbol):
# 表头
html = f"<h3>{name} ({symbol}) 最近5天的BIAS信号:</h3>"
html += "<table border='1'><tr><th>日期</th><th>收盘价</th><th>移动平均线</th><th>BIAS</th><th>信号</th></tr>"
# 表格内容
for date, row in df.tail(5).iterrows():
# 根据信号设置颜色
if row['信号'] == '买入信号':
signal_color = "blue"
elif row['信号'] == '卖出信号':
signal_color = "red"
else:
signal_color = "black"
html += f"<tr><td>{date.strftime('%Y-%m-%d')}</td><td>{round(row['Close'], 2)}</td><td>{round(row['MA'], 2)}</td><td>{row['BIAS']}</td><td><span style='color:{signal_color};'>{row['信号']}</span></td></tr>"
html += "</table>"
return html
# 主程序
if __name__ == "__main__":
# 获取当前日期
today = datetime.today().strftime('%Y-%m-%d')
# 存储所有ETF的分析结果
results = []
# 遍历所有ETF
for symbol, name in etf_names.items():
print(f"\n正在分析 {name} ({symbol}) 的BIAS信号...")
# 获取ETF数据
df = fetch_etf_data(symbol)
# 计算BIAS指标
df = calculate_bias(df, window=12)
# 生成交易信号
df = generate_signals(df, buy_threshold=-6, sell_threshold=6)
# 生成简单HTML表格
html_table = generate_simple_html_table(df, name, symbol)
results.append(html_table)
# 将所有结果合并为HTML内容
html_content = "<html><body>" + "<br>".join(results) + "</body></html>"
# 发送邮件
send_email(html_content, today)