2016-12-07 57 views
0

我正在嘗試編寫一個代碼來構建由協整對投資組合(股票價格是協整)組成的dataFrame。在這種情況下,投資組合中的股票從S & P500中選擇,它們具有相同的權重。提高Python for循環的性能?

此外,對於一些經濟問題,投資組合必須包括相同的部門。

例如: 如果一個投資組合中的股票來自[IT]和[金融]部門,第二個投資組合必須從[IT]和[金融]部門中選擇股票。

投資組合中沒有正確的股票數量,所以我正在考慮每個股票10到20個股票。但是,當考慮組合時,這是(500選擇10),所以我有一個計算時間的問題。

以下是我的代碼:

def adf(x, y, xName, yName, pvalue=0.01, beta_lower=0.5, beta_upper=1): 
    res=pd.DataFrame() 
    regress1, regress2 = pd.ols(x=x, y=y), pd.ols(x=y, y=x) 
    error1, error2 = regress1.resid, regress2.resid 
    test1, test2 = ts.adfuller(error1, 1), ts.adfuller(error2, 1) 
    if test1[1] < pvalue and test1[1] < test2[1] and\ 
    regress1.beta["x"] > beta_lower and regress1.beta["x"] < beta_upper: 
     res[(tuple(xName), tuple(yName))] = pd.Series([regress1.beta["x"], test1[1]]) 
     res = res.T 
     res.columns=["beta","pvalue"] 
     return res 
    elif test2[1] < pvalue and regress2.beta["x"] > beta_lower and\ 
    regress2.beta["x"] < beta_upper: 
     res[(tuple(yName), tuple(xName))] = pd.Series([regress2.beta["x"], test2[1]]) 
     res = res.T 
     res.columns=["beta","pvalue"] 
     return res 
    else: 
     pass 




def coint(dataFrame, nstocks = 2, pvalue=0.01, beta_lower=0.5, beta_upper=1): 
    # dataFrame = pandas_dataFrame, in this case, data['Adj Close'], row=time, col = tickers 
    # pvalue = level of significance of adf test 
    # nstocks = number of stocks considered for adf test (equal weight) 
    # if nstocks > 2, coint return cointegration between portfolios 
    # beta_lower = lower bound for slope of linear regression 
    # beta_upper = upper bound for slope of linear regression 

    a=time.time() 
    tickers = dataFrame.columns 
    tcomb = itertools.combinations(dataFrame.columns, nstocks) 
    res = pd.DataFrame() 
    sec = pd.DataFrame() 
    for pair in tcomb: 
     xName, yName = list(pair[:int(nstocks/2)]), list(pair[int(nstocks/2):]) 
     xind, yind = tickers.searchsorted(xName), tickers.searchsorted(yName) 
     xSector = list(SNP.ix[xind]["Sector"]) 
     ySector = list(SNP.ix[yind]["Sector"]) 
     if set(xSector) == set(ySector): 
      sector = [[(xSector, ySector)]] 
      x, y = dataFrame[list(xName)].sum(axis=1), dataFrame[list(yName)].sum(axis=1) 
      res1 = adf(x,y,xName,yName) 
      if res1 is None: 
       continue 
      elif res.size==0: 
       res=res1 
       sec = pd.DataFrame(sector, index = res.index, columns = ["sector"]) 
       print("added : ", pair) 
      else: 
       res=res.append(res1) 
       sec = sec.append(pd.DataFrame(sector, index = [res.index[-1]], columns = ["sector"])) 
       print("added : ", pair) 
    res = pd.concat([res,sec],axis=1) 
    res=res.sort_values(by=["pvalue"],ascending=True) 
    b=time.time() 
    print("time taken : ", b-a, "sec") 
    return res 

當nstocks = 2時,這大約需要263秒,但作爲nstocks增加,環路採用了大量的時間(超過一天)

我收集使用pandas_datareader.data 從雅虎財務「調關閉」數據和索引是時間和列是不同的代號

任何建議或幫助將受到讚賞

回答

2

我不知道你有什麼電腦,但我會建議你使用循環的某種多處理。我沒有看到你的代碼真的很難,但據我所見ressec可以被移動到共享內存對象中,並且個別循環與multiprocessing平行。

如果你有一個體面的CPU它可以提高4-6倍的性能。如果您有權訪問某種HPC,它可以創造奇蹟。

0

我建議使用探查器來縮小最耗時的調用和循環次數(循環次數是否爲預期次數?)。 Python 3只有在標準庫中探查:

https://docs.python.org/3.6/library/profile.html

您可以調用它在你的代碼:

import cProfile 
cProfile.run('your_function(inputs)') 

或者如果腳本是一個更簡單的入口點:

python -m cProfile [-o output_file] [-s sort_order] your-script.py