为什么要做这件事
一直有个模糊的感觉:临时起意的交易,胜率明显低于按计划执行的交易。但"感觉"这东西在交易里最不值钱,于是我把 214 笔成交记录导出来,用 Python 跑了一遍。
结论比想象中更极端:
| 分组 | 笔数 | 平均持仓(交易日) | 胜率 | 平均每笔 |
|---|---|---|---|---|
| 计划内卖出 | 96 | 6.2 | 58% | +2.1% |
| 临时起意 | 47 | 1.4 | 21% | -3.4% |
胜率差37 个百分点,单笔盈亏差5.5 个百分点。
数据准备
导出成交记录,最少需要这些字段:
importpandasaspd cols=['code','buy_date','sell_date','buy_price','sell_price','shares','planned']# planned: 卖出是否符合事前计划df=pd.read_csv('trades.csv',parse_dates=['buy_date','sell_date'])```## 核心指标计算```python df['ret']=(df.sell_price-df.buy_price)/df.buy_price df['hold']=(df.sell_date-df.buy_date).dt.days df['win']=df.ret>0defsummary(g):returnpd.Series({'笔数':len(g),'平均持仓':round(g.hold.mean(),1),'胜率':f'{g.win.mean()*100:.0f}%','平均每笔':f'{g.ret.mean()*100:+.1f}%','盈亏比':round(g.loc[g.win,'ret'].mean()/abs(g.loc[~g.win,'ret'].mean()),2)})print(df.groupby('planned').apply(summary,include_groups=False))include_groups=False是 pandas 2.2+ 的要求,不加会告警。
一个反直觉的发现
我把"临时起意"的交易再按持仓时长切一刀:
imp=df[~df.planned]imp.groupby(pd.cut(imp.hold,[0,1,3,7,100]))['win'].agg(['mean','count'])持仓不足 1 天的那部分,胜率只有14%,而其中"当天买入当天卖出"的,接近一半是被分时图吓出来的。
换句话说:不是你的判断变差了,是决策场景变差了。
把它变成可执行的东西
复盘完我改了三处流程,都是工程问题,不是心态问题:
- 决策前置:买入前必须写清触发条件、止损位、目标位、最大仓位。写不出来的不买——这是最有效的一条,砍掉了 60% 的冲动单。
- 执行自动化:止损和目标位全挂条件单/预警,把"盘中决定"这个环节整个删掉。
- 复盘结构化:盘后 20 分钟,只回答一个问题——"今天的动作符合规则吗?“不回答"为什么没赚到”。后者会诱导你去找借口,前者才会改进流程。
# 每天复盘只输出这一行,就够了print(f"规则内交易占比:{df.planned.mean()*100:.0f}% "f"规则内胜率:{df[df.planned].win.mean()*100:.0f}% "f"违规胜率:{df[~df.planned].win.mean()*100:.0f}%")```## 一点想法这套分析的真正价值不在于算出58%和21%,而在于把"我最近状态不好"这种无法证伪的说法,换成了一个可以每周跟踪的数字:**规则内交易占比**。 从68%提升到85%,我用了大概六周。期间学到的技术分析一点没变,收益结构变了。---数据为个人交易记录,代码仅作方法论演示,不构成任何投资建议。