<s id="iwbjp"><object id="iwbjp"><blockquote id="iwbjp"></blockquote></object></s>
      <tbody id="iwbjp"></tbody>
      <button id="iwbjp"><object id="iwbjp"></object></button>
      1. <button id="iwbjp"><object id="iwbjp"><menuitem id="iwbjp"></menuitem></object></button>
        1. <th id="iwbjp"></th>
          <tbody id="iwbjp"></tbody>
          黑山量化投資社區

          【量子策略研究系列(一)】跟蹤趨勢,順勢突破——滬深300下的Dual Thrust策略探究

          量化投資與金融科技2021-10-03 09:21:58

          1

          策略簡介


          Dual Thrust策略由Michael Chalek在20世紀80年代開發,曾被Future Thruth雜志評為最賺錢的策略之一,在自動化交易排名中,收益表現仍位列第二。Dual Thrust是一個追漲殺跌的短期趨勢策略,簡單而而有效,普遍適用于股票、期貨和外匯等市場。


          Dual Thrust策略的邏輯原型是開盤區間突破策略,該策略首先計算觸發值,即取昨日收盤時,最高價-收盤價和收盤價-最低價中較大者;然后取今日開盤價,當價格超過開盤價+觸發值時馬上買入,低于開盤價-觸發值時馬上賣空。


          Dual Thrust策略在開盤區間突破策略的基礎上做出改進。


          1. 在觸發值的設置上,利用前N日的四個價位,即最高價的最高價(HH)、收盤價的最高價(HC)、收盤價的最低價(LC)和最低價的最低價(LL),來確定一個合理的range。


          這一改進可以使一定時期內的range保持相對穩定。具體來說,HH和LL限定了N日內價格的波動區間,HC和LC表示的是N日內的波動情況。若HC和LC處于中間位置,則表明價格在N日內的波動只是偶然情況,在其余時間價格波動較??;若價格在N日內呈現單邊趨勢,則HH和LL確定的區間范圍較大,HC和LC也會接近箱體上下沿,需要更多點數才能產生價格突破。


          2. 在上下雙軌的確定上,考慮了非對稱的幅度,即設置兩個不同的參數K1和K2分別計算多頭和空頭的觸發條件。當K1>K2時,空頭相對容易被觸發;反之則相反。


          2

          計算公式(以日為單位舉例)?


          (1)N日內每天的最高價HIGH(N), 最低價LOW(N), 和收盤價CLOSE(N)


          (2)HH = N日HIGH的最高價 = MAX(HIGH(N))

          ? ? ? ?LC = N日CLOSE的最低價 = MIN(CLOSE(N))

          ? ? ? ?HC = N日CLOSE的最高價 = MAX(CLOSE(N))

          ? ? ? ?LL = N日LOW的最低價 = MIN(LOW(N))


          (3)計算震蕩區間Range

          ? ? ? ?Range = MAX(HH-LC, HC - LL)


          (4)計算上下軌

          ? ? ? ?上軌 = 開盤價 + K1 * Range

          ? ? ? ?下軌 = 開盤價 - K2 * Range

          ? ? ? ?K1, K2為Range的系數,由用戶自行設定。



          3

          偽代碼


          Inputs: K1(.5),K2(.5),Mday(1),Nday(1);

          Vars: BuyRange(0), SellRange(0);

          Vars: BuyTrig(0),SellTrig(0);

          Vars: HH(0),LL(0),HC(0),LC(0);

          If CurrentBar > 1 Then Begin

          HH = Highest(High,Mday);

          HC = Highest(Close,Mday);

          LL = Lowest(Low,Mday);

          LC = Lowest(Close,Mday);

          If (HH - LC) >= (HC - LL) Then Begin

          SellRange = HH - LC;

          End Else Begin

          SellRange = HC - LL;

          End;

          HH = Highest(High,Nday);

          HC = Highest(Close,Nday);

          LL = Lowest(Low,Nday);

          LC = Lowest(Close,Nday);

          If (HH - LC) >= (HC - LL) Then Begin

          BuyRange = HH - LC;

          End Else Begin

          BuyRange = HC - LL;

          End;

          BuyTrig = K1*BuyRange;

          SellTrig = K2*SellRange;

          If MarketPosition = 0 Then Begin

          Buy at Open of next bar + BuyTrig Stop;

          Sell at Open of next bar - SellTrig Stop;

          End;

          If MarketPosition = -1 Then Begin Buy at Open of next bar + Buytrig Stop; End;

          If MarketPosition = 1 Then Begin

          Sell at Open of next bar - SellTrig Stop;

          End;

          End;


          4

          使用方法


          如果當前價格向上/向下突破Range一定的比例,則認為一波上漲/下跌行情形成,產生買入/賣出信號。


          以滬深300作為交易標的,計算好上下軌之后,一旦價格突破上軌,我們就買入。當價格突破下軌,我們就賣出。


          所以,對于上下軌系數的設定十分關鍵。因此,投資者在使用該策略時,一方面可以參考歷史數據測試的最優參數,另一方面,則可以根據自己對后市的判斷,或從其他大周期的技術指標入手,階段性地動態調整K1和K2的值。


          5

          策略收益分析








          6

          小結


          可以看出,策略在2017年1月和2月期間實現了19.80%的年化收益率,最大回撤為3.7%,取得了較好的效果。此外還可以觀察到,在1月上旬,該策略表現略低于指數,從1月中旬開始,該策略收益持續跑贏指數。1月上旬,指數處于窄幅震蕩的盤整期,自1月中旬起,指數開始進入持續上行的走勢,這也驗證了本策略在市場趨勢明顯的時候能取得較好的收益,而在大盤震蕩的時期表現欠佳。


          由于本文只是為了簡要講解該策略,只選取了幾個月的時間進行回測。進一步的分析需要選取更長的時間維度進行回測。


          Dual Thrust策略在短期和長期都適用,重點是對參數的調節。調小參數做短期抓震蕩,調大參數做長期抓趨勢,看多調小K1,看空調小K2。如何靈活掌握參數設置的精髓,從容面對各種行情,就留給讀者結合量子投研平臺去探索了。


          7

          Code


          # -*- coding=UTF-8 -*-
          # Dual Thrust
          策略
          # Dual Thrust是一個趨勢跟蹤系統,由MichaelChalek20世紀80年代開發,曾被FutureThruth雜志評為最賺錢的策略之一。
          # Dual Trust是一個追漲殺跌的策略,原理并不復雜。是一個簡單而又有效的短期趨勢策略

          # 計算原理
          # Dual Thrust策略利用前N日的最高價,最低價和收盤價,來確定一個合理的震蕩區間Range。利用前一時間點的開盤價和Range,
          # 確定當前的上下雙軌。如果當前價格向上/向下突破Range一定的比例,則認為一波上漲/下跌行情形成,產生買入/賣出信號。
          # 1N日內每天的最高價HIGH(N), 最低價LOW(N), 和收盤價CLOSE(N)
          #
          2HH = NHIGH的最高價 = MAX(HIGH(N))
          #???????? LC = N
          CLOSE的最低價 = MIN(CLOSE(N))
          #???????? HC = N
          CLOSE的最高價 = MAX(CLOSE(N))
          #???????? LL = N
          LOW的最低價 = MIN(LOW(N))
          #
          3)計算震蕩區間Range
          #???????? Range = MAX
          HH-LC, HC - LL
          # 4)計算上下軌
          #???????? 上軌 = 開盤價 + K1 * Range
          #????????
          下軌 = 開盤價 - K2 * Range
          #???????? K1, K2
          Range的系數,由用戶自行設定。

          # 使用方法
          # Dual Thrust策略是一個趨勢突破策略。計算好上下軌之后,一旦價格突破上軌,我們就買入;當價格突破下軌,我們就賣出。所以,對于上下軌系數的設定十分關鍵。

          # K1K2的值越小,越容易觸發對應的軌道。而且,當K1<K2時,多頭相對容易被觸發;當K1>K2時,空頭相對容易被觸發。
          # 因此,投資者在使用該策略時,一方面可以參考歷史數據測試的最優參數,另一方面,則可以根據自己對后市的判斷,或從其他大周期的技術指標入手,階段性地動態調整K1K2的值。
          from CloudQuant importSDKCoreEngine? #導入量子金服SDK
          from CloudQuant importAssetType
          from CloudQuant importQuoteCycle
          import numpy as np


          config
          = {
          ???
          'username':'maodaren',? # 訪問SDK所使用的用戶名,即量子投研管理平臺的登錄名
          ???
          'password':'zyy666',? # 訪問SDK所使用的用戶名對應的密碼
          ???
          'rootpath':'d:/cStrategy/',? # 基礎數據存放的路徑,即客戶端所在路徑
          ???
          'initCapitalStock': 10000000,? # 回測開始時的初始資金
          ???
          'startDate':20170101,? # 回測開始時的日期
          ???
          'endDate':20170301,? # 回測結束時的日期
          ???
          'cycle': QuoteCycle.M15,? # 進行回測前的時間粒度,int類型,定義在枚舉QuoteCycle
          ???
          'assetType':AssetType.Stock,
          ???
          'feeRate':0.001,? # 手續費率
          ???
          'feeLimit':5,? # 最低手續費
          ???
          'strategyName': 'DUALTHRUST',?# 策略名
          ???
          # 'logfile': "CloudQuantTest.log",? # 在策略中調用log方法所生成的日志文件名
          ???
          'dealByVolume': False? #撮合是否考慮實際交易量
          }

          def initial(sdk):
          ???
          count = 0
          ???
          days = 10
          ???
          sdk.setGlobal('DAYS', days)
          ???
          sdk.setGlobal(
          'COUNT',count)

          def initPerDay(sdk):
          ???
          date =sdk.getNowDate()
          ???
          print date
          ??? COUNT
          = sdk.getGlobal('COUNT')
          ???
          COUNT = COUNT+1
          ???
          sdk.setGlobal('COUNT',COUNT)
          ???
          DAYS
          = sdk.getGlobal('DAYS')

          ???
          HIGH = sdk.getFactorData('LZ_CN_STKA_QUOTE_THIGH')? #獲取最高收盤價因子
          ???
          if HIGH is None:
          ?????? ?
          return
          ???
          HIGH = HIGH[-(DAYS+1):-1]

          ???
          LOW = sdk.getFactorData('LZ_CN_STKA_QUOTE_TLOW')? #獲取最低收盤價因子
          ???
          if LOW is None:
          ???????
          return
          ???
          LOW = LOW[-(DAYS+1):-1]

          ???
          Tclose = sdk.getFactorData('LZ_CN_STKA_QUOTE_TCLOSE')? # 用的是今收盤價因子,因為回測時數據只取到昨天

          ?? ?
          if Tcloseis None:
          ???????
          return
          ???
          lclose = Tclose[-1]??? # 獲取昨日收盤價
          ???
          CLOSE = Tclose[-(DAYS+1):-1]? #獲取最近收盤價

          ???
          # 以滬深300成分股作為交易標的
          ???
          temp = sdk.getFactorData('LZ_CN_STKA_INDEX_HS300MEMBER')
          ???
          if temp is None:
          ???????
          return
          ???
          temp1 = temp[-1]
          ???
          loc = []
          ???
          condition = [1 if j == '1' else 0 for j in temp1]
          ???
          for k in range(len(condition)):
          ???????
          if condition[k] == 1:
          ???????????
          loc.append(k)
          ???
          stock_list
          = sdk.getStockList()? #返回對象數據類型為列表
          ???
          if stock_listis None:
          ???????
          return
          ?? ?
          deal_stock= list(np.array(stock_list)[loc])? #以回測前一天的滬深300成分股作為交易標的
          ???
          sdk.setGlobal('DEAL_STOCK',deal_stock)???

          ???
          # 取出滬深300部分
          ???
          lclose = lclose[loc]? #前一日滬深300收盤價
          ???
          HIGH = [HIGH[i][loc] for i in range(DAYS)] #10日滬深300最高價
          ???
          LOW = [LOW[i][loc] for i in range(DAYS)]? #10日滬深300最低價
          ???
          CLOSE = [CLOSE[i][loc] for i in range(DAYS)]? #10日滬深300收盤價

          ???
          # 設置全局變量
          ???
          sdk.setGlobal('CLOSE',CLOSE)
          ???
          sdk.setGlobal(
          'HIGH', HIGH)
          ???
          sdk.setGlobal(
          'LOW', LOW)
          ???
          sdk.setGlobal(
          'LOC', loc)
          ???
          sdk.setGlobal(
          'LCLOSE',lclose)
          ???
          sdk.setGlobal(
          'Tclose',Tclose)


          def strategy(sdk):
          ???
          # 獲取全局變量
          ???
          COUNT = sdk.getGlobal('COUNT')
          ???
          DAYS = sdk.getGlobal('DAYS')
          ???
          Tclose = sdk.getGlobal('Tclose')
          ???
          lclose = sdk.getGlobal('LCLOSE')
          ???
          deal_stock = sdk.getGlobal('DEAL_STOCK')
          ???
          HIGH = sdk.getGlobal('HIGH')
          ???
          LOW = sdk.getGlobal('LOW')
          ???
          CLOSE = sdk.getGlobal('CLOSE')
          ???
          LOC = sdk.getGlobal('LOC')

          ???
          K1 = 0.5
          ???
          K2 = 0.5

          ???
          quotes = sdk.getQuotes(deal_stock, tsInd = AssetType.Stock)
          ???
          if quotesis None:
          ???????
          return
          ???
          pos = sdk.getPositions()? #查詢持倉盤口信息
          ???
          if pos is None:
          ???????
          return
          ???
          pos_code = [i.code for i in pos]
          ???
          deal_diff = np.setdiff1d(quotes.keys(), pos_code)? #取出當前未持倉股票

          ???
          if pos:
          ???????
          for stockrecordin pos:
          ?? ?????????
          if stockrecord.codenot in deal_stock:? #不再是滬深300成分股,直接賣出
          ???????????????
          quote = sdk.getQuote(stockrecord.code)
          ???????????????
          if quote is None:
          ???????????????????
          continue
          ???????????????
          sdk.makeOrder(stockrecord.code, quote.current, stockrecord.optPosition,-1)

          ???????????
          elif stockrecord.codein deal_stock and stockrecord.code inquotes.keys():? # 是成分股且能取到行情數據
          ???????????????
          quote = sdk.getQuote(stockrecord.code)
          ???????????????
          if quote is None:
          ???????????????????
          continue
          ??????????? ????
          index = deal_stock.index(stockrecord.code)
          ???????????????
          # for i in range(DAYS):
          ???????????????
          HH = max(list(np.array(HIGH)[:,index]))
          ???????????????
          LC = min(list(np.array(CLOSE)[:,index]))
          ???????????????
          HC = max(list(np.array(CLOSE)[:,index]))
          ???????????????
          LL = min(list(np.array(LOW)[:,index]))
          ???????????????
          RANGE = max(HH-LC,HC-LL)
          ???????????????
          UP_RANGE = quote.open + K1*RANGE
          ??????????????? DOWN_RANGE
          = quote.open- K2*RANGE
          ???????????????
          if quotes[stockrecord.code].current< DOWN_RANGE:? #穿破DOWN_RANGE下限直接賣出
          ????????????????????
          sdk.makeOrder(stockrecord.code, quotes[stockrecord.code].current,stockrecord.optPosition,-1)

          ???????????
          else:
          ???????????????
          pass

          ???
          # 股票買入操作
          ???
          stock_to_buy =[]
          ???
          account = sdk.getAccountInfo()?# 獲取賬戶信息
          ???
          if accountis None:
          ???????
          return
          ???
          budget = account.availableCash? # 用可用余額進行建倉操作
          ???
          if list(deal_diff):? # 存在可建倉股票
          ???????
          for code in deal_diff:
          ???????????
          quote = sdk.getQuote(code)
          ???????????
          if quote is None:
          ???????????????
          return
          ??????????? print
          code
          ??????????? index
          = deal_stock.index(code)
          ???????????
          print len(deal_stock)

          ???????????
          print np.shape(HIGH[-1]),1
          ???????????
          print? index
          ???????????
          print? deal_stock[index]

          ???????????
          np.savetxt("filena4me.txt",np.array(HIGH)[:,13])
          ???????????
          HH = max(list(np.array(HIGH)[:,index]))
          ???????????
          LC = min(list(np.array(CLOSE)[:,index]))
          ???????????
          HC = max(list(np.array(CLOSE)[:,index]))
          ???????????
          LL = min(list(np.array(LOW)[:,index]))
          ???????????
          print? HH,LC,HC,LL,1
          ?? ?????????
          RANGE = max(HH-LC, HC-LL)
          ???????????
          UP_RANGE = quote.open + K1*RANGE
          ??????????? DOWN_RANGE
          = quote.open- K2*RANGE
          ???????????
          if DOWN_RANGE<= quote.current:? #當股價超出上限視為買入時機
          ???????????????
          stock_to_buy.append(code)
          ???????
          if stock_to_buy!= []:
          ???????????
          orders = [[i, quotes[i].current,
          ??????????????????????
          int(budget / len(stock_to_buy) / quotes[i].current/ 100) * 100, 1] for i in stock_to_buy ifquotes[i].current!= 0]
          ???????????
          sdk.makeOrders(orders, tsInd = AssetType.Stock)



          def main():
          ???
          # 將策略函數加入
          ???
          config['initial']= initial
          ??? config
          ['strategy'] = strategy
          ??? config
          ['preparePerDay'] = initPerDay
          ???
          # 啟動SDK
          ???
          SDKCoreEngine(**config).run()


          if __name__ == "__main__":
          ???
          import time

          ??? starttime
          = time.time()

          ???
          main()

          ???
          endtime
          = time.time()

          ???
          print endtime- starttime


          量子投研管理平臺下載地址:http://www.yunkuanke.com/download





          致力于服務量化投資私募基金和優質金融機構。秉承著用科技推動中國量化資產管理行業發展的使命,專業、高效的經營理念。我們以成長的姿態,在一個充滿巨大想象空間的領域,正在快速成長為金融機構值得信賴的長期合作伙伴。



          點擊“閱讀原文”下載量子投研管理平臺