从业N年,一直做企业内部系统。

数年前,ITS部门来了一个A国(not USA)人,年龄比咱还小一轮。当然,自小喝洋墨水长大的,英语很溜。有次喝高了,对咱很不客气地说,你念那多书有啥用?我连大学的门都没进过,照样级别比你高一级。我听后很郁闷。但仔细想来,做公司内部系统吧,小学程度,会四则运算,逻辑上不糊涂,就可在世界500强企业的ITS部门混饭吃。

又过了几年,那A国人又高就别处,咱还照样做着小学生就能做的事情。这事情就一个结,从未了结。

最近,终于有个机会让咱用了一回高等数学。给读书无用论一记响亮的耳瓜。

做生意,图回报,这是真理。投入多少,多长时间能收回,这就要计算IRR。用EXCEL的话,简单,用Oracle的话,麻烦。(这不是开玩笑,因为Excel装备有计算IRR的函数,而Oracle则是在价格不菲的OLAP软件中才提供了计算IRR的功能。)

IRR如何计算,有兴趣的朋友可参考

WikiPedia:http://en.wikipedia.org/wiki/Internal_rate_of_return

或 http://zainco.blogspot.jp/2008/08/internal-rate-of-return-using-newton.html

或 http://www.corality.com/tutorials/iterative-approach-calculating-internal-rate-return-irr

当npv=0时的r就是IRR。

展开后就是个多项式,

当多项式等于0时,r等于多少?

这个问题没有精确解(解析解),只有近似解(数值解)。

通常使用的方法是Newton-Raphson方法。

咱还是实用主义,先看编码。

原理可参考以上几个URL。

PL/SQL编码

1. 计算XIRR的函数

这段代码是从Oracle Forum上抄来的, http://forums.oracle.com/forums/thread.jspa?threadID=549939

必须预先定义2个Type:

create or replace type p_date_array is varray(250) of date;

create or replace type t_amount_array is varray(250) of number;

create or replace FUNCTION            "XIRR" (p_date_array in p_date_array,
p_amount_array in t_amount_array,
p_guess in number default 0
)
RETURN NUMBER
IS
----- Reference: http://forums.oracle.com/forums/thread.jspa?threadID=549939
-- pre-defined types:
-- create or replace type p_date_array is varray(250) of date;
-- create or replace type t_amount_array is varray(250) of number;
BEGIN
declare
z number := 0;
step_limit number := 0;
temp number;
rtn_err number := -9999999;
step number := 0.1;
d number := 0.5;
l_MaxDate date;
l_MinDate date;
srok number;
begin
l_MaxDate := p_date_array(1);
l_MinDate := p_date_array(1);
-- 5@2K9 ?@>E>4: ?>8A: <0:A. 40BK 8 =0;8G8O E>BO 1K >4=>3> <8=CA0 8 ?;NA0 2 ?>B>:0E
for i in 1 .. p_date_array.count
loop
if p_date_array(i) > l_MaxDate then
l_MaxDate := p_date_array(i);
end if;
if p_date_array(i) < l_MinDate then
l_MinDate := p_date_array(i);
end if;
end loop;
select months_between(l_MaxDate, l_MinDate)
into srok
from dual;
loop
temp := p_amount_array(1);
for i in 2 .. p_amount_array.count
loop
temp := temp + p_amount_array(i)/power((1 + d),(p_date_array(i) - p_date_array(1))/365);
end loop;
if (temp > 0) and (z = 0) then
step := step / 2;
z := 1;
end if;
if (temp < 0) and (z = 1) then
step := step / 2;
z := 0;
end if;
if (z = 0) then
d := d - step;
else
d := d + step;
end if;
step_limit := step_limit + 1;
if (step_limit = 10000) then
return rtn_err; -- a kind of error
exit;
end if;
exit when(round(temp * 100000) = 0);
end loop;
return d;
EXCEPTION
WHEN OTHERS THEN
return rtn_err;
end;
END XIRR;

2. 计算IRR的函数

create or replace FUNCTION            "IRR" ( p_amount_array in t_amount_array,
p_guess in number default 0
)
RETURN NUMBER
IS
PDA P_DATE_ARRAY;
BEGIN
PDA := P_DATE_ARRAY() ; -- initialize Varray with NULL, count=0
for i in 1 .. p_amount_array.count
loop
PDA.EXTEND; -- Add 1 element to Varray
PDA(i) := sysdate + 365*(i-1) ;
end loop;
Return XIRR(P_DATE_ARRAY => PDA,P_AMOUNT_ARRAY => p_amount_array, P_GUESS => P_GUESS);
END;

3. 相关函数,XNPV,NPV

create or replace FUNCTION            "XNPV" (p_date_array in p_date_array,
p_amount_array in t_amount_array,
p_discount_rate in number
)
RETURN NUMBER
IS
----- Reference: http://forums.oracle.com/forums/thread.jspa?threadID=549939
-- pre-defined types:
-- create or replace type p_date_array is varray(250) of date;
-- create or replace type t_amount_array is varray(250) of number;
z number := 0;
step_limit number := 0;
temp number;
step number := 0.1;
xnpv number := 0.5;
l_MaxDate date;
l_MinDate date;
srok number;
begin
/*********** Formular *************
XNPV = I(1) + I(2)/(1+r)^(d(2)-d(1))/365 + ........ + I(n)/(1+r)^(d(n)-d(1))/365
***********************************/
xnpv := p_amount_array(1);
for i in 2 .. p_amount_array.count
loop
xnpv := xnpv + p_amount_array(i)/power((1 + p_discount_rate),(p_date_array(i) - p_date_array(1))/365);
end loop;
return xnpv;
end;
create or replace FUNCTION            "NPV" ( p_amount_array in t_amount_array,
p_discount_rate in number
)
RETURN NUMBER
IS
PDA P_DATE_ARRAY;
BEGIN
PDA := P_DATE_ARRAY() ; -- initialize Varray with NULL, count=0
for i in 1 .. p_amount_array.count
loop
PDA.EXTEND; -- Add 1 element to Varray
PDA(i) := sysdate + 365*(i-1) ;
--htp.p(PDA(i));
end loop;
Return XNPV(P_DATE_ARRAY => PDA,P_AMOUNT_ARRAY => p_amount_array, P_DISCOUNT_RATE => p_discount_rate);
END;

4. 用例

原始数据

2001/1/1 2002/1/1 2003/1/1 2004/1/1 2005/1/1 2006/1/1
-6264695 667885.4979 329584.128 329584.128 329584.1 3527014
DECLARE
PDA P_DATE_ARRAY;
PAA T_AMOUNT_ARRAY;
P_GUESS NUMBER;
P_DISCOUNT_RATE Number := 0.0743;
v_Return NUMBER;
BEGIN
-- Modify the code to initialize the variable
PDA := P_DATE_ARRAY(
to_date('2007/01/01','yyyy/mm/dd'),
to_date('2008/01/01','yyyy/mm/dd'),
to_date('2009/01/01','yyyy/mm/dd'),
to_date('2010/01/01','yyyy/mm/dd'),
to_date('2011/01/01','yyyy/mm/dd'),
to_date('2012/01/01','yyyy/mm/dd'),
to_date('2013/01/01','yyyy/mm/dd'),
to_date('2014/01/01','yyyy/mm/dd')
);
-- Modify the code to initialize the variable
PAA := T_AMOUNT_ARRAY(-112651.395506849,274684.931506849);
P_GUESS := NULL;
v_Return := XIRR(P_DATE_ARRAY => PDA,P_AMOUNT_ARRAY => PAA,P_GUESS => P_GUESS);
DBMS_OUTPUT.PUT_LINE('XIRR = ' || v_Return);
v_Return := IRR(P_AMOUNT_ARRAY => PAA,P_GUESS => P_GUESS);
DBMS_OUTPUT.PUT_LINE('IRR = ' || v_Return);
v_Return := XNPV(P_DATE_ARRAY => PDA,P_AMOUNT_ARRAY => PAA,P_DISCOUNT_RATE => P_DISCOUNT_RATE);
DBMS_OUTPUT.PUT_LINE('XNPV = ' || v_Return);
v_Return := NPV(P_AMOUNT_ARRAY => PAA,P_DISCOUNT_RATE => P_DISCOUNT_RATE);
DBMS_OUTPUT.PUT_LINE('NPV = ' || v_Return);
END;

结果:

XIRR = 1.4383624397218227386474609375
IRR = 1.4383624397218227386474609375
XNPV = 143035.9651064331372056222656613608861584
NPV = 143035.9651064331372056222656613608861584

Statement processed.


0.23 seconds

5. 与EXCEL计算结果的比较

  Excel Oracle
XIRR -0.04458783  -.044584477263 -3.35245E-06
IRR -4% -.0446097485299 -3.67924E-11
XNPV -2379917.807  -2380026.06389 108.2568879
NPV ¥-2,214,823.89 -2379385.302111 164561.4141

从业N年初次用到高等数学:用PL/SQL算IRR相关推荐

  1. Iterative Answer Prediction with Pointer-Augmented Multimodal Transformers for TextVQA

    1. Abstract Visual Question Answering (VQA)任务,忽略一个重要的模态-图像中的文本,它承载着场景理解和推理的基本信息.例如,在图1中,标志上的深水警告人们现场 ...

  2. Serverless——前端的3.0时代

    导语:<信息简史>中说"进化本身是生物体与环境之间持续不断的信息交换的具体表现",前端技术的进化也是如此.浩瀚的前端宇宙中,又出现过哪些耀眼的星辰呢?指引前端未来的&q ...

  3. 河南最新道路货物运输驾驶员考试真题及答案解析

    百分百题库提供道路货物运输驾驶员考试试题.道路货物运输驾驶员考试预测题.道路货物运输驾驶员考试真题.道路货物运输驾驶员证考试题库等,提供在线做题刷题,在线模拟考试,助你考试轻松过关. 31.道路货物运 ...

  4. 货运资格证年审过期了怎么办

    我考取货运资格证已经很久了,那么货运资格证年审过期了怎么办呢?应该怎么进行处理呢?上学吧君今天就来告诉大家. 货运从业资格证有效期6年,有效期满可提前30日去换证,对于逾期180天未换证的会注销其从业 ...

  5. Oracle Job定时任务的使用详解

    转自:http://www.cnblogs.com/Chestnuts/p/7068456.html Oracle中的job能为你做的就是在你规定的时间格式里执行存储过程,定时执行一个任务 . 下面是 ...

  6. oracle 存储过程 状态,查看ORACLE中正在运行的存储过程 | 学步园

    1.如何查看ORACLE中正在运行的存储过程 select owner,name from v$db_object_cache where type like '%PROCE%' and locks ...

  7. 世界级Oracle专家权威力作

    世界级Oracle专家权威力作 <Oracle 10g数据库管理艺术>姊妹篇 全面阐述Oracle 11g新特性 "这是市面上最详细的11g参考书,内容非常丰富,我极力推荐此书. ...

  8. .net程序员使用Oracle新手上路指南

    虽然oracle,sqlserver都是关系型数据库,sql语句大部分也差不多,但是从sqlserver换到oracle还是有很多不适应的地方,本文旨在帮助广大初次接触oracle的.net程序员快速 ...

  9. 学习动态性能表(3)--v$sqlv$sql_plan

    学习动态性能表 第三篇-(1)-v$sq 2007.5.25 V$SQL中存储具体的SQL语句. 一条语句可以映射多个cursor,因为对象所指的cursor可以有不同用户(如例1).如果有多个cur ...

最新文章

  1. Spring入门详细教程(一)
  2. 灰色条怎么写_货车司机必须牢记的5条驾驶经验,最后一个能做到的人不多
  3. YZMCMS V5.3后台 SSRF
  4. vue 安装php,vue中使用openinstall
  5. 【转】DICOM网络协议(一)概述
  6. 热议 | 深圳中学教师年薪35万,有一半是博士
  7. 555定时器的应用——施密特触发器
  8. Eclipse 导入项目与 svn 插件关联全过程记录
  9. 贝叶斯网络、马尔可夫模型、马尔可夫过程、马尔可夫链、马尔可夫网络基本概念
  10. 旧手机别扔,手把手教你DIY一台Linux服务器
  11. Java—圆柱体计算
  12. PMP合同的类型选择
  13. C#之AutoCAD图层样式定义
  14. FPGA的进阶项目——开源示波器
  15. SpringBoot2基础篇
  16. 用数据分析验证,王者荣耀完胜阴阳师,小学生才是最终的赢家
  17. 笔记本计算机拆开视频,Designer笔记本电脑的视频电路拆解
  18. 方舟生存进化无修改服务器,方舟生存进化私人服务器设置教程
  19. 如何查看网站服务器的地址
  20. 电脑每次启动都硬盘自检

热门文章

  1. ZWAVE COMMAND_CLASS_HAIL, Aeotec doorbell notification
  2. OSChina 周三乱弹 ——不小心摔倒把班主任的裙子脱了
  3. 年轻人学什么技术有前途?
  4. Floor Number
  5. OpenGL - Bloom
  6. 李开复:身处浪潮中的“弄潮儿”的切身体会
  7. 如何把pdf图片转换成txt
  8. AutoCAD入门——斜线
  9. Diffie-Hellman Key Agreement Protocol 资源管理错误漏洞(CVE-2002-20001)
  10. Unity单选题开发