一点金融数学:计算通胀和利息

最近,我不得不检查我市的公用事业部门所做的计算。 存在一个有争议的问题,只有进行正确的计算才能解决。 展望未来,我会说公共事业认为错了。 因此,在这里,我们将根据乌克兰《民法典》考虑如何正确计算通货膨胀成本和每年3%的债务债务。

第一部分描述了通货膨胀成本的计算,这是乌克兰所特有的。
第二部分(较大的部分)将专门讨论每年计算3%的问题。 它也适用于俄罗斯联邦,白俄罗斯和哈萨克斯坦,但是在这些国家中,利率不是固定的,而是取决于中央银行的再融资利率。 这个国家的其他地方看起来都没有。

第二部分非常接近于计算普通信贷交易(贷款,贷款,借款等)的利息。

图片替代

首先是理论,最后是一些代码。

所有这一切都削减了。

因此,我从公用事业获得了一份文件“通货膨胀成本和每年3%的累积报表”。 我对其进行了检查,结果发现它是用错误的算法计算的,因此很有趣,因为它必须执行乌克兰民法典条款的要求。

应该考虑的是《乌克兰民法典》中写的:
乌克兰民法典第625条。 “违反金钱义务的责任”
2.延迟履行货币义务的债务人应债权人的要求,有义务在考虑到整个延迟期间的既定通货膨胀指数的基础上,偿还债务金额,以及每年逾期金额的3%...
根据债务数字,公用事业公司计算了每年通货膨胀成本和3%。

通货膨胀成本


此外,我将讨论计算算法,而不是特定的数字。

通货膨胀是一个以货币贬值为特征的过程,即购买力下降和价格普遍上涨。 除通货膨胀外,现金流量计算的最终结果是非常随意的。

通货膨胀指数(II)或消费者物价指数(CPI),消费者物价指数(CPI)-一种用来衡量经济中特定时期内商品和服务(消费者篮子)平均价格水平的价格指数类型之一。

人工智能是表征人口为非生产性消费而获得的商品和服务的总体价格水平动态的指标。 这是增长指数,它显示了报告所述期间平均价格上涨的百分比。

在乌克兰,AI和CPI是同义词

由于价格指数是一个环比指数,因此对于一个接一个的时期,它是通过乘以指标来计算的,例如101%* 102%=(1.01 * 1.02)* 100%= 103.02%。

AI由乌克兰国家统计委员会计算,并在官方期刊中发布。 这些关键数据可用于重新计算现金金额。
社区工作者怎么看?

水电费帐单文件的一部分

最后结算日期为2016年12月7日。

让我们看看公共工作者如何获得通货膨胀成本比率?

用肉眼可以看到,在第三(和第五列)中,应该是整数部分0,而不是整数部分1。它们是如何得到小数部分的?

2016年9月。小数部分0.028。 9月的付款期限为2016年10月20日。小数部分对应于国家统计委员会发布的2016年10月的通胀指数-102.8%

2016年8月。小数部分0.0465。 8月的付款期限为2016年9月20日。小数部分对应于9月份的通胀指数乘以10月份的II:101.8%* 102.8%= 104.65%,或以股票计算,为1.018 * 1.028 = 1.046504。 公用事业将四舍五入到1.0465并打印此数字,尽管应该删除该单位,因为在下一列中,它们仅打印通货膨胀成本的金额,而不打印累积的金额。

2016年7月或更早。 我执行了这些计算并恢复了算法。 从提供服务的月份起的下一个月(到期日)开始,到2016年10月,公用事业乘以通胀指数。

起点只是部分正确。 正如我将在稍后展示的那样,在一般情况下,确实需要从本月开始计算,但是在我们的特殊情况下,应该跳过第一个月(将AI等于100%)。

乘法的终点 。 由于计算的最后一天是12月,您需要完成12月,因此通常是这种情况。 正如我稍后将显示的那样,在这种特殊情况下,还需要跳过12月(也将AI等于100%)。 并且在12月7日,12月的AI没有时间发布。

为什么在任何地方都没有考虑到11月? 我认为他们只是忘记将其输入系统。

现在让我们看看如何计算通胀指数。 必要时 -于2012年7月17日乌克兰最高经济法院第01-06 / 928/2012号信息通报中描述[6]。

我将给出该段的一部分:
将在本月考虑从每月1日到15日偿还的债务金额,并且如果要从每月16日到31日偿还债务,则从下个月开始计算。

同样,如果已从一个月的1到15天还清债务,则不计入本月的价格计算通货膨胀成本;如果一个月的16至31天,则应将本月的通货膨胀成本计算在内。
在我们的情况下,付款期限是提供服务的月份之后的下一个月的第20天,即 对于9月提供的服务,结算的开始日期是2016年10月21日,截止日期是2016年12月7日。

即 正确地说:对于2016年9月提供的服务,请考虑从10月到12月的三个月的通货膨胀(通过游标或周期),但在第一个月和上个月,请使AI等于1(100%),并仅考虑11月。

2016年11月,人工智能占101.8%,即 系数应为0.0180,而不是0.0280。 我之前写过有关牵头单位的文章。

每年3%


让我们看看公共服务每年如何获得3%的系数和应计金额? 这是上表的第五列。

如我先前所写,不应有前导单位,而应有0。我们查看小数部分,请注意,它存在某种可疑的舍入方式-前一个月每个月比当月多0.0025。

通过简单的计算,可以确定公用事业不用再费力就将3%分成12个月,每月收取0.0025或0.25%,并且对于每个完整和不完整的延迟月份都应计入该百分比。 是的,如果您看一下2016年10月,付款截止日期是11月21日,计算是在12月7日进行的,那么对于一个不完整的月份,他们的计算是0.25%。

这种方法钦佩残酷的直率,但是,正如我稍后将要说明的那样,金融数学并不知道这种算法。

乌克兰的立法和金融数学并未对每年如何收取3%的费用给出明确的答案。 我搜索了几本与此主题相关的书,但是这些书都是古老的,可以追溯到2002年。 因此,这些书中的算法将得到补充,因为有可能从更现代和西方的文章中搜索到谷歌。 [1]已于2007年重印,但找不到最新的俄语书籍。 也许是因为金融数学作为一门科学起源于很久以前,而在计算机出现之前很久,“信用”和“信用利息”等概念就在几百年前出现了。 自2002年以来,算法没有太大变化。

但是西方对这个问题的看法与俄语书籍中所描述的不同。 我将首先从俄语书籍中引用信息,然后从西方文章中引用信息,以指出它们的重合之处。

下面的内容与特定的案例有关,即每年拖欠3%的利息,但是如果根据单利而非复利计息,则还可以归纳为计算其他信用关系的利息。

根据艺术。 625根据简单利率计划,乌克兰《民法典》每年需要累加3%。 要计算利息金额,必须将债务金额(一般情况下为贷款本金)乘以3%的标准化年利率,再乘以延误所占的年比例(年限)。 如果延迟时间超过一年,则此份额可能会超过1。

延迟的持续时间以天数表示。 在更一般的情况下,贷款期限可以以天表示(此处不考虑贷款期限以月和年表示的情况)。 3%的年利率是当年单利的标准化利率。 因此,您需要能够将以天为单位的延迟(信用)持续时间带入以年为单位的持续时间。 这不是一件容易的事,因为一年的长短取决于年份。

以天为单位的持续时间是日历间隔持续时间的唯一定义度量,而不是以年为单位的持续时间。 后者的定义需要以将以天为单位的持续时间转换为以年为单位的持续时间的规则的形式进行说明。 用于将以天为单位的持续时间转换为以年为单位的持续时间的许多标准方法是基于将天数除以所谓的“年度除数” 。 年度除数的最典型值是360天和365天。 在最简单的情况下,除数是一个常数,与间隔无关。 期间中的天数始终充当红利(分数的分子)。
并且您需要确定以天为单位计算条件的过程。 让我们考虑两个牵强的示例:

  1. 从2018年12月6日至2018年12月7日,客户从银行获得短期贷款。 合同的期限是多少?我需要多少天才能产生利息? 显然-1天。
  2. 订户从电信运营商处预订了服务,有效期为2018年12月6日至2018年12月7日。 服务的提供方式是什么?我必须在多少天内支付服务订阅费? 显然是2天。

有什么区别?

事实是,日期不是时间轴上的一点,而是可以用两种方式写的间隔(回想一下,间隔边界处的方括号表示该点在间隔中,括号是不在间隔中的点):

  • [06.12.2018 00.00.00,12/07/2018 00.00.00)-此处间隔的右边界不包含在间隔中,
  • [06/12/2018 00.00.00,12/06/2018 23.59.59]-此处间隔的右边界包含在间隔中。

在第一种情况(1)中,当未明确给出时间间隔,而是以日期之间的间隔形式给出时,通常会计算出确切的天数,包括第一天或最后一天,但不能同时给出这两者。 [4]用同样的话说:“发放贷款的那天和还款日被认为是一天。”

该方法确定所谓的精确时间。 还可以很容易地确定两个日期是否都指向同一年,并且可以使用日历显示该年中每一天的序列号。 然后,从延迟日期的序列号中减去早期日期的序列号就足够了,结果将给出该期间的持续时间。 在Oracle数据库中,您可以简单地减去截断到一天(舍弃时间)的日期(DATE类型),一个到另一个,差是整数天数。

在第二种情况(2)中,我们谈论的是天数,因此我们计算了两天。

此外,我从这样的事实出发,例如在公共服务的情况下,付款截止日期是9月20日(即这是最后一个可接受的付款日),并且已经在9月21日付款,即已经确定了您的天数。显然,延迟必须等于1天。 如果您面临间隔不包括左边界的指示,请向右移动左边界一天。

我们如何计算天数和分数分子? 有一个精确的计算和一个近似的计算。

准确计算天数


俄语练习


本文进一步基于[1]。

选择周期中确切的天数作为除数,以及两个最常见的规则给出最常见的规则作为分母-360或365的年度除数:

规则(R1)ACT / 365。 对于此规则,以天为单位的持续时间除以数字365。我注意到a年的长度将为366/365 = 1.00274,这不止一个。 ACT / 365规则错误在一个时期内越大,越多。 因此,此规则每年产生的3%的值将超过3%。

规则(R2)ACT / 360。 这就是所谓的“银行规则”,根据该规则,以天为单位的持续时间除以360。该规则进一步增加了缺口的年度长度。 对于非-年,其长度将为365/360 = 1.01389,对于a年,则为366/360 = 1.01667。 自然,时间越长,以年计的“延伸”程度就越大。 该规则最常用于与货币市场有关的计算中,即 市场短期债务,例如银行存款,票据,商业票据,存款证明等。每年3%的值将比使用以前的规则时更大。

如果接受的年度除数等于360天,则使用这种除数获得的利息称为普通利息或商业利息。 如果除数等于365,或者我将在后面显示366天,则该利息称为精确利息。

显然,普通百分数比精确百分数大得多。

尽管第一个规则比第二个规则更准确,但是两个规则都不够准确。

为了消除leap年对结果的影响,还有另外两个规则。

规则(R3)ACT / 365,日本。 以与ACT / 365规则相同的方式执行计算,但是在计算间隔持续时间(分数分子)时,不包括leap日。 年度除数保持不变。

根据Wiki:
在许多欧洲国家中,直到18世纪,人们都认为2月29日是不存在的日子,这一日期没有法律地位。 通常,由于问题的正式方面和在法院解决案件方面的困难,当天没有进行交易,没有付款,没有以债务支付等。


另一种方式与除数的实际变化有关。

规则(R4)ACT / ACT基本。 我们将所需时间分为三个部分:

  • 第一部分,从开始日期到开始日期所在的年末,
  • 第三部分-从结束日期所在的年份开始到结束日期,
  • 第二部分-第一部分和第三部分之间为0或几个完整的日历年。

通过将天数除以年度除数365或366(取决于是否为leap年)来获得第一部分和第三部分的持续时间。 根据定义,第二个周期的持续时间由整数个完整日历年组成,无论它们是否跨越。 通过将三个部分的持续时间相加(以三个数字表示,其中第二个为整数,第一个和第三个为小数),可以得出整个周期的年数。

规则(R5)ACT / ACT的“简短”修改,期限少于一年。 在这种情况下,以天为单位的持续时间除以年度除数365或366,取决于搜索期间中是否有2月29日的日期? 短ACT / ACT规则的一个特点是,如果间隔不适合日历年(其结束时间属于相邻年份),则应用基本规则和短规则将导致不同的结果。

西方实践


在西方实践中,对规则的描述有所不同。 通常,相同的俄语规则使用不同的名称,而且一次也不会使用一个。

该信息进一步基于[2]。 我是Vicki,我检查了所有来源并使用了其他Google信息:在天数确切的规则中,所有内容都是正确的,但是在天数近似的规则中,还有其他一些对规则的解释,因此它们经常会随着时间而变化,因此,将规则付诸实践,本文的大概天数不够。

规则(W1)实际/实际ISDA。 该规则的结果与(R4)“ ACT / ACT main”相同,但表述方式不同:该间隔分为leap年和非le年,无论它们是完整的还是不完整的,而且,天数总和years年除以365,非le年的天数总和除以366,两个数字相加。

西方惯例中该规则的其他名称:实际/实际,行为/行为,实际/ 365,行为/ 365。 是的,姓氏与规则(R1)相同,尽管规则的本质不同。

规则(W2)实际/ 365固定。 此规则完全重复规则(R1)ACT / 365-天数除以365。

西方惯例中该规则的其他名称:Act / 365 Fixed,A / 365 Fixed,A / 365F,英语。

规则(W3)实际/ 360。 此规则重复(R2)ACT / 360-确切的天数除以360。

规则(W4)实际/ 364。 天数除以364。在俄语国家中没有类似的天数。

规则(W5)实际/ 365L。 它包含两个调整:
  1. 每年付款。 如果日期是该时间段内的2月29日,则该时间段的天数除以年度除数366,如果不是,则除以365。在这种情况下,它与规则(R5)ACT / ACT“简短修改”相吻合。
  2. 如果付款频率与年度不同。 如果结束日期是a年(不一定等于2月29日),则年度除数为366,否则为365。在俄语国家中,没有类似的数字。

另一个名称是ISMA-Year。

规则(W6)实际/实际AFB。 它包含两个调整:
  1. 少于一年的期间的主要日期:如果日期是该期间内的2月29日,则该期间的天数除以年度除数366,否则除以365。 。
  2. 延长,期限超过一年:从结束日期到开始日期,会计算一个整数整年。 如果余额少于一年,则适用主要规则。 总结了基本规则下的完整年份数和年度份额。

如果倒数是在2月28日进行的,那么在倒数年前存在细微差别,而整整整整一年之后,该年被证明是be年。在这种情况下,应该采用n年前的日期为2月29日。我补充说,如果倒计时是从2月29日开始进行的,那么整整年前的数字不是4的倍数,因此,前一年也不是a年,这也是一个问题。我在这里没有详细介绍。但是您可以参考[2]中的链接。

还有“樱桃蛋糕” 规则(W7)1/1。天数除以年度除数365.25。用于与通货膨胀有关的计算。

预计天数


上面列出的规则是基于日历天数的确切持续时间。但是,有时会基于所谓的简化的或近似的天数计数方案。这些计划的目的是使所有月份的持续时间“平均”到30天。因此,一年将由30天的12个月组成,即在360天之内。因此,这些规则的年度除数(分数的分母)将始终为360,并且分子以特殊方式计算。

由于在大多数情况下(但当然并非总是),贷款的确切天数不只是近似值(可以通过确定一年中一个月的平均天数来轻松看出,即30.44),因此通常使用贷款的确切天数来计算利息增长比估计要大。 [4]

此规则的最简单版本,即所谓的基本规则30/360,描述如下(以下是有关书[1]-俄语实践的信息):

基本规则30/360。日期之间的大概天数是
 360 *(y2-y1)+ 30 *(m2-m1)+(d2-d1), 
y,m,d-第二和第一个日期中的年,月和日。

该规则出现在创建第一个计算设备之前,并在财务实践中大大节省了计算操作的成本。尽管现在对简化方法的需求已经消失,但是在实践中已经站稳了脚跟,根据传统,它们有时在当前使用。

该规则适用于强制性的修改指示,该修改指示了如何处理月份的最后几天:

俄语练习


由[1]给出。

规则(R6)30/360 ISDA。如果d1 = 31,则d1'= 30,否则d1'= d1。如果d2 = 31且d1'= 30,则d2'= 30,否则d2'= d2。

规则(R7)30E / 360。如果d1 = 31,则d1'= 30,否则d1'= d1。如果d2 = 31,则d2'= 30,否则d2'= d2。

此规则是ISDA规则30/360的变体,主要在欧洲使用,因此在该规则的名称中标有“ E”。仅当第二个日期也是31日时,它才与ISDA规则30/360不同。欧洲版本始终将其转换为第30个数字,而不管第一个日期如何。

规则(R8)30/360 PSA。如果d1 = 31或d1是2月的最后一天,则d1'= 30,否则d1'= d1。如果d2 = 31且d1'= 30,则d2'= 30,否则d2'= d2。

[1]中对30/360 SIA规则的描述很可能是错误的,因此在此不再赘述。

西方实践


根据[2]给出。

规则(W8)30/360保证金基础。与(R6)30/360 ISDA相同。其他名称:30A / 360。

规则(W9)30E / 360。与(R7)30E / 360相同。其他名称:30/360 ICMA,30S / 360,以欧洲债券为基础(ISDA 2006),特殊德语。

规则(W10)30E / 360 ISDA。如果d1是该月的最后一天,则d1'= 30。如果d2是非二月的最后一天,则d2'= 30。

其他名称:30E / 360 ISDA,基于欧洲债券的标准(ISDA 2000),德语。

规则(W11)30/360 SIA。如果d1是2月的最后一天,而d2是2月的最后一天,则d2'= 30。如果d1 = 31或2月的最后一天,则d1'= 30,否则d1'= d1。如果d1'= 30且d2 = 31,则d2'= 30,否则d2'= d1。

规则(R4)ACT / ACT,(W1)实际/实际ISDA,(W2)实际/ 365固定规则也称为“英语练习”。

规则(R2)ACT / 360和(W3)实际/ 360也称为“法语练习”。

规则(R7)30E / 360,(W9)30E / 360和(W10)30E / 360 ISDA也称为“德国惯例”或“德国惯例”。


因此,考虑到确切的利息和普通的利息,以及计算利息的确切和近似的天数,我们得到了四种计算简单利息的方法(规则的名称在俄语中表示):

  1. 具有确切天数的正常利息(ACT / 360-银行业务规则),
  2. 确切的百分比以及确切的天数(ACT / 365,ACT / ACT),
  3. 正常的利息,大约为几天(30/360),
  4. 大约有几天的确切百分比。

最常用的第一种方法称为银行法则,第二种和第三种方法较少见,而第四种则几乎没有。 [4]说:“ ...具有确切利率和大约贷款天数的计算选项是没有意义的,并不适用。”

以上对周期的近似持续时间(以一年的分数表示)的计算显示了所应用规则的简单性和多样性。它们的应用(以及原产地)取决于国家,货币,金融工具的类型,专业协会,协议。 [1]

结论:

在乌克兰的公共事业中,我如何算上3%?

浅析艺术运用的司法实践。乌克兰《民法》第625条指出,通常使用(R1)ACT / 365 [3]方法,但方法尚不明确。我认为您仍然需要申请(R4)ACT / ACT,这就是为什么:如果您使用ACT / 365方法在整个leap年中应计3%,那么利息金额将等于3.008219%,这是债务(或贷款主体的规模)一百万个货币单位将产生CU 82.19的盈余法律规定的年度标准利率超过3%。随着利息的逐步积累,这将变得尤为重要。

我将不胜感激,尤其是银行员工的意见。

使用的资料来源

1)Bocharov,P.P.,Kasimov,Yu.F.金融数学。莫斯科:加尔达基,2002年
2)日计数惯例,zh.wikipedia.org/wiki/Day_count_convention
3)艺术应用分析。乌克兰《民法典》第625条的民事诉讼程序,zib.com.ua / ua / 74602-analiz_praktiki_zastosuvannya_st_625_civilnogo_kodeksu_ukrai.html
4)Chetyrkin E.M.金融数学。莫斯科:案例,2005年
5)日计数惯例和应计因素,docs.fincad.com
/ support / developerfunc / mathref / Daycount.htm 6)乌克兰最高经济法院的通知信,日期为01-06 / 928/2012,日期为2012年7月17日,zakon.rada.gov.ua/laws/show/v_928600-12

现在在Oracle数据库上有一些代码:

这是我为我的特殊情况制作的一个软件包-它计算通货膨胀成本和乌克兰每年3%。

Oracle数据库中没有聚合函数可乘以通货膨胀值。因此,我使用对数的总和。

隐藏文字
CREATE OR REPLACE TYPE DEBT_OVERHEAD_T as object (ID number, DEBT_DATE date, OVERHEAD_AMOUNT number); CREATE OR REPLACE TYPE DEBT_WITH_INF_AMOUNT_T as object (ID number, DEBT_DATE date, DEBT_AMOUNT number, PAYMENT_DATE date, INF_MONTH date, INF_RATE number, SKIP_INFLATION char (1), INF_RATE_ACCUMULATED number , INF_COEF_ACCUMULATED number, INF_AMOUNT_ACCUMULATED number, INF_AMOUNT_MONTH number); CREATE OR REPLACE TYPE DEBT_WITH_INF_T as object (ID number, DEBT_DATE date, DEBT_AMOUNT number, PAYMENT_DATE date, INF_MONTH date, INF_RATE number, SKIP_INFLATION char (1)); CREATE OR REPLACE TYPE DEBT_WITH_PCT_AMOUNT_T as object (ID number, DEBT_DATE date, DEBT_AMOUNT number, PAYMENT_DATE date, PCT_YEAR number, PCT_YEAR_DAYS number, PCT_YEAR_PCT_PER_DAY number, PCT_YEAR_BEGIN_DATE date , PCT_YEAR_END_DATE date, PCT_YEAR_DAYS_CALC number, PCT_YEAR_PCT_PER_YEAR number, PCT_AMOUNT_PER_YEAR number); CREATE OR REPLACE TYPE DEBT_OVERHEAD_LIST_T as table of DEBT_OVERHEAD_T; CREATE OR REPLACE TYPE DEBT_WITH_INF_AMOUNT_LIST_T as table of DEBT_WITH_INF_AMOUNT_T; CREATE OR REPLACE TYPE DEBT_WITH_INF_LIST_T as table of DEBT_WITH_INF_T; CREATE OR REPLACE TYPE DEBT_WITH_PCT_AMOUNT_LIST_T as table of DEBT_WITH_PCT_AMOUNT_T; CREATE OR REPLACE PACKAGE CALC_OVERHEADS_P is function GET_DEBT_WITH_INF (p_debt_date_begin date, p_debt_date_end date, p_last_collection_date date) return DEBT_WITH_INF_LIST_T; function GET_DEBT_WITH_INF_AMOUNT (p_debt_date_begin date, p_debt_date_end date, p_last_collection_date date) return DEBT_WITH_INF_AMOUNT_LIST_T; function GET_DEBT_WITH_INF_AMOUNT_TOTAL (p_debt_date_begin date, p_debt_date_end date, p_last_collection_date date) return DEBT_OVERHEAD_LIST_T; function GET_DEBT_WITH_PCT_AMOUNT (p_debt_date_begin date, p_debt_date_end date, p_last_collection_date date) return DEBT_WITH_PCT_AMOUNT_LIST_T; function GET_DEBT_WITH_PCT_AMOUNT_TOTAL (p_debt_date_begin date, p_debt_date_end date, p_last_collection_date date) return DEBT_OVERHEAD_LIST_T; end; / CREATE OR REPLACE PACKAGE BODY CALC_OVERHEADS_P is function GET_DEBT_WITH_INF (p_debt_date_begin date, p_debt_date_end date, p_last_collection_date date) return DEBT_WITH_INF_LIST_T is ret_value DEBT_WITH_INF_LIST_T; begin with T1 as (select a.ID, a.DEBT_DATE, a.DEBT_AMOUNT, a.PAYMENT_DATE, b.INF_MONTH, c.AVAL as INF_RATE from DEBTS a cross apply (select add_months (trunc (a.PAYMENT_DATE, 'month'), rownum - 1) as INF_MONTH from dual connect by level <= months_between (trunc (p_last_collection_date, 'month'), trunc (a.PAYMENT_DATE, 'month')) + 1) b left join INFLATION c on c.ADATE = b.INF_MONTH and c.TYP = 'M' where a.DEBT_DATE between p_debt_date_begin and p_debt_date_end ) , T2 as (select ID, DEBT_DATE, DEBT_AMOUNT, PAYMENT_DATE, INF_MONTH, INF_RATE , case when trunc (PAYMENT_DATE, 'month') = INF_MONTH and extract (day from PAYMENT_DATE) between 16 and 31 then 'Y' when trunc (p_last_collection_date, 'month') = INF_MONTH and extract (day from p_last_collection_date) between 1 and 15 then 'Y' end as SKIP_INFLATION from T1) select DEBT_WITH_INF_T (ID, DEBT_DATE, DEBT_AMOUNT, PAYMENT_DATE, INF_MONTH, INF_RATE, SKIP_INFLATION) bulk collect into ret_value from T2; return ret_value; end; function GET_DEBT_WITH_INF_AMOUNT (p_debt_date_begin date, p_debt_date_end date, p_last_collection_date date) return DEBT_WITH_INF_AMOUNT_LIST_T is ret_value DEBT_WITH_INF_AMOUNT_LIST_T; begin with T1 as (select ID, DEBT_DATE, DEBT_AMOUNT, PAYMENT_DATE, INF_MONTH, INF_RATE, SKIP_INFLATION , exp (sum (ln (case when SKIP_INFLATION = 'Y' or INF_RATE is null then 1 else INF_RATE / 100 end)) over (partition by ID order by INF_MONTH rows between unbounded preceding and current row)) * 100 as INF_RATE_ACCUMULATED from table (CALC_OVERHEADS_P.GET_DEBT_WITH_INF (p_debt_date_begin, p_debt_date_end, p_last_collection_date))) , T2 as (select ID, DEBT_DATE, DEBT_AMOUNT, PAYMENT_DATE, INF_MONTH, INF_RATE, SKIP_INFLATION, INF_RATE_ACCUMULATED , (INF_RATE_ACCUMULATED - 100) / 100 as INF_COEF_ACCUMULATED , round (((INF_RATE_ACCUMULATED - 100) / 100) * DEBT_AMOUNT, 2) as INF_AMOUNT_ACCUMULATED from T1) select DEBT_WITH_INF_AMOUNT_T (ID, DEBT_DATE, DEBT_AMOUNT, PAYMENT_DATE, INF_MONTH, INF_RATE, SKIP_INFLATION, INF_RATE_ACCUMULATED, INF_COEF_ACCUMULATED, INF_AMOUNT_ACCUMULATED , INF_AMOUNT_ACCUMULATED - lag (INF_AMOUNT_ACCUMULATED, 1, 0) over (partition by ID order by INF_MONTH)) bulk collect into ret_value from T2; return ret_value; end; function GET_DEBT_WITH_INF_AMOUNT_TOTAL (p_debt_date_begin date, p_debt_date_end date, p_last_collection_date date) return DEBT_OVERHEAD_LIST_T is ret_value DEBT_OVERHEAD_LIST_T; begin with T1 as (select ID , DEBT_DATE , round ((exp (sum (ln (case when SKIP_INFLATION = 'Y' then 1 else INF_RATE / 100 end))) - 1) * DEBT_AMOUNT, 2) as INF_AMOUNT from table (CALC_OVERHEADS_P.GET_DEBT_WITH_INF (p_debt_date_begin, p_debt_date_end, p_last_collection_date)) group by ID, DEBT_DATE, DEBT_AMOUNT) select DEBT_OVERHEAD_T (ID, DEBT_DATE, INF_AMOUNT) bulk collect into ret_value from T1; return ret_value; end; function GET_DEBT_WITH_PCT_AMOUNT (p_debt_date_begin date, p_debt_date_end date, p_last_collection_date date) return DEBT_WITH_PCT_AMOUNT_LIST_T is ret_value DEBT_WITH_PCT_AMOUNT_LIST_T; begin with T1 as (select * from DEBTS a cross apply (select extract (year from PAYMENT_DATE) + level - 1 as PCT_YEAR from dual connect by level <= extract (year from p_last_collection_date) - extract (year from PAYMENT_DATE) + 1) where DEBT_DATE between p_debt_date_begin and p_debt_date_end ) , T2 as (select ID, DEBT_DATE, DEBT_AMOUNT, PAYMENT_DATE, PCT_YEAR, to_date ('31.12.'||PCT_YEAR, 'DD.MM.YYYY') - to_date ('01.01.'||PCT_YEAR, 'DD.MM.YYYY') + 1 as PCT_YEAR_DAYS from T1) , T3 as (select ID, DEBT_DATE, DEBT_AMOUNT, PAYMENT_DATE, PCT_YEAR, PCT_YEAR_DAYS , 0.03 / PCT_YEAR_DAYS as PCT_YEAR_PCT_PER_DAY from T2) , T4 as (select ID, DEBT_DATE, DEBT_AMOUNT, PAYMENT_DATE, PCT_YEAR, PCT_YEAR_DAYS, PCT_YEAR_PCT_PER_DAY , greatest (PAYMENT_DATE + 1, to_date ('01.01.'||PCT_YEAR, 'DD-MM-YYYY')) as PCT_YEAR_BEGIN_DATE , least (to_date ('31.12.'||PCT_YEAR, 'DD-MM-YYYY'), p_last_collection_date) as PCT_YEAR_END_DATE from T3) , T5 as (select ID, DEBT_DATE, DEBT_AMOUNT, PAYMENT_DATE, PCT_YEAR, PCT_YEAR_DAYS, PCT_YEAR_PCT_PER_DAY, PCT_YEAR_BEGIN_DATE, PCT_YEAR_END_DATE , PCT_YEAR_END_DATE - PCT_YEAR_BEGIN_DATE + 1 as PCT_YEAR_DAYS_CALC , (PCT_YEAR_END_DATE - PCT_YEAR_BEGIN_DATE + 1) * PCT_YEAR_PCT_PER_DAY as PCT_YEAR_PCT_PER_YEAR , round ((PCT_YEAR_END_DATE - PCT_YEAR_BEGIN_DATE + 1) * PCT_YEAR_PCT_PER_DAY * DEBT_AMOUNT, 2) as PCT_AMOUNT_PER_YEAR from T4) select DEBT_WITH_PCT_AMOUNT_T (ID, DEBT_DATE, DEBT_AMOUNT, PAYMENT_DATE, PCT_YEAR, PCT_YEAR_DAYS, PCT_YEAR_PCT_PER_DAY, PCT_YEAR_BEGIN_DATE, PCT_YEAR_END_DATE, PCT_YEAR_DAYS_CALC, PCT_YEAR_PCT_PER_YEAR, PCT_AMOUNT_PER_YEAR) bulk collect into ret_value from T5; return ret_value; end; function GET_DEBT_WITH_PCT_AMOUNT_TOTAL (p_debt_date_begin date, p_debt_date_end date, p_last_collection_date date) return DEBT_OVERHEAD_LIST_T is ret_value DEBT_OVERHEAD_LIST_T; begin select DEBT_OVERHEAD_T (ID, DEBT_DATE, sum (PCT_AMOUNT_PER_YEAR)) bulk collect into ret_value from table (CALC_OVERHEADS_P.GET_DEBT_WITH_PCT_AMOUNT (p_debt_date_begin, p_debt_date_end, p_last_collection_date)) group by ID, DEBT_DATE; return ret_value; end; end; 

Source: https://habr.com/ru/post/zh-CN466401/


All Articles