Ошибка значения: ошибка математической области при расчете отрицательного IRR

#python #math #scipy

Вопрос:

У меня есть приведенный ниже воспроизводимый случай, который выдает мне ошибку:

 return reduce(lambda a, b: a   b, map(lambda x: x[1] / math.pow(1   i, x[0]),zip(dcfs, values)))
 

Ошибка значения: ошибка математического домена

Это уже очень упрощенный случай. Если я инвестирую 100 долларов и получу обратно только 50 долларов почти через год(0,99), что может произойти в реальном мире, скажем, я внесу деньги 1 января и получу деньги обратно 28 декабря. IRR должен составлять -50%.

Я вижу, что есть два способа исправить нижеприведенное:

  1. Измените dcfs на [0,1], тогда это будет работать
  2. Измените начальное предположение на -0,05

Однако, когда у меня более сложный случай с отрицательной IRR, работает любой из вышеперечисленных способов (я не могу изменить все денежные потоки, чтобы они были на точный конец года, и даже если я изменю первоначальное предположение на -0,05, это все равно нарушит ошибку). Кто-нибудь может помочь?

 import math
from scipy.optimize import fsolve
from functools import reduce

dcfs = [0,0.99]
values = [-100,50]
initialGuess = 0.05

def npvFromIrr(i):
    return reduce(lambda a, b: a   b, map(lambda x: x[1] / math.pow(1   i, x[0]),zip(dcfs, values)))

sol, info, ier, msg = fsolve(npvFromIrr, initialGuess, full_output=True)
print(sol)
 

Комментарии:

1. Он ValueError: math domain error возникает, когда вы выполняете математическую функцию над отрицательным или нулевым числом, которое не может быть вычислено. Чтобы устранить эту ошибку, убедитесь, что вы используете допустимое число для используемой математической функции.

2. Ошибка в вашем коде вызвана -100 входом values = [-100,50] . Код работает хорошо, если вы замените его положительным числом. Чего именно вы пытаетесь здесь достичь? `

3. это для расчета IRR, отрицательный означает исходящий денежный поток, а положительный означает входящий денежный поток. отрицательное число не является проблемой, как вы можете видеть, если я изменю dcf на [0,1], то это сработает. проблема в fsolve, он должен легко найти ответ -0,5…

Ответ №1:

В качестве обходного пути вы можете преобразовать периоды движения денежных средств в дни вместо лет (и при необходимости скорректировать первоначальное предположение).

 dcfs = [_*365.25 for _ in dcfs]
initialGuess = -0.05/365.25

sol, info, ier, msg = fsolve(npvFromIrr, initialGuess, full_output=True)
 

Это дает значение массива([-0.00191507]), которое вы можете преобразовать обратно в годовой курс,

 annual_rate = math.pow((1   sol[0]), 365.35) - 1
# -0.5035836839765218
 

В качестве альтернативы вы можете посмотреть, могут ли некоторые другие решатели внутри scipy.optimize решить эту проблему, не пытаясь увеличить отрицательное число до действительного числа