第一步:分组
将df按照持仓时间和空仓时间进行分组,分组完成之后就可以在
# ===将每笔交易的start_time设置为发出信号的candle_begin_time,用于分组
open_mask = (df['signal'].abs() == 1)
df.loc[open_mask, 'start_time'] = df.loc[open_mask, 'candle_begin_time']
close_mask = (df['signal'] == 0)
df.loc[close_mask, 'start_time'] = pd.Timestamp(0)
df['start_time'].ffill(inplace=True)
第二步:在每个group中计算极大值
在group中的每一行求本轮开仓到该时间的极大值。
# 计算每笔交易的最大回撤
df['signal_'] = df['signal'].ffill()
df['dir_close'] = df['signal_'] * df['close']
df['cum_extreme'] = df[df['start_time'] > pd.Timestamp(0)].groupby('start_time')['dir_close'].cummax()
df['cum_extreme'] *= df['signal_']
第三步:在每一行计算最大回撤
df['max_loss_pct'] = (1 - df['close'] / df['cum_extreme']) * df['signal_']