Netezza SQL如何计算不同利率的每日复利

时间:2020-02-28 23:43:43

标签: netezza

我在弄清楚如何计算不同利率期间的初始金额的每日复利时遇到麻烦,无法得出包括每个利率期间的利息金额的新总计。面临的挑战是,对于每个后续利率期,您都必须计算金额的利息加上之前的利息!!!因此,这不是一个简单的总计。

例如,使用以下费率表。

rate from date rate to date rate
-------------- ------------ ----
2013-07-15     2013-09-30   3
2013-10-01     2013-12-31   4
2014-01-01     2014-03-31   3

使用$ 32,550.37的初始金额,我必须遍历每个利率期并计算利息,最终的金额为$ 33,337.34。

rate from date rate to date rate daysx amount     interest
-------------- ------------ ---- ----- ---------- --------
2013-07-15     2013-09-30   .03  78    32,550.37  209.34
2013-10-01     2013-12-31   .04  92    32,759.71  331.94
2014-01-01     2014-03-31   .03  90    33,091.65  245.69
                          Final Amount 33,337.34

例如,初始金额$ 32,550.37的利息为$ 209.34,利率为3%。对于第二个利率期,我将该利息加到金额中,即32,759.71美元,然后计算32,759.71美元的利息为4%。等等

我正在使用的Netezza不允许使用递归SQL,所以我一直在尝试使用窗口函数,但还没有成功……

DROP TABLE TRATES;
CREATE TABLE TRATES (RATE_FROM_DATE DATE, RATE_TO_DATE DATE, RATE DECIMAL(10,2));
INSERT INTO TRATES VALUES ('2013-07-15','2013-09-30',.03);
INSERT INTO TRATES VALUES ('2013-10-01','2013-12-31',.04);
INSERT INTO TRATES VALUES ('2014-01-01','2014-03-31',.03);

SELECT TRATES.*
     , DAYS_BETWEEN(RATE_FROM_DATE, RATE_TO_DATE)+1 AS DAYSX
     , (AMOUNT * POW(1+(RATE)/365,(DAYS_BETWEEN(RATE_FROM_DATE, RATE_TO_DATE)+1)))) – AMOUNT
       AS INTEREST
     , FIRST_VALUE(AMOUNT) OVER(ORDER BY RATE_FROM_DATE)
       *(POW(1+(RATE/100)/365,(DAYS_BETWEEN(RATE_FROM_DATE, RATE_TO_DATE)+1)))
       AS NEW_AMOUNT       
FROM TRATES
JOIN (SELECT 32550.37 AS AMOUNT) AS TPARMS ON 1=1
;

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

我使用的事实是利率的变动并不取决于变动发生的顺序,因此3天以3%紧随其后,但4天以2%得出的结果与4天以2%紧随其后的结果相同3%,3天。 此外,对数求和将使您可以将行相乘: https://blog.jooq.org/2018/09/21/how-to-write-a-multiplication-aggregate-function-in-sql/

简而言之:log(a1)+ log(a2)+ .. + log(an)= log(a1 * a2 * .. * an)

这几乎是一个有用的解决方案(并且表现合理):

DROP TABLE TRATES if exists;
CREATE temp TABLE TRATES (RATE_FROM_DATE DATE, RATE_TO_DATE DATE, RATE DECIMAL(10,2));
INSERT INTO TRATES VALUES ('2013-07-15','2013-09-30',.03);
INSERT INTO TRATES VALUES ('2013-10-01','2013-12-31',.04);
INSERT INTO TRATES VALUES ('2014-01-01','2014-03-31',.03);

create temp table dates as 
select '2010-01-01'::date -1+row_number() over (order by null) as Date
from ( select * from 
    _v_dual_dslice a cross join _v_dual_dslice b cross join _v_dual_dslice c cross join _v_dual_dslice d
    limit 10000 ) x
;

SELECT AMOUNT*pow(10,sum(log(1+rate::double/365)))
FROM TRATES join dates
on date between RATE_FROM_DATE and RATE_TO_DATE
JOIN (SELECT 32550.37 AS AMOUNT) AS TPARMS ON 1=1
group by AMOUNT

我敢肯定,您可以通过一些努力使它更漂亮,甚至在需要的情况下让它在260天的间隔中的指定日期返回结果