一、IRR计算的原理:

  内部收益率(Internal Rate of Return (IRR)),就是资金流入现值总额与资金流出现值总额相等、净现值等于零时的折现率。

用公式 标识:-200+[30/(1+IRR)+30/(1+IRR)^2+....+30/(1+IRR)^10]=0。多次方程求解。

在计算机界求解高次方程的做法通常是利用牛顿插值法(Newton-Raphson)来实现,也有翻译牛顿迭代的。

二、关于牛顿迭代:

设r是  的根,选取 作为r的初始近似值,过点  做曲线  的切线L,L的方程为  ,求出L与x轴交点的横坐标

 ,称x1为r的一次近似值。过点  做曲线  的切线,并求该切线与x轴交点的横坐标  ,称 为r的二次近似值。重复以上过程,得r的近似值序列,其中,
 称为r的  次近似值。
三、Java的实现方式:
import java.math.BigDecimal;public class IRRUtilMath2 {public static double irr(double[] income) {return irr(income, 0.1D);}public static double irr(double[] values, double guess) {int maxIterationCount = 20;double absoluteAccuracy = 1.0E-007D;double x0 = guess;int i = 0;while (i < maxIterationCount) {double fValue = 0.0D;double fDerivative = 0.0D;for (int k = 0; k < values.length; k++) {fValue += values[k] / Math.pow(1.0D + x0, k);fDerivative += -k * values[k] / Math.pow(1.0D + x0, k + 1);}double x1 = x0 - fValue / fDerivative;if (Math.abs(x1 - x0) <= absoluteAccuracy) {return x1;}x0 = x1;i++;}return (0.0D / 0.0D);}public static void main(String[] args) {double[] income = {-359900,19413.67,19413.67,19413.67,19413.67,19413.67,19413.67,19413.67,19413.67,19413.67,19413.67,19413.67,19413.67,19413.67,19413.67,19413.67,19413.67,19413.67,19413.67,19413.67,19413.67,19413.67,18241.01,0,0};double ret = irr(income,0.00001d)*12 ;System.out.println(new BigDecimal(ret));}
}

四、根据Java版实现的SQL版:

--定义type
create or replace type typ_cashflow_array is varray(60) of number;--实现函数
function IRR_ZEN(p_amount_array in typ_cashflow_array, p_guess in number)RETURN NUMBER is rtn_err number := -9999999;maxIterationCount number := 20;absoluteAccuracy number := 0.0000001;x0 number := p_guess;x1 number := 0;i_num integer := 0; fValue number := 0.0;fDerivative number := 0.0;BEGIN--x0 :=p_guess;while (i_num < maxIterationCount) loopfValue := 0.0;fDerivative := 0.0;for k in 1..p_amount_array.count loopfValue :=fValue+p_amount_array(k)/power(1.0 + x0, k);fDerivative :=fDerivative+(-k *p_amount_array(k)/power(1.0 + x0, k + 1));end loop;x1 := x0 - fValue / fDerivative;if (abs(x1 - x0) <= absoluteAccuracy) thenreturn x1;end if;x0 := x1;i_num := i_num+1;end loop; return (0.0/0.0);EXCEPTIONWHEN OTHERS THENreturn rtn_err; END IRR_ZEN;

五、关于函数的调用:

  方法一,将现金流组成字符串,然后用函数拆解字符串。具体实现方式是

function IRR(in_varray in varchar2) return numberis v_irr number;v_amount_array  typ_cashflow_array;beginv_amount_array :=typ_cashflow_array();declarev_varray_str varchar2(1000);v_length number;v_split varchar2(2);v_cnt integer; begin v_varray_str:=ltrim(rtrim(in_varray));v_length:=0;v_split :=',';v_cnt :=1;---劈开字符串,为数据赋值while instr(v_varray_str,v_split)<>0 loopv_length:=v_length+1; v_amount_array.extend;v_amount_array(v_cnt) :=to_number(substr(v_varray_str,1,instr(v_varray_str,v_split)-1));v_varray_str:=substr(v_varray_str,instr(v_varray_str,v_split)+length(v_split),length(v_varray_str));v_cnt :=v_cnt+1;end loop;--循环的末尾追加最后一个数字
        v_amount_array.extend;v_amount_array(v_cnt) :=to_number(v_varray_str);end; v_irr :=IRR_ZEN(p_amount_array => v_amount_array, p_guess =>0.1 );return v_irr;end ;

调用的时候:

select LES_FIN_TO_DW.IRR(listagg(t.fee_amt,',') within group( order by t.pay_pd))*12  from
F_LES_PAY_SCH_IRR_CAL_CASHFLOW t
where t.pay_sch_id=180605104121724
order by t.pay_pd;

方法二:  直接使用类型转换公式初始化数组

select les_fin_to_dw.IRR_ZEN(cast(collect(fee_amt) as typ_cashflow_array),0.1)*12
from(
select t.fee_amt
from F_LES_PAY_SCH_IRR_CAL_CASHFLOW t
where t.pay_sch_id=171218104072346
order by t.pay_pd
);

方法一的弊端:

listagg可连接的最大字节长度是4000byte.当金额比较大,现金流周期比较长的时候可能会有问题。

方法二的弊端:

 现金流的输入是有顺序的,必须先排序。

参考资料:
https://baike.baidu.com/item/%E7%89%9B%E9%A1%BF%E8%BF%AD%E4%BB%A3%E6%B3%95/10887580?fr=aladdin

转载于:https://www.cnblogs.com/Alex-Zeng/p/9334582.html

ORACLE SQL 实现IRR的计算相关推荐

  1. Oracle中使用SQL根据出生日期精确计算年龄

    Oracle中使用SQL根据出生日期精确计算年龄 提示:以下是本篇文章正文内容,下面案例可供参考 代码如下(示例): select XM,CSNY as 出生日期,-- extract函数用于提取日期 ...

  2. oracle发票验证,通过使用Oracle SQL脚本进行计算(总发票)的多个表的更新记录...

    我有一个SERVICE表,该表存储一个表中的服务数量,然后链接到连接到INVOICE的LINE表.通过使用Oracle SQL脚本进行计算(总发票)的多个表的更新记录 我想要创建一个触发器,根据SER ...

  3. Oracle SQL高级编程——分析函数(窗口函数)全面讲解

    Oracle SQL高级编程--分析函数(窗口函数)全面讲解 注:本文来源于:<Oracle SQL高级编程--分析函数(窗口函数)全面讲解> 概述 分析函数是以一定的方法在一个与当前行相 ...

  4. oracle sql 执行计划分析_《真正读懂Oracle SQL执行计划》

    maclean_0071人评论1235人阅读2013-10-25 15:18:12 [视频教学:性能优化]Maclean Liu的Oracle性能优化讲座第一回<真正读懂Oracle SQL执行 ...

  5. Oracle SQL语句执行过程

    前言 QQ群讨论的时候有人遇到这样的问题:where子句中无法访问Oracle自定义的字段别名.这篇 博客就是就这一问题做一个探讨,并发散下思维,谈谈SQL语句的执行顺序问题. 问题呈现 直接给出SQ ...

  6. Oracle SQL性能优化的40条军规

    Oracle SQL性能优化的40条军规 1. SQL语句执行步骤 语法分析> 语义分析> 视图转换 >表达式转换> 选择优化器 >选择连接方式 >选择连接顺序 & ...

  7. Oracle SQL性能优化40条,值得收藏

    1. SQL语句执行步骤 语法分析> 语义分析> 视图转换 >表达式转换> 选择优化器 >选择连接方式 >选择连接顺序 >选择数据的搜索路径 >运行&q ...

  8. Oracle SQL 基础要点

    Oracle SQL 基础要点 本文是学习<程序员的SQL金典>时的读书摘要,记录一些自己不太熟悉或者很重要的知识点.方便后期对照复习. 1.各种主流数据库的优缺点比较 - DB2由IBM ...

  9. Oracle SQL开发考试试题

    Oracle SQL开发考试试题,主要围绕Oracle SQL的基础开发,以及SQL优化的相关知识点,主要的考点: (1) DML考点: (2) DDL考点: (3)SELECT考点 (4)子查询考点 ...

最新文章

  1. 关于spring service层的mybatis缓存问题,待解决
  2. 8天学通MongoDB——第二天 细说增删查改
  3. kafka实战最佳经验,阿里又现海王!某程序员同时约两个女生十一出游
  4. DiscuX END - 553 Envolope sender mismatch with header from..
  5. mysql sql乱码怎么解决_MYSQL数据库导入SQL文件出现乱码如何解决
  6. 苏区振兴下的赣州发展状况分析
  7. c语言汉字属于什么类型_你知道你的身体属于什么类型么?
  8. idea补全代码快捷键
  9. VMware10 安装centos6.7 设置NAT模式固定ip
  10. Java构造字符串算法题_LeetCode算法题-Repeated Substring Pattern(Java实现)
  11. 类创建几种java_Java创建对象的几种方式
  12. 非对称加密提交表单到PHP
  13. opencv java 人脸识别_Java OpenCV实现人脸识别过程详解
  14. 2013年最新热门软件分享第一季
  15. 计算机丢失cxcore100.dll,cxcore100.dll
  16. 2dpca matlab程序,simulink基于2DPCA的人脸识别
  17. picker插件 vue 移动端_基于 vue 的 picker 组件 vue-awesome-picker
  18. 编程计算1!+2!+3!+…+N!
  19. flowable中强制结束流程
  20. Three.js学习二——Three.js极简入门

热门文章

  1. 永久禁用Win10驱动程序强制签名
  2. 距离成为科技“爆款”,“眼动追踪”还有多远?
  3. 03、矢量图形查询工具(Symbol Unicode)
  4. OKR团队绩效管理学习1
  5. CSS使图片变模糊,亲测非常好用
  6. 放开那三国服务器维护中是什么意思,《放开那三国2》游戏11月25日更新维护公告...
  7. Pixhawk学习6.2——姿态解算
  8. ubuntu server 安装中文字库
  9. 备忘录莫名其妙的没了_苹果手机备忘录突然消失了该怎么办
  10. Wine完全使用完全指南(从初级到高级)