生活随笔
收集整理的這篇文章主要介紹了
海龟交易法(期货)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1. 原理
1.1 起源
海龜交易思想起源于上世紀八十年代的美國。理查德丹尼斯與好友比爾打賭,主題是一個成功的交易員是天生的還是后天的。理查德用十年時間證明了通過日常系統培訓,交易員可以通過后天培訓成為一名優秀的交易者。這套培訓系統就是海龜交易系統。
海龜交易系統是一個完整的、機械的交易思想,可以系統地完成整個交易過程。它包括了買賣什么、頭寸規模、何時買賣、何時退出等一系列交易策略,是一個趨勢交易策略。它最顯著的特點是捕捉中長期趨勢,力求在短期內獲得最大的收益。
1.2 建倉資金
海龜交易法將建倉資金按照一定比例劃分為若干個小部分,每次建倉頭寸和加倉規模都與波動量N(又稱平均真實波動振幅average true range ATR)有關。ATR是日內指數最大波動的平均振幅,由當日最高、最低價和上一交易日的收盤價決定。
ATR
其中PDC是前一交易日的收盤價,ATR就是TR在N天內的均值。
價值波動量
利用N值來體現價值波動量DV:
DV = N * 合約每點價值
其中每點代表的價值量是指每一個指數點數所代表的價格。
每一次開倉交易合約數unit的確定是將總資產的1%除以DV得到。
1.3 入市信號
海龜交易法使用的是以一個理查德唐奇安的通道突破系統為基礎的入市系統。唐奇安通道分為系統一和系統二,對應短期突破和中長期突破。其中,短期突破系統是以20日(最高價或最低價)突破為基礎,當價格突破20日價格即為入市信號;中長期系統是當盤中價格突破過去55日價格為入市信號。
1.4 加倉和止損
海龜交易法的加倉規則是當捕捉到入市信號后建立第一個交易單位的頭寸,市價繼續向盈利方向突破1/2N時加倉。
止損位為2N,同加倉一樣采用平均真實振幅N值為止損單位。每加倉一次,止損位就提高1/2N。
1.5 止盈
短期:多頭頭寸在突破過去10日最低價處止盈離市,空頭頭寸在突破過去10日最高價處止盈離市。
中長期:多頭頭寸在突破過去20日最低價處止盈離市,空頭頭寸在突破過去20日最高價處止盈離市。
2. 策略思路
第一步:獲取歷史數據,計算唐奇安通道和ATR
第二步:當突破唐奇安通道時,開倉。
第三步:計算加倉和止損信號。
回測標的:DCE.i2012
回測時間:2020-02-15 至 2020-09-01
回測初始資金:100萬
Tips:
ATR值是不斷變化的,這就會導致在對期貨平倉時,可能出現平倉數量 > 持倉數量的現象。比如前一交易日的持倉為10,今日的ATR值為22.假設當前價格觸發平倉條件,平倉1/2ATR。1/2ATR=11 > 10, 這樣就會導致委托失敗報錯。所以要加入一個變量volume_hold用來記錄當前持倉量,與1/2*ATR作比較。
注意:若修改回測期,需要修改對應的回測標的。
3. 策略代碼
# coding=utf-8from __future__ import print_function, absolute_import, unicode_literalsimport numpy as npimport pandas as pdfrom gm.api import *'''以短期為例:20日線第一步:獲取歷史數據,計算唐奇安通道和ATR第二步:當突破唐奇安通道時,開倉。第三步:計算加倉和止損信號。'''def init(context):# 設置計算唐奇安通道的參數context.n = 20# 設置合約標的context.symbol = 'DCE.i2012'# 設置交易最大資金比率context.ratio = 0.8# 訂閱數據subscribe(symbols=context.symbol, frequency='60s', count=2)# 獲取當前時間time = context.now.strftime('%H:%M:%S')# 如果策略執行時間點是交易時間段,則直接執行algo定義atr等參數,以防直接進入on_bar()導致atr等未定義if '09:00:00' < time < '15:00:00' or '21:00:00' < time < '23:00:00':algo(context)# 如果是交易時間段,等到開盤時間確保進入algo()schedule(schedule_func=algo, date_rule='1d', time_rule='09:00:00')schedule(schedule_func=algo, date_rule='1d', time_rule='21:00:00')def algo(context):# 計算通道的數據:當日最低、最高、上一交易日收盤# 注:由于talib庫計算ATR的結果與公式求得的結果不符,所以這里利用公式計算ATR# 如果是回測模式,當天的數據直接用history取到if context.mode == 2:data = history_n(symbol=context.symbol, frequency='1d', count=context.n+1, end_time=context.now, fields='close,high,low,bob', df=True) # 計算ATRtr_list = []for i in range(0, len(data)-1):tr = max((data['high'].iloc[i] - data['low'].iloc[i]), data['close'].shift(-1).iloc[i] - data['high'].iloc[i],data['close'].shift(-1).iloc[i] - data['low'].iloc[i])tr_list.append(tr)context.atr = int(np.floor(np.mean(tr_list)))context.atr_half = int(np.floor(0.5 * context.atr))# 計算唐奇安通道context.don_open = np.max(data['high'].values[-context.n:])context.don_close = np.min(data['low'].values[-context.n:])# 如果是實時模式,當天的數據需要用current取到if context.mode == 1:data = history_n(symbol=context.symbol, frequency='1d', count=context.n, end_time=context.now, fields='close,high,low',df=True) # 計算ATRcurrent_data = current(symbols=context.symbol) # 最新一個交易日的最高、最低tr_list = []for i in range(1, len(data)):tr = max((data['high'].iloc[i] - data['low'].iloc[i]),data['close'].shift(-1).iloc[i] - data['high'].iloc[i],data['close'].shift(-1).iloc[i] - data['low'].iloc[i])tr_list.append(tr)# 把最新一期tr加入列表中tr_new = max((current_data[0]['high'] - current_data[0]['low']),data['close'].iloc[-1] - current_data[0]['high'],data['close'].iloc[-1] - current_data[0]['low'])tr_list.append(tr_new)context.atr = int(np.floor(np.mean(tr_list)))context.atr_half = int(np.floor(0.5 * context.atr))# 計算唐奇安通道context.don_open = np.max(data['high'].values[-context.n:])context.don_close = np.min(data['low'].values[-context.n:])# 計算加倉點和止損點context.long_add_point = context.don_open + context.atr_halfcontext.long_stop_loss = context.don_open - context.atr_halfcontext.short_add_point = context.don_close - context.atr_halfcontext.short_stop_loss = context.don_close + context.atr_halfdef on_bar(context, bars):# 提取數據symbol = bars[0]['symbol']recent_data = context.data(symbol=context.symbol, frequency='60s', count=2, fields='close,high,low')close = recent_data['close'].values[-1]# 賬戶倉位情況position_long = context.account().position(symbol=symbol, side=PositionSide_Long)position_short = context.account().position(symbol=symbol, side=PositionSide_Short)# 當無持倉時if not position_long and not position_short:# 如果向上突破唐奇安通道,則開多if close > context.don_open:order_volume(symbol=symbol, side=OrderSide_Buy, volume=context.atr, order_type=OrderType_Market, position_effect=PositionEffect_Open)print('開多倉atr')# 如果向下突破唐奇安通道,則開空if close < context.don_close:order_volume(symbol=symbol, side=OrderSide_Sell, volume=context.atr, order_type=OrderType_Market, position_effect=PositionEffect_Open)print('開空倉atr')# 有持倉時# 持多倉,繼續突破(加倉)if position_long:# 當突破1/2atr時加倉if close > context.long_add_point:order_volume(symbol=symbol, volume=context.atr_half, side=OrderSide_Buy, order_type=OrderType_Market,position_effect=PositionEffect_Open)print('繼續加倉0.5atr')context.long_add_point += context.atr_halfcontext.long_stop_loss += context.atr_half# 持多倉,止損位計算if close < context.long_stop_loss:volume_hold = position_long['volume']if volume_hold >= context.atr_half:order_volume(symbol=symbol, volume=context.atr_half, side=OrderSide_Sell, order_type=OrderType_Market, position_effect=PositionEffect_Close)else:order_volume(symbol=symbol, volume=volume_hold, side=OrderSide_Sell, order_type=OrderType_Market,position_effect=PositionEffect_Close)print('平多倉0.5atr')context.long_add_point -= context.atr_halfcontext.long_stop_loss -= context.atr_half# 持空倉,繼續突破(加倉)if position_short:# 當跌破加倉點時加倉if close < context.short_add_point:order_volume(symbol = symbol, volume=context.atr_half, side=OrderSide_Sell, order_type=OrderType_Market, position_effect=PositionEffect_Open)print('繼續加倉0.5atr')context.short_add_point -= context.atr_halfcontext.short_stop_loss -= context.atr_half# 持多倉,止損位計算if close > context.short_stop_loss:volume_hold = position_short['volume']if volume_hold >= context.atr_half:order_volume(symbol=symbol, volume=context.atr_half, side=OrderSide_Buy, order_type=OrderType_Market, position_effect=PositionEffect_Close)else:order_volume(symbol=symbol, volume=volume_hold, side=OrderSide_Buy, order_type=OrderType_Market,position_effect=PositionEffect_Close)print('平空倉0.5atr')context.short_add_point += context.atr_halfcontext.short_stop_loss += context.atr_halfif __name__ == '__main__':'''strategy_id策略ID,由系統生成filename文件名,請與本文件名保持一致mode實時模式:MODE_LIVE回測模式:MODE_BACKTESTtoken綁定計算機的ID,可在系統設置-密鑰管理中生成backtest_start_time回測開始時間backtest_end_time回測結束時間backtest_adjust股票復權方式不復權:ADJUST_NONE前復權:ADJUST_PREV后復權:ADJUST_POSTbacktest_initial_cash回測初始資金backtest_commission_ratio回測傭金比例backtest_slippage_ratio回測滑點比例'''run(strategy_id='strategy_id',filename='main.py',mode=MODE_BACKTEST,token='token',backtest_start_time='2020-02-15 09:15:00',backtest_end_time='2020-09-01 15:00:00',backtest_adjust=ADJUST_PREV,backtest_initial_cash=1000000,backtest_commission_ratio=0.0001,backtest_slippage_ratio=0.0001)
4. 回測結果與穩健性分析
設定初始資金100萬,手續費率為0.01%,滑點比率為0.01%?;販y結果如下圖所示。
回測期累計收益率為18.75%,年化收益率為6.42%,滬深300收益率為18.75%,策略跑輸滬深300指數。最大回撤為4.20%,勝率為48.15%。
為了檢驗策略的穩健性,改變策略標的和計算唐奇安通道的參數n,回測結果如下。
標的唐奇安通道參數年化收益率最大回撤
| DCE.i2012 | 20 | 6.42% | 4.20% |
| DCE.i2012 | 25 | 3.45% | 4.99% |
| DCE.i2012 | 30 | -0.35% | 4.23% |
| DCE.m2012 | 20 | -0.28% | 1.50% |
| DCE.m2012 | 25 | 1.19% | 0.52% |
| DCE.m2012 | 30 | 1.23% | 0.47% |
| SHFE.rb2012 | 20 | -4.48% | 2.61% |
| SHFE.rb2012 | 25 | -2.80% | 2.84% |
| SHFE.rb2012 | 30 | -3.01% | 2.39% |
由上表可知,不同標的收益結果呈現差異。其中大商所的鐵礦石收益情況最好,其他兩個品種收益較差,整體收益情況較差。說明該策略在使用上存在一定風險。
總結
以上是生活随笔為你收集整理的海龟交易法(期货)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。