Skip to content

Instantly share code, notes, and snippets.

@sletix
Created April 4, 2019 14:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sletix/ce8c2c4ad916dd7aed030a6ec2cc772d to your computer and use it in GitHub Desktop.
Save sletix/ce8c2c4ad916dd7aed030a6ec2cc772d to your computer and use it in GitHub Desktop.
IRR Calc
require 'date'
# ruby implemenation from js
# http://jsfiddle.net/exmmo/m5kbb0up/
# https://habr.com/ru/post/233987/
module IRRCalc
# args:
#
# * входящие данные - даты платежей
# dates = [ Date.new(2014, 9, 1), Date.new(2014, 10, 1), Date.new(2014, 11, 1), Date.new(2014, 12, 1) ]
#
# * входящие данные - суммы платежей
# payments = [-100000, 34002.21, 34002.21, 34002.21 ]
#
def self.perform(dates, payments)
m = dates.count # число платежей
bp = 30.0 # Задаем базвый период bp
cbp = (365 / bp).round # Считаем число базовых периодов в году:
# заполним массив с количеством дней с даты выдачи до даты к-го платежа
days = []
m.times do |i|
days[i] = ((dates[i].to_time.to_i - dates[0].to_time.to_i) / (24.0 * 60 * 60))
end
# посчитаем Ек и Qк для каждого платежа
e = []
q = []
m.times do |k|
e[k] = (days[k] % bp) / bp
q[k] = (days[k] / bp).floor
end
# Втупую методом перебора начиная с 0 ищем i до максимального приблежения с шагом s
i = 0
x = 1
x_m = 0
s = 0.000001
while (x > 0) do
x_m = x
x = 0
m.times do |k|
x = x + payments[k] / ((1 + e[k] * i) * (1+i)**q[k])
end
i = i + s
end
i = i - s if x > x_m
# считаем ПСК
(i * cbp * 100 * 1000).floor / 1000.0
end
end
RSpec.describe IRRCalc do
let(:dates) { [ Date.new(2014, 9, 1), Date.new(2014, 10, 1), Date.new(2014, 11, 1), Date.new(2014, 12, 1) ] }
let(:payments) { [-100000, 34002.21, 34002.21, 34002.21 ] }
it 'should return calculated irr' do
expect(described_class.perform(dates, payments)).to eq 11.863
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment