@@ -5,6 +5,7 @@ class Loan
55 PAYMENT_TYPE_MAPPING = { end : 0 , beginning : 1 } . freeze
66
77 # @return [Float] The amount of loan request (I.e. a present value)
8+ # You can use #pv method to calculate value if param is not defined.
89 # Defaults to 0.
910 attr_accessor :amount
1011
@@ -27,23 +28,32 @@ class Loan
2728 attr_accessor :duration
2829
2930 # @return [Float] Future value.
31+ # You can use #fv method to calculate value if param is not defined.
3032 # Defaults to 0.
3133 attr_accessor :future_value
3234
35+ # @return [Float] The (fixed) periodic payment.
36+ # You can use #pmt method to calculate value if param is not defined.
37+ attr_accessor :payment
38+
39+ # Create a new Loan instance.
3340 def initialize ( **options )
3441 initialize_payment_type ( options [ :ptype ] )
3542 @nominal_rate = options . fetch ( :nominal_rate , 0 ) . to_f
3643 @duration = options . fetch ( :duration , 1 ) . to_f
3744 @amount = options . fetch ( :amount , 0 ) . to_f
3845 @future_value = options . fetch ( :future_value , 0 ) . to_f
39- @monthly_rate = @nominal_rate / 12
46+ @payment = options [ :payment ]
47+ @monthly_rate = @nominal_rate / 12
4048 end
4149
4250 # Pmt computes the payment against a loan principal plus interest (future_value = 0).
4351 # It can also be used to calculate the recurring payments needed to achieve
4452 # a certain future value given an initial deposit,
4553 # a fixed periodically compounded interest rate, and the total number of periods.
4654 #
55+ # Required Loan arguments: nominal_rate, duration, amount, future_value*
56+ #
4757 # @return [Numeric] The (fixed) periodic payment.
4858 #
4959 # @example
@@ -69,6 +79,36 @@ def pmt
6979 ( -future_value + amount * factor ) / second_factor
7080 end
7181
82+ # Fv computes future value at the end of some periods (duration).
83+ # Required Loan arguments: nominal_rate, duration, payment, amount*
84+ #
85+ # @param payment [Float] The (fixed) periodic payment.
86+ # In case you don't want to modify the original loan, use this parameter to recalculate fv.
87+ #
88+ # @return [Float] The value at the end of the `duration` periods.
89+ #
90+ # @example
91+ # require 'finance_rb'
92+ # Finance::Loan.new(nominal_rate: 0.05, duration: 120, amount: -100, payment: -200).fv
93+ # #=> 15692.928894335748
94+ #
95+ # @see http://www.oasis-open.org/committees/documents.php?wg_abbrev=office-formulaOpenDocument-formula-20090508.odt
96+ # @see [WRW] Wheeler, D. A., E. Rathke, and R. Weir (Eds.) (2009, May).
97+ # Open Document Format for Office Applications (OpenDocument)v1.2,
98+ # Part 2: Recalculated Formula (OpenFormula) Format - Annotated Version,
99+ # Pre-Draft 12. Organization for the Advancement of Structured Information
100+ # Standards (OASIS). Billerica, MA, USA. [ODT Document].
101+ def fv ( payment : nil )
102+ raise ArgumentError , 'no payment given' if self . payment . nil? && payment . nil?
103+
104+ final_payment = payment || self . payment
105+
106+ factor = ( 1.0 + monthly_rate ) **duration
107+ second_factor = ( factor - 1 ) * ( 1 + monthly_rate * ptype ) / monthly_rate
108+
109+ -( ( amount * factor ) + ( final_payment . to_f * second_factor ) )
110+ end
111+
72112 private
73113
74114 def initialize_payment_type ( ptype )
0 commit comments