Python - более быстрая альтернатива циклам for - PullRequest
0 голосов
/ 12 сентября 2018

Я пытаюсь построить модель биномиальной решетки в Python.Идея состоит в том, что существует несколько биномиальных решеток, и в зависимости от значения в конкретной решетке ряд операций выполняется в других решетках.Эти операции аналогичны «модели определения цены опциона» (ссылка на модели Блэка-Шоулза) в том смысле, что вычисления начинаются с последнего столбца решетки, и они повторяются в предыдущем столбце по одному шагу за раз.Например, если у меня есть биноминальная решетка с n столбцами, 1. Я вычисляю значения в n-м столбце для одной или нескольких решеток.2. На основе этих значений я обновляю значения в (n-1) -ом столбце в той же или других биномиальных решетках. 3. Этот процесс продолжается до тех пор, пока я не достигну первого столбца.

Короче говоря, я не могу обработатьвычисления для всей решетки одновременно, так как значение в каждом столбце зависит от значений в следующем столбце и т. д.

С точки зрения кодирования, я написал функцию, которая выполняет вычисления для определенного столбца в решеткеи выводит числа, которые используются в качестве входных данных для следующего столбца в процессе.

def column_calc(StockPrices_col, ConvertProb_col, y_col, ContinuationValue_col, ConversionValue_col, coupon_dates_index, convert_dates_index ,
                call_dates_index, put_dates_index, ConvertProb_col_new, ContinuationValue_col_new, y_col_new,tau, r, cs, dt,call_trigger,
                putPrice,callPrice):

for k in range(1, n+1-tau):

     ConvertProb_col_new[n-k] = 0.5*(ConvertProb_col[n-1-k] + ConvertProb_col[n-k])

     y_col_new[n-k] =  ConvertProb_col_new[n-k]*r + (1- ConvertProb_col_new[n-k]) *(r + cs) 

     # Calculate the holding value
     ContinuationValue_col_new[n-k] = 0.5*(ContinuationValue_col[n-1-k]/(1+y_col[n-1-k]*dt) +  ContinuationValue_col[n-k]/(1+y_col[n-k]*dt))

     # Coupon payment date
     if np.isin(n-1-tau, coupon_dates_index) == True:

         ContinuationValue_col_new[n-k] = ContinuationValue_col_new[n-k] + Principal*(1/2*c);

     # check put/call schedule
     callflag = (np.isin(n-1-tau, call_dates_index)) & (StockPrices_col[n-k] >= call_trigger)
     putflag = np.isin(n-1-tau, put_dates_index)
     convertflag = np.isin(n-1-tau, convert_dates_index)

     # if t is in call date
     if (np.isin(n-1-tau, call_dates_index) == True) & (StockPrices_col[n-k] >= call_trigger):

         node_val = max([putPrice * putflag, ConversionValue_col[n-k] * convertflag, min(callPrice, ContinuationValue_col_new[n-k])] )
     # if t is not call date    
     else:

         node_val = max([putPrice * putflag, ConversionValue_col[n-k] * convertflag, ContinuationValue_col_new[n-k]] )


     # 1. if Conversion happens
     if node_val == ConversionValue_col[n-k]*convertflag:
         ContinuationValue_col_new[n-k] = node_val
         ConvertProb_col_new[n-k] = 1

     # 2. if put happens
     elif node_val == putPrice*putflag:
         ContinuationValue_col_new[n-k] = node_val
         ConvertProb_col_new[n-k] = 0

     # 3. if call happens
     elif node_val == callPrice*callflag:
         ContinuationValue_col_new[n-k] = node_val
         ConvertProb_col_new[n-k] = 0

     else:
         ContinuationValue_col_new[n-k] = node_val


return ConvertProb_col_new, ContinuationValue_col_new, y_col_new

Я вызываю эту функцию для каждого столбца в решетке через цикл for.По сути, я запускаю вложенный цикл for для всех вычислений.

Моя проблема - это очень медленно.Функция не занимает много времени.но вторая итерация, в которой я вызываю функцию через цикл for, занимает очень много времени (в среднем время, в течение которого функция будет повторяться ниже, поскольку цикл близок к 1000 или 1500). Для запуска полной модели требуется почти 2,5 минуты.очень медленный со стандартной точки зрения моделирования.Как упоминалось выше, большую часть времени занимает вложенный цикл, показанный ниже:

temp_mat = np.empty((n,3))*(np.nan)
temp_mat[:,0] = ConvertProb[:, n-1]
temp_mat[:,1] = ContinuationValue[:, n-1]
temp_mat[:,2] = y[:, n-1]

ConvertProb_col_new = np.empty((n,1))*(np.nan)
ContinuationValue_col_new = np.empty((n,1))*(np.nan)
y_col_new = np.empty((n,1))*(np.nan)


for tau in range(1,n):    

    ConvertProb_col = temp_mat[:,0]
    ContinuationValue_col = temp_mat[:,1]
    y_col = temp_mat[:,2]

    ConversionValue_col = ConversionValue[:, n-tau-1]
    StockPrices_col = StockPrices[:, n-tau-1]



    out = column_calc(StockPrices_col, ConvertProb_col, y_col, ContinuationValue_col, ConversionValue_col, coupon_dates_index, convert_dates_index ,call_dates_index, put_dates_index, ConvertProb_col_new, ContinuationValue_col_new, y_col_new, tau, r, cs, dt,call_trigger,putPrice,callPrice)

    temp_mat[:,0] = out[0].reshape(np.shape(out[0])[0],)
    temp_mat[:,1] = out[1].reshape(np.shape(out[1])[0],)
    temp_mat[:,2] = out[2].reshape(np.shape(out[2])[0],)

#Final value
print(temp_mat[-1][1])

Есть ли способ уменьшить время, затрачиваемое во вложенном цикле for?или есть ли альтернатива, которую я могу использовать вместо вложенного цикла for.Пожалуйста, дайте мне знать.Большое спасибо !!!

...