【量化交易笔记】12.海龟交易策略

编程入门 行业动态 更新时间:2024-10-23 20:17:39

【量化交易笔记】12.<a href=https://www.elefans.com/category/jswz/34/1764264.html style=海龟交易策略"/>

【量化交易笔记】12.海龟交易策略

引言

海龟交易法则是一种著名的趋势跟踪交易策略,适用于中长线投资者。

海龟交易策略(Turtle Trading)起源于美国,由著名的交易员理查德·丹尼斯(Richard Dennis)创立。这种交易策略属于趋势跟踪策略,适用于中长线投资者。其核心思想是捕捉市场的主要趋势,并在趋势开始时买入,趋势结束时卖出。海龟交易法则以严格的纪律和长期的跟踪为特点,旨在实现稳定的长期盈利。

原理:

海龟交易策略一套完整的交易系统,包括市场,入市,头寸规模、止损/止盈,出场,买卖策略等。

  1. 市场:海龟交易者关注全球市场,主要观察股票、债券、商品、货币等市场的趋势。
  2. 入市:海龟交易者使用一定的技术指标来判断市场趋势,并在市场价格突破一定阻力位时买入。例如,他们可能会使用移动平均线或趋势线来确定趋势。
    头寸规模:海龟交易者会根据他们的风险承受能力和市场状况来决定头寸规模。他们通常会使用一定比例的账户资金来投资,以控制风险。
  3. 止损/止盈:海龟交易者会设定止损点和止盈点,以限制损失并锁定盈利。止损点通常设置在离当前价格一定距离的位置,以减少损失。止盈点则根据市场状况和投资者的目标来设定。
  4. 出场:海龟交易者在市场价格达到止盈点或止损点时平仓。他们也会在市场趋势逆转时出场,以避免损失。
  5. 买卖策略:海龟交易者既可以做多,也可以做空。他们通常会观察市场趋势,并在趋势开始时买入,趋势结束时卖出。他们也会在市场波动较大时进行反趋势交易,以获取短线利润。

总的来说,海龟交易法则是一套以风险控制为核心的交易系统,旨在捕捉市场趋势并最大化盈利。

趋势追踪——唐奇安通道

海龟交易法则利用唐奇安通道的突破点作为买卖信号指导交易,简单而言唐奇安通道是由一条上轨线、中线和下线组成,上轨线由N1日内最高价构成,下轨线由N2日内最低价计算,当价格冲破上轨是可能的买入信号,反之,冲破下轨时是可能的卖出信号。

海龟交易系统本质上是一个趋势跟随的系统,但是最值得学习的是资金管理尤其是分批建仓及动态止损的部分。书中提到了N值仓位管理法,其中N值与技术指标平均真实波幅 ATR计算类似。ATR是真实波幅TR的20日平均值,而TR是当前交易日最高价和最低价之差 、前一交易日收盘价与当前交易日最高价之差、前一交易日收盘价与当前交易日最低价之差三者中的最大值,用公式表示为:

TR=Max(High−Low,abs(High−PreClose),abs(PreClose−Low)),技术指标库TA-Lib提供了直接计算ATR的函数。

下面使用简化版的海龟交易法则进行历史回测,即不考虑仓位管理和动态止损/止盈条件,以唐奇安通道突破作为买入卖出信号。

交易规则为:
(1)当今天的收盘价,大于过去20个交易日中的最高价时,以收盘价买入;
(2)买入后,当收盘价小于过去10个交易日中的最低价时,以收盘价卖出。

数据采集模块

import pandas as pd 
import numpy as np
import talib as ta
from datetime import datetime,timedelta
import matplotlib.pyplot as plt
%matplotlib inline 
#正常显示画图时出现的中文和负号
import warnings
warnings.filterwarnings("ignore")
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus']=False
import baostock as bs#### 登陆系统 ####
def get_k_data(code,start,end):lg = bs.login()rs = bs.query_history_k_data_plus(code,"date,code,open,high,low,close,preclose,volume,amount,adjustflag,turn,tradestatus,pctChg,peTTM,pbMRQ,psTTM,pcfNcfTTM,isST",start_date=start, end_date=end,frequency="d", adjustflag="3")data=rs.get_data()data['date'] = pd.to_datetime(data['date']) bs.logout()   return data.set_index('date')

为了与前面的文章统一,仍选sh.600000,时间区间为从2023-1-1 到 2023-10-19

hs=get_k_data('sh.600000','2023-1-1','2023-10-19')[['close','open','high','low','volume']]
#最近N1个交易日最高价
hs['up']=ta.MAX(hs.high,timeperiod=20).shift(1)
#最近N2个交易日最低价
hs['down']=ta.MIN(hs.low,timeperiod=10).shift(1)
#每日真实波动幅度
hs['ATR']=ta.ATR(hs.high,hs.low,hs.close,timeperiod=20)
hs.tail()
datecloseopenhighlowvolumeupdownATR
2023-10-137.10007.11007.15007.0800196504107.27.00.096226
2023-10-167.07007.12007.13007.0400249077337.27.00.095914
2023-10-177.09007.09007.10007.0500190291437.27.00.093619
2023-10-187.05007.07007.11007.0500214857217.27.00.091938
2023-10-196.84007.04007.05006.8300616797717.27.00.098341

设置买卖策略及相关信号

def my_strategy(data):x1=data.close>data.upx2=data.close.shift(1)<data.up.shift(1)x=x1&x2y1=data.close<data.downy2=data.close.shift(1)>data.down.shift(1)y=y1&y2data.loc[x,'signal']='buy'data.loc[y,'signal']='sell'buy_date=(data[data.signal=='buy'].index).strftime('%Y%m%d')sell_date=(data[data.signal=='sell'].index).strftime('%Y%m%d')buy_close=data[data.signal=='buy'].close.round(2).tolist()sell_close=data[data.signal=='sell'].close.round(2).tolist()return (buy_date,buy_close,sell_date,sell_close)

以下代码实现了回测,并加上了alpha 、 beta、年化收益、夏普比率等

相关公式

年化收益率

年化收益率=[(投资内收益 / 本金)/ 投资天数] * 365×100%
而实际上采用以下公式计算,考虑到一年的交易日 约为250日
p r = ( p e n d p s t a r ) 250 / n − 1 p_r=(\frac{p_{end}}{p_{star}})^{250/n}-1 pr​=(pstar​pend​​)250/n−1

这里的alpha和beta 是指量化投资理论的 α \alpha α 和 β \beta β 。

贝塔(Beta)

表示投资的系统性风险,反映了策略对大盘变化的敏感性。
例如,一个策略的Beta为1.3,则大盘涨1%的时候,策略可能涨1.3%,反之亦然;

如果一个策略的Beta为-1.3,说明大盘涨1%的时候,策略可能跌1.3%,反之亦然。
β = C o v ( p n , B n ) σ B 2 \beta=\frac{Cov(p_n,B_n)}{\sigma^2_B} β=σB2​Cov(pn​,Bn​)​
p n p_n pn​:策略每日收益率
B n B_n Bn​:基准每日收益率
σ B 2 \sigma^2_B σB2​:基准每日收益方差
C o v ( p n , B n ) Cov(p_n,B_n) Cov(pn​,Bn​):策略和基准每日收益率的协方差

阿尔法(Alpha)

非系统性风险,Alpha是投资者获得与市场波动无关的回报,一般用来度量投资者的投资技艺。例如,投资者获得了12%的回报,其基准获得了10%的回报,那么Alpha或者价值增值的部分就是2%。

α = p r − r f − β ( B r − r f ) \alpha=p_r-r_f-\beta(B_r-r_f) α=pr​−rf​−β(Br​−rf​)
p r p_r pr​:策略的年化收益率
r f r_f rf​:无风险收益率
B r B_r Br​:基准年化收益率

收益波动率(Volatility)

用来测量资产的风险性,波动越大代表策略风险越高。
σ p = 250 n − 1 ∑ t = 1 n ( p t − p t ‾ ) 2 \sigma_p=\sqrt{\frac{250}{n-1} \sum^n_{t=1}(p_t- \overline{p_t})^2} σp​=n−1250​∑t=1n​(pt​−pt​​)2

夏普比率(Sharpe Ratio)

表示每承受一单位总风险,会产生多少的超额报酬,可以同时对策略的收益与风险进行综合考虑。
夏普比率为(算法交易收益-基准收益)/算法交易收益的标准差
S h a r p R a t i o = p r − r f σ p SharpRatio=\frac{p_r-r_f}{\sigma_p} SharpRatio=σp​pr​−rf​​
p r p_r pr​:策略的年化收益率
r f r_f rf​:无风险收益率
σ p \sigma_p σp​策略收益率波动率

信息比率(Information Ratio)

衡量单位超额风险带来的超额收益。

信息比率越大,说明该策略单位跟踪误差所获得的超额收益越高,因此,信息比率较大的策略的表现要优于信息比率较小的策略。合理的投资目标应该是在承担适度风险下,尽可能追求高信息比率。
I n f o r m a t i o n R a t i o = p r − B r σ t InformationRatio=\frac{p_r-B_r}{\sigma_t} InformationRatio=σt​pr​−Br​​

最大回撤(Max Drawdown)

描述策略可能出现的最糟糕的情况。

M a x D r a w D o w n t = max ⁡ ( 1 − P j P i ) MaxDrawDown_t=\max(1-\frac{P_j}{P_i}) MaxDrawDownt​=max(1−Pi​Pj​​)


def strategy(stock,start,end,N1=20,N2=10):df=get_k_data(stock,start,end)[['close','open','high','low','volume']]df=df.astype("float")df['ret']=df.close/df.close.shift(1)-1#最近N1个交易日最高价df['H_N1']=ta.MAX(df.high,timeperiod=N1)#最近N2个交易日最低价df['L_N2']=ta.MIN(df.low,timeperiod=N2)#当日收盘价>昨天最近N1个交易日最高点时发出信号设置为1buy_index=df[df.close>df['H_N1'].shift(1)].indexdf.loc[buy_index,'收盘信号']=1#将当日收盘价<昨天最近N2个交易日的最低点时收盘信号设置为0sell_index=df[df.close<df['L_N2'].shift(1)].indexdf.loc[sell_index,'收盘信号']=0df['当天仓位']=df['收盘信号'].shift(1)df['当天仓位'].fillna(method='ffill',inplace=True)d=df[df['当天仓位']==1].index[0]-timedelta(days=1)df1=df.loc[d:].copy()df1['ret'][0]=0df1['当天仓位'][0]=0#当仓位为1时,买入持仓,当仓位为0时,空仓,计算资金净值df1['策略净值']=(df1.ret.values*df1['当天仓位'].values+1.0).cumprod()df1['指数净值']=(df1.ret.values+1.0).cumprod()df1['策略收益率']=df1['策略净值']/df1['策略净值'].shift(1)-1df1['指数收益率']=df1.rettotal_ret=df1[['策略净值','指数净值']].iloc[-1]-1annual_ret=pow(1+total_ret,250/len(df1))-1dd=(df1[['策略净值','指数净值']].cummax()-df1[['策略净值','指数净值']])/df1[['策略净值','指数净值']].cummax()d=dd.max()beta=df1[['策略收益率','指数收益率']].cov().iat[0,1]/df1['指数收益率'].var()alpha=(annual_ret['策略净值']-annual_ret['指数净值']*beta)exReturn=df1['策略收益率']-0.03/250sharper_atio=np.sqrt(len(exReturn))*exReturn.mean()/exReturn.std()TA1=round(total_ret['策略净值']*100,2)TA2=round(total_ret['指数净值']*100,2)AR1=round(annual_ret['策略净值']*100,2)AR2=round(annual_ret['指数净值']*100,2)MD1=round(d['策略净值']*100,2)MD2=round(d['指数净值']*100,2)S=round(sharper_atio,2)df1[['策略净值','指数净值']].plot(figsize=(15,7))plt.title(stock+'海龟交易策略简单回测',size=15)bbox = dict(boxstyle="round", fc="w", ec="0.5", alpha=0.9)plt.text(df1.index[int(len(df1)/5)], df1['指数净值'].max()/1.08, f'累计收益率:\策略{TA1}%,指数{TA2}%;\n年化收益率:策略{AR1}%,指数{AR2}%;\n最大回撤: 策略{MD1}%,指数{MD2}%;\n\策略alpha: {round(alpha,2)},策略beta:{round(beta,2)}; \n夏普比率: {S}',size=13,bbox=bbox) plt.xlabel('')ax=plt.gca()ax.spines['right'].set_color('none')ax.spines['top'].set_color('none')plt.show()# return df1.loc[:,['close','ret','H_N1','L_N2','当天仓位','策略净值','指数净值']]

直接调用

strategy("sh.600000","2023-01-01","2023-10-19")

其他其他策略的收益情况

strategy('sz.300576','2023-01-01','2023-10-19')

结论

经过上述步骤,我们就实现了一个简单的海龟交易策略。交易次数并不多,另外可通过对上述代码做进一步的扩展,使其更加完善和复杂。

原始的海龟交易采用唐奇安通道来追踪趋势,在趋势比较明显的行情表现不错,但是在震荡的行情中效果不佳,当然这是所有趋势型策略的通病。下面着重使用Python对唐奇安通道进行可视化,并利用简化版的海龟交易法则进行简单的历史回测。

更多推荐

【量化交易笔记】12.海龟交易策略

本文发布于:2023-12-03 20:40:14,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1657414.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:海龟   策略   笔记

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!