存过调用irr
create or replace package PKG_BATCH as
/******************************************************************************
创建作者:lijunyu
创建日期:2018-01-10
功能描述:封包日后的第一个还款日批处理
实现逻辑:
******************************************************************************/
procedure PACKAGEDATE_FIRST_RETENDATE;
/******************************************************************************
创建作者:lijunyu
创建日期:2018-01-10
功能描述:基础资产IRR计算批处理
实现逻辑:
******************************************************************************/
procedure ASSET_IRR_CAL;
end PKG_BATCH;
/
create or replace package body PKG_BATCH as
/******************************************************************************
创建作者:lijunyu
创建日期:2018-01-10
功能描述:封包日后的第一个还款日批处理
实现逻辑:
******************************************************************************/
procedure PACKAGEDATE_FIRST_RETENDATE as
begin
merge into assetportfoliostructure b
using (select b.id, min(d.returndate) PAYDATEAFTERPACKAGE
from assetschedule d, assetportfoliostructure b
where b.assetcode = d.assetcode
and d.returndate >= b.intpacketdate
and b.isPAYDATEAFTERPACKAGE = 'N'
group by b.id) e
on (b.id = e.id)
when matched then
update
set PAYDATEAFTERPACKAGE = e.PAYDATEAFTERPACKAGE,
b.isPAYDATEAFTERPACKAGE = 'Y';
commit;
end PACKAGEDATE_FIRST_RETENDATE;
/******************************************************************************
创建作者:lijunyu
创建日期:2018-01-10
功能描述:基础资产IRR计算批处理
实现逻辑:
******************************************************************************/
procedure ASSET_IRR_CAL as
begin
DECLARE
PAA t_amount_array; --金额集合
v_Return number; --返回IRR
cnt number; --计数
asset_code varchar2(64); --借据编号
V_index number;
BEGIN
-- Modify the code to initialize the variable
declare
--游标
cursor c_job is
select c.payinteresttotal,
c.payprincipaltotal,
c.basenominal,
c.assetcode
from assetschedule c, assetportfoliostructure a
where c.assetcode = a.assetcode
and a.isINSIDEYIELD = 'N'
-- and a.assetcode like 'XFJR121%'
order by c.assetcode, c.returndate;
code c_job%rowtype;
begin
cnt := 2;
asset_code := '';
PAA := t_amount_array();
V_index := 0;
for code in c_job loop
if asset_code = code.assetcode then
PAA.EXTEND;
PAA(cnt) := code.payinteresttotal + code.payprincipaltotal;
cnt := cnt + 1;
else
if PAA.count > 0 then
--计算IRR
v_Return := IRR(PAA);
-- DBMS_OUTPUT.PUT_LINE(asset_code || 'IRR = ' || v_Return );
--修改IRR值
if v_Return is not null then
if v_Return >= 0 then
update assetportfoliostructure bb
set bb.INSIDEYIELD = v_Return, bb.isINSIDEYIELD = 'Y'
where bb.assetcode = asset_code;
V_index := V_index + 1;
if V_index > 10 then
commit;
end if;
end if;
end if;
end if;
-- 把新的借据编号赋给assetcode
asset_code := code.assetcode;
--第一个
PAA := t_amount_array(0 - code.basenominal);
cnt := 2;
end if;
end loop;
end;
END;
end ASSET_IRR_CAL;
end PKG_BATCH;
/
irr.fnc:
create or replace function IRR(p_amount_array in t_amount_array) 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;
PDA(i) := sysdate + 365*(i-1);
end loop;
Return XIRR(P_DATE_ARRAY => PDA,P_AMOUNT_ARRAY => p_amount_array);
end IRR;
/
xirr.fnc:
create or replace function XIRR(p_date_array in p_date_array, p_amount_array in t_amount_array) return number is
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> <88=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;
/