powered by simpleCommunicator - 2.0.30     © 2024 Programmizd 02
Map
Форумы / Oracle [игнор отключен] [закрыт для гостей] / XIRR function in PL/SQL ?
25 сообщений из 34, страница 1 из 2
XIRR function in PL/SQL ?
    #34560654
Valeriy Borysyuk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привет всем!

Поделитесь пожалуйста процедурой вычисления XIRR на PL/SQL, если есть у кого-то
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #34695465
Serg Kravchenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Добрый день.

Аналогичная история - ищу реализацию данной функции.
Вам удалось найти?

Если да - поделитесь, плиз, на zchermit@mail.ru...
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #34695572
Valeriy Borysyuk
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
На сипане смотри реализацию на перле. Там есть все исходники с комментариями. Эта функция там IRR называется, но на самом деле она XIRR. Я пока не буду делать ее на PL/SQL тк уже сменил работу и надобность отпала (надолго -ли...).

http://search.cpan.org/~erwan/Finance-Math-IRR-0.10/lib/Finance/Math/IRR.pm

Очень хорошо прокомментирован исходник. Придецца сначала освоить методы решения полиномов.
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #34697010
ЭСП
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
У меня тоже проблема - нужно доходность к погашению и амортизацию скидок-премий
по ценным бумагам вычислять по эффективной ставке процента (IRR).
И всё-таки, кто то может уже делал такую ф-ю.
Поделитесь плиз.
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #34698003
Volder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ЭСПИ всё-таки, кто то может уже делал такую ф-ю.
Поделитесь плиз.
ставьте задачу конкретную (с данными, алгоритмами, желаемыми результатами).
Думаю простого SQL достаточно будет.
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #34699870
ЭСП
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Нет, для IRR просто SQL не достаточно.
Кто это делал, тот знает. Тот и может подсказать.
А я в полиномах не шарю.
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #34700127
Volder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
ЭСПНет, для IRR просто SQL не достаточно.ну почему же недостаточно...

на 10-ке в лоб - метод подбора на простом примере с некоторыми допущениями (про perfomance речь не идет):

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
SQL> with t as (select to_date('01.01.2007','dd.mm.yyyy') dt, - 100  summ from dual union all
   2              select to_date('01.07.2007','dd.mm.yyyy') dt,  58  summ from dual union all
   3              select to_date('01.01.2008','dd.mm.yyyy') dt,  60  summ from dual)
   4             --
   5              select round(irr* 100 , 2 )||' %' эффективная_ставка from
   6              (select * from t
   7               model
   8                dimension by (row_number() over (order by dt) rn)
   9                measures(dt-first_value(dt) over (order by dt) dt, summ s,  0  ss,  0  irr, power( 10 ,- 4 ) rate_step,  0  disc_summ)
  10                rules iterate( 100000 ) until (s[ 1 ]+disc_summ[ 1 ]< 0 )
  11                (ss[any]=s[CV()]/power( 1 +IRR[ 1 ],dt[CV()]/ 365 ),
  12                 disc_summ[ 1 ]=sum(ss)[rn> 1 ],
  13                 irr[ 1 ]=irr[ 1 ]+rate_step[ 1 ])
  14              )
  15              where rn= 1 
  16   /

ЭФФЕКТИВНАЯ_СТАВКА
------------------------------------------
 24 . 89  %

SQL> 
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #34747308
Volder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
тут коллеги тоже занимались эффективной процентной ставкой.
решил более пристально глянуть на этот вопрос.
что получилось - запостил в этой ветке - если кому-то потом интересно будет.

раньше ставку получал простым перебором, сейчас алгоритм поменял.
результат:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
SQL> set timing on;
SQL> 
SQL>  with t as (select to_date('01.01.2007','dd.mm.yyyy') dt, - 100  summ from dual union all
   2               select to_date('01.07.2007','dd.mm.yyyy') dt,  58  summ from dual union all
   3               select to_date('01.01.2008','dd.mm.yyyy') dt,  60  summ from dual)
   4              --
   5               select to_char((irr-rate_step)* 100 ,'999999.0000000')||' %' эффективная_ставка, iter количество_итераций from
   6               (select * from t
   7                model
   8                 dimension by (row_number() over (order by dt) rn)
   9                 measures(dt-first_value(dt) over (order by dt) dt, summ s,  0  ss,  0  irr, power( 10 ,- 6 ) rate_step,  0  disc_summ,  0  iter)
  10                 rules iterate( 10000000 ) until (disc_summ[ 1 ]< 0 )
  11                 (ss[any]=s[CV()]/power( 1 +IRR[ 1 ],dt[CV()]/ 365 ),
  12                  disc_summ[ 1 ]=sum(ss)[any],
  13                  irr[ 1 ]=irr[ 1 ]+rate_step[ 1 ],
  14                  iter[ 1 ]=iteration_number+ 1 )
  15               )
  16               where rn= 1 
  17   /

ЭФФЕКТИВНАЯ_СТАВКА КОЛИЧЕСТВО_ИТЕРАЦИЙ
------------------ -------------------
      24 . 8720000  %                248721 

Executed in  29 . 422  seconds

SQL> 
SQL>  with t as (select to_date('01.01.2007','dd.mm.yyyy') dt, - 100  summ from dual union all
   2               select to_date('01.07.2007','dd.mm.yyyy') dt,  58  summ from dual union all
   3               select to_date('01.01.2008','dd.mm.yyyy') dt,  60  summ from dual)
   4               --
   5            select to_char(irr* 100 ,'999999.0000000000000')||' %' эффективная_ставка, iter количество_итераций from
   6               (select * from t
   7                model
   8                 dimension by (row_number() over (order by dt) rn)
   9                 measures(dt-first_value(dt) over (order by dt) dt, summ s,  0  ss,  1  disc_summ,  0  irr,  1  interv/*100%*/,  0  iter)
  10                 rules iterate( 100 ) until (abs(interv[ 1 ])<power( 10 ,- 6 ))
  11                       (ss[any]=s[CV()]/power( 1 +IRR[ 1 ],dt[CV()]/ 365 ),
  12                       irr[ 1 ] = decode(sign(disc_summ[ 1 ]),sign(sum(ss)[any]),irr[ 1 ]+sign(disc_summ[ 1 ])*interv[ 1 ],irr[ 1 ]-sign(disc_summ[ 1 ])*interv[ 1 ]/ 2 ),
  13                       interv[ 1 ]= decode(sign(disc_summ[ 1 ]),sign(sum(ss)[any]),interv[ 1 ],interv[ 1 ]/ 2 ),
  14                       disc_summ[ 1 ]=sum(ss)[any],
  15                       iter[ 1 ]=iteration_number+ 1 
  16                       )
  17                )
  18                where rn= 1 
  19   /

ЭФФЕКТИВНАЯ_СТАВКА      КОЛИЧЕСТВО_ИТЕРАЦИЙ
----------------------- -------------------
      24 . 8719215393066  %                   29 

Executed in  0 . 172  seconds

SQL> 

думаю, выгода такого подхода очевидна.
теперь немножко подробней:

алгоритм простой. Можно его назвать метод "сужающихся интервалов" (наверняка в математике что-то такое есть уже, умные коллеги подсказывают - "метод хорд", "метод ньютона"). Но т.к. память сумбурно отреагировала на слово "полином" - про способы их решения вообще отклика не последовало. То что в голову пришло - то и реализовал.

все оч просто. берем первоначальную ставку (IRR=0%), первоначальный интервал (interv=100%) - по сути как rate_step в первом варианте.
Далее считаем сумму дисконтированных денежных потоков к начальной дате. При ставке 0% она будет положительна, по мере увеличения эфф ставки - сумма будет уменьшается. В тот момент когда сумма станет =0 - нас и интересует значение эфф ставки.

первый шаг - прибавляем интервал. IRR стала 100% считаем сумму дисконтированных потоков. Если сумма сменила знак - то перебор. Мы уменьшаем интервал вдвое (до 50%) и делаем шаг в обратную сторону на интервал. Если при первом шаге - сумма потоков не изменила знак - то мы интервал не меняем (100%) и двигаемся в ту же сторону (IRR=200% на следующем шаге).
В итоге мы постепенно уменьшая интервал (шаг) будем прыгать вокруг нуля (то в +, то в -). пока необходимая точность не будет достигнута.

PS
У себя наложил условие
Код: plaintext
until (abs(interv[ 1 ])<power( 10 ,- 6 ))
т.е. точность эфф ставки задаем как 0.000001.
Можно задать точность на суммы потоков - например, если нам нужно посчитать эфф ставку, чтобы она давала точность сумм до копеек, можно сделать что-то вроде:
Код: plaintext
until (abs(disc_summ[ 1 ])< 0 . 01 )

надеюсь, кому-то пригодится.
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #34748264
Volder
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
по "методу хорд" нужно еще меньшее количество итераций для той же точности:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
SQL>  with t as (select to_date('01.01.2007','dd.mm.yyyy') dt, - 100  summ from dual union all
   2               select to_date('01.07.2007','dd.mm.yyyy') dt,  58  summ from dual union all
   3               select to_date('01.01.2008','dd.mm.yyyy') dt,  60  summ from dual)
   4                --
   5             select to_char(irr* 100 ,'999999.0000000000000')||' %' эффективная_ставка, iter количество_итераций from
   6                (select * from t
   7                 model
   8                  dimension by (row_number() over (order by dt) rn)
   9                  measures(dt-first_value(dt) over (order by dt) dt, summ s,  0  ss,  1  disc_summ,  0  irr,  1  interv/*100%*/,  0  iter)
  10                  rules iterate( 100 ) until (abs(disc_summ[ 1 ])<power( 10 ,- 6 ))
  11                        (ss[any]=s[CV()]/power( 1 +IRR[ 1 ],dt[CV()]/ 365 ),
  12                        irr[ 1 ] = decode(sign(disc_summ[ 1 ]),sign(sum(ss)[any]),irr[ 1 ]+sign(disc_summ[ 1 ])*interv[ 1 ],irr[ 1 ]-sign(disc_summ[ 1 ])*interv[ 1 ]/ 2 ),
  13                        interv[ 1 ]= decode(sign(disc_summ[ 1 ]),sign(sum(ss)[any]),interv[ 1 ],interv[ 1 ]/ 2 ),
  14                        disc_summ[ 1 ]=sum(ss)[any],
  15                        iter[ 1 ]=iteration_number+ 1 
  16                        )
  17                 )
  18                 where rn= 1 
  19   /

ЭФФЕКТИВНАЯ_СТАВКА      КОЛИЧЕСТВО_ИТЕРАЦИЙ
----------------------- -------------------
      24 . 8719394207001  %                   35 

Executed in  0 . 188  seconds

SQL> 
SQL>  with t as (select to_date('01.01.2007','dd.mm.yyyy') dt, - 100  summ from dual union all
   2               select to_date('01.07.2007','dd.mm.yyyy') dt,  58  summ from dual union all
   3               select to_date('01.01.2008','dd.mm.yyyy') dt,  60  summ from dual)
   4               --
   5            select to_char(( 1 /x- 1 )* 100 ,'999999.0000000000000')||' %' эффективная_ставка, iter количество_итераций from
   6               (select * from t
   7                model
   8                 dimension by (row_number() over (order by dt) rn)
   9                 measures(dt-first_value(dt) over (order by dt) dt, summ s,  0  ss,  0  f_a,  0  f_b,  0  f_x,  0  a,  1  b,  0  x,  0  iter)
  10                 rules iterate( 100 ) until (abs(f_x[ 1 ])< power( 10 ,- 6 ))
  11                       (ss[any]=s[CV()]*power(a[ 1 ],dt[CV()]/ 365 ),
  12                        f_a[ 1 ]=sum(ss)[any],
  13                        ss[any]=s[CV()]*power(b[ 1 ],dt[CV()]/ 365 ),
  14                        f_b[ 1 ]=sum(ss)[any],
  15                        x[ 1 ]=a[ 1 ]-f_a[ 1 ]*(b[ 1 ]-a[ 1 ])/(f_b[ 1 ]-f_a[ 1 ]),
  16                        ss[any]=s[CV()]*power(x[ 1 ],dt[CV()]/ 365 ),
  17                        f_x[ 1 ]=sum(ss)[any],
  18                        a[ 1 ]=decode(sign(f_a[ 1 ]*f_x[ 1 ]), 1 ,x[ 1 ],a[ 1 ]),
  19                        b[ 1 ]=decode(sign(f_a[ 1 ]*f_x[ 1 ]), 1 ,b[ 1 ],x[ 1 ]),
  20                        iter[ 1 ]=iteration_number+ 1 
  21                       )
  22                )
  23                where rn= 1 
  24   /

ЭФФЕКТИВНАЯ_СТАВКА      КОЛИЧЕСТВО_ИТЕРАЦИЙ
----------------------- -------------------
      24 . 8719328405865  %                   13 

Executed in  0 . 047  seconds

SQL> 

PS последний пример писал "в лоб" по алгоритму
можно упростить, чтобы на след итерации не обсчитывать те же суммы заново, которые посчитаны на предыдущем шаге.
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #34749527
ЭСП
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Да, решение интересное, но вот у нас база 9.2, а в ней model нет.
За решение большое спасибо!!!
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #34770147
Serg Kravchenko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Вот что удалось "набредить" мне для 9-ки. С функцией ЧИСТВНДОХ (она же XIRR) вроде как совпадает.
Сильно не пинать. В PL/SQL слабоват :(

-- Массив дат
type t_date_array is varray(200000) of date;
-- Массив потоков
type t_amount_array is varray(200000) of number;


function Xirr(p_date_array in t_date_array,
p_amount_array in t_amount_array,
p_guess in number default 0

) return number is
z number := 0;
step_limit number := 0;
temp number;
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);

-- Первый проход: поиск макс. даты и наличия хотя бы одного минуса и плюса в потоках
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;

exit when((round(temp * 100000) = 0) or (step_limit = 10000));

end loop;

return d;

end Xirr;
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #35327710
Viatcheslav_A
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Serg Kravchenko
if (z = 0) then
d := d - step;
else
d := d + step;
end if;

Вроде как знаки поменять надо?!
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
XIRR function in PL/SQL ?
    #37228790
Владимир П
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Подскажите а как можно добиться результата работы Excel-евской ВСД функции?
по значениям -100, 58, 60 она выдвет 12%?
я в этом вообще не бум бум, а есть задача получить значения = ВСД*12!
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #37228923
Фотография env
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Владимир П,

stfw всд
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #37388605
Volder, ваше решение очень красивое.
Как я понял в вашем примере берется только 3 даты с суммами.
Возможно ли сделать так, чтобы брался весь промежуток дат платежа?
Я имею ввиду 1 платеж в месяц.
К примеру первый платеж 16/06/2011 200000 , а последний 13/06/2014 5916.36?
Спасибо.
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #37390161
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Шелухин АлексейГробокопателям - http://www.bugtraq.ru/forum/faq/general/smart-questions.html] RTFM
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #37438807
RSA86
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Всем привет. Возникла задача рассчитать XIRR на Oracle. Воспользовался скриптом который был приведен Volder. За что ему отдельное СПАСИБО. Однако вот не задачка. Почему то данные которые я получаю в excel при расчётё отличаются от расчётов в oracle, хотя исходные данные одинаковые. Помогите плиз. А то всю голову сломал, чтобы понять что не так. Вот данные которые я получаю в oracle:
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #37438813
RSA86
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А вот что в excel:

Данные отличаются. Это только один пример из нескольких. Почему такая разница в результатах? Плиз помогите!!!
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #37438821
RSA86
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Получается вот такая разница:
oracle - 4.74%
excel - 4.82%
Почему?
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #37438827
RSA86
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
А вот формула которая используется в excel =ЧИСТВНДОХ(K2:K5;C2:C5;0,1)
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #37438893
Фотография orawish
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RSA86,

знак? наверное на сходимость надо проверять не модуль суммы, а сумму модулей
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #37439485
Фотография samatom
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
RSA86,


Не совсем по теме, точнее, рассуждения около неё:
1) IRR, сделанная на модели будет работать только для "коротких" кредитов с простой ставкой. На "длинных", например, ипотека - работает очень долго. Лучше использовать какой-нибудь численный метод, типа деления отрезка пополам (на PL\SQL) - они хорошо и быстро сходятся.
2) на моей практике любой численный метод давал такое же значение, что и в Excel.
3) также доводилось встречаться с кредитными историями, где ПСК была 4000-5000%. На таких очень сложных кредитах валились все известные мне алгоритмы расчета ПСК (включая Excel), затюненные под расчет в диапазоне 0-1000%. В таких случаях приходилось строить практически вручную график и искать корни практически визуально =)

Резюмирую, выбор метода расчета ПСК необходимо делать, опираясь на
1) тип кредита (новый или существующий, карточки, срочный),
2) срок,
3) основная масса кредитов укладывается в диапазон 0-1000%, но нужно предусмотреть случаи, когда ставка зашкалит.
4) старайтесь унифицировать расчет ПСК в организации и бизнес-процессах, реализовав её как сервис АБС, иначе потом будет поздно =)

PS: По ПСК очень много проблем, которые ещё не решены законодательно. Много чего не прописано для случаев "а что если". Из 2008-У трудно однозначно вывести все возможные случаи. Я много постил свои проблемы и вопросы на авторитетных банковских форумах, но не получил ни одного ответа, не говоря уже о своих оналитегах (сами знаете, какова квалификация большинства из них).
В банках, в которых довелось видеть ПСК, всегда можно было зацепиться и докопаться до чего-либо, т.к. каждый банк отличается от другого по части работы с ПСК (оналитеги везде же разные =)).
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
XIRR function in PL/SQL ?
    #38010061
grago
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Подскажите, плиз, а кому-то удалось повторить ЧИСТВНДОХ? Ибо бухгалтера считают ее эталоном...
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #38010239
Давно уже
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
grago,
Давно уже у всех кому надо есть. Причем на нормальных алгоритмах, точность до десятитысячных, находится за 5-6 итераций.
...
Рейтинг: 0 / 0
XIRR function in PL/SQL ?
    #38010511
hexcept
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
нашел в загашниках такой вот г...код, мож, пригодится кому:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
-- 1) temporary table create:
create global temporary table eff_rate_tmp(dt date,summ number)
on commit preserve rows
/
grant delete on eff_rate_tmp to public
/
grant insert on eff_rate_tmp to public
/
grant select on eff_rate_tmp to public
/
grant update on eff_rate_tmp to public
/

-- 2) function ddl:
create or replace function xirr return number is
-- расчет эффективной % ставки (XIRR, ЧИСТВНДОХ в Excel)
-- по данным temporary-таблицы eff_rate_tmp;
-- hexcept@gmail.com, 2008-09
 l_eff_rate number;
begin
 select round((1/x-1),6) into l_eff_rate -- 6 знаков после запятой...
 from
 (
  select * from eff_rate_tmp
  model
  dimension by ( row_number() over (order by dt) rn )
  measures
  (
   dt-first_value(dt) over (order by dt) dat,
   summ s,
   0 ss,
   0 f_a,
   0 f_b,
   0 f_x,
   0 a,
   1 b,
   0 x,
   0 iter
  )
  rules iterate(100)
  until (abs(f_x[1])< power(10,-6)) -- точность эфф.ставки задаем 0.000001
  (
   ss[any]=s[CV()]*power(a[1],dat[CV()]/365),
   f_a[1]=sum(ss)[any],
   ss[any]=s[CV()]*power(b[1],dat[CV()]/365),
   f_b[1]=sum(ss)[any],
   x[1]=a[1]-f_a[1]*(b[1]-a[1])/(f_b[1]-f_a[1]),
   ss[any]=s[CV()]*power(x[1],dat[CV()]/365),
   f_x[1]=sum(ss)[any],
   a[1]=decode(sign(f_a[1]*f_x[1]),1,x[1],a[1]),
   b[1]=decode(sign(f_a[1]*f_x[1]),1,b[1],x[1]),
   iter[1]=iteration_number+1
  )
 )
 where rn=1;

 return l_eff_rate;
end;
/

-- 3) тестовые данные:
insert into eff_rate_tmp (dt,summ) values( to_date('01.01.2007','dd.mm.yyyy'),-100 )
/
insert into eff_rate_tmp (dt,summ) values( to_date('01.07.2007','dd.mm.yyyy'),58 )
/
insert into eff_rate_tmp (dt,summ) values( to_date('01.01.2008','dd.mm.yyyy'),60 )
/

-- 4) ЧИСТВНДОХ:
select xirr from dual
...
Рейтинг: 0 / 0
25 сообщений из 34, страница 1 из 2
Форумы / Oracle [игнор отключен] [закрыт для гостей] / XIRR function in PL/SQL ?
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]