2016-12-07 134 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