首页 > 编程问答 >Python 上债券的内部收益率

Python 上债券的内部收益率

时间:2024-07-23 15:54:46浏览次数:6  
标签:python finance irr

在Excel中,有一个公式(IRR.Payment: https://support.microsoft.com/fr-fr/office/fonction-tri-paiements-de1242ec-6477-445b-b11b-a303ad9adc9d )计算债券的 IRR。我正在尝试在 python 算法上重现这一点,以便能够在我的代码中计算它。我在网上找到了这段代码:

import numpy as np
import matplotlib.pyplot as plt
from scipy import optimize

def tri(cashflows, periods_per_year):
    ##:param periods_per_year: number of periods per year (1 for annualy, 2 for half-yearly, 4 for quarterly)
 
    def npv(rate):
        npv = 0
        for cf in cashflows:
            npv += cf / (1 + rate / periods_per_year) ** (cashflows.index(cf) / (periods_per_year) + 1)
        return npv
 
    def f(rate):
        return npv(rate)
 
    def df(rate):
        d = 0
        for i, cf in enumerate(cashflows):
            d -= (i + 1) * cf / (1 + rate / periods_per_year) ** ((i + 1) / periods_per_year + 1)
        return d
 
    guess = 0.1  # Valeur initiale pour la recherche du TRI
    tri_value = optimize.newton(f, guess, fprime=df) * periods_per_year * 100
 
    return tri_value
 
# Example n°1
cashflows = [-1000, 50, 50, 50, 50, 1050]  
periods_per_year1 = 1  
print("TRI :", tri(cashflows, periods_per_year), "%")

#Example n°2
cashflows2 = [-500,150,150,150,150]
print("TRI 2 :", tri(cashflows2, periods_per_year), "%")

#Example n°3
cashflows3= [-10000,2750,4250,3250,2750]
periods_per_year3 = 2
print("TRI 3 :", tri(cashflows3, periods_per_year3), "%")

但是,通过进行一些测试来检查一切是否正常工作,我发现了差异。这是我在 excel 上的示例和结果的屏幕截图 excel 上的示例

示例 n°1 在我的 python 代码中给出了 5.3%,在 excel 上给出了 4.99% 示例 n°2 在我的 python 代码中给出 19.99%,在 excel 中给出 7.7% 示例 #3 在 python 中失败并出现以下错误: Traceback(最近一次调用最后一次): 文件“/tmp/main.py”,第 31 行,位于 导入用户代码 文件“/tmp/user_code.py”,第 45 行,位于 print("TRI 3 :", tri(cashflows3,​​ period_per_year3), "%") ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 文件“/tmp/user_code.py”,第 30 行,三 tri_value = optimize.newton(f, 猜测, fprime=df) * period_per_year * 100 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 文件“/usr/local/lib/python3.11/dist-packages/scipy/optimize/_zeros_py.py”,第 391 行,牛顿 引发运行时错误(消息) RuntimeError: 50 次迭代后无法收敛,值为 0.6855681985991275。

有人可以向我解释一下为什么存在这些差异以及如何确保代码不会出现运行时错误吗?

我没有任何线索做什么


让我们来分解一下这些差异以及如何改进你的 Python 代码。

1. 差异和运行时错误

你所看到的差异主要源于 IRR 计算的本质,以及你在 Python 代码和 Excel 的 XIRR 函数中处理此问题的方式。

  • IRR 的迭代性质: IRR 的计算不是一个直接的公式。它是一个迭代过程,从一个初始猜测开始,并反复细化,直到找到一个使净现值 (NPV) 大致等于零的折现率。此迭代过程中的细微差异会导致结果略有不同。

  • 初始猜测和收敛: 你的 Python 代码使用 scipy.optimize.newton 函数,它需要一个初始猜测(你在本例中将其设置为 0.1)。牛顿法(一种用于求解方程的根的算法)可能对初始猜测很敏感。如果初始猜测距离实际根太远,它可能会无法收敛,或者可能收敛到不同的根,从而导致你看到的运行时错误或不准确的结果。

  • Excel 的 XIRR: Excel 的 XIRR 函数也使用迭代方法,但它可能有不同的收敛标准或用于初始猜测的内部机制,这会导致结果略有不同。

2. 改进你的 Python 代码

以下是改进 Python 代码的一些方法:

  • 更好的初始猜测: 不要对所有情况都使用固定的初始猜测 (0.1),而是尝试找到一个更接近实际 IRR 的更好的初始猜测。一种方法是使用一个范围内的多个初始猜测,或使用其他数值方法来获得更接近的初始猜测。

  • 收敛容差: 你可以调整 scipy.optimize.newton 函数的收敛容差,使其对结果更严格或更宽松。这可以通过设置 tol 参数来完成。

  • 替代求解器: 除了 scipy.optimize.newton 之外,SciPy 还提供了其他求根算法,例如 scipy.optimize.brentq scipy.optimize.fsolve 。这些求解器可能更稳健,并且不太可能受到初始猜测的影响。

3. 改进的 Python 代码

这是一个使用 scipy.optimize.fsolve 的改进后的 Python 代码版本:

import numpy as np
from scipy.optimize import fsolve

def tri(cashflows, periods_per_year):
    """
    计算现金流序列的内部收益率 (IRR)。

    Args:
        cashflows (list): 现金流列表,第一个元素是初始投资。
        periods_per_year (int): 每年期数。

    Returns:
        float: 内部收益率 (IRR),以百分比表示。
    """

    def npv(rate):
        """计算给定折现率的净现值 (NPV)。"""
        return np.sum([cf / (1 + rate / periods_per_year)**((i+1)/periods_per_year) 
                       for i, cf in enumerate(cashflows)])

    # 使用 fsolve 查找 NPV = 0 的折现率
    guess = 0.1  # 初始猜测
    tri_value = fsolve(npv, guess)[0] * periods_per_year * 100 
    return tri_value

# 测试用例
cashflows = [-1000, 50, 50, 50, 50, 1050]
periods_per_year1 = 1
print("IRR:", tri(cashflows, periods_per_year1), "%")

cashflows2 = [-500, 150, 150, 150, 150]
print("IRR 2:", tri(cashflows2, periods_per_year1), "%")

cashflows3 = [-10000, 2750, 4250, 3250, 2750]
periods_per_year3 = 2
print("IRR 3:", tri(cashflows3, periods_per_year3), "%")

此代码应该提供更准确且更可靠的 IRR 计算结果,并减少运行时错误的可能性。

标签:python,finance,irr
From: 78782190

相关文章

  • 使用Python连接ftps服务器时nlst返回错误
    我可以使用TotalCommander登录服务器:ftps://publishedprices.co.il用户名:“奥舍拉德”密码为空并带有lftp-uosherad:publishedprices.co.il但是当我尝试登录并使用Python获取文件列表时nlst函数返回超时代码:fromftplibimportFTP_TLS......
  • 在我的 python 代码中,我无法使用 slixmpp 连接到 Openfire 服务器
    在我的python代码中,我无法连接到Openfire服务器。我想连接到OpenFire服务器我的代码是importthreadingimporttkinterastkfromtkinterimportsimpledialog,scrolledtextimportjsonimportloggingimportasynciofromslixmppimportClientXMPPcla......
  • 如何在Python中获取字符的unicode?
    想要获取中文或越南语的汉名和日文字符的unicode我已经尝试过这些代码text="......
  • 三种语言实现计算逆序对的数量(C++/Python/Java)
    题目给定一个长度为......
  • python项目中__init__.py是什么文件有什么作用
    __init__.py 文件在Python项目中的作用主要是将目录标识为一个Python包。它在包的初始化过程中起到了重要作用。具体来说,__init__.py 文件有以下几个功能:1.标识包:-当一个目录中包含 __init__.py 文件时,这个目录就被视为一个Python包。这样,Python解释器就能够识别......
  • 从零开始构建你的第一个Python Web应用
    在本文中,我们将带领你从零开始构建一个简单的PythonWeb应用。不需要任何先验知识,我们会一步步地指导你完成设置、框架选择、代码编写到部署的整个过程。无论你是Web开发新手还是希望扩展技能的老手,这篇文章都将为你提供一个实践操作的起点。一、前言随着互联网技术的飞速......
  • Python中的global关键字是如何工作的?
    在Python中,global关键字扮演着特殊而重要的角色,它主要用于在函数内部声明全局变量。理解global关键字的工作原理,首先需要明确Python中变量作用域的概念,以及为什么需要global关键字。下面,我将详细解释global关键字的工作机制,包括其作用、使用场景、注意事项,以及它在Python编......
  • Python中enumerate()函数
    Python中enumerate()函数的作用是什么?enumerate()函数在Python中是一个非常有用的内置函数,它用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在for循环当中。使用enumerate()可以使你在循环中获取每个元素的同时,也能......
  • 我无法解决 python 捕获脚本中的此错误
    defclick_folder(self,文件夹名称):尝试:#单击主文件夹main_folder=self.wait.until(EC.presence_of_element_located((By.XPATH,f"//div[contains(@class,'folders-text_block')]//div[text()='{folder_name}']")))main_folder.click()print......
  • 尝试从图像 url 中抓取图像(使用 python urllib ),但获取 html
    我尝试从以下网址获取图像。http://upic.me/i/fj/the_wonderful_mist_once_again_01.jpg我可以右键单击并另存为,但是当我尝试使用urlretrievelikeimporturllibimg_url='http://upic.me/i/fj/the_wonderful_mist_once_again_01.jpg'urllib.urlretriev......