换手率、胜率与盈亏比
直觉
除了风险调整收益,还有三个「过程指标」决定一个策略实不实用:
- 换手率:买卖有多频繁 → 决定交易成本;
- 胜率:赚钱的次数占比 → 心理舒适度;
- 盈亏比:平均每次赚的 ÷ 平均每次亏的 → 即使胜率低也能盈利。
定义
设持仓序列为 ,单期收益 :
「人话」解释:高胜率一定好吗?
不一定。一个「每次赚 1%、偶尔亏 20%」的策略胜率可能 90%,但一次大亏抹平所有利润。 反过来,趋势策略常常胜率只有 30~40%,但靠「亏小赚大」的高盈亏比照样盈利。 所以胜率和盈亏比要一起看:期望 = 胜率×平均盈利 − 败率×平均亏损,正期望才能长期赚钱。
可运行案例:双均线策略的过程指标
用 quant.vector_backtest 跑一个双均线策略,读出换手率,并从收益序列算胜率、盈亏比。
import quant
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('/data/spy_daily.csv', parse_dates=['date']).set_index('date')
close = df['adj_close']
# 双均线信号 → 持续仓位(ffill)
raw = (close.rolling(20).mean() > close.rolling(60).mean()).astype(float)
signal = raw.replace(0, np.nan).ffill().fillna(0)
res = quant.vector_backtest(close, signal, cost_bps=2.0, freq=252)
strat_ret = res['returns']
wins = strat_ret[strat_ret > 0]; losses = strat_ret[strat_ret < 0]
win_rate = len(wins) / len(strat_ret)
avg_win = wins.mean(); avg_loss = losses.mean()
pl_ratio = avg_win / abs(avg_loss) if avg_loss != 0 else float('nan')
expectancy = win_rate*avg_win + (1-win_rate)*avg_loss # 单期期望
print(f"总换手率 : {res['turnover']:.1f} (越大=交易越频繁, 成本越高)")
print(f"胜率 : {win_rate:.2%}")
print(f"平均盈利期 : {avg_win*100:.3f}%")
print(f"平均亏损期 : {avg_loss*100:.3f}%")
print(f"盈亏比 : {pl_ratio:.3f}")
print(f"单期期望 : {expectancy*100:.4f}% (正=长期可赚)")
print("\n夏普:", round(quant.sharpe(strat_ret, freq=252), 3),
" 最大回撤:", f"{quant.max_drawdown(res['equity']):.2%}")
动手改一改
把均线改成更敏感的 5/20——你会看到换手率飙升、交易成本吃掉收益,单期期望可能转负。这就是「过度交易」的代价。
小结
- 换手率 = 持仓变动绝对值之和,决定成本(引擎按换手扣
cost_bps); - 胜率 = 盈利期占比;盈亏比 = 平均盈利/平均亏损;
- 期望 = 胜率×盈利 − 败率×亏损,正期望才是长期盈利的根本。