交易史上最著名的实验
使用海龟交易法则之前,需要先了解注明的海龟实验。1983年年中,著名的商品投机家理查德.丹尼斯与他的老友比尔.埃克哈特进行了一场辩论,这场辩论是关于伟大的交易员是天生造就还是后天培养的。理查德相信,他可以教会人们成为伟大的交易员。比尔则认为遗传和天性才是决定因素。
为了解决这一问题,理查德建议招募并培训一些交易员,给他们提供真实的帐户进行交易,看看两个人中谁是正确的。理查德或许是当时世界上最著名的交易员,所以,有1000多位申请人前来投奔他。他会见了其中的80位,并在这群人精选出10个人。后来这个名单变成13个人,所增加的3个人理查德以前就认识。
理查德在开始这项计划之前,刚从亚洲回来。他在新加坡的海龟农场曾说过:“我们要培养交易者,就像新加坡人养海龟一样。”于是,这13名学员日后便被称作‘海龟’。最终,这项计划成为交易史上最著名的实验,在随后的四年中,海龟们取得了年均复利80%的收益。
理查德也证明了交易可以被传授。他用一套简单的法则,就可以使仅有很少或根本没有交易经验的人成为优秀的交易员。这套法则便是著名的海龟交易法则。
海龟交易法则的原理
海龟交易法则有四大模块,分别是入市、资金管理、止损及退出。这四大模块分别解决了在哪个市场买卖、买卖什么、如何设定头寸规模、什么时候买卖、什么时候止损、什么时候退出市场等问题,是一套完整的交易体系。
入市部分
我们需要构建唐奇安通道来生成交易的指令。唐奇安通道的使用方式类似于布林线,但构建时并不使用标准差,而是捕捉趋势信号。上线为过去20天的最高价,下线为过去10天的最低价,中线是上线加下线除以2。当股价上破时买入,当股价下坡时卖出。
资金管理部分
需要计算N值。N值与平均真实波幅ATR相似,我们通过N值来确定仓位的大小。原则是波动大的市场买少一点,波动小的市场买多一点,最终使得在不同市场中承受的风险相似。
N值的含义是,过去20天股价最大波动范围的平均幅度。TrueRange=Max(High−Low,abs(High−PreClose),abs(PreClose−Low))
N=(PreN∗19+TrueRange20) / 20
Unit = 1/N
计算Unit公式的背后含义是,UnitN=Capital1%。在股票市场中计算的Unit就是多少股。当股价在上一次买入的基础上上涨了0.5N,则加仓一个Unit。
止损部分
当股价比最后一次买入的价格下跌2N,则立即清仓止损。
用Python实现
下面我们以中国平安的个股为例,根据海龟交易法则进行操作:
import numpy as np
import pandas as pd
from CAL.PyCAL import *
start = '2013-01-01' # 回测起始时间
end = '2019-01-01' # 回测结束时间
benchmark = '601318.XSHG'
universe = ['601318.XSHG']
capital_base = 100000 # 起始资金
freq = 'd'
refresh_rate = 1
accounts = {
'fantasy_account': AccountConfig(account_type='security', capital_base=100000)
}
def initialize(context): #初始化环境
context.last_buy_prcie = 0 #上一次买入价
context.hold_flag = False # 是否持有头寸标志
context.limit_unit = 10 # 限制最多买入的单元数
context.unit = 0
context.add_time = 0 # 买入次数
def CalcATR(data):
TR_List = []
for i in range(1,21):
TR = max(data['highPrice'].iloc[i]-data['lowPrice'].iloc[i],abs(data['highPrice'].iloc[i]-data['closePrice'].iloc[i-1]),abs(data['closePrice'].iloc[i-1]-data['lowPrice'].iloc[i]))
TR_List.append(TR)
ATR = np.array(TR_List).mean()
return ATR
def CalcUnit(perValue,ATR):
return round((perValue/ATR)/100)*100
def SellComplete(hold_flag,security_position):
if len(security_position)>0 and hold_flag==False:
return True
else:
return False
def IN_OR_OUT(data,price,T):
up = max(data['highPrice'].iloc[-T:-1])
down = min(data['lowPrice'].iloc[-int(T/2):-1]) # 这里是10日唐奇安下沿
if price>up:
return 1
elif price<down:
return -1
else:
return 0
def Add_OR_Stop(price,lastprice,ATR):
if price >= lastprice + 0.5*ATR:
return 1
elif price <= lastprice - 2*ATR:
return -1
else:
return 0
def handle_data(context):
T = 20
stock_account = context.get_account('fantasy_account')
data = context.history(['601318.XSHG'], attribute=['openPrice', 'highPrice', 'lowPrice', 'closePrice'], time_range=T+1, freq='1d', style='sat', rtype='frame')
stk = universe[0]
data = data[stk]
data = pd.DataFrame(data)
prices = context.current_price(stk) #获得最近价格
today = Date.fromDateTime(context.current_date)
today = today.toISO() #转换为标准日期格式
#剔除停牌的股票
if np.isnan(prices) or prices == 0: # 停牌或是还没有上市等原因不能交易
return
# 计算ATR和unit
ATR = CalcATR(data)
value = stock_account.portfolio_value * 0.01
context.unit = CalcUnit(value,ATR)
#判断是否处于空仓的状态
if SellComplete(context.hold_flag,stock_account.get_positions()):
for stk in stock_account.get_positions():
stock_account.order_to(stk,0)
#判断买卖时机
out = IN_OR_OUT(data,prices,T)
if out ==1 and context.hold_flag==False:
stock_account.order_to(stk,context.unit)
context.add_time = 1 #入场之后持仓就+1
context.hold_flag = True
context.last_buy_prcie = prices
elif out==-1 and context.hold_flag ==True: #离场
stock_account.order_to(stk,0)
initialize(context) # 重新初始化参数
#判断加仓或止损
if context.hold_flag==True and len(stock_account.get_positions())>0:
temp = Add_OR_Stop(prices,context.last_buy_prcie,ATR)
if temp ==1 and context.add_time<=context.limit_unit: # 加仓
order_num = min(context.unit,int((stock_account.cash/prices)/100)*100)
stock_account.order(stk,order_num)
context.last_buy_prcie = prices
context.add_time += 1
elif temp== -1: # 止损
stock_account.order_to(stk,0)
initialize(context)
return
写完代码后运行,结果如下:
image.png综上所述,海龟交易法则的应用效果还不错。
刺猬偷腥
2019年1月26日
网友评论