乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      用 Python 做股市數(shù)據(jù)分析(二)

       黑馬_御風(fēng) 2017-08-24


      編譯:伯樂在線 - 小米云豆粥

      如有好文章投稿,請(qǐng)點(diǎn)擊 → 這里了解詳情


      這篇博文是用Python分析股市數(shù)據(jù)系列兩部中的第二部,內(nèi)容基于我在猶他大學(xué) 數(shù)學(xué)3900 (數(shù)據(jù)科學(xué))的課程 (閱讀第一部分《用 Python 做股市數(shù)據(jù)分析(一)》)。在這兩篇博文中,我會(huì)討論一些基礎(chǔ)知識(shí),包括比如如何用pandas從雅虎財(cái)經(jīng)獲得數(shù)據(jù), 可視化股市數(shù)據(jù),平均數(shù)指標(biāo)的定義,設(shè)計(jì)移動(dòng)平均交匯點(diǎn)分析移動(dòng)平均線的方法,回溯測(cè)試和 基準(zhǔn)分析法。這篇文章會(huì)討論如何設(shè)計(jì)用移動(dòng)平均交匯點(diǎn)分析移動(dòng)平均線的系統(tǒng),如何做回溯測(cè)試和基準(zhǔn)分析,最后留有一些練習(xí)題以饗讀者。


      注意:本文僅代表作者本人的觀點(diǎn)。文中的內(nèi)容不應(yīng)該被當(dāng)做經(jīng)濟(jì)建議。我不對(duì)文中代碼負(fù)責(zé),取用者自己負(fù)責(zé)


      交易策略


      在特定的預(yù)期條件達(dá)成時(shí)一個(gè)開放頭寸會(huì)被關(guān)閉。多頭頭寸表示交易中需要金融商品價(jià)格上升才能產(chǎn)生盈利,空頭頭寸表示交易中需要金融商品價(jià)格下降才能產(chǎn)生盈利。在股票交易中,多頭頭寸是牛市,空頭頭寸是熊市,反之則不成立。(股票期權(quán)交易中這個(gè)非常典型)


      例如你在預(yù)計(jì)股價(jià)上漲的情況下購(gòu)入股票,并計(jì)劃在股票價(jià)格上漲高于購(gòu)入價(jià)時(shí)拋出,這就是多頭頭寸。就是說你持有一定的金融產(chǎn)品,如果它們價(jià)格上漲,你將會(huì)獲利,并且沒有上限;如果它們價(jià)格下降,你會(huì)虧損。由于股票價(jià)格不會(huì)為負(fù),虧損是有限度的。相反的,如果你預(yù)計(jì)股價(jià)會(huì)下跌,就從交易公司借貸股票然后賣出,同時(shí)期待未來股票價(jià)格下降后再低價(jià)買入還貸來賺取差額,這就是空頭股票。如果股價(jià)下跌你會(huì)獲利。空頭頭寸的獲利額度受股價(jià)所限(最佳情況就是股票變得一文不值,你不用花錢就能將它們買回來),而損失卻沒有下限,因?yàn)槟阌锌赡苄枰ê芏噱X才能買回股票。所以交換所只會(huì)在確定投資者有很好的經(jīng)濟(jì)基礎(chǔ)的情況下才會(huì)讓他們空頭借貸股票。


      所有股民都應(yīng)該決定他在每一股上可以冒多大的風(fēng)險(xiǎn)。比如有人決定無論什么情況他都不會(huì)在某一次交易中投入總額的10%去冒險(xiǎn)。同時(shí)在交易中,股民要有一個(gè)撤出策略,這是讓股民退出頭寸的各種條件。股民也可以設(shè)置一個(gè)目標(biāo),這是導(dǎo)致股民退出頭寸的最小盈利額。同樣的,股民也需要有一個(gè)他能承受的最大損失額度。當(dāng)預(yù)計(jì)損失大于可承受額度時(shí),股民應(yīng)該退出頭寸以避免更大損失(這可以通過設(shè)置停止損失委托來避免未來的損失)。


      我們要設(shè)計(jì)一個(gè)交易策略,它包含用于快速交易的交易激發(fā)信號(hào)、決定交易額度的規(guī)則和完整的退出策略。我們的目標(biāo)是設(shè)計(jì)并評(píng)估該交易策略。


      假設(shè)每次交易金額占總額的比例是固定的(10%)。同時(shí)設(shè)定在每一次交易中,如果損失超過了20%的交易值,我們就退出頭寸?,F(xiàn)在我們要決定什么時(shí)候進(jìn)入頭寸,什么時(shí)候退出以保證盈利。


      這里我要演示移動(dòng)平均交匯點(diǎn)分析移動(dòng)平均線的方法。我會(huì)使用兩條移動(dòng)平均線,一條快速的,另一條是慢速的。我們的策略是:


      • 當(dāng)快速移動(dòng)平均線和慢速移動(dòng)線交匯時(shí)開始交易

      • 當(dāng)快速移動(dòng)平均線和慢速移動(dòng)線再次交匯時(shí)停止交易


      做多是指在快速平均線上升到慢速平均線之上時(shí)開始交易,當(dāng)快速平均線下降到慢速平均線之下時(shí)停止交易。賣空正好相反,它是指在快速平均線下降到慢速平均線之下時(shí)開始交易,快速平均線上升到慢速平均線之上時(shí)停止交易。


      現(xiàn)在我們有一整套策略了。在使用它之前我們需要先做一下測(cè)試。回溯測(cè)試是一個(gè)常用的測(cè)試方法,它使用歷史數(shù)據(jù)來看策略是否會(huì)盈利。例如這張?zhí)O果公司的股票價(jià)值圖,如果20天的移動(dòng)平均是快速線,50天的移動(dòng)平均是慢速線,那么我們這個(gè)策略不是很掙錢,至少在你一直做多頭頭寸的時(shí)候。


      下面讓我們來自動(dòng)化回溯測(cè)試的過程。首先我們要識(shí)別什么時(shí)候20天平均線在50天之下,以及之上。


      apple['20d-50d'] =apple['20d'] -apple['50d']

      apple.tail()



      我們將差異的符號(hào)稱為狀態(tài)轉(zhuǎn)換。快速移動(dòng)平均線在慢速移動(dòng)平均線之上代表牛市狀態(tài);相反則為熊市。以下的代碼用于識(shí)別狀態(tài)轉(zhuǎn)換。


      # np.where() is a vectorized if-else function, where a condition is checked for each component of a vector, and the first argument passed is used when the condition holds, and the other passed if it does not

      apple['Regime'] = np.where(apple['20d-50d'] > 0, 1, 0)

      # We have 1's for bullish regimes and 0's for everything else. Below I replace bearish regimes's values with -1, and to maintain the rest of the vector, the second argument is apple['Regime']

      apple['Regime'] = np.where(apple['20d-50d'] <>0, -1, apple['Regime'])

      apple.loc['2016-01-01':'2016-08-07','Regime'].plot(ylim = (-2,2)).axhline(y = 0, color = 'black', lw = 2)


      apple['Regime'].plot(ylim =(-2,2)).axhline(y =0, color ='black', lw =2)


      apple['Regime'].value_counts()


      1    966

      -1    663

      0     50

      Name: Regime, dtype: int64


      從上面的曲線可以看到有966天蘋果公司的股票是牛市,663天是熊市,有54天沒有傾向性。(原文中牛市和熊市說反了,譯文中更正;原文數(shù)字跟代碼結(jié)果對(duì)不上,譯文按照代碼結(jié)果更正)


      交易信號(hào)出現(xiàn)在狀態(tài)轉(zhuǎn)換之時(shí)。牛市出現(xiàn)時(shí),買入信號(hào)被激活;牛市完結(jié)時(shí),賣出信號(hào)被激活。同樣的,熊市出現(xiàn)時(shí)賣出信號(hào)被激活,熊市結(jié)束時(shí),買入信號(hào)被激活。(只有在你空頭股票,或者使用一些其他的方法例如用股票期權(quán)賭市場(chǎng)的時(shí)候這種情況才對(duì)你有利)



      # To ensure that all trades close out, I temporarily change the regime of the last row to 0

      regime_orig = apple.ix[-1, 'Regime']

      apple.ix[-1, 'Regime'] = 0

      apple['Signal'] = np.sign(apple['Regime'] - apple['Regime'].shift(1))

      # Restore original regime data

      apple.ix[-1, 'Regime'] = regime_orig

      apple.tail()



      apple['Signal'].plot(ylim =(-2, 2))


      apple['Signal'].value_counts()


      0.0    1637

      -1.0      21

      1.0      20

      Name: Signal, dtype: int64


      我們會(huì)買入蘋果公司的股票20次,拋出21次 (原文數(shù)字跟代碼結(jié)果不符,譯文根據(jù)代碼結(jié)果更正)。如果我們只選了蘋果公司的股票,六年內(nèi)只有21次交易發(fā)生。如果每次多頭轉(zhuǎn)空頭的時(shí)候我們都采取行動(dòng),我們將會(huì)參與21次交易。(請(qǐng)記住交易次數(shù)不是越多越好,畢竟交易不是免費(fèi)的)


      你也許注意到了這個(gè)系統(tǒng)不是很穩(wěn)定??焖倨骄€在慢速平均線之上就激發(fā)交易,即使這個(gè)狀態(tài)只是短短一瞬,這樣會(huì)導(dǎo)致交易馬上終止(這樣并不好因?yàn)楝F(xiàn)實(shí)中每次交易都要付費(fèi),這個(gè)費(fèi)用會(huì)很快消耗掉收益)。同時(shí)所有的牛市瞬間轉(zhuǎn)為熊市,如果你允許同時(shí)押熊市和牛市,那就會(huì)出現(xiàn)每次交易結(jié)束就自動(dòng)激發(fā)另一場(chǎng)押相反方向交易的詭異情況。更好的系統(tǒng)會(huì)要求有更多的證據(jù)來證明市場(chǎng)的發(fā)展方向,但是這里我們不去追究那個(gè)細(xì)節(jié)。


      下面我們來看看每次買入賣出時(shí)候的股票價(jià)格。


      apple.loc[apple['Signal'] ==1, 'Close']


      Date

      2010-03-16    224.449997

      2010-06-18    274.070011

      2010-09-20    283.230007

      2011-05-12    346.569988

      2011-07-14    357.770004

      2011-12-28    402.640003

      2012-06-25    570.770020

      2013-05-17    433.260010

      2013-07-31    452.529984

      2013-10-16    501.110001

      2014-03-26    539.779991

      2014-04-25    571.939980

      2014-08-18     99.160004

      2014-10-28    106.739998

      2015-02-05    119.940002

      2015-04-28    130.559998

      2015-10-27    114.550003

      2016-03-11    102.260002

      2016-07-01     95.889999

      2016-07-25     97.339996

      Name: Close, dtype: float64


      apple.loc[apple['Signal'] ==-1, 'Close']


      Date

      2010-06-11    253.509995

      2010-07-22    259.020000

      2011-03-30    348.630009

      2011-03-31    348.510006

      2011-05-27    337.409992

      2011-11-17    377.410000

      2012-05-09    569.180023

      2012-10-17    644.610001

      2013-06-26    398.069992

      2013-10-03    483.409996

      2014-01-28    506.499977

      2014-04-22    531.700020

      2014-06-11     93.860001

      2014-10-17     97.669998

      2015-01-05    106.250000

      2015-04-16    126.169998

      2015-06-25    127.500000

      2015-12-18    106.029999

      2016-05-05     93.239998

      2016-07-08     96.680000

      2016-09-01    106.730003

      Name: Close, dtype: float64


      # Create a DataFrame with trades, including the price at the trade and the regime under which the trade is made.

      apple_signals = pd.concat([

              pd.DataFrame({'Price': apple.loc[apple['Signal'] == 1, 'Close'],

                           'Regime': apple.loc[apple['Signal'] == 1, 'Regime'],

                           'Signal': 'Buy'}),

              pd.DataFrame({'Price': apple.loc[apple['Signal'] == -1, 'Close'],

                           'Regime': apple.loc[apple['Signal'] == -1, 'Regime'],

                           'Signal': 'Sell'}),

          ])

      apple_signals.sort_index(inplace = True)

      apple_signals



      # Let's see the profitability of long trades

      apple_long_profits = pd.DataFrame({

              'Price': apple_signals.loc[(apple_signals['Signal'] == 'Buy') &

                                        apple_signals['Regime'] == 1, 'Price'],

              'Profit': pd.Series(apple_signals['Price'] - apple_signals['Price'].shift(1)).loc[

                  apple_signals.loc[(apple_signals['Signal'].shift(1) == 'Buy') & (apple_signals['Regime'].shift(1) == 1)].index

              ].tolist(),

              'End Date': apple_signals['Price'].loc[

                  apple_signals.loc[(apple_signals['Signal'].shift(1) == 'Buy') & (apple_signals['Regime'].shift(1) == 1)].index

              ].index

          })

      apple_long_profits



      從上表可以看出2013年5月17日那天蘋果公司股票價(jià)格大跌,我們的系統(tǒng)會(huì)表現(xiàn)很差。但是那個(gè)價(jià)格下降不是因?yàn)樘O果遇到了什么大危機(jī),而僅僅是一次分股。由于分紅不如分股那么顯著,這也許會(huì)影響系統(tǒng)行為。


      # Let's see the result over the whole period for which we have Apple data

      pandas_candlestick_ohlc(apple, stick = 45, otherseries = ['20d', '50d', '200d'])


      我們不希望我們的交易系統(tǒng)的表現(xiàn)受到分紅和分股的影響。一個(gè)解決方案是利用歷史的分紅分股數(shù)據(jù)來設(shè)計(jì)交易系統(tǒng),這些數(shù)據(jù)可以真實(shí)地反映股市的行為從而幫助我們找到最佳解決方案,但是這個(gè)方法要更復(fù)雜一些。另一個(gè)方案就是根據(jù)分紅和分股來調(diào)整股票的價(jià)格。


      雅虎財(cái)經(jīng)只提供調(diào)整之后的股票閉市價(jià)格,不過這些對(duì)于我們調(diào)整開市,高價(jià)和低價(jià)已經(jīng)足夠了。調(diào)整閉市股價(jià)是這樣實(shí)現(xiàn)的:



      讓我們回到開始,先調(diào)整股票價(jià)格,然后再來評(píng)價(jià)我們的交易系統(tǒng)。


      def ohlc_adj(dat):

          '''

          :param dat: pandas DataFrame with stock data, including 'Open', 'High', 'Low', 'Close', and 'Adj Close', with 'Adj Close' containing adjusted closing prices

          :return: pandas DataFrame with adjusted stock data

          This function adjusts stock data for splits, dividends, etc., returning a data frame with

          'Open', 'High', 'Low' and 'Close' columns. The input DataFrame is similar to that returned

          by pandas Yahoo! Finance API.

          '''

          return pd.DataFrame({'Open': dat['Open'] * dat['Adj Close'] / dat['Close'],

                             'High': dat['High'] * dat['Adj Close'] / dat['Close'],

                             'Low': dat['Low'] * dat['Adj Close'] / dat['Close'],

                             'Close': dat['Adj Close']})

      apple_adj = ohlc_adj(apple)

      # This next code repeats all the earlier analysis we did on the adjusted data

      apple_adj['20d'] = np.round(apple_adj['Close'].rolling(window = 20, center = False).mean(), 2)

      apple_adj['50d'] = np.round(apple_adj['Close'].rolling(window = 50, center = False).mean(), 2)

      apple_adj['200d'] = np.round(apple_adj['Close'].rolling(window = 200, center = False).mean(), 2)

      apple_adj['20d-50d'] = apple_adj['20d'] - apple_adj['50d']

      # np.where() is a vectorized if-else function, where a condition is checked for each component of a vector, and the first argument passed is used when the condition holds, and the other passed if it does not

      apple_adj['Regime'] = np.where(apple_adj['20d-50d'] > 0, 1, 0)

      # We have 1's for bullish regimes and 0's for everything else. Below I replace bearish regimes's values with -1, and to maintain the rest of the vector, the second argument is apple['Regime']

      apple_adj['Regime'] = np.where(apple_adj['20d-50d'] <>0, -1, apple_adj['Regime'])

      # To ensure that all trades close out, I temporarily change the regime of the last row to 0

      regime_orig = apple_adj.ix[-1, 'Regime']

      apple_adj.ix[-1, 'Regime'] = 0

      apple_adj['Signal'] = np.sign(apple_adj['Regime'] - apple_adj['Regime'].shift(1))

      # Restore original regime data

      apple_adj.ix[-1, 'Regime'] = regime_orig

      # Create a DataFrame with trades, including the price at the trade and the regime under which the trade is made.

      apple_adj_signals = pd.concat([

              pd.DataFrame({'Price': apple_adj.loc[apple_adj['Signal'] == 1, 'Close'],

                           'Regime': apple_adj.loc[apple_adj['Signal'] == 1, 'Regime'],

                           'Signal': 'Buy'}),

              pd.DataFrame({'Price': apple_adj.loc[apple_adj['Signal'] == -1, 'Close'],

                           'Regime': apple_adj.loc[apple_adj['Signal'] == -1, 'Regime'],

                           'Signal': 'Sell'}),

          ])

      apple_adj_signals.sort_index(inplace = True)

      apple_adj_long_profits = pd.DataFrame({

              'Price': apple_adj_signals.loc[(apple_adj_signals['Signal'] == 'Buy') &

                                        apple_adj_signals['Regime'] == 1, 'Price'],

              'Profit': pd.Series(apple_adj_signals['Price'] - apple_adj_signals['Price'].shift(1)).loc[

                  apple_adj_signals.loc[(apple_adj_signals['Signal'].shift(1) == 'Buy') & (apple_adj_signals['Regime'].shift(1) == 1)].index

              ].tolist(),

              'End Date': apple_adj_signals['Price'].loc[

                  apple_adj_signals.loc[(apple_adj_signals['Signal'].shift(1) == 'Buy') & (apple_adj_signals['Regime'].shift(1) == 1)].index

              ].index

          })

      pandas_candlestick_ohlc(apple_adj, stick = 45, otherseries = ['20d', '50d', '200d'])



      apple_adj_long_profits



      可以看到根據(jù)分紅和分股調(diào)整之后的價(jià)格圖變得很不一樣了。之后的分析我們都會(huì)用到這個(gè)調(diào)整之后的數(shù)據(jù)。


      假設(shè)我們?cè)诠墒杏幸话偃f,讓我們來看看根據(jù)下面的條件,我們的系統(tǒng)會(huì)如何反應(yīng):


      • 每次用總額的10%來進(jìn)行交易

      • 退出頭寸如果虧損達(dá)到了交易額的20%


      模擬的時(shí)候要記?。?/p>


      • 每次交易有100支股票

      • 我們的避損規(guī)則是當(dāng)股票價(jià)格下降到一定數(shù)值時(shí)就拋出。我們需要檢查這段時(shí)間內(nèi)的低價(jià)是否低到可以出發(fā)避損規(guī)則?,F(xiàn)實(shí)中除非我們買入看空期權(quán),我們無法保證我們能以設(shè)定低值價(jià)格賣出股票。這里為了簡(jiǎn)潔我們將設(shè)定值作為賣出值。

      • 每次交易都會(huì)付給中介一定的傭金。這里我們沒有考慮這個(gè)。


      下面的代碼演示了如何實(shí)現(xiàn)回溯測(cè)試:


      # We need to get the low of the price during each trade.

      tradeperiods =pd.DataFrame({'Start': apple_adj_long_profits.index,

                                  'End': apple_adj_long_profits['End Date']})

      apple_adj_long_profits['Low'] =tradeperiods.apply(lambdax: min(apple_adj.loc[x['Start']:x['End'], 'Low']), axis =1)

      apple_adj_long_profits



      # Now we have all the information needed to simulate this strategy in apple_adj_long_profits

      cash =1000000

      apple_backtest =pd.DataFrame({'Start Port. Value': [],

                               'End Port. Value': [],

                               'End Date': [],

                               'Shares': [],

                               'Share Price': [],

                               'Trade Value': [],

                               'Profit per Share': [],

                               'Total Profit': [],

                               'Stop-Loss Triggered': []})

      port_value =.1# Max proportion of portfolio bet on any trade

      batch =100# Number of shares bought per batch

      stoploss =.2# % of trade loss that would trigger a stoploss

      forindex, row inapple_adj_long_profits.iterrows():

          batches =np.floor(cash *port_value) //np.ceil(batch *row['Price']) # Maximum number of batches of stocks invested in

          trade_val =batches *batch *row['Price'] # How much money is put on the line with each trade

          ifrow['Low'] <>(1-stoploss) *row['Price']:   # Account for the stop-loss

              share_profit =np.round((1-stoploss) *row['Price'], 2)

              stop_trig =True

          else:

              share_profit =row['Profit']

              stop_trig =False

          profit =share_profit *batches *batch # Compute profits

          # Add a row to the backtest data frame containing the results of the trade

          apple_backtest =apple_backtest.append(pd.DataFrame({

                      'Start Port. Value': cash,

                      'End Port. Value': cash +profit,

                      'End Date': row['End Date'],

                      'Shares': batch *batches,

                      'Share Price': row['Price'],

                      'Trade Value': trade_val,

                      'Profit per Share': share_profit,

                      'Total Profit': profit,

                      'Stop-Loss Triggered': stop_trig

                  }, index =[index]))

          cash =max(0, cash +profit)

      apple_backtest



      apple_backtest['End Port. Value'].plot()



      我們的財(cái)產(chǎn)總額六年增加了10%。考慮到每次交易額只有總額的10%,這個(gè)成績(jī)不算差。


      同時(shí)我們也注意到這個(gè)策略并沒有引發(fā)停止損失委托。這意味著我們可以不需要它么?這個(gè)難說。畢竟這個(gè)激發(fā)事件完全取決于我們的設(shè)定值。


      停止損失委托是被自動(dòng)激活的,它并不會(huì)考慮股市整體走勢(shì)。也就是說不論是股市真正的走低還是暫時(shí)的波動(dòng)都會(huì)激發(fā)停止損失委托。而后者是我們需要注意的因?yàn)樵诂F(xiàn)實(shí)中,由價(jià)格波動(dòng)激發(fā)停止損失委托不僅讓你支出一筆交易費(fèi)用,同時(shí)還無法保證最終的賣出價(jià)格是你設(shè)定的價(jià)格。


      下面的鏈接分別支持和反對(duì)使用停止損失委托,但是之后的內(nèi)容我不會(huì)要求我們的回溯測(cè)試系統(tǒng)使用它。這樣可以簡(jiǎn)化系統(tǒng),但不是很符合實(shí)際(我相信工業(yè)系統(tǒng)應(yīng)該有停止損失委托)。


      現(xiàn)實(shí)中我們不會(huì)只用總額的10%去押一支股票而是投資多種股票。在給定的時(shí)間可以跟不同公司同時(shí)交易,而且大部分財(cái)產(chǎn)應(yīng)該在股票上,而不是現(xiàn)金?,F(xiàn)在我們開始投資多支股票 (原文是stops,感覺是typo,譯文按照stocks翻譯),并且在兩條移動(dòng)平均線交叉的時(shí)候退市(不使用止損)。我們需要改變回溯測(cè)試的代碼。我們會(huì)用一個(gè)pandas的DataFrame來存儲(chǔ)所有股票的買賣,上一層的循環(huán)也需要記錄更多的信息。


      下面的函數(shù)用于產(chǎn)生買賣訂單,以及另一回溯測(cè)試函數(shù)。


      代碼過長(zhǎng),微信閱讀體驗(yàn)不好,可點(diǎn)擊「閱讀原文」在網(wǎng)頁版查看


      signals =ma_crossover_orders([('AAPL', ohlc_adj(apple)),

                                    ('MSFT',  ohlc_adj(microsoft)),

                                    ('GOOG',  ohlc_adj(google)),

                                    ('FB',    ohlc_adj(facebook)),

                                    ('TWTR',  ohlc_adj(twitter)),

                                    ('NFLX',  ohlc_adj(netflix)),

                                    ('AMZN',  ohlc_adj(amazon)),

                                    ('YHOO',  ohlc_adj(yahoo)),

                                    ('SNY',   ohlc_adj(yahoo)),

                                    ('NTDOY', ohlc_adj(nintendo)),

                                    ('IBM',   ohlc_adj(ibm)),

                                    ('HPQ',   ohlc_adj(hp))],

                                  fast =20, slow =50)

      signals


      475 rows × 3 columns


      bk =backtest(signals, 1000000)

      bk



      475 rows × 9 columns


      bk['Portfolio Value'].groupby(level =0).apply(lambdax: x[-1]).plot()


      更為現(xiàn)實(shí)的投資組合可以投資任何12支股票而達(dá)到100%的收益。這個(gè)看上去不錯(cuò),但是我們可以做得更好。


      基準(zhǔn)分析法


      基準(zhǔn)分析法可以分析交易策略效率的好壞。所謂基準(zhǔn)分析,就是將策略和其他(著名)策略進(jìn)行比較從而評(píng)價(jià)該策略的表現(xiàn)好壞。


      每次你評(píng)價(jià)交易系統(tǒng)的時(shí)候,都要跟買入持有策略(SPY)進(jìn)行比較。除了一些信托基金和少數(shù)投資經(jīng)理沒有使用它,該策略在大多時(shí)候都是無敵的。有效市場(chǎng)假說強(qiáng)調(diào)沒有人能戰(zhàn)勝股票市場(chǎng),所以每個(gè)人都應(yīng)該購(gòu)入指數(shù)基金,因?yàn)樗芊磻?yīng)整個(gè)市場(chǎng)的構(gòu)成。SPY是一個(gè)交易型開放式指數(shù)基金(一種可以像股票一樣交易的信托基金),它的價(jià)格有效反映了S&P 500中的股票價(jià)格。買入并持有SPY,說明你可以有效地匹配市場(chǎng)回報(bào)率而不是戰(zhàn)勝它。


      下面是SPY的數(shù)據(jù),讓我們看看簡(jiǎn)單買入持有SPY能得到的回報(bào):


      spyder =web.DataReader('SPY', 'yahoo', start, end)

      spyder.iloc[[0,-1],:]



      batches =1000000//np.ceil(100*spyder.ix[0,'Adj Close']) # Maximum number of batches of stocks invested in

      trade_val =batches *batch *spyder.ix[0,'Adj Close'] # How much money is used to buy SPY

      final_val =batches *batch *spyder.ix[-1,'Adj Close'] +(1000000-trade_val) # Final value of the portfolio

      final_val


      2180977.0


      # We see that the buy-and-hold strategy beats the strategy we developed earlier. I would also like to see a plot.

      ax_bench =(spyder['Adj Close'] /spyder.ix[0, 'Adj Close']).plot(label ='SPY')

      ax_bench =(bk['Portfolio Value'].groupby(level =0).apply(lambdax: x[-1]) /1000000).plot(ax =ax_bench, label ='Portfolio')

      ax_bench.legend(ax_bench.get_lines(), [l.get_label() forl inax_bench.get_lines()], loc ='best')

      ax_bench


      買入持有SPY比我們當(dāng)前的交易系統(tǒng)好——我們的系統(tǒng)還沒有考慮不菲的交易費(fèi)用??紤]到機(jī)會(huì)成本和該策略的消耗,我們不應(yīng)該用它。


      怎樣才能改進(jìn)我們的系統(tǒng)呢?對(duì)于初學(xué)者來盡量多樣化是一個(gè)選擇。目前我們所有的股票都來自技術(shù)公司,這意味著技術(shù)型公司的不景氣會(huì)反映在我們的投資組合上。我們應(yīng)該設(shè)計(jì)一個(gè)可以利用空頭頭寸和熊市的系統(tǒng),這樣不管市場(chǎng)如何變動(dòng),我們都可以盈利。我們也可以尋求更好的方法預(yù)測(cè)股票的最高期望價(jià)格。但是不論如何我們都需要做得比SPY更好,不然由于我們的系統(tǒng)會(huì)自帶機(jī)會(huì)成本,是沒用的。


      其他的基準(zhǔn)策略也是存在的。如果我們的系統(tǒng)比“買入持有SPY”更好,我們可以進(jìn)一步跟其他的系統(tǒng)比較,例如:



      (我最初在這里接觸到這些策略)基本準(zhǔn)則仍然是:不要使用一個(gè)復(fù)雜的,包含大量交易的系統(tǒng)如果它贏不了一個(gè)簡(jiǎn)單的交易不頻繁的指數(shù)基金模型。(事實(shí)上這個(gè)標(biāo)準(zhǔn)挺難實(shí)現(xiàn)的)


      最后要強(qiáng)調(diào)的是,假設(shè)你的交易系統(tǒng)在回溯測(cè)試中打敗了所有的基準(zhǔn)系統(tǒng),也不意味著它能夠準(zhǔn)確地預(yù)測(cè)未來。因?yàn)榛厮轀y(cè)試容易過擬合,它不能用于預(yù)測(cè)未來。


      結(jié)論


      雖然講座最后的結(jié)論不是那么樂觀,但記住有效市場(chǎng)理論也有缺陷。我個(gè)人的觀點(diǎn)是當(dāng)交易更多依賴于算法的時(shí)候,就更難戰(zhàn)勝市場(chǎng)。有一個(gè)說法是:信托基金都不太可能戰(zhàn)勝市場(chǎng),你的系統(tǒng)能戰(zhàn)勝市場(chǎng)僅僅是一個(gè)可能性而已。(當(dāng)然信托基金表現(xiàn)很差的原因是收費(fèi)太高,而指數(shù)基金不存在這個(gè)問題。)


      本講座只簡(jiǎn)單地說明了一種基于移動(dòng)平均的交易策略。還有許多別的交易策略這里并沒有提到。而且我們也沒有深入探討空頭股票和貨幣交易。特別是股票期權(quán)有很多東西可以講,它也提供了不同的方法來預(yù)測(cè)股票的走向。你可以在Derivatives Analytics with Python: Data Analysis, Models, Simulation, Calibration and Hedging書中讀到更多的相關(guān)內(nèi)容。(猶他大學(xué)的圖書館有這本書)


      另一個(gè)資源是O’Reilly出的Python for Finance,猶他大學(xué)的圖書館里也有。


      記住在股票里面虧錢是很正常的,同樣股市也能提供其他方法無法提供的高回報(bào),每一個(gè)投資策略都應(yīng)該是經(jīng)過深思熟慮的。這個(gè)講座旨在拋磚引玉,希望同學(xué)們自己進(jìn)一步探討這個(gè)話題。


      作業(yè)


      問題1


      建立一個(gè)基于移動(dòng)平均的交易系統(tǒng)(不需要止損條件)。選擇15支2010年1月1日之前上市的股票,利用回溯測(cè)試檢驗(yàn)?zāi)愕?系統(tǒng),并且SPY基準(zhǔn)作比較,你的系統(tǒng)能戰(zhàn)勝市場(chǎng)嗎?


      問題2


      在現(xiàn)實(shí)中每一筆交易都要支付一筆傭金。弄明白如何計(jì)算傭金,然后修改你的backtes()函數(shù),使之能夠計(jì)算不同的傭金模式(固定費(fèi)用,按比例收費(fèi)等等)。


      我們現(xiàn)在的移動(dòng)平均交匯點(diǎn)分析系統(tǒng)在兩條平均線交叉的時(shí)候觸發(fā)交易。修改系統(tǒng)令其更準(zhǔn)確:



      當(dāng)你完成修改之后,重復(fù)問題1,使用一個(gè)真實(shí)的傭金策略(從交易所查)來模擬你的系統(tǒng),同時(shí)要求移動(dòng)平均差異達(dá)到一定的移動(dòng)標(biāo)準(zhǔn)差再激發(fā)交易。


      問題3


      我們的交易系統(tǒng)無法處理空頭股票??疹^買賣的復(fù)雜性在于損失是沒有下限的(多頭頭寸的最大損失等于購(gòu)入股票的總價(jià)格)。學(xué)習(xí)如何處理空頭頭寸,然后修改backtest()使其能夠處理空頭交易。思考要如何實(shí)現(xiàn)空頭交易,包括允許多少空頭交易?在進(jìn)行其他交易的時(shí)候如何處理空頭交易?提示:空頭交易的量在函數(shù)中可以用一個(gè)負(fù)數(shù)來表示。


      完成之后重復(fù)問題1,也可以同時(shí)考慮問題2中提到的因素。


        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多