免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
Backtrader量化平臺(tái)教程(四)SSA策略實(shí)際案例

        上次我們講述了strategy的完整生命周期,并引入了一個(gè)indicator。今天,我們先講述幾個(gè)零碎的知識(shí)點(diǎn),然后正式編寫(xiě)一個(gè)SSA策略,包括indicator的編寫(xiě)和策略的回測(cè)。

1.關(guān)于data

1.1datafeed

        在一開(kāi)始我們就討論過(guò)datafeed,也就是cerebro的本源,數(shù)據(jù)。我們看一下上次我們的策略是怎么來(lái)的。

  1. dataframe = pd.read_csv('dfqc.csv', index_col=0, parse_dates=True)  
  2. dataframe['openinterest'] = 0  
  3. data = bt.feeds.PandasData(dataname=dataframe,  
  4.                         fromdate = datetime.datetime(2015, 1, 1),  
  5.                         todate = datetime.datetime(2016, 12, 31)  
  6.                         )  
  7. # Add the Data Feed to Cerebro  
  8. cerebro.adddata(data)  
        我們的數(shù)據(jù)是從一個(gè)dfqc的csv文件里面來(lái)的,這里,可能大家沒(méi)有這個(gè)數(shù)據(jù),之前上傳的csdn,不只是還沒(méi)通過(guò)還是怎么的。今天就把他存到百度云,大家有需要的可以自行下載。這是東風(fēng)汽車的股票數(shù)據(jù),是從wind上獲取的。大家沒(méi)有wind也可以用tushare之類的免費(fèi)api獲得。

鏈接:http://pan.baidu.com/s/1slnULbv 密碼:wi3k

        文件里面的數(shù)據(jù)大概是這樣的:

2014-03-13 00:00:00.005,1.425,1.434,1.449,1.418,457767208.02014-03-14 00:00:00.005,1.429,1.422,1.436,1.416,196209439.02014-03-17 00:00:00.005,1.433,1.434,1.437,1.422,250946201.02014-03-18 00:00:00.005,1.434,1.425,1.437,1.424,245516577.02014-03-19 00:00:00.005,1.423,1.419,1.423,1.406,331866195.02014-03-20 00:00:00.005,1.412,1.408,1.434,1.407,379443759.02014-03-21 00:00:00.005,1.406,1.463,1.468,1.403,825467935.0
  1. dataframe = pd.read_csv('dfqc.csv', index_col=0, parse_dates=True)  
         大家注意我們把csv讀入pandas的參數(shù),index_col=0表示第一列時(shí)間數(shù)據(jù)是作為pandas 的index的,parse_dates=Ture是自動(dòng)把數(shù)據(jù)中的符合日期的格式變成datetime類型。為什么要這樣呢?其實(shí)讀入后的pandas長(zhǎng)怎么樣都是由backtrader規(guī)定的。


1.2 strategy中的data

        大家不知道有沒(méi)有注意,strategy的初始化函數(shù)(init)中,

  1. self.dataclose = self.datas[0].close  
        有這樣一句。在backtrader中,self.datas[0] 與self.data是等價(jià)的,換句話說(shuō),同一個(gè)東西不同的叫法罷了。為什么會(huì)有前面這種,筆者認(rèn)為,backtrader應(yīng)當(dāng)可以支持多個(gè)datafeed,目前還沒(méi)有使用到,先按下不表。

        看看前面的pandas的要求的結(jié)構(gòu),我們就知道,不僅僅有self.datas[0].close,還會(huì)有self.datas[0].open。也確實(shí)如此。只是我們通常拿close作為一個(gè)價(jià)格基準(zhǔn)罷了。這里,

  1. self.datas[0].close  
        返回的是一個(gè)lines。lines是backtrader一個(gè)很重要的概念,我們可以理解為時(shí)間序列流,這類數(shù)據(jù),后面可以跟index,也就是說(shuō),可以有
  1. self.datas[0].close[0]  
  1. <pre code_snippet_id="2353235" snippet_file_name="blog_20170424_6_5245707" name="code" class="python" style="font-size: 18px;">self.datas[0].close[1]</pre><pre code_snippet_id="2353235" snippet_file_name="blog_20170424_7_1483717" name="code" class="python" style="font-size: 18px;">self.datas[0].close[-1]</pre>  
  2. <pre></pre>  
  3. <p></p>  
  4. <pre></pre>  
  5. 等等,但是這里的index是有意義的,0代表當(dāng)前時(shí)刻,-1代表前一時(shí)刻,1代表后一時(shí)刻,一次類推。  
  6. <p></p>  
  7. <p><span style="font-size:18px">所以在next中使用self.dataclose[0],<span style="font-size:18px">self.dataclose[-1]就很好理解了。</span></span></p>  
  8. <p></p>  
  9. <h1><a name="t3"></a><span style="font-size:18px">2.SSA</span></h1>  
  10. <p></p>  
  11. <p><span style="font-size:18px">        接下來(lái),開(kāi)始進(jìn)入完整的一個(gè)策略的研究,同時(shí)學(xué)習(xí)編寫(xiě)一個(gè)indicator。</span></p>  
  12. <p><span style="font-size:18px">        SSA就是奇異譜分析。</span></p>  
  13.        <span style="font-size:18px"> 奇異譜分析是近年來(lái)興起的一種研究非線性時(shí)間序列數(shù)據(jù)的強(qiáng)大的方法。它根據(jù)所觀測(cè)到的時(shí)間序列構(gòu)造出軌跡矩陣,并對(duì)軌跡矩陣進(jìn)行分解、重構(gòu),從而提取出代表原時(shí)間序列不同成分的信號(hào),如長(zhǎng)期趨勢(shì)信號(hào)、周期信號(hào)、噪聲信號(hào)等,從而對(duì)時(shí)間序列的結(jié)構(gòu)進(jìn)行分析,并可進(jìn)一步預(yù)測(cè)。</span>  
  14. <p><span style="font-size:18px">        說(shuō)的通俗點(diǎn),我們平時(shí)用均線,但是有一個(gè)問(wèn)題,均線雖然算法本質(zhì)上有平滑噪音的含義,但是有時(shí)候,也把重要的信息給平滑掉了。所以,我們是不是除了平滑這樣的方法之外,要開(kāi)拓新的方法來(lái)分離噪音和有用信息呢。</span></p>  
  15. <p><span style="font-size:18px">圖像的壓縮給我們一個(gè)很重要的啟示,就是譜分解,如果不知道什么是譜分解的話,只要知道,這是一種先分解,然后獲取重要信息的一種方法即可。</span></p>  
  16. <p><span style="font-size:18px">        奇異譜分解的基本思想很簡(jiǎn)單,分成如下幾個(gè)步驟:</span></p>  
  17. <h2><a name="t4"></a><span style="font-size:18px">2.1將時(shí)間序列轉(zhuǎn)化為軌跡矩陣</span></h2>  
  18. <p><span style="font-size:18px">假設(shè)有一個(gè)時(shí)間序列,當(dāng)然,對(duì)于我們而言,就是股價(jià):Y(T)=(y(1),?,y(T))</span></p>  
  19. <p><span style="font-size:18px">X=</span><span style="font-size:18px">(y1,y2,y3,?ym;</span></p>  
  20. <p><span style="font-size:18px">      y2,y3,y4,?ym+1;</span></p>  
  21. <p><span style="font-size:18px">     ..................................</span></p>  
  22. <p><span style="font-size:18px">     ..................................</span></p>  
  23. <p><span style="font-size:18px">      yn,yn+1,yn+2,?,yT)</span></p>  
  24. <p><span style="font-size:18px">就變成了這樣一個(gè)n*m的矩陣。</span></p>  
  25. <p><span style="font-size:18px">其中,m為選取的窗口長(zhǎng)度,可以當(dāng)做MA中的窗口長(zhǎng)度一樣理解。n=T-m+1。</span></p>  
  26. <h2><a name="t5"></a><span style="font-size:18px">2.2SVD分解與矩陣重構(gòu)</span></h2>  
  27. <p><span style="font-size:18px">計(jì)算X.T*X并對(duì)其進(jìn)行奇異值分解(SVD),從而得到其m個(gè)特征值</span></p>  
  28. <p><span style="font-size:18px">λ1≥λ2≥?≥λm≥0</span></p>  
  29. <p><span style="font-size:18px">然后按照從大到小的原則進(jìn)行矩陣重構(gòu)。筆者建議大家看一下SVD分解的相關(guān)內(nèi)容,可以更好的理解這一部分。</span></p>  
  30. <p><span style="font-family:MathJax_Math-italic; font-size:18px">假設(shè)重構(gòu)后的矩陣為</span></p>  
  31. <p><span style="font-family:MathJax_Math-italic; font-size:18px">X=</span><span style="font-family:MathJax_Math-italic; font-size:18px">(x1,1 x1,2 x1,3 ? x1,m;</span></p>  
  32. <p><span style="font-family:MathJax_Math-italic; font-size:18px"> x2,1 x2,2 x2,3  ? x2,m+1 </span></p>  
  33. <p><span style="font-family:MathJax_Math-italic; font-size:18px"> ..........................</span></p>  
  34. <p><span style="font-family:MathJax_Math-italic; font-size:18px"> ..........................</span></p>  
  35. <p><span style="font-family:MathJax_Math-italic; font-size:18px"> xn,1 xn,2 xn,3 ?  xn,n+m?1)</span></p>  
  36. <h2><a name="t6"></a><span style="font-family:MathJax_Math-italic; font-size:18px">2.3序列重構(gòu)</span></h2>  
  37. <p><span style="font-family:MathJax_Math-italic; font-size:18px">   可是我們要的是像MA一樣的線呀,現(xiàn)在這個(gè)顯然不是,所以我們要再把矩陣變成時(shí)間序列。方法還是有很多的,比如最常用的有對(duì)角相加:</span></p>  
  38. <p><span style="font-family:MathJax_Math-italic; font-size:18px">y1=x1,1 y2=(x1,2 + x2,1)/2  y3=(x1,3 + x2,2 + x3,1)/3</span></p>  
  39. <p><span style="font-family:MathJax_Math-italic; font-size:18px">......</span></p>  
  40. <h2><a name="t7"></a><span style="font-family:MathJax_Math-italic"><span style="font-size:18px">2.4 接下來(lái),我們就用代碼實(shí)現(xiàn)上面的這些步驟。</span></span></h2>  
  41. <p><span style="font-family:MathJax_Math-italic; font-size:18px"><span style="font-size:18px"></span></span></p>  
  42. <pre code_snippet_id="2353235" snippet_file_name="blog_20170424_8_8037370" name="code" class="python">    def get_window_matrix(self, input_array, t, m):  
  43.         # 將時(shí)間序列變成矩陣  
  44.         temp = []  
  45.         n = t - m + 1  
  46.         for i in range(n):  
  47.             temp.append(input_array[i:i + m])  
  48.         window_matrix = np.array(temp)  
  49.         return window_matrix  
  50.   
  51.     def svd_reduce(self, window_matrix):  
  52.         # svd分解  
  53.         u, s, v = np.linalg.svd(window_matrix)  
  54.         m1, n1 = u.shape  
  55.         m2, n2 = v.shape  
  56.         index = s.argmax()  # get the biggest index  
  57.         u1 = u[:, index]  
  58.         v1 = v[index]  
  59.         u1 = u1.reshape((m1, 1))  
  60.         v1 = v1.reshape((1, n2))  
  61.         value = s.max()  
  62.         new_matrix = value * (np.dot(u1, v1))  
  63.         return new_matrix  
  64.   
  65.     def recreate_array(self, new_matrix, t, m):  
  66.         # 時(shí)間序列重構(gòu)  
  67.         ret = []  
  68.         n = t - m + 1  
  69.         for p in range(1, t + 1):  
  70.             if p < m:  
  71.                 alpha = p  
  72.             elif p > t - m + 1:  
  73.                 alpha = t - p + 1  
  74.             else:  
  75.                 alpha = m  
  76.             sigma = 0  
  77.             for j in range(1, m + 1):  
  78.                 i = p - j + 1  
  79.                 if i > 0 and i < n + 1:  
  80.                     sigma += new_matrix[i - 1][j - 1]  
  81.             ret.append(sigma / alpha)  
  82.         return ret  
  83.   
  84.     def SSA(self, input_array, t, m):  
  85.         window_matrix = self.get_window_matrix(input_array, t, m)  
  86.         new_matrix = self.svd_reduce(window_matrix)  
  87.         new_array = self.recreate_array(new_matrix, t, m)  
  88.         return new_array</pre>   這里,我們調(diào)用SSA函數(shù)就可以獲得重構(gòu)后的時(shí)間序列。  
  89. <p></p>  
  90. <p><span style="font-family:MathJax_Math-italic; font-size:18px"><span style="font-size:18px">那么按照邏輯,重構(gòu)后的時(shí)間序列我們選取最后一個(gè),就是我們要的當(dāng)天的SSA了,然后就可以像趨勢(shì)線一樣使用。</span></span></p>  
  91. <h1><a name="t8"></a><span style="font-family:MathJax_Math-italic; font-size:18px"><span style="font-size:18px">3.indicator編寫(xiě)</span></span></h1>  
  92. <p><span style="font-family:MathJax_Math-italic; font-size:18px"><span style="font-size:18px">   到這里,我們已經(jīng)有了生成一個(gè)像SMA均線一樣的函數(shù)了,接下來(lái)就可以開(kāi)始寫(xiě)一個(gè)自己的indicator。到這里,我們先來(lái)看一下上次我們生成的indicator最后plot出來(lái)的圖:</span></span></p>  
  93. <p><span style="font-family:MathJax_Math-italic; font-size:18px"><span style="font-size:18px"><img src="http://img.blog.csdn.net/20170424200502314?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXRseXg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt=""><br>  
  94. <br>  
  95. </span></span></p>  
  96. <p><span style="font-family:MathJax_Math-italic; font-size:18px">  我們可以從圖上看出很多直觀的信息。比如什么時(shí)候買,什么時(shí)候賣,之前的indicator線長(zhǎng)什么樣。</span><br>  
  97. </p>  
  98. <p><span style="font-family:MathJax_Math-italic; font-size:18px">  不說(shuō)SMA,我們寫(xiě)一下我們自己的indicator吧。</span></p>  
  99. <p><span style="font-family:MathJax_Math-italic; font-size:18px">  首先,我們看一下我們調(diào)用SMA的時(shí)候是怎么調(diào)用的吧。</span></p>  
  100. <p><span style="font-family:MathJax_Math-italic; font-size:18px"></span></p>  
  101. <pre code_snippet_id="2353235" snippet_file_name="blog_20170424_9_9433592" name="code" class="python">        self.sma = bt.indicators.SimpleMovingAverage(  
  102.             self.datas[0], period=self.params.maperiod)  
  103. </pre>  其實(shí)們這里self.datas[0]不最為參數(shù)傳入也是可以的。  
  104. <p></p>  
  105. <p><span style="font-family:MathJax_Math-italic; font-size:18px">  即如果你寫(xiě)成:</span></p>  
  106. <p><span style="font-family:MathJax_Math-italic; font-size:18px"></span></p>  
  107. <pre code_snippet_id="2353235" snippet_file_name="blog_20170424_10_655092" name="code" class="python">        self.sma = bt.indicators.SimpleMovingAverage(period=self.params.maperiod)  
  108. </pre>效果是一毛一樣的。  
  109. <p></p>  
  110. <p><span style="font-family:MathJax_Math-italic; font-size:18px">  我們首先可以看到,這是一個(gè)和bt.indicator類有很大關(guān)系的一個(gè)東西,然后可以在調(diào)用的時(shí)候傳入一個(gè)參數(shù),在SMA中是平滑移動(dòng)的窗口大小。</span></p>  
  111. <p><span style="font-family:MathJax_Math-italic; font-size:18px">  實(shí)際上,任何一個(gè)indicator都是bt.indicator的子類,也就是說(shuō),我們自己寫(xiě)indicator的時(shí)候需要繼承bt.indicator。既然是繼承,那么接下來(lái)就是override幾個(gè)函數(shù),然后就可以實(shí)現(xiàn)功能了。而實(shí)際情況就是這樣。</span></p>  
  112. <p><span style="font-family:MathJax_Math-italic; font-size:18px">我們?cè)賮?lái)觀察一下我們?cè)谑褂胕ndicator的時(shí)候是怎么使用的。</span></p>  
  113. <p><span style="font-family:MathJax_Math-italic; font-size:18px"></span></p>  
  114. <pre code_snippet_id="2353235" snippet_file_name="blog_20170424_11_9401355" name="code" class="python"> if self.dataclose[0] > self.sma[0]:  
  115. </pre>前面說(shuō)過(guò),<br>  
  116. <pre code_snippet_id="2353235" snippet_file_name="blog_20170424_12_2574702" name="code" class="python" style="font-size: 18px;">self.dataclose[0]</pre>是一個(gè)lines,不難猜測(cè),self.sma也是一個(gè)lines。所以說(shuō),我們自己寫(xiě)的indica最后返回的就應(yīng)該是一個(gè)lines。  
  117. <p></p>  
  118. <p><span style="font-family:MathJax_Math-italic; font-size:18px">好了,我們開(kāi)始吧。</span></p>  
  119. <p><span style="font-family:MathJax_Math-italic; font-size:18px"></span></p>  
  120. <pre code_snippet_id="2353235" snippet_file_name="blog_20170424_13_3272814" name="code" class="python">class ssa_index_ind(bt.Indicator):  
  121.     lines = ('ssa',)  
  122.     def __init__(self, ssa_window):  
  123.         self.params.ssa_window = ssa_window  
  124.         # 這個(gè)很有用,會(huì)有 not maturity生成  
  125.         self.addminperiod(self.params.ssa_window * 2)  
  126.   
  127.     def get_window_matrix(self, input_array, t, m):  
  128.         # 將時(shí)間序列變成矩陣  
  129.         temp = []  
  130.         n = t - m + 1  
  131.         for i in range(n):  
  132.             temp.append(input_array[i:i + m])  
  133.         window_matrix = np.array(temp)  
  134.         return window_matrix  
  135.   
  136.     def svd_reduce(self, window_matrix):  
  137.         # svd分解  
  138.         u, s, v = np.linalg.svd(window_matrix)  
  139.         m1, n1 = u.shape  
  140.         m2, n2 = v.shape  
  141.         index = s.argmax()  # get the biggest index  
  142.         u1 = u[:, index]  
  143.         v1 = v[index]  
  144.         u1 = u1.reshape((m1, 1))  
  145.         v1 = v1.reshape((1, n2))  
  146.         value = s.max()  
  147.         new_matrix = value * (np.dot(u1, v1))  
  148.         return new_matrix  
  149.   
  150.     def recreate_array(self, new_matrix, t, m):  
  151.         # 時(shí)間序列重構(gòu)  
  152.         ret = []  
  153.         n = t - m + 1  
  154.         for p in range(1, t + 1):  
  155.             if p < m:  
  156.                 alpha = p  
  157.             elif p > t - m + 1:  
  158.                 alpha = t - p + 1  
  159.             else:  
  160.                 alpha = m  
  161.             sigma = 0  
  162.             for j in range(1, m + 1):  
  163.                 i = p - j + 1  
  164.                 if i > 0 and i < n + 1:  
  165.                     sigma += new_matrix[i - 1][j - 1]  
  166.             ret.append(sigma / alpha)  
  167.         return ret  
  168.   
  169.     def SSA(self, input_array, t, m):  
  170.         window_matrix = self.get_window_matrix(input_array, t, m)  
  171.         new_matrix = self.svd_reduce(window_matrix)  
  172.         new_array = self.recreate_array(new_matrix, t, m)  
  173.         return new_array  
  174.   
  175.     def next(self):  
  176.         data_serial = self.data.get(size=self.params.ssa_window * 2)  
  177.         self.lines.ssa[0] = self.SSA(data_serial, len(data_serial), int(len(data_serial) / 2))[-1]  
  178. </pre><br>  
  179.   大部分是ssa計(jì)算大代碼,我們看一下之前沒(méi)見(jiàn)過(guò)的。  
  180. <p></p>  
  181. <p><span style="font-family:MathJax_Math-italic; font-size:18px"></span></p>  
  182. <pre code_snippet_id="2353235" snippet_file_name="blog_20170424_14_7002567" name="code" class="python">lines = ('ssa',)  
  183.     def __init__(self, ssa_window):  
  184.         self.params.ssa_window = ssa_window  
  185.         # 這個(gè)很有用,會(huì)有 not maturity生成  
  186.         self.addminperiod(self.params.ssa_window * 2)</pre>  這里,lines是必須的,一個(gè)indicator至少要有一個(gè)lines,里面的ssa就是這個(gè)lines的命名,后續(xù)會(huì)出現(xiàn)。  
  187. <p></p>  
  188. <p><span style="font-family:MathJax_Math-italic; font-size:18px">既然是繼承了一個(gè)類,那么init函數(shù)是必須的了。傳入的參數(shù)是ssa是窗口大小,那么不言而已,我們收下就是了。<br>  
  189. </span></p>  
  190. <pre code_snippet_id="2353235" snippet_file_name="blog_20170424_15_6064476" name="code" class="python" style="font-size: 18px;"> self.addminperiod(self.params.ssa_window * 2)</pre>  這個(gè)是什么呢?我們?cè)谏弦淮螌trategy的生命周期的時(shí)候講到過(guò),比如一個(gè)5day的均線,那么開(kāi)始五天是沒(méi)有indicator的,這個(gè)時(shí)候,策略會(huì)調(diào)用prenext方法。而在indicator中,這個(gè)函數(shù)就是告訴strategy,我需要幾天才能成熟。根據(jù)ssa的計(jì)算方法,我們需要的是<pre code_snippet_id="2353235" snippet_file_name="blog_20170424_16_8714435" name="code" class="python" style="font-size: 18px;">self.params.ssa_window * 2</pre>  
  191. <p></p>  
  192. <p><span style="font-family:MathJax_Math-italic; font-size:18px">  然后是next,和strategy一樣</span></p>  
  193. <p><span style="font-family:MathJax_Math-italic; font-size:18px"></span></p>  
  194. <pre code_snippet_id="2353235" snippet_file_name="blog_20170424_17_4603780" name="code" class="python">    def next(self):  
  195.         data_serial = self.data.get(size=self.params.ssa_window * 2)  
  196.         self.lines.ssa[0] = self.SSA(data_serial, len(data_serial), int(len(data_serial) / 2))[-1]  
  197. </pre>  每一個(gè)時(shí)刻這個(gè)方法都會(huì)被調(diào)用一次。  
  198. <p></p>  
  199. <p><span style="font-family:MathJax_Math-italic; font-size:18px"></span></p>  
  200. <pre code_snippet_id="2353235" snippet_file_name="blog_20170424_18_8856921" name="code" class="python" style="font-size: 18px;">self.data.get(size=self.params.ssa_window * 2)</pre>  用于獲得size數(shù)量的數(shù)據(jù),當(dāng)然是往歷史方向延伸。  
  201. <p></p>  
  202. <p><span style="font-family:MathJax_Math-italic; font-size:18px">到這里,我們的indicator就完全寫(xiě)好了。</span></p>  
  203. <h1><a name="t9"></a><span style="font-family:MathJax_Math-italic; font-size:18px">4.調(diào)用indicator</span></h1>  
  204. <p><span style="font-family:MathJax_Math-italic; font-size:18px"></span></p>  
  205. <pre code_snippet_id="2353235" snippet_file_name="blog_20170424_19_7537146" name="code" class="python">self.ssa = ssa_index_ind(ssa_window=self.params.ssa_window, subplot=False)  
  206. </pre>  一模一樣的調(diào)用方法。這里我們看到比SMA多了一個(gè)參數(shù),subplot = False。這個(gè)最后再解釋。  
  207. <p></p>  
  208. <p><span style="font-family:MathJax_Math-italic; font-size:18px">  把所有代碼貼出來(lái),然后運(yùn)行一下吧。</span></p>  
  209. <p><span style="font-family:MathJax_Math-italic; font-size:18px"></span></p>  
  210. <pre code_snippet_id="2353235" snippet_file_name="blog_20170424_20_9315052" name="code" class="python"># -*- coding: utf-8 -*-  
  211.   
  212. from __future__ import (absolute_import, division, print_function,  
  213.                         unicode_literals)  
  214.   
  215. import datetime  # For datetime objects  
  216. import pandas as pd  
  217. import backtrader as bt  
  218. import numpy as np  
  219.   
  220. class ssa_index_ind(bt.Indicator):  
  221.     lines = ('ssa',)  
  222.     def __init__(self, ssa_window):  
  223.         self.params.ssa_window = ssa_window  
  224.         # 這個(gè)很有用,會(huì)有 not maturity生成  
  225.         self.addminperiod(self.params.ssa_window * 2)  
  226.   
  227.     def get_window_matrix(self, input_array, t, m):  
  228.         # 將時(shí)間序列變成矩陣  
  229.         temp = []  
  230.         n = t - m + 1  
  231.         for i in range(n):  
  232.             temp.append(input_array[i:i + m])  
  233.         window_matrix = np.array(temp)  
  234.         return window_matrix  
  235.   
  236.     def svd_reduce(self, window_matrix):  
  237.         # svd分解  
  238.         u, s, v = np.linalg.svd(window_matrix)  
  239.         m1, n1 = u.shape  
  240.         m2, n2 = v.shape  
  241.         index = s.argmax()  # get the biggest index  
  242.         u1 = u[:, index]  
  243.         v1 = v[index]  
  244.         u1 = u1.reshape((m1, 1))  
  245.         v1 = v1.reshape((1, n2))  
  246.         value = s.max()  
  247.         new_matrix = value * (np.dot(u1, v1))  
  248.         return new_matrix  
  249.   
  250.     def recreate_array(self, new_matrix, t, m):  
  251.         # 時(shí)間序列重構(gòu)  
  252.         ret = []  
  253.         n = t - m + 1  
  254.         for p in range(1, t + 1):  
  255.             if p < m:  
  256.                 alpha = p  
  257.             elif p > t - m + 1:  
  258.                 alpha = t - p + 1  
  259.             else:  
  260.                 alpha = m  
  261.             sigma = 0  
  262.             for j in range(1, m + 1):  
  263.                 i = p - j + 1  
  264.                 if i > 0 and i < n + 1:  
  265.                     sigma += new_matrix[i - 1][j - 1]  
  266.             ret.append(sigma / alpha)  
  267.         return ret  
  268.   
  269.     def SSA(self, input_array, t, m):  
  270.         window_matrix = self.get_window_matrix(input_array, t, m)  
  271.         new_matrix = self.svd_reduce(window_matrix)  
  272.         new_array = self.recreate_array(new_matrix, t, m)  
  273.         return new_array  
  274.   
  275.     def next(self):  
  276.         data_serial = self.data.get(size=self.params.ssa_window * 2)  
  277.         self.lines.ssa[0] = self.SSA(data_serial, len(data_serial), int(len(data_serial) / 2))[-1]  
  278.   
  279. # Create a Stratey  
  280. class MyStrategy(bt.Strategy):  
  281.     params = (  
  282.         ('ssa_window', 15),  
  283.         ('maperiod', 15),  
  284.     )  
  285.   
  286.     def log(self, txt, dt=None):  
  287.         ''''' Logging function fot this strategy'''  
  288.         dt = dt or self.datas[0].datetime.date(0)  
  289.         print('%s, %s' % (dt.isoformat(), txt))  
  290.   
  291.     def __init__(self):  
  292.         # Keep a reference to the "close" line in the data[0] dataseries  
  293.         self.dataclose = self.datas[0].close  
  294.   
  295.         # To keep track of pending orders and buy price/commission  
  296.         self.order = None  
  297.         self.buyprice = None  
  298.         self.buycomm = None  
  299.   
  300.         # Add a MovingAverageSimple indicator  
  301.         self.ssa = ssa_index_ind(ssa_window=self.params.ssa_window, subplot=False)  
  302.         # bt.indicator.LinePlotterIndicator(self.ssa, name='ssa')  
  303.         self.sma = bt.indicators.SimpleMovingAverage(period=self.params.maperiod)  
  304.     def start(self):  
  305.         print("the world call me!")  
  306.   
  307.     def prenext(self):  
  308.         print("not mature")  
  309.   
  310.     def notify_order(self, order):  
  311.         if order.status in [order.Submitted, order.Accepted]:  
  312.             # Buy/Sell order submitted/accepted to/by broker - Nothing to do  
  313.             return  
  314.   
  315.         # Check if an order has been completed  
  316.         # Attention: broker could reject order if not enougth cash  
  317.         if order.status in [order.Completed]:  
  318.             if order.isbuy():  
  319.                 self.log(  
  320.                     'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %  
  321.                     (order.executed.price,  
  322.                      order.executed.value,  
  323.                      order.executed.comm))  
  324.   
  325.                 self.buyprice = order.executed.price  
  326.                 self.buycomm = order.executed.comm  
  327.             else:  # Sell  
  328.                 self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %  
  329.                          (order.executed.price,  
  330.                           order.executed.value,  
  331.                           order.executed.comm))  
  332.   
  333.             self.bar_executed = len(self)  
  334.   
  335.         elif order.status in [order.Canceled, order.Margin, order.Rejected]:  
  336.             self.log('Order Canceled/Margin/Rejected')  
  337.   
  338.         self.order = None  
  339.   
  340.     def notify_trade(self, trade):  
  341.         if not trade.isclosed:  
  342.             return  
  343.   
  344.         self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %  
  345.                  (trade.pnl, trade.pnlcomm))  
  346.   
  347.     def next(self):  
  348.         # Simply log the closing price of the series from the reference  
  349.         self.log('Close, %.2f' % self.dataclose[0])  
  350.   
  351.         # Check if an order is pending ... if yes, we cannot send a 2nd one  
  352.         if self.order:  
  353.             return  
  354.   
  355.         # Check if we are in the market  
  356.         if not self.position:  
  357.   
  358.             # Not yet ... we MIGHT BUY if ...  
  359.             if self.dataclose[0] > self.ssa[0]:  
  360.   
  361.                 # BUY, BUY, BUY!!! (with all possible default parameters)  
  362.                 self.log('BUY CREATE, %.2f' % self.dataclose[0])  
  363.   
  364.                 # Keep track of the created order to avoid a 2nd order  
  365.                 self.order = self.buy()  
  366.   
  367.         else:  
  368.   
  369.             if self.dataclose[0] < self.ssa[0]:  
  370.                 # SELL, SELL, SELL!!! (with all possible default parameters)  
  371.                 self.log('SELL CREATE, %.2f' % self.dataclose[0])  
  372.   
  373.                 # Keep track of the created order to avoid a 2nd order  
  374.                 self.order = self.sell()  
  375.     def stop(self):  
  376.         print("death")  
  377.   
  378. if __name__ == '__main__':  
  379.     # Create a cerebro entity  
  380.     cerebro = bt.Cerebro()  
  381.     # Add a strategy  
  382.     cerebro.addstrategy(MyStrategy)  
  383.     # 本地?cái)?shù)據(jù),筆者用Wind獲取的東風(fēng)汽車數(shù)據(jù)以csv形式存儲(chǔ)在本地。  
  384.     # parase_dates = True是為了讀取csv為dataframe的時(shí)候能夠自動(dòng)識(shí)別datetime格式的字符串,big作為index  
  385.     # 注意,這里最后的pandas要符合backtrader的要求的格式  
  386.     dataframe = pd.read_csv('dfqc.csv', index_col=0, parse_dates=True)  
  387.     dataframe['openinterest'] = 0  
  388.     data = bt.feeds.PandasData(dataname=dataframe,  
  389.                             fromdate = datetime.datetime(2015, 1, 1),  
  390.                             todate = datetime.datetime(2016, 12, 31)  
  391.                             )  
  392.     # Add the Data Feed to Cerebro  
  393.     cerebro.adddata(data)  
  394.     # Set our desired cash start  
  395.     cerebro.broker.setcash(100.0)  
  396.     # 設(shè)置每筆交易交易的股票數(shù)量  
  397.     cerebro.addsizer(bt.sizers.FixedSize, stake=10)  
  398.     # Set the commission  
  399.     cerebro.broker.setcommission(commission=0.0)  
  400.     # Print out the starting conditions  
  401.     print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())  
  402.     # Run over everything  
  403.     cerebro.run()  
  404.     # Print out the final result  
  405.     print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())  
  406.     cerebro.plot()  
  407. </pre>結(jié)果是這樣的:  
  408. <p></p>  
  409. <p><span style="font-family:MathJax_Math-italic; font-size:18px"><img src="http://img.blog.csdn.net/20170424202750157?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXRseXg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt=""><br>  
  410. <br>  
  411.   如果我們把</span></p>  
  412. <pre code_snippet_id="2353235" snippet_file_name="blog_20170424_21_6425114" name="code" class="python" style="font-size: 18px;">subplot=False</pre>刪去,大家可以自己運(yùn)行一下看看plot出來(lái)的是怎么樣的呢。  
  413. <p></p>  
  414. <p><span style="font-family:MathJax_Math-italic; font-size:18px"><br>  
  415. <br>  
  416. <br>  
  417. <br>  
  418. </span></p>  
  419. <p><span style="font-family:MathJax_Math-italic; font-size:18px"><br>  
  420. </span></p>  
  421. <p><span style="font-family:MathJax_Math-italic; font-size:18px"><br>  
  422. </span></p>  
  423.               
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
CSS3的REM設(shè)置字體大小
很全的教育學(xué)習(xí)資料匯總
【學(xué)習(xí)ios之路:UI系列】(UISearchBar,UISearchDisplayController) 和UISearchController(iOS8新特性)
WordPress+Markdown+為知筆記,實(shí)現(xiàn)高質(zhì)量筆記和博客
應(yīng)用外邊距屬性制作的文字
<span style="color: rgb(0, 0, 0); font-size: 14px; font-weight: 400;">何謂“古風(fēng)圈”</span>
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服