1. 程式人生 > >【策略研究】海龜交易法則(附原始碼)

【策略研究】海龜交易法則(附原始碼)

海龜交易法則簡介

什麼是海龜交易法則?

​ 1983年年中,著名的商品投機家理查德.丹尼斯與他的老友比爾.埃克哈特進行了一場辯論,這場辯論是關於偉大的交易員是天生造就還是後天培養的。理查德相信,他可以教會人們成為偉大的交易員。比爾則認為遺傳和天性才是決定因素。

​ 為了解決這一問題,理查德建議招募並培訓一些交易員,給他們提供真實的帳戶進行交易,看看兩個人中誰是正確的。

​ 他們在《巴倫氏》、《華爾街期刊》和《紐約時報》上刊登了大幅廣告,招聘交易學員。廣告中稱,在一個短暫的培訓會後,新手將被提供一個帳戶進行交易。

​ 理查德從報名的人中精選出13個人,1983年12月底,學員被邀請到芝加哥進行兩週的培訓,到1984年1月初,開始用小帳戶進行交易。到了2月初,在學員證明了自己的能力之後,丹尼斯給其中的大多數人提供了50萬至200萬美元的資金帳戶。

​ “學員們被稱為‘海龜’(丹尼斯先生說這項計劃開始時他剛剛從亞洲回來,他解釋了自己向別人說過的話,‘我們正在成長為交易員,就象在新加坡他們正在成長為海龜一樣’)。”----斯坦利.W.安格瑞斯特,《華爾街期刊》,1989年9月5日

​ 海龜成為交易史上最著名的實驗,因為在隨後的四年中這些海龜交易員取得了年均複利80%的收益。

​ 是的,裡克證明了交易可以被傳授。他證明了用一套簡單的法則,他可以使僅有很少或根本沒有交易經驗的人成為優秀的交易員。而這個交易法則被後世稱為“海龜交易法則”。

海龜交易法則具體內容

海龜交易法則:海龜交易法則屬於趨勢交易,首先建立唐奇安通道(下文會具體解釋),即確定上突破線和下突破線,如果價格突破上線,則做多,如果價格突破下線就平倉或做空。

唐奇安通道與開倉

唐奇安通道,作為一個通道必定有上線和下線,上線就是前N1日內的最高價,下線就是前N2日內的最低價,一般來說N1=20,N2=10;然後,價格上穿就買,下穿就賣,就是這麼簡單。

但是僅僅只用唐奇安通道進行買賣,其實效果跟MACD線等其他趨勢策略的效果差不多,並沒有更優

ATR與倉位管理

海龜交易法則最核心的部分,在於倉位的控制,這種止損會讓你基準的虧損不超過總資金的n%,所以這部分的思想是需要我們學習的。

當日的真實波幅TR(true range)

計算當日真實波幅公式

​ TR_1=Max(H_1−L_1,H_1−C_0,C_0−L_1)

其中,下表1代表當日,下表0代表昨日,C_0是昨日開盤價close,H是最高價high,L是最低價low。

平均波幅ATR(Average true range)

一般取前20日的平均TR。

​ ATR{20}=mean(TR_1,TR_2…TR{19},TR_{20})

其中,公式mean(X_1,X_2)代表求X_1和X_2的平均數。

這時候我們已經求出ATR,這個數字可以當做衡量今天的價格波幅的基準,為1單位,比如現在價格是100元,基準波幅ATR=4元,代表今天基準波幅在98-102元,如果是2倍ATR,波幅就在96-104元。

倉位管理

在僅討論多頭的情況下:

1、如果標的價格跌破"持倉均價-0.5(1、1.5、2)倍的ATR",則平倉至原始倉位的75%(50%,25%,0%)。

2、如果標的價格跌破唐奇安通道下軌,則全平倉。

海龜交易法則策略實現(基於掘金量化平臺

策略思想

  • 當價格上穿唐奇安通道且短MA在長MA上方時開多倉;當價格下穿唐奇安通道且短MA在長MA下方時開空倉(8手)

  • 若有多倉則在價格跌破唐奇安平倉通道下軌的時候全平倉位,否則根據跌破持倉均價 - x(x=0.5,1,1.5,2)倍ATR把倉位平至6/4/2/0手

  • 若有空倉則在價格漲破唐奇安平倉通道上軌的時候全平倉位,否則根據漲破持倉均價 + x(x=0.5,1,1.5,2)倍ATR把倉位平至6/4/2/0手

策略主要步驟實現

訂閱資料

subscribe(symbols=symbols, frequency='1d', count=31, wait_group=True)(symbols=symbols, frequency='1d', count=31, wait_group=True)

​ 訂閱資料需要在定義init函式裡面設定,並呼叫subscribe函式,這裡注意,我們需要通過計算前三十根bars來作為開平倉的標準,並在當前bar上做出開平倉操作,所以需要獲取31根bar:

  • symbols 需要設定訂閱的標的程式碼。

  • frequency需設定訂閱資料的週期級別,這裡設定1d 表示以一天為週期。

  • count需要設定獲取的bar的數量

資料獲取

data = context.data(symbol=symbol, frequency='1d', count=31, fields='close') = context.data(symbol=symbol, frequency='1d', count=31, fields='close')

​ 訂閱資料之後,需要獲取已經訂閱的資料來進行操作,這時需呼叫context.data函式:

  • symbols 需要設定訂閱的標的程式碼。

  • frequency需設定訂閱資料的週期級別,這裡設定1d表示以一天為週期。

  • count需要設定獲取的bar的數量

  • fields需要設定返回值的種類

獲取持倉資訊

position_long = context.account().position(symbol=symbol, side=PositionSide_Long)
​
position_short = context.account().position(symbol=symbol, side=PositionSide_Short) = context.account().position(symbol=symbol, side=PositionSide_Long)
​
position_short = context.account().position(symbol=symbol, side=PositionSide_Short)

​ 在判斷平倉條件時,需要獲取持倉資訊(包含持倉均價),這就需要呼叫context.account().position函式:

  • symbols 需要設定訂閱的標的程式碼。

  • side需要設定持倉方向,有PositionSide_LongPositionSide_Short兩個選擇。

策略回測分析

回測報告

分析

​ 我們選取了2017年6月至2017年12月作為回測週期,“RB1801”與“FG801”作為標的合約,均線長短週期分別為5d,20d,唐奇安通道上下軌計算週期分別為20d,10d,ATR計算週期為20d,可以看出:

  • 勝率(具有盈利的平倉次數與總平倉次數之比)達到了34.48%,因為海龜交易法則為趨勢跟蹤策略,所以勝率不會太高。

  • 卡瑪比率(年化收益率與歷史最大回撤之比)是使用最大回撤率來衡量風險。採用最大回撤率來衡量風險,關注的是最極端的情況。卡瑪比率越高表示策略承受每單位最大損失獲得的報酬越高。在這裡卡瑪比率超過了9。

  • 夏普比率(年化收益率減無風險收益率的差收益波動率之比)超過2.5,也即承受1單位的風險,會有超過2.5個單位的收益回報。

  • 策略收益曲線整體相對穩定,適合穩定型投資者,最大回撤極小,另外,策略在趨勢行情行情中表現更加。

  1. # coding=utf-8
  2. from __future__ import print_function, absolute_import, unicode_literals
  3. import numpy as np
  4. import pandas as pd
  5. try:
  6. import talib
  7. except:
  8. print('請安裝TA-Lib庫')
  9. from gm.api import*
  10. '''
  11. 本策略通過計算CZCE.FG801和SHFE.rb1801的ATR.唐奇安通道和MA線,並:
  12. 上穿唐奇安通道且短MA在長MA上方則開多倉,下穿唐奇安通道且短MA在長MA下方則開空倉
  13. 若有 多/空 倉位則分別:
  14. 價格 跌/漲 破唐奇安平倉通道 上/下 軌則全平倉位,否則
  15. 根據 跌/漲 破持倉均價 -/+ x(x=0.5,1,1.5,2)倍ATR把倉位
  16. 回測資料為:CZCE.FG801和SHFE.rb1801的1min資料
  17. 回測時間為:2017-09-15 09:15:00到2017-10-01 15:00:00
  18. '''
  19. def init(context):
  20. # context.parameter分別為唐奇安開倉通道.唐奇安平倉通道.短ma.長ma.ATR的引數
  21. context.parameter =[55,20,10,60,20]
  22. context.tar = context.parameter[4]
  23. # context.goods交易的品種
  24. context.goods =['CZCE.FG801','SHFE.rb1801']
  25. # context.ratio交易最大資金比率
  26. context.ratio =0.8
  27. # 訂閱context.goods裡面的品種, bar頻率為1min
  28. subscribe(symbols=context.goods, frequency='60s', count=101)
  29. # 止損的比例區間
  30. def on_bar(context, bars):
  31. bar = bars[0]
  32. symbol = bar['symbol']
  33. recent_data = context.data(symbol=symbol, frequency='60s', count=101, fields='close,high,low')
  34. close = recent_data['close'].values[-1]
  35. # 計算ATR
  36. atr = talib.ATR(recent_data['high'].values, recent_data['low'].values, recent_data['close'].values,
  37. timeperiod=context.tar)[-1]
  38. # 計算唐奇安開倉和平倉通道
  39. context.don_open = context.parameter[0]+1
  40. upper_band = talib.MAX(recent_data['close'].values[:-1], timeperiod=context.don_open)[-1]
  41. context.don_close = context.parameter[1]+1
  42. lower_band = talib.MIN(recent_data['close'].values[:-1], timeperiod=context.don_close)[-1]
  43. # 計算開倉的資金比例
  44. percent = context.ratio / float(len(context.goods))
  45. # 若沒有倉位則開倉
  46. position_long = context.account().position(symbol=symbol, side=PositionSide_Long)
  47. position_short = context.account().position(symbol=symbol, side=PositionSide_Short)
  48. ifnot position_long andnot position_short:
  49. # 計算長短ma線.DIF
  50. ma_short = talib.MA(recent_data['close'].values, timeperiod=(context.parameter[2]+1))[-1]
  51. ma_long = talib.MA(recent_data['close'].values, timeperiod=(context.parameter[3]+1))[-1]
  52. dif = ma_short - ma_long
  53. # 獲取當前價格
  54. # 上穿唐奇安通道且短ma在長ma上方則開多倉
  55. if close > upper_band and(dif >0):
  56. order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market,
  57. position_side=PositionSide_Long)
  58. print(symbol,'市價單開多倉到比例: ', percent)
  59. # 下穿唐奇安通道且短ma在長ma下方則開空倉
  60. if close < lower_band and(dif <0):
  61. order_target_percent(symbol=symbol, percent=percent, order_type=OrderType_Market,
  62. position_side=PositionSide_Short)
  63. print(symbol,'市價單開空倉到比例: ', percent)
  64. elif position_long:
  65. # 價格跌破唐奇安平倉通道全平倉位止損
  66. if close < lower_band:
  67. order_close_all()
  68. print(symbol,'市價單全平倉位')
  69. else:
  70. # 獲取持倉均價
  71. vwap = position_long['vwap']
  72. # 獲取持倉的資金
  73. money = position_long['cost']
  74. # 獲取平倉的區間
  75. band = vwap - np.array([200,2,1.5,1,0.5,-100])* atr
  76. grid_percent = float(pd.cut([close], band, labels=[0,0.25,0.5,0.75,1])[0])* percent
  77. # 選擇現有百分比和區間百分比中較小的值(避免開倉)
  78. target_percent = np.minimum(money / context.account().cash['nav'], grid_percent)
  79. if target_percent !=1.0:
  80. print(symbol,'市價單平多倉到比例: ', target_percent)
  81. order_target_percent(symbol=symbol, percent=target_percent, order_type=OrderType_Market,
  82. position_side=PositionSide_Long)
  83. elif position_short:
  84. # 價格漲破唐奇安平倉通道或價格漲破持倉均價加兩倍ATR平空倉
  85. if close > upper_band:
  86. order_close_all()
  87. print(symbol,'市價單全平倉位')
  88. else:
  89. # 獲取持倉均價
  90. vwap = position_short['vwap']
  91. # 獲取持倉的資金
  92. money = position_short['cost']
  93. # 獲取平倉的區間
  94. band = vwap + np.array([-100,0.5,1,1.5,2,200])* atr
  95. grid_percent = float(pd.cut([close], band, labels=[1,0.75,0.5,0.25,0])[0])* percent
  96. # 選擇現有百分比和區間百分比中較小的值(避免開倉)
  97. target_percent = np.minimum(money / context.account().cash['nav'], grid_percent)
  98. if target_percent !=1.0:
  99. order_target_percent(symbol=symbol, percent=target_percent, order_type=OrderType_Market,
  100. position_side=PositionSide_Short)
  101. print(symbol,'市價單平空倉到比例: ', target_percent)
  102. if __name__ =='__main__':
  103. '''
  104. strategy_id策略ID,由系統生成
  105. filename檔名,請與本檔名保持一致
  106. mode實時模式:MODE_LIVE回測模式:MODE_BACKTEST
  107. token繫結計算機的ID,可在系統設定-金鑰管理中生成
  108. backtest_start_time回測開始時間
  109. backtest_end_time回測結束時間
  110. backtest_adjust股票復權方式不復權:ADJUST_NONE前復權:ADJUST_PREV後復權:ADJUST_POST
  111. backtest_initial_cash回測初始資金
  112. backtest_commission_ratio回測佣金比例
  113. backtest_slippage_ratio回測滑點比例
  114. '''
  115. run(strategy_id='strategy_id',
  116. filename='main.py',
  117. mode=MODE_BACKTEST,
  118. token='token_id',
  119. backtest_start_time='2017-09-15 09:15:00',
  120. backtest_end_time='2017-10-01 15:00:00',
  121. backtest_adjust=ADJUST_PREV,
  122. backtest_initial_cash=10000000,
  123. backtest_commission_ratio=0.0001,
  124. backtest_slippage_ratio=0.0001)

文章來源:掘金量化交易平臺     轉載請註明出處!

-----------------------------------------------------------------------------------------------------------------------------------------------------------

更多策略原始碼檢視: