交易

基於協整的配對交易-權益線

  • August 5, 2015

我正在我的大學準備一個項目,我必須使用兩隻股票之間的協整來製定一個簡單的配對交易策略。

我被困在淨值線計算上。我已經準備了開盤和收盤信號,但仍然需要準備一張**淨值線圖,**但我不知道如何計算它。

有一些細節:

  • 做多被低估的股票,做空被高估的股票

  • 允許無邊界賣空,押金為賣空價值的100%

  • 開倉時,我們假設空頭頭寸和多頭頭寸的份額相等

-開/關信號由收盤價定義,倉位由次日開盤價****開/平

-交易費用為頭寸價值的0.1%(開盤和收盤時)

是的,即使使用 pandas 之類的好工具,它也可以非常複雜。但基本思想是找到頭寸進入和退出以獲得現金流。

這是我從生成的信號中獲取所有這些東西的程式碼(在我的回測器中,信號是每個時刻投資組合中 2 支股票的一部分)。我希望我在這裡找到了所有的錯誤,但沒有保證。 Total_invested變數用於僅使用初始資本計算投資組合中的股份總數。

實際上,這段程式碼是我將在幾個月內開源的回測引擎的一部分。它還處理點差和固定佣金,因此您可以跳過這一部分。這將需要適應您的條件,但希望有所幫助!

另請查看Mike Halls-Moore 的文章。這個網站對我幫助很大!

def get_portfolio(self, signals, prices):
   time_index = prices.index
   end = time_index[-1]
   # Assets prices
   x_prices = prices[self.sym1]
   y_prices = prices[self.sym2]
   # Assets weights in portfolio
   x_weights = signals.map(lambda sig:sig[self.sym1])
   y_weights = signals.map(lambda sig:sig[self.sym2])
   # Total number of invested shares
   total_invested = pd.Series(index = signals.index)
   # Need trade enters to calculate portfolio size
   enter_points = x_weights.diff().fillna(0)!=0
   # Index magic here:
   # We need to delete position exits, we suppose there are separate enters/exits
   enter_points[enter_points[enter_points].index[1::2]] = False
   # capital = w₁⋅total⋅p₁ + w₂⋅total⋅p₂ (cover position)
   total_invested[enter_points] = (self.initial_capital
       /(x_weights.abs()[enter_points]*x_prices[enter_points]
       + y_weights.abs()[enter_points]*y_prices[enter_points]))
   # Zero for right initial open and final close
   total_invested.iloc[0] = 0; total_invested.iloc[-1] = 0;
   total_invested.fillna(method='ffill', inplace=True)
   # Positions rounded to lot sizes
   x_positions = (total_invested*x_weights//self.lot1*self.lot1).fillna(0)
   y_positions = (total_invested*y_weights//self.lot2*self.lot2).fillna(0)
   long_pos = x_positions.copy(); long_pos[long_pos<0] = 0
   short_pos = x_positions.copy(); short_pos[short_pos>0] = 0
   x_pos_diff = x_positions.diff().fillna(0)
   y_pos_diff = y_positions.diff().fillna(0)

   # Tribute to the market-makers: spread
   # Binary divide because we count twice: enter & exit
   tribute = (abs(x_pos_diff)*self.spread1 + abs(y_pos_diff)*self.spread2)/2
   # Cashflow & Turnover: not the same!
   cashflow = -x_pos_diff*x_prices - y_pos_diff*y_prices
   turnover = abs(x_pos_diff)*x_prices + abs(y_pos_diff)*y_prices
   # Commission from turnover
   commission = turnover * self.commission
   commission[cashflow!=0] += self.fixed_commission
   portfolio = pd.DataFrame(index=time_index, columns=['EQ','holdings',
       'cash','cashflow','long_trades','short_trades',
       'x_positions','y_positions'])
   # Value of shares
   portfolio['holdings'] = x_positions*x_prices + y_positions*y_prices
   # Value of cash, paid commission on each transaction
   portfolio['cash'] = self.initial_capital + (cashflow
       - commission - tribute).cumsum()
   # Equity is the sum of both
   portfolio['EQ'] = portfolio['cash'] + portfolio['holdings']
   portfolio['turnover'] = turnover

   # Time points of trades
   portfolio['long_trades'] = long_pos.diff().fillna(0)
   portfolio['short_trades'] = short_pos.diff().fillna(0)

   portfolio['x_positions'] = x_positions
   portfolio['y_positions'] = y_positions
   return portfolio

引用自:https://quant.stackexchange.com/questions/19167