我正在尝试计算给定 IRR 的盈亏平衡价格,但陷入范围的根求解器中。一个简单的例子:
n = 10. # no of periods
years = np.arange(n) + 1
initial_investment = [-1000]
quantity_sold = np.full(n, 20)
price = np.full(n, 20)
revenue = quantity_sold * price
expense = np.full(n, 50)
cash_flow = np.concatenate([initial_investment, revenue - expense])
这样我们就可以计算 IRR 并使用
numpy_financial
验证 NPV 是否为 0:
npf.irr(cash_flow), npf.npv(0.32975, cash_flow)
# (0.32975, 0.008)
我想做的恰恰相反:假设 IRR 为 40%,盈亏平衡价格所需的现金流量是多少(NPV = 0)。
我正在使用
scipy.optimize.root
但对于如何构建它却迷失了方向。我可以反转 npf.npv
来获得 IRR:
optimize.root(npf.npv, args=cash_flow, x0=0.5)
但 cash_flow 是一个数组,甚至允许该数组的值保持不变。给定 IRR,我该如何求解
cash_flow
?
这当然是可能的,但除非你进一步限制问题(例如通过固定初始投资),否则意义不大。否则,系统是欠定的:
import numpy as np
import scipy.optimize
n = 10 # no of periods
years = np.arange(1, 1 + n)
initial_investment = -1000
quantity_sold = np.full(shape=n, fill_value=20)
price = np.full(shape=n, fill_value=20.)
revenue = quantity_sold * price
expense = np.full(shape=n, fill_value=50.)
cash_flow = np.concatenate(((initial_investment,), revenue - expense))
# Forward calculation of IRR, shown without use of `npf`
def npv(rate: float) -> float:
return (cash_flow / (1 + rate)**np.arange(cash_flow.size)).sum()
result = scipy.optimize.root_scalar(f=npv, x0=0.5, bracket=(0, 1))
assert result.converged
irr = result.root
assert np.isclose(0.32975, irr, atol=0, rtol=1e-5)
np.isclose(0, npv(irr), rtol=0, atol=1e-12)
print('irr =', irr)
# Back-calculation of cash flow, again without `npf`
def npv_from_series(cash_flow: np.ndarray) -> float:
return (cash_flow / (1 + irr)**np.arange(cash_flow.size)).sum()
result = scipy.optimize.least_squares(
fun=npv_from_series,
x0=np.concatenate(((-1,), np.ones(n))),
bounds=scipy.optimize.Bounds(
lb=np.concatenate(((-np.inf,), np.zeros(n))),
ub=np.concatenate(((0,), np.full(shape=n, fill_value=np.inf))),
),
)
assert result.success
cash_flow = result.x
print(f'Cash flow for IRR of {irr:.1%}:')
print(cash_flow)
print(f'NPV error: {result.fun[0]:.2e}')
irr = 0.3297531334357468
Cash flow for IRR of 33.0%:
[-3.32043506 0.99765753 1.06177051 1.11807742 1.17345293 1.23855932
1.33771217 1.5628038 3.13235102 0.0914474 0.674785 ]
NPV error: 1.80e-16