活动介绍

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() 给上述代码再加上最大回撤及夏普比率 卡玛比率代码 比较基准也一块加上

时间: 2025-07-08 14:35:43 浏览: 18
<think>好的,我需要帮用户给现有的Python代码添加最大回撤、夏普比率和卡玛比率,同时将这些指标与基准(沪深300)进行比较。现在我先仔细理解用户提供的代码结构,然后确定需要添加的部分。 首先,用户现有的代码通过美债收益率的移动平均生成交易信号,计算策略的净值曲线和年化收益率。现在需要补充三个指标:最大回撤、夏普比率、卡玛比率,并且对基准也做同样的计算。 最大回撤的计算需要找出净值曲线从峰值到谷底的最大跌幅。可以通过累计最大值和当前值来计算每日的回撤,然后取最大值。 夏普比率需要策略的年化收益率减去无风险利率(这里可能需要假设,比如用美债收益率作为无风险利率?但用户代码中未明确,可能需要用0或者另外获取数据),然后除以年化波动率。这里需要注意计算的是日度夏普,然后年化处理。 卡玛比率则是年化收益率除以最大回撤,所以需要先算年化收益和最大回撤。 另外,用户希望将基准(沪深300的净值)也计算同样的指标,所以需要分别对策略和基准进行处理。 现在分步骤考虑: 1. **计算最大回撤**:对于策略和基准的净值序列,计算每个时间点的历史最高值,然后计算当前净值相对于历史最高值的回撤比例,找出最大值。 2. **计算夏普比率**:需要日收益率数据。年化收益率已经计算,但需要年化波动率。假设一年约250个交易日。另外,无风险利率可能需要处理,例如用户可能用美债收益率的平均值作为无风险利率,或者忽略(即设为0)。这里可能需要进一步确认,但用户代码中没有明确,暂时假设无风险利率为0,或者从数据中提取。例如,美债收益率可能作为无风险利率的代理,但需要日度数据。当前代码中的美债收益率是周数据,填充到日数据,可能用ffill。所以,可以考虑每日的无风险利率是该天的美债收益率,或者周最后一个交易日的值。但这里可能比较复杂,用户可能希望简化处理,比如假设无风险利率为0。或者,用美债收益率的日数据计算日度的无风险收益。例如,将美债收益率除以252得到日利率。这部分需要明确,但用户代码中可能没有处理,所以可能需要假设或者询问用户,但根据用户的问题,可能暂时按默认方式处理,即使用年化无风险利率,例如0或者使用美债收益率的平均值。但需要看用户的数据是否有相关字段。 查看代码中的df结构,合并了美债收益率的数据,可能day_df中有美债收益率的日数据。所以,可以考虑将每日的美债收益率作为无风险利率。例如,将日度的美债收益率除以252(假设年化),得到日无风险利率。例如,如果美债收益率是年化的,那么日利率是r/252。但需要确认用户的数据中美债收益率的单位是否为年化百分比。例如,用户数据中的美债收益率如果是3表示3%,那么需要转换成小数形式。在现有代码中,用户处理涨跌幅时除以了100,所以可能美债收益率也是以百分比形式存在,需要转换。例如,原数据中的‘美国国债收益率10年’是百分比数值,比如3.0代表3%,所以用户可能在合并后没有处理,所以在day_df中的‘美债收益率’是百分比数值。例如,如果美债收益率是3%,那么日无风险利率为0.03/252。这可能需要调整。 但用户的代码中,可能未对美债收益率进行单位转换,例如原数据中的美债收益率是否为百分比形式(比如3.0代表3%)?比如在bond_df中,是否已经是小数形式?查看用户代码: 在获取美债收益率数据时,用户用的是akshare的bond_zh_us_rate函数。查阅akshare文档,美国国债收益率的数据返回的是数值型,例如10年期国债收益率可能是以百分比为单位,比如1.5表示1.5%。因此,用户可能需要将其转换为小数。例如,原数据中的美债收益率是1.5,那么实际是0.015。但用户当前代码中在合并后,并未进行这样的转换。例如,在合并后的df中的‘美债收益率’列是直接取自bond_df的‘美国国债收益率10年’,所以可能是百分比数值,如2.5代表2.5%。这时候需要除以100转化为小数形式。但用户的代码中,在获取沪深300的涨跌幅时,将其除以100转化为小数,但美债收益率可能没有处理,所以在计算无风险利率时需要转换。这可能是一个问题,需要确认。 例如,用户当前的代码中: hs300_df[‘涨跌幅’] = hs300_df[‘涨跌幅’] / 100.0 #将百分比转化成小数形式 但bond_df中的‘美国国债收益率10年’没有进行这样的转换,所以可能该列的数据是如3.0表示3%,即0.03的小数形式?或者原数据是3.0代表3%?需要确认akshare返回的数据格式。假设akshare返回的美债收益率是百分比形式,例如3.0代表3%,则用户需要将其除以100转换为小数。例如,在合并后的df中美债收益率是3.0,此时用户需要将其转换为0.03。否则,如果已经是小数形式(如0.03),则无需转换。如果用户代码中未处理,那么在计算无风险利率时可能出现错误。 例如,用户代码中的美债收益率可能未转换,导致数值错误。这可能是一个潜在的问题。但根据用户的现有代码,暂时无法确定,所以可能需要假设。例如,假设美债收益率是以百分比形式存在,例如3.0代表3%,所以在计算时需要除以100转换为小数。因此,在计算无风险利率时,需要将美债收益率转换为小数,再计算日利率。 例如,假设用户的美债收益率是年化百分比,则日无风险利率为 (美债收益率 / 100) / 252。 但用户的代码中,美债收益率可能已经被处理了?或者原数据中已经是小数形式?比如,bond_zh_us_rate返回的数据是否已经是小数?比如,3%表示为0.03。需要确认。假设原数据中的美债收益率是小数形式,例如0.03代表3%,那么无需转换。否则,如果是3.0,则需要除以100。 这个问题可能会影响夏普比率的计算,所以需要处理。如果用户当前代码中没有对美债收益率进行转换,那么需要加上这一步。例如,在合并后的df中美债收益率是百分比数值,需要除以100。 例如,在合并后的df中,加入: df['美债收益率'] = df['美债收益率'] / 100.0 但用户当前的代码中没有这一步,所以在后续计算中可能存在错误。但用户的问题不是调试代码,而是添加最大回撤等指标。因此,这里可能需要先修正美债收益率的转换问题,或者在计算无风险利率时进行处理。 这可能是一个需要注意的地方,但根据用户提供的现有代码,可能没有处理,所以这可能导致夏普比率计算时的错误。因此,在回答时需要指出这一点,或者直接在代码中添加转换。 综上,考虑到用户可能忽略将美债收益率转换为小数形式,所以在夏普比率计算时,需要处理。例如,在合并后的数据中,将美债收益率除以100: df['美债收益率'] = df['美债收益率'] / 100.0 或者在计算无风险利率时处理。 现在回到用户的代码,在合并后的df中,美债收益率是来自bond_df的‘美国国债收益率10年’,而bond_df的数据可能未转换,所以需要检查是否应该进行转换。例如,假设原数据中的美债收益率是百分比数值,例如3.0代表3%,所以需要除以100转换为小数形式。这可能是一个必要的步骤,但用户的现有代码中没有,所以在添加指标时可能需要先处理。 因此,在合并后的df中,应该添加: df['美债收益率'] = df['美债收益率'] / 100.0 这样才能正确使用美债收益率作为无风险利率。否则,如果美债收益率是小数形式,例如0.03代表3%,则无需处理。这需要用户确认akshare返回的数据格式。但根据用户处理涨跌幅的方式(除以100),推测美债收益率也需要同样的处理,所以应该在代码中添加这一步。 现在,假设用户的代码需要修正,将美债收益率转换为小数形式,在合并后的数据中添加: df['美债收益率'] = df['美债收益率'] / 100.0 接下来,计算夏普比率时,需要策略的日收益率减去无风险利率的日收益率。假设美债收益率是年化的,那么日无风险利率为 (美债收益率) / 252。例如,年化3%的美债收益率对应的日利率约为0.03/252 ≈ 0.00011905。 因此,在计算每日的超额收益率时,策略的日收益率减去当日的无风险日利率。 但需要注意,美债收益率的数据可能存在缺失或者填充的情况。在用户代码中,合并数据时使用了ffill填充,所以每个交易日都有美债收益率的数据。 现在,添加最大回撤、夏普比率、卡玛比率的具体步骤: **对于策略和基准:** 1. 最大回撤: 计算累计最大净值,然后计算每日回撤((累计最大值 - 当前净值)/ 累计最大值),取最大值。 2. 夏普比率: 计算日度超额收益率(策略日收益率 - 无风险日利率),计算平均超额收益率的年化值(乘以252),标准差年化(乘以sqrt(252)),夏普比率 = 年化平均超额收益率 / 年化标准差。 或者,如果假设无风险利率为0,则直接使用策略的日收益率计算。 但更准确的做法是使用无风险利率,这里用美债收益率作为无风险利率的代理。 3. 卡玛比率: 年化收益率 / 最大回撤。 **具体代码实现:** 首先,计算策略和基准的净值曲线已经存在('strategy'和'benchmark'列)。 然后,计算最大回撤: 对于策略: max_drawdown = (1 - (day_df['strategy'] / day_df['strategy'].cummax())).max() 同样,基准的最大回撤: benchmark_max_drawdown = (1 - (day_df['benchmark'] / day_df['benchmark'].cummax())).max() 然后,夏普比率: 需要策略的日收益率,这里策略的日收益率存储在'strategy_pct'列,但已经考虑了持仓和交易成本。或者,策略的日收益率是根据'strategy'列计算的每日收益率。例如: day_df['strategy_daily_return'] = day_df['strategy'].pct_change().fillna(0) 但可能更准确的方式是使用已经计算好的'strategy_pct'列,因为策略的日收益率是涨跌幅乘以持仓,并且考虑交易成本后的净值。但原代码中的'strategy_pct'是涨跌幅乘以position,然后累计乘积再除以after_cost的累计乘积,这可能比较复杂。或者,可能应该根据净值的每日变化来计算日收益率。例如,策略的日收益率是 (strategy_t / strategy_{t-1}) - 1。 所以更准确的计算方式是: day_df['strategy_daily_return'] = day_df['strategy'].pct_change().fillna(0) 同样,基准的日收益率是涨跌幅,即'涨跌幅'列。 对于无风险日利率,假设美债收益率是年化收益率,将其转换为日利率: day_df['risk_free_daily'] = day_df['美债收益率'] / 252 然后,计算超额收益率: day_df['excess_return_strategy'] = day_df['strategy_daily_return'] - day_df['risk_free_daily'] 夏普比率 = (平均超额收益率 * 252) / (超额收益率的标准差 * sqrt(252)) 即: sharpe_ratio = (excess_return_strategy.mean() * 252) / (excess_return_strategy.std() * np.sqrt(252)) 同样,对于基准: day_df['benchmark_daily_return'] = day_df['benchmark'].pct_change().fillna(0) excess_return_benchmark = day_df['benchmark_daily_return'] - day_df['risk_free_daily'] sharpe_ratio_benchmark = (excess_return_benchmark.mean() * 252) / (excess_return_benchmark.std() * np.sqrt(252)) 卡玛比率: 策略年化收益率 / 策略最大回撤 假设已有策略的年化收益率变量annual_return(以小数形式,比如0.1代表10%),则卡玛比率 = annual_return / max_drawdown 同样计算基准的年化收益率,然后卡玛比率。 但原代码中的annual_return是用户计算的策略年化收益率,但以百分比形式输出。例如,用户代码中的: annual_return = 100 * (pow(day_df['strategy'].iloc[-1], 250/day_df.shape[0]) - 1.0) 这里,可能计算有误,因为通常年化收益率的计算应该是 (净值^(365/天数) - 1),但用户这里用250/day_df.shape[0]。假设一年250个交易日,所以是正确的。 但需要将结果转换为小数形式,比如如果annual_return是10.5(代表10.5%),则需要除以100得到0.105。 因此,在计算卡玛比率时,应该用年化收益率的小数形式除以最大回撤的小数形式。 现在,具体代码步骤: 首先,计算最大回撤: # 策略最大回撤 strategy_max_drawdown = (1 - day_df['strategy'] / day_df['strategy'].cummax()).max() # 基准最大回撤 benchmark_max_drawdown = (1 - day_df['benchmark'] / day_df['benchmark'].cummax()).max() 然后,计算夏普比率: 假设无风险利率是美债收益率,年化转换为日: import numpy as np # 转换美债收益率为小数(如果尚未转换) day_df['美债收益率'] = day_df['美债收益率'] / 100.0 # 如果原数据是百分比形式,例如3.0代表3% day_df['risk_free_daily'] = day_df['美债收益率'] / 252 # 计算策略的日收益率 day_df['strategy_daily_return'] = day_df['strategy'].pct_change().fillna(0) # 计算基准的日收益率 day_df['benchmark_daily_return'] = day_df['benchmark'].pct_change().fillna(0) # 策略超额收益 day_df['excess_return_strategy'] = day_df['strategy_daily_return'] - day_df['risk_free_daily'] # 基准超额收益 day_df['excess_return_benchmark'] = day_df['benchmark_daily_return'] - day_df['risk_free_daily'] # 计算夏普比率 sharpe_strategy = (day_df['excess_return_strategy'].mean() * 252) / (day_df['excess_return_strategy'].std() * np.sqrt(252)) sharpe_benchmark = (day_df['excess_return_benchmark'].mean() * 252) / (day_df['excess_return_benchmark'].std() * np.sqrt(252)) 卡玛比率: # 计算策略年化收益率(小数形式) annual_return_strategy = pow(day_df['strategy'].iloc[-1], 250/day_df.shape[0]) - 1.0 # 卡玛比率策略 calmar_strategy = annual_return_strategy / strategy_max_drawdown # 计算基准年化收益率 annual_return_benchmark = pow(day_df['benchmark'].iloc[-1], 250/day_df.shape[0]) - 1.0 # 卡玛比率基准 calmar_benchmark = annual_return_benchmark / benchmark_max_drawdown 然后,将这些指标格式化输出,与之前的annual_return一起显示。 用户当前的代码中,annual_return是以百分比形式打印的,所以可能需要将这里的annual_return_strategy乘以100得到百分比形式。 同时,注意原代码中的annual_return计算可能存在误差,因为用户用了250/day_df.shape[0],而实际交易日数量可能不等于该数值。但用户可能假设如此,所以保持原计算方式。 现在,将这些代码添加到用户的代码中: 在计算完annual_return后,添加: import numpy as np # 计算最大回撤 day_df['strategy_cummax'] = day_df['strategy'].cummax() strategy_max_drawdown = (1 - day_df['strategy'] / day_df['strategy_cummax']).max() day_df['benchmark_cummax'] = day_df['benchmark'].cummax() benchmark_max_drawdown = (1 - day_df['benchmark'] / day_df['benchmark_cummax']).max() # 转换美债收益率为小数形式(假设原数据为百分比) day_df['美债收益率'] = day_df['美债收益率'] / 100.0 # 计算无风险日利率 day_df['risk_free_daily'] = day_df['美债收益率'] / 252 # 计算策略和基准的日收益率 day_df['strategy_daily_return'] = day_df['strategy'].pct_change().fillna(0) day_df['benchmark_daily_return'] = day_df['benchmark'].pct_change().fillna(0) # 计算超额收益 day_df['excess_return_strategy'] = day_df['strategy_daily_return'] - day_df['risk_free_daily'] day_df['excess_return_benchmark'] = day_df['benchmark_daily_return'] - day_df['risk_free_daily'] # 计算夏普比率 sharpe_strategy = (day_df['excess_return_strategy'].mean() * 252) / (day_df['excess_return_strategy'].std() * np.sqrt(252)) sharpe_benchmark = (day_df['excess_return_benchmark'].mean() * 252) / (day_df['excess_return_benchmark'].std() * np.sqrt(252)) # 计算卡玛比率 annual_return_strategy = pow(day_df['strategy'].iloc[-1], 250/day_df.shape[0]) - 1.0 calmar_strategy = annual_return_strategy / strategy_max_drawdown annual_return_benchmark = pow(day_df['benchmark'].iloc[-1], 250/day_df.shape[0]) - 1.0 calmar_benchmark = annual_return_benchmark / benchmark_max_drawdown # 输出结果 print('策略年化收益率:{:.2f}%'.format(annual_return * 100)) # 这里原代码中的annual_return可能已经计算正确? print('策略最大回撤:{:.2%}'.format(strategy_max_drawdown)) print('策略夏普比率:{:.2f}'.format(sharpe_strategy)) print('策略卡玛比率:{:.2f}'.format(calmar_strategy)) print('------------------------') print('基准年化收益率:{:.2f}%'.format(annual_return_benchmark * 100)) print('基准最大回撤:{:.2%}'.format(benchmark_max_drawdown)) print('基准夏普比率:{:.2f}'.format(sharpe_benchmark)) print('基准卡玛比率:{:.2f}'.format(calmar_benchmark)) 但需要注意原代码中的annual_return变量是否正确。用户原来的代码: annual_return = 100 * (pow(day_df['strategy'].iloc[-1], 250/day_df.shape[0]) - 1.0) 这可能有问题,因为策略的净值在计算时除以了after_cost的累计乘积。例如,策略的净值计算是: day_df['strategy'] = (1.0 + day_df['strategy_pct']).cumprod() / day_df['after_cost'].cumprod() 但after_cost的累计乘积可能不是简单的时间加权,需要确认是否正确。或者,是否应该直接根据strategy的净值曲线计算年化收益率。例如,年化收益率的正确计算应该是: (day_df['strategy'].iloc[-1] ** (252 / len(day_df))) - 1 假设每年252个交易日,len(day_df)是总交易日数。所以用户原来的代码中使用了250/day_df.shape[0],可能存在偏差。应该根据实际交易天数调整。 例如,正确的年化收益率计算应为: annual_return_strategy = (day_df['strategy'].iloc[-1] ** (252 / len(day_df))) - 1 同样适用于基准的年化收益率。 因此,用户原来的annual_return计算可能需要修正。例如,将250改为252,并计算正确的年化收益率。但用户可能根据自身需求设置,这里暂时保持原计算方式,但需要注意。 综上,将这些代码添加到用户现有代码的打印年化收益率之后即可。 同时,可能需要在计算前导入numpy: import numpy as np 现在,整合到用户代码中: 在plt.show()之前添加: # 计算最大回撤 day_df['strategy_cummax'] = day_df['strategy'].cummax() strategy_max_drawdown = (1 - day_df['strategy'] / day_df['strategy_cummax']).max() day_df['benchmark_cummax'] = day_df['benchmark'].cummax() benchmark_max_drawdown = (1 - day_df['benchmark'] / day_df['benchmark_cummax']).max() # 转换美债收益率为小数形式(假设原数据为百分比) day_df['美债收益率'] = day_df['美债收益率'] / 100.0 # 计算无风险日利率 day_df['risk_free_daily'] = day_df['美债收益率'] / 252 # 计算策略和基准的日收益率 day_df['strategy_daily_return'] = day_df['strategy'].pct_change().fillna(0) day_df['benchmark_daily_return'] = day_df['benchmark'].pct_change().fillna(0) # 计算超额收益 day_df['excess_return_strategy'] = day_df['strategy_daily_return'] - day_df['risk_free_daily'] day_df['excess_return_benchmark'] = day_df['benchmark_daily_return'] - day_df['risk_free_daily'] # 计算夏普比率 sharpe_strategy = (day_df['excess_return_strategy'].mean() * 252) / (day_df['excess_return_strategy'].std() * np.sqrt(252)) sharpe_benchmark = (day_df['excess_return_benchmark'].mean() * 252) / (day_df['excess_return_benchmark'].std() * np.sqrt(252)) # 计算卡玛比率 annual_return_strategy = pow(day_df['strategy'].iloc[-1], 250/day_df.shape[0]) - 1.0 calmar_strategy = annual_return_strategy / strategy_max_drawdown annual_return_benchmark = pow(day_df['benchmark'].iloc[-1], 250/day_df.shape[0]) - 1.0 calmar_benchmark = annual_return_benchmark / benchmark_max_drawdown print('策略年化收益率:{:.2f}%'.format(annual_return)) print('策略最大回撤:{:.2%}'.format(strategy_max_drawdown)) print('策略夏普比率:{:.2f}'.format(sharpe_strategy)) print('策略卡玛比率:{:.2f}'.format(calmar_strategy)) print('------------------------') print('基准年化收益率:{:.2f}%'.format(annual_return_benchmark * 100)) print('基准最大回撤:{:.2%}'.format(benchmark_max_drawdown)) print('基准夏普比率:{:.2f}'.format(sharpe_benchmark)) print('基准卡玛比率:{:.2f}'.format(calmar_benchmark)) 但需要注意,原来的annual_return是用户计算的策略年化收益率,而annual_return_strategy是重新计算的,可能存在差异。例如,用户原来的代码: annual_return = 100 * (pow(day_df['strategy'].iloc[-1], 250/day_df.shape[0]) - 1.0) 而在这里,annual_return_strategy = pow(...) - 1.0,没有乘以100。所以,在打印基准年化时,应该使用annual_return_benchmark * 100。 或者,统一使用新的计算方式,避免混淆。例如,重新计算策略和基准的年化收益率: # 重新计算年化收益率(假设250个交易日) annual_return_strategy = (day_df['strategy'].iloc[-1] ** (250 / len(day_df))) - 1 annual_return_benchmark = (day_df['benchmark'].iloc[-1] ** (250 / len(day_df))) - 1 print('策略年化收益率:{:.2%}'.format(annual_return_strategy)) print('策略最大回撤:{:.2%}'.format(strategy_max_drawdown)) print('策略夏普比率:{:.2f}'.format(sharpe_strategy)) print('策略卡玛比率:{:.2f}'.format(annual_return_strategy / strategy_max_drawdown)) print('------------------------') print('基准年化收益率:{:.2%}'.format(annual_return_benchmark)) print('基准最大回撤:{:.2%}'.format(benchmark_max_drawdown)) print('基准夏普比率:{:.2f}'.format(sharpe_benchmark)) print('基准卡玛比率:{:.2f}'.format(annual_return_benchmark / benchmark_max_drawdown)) 这样更统一,可能更准确。 但用户原来的代码中annual_return是乘以100并以百分比打印,所以需要保持一致性。或者,建议用户统一使用更准确的年化计算方法,并确保美债收益率的转换正确。 综上,最终的代码补充部分应该包括: 1. 转换美债收益率为小数形式(如果原数据是百分比)。 2. 计算最大回撤。 3. 计算夏普比率,使用美债收益率作为无风险利率。 4. 计算卡玛比率。 同时,将基准的相同指标一并计算并输出。 最后,确保导入numpy库,并在代码中添加必要的部分。</think>以下是添加最大回撤、夏普比率和卡玛比率的完整代码实现(新增部分已用注释标注): ```python # ... 原有代码保持不变 ... # ======新增性能指标计算====== import numpy as np # 计算最大回撤(策略) day_df['strategy_cummax'] = day_df['strategy'].cummax() strategy_drawdown = (day_df['strategy'] - day_df['strategy_cummax']) / day_df['strategy_cummax'] strategy_max_drawdown = strategy_drawround.min() # 计算最大回撤(基准) day_df['benchmark_cummax'] = day_df['benchmark'].cummax() benchmark_drawdown = (day_df['benchmark'] - day_df['benchmark_cummax']) / day_df['benchmark_cummax'] benchmark_max_drawdown = benchmark_drawdown.min() # 转换美债收益率为小数格式(假设原始数据为百分比) day_df['美债收益率'] = day_df['美债收益率'] / 100.0 # 计算年化无风险利率(使用美债收益率均值) risk_free_rate = day_df['美债收益率'].mean() # 计算夏普比率(策略) strategy_return = day_df['strategy'].pct_change().dropna() excess_return_strategy = strategy_return - risk_free_rate/252 sharpe_strategy = np.sqrt(252) * excess_return_strategy.mean() / excess_return_strategy.std() # 计算夏普比率(基准) benchmark_return = day_df['涨跌幅'].copy() excess_return_benchmark = benchmark_return - risk_free_rate/252 sharpe_benchmark = np.sqrt(252) * excess_return_benchmark.mean() / excess_return_benchmark.std() # 计算卡玛比率(策略) annual_return_strategy = (day_df['strategy'].iloc[-1] ** (250/len(day_df)) - 1) calmar_strategy = annual_return_strategy / abs(strategy_max_drawdown) # 计算卡玛比率(基准) annual_return_benchmark = (day_df['benchmark'].iloc[-1] ** (250/len(day_df)) - 1) calmar_benchmark = annual_return_benchmark / abs(benchmark_max_drawdown) # ======结果输出====== print('\n======策略表现======') print(f'策略年化收益率:{annual_return:.2f}%') print(f'策略最大回撤:{abs(strategy_max_drawdown):.2%}') print(f'策略夏普比率:{sharpe_strategy:.2f}') print(f'策略卡玛比率:{calmar_strategy:.2f}') print('\n======基准表现======') print(f'基准年化收益率:{annual_return_benchmark*100:.2f}%') print(f'基准最大回撤:{abs(benchmark_max_drawdown):.2%}') print(f'基准夏普比率:{sharpe_benchmark:.2f}') print(f'基准卡玛比率:{calmar_benchmark:.2f}') # ... 后续绘图代码保持不变 ... ``` **代码说明:** 1. **最大回撤计算**:通过累计最大值计算每个交易日的回撤率,取最小值作为最大回撤(结果为负值,取绝对值显示) 2. **夏普比率计算**: - 使用$$Sharpe = \frac{E(R_p - R_f)}{\sigma_p} \times \sqrt{252}$$公式 - 将年化美债收益率转换为日无风险利率$$R_f^{daily} = R_f^{annual}/252$$ 3. **卡玛比率计算**: - 使用$$Calmar = \frac{年化收益率}{最大回撤}$$公式 - 年化收益率计算保持与原有代码一致(250个交易日假设) 4. **基准指标计算**: - 使用沪深300原始涨跌幅计算基准的夏普比率 - 基准最大回撤计算方式与策略一致 **注意事项:** 1. 美债收益率数据需要确认是否为百分比格式,若原始数据已为小数格式需删除转换代码 2. 年化交易日假设可根据实际数据调整(建议使用252天) 3. 最大回撤计算结果为负值,输出时取绝对值显示
阅读全文

相关推荐

最新推荐

recommend-type

婚纱摄影公司网络推广人员工作绩效说明.docx

婚纱摄影公司网络推广人员工作绩效说明.docx
recommend-type

公路工程的项目管理分析.doc

公路工程的项目管理分析.doc
recommend-type

VC图像编程全面资料及程序汇总

【标题】:"精通VC图像编程资料全览" 【知识点】: VC即Visual C++,是微软公司推出的一个集成开发环境(IDE),专门用于C++语言的开发。VC图像编程涉及到如何在VC++开发环境中处理和操作图像。在VC图像编程中,开发者通常会使用到Windows API中的GDI(图形设备接口)或GDI+来进行图形绘制,以及DirectX中的Direct2D或DirectDraw进行更高级的图形处理。 1. GDI(图形设备接口): - GDI是Windows操作系统提供的一套应用程序接口,它允许应用程序通过设备无关的方式绘制图形。 - 在VC图像编程中,主要使用CDC类(设备上下文类)来调用GDI函数进行绘制,比如绘制线条、填充颜色、显示文本等。 - CDC类提供了很多函数,比如`MoveTo`、`LineTo`、`Rectangle`、`Ellipse`、`Polygon`等,用于绘制基本的图形。 - 对于图像处理,可以使用`StretchBlt`、`BitBlt`、`TransparentBlt`等函数进行图像的位块传输。 2. GDI+: - GDI+是GDI的后继技术,提供了更丰富的图形处理功能。 - GDI+通过使用`Graphics`类来提供图像的绘制、文本的渲染、图像的处理和颜色管理等功能。 - GDI+引入了对矢量图形、渐变色、复杂的文本格式和坐标空间等更高级的图形处理功能。 - `Image`类是GDI+中用于图像操作的基础类,通过它可以进行图像的加载、保存、旋转、缩放等操作。 3. DirectX: - DirectX是微软推出的一系列API集合,用于在Windows平台上进行高性能多媒体编程。 - DirectX中的Direct2D是用于硬件加速的二维图形API,专门用于UI元素和简单的图形渲染。 - DirectDraw主要用于硬件加速的位图操作,比如全屏游戏开发中的画面渲染。 4. 位图操作: - 在VC图像编程中,位图操作是一个重要的部分。需要了解如何加载、保存和处理位图(BMP)文件。 - 可以使用位图文件格式的解析,来访问位图的像素数据,进行像素级别的图像处理和修改。 5. 高级图像处理技术: - 包括图像滤镜、图像转换、图像压缩和解压缩技术。 - 需要掌握一些图像处理算法,比如卷积、FFT(快速傅里叶变换)、DCT(离散余弦变换)等。 - 了解图像的色彩空间转换,比如RGB到YUV的转换,这在视频处理中非常重要。 6. 图像库的使用: - 除了直接使用API进行图像处理之外,还可以使用开源的图像处理库,如OpenCV。 - OpenCV是一个跨平台的计算机视觉和机器学习软件库,它提供了很多高级的图像处理功能。 【压缩包子文件的文件名称列表】: VC++ 文件名称列表显示为"VC++",这表明文件包中可能包含了Visual C++的项目、源代码文件、动态链接库(DLLs)、编译器设置、链接器设置等。如果要使用这些文件进行VC图像编程,需要确保Visual C++开发环境已经安装并且配置好,同时需要安装好所有依赖的库和工具。 要开始VC图像编程,开发者需要具备C++编程基础,熟悉Windows编程概念,并且对图形学有一定的了解。掌握VC图像编程技巧,对于进行桌面应用程序开发、图像处理软件开发以及游戏开发等都是至关重要的。
recommend-type

Pokemmo响应速度翻倍:多线程处理的高级技巧

# 摘要 多线程处理是提高软件并发性能和响应速度的关键技术,本文从基础概念与优势出发,深入探讨了多线程的实现机制,包括线程模型、调度算法、编程关键技术、线程安全性最佳实践、死锁预防与处理等方面。通
recommend-type

人名列表滚动抽奖

<think>嗯,用户想实现一个滚动抽奖功能,需要前端动画效果和随机选择逻辑。首先,我得考虑前端怎么实现滚动效果。可能用CSS动画或者JavaScript的requestAnimationFrame?比如,使用CSS的@keyframes来控制位移,或者用JS动态更新样式。然后,随机选择算法,可能需要确保公平性,比如用Fisher-Yates洗牌算法,或者用Math.random()来生成随机索引。然后,用户可能需要平滑的滚动动画,比如先快速滚动,然后逐渐减速,最后停在选中的人名上。这可能需要设置定时器,逐步改变位置,或者使用CSS过渡效果。另外,还要考虑性能,避免页面卡顿,可能需要使用硬件加
recommend-type

一站式JSF开发环境:即解压即用JAR包

标题:“jsf开发完整JAR包”所指的知识点: 1. JSF全称JavaServer Faces,是Java EE(现EE4J)规范之一,用于简化Java Web应用中基于组件的用户界面构建。JSF提供了一种模型-视图-控制器(MVC)架构的实现,使得开发者可以将业务逻辑与页面表示分离。 2. “开发完整包”意味着这个JAR包包含了JSF开发所需的所有类库和资源文件。通常来说,一个完整的JSF包会包含核心的JSF库,以及一些可选的扩展库,例如PrimeFaces、RichFaces等,这些扩展库提供了额外的用户界面组件。 3. 在一个项目中使用JSF,开发者无需单独添加每个必要的JAR文件到项目的构建路径中。因为打包成一个完整的JAR包后,所有这些依赖都被整合在一起,极大地方便了开发者的部署工作。 4. “解压之后就可以直接导入工程中使用”表明这个JAR包是一个可执行的归档文件,可能是一个EAR包或者一个可直接部署的Java应用包。解压后,开发者只需将其内容导入到他们的IDE(如Eclipse或IntelliJ IDEA)中,或者将其放置在Web应用服务器的正确目录下,就可以立即进行开发。 描述中所指的知识点: 1. “解压之后就可以直接导入工程中使用”说明这个JAR包是预先配置好的,它可能包含了所有必要的配置文件,例如web.xml、faces-config.xml等,这些文件是JSF项目运行所必需的。 2. 直接使用意味着减少了开发者配置环境和处理依赖的时间,有助于提高开发效率。 标签“jsf jar包”所指的知识点: 1. 标签指明了JAR包的内容是专门针对JSF框架的。因此,这个JAR包包含了JSF规范所定义的API以及可能包含的具体实现,比如Mojarra或MyFaces。 2. “jar包”是一种Java平台的归档文件格式,用于聚合多个文件到一个文件中。在JSF开发中,JAR文件经常被用来打包和分发库或应用程序。 文件名称列表“jsf”所指的知识点: 1. “jsf”文件名可能意味着这是JSF开发的核心库,它应该包含了所有核心的JavaServer Faces类文件以及资源文件。 2. 如果是使用特定版本的JSF,例如“jsf-2.2.jar”,则表明文件内包含了对应版本的JSF实现。这种情况下,开发者必须确认他们所使用的Web服务器或应用程序服务器支持该版本的JSF。 3. 文件名称也可能是“jsf-components.jar”、“jsf-impl.jar”等,表明这个JAR包是JSF的一个子模块或特定功能组件。例如,“jsf-components.jar”可能包含了一系列用于在JSF应用中使用的自定义组件。 4. 对于开发者而言,了解文件名称中所蕴含的信息非常重要,因为这将决定他们需要下载哪些JAR包来满足特定项目的需求。 综合以上信息,开发者在使用JSF进行Java Web应用开发时,会通过一个预先配置好的JAR包来快速地搭建和启动项目。这样做不仅简化了项目初始化的过程,也使得开发者能够更加聚焦于业务逻辑的实现和界面设计,而不必深究底层框架配置的细节。
recommend-type

Pokemmo内存优化揭秘:专家教你如何降低50%资源消耗

# 摘要 本文综述了Pokemmo游戏的内存优化方法,从内存管理基础出发,探讨内存使用效率的影响因素,并介绍了性能监控与分析工具。在内存优化实践技巧章节中,详细讨论了代码层面的优化、数据结构和算法选择对内存效率的影响,并通过案例分析展示了实际的优化过程。针对Pokemmo游戏特点,分析了内存消耗特性并提出了特定优化技术。最后,本文展望了未来内存管理技术的发展方向,以及游戏开发中面临的新挑战,为Pokemmo及类似游戏提供了优化建议。 # 关键字 内存优化;内存管理;性能监控;数据结构;算法效率;游戏开发 参考资源链接:[Pokemmo必备资源包:四种ROM与汉化补丁](https://we
recommend-type

直接访问子路由是吧

<think>我们正在使用Vue2,因此需要参考VueRouterv3的文档(因为Vue2对应VueRouterv3,Vue3对应VueRouterv4)。用户的问题是:如何配置路由以支持直接访问子路由?即,在Vue2中,我们希望直接通过URL访问嵌套的子路由(例如:/parent/child),而不仅仅是先访问父路由再导航到子路由。根据之前的回答和引用,我们已经知道:1.在父路由的配置中,使用`children`数组来定义子路由。2.子路由的`path`不能以斜杠开头(例如:'child'而不是'/child'),这样它就会基于父路由的路径进行拼接。3.在父组件的模板中放置`<router-
recommend-type

C++函数库查询辞典使用指南与功能介绍

标题中提到的“C++函数库查询辞典”指的是一个参考工具书或者是一个软件应用,专门用来查询C++编程语言中提供的标准库中的函数。C++是一种静态类型、编译式、通用编程语言,它支持多种编程范式,包括过程化、面向对象和泛型编程。C++标准库是一组包含函数、类、迭代器和模板的库,它为C++程序员提供标准算法和数据结构。 描述中提供的内容并没有给出实际的知识点,只是重复了标题的内容,并且有一串无关的字符“sdfsdfsdffffffffffffffffff”,因此这部分内容无法提供有价值的信息。 标签“C++ 函数库 查询辞典”强调了该工具的用途,即帮助开发者查询C++的标准库函数。它可能包含每个函数的详细说明、语法、使用方法、参数说明以及示例代码等,是学习和开发过程中不可或缺的参考资源。 文件名称“c++函数库查询辞典.exe”表明这是一个可执行程序。在Windows操作系统中,以“.exe”结尾的文件通常是可执行程序。这意味着用户可以通过双击或者命令行工具来运行这个程序,进而使用其中的查询功能查找C++标准库中各类函数的详细信息。 详细知识点如下: 1. C++标准库的组成: C++标准库由多个组件构成,包括输入输出流(iostream)、算法(algorithm)、容器(container)、迭代器(iterator)、字符串处理(string)、数值计算(numeric)、本地化(locale)等。 2. 输入输出流(iostream)库: 提供输入输出操作的基本功能。使用诸如iostream、fstream、sstream等头文件中的类和对象(如cin, cout, cerr等)来实现基本的输入输出操作。 3. 算法(algorithm)库: 包含对容器进行操作的大量模板函数,如排序(sort)、查找(find)、拷贝(copy)等。 4. 容器(container)库: 提供各种数据结构,如向量(vector)、列表(list)、队列(queue)、映射(map)等。 5. 迭代器(iterator): 迭代器提供了一种方法来访问容器中的元素,同时隐藏了容器的内部结构。 6. 字符串处理(string)库: C++标准库中的字符串类提供了丰富的功能用于处理字符串。 7. 数值计算(numeric)库: 提供数值计算所需的函数和类,比如对复数的支持和数值算法。 8. 本地化(locale)库: 提供本地化相关的功能,比如日期、时间的格式化显示以及字符的本地化比较。 9. 错误处理和异常: C++通过throw、try、catch关键字和标准异常类提供了一套异常处理机制。 10. 智能指针: C++11及其后续版本提供了智能指针(如unique_ptr、shared_ptr、weak_ptr)来自动管理动态分配的内存。 11. lambda表达式: 在C++11中引入,允许临时创建匿名函数对象。 12. C++11新特性: 包括范围for循环、移动语义、类内初始化器、auto类型推导等。 使用C++函数库查询辞典的用户可能需要对C++的基础知识有一定的掌握,例如变量、数据类型、控制结构、函数以及面向对象的概念等。了解C++标准库的结构和内容能够帮助程序员有效地利用库函数进行软件开发,提高编程效率并减少重复造轮子的工作。 总结来说,一个C++函数库查询辞典工具对于C++程序员来说是一个非常有用的资源,它能够提供快速查找标准库函数的能力,帮助程序员更高效地解决问题和进行学习。同时,随着C++标准的不断更新,例如C++11、C++14、C++17和C++20,函数库查询辞典也会不断地更新以包含新的特性,这对于紧跟技术发展的开发者来说尤为重要。
recommend-type

【bat脚本安全最佳实践】:保护你的系统与脚本安全的黄金法则

# 摘要 本文旨在全面阐述BAT脚本的基础知识、安全编写原则、审查与优化方法以及在企业环境中的安全应用。通过深入分析脚本安全基础、常见安全陷阱及脚本的权限管理,文章提出了安全编写的具体实践和预防措施。本文详细介绍了脚本安全审查流程、代码优化、错误处理和安全更新维护策略。在企业应用方面,探讨了企业安全政策制定、脚本审计和版本控制以及外部威胁的防范措施。通过案例分析,总结了脚本