import pandas as pd
import akshare as ak
import warnings
warnings.filterwarnings(‘ignore’)
======参数设置======
start_date = ‘20100101’ #开始日期
end_date = ‘20250320’ #结束日期
ma_length = 26 #均线长度
cost = 0.0003 #交易费率,万三
获取美债收益率数据
bond_df = ak.bond_zh_us_rate(start_date=start_date)
bond_df[‘日期’] = bond_df[‘日期’].apply(lambda x: x.strftime(‘%Y-%m-%d’))
获取沪深300指数数据
hs300_df = ak.index_zh_a_hist(symbol=‘000300’, period=‘daily’, start_date=start_date, end_date=end_date)
hs300_df[‘涨跌幅’] = hs300_df[‘涨跌幅’] / 100.0 #将百分比转化成小数形式
合并数据,以沪深300日期为准
df = pd.merge(hs300_df[[‘日期’, ‘收盘’, ‘涨跌幅’]].rename(columns={‘收盘’:‘沪深300’}),
bond_df[[‘日期’,‘美国国债收益率10年’]].rename(columns={‘美国国债收益率10年’:‘美债收益率’}),
on=‘日期’, how=‘left’).fillna(method=‘ffill’).reset_index(drop=True)
df[‘日期’] = pd.to_datetime(df[‘日期’]) # ======获取每周最后一个交易日======
rule:重采样频率,W-周频,M-月频
week_df = df.resample(rule=‘W’, on=‘日期’).agg({‘日期’:‘last’,‘美债收益率’:‘last’}).dropna()
week_df[‘美债收益率MA’] = week_df[‘美债收益率’].rolling(ma_length).mean()
week_df[‘周最后交易日’] = 1
week_df.index.name = ‘date’ # 拼接数据
day_df = pd.merge(df.drop(columns=[‘美债收益率’]), week_df, on=‘日期’, how=‘left’)
day_df[‘周最后交易日’] = day_df[‘周最后交易日’].fillna(value=0) # 生成交易信号
如果 r-r_ma(26)<0,认为情绪偏多,今日只能看到昨日的数据
day_df.loc[((day_df[‘美债收益率’]-day_df[‘美债收益率MA’]).shift(1)<0) & (day_df[‘周最后交易日’].shift(1)>0), ‘signal’] = 1
如果 r-r_ma(26)>0,认为情绪偏空,今日只能看到昨日的数据
day_df.loc[((day_df[‘美债收益率’]-day_df[‘美债收益率MA’]).shift(1)>0) & (day_df[‘周最后交易日’].shift(1)>0), ‘signal’] = -1
day_df = day_df.set_index(‘日期’, drop=True) # 将交易信号转化为持仓
day_df[‘signal’] = day_df[‘signal’].fillna(method=‘ffill’).fillna(value=0)
day_df[‘position’] = day_df[‘signal’].shift(1).fillna(value=0) #收盘交易,下一日才会有持仓
考虑交易成本
day_df[‘after_cost’] = 1.0
day_df.loc[day_df[‘signal’] != day_df[‘signal’].shift(1), ‘after_cost’] = (1.0 + cost) * (1.0 + cost) #开平仓各收一次手续费
day_df.loc[(day_df[‘signal’].shift(1) == 0) & (day_df[‘signal’] != 0), ‘after_cost’] = 1.0 + cost #第一次开仓只收一次手续费
day_df.loc[day_df.index[0], ‘after_cost’] = 1.0 # 画出净值曲线图
import matplotlib.pyplot as plt
plt.rcParams[‘font.sans-serif’] = [‘SimHei’]
plt.rcParams[‘axes.unicode_minus’] = False
择时策略的日收益率
day_df[‘strategy_pct’] = day_df[‘涨跌幅’] * day_df[‘position’]
#策略和沪深300的净值
day_df[‘strategy’] = (1.0 + day_df[‘strategy_pct’]).cumprod() / day_df[‘after_cost’].cumprod()
day_df[‘benchmark’] = (1.0 + day_df[‘涨跌幅’]).cumprod()
粗略计算年化收益率
annual_return = 100 * (pow(day_df[‘strategy’].iloc[-1], 250/day_df.shape[0]) - 1.0)
print(‘美债收益率大盘择时策略的年化收益率:%.2f%%’ %annual_return)
#将索引从字符串转换为日期格式,方便展示
ax = day_df[[‘strategy’,‘benchmark’]].plot(figsize=(16,8), color=[‘SteelBlue’,‘Red’], grid=True,
title=‘美债收益率大盘择时策略净值’)
plt.show() 给上述代码再加上最大回撤及夏普比率 卡玛比率代码 比较基准也一块加上