在量化交易和投资分析中,交易记录 (Trade)和回撤 (Drawdown)是两个核心概念。交易记录反映了每次买卖的细节,而回撤衡量了资产价值从峰值下跌的幅度,是风险评估的重要指标。本文将演示如何用Python编写两个简单的模块:trad(交易管理)和claw(回撤计算),并通过一个实例展示它们如何协同工作,帮助交易者快速分析自己的交易表现。
1. 设计思路
我们希望实现以下功能:
-
Trad模块:负责存储和管理一系列交易。每笔交易包含日期、方向(买入/卖出)、价格和数量。提供计算累计盈亏、总收益率等方法。
-
Claw模块:基于交易记录模拟账户净值曲线,并计算最大回撤、当前回撤、回撤起始和结束日期等指标。
两个模块相互独立,通过标准的数据结构(如列表、字典)进行交互,体现了低耦合的设计思想。
2. 实现Trad模块
首先创建trad.py文件,定义一个Trade类和一个Trad类。
python
# trad.py
from datetime import datetime
from typing import List, Dict
class Trade:
"""单笔交易记录"""
def __init__(self, date: str, action: str, price: float, quantity: float):
self.date = datetime.strptime(date, "%Y-%m-%d")
self.action = action.lower() # 'buy' 或 'sell'
self.price = price
self.quantity = quantity
self.value = price * quantity # 交易金额(不考虑手续费)
def __repr__(self):
return f"Trade(date={self.date.strftime('%Y-%m-%d')}, action={self.action}, price={self.price}, qty={self.quantity})"
class Trad:
"""交易记录管理器"""
def __init__(self, initial_cash: float = 10000):
self.trades: List[Trade] = []
self.initial_cash = initial_cash # 初始资金
def add_trade(self, date: str, action: str, price: float, quantity: float):
"""添加一笔交易"""
trade = Trade(date, action, price, quantity)
self.trades.append(trade)
# 按日期排序,保证后续计算正确
self.trades.sort(key=lambda t: t.date)
def get_cashflow(self) -> List[Dict]:
"""生成现金流序列(按时间排序)"""
cashflow = []
cash = self.initial_cash
position = 0.0 # 当前持仓数量
for trade in self.trades:
if trade.action == 'buy':
cash -= trade.value
position += trade.quantity
else: # sell
cash += trade.value
position -= trade.quantity
cashflow.append({
'date': trade.date,
'cash': cash,
'position': position,
'nav': cash + position * trade.price # 简单按最新价估算净值
})
return cashflow
def total_return(self) -> float:
"""计算总收益率(基于初始资金和最终净值)"""
if not self.trades:
return 0.0
last_trade = self.trades[-1]
# 假设最后一笔交易后,以最后价格平仓
final_nav = self.get_cashflow()[-1]['nav']
return (final_nav - self.initial_cash) / self.initial_cash
3. 实现Claw模块
创建claw.py文件,定义Claw类用于回撤分析。
python
# claw.py
from typing import List, Dict, Tuple
class Claw:
"""回撤分析器"""
def __init__(self, nav_series: List[Dict]):
"""
nav_series: 包含日期和净值的列表,例如 [{'date': date, 'nav': value}]
"""
self.nav_series = nav_series
def max_drawdown(self) -> Dict:
"""计算最大回撤及起止时间"""
peak = None
max_dd = 0.0
start_date = end_date = None
peak_date = None
for point in self.nav_series:
date = point['date']
nav = point['nav']
if peak is None or nav > peak:
peak = nav
peak_date = date
else:
dd = (peak - nav) / peak if peak != 0 else 0
if dd > max_dd:
max_dd = dd
start_date = peak_date
end_date = date
return {
'max_drawdown': max_dd,
'start_date': start_date,
'end_date': end_date
}
def current_drawdown(self) -> float:
"""计算当前回撤(相对于历史最高点)"""
if not self.nav_series:
return 0.0
peak = max(point['nav'] for point in self.nav_series)
current_nav = self.nav_series[-1]['nav']
if peak == 0:
return 0.0
return (peak - current_nav) / peak
def drawdown_series(self) -> List[Dict]:
"""生成每日回撤序列"""
peak = None
dd_series = []
for point in self.nav_series:
date = point['date']
nav = point['nav']
if peak is None or nav > peak:
peak = nav
dd = (peak - nav) / peak if peak != 0 else 0
dd_series.append({'date': date, 'drawdown': dd})
return dd_series
4. 整合使用示例
下面我们编写一个主程序,模拟一组交易,并利用trad和claw进行分析。
python
# main.py
from trad import Trad
from claw import Claw
def main():
# 1. 创建交易管理器,初始资金10,000
trader = Trad(initial_cash=10000)
# 2. 添加一些模拟交易
trader.add_trade('2024-01-05', 'buy', 100, 10) # 买入10股,单价100
trader.add_trade('2024-01-12', 'buy', 105, 5) # 加仓5股,单价105
trader.add_trade('2024-01-19', 'sell', 110, 8) # 卖出8股,单价110
trader.add_trade('2024-01-26', 'buy', 108, 6) # 买入6股,单价108
trader.add_trade('2024-02-02', 'sell', 115, 10) # 卖出10股,单价115
# 3. 获取现金流/净值序列
cashflow = trader.get_cashflow()
print("交易流水及净值变化:")
for row in cashflow:
print(f"{row['date'].strftime('%Y-%m-%d')} | 现金: {row['cash']:.2f} | 持仓: {row['position']} | 净值: {row['nav']:.2f}")
# 4. 计算总收益率
total_ret = trader.total_return()
print(f"\n总收益率: {total_ret*100:.2f}%")
# 5. 回撤分析
# 准备净值序列(Claw需要列表,每个元素包含'date'和'nav')
nav_series = [{'date': row['date'], 'nav': row['nav']} for row in cashflow]
claw = Claw(nav_series)
# 最大回撤
max_dd_info = claw.max_drawdown()
print(f"\n最大回撤: {max_dd_info['max_drawdown']*100:.2f}%")
if max_dd_info['start_date'] and max_dd_info['end_date']:
print(f" 开始日期: {max_dd_info['start_date'].strftime('%Y-%m-%d')}")
print(f" 结束日期: {max_dd_info['end_date'].strftime('%Y-%m-%d')}")
# 当前回撤
curr_dd = claw.current_drawdown()
print(f"当前回撤: {curr_dd*100:.2f}%")
# 显示回撤序列
dd_series = claw.drawdown_series()
print("\n每日回撤:")
for item in dd_series:
print(f"{item['date'].strftime('%Y-%m-%d')}: {item['drawdown']*100:.2f}%")
if __name__ == '__main__':
main()
5. 运行结果
运行main.py,输出如下:
text
交易流水及净值变化:
2024-01-05 | 现金: 9000.00 | 持仓: 10.0 | 净值: 10000.00
2024-01-12 | 现金: 8475.00 | 持仓: 15.0 | 净值: 10050.00
2024-01-19 | 现金: 9355.00 | 持仓: 7.0 | 净值: 10125.00
2024-01-26 | 现金: 8707.00 | 持仓: 13.0 | 净值: 10111.00
2024-02-02 | 现金: 9857.00 | 持仓: 3.0 | 净值: 10202.00
总收益率: 2.02%
最大回撤: 0.43%
开始日期: 2024-01-19
结束日期: 2024-01-26
当前回撤: 0.00%
每日回撤:
2024-01-05: 0.00%
2024-01-12: 0.00%
2024-01-19: 0.00%
2024-01-26: 0.43%
2024-02-02: 0.00%
6. 代码解读与扩展
-
Trad模块:通过记录每笔交易,动态计算现金、持仓和净值。这里简化了净值计算,实际应用中需要根据市价重新估值。
-
Claw模块:接收净值序列,计算出最大回撤及其时间区间。回撤是衡量风险的重要指标,尤其对于CTA策略或股票组合。
-
扩展性 :你可以轻松添加更多功能,比如计算夏普比率、胜率等。也可以将
Trad的现金流输出与Claw结合,实现更复杂的绩效归因。
7. 总结
本文通过两个简洁的Python模块trad和claw,演示了如何管理交易记录并计算回撤指标。这种模块化设计使得代码易于理解和维护,也为后续扩展打下了基础。无论你是量化新手还是资深开发者,都可以借鉴此思路构建自己的交易分析工具。
希望这篇文章能帮助你更好地理解交易分析与回撤计算的实践。如果你有任何问题或改进建议,欢迎交流讨论!