金融业XIRR函数的算法思想与实现,java/plsql
一.内部收益率(IRR)介绍
内部收益率(Internal Rate of Return (IRR)),就是NPV(净现值)等于零时的折现率。计算内部收益率要用若干个折现率进行试算,直至找到净现值等于零或接近于零的那个折现率。内部收益率是一个投资项目期望达到的收益率。
它是一项投资渴望达到的报酬率,该指标越大越好。通常来说,内部收益率大于等于市场的基准收益率时,该项目是可行的,反正则会造成亏损。投资项目各年的现金流与折现率乘积之和为项目的净现值,净现值为零时的折现率就是项目的内部收益率。
而XIRR需要精确到具体的天数,相对于IRR更为准确。
二.算法思想
算法公式:
Ci为每一笔的实缴现金流
di为投资每笔实缴现金流发生日期
d1为第一笔实缴日期
Rate为内部毛收益率-Gross-IRR
与Excel的算法公式相同,Rate是XNPV为0时的折现率,该公式的求和即为XNPV。
找出使XNPV=0时的Rate最简单的算法思想是折半查找,通过给定一个guess值带入公式不断迭代,最后探测出需要的值,该值需满足带回公式验算可令XNPV的精度小于1E-15,即近似为0。
三.代码实现
1.JAVA实现
public double xirr(double [] values, Date [] dates, double guess){double result = Double.NaN; double irrGuess = 0.1D; double sumCashFlows = 0.0D; boolean wasHi = false; double npv = 0.0D; int negativeCashFlowCount = 0; int positiveCashFlowCount = 0; if (values == null || values.length == 0) return result;if (dates == null || dates.length == 0) return result;if (values.length != dates.length) return result;for (int i = 0; i < values.length; i++) {sumCashFlows += values[i];if (values[i] > 0.0){negativeCashFlowCount++;} else if (values[i] < 0.0){positiveCashFlowCount++;}}if(negativeCashFlowCount <= 0 || positiveCashFlowCount <= 0) return result;if (!Double.isNaN(guess)) {irrGuess = guess;if (irrGuess <= 0.0) irrGuess = 0.5;}double irr = sumCashFlows < 0 ? -irrGuess : irrGuess;for (int i = 0; i <= MAX_ITERATION; i++) {npv = getXirr(irr, values, dates);if (Math.abs(npv) < MIN_VALUE){result = irr;break;}if (npv > 0.0) {if (wasHi) irrGuess /= 2;irr += irrGuess;if (wasHi) {irrGuess -= min_accuracy;wasHi = false;}} else {irrGuess /= 2;irr -= irrGuess;wasHi = true;}if (irrGuess <= min_accuracy) {result = irr;break;}}return result;}public double getXirr(final double guess, double [] values, Date [] dates){double result = 0.0D;for (int i = 0; i < dates.length; i++) {result += values[i] / Math.pow(1 + guess, DateUtil.getIntervalDays(dates[i], dates[0]) / FULL_YEAR_DAYS);}return result;}
2.改写为PLSQL函数
CREATE OR REPLACE FUNCTION "FIND_XIRR" (p_date_array in p_date_array,p_amount_array in t_amount_array,p_guess in number default 0)RETURN NUMBER ISBEGINdeclarertn_err number := -9999999;step number := 0;v_sum number;guess number := 0.5;wasHi number := -1;d number := 0;returnd number := 0;begind := 0;v_sum := 0;for i in 1 .. p_amount_array.count loopv_sum := v_sum +p_amount_array(i) /power((1 + d), (p_date_array(i) - p_date_array(1)) / 365);end loop;if (v_sum > 0) thend := guess;elsed := (-1) * guess;end if;step := 100;loopv_sum := 0;for i in 1 .. p_amount_array.count loopv_sum := v_sum +p_amount_array(i) /power((1 + d), (p_date_array(i) - p_date_array(1)) / 365);end loop;if (v_sum > 0) thenif (wasHi > 0) thenguess := guess / 2;end if;d := d + guess;if (wasHi > 0) thenguess := guess - 0.000000000000001;wasHi := -1;end if;elseguess := guess / 2;d := d - guess;wasHi := 0;end if;if (abs(v_sum) < 0.000000000000001) thenreturnd := d;exit;end if;step := step - 1;if (step = 0) thenreturnd := d;exit;end if;end loop;return returnd;EXCEPTIONWHEN OTHERS THENreturn rtn_err;end;
END FIND_XIRR;
需要注意的是输入的现金流数组必须满足一个正现金流和一个负现金流,日期类型为YYYYMMDD格式,不满足需要进行类型转换,现金流要输入合理的测试数据,否则是无法找出满足跳出循环条件的XIRR值。
测试数据:
P_DATE_ARRAY[2016/9/26,2018/7/2,2020/3/31]
P_AMOUNT_ARRAY[1000000000,18500000,-1249940250]
RETURN_XIRR:0.06057268
与Excel计算值几乎没有误差。
金融业XIRR函数的算法思想与实现,java/plsql相关推荐
- 95% 的算法都是基于这 6 种算法思想,大厂Java面试必考点
// 当前结点的 id 符合查找条件,返回当前结点 if(node.id === id) return node // 前结点的 id 不符合查找条件,继续查找它的每一个子结点 for(var i = ...
- 金融业-xirr函数------Java实现
package com.rqtanc.utils;import java.util.Arrays; import java.util.Date; import java.util.List;/*** ...
- 大数据——Redshift通过UDF函数实现金融业XIRR函数
函数简介: https://support.microsoft.com/zh-cn/office/xirr-%e5%87%bd%e6%95%b0-de1242ec-6477-445b-b11b-a30 ...
- 算法思想——迭代 (用java语言实现 迭代相关的6个案例等)
1. 首先看一下:递归,递推,迭代有什么区别? 递归:程序调用自身的编程技巧称为递归,是函数自己调用自己. 使用递归要注意的有3点: 递归就是在过程或函数里面调用自身; 在使用递归时,必须有一个明确的 ...
- c语言算法6,c语言6函数和算法.ppt
c语言6函数和算法创新 近半个月目标 学会使用函数进行模块化程序设计 学会调试由多个函数(包含库函数)组成的程序 主要内容 模块化程序设计思想 函数定义和函数调用.函数原型(函数声明) 函数的参数和返 ...
- java中小写转大写函数_lotus 中日期小写转大写的函数及算法(lotus script) (转)...
lotus 中日期小写转大写的函数及算法(lotus script) (转)[@more@] 日期小写变大写 --------------------------------------------- ...
- JAVA工程师常用算法_算法工程师必须要知道的8种常用算法思想
算法思想有很多,业界公认的常用算法思想有8种,分别是枚举.递推.递归.分治.贪心.试探法.动态迭代和模拟.当然8种只是一个大概的划分,是一个"仁者见仁.智者见智"的问题. 1.1 ...
- Algorithms_算法思想_递归分治
文章目录 引导案例 递归的定义 什么样的问题可以用递归算法来解决 递归如何实现以及包含的算法思 递归的公式 斐波那契数列代码实现 递归的时间复杂度和空间复杂度 递 与 归 递归的优化 优化方式一:不使 ...
- 快速排序 C++代码实现及其算法思想及时间复杂度分析及优化 恋上数据结构笔记
文章目录 复习梗概 算法思想 算法复杂度分析及稳定性 如何优化? 快速排序改进版代码C++ 快速排序个人青春版代码 完整代码 复习梗概 算法思想,别的排序名字直接就能让人联想到它的算法思想,唯独快速排 ...
最新文章
- 南京大学《物联网技术导论》课程
- 深入理解HTTP Session
- Android构建boot.img(一):root目录与ramdisk.img的生成
- 宝塔面板部署nuxt_MacOS下创建及部署vue.js项目(及Nuxt.js、PM2等相关流程)
- 地图处理(dfs算法)
- OA中总结:s:select,关于使用modelDriven,项目分层,@Transactional,jspf,各个层上配置注解交给spring管理的方法,简单的OGNL表达式写法
- 《数据库SQL实战》找出所有员工当前薪水salary情况
- test of ui5 duplicate control id
- Google Guava –与Monitor同步
- 深入java核心_Java核心(五)深入理解BIO、NIO、AIO
- 产品ajax无刷新kesion,KesionCMSV6置标使用手册.doc
- 大白话系列之java_并发系列2-大白话聊聊Java并发面试问题之Java 8如何优化CAS性能?【石杉的架构笔记】...
- 拉链式存储_用户维度表(拉链表的方式存储)
- 以正确的方式招募数据科学家!
- php扩展可以通过pecl 或者phpize 安装
- Github 教程 -- 使用指南
- Linux 设置Dlan服务器
- 为了学习Python,我汇总了这10个免费的视频课程!
- c语言生日蛋糕图片,poj1190生日蛋糕
- 微信运动服务器忙,很哥解密:微信运动有玄机,有人悄悄惦记你