finance_engine 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a461095fc7ba2a9fe186d3e9ad0d97b17578cc2f
4
+ data.tar.gz: 58b5fc4581f833b153a1c1a0b71c2bc38d6f99b4
5
+ SHA512:
6
+ metadata.gz: 478421efb129d5123c87911e6f76cc6253aa77b8b1c76e5ed7aeaef5b227ae766d70fb9115b3895d3b2799fc068072224f45e54808052fbf224bc7c6afa475e6
7
+ data.tar.gz: 7480b5610dbb0d07d28266e3b5dc50855282c6a36e0186a29290734dc340d78fc224e422fd208a0deb1fa58f29bf3823b4bbd42f5b0e0822f93a27939763c164
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+ ruby '2.0.0'
3
+
4
+ # Specify your gem's dependencies in finance_engine.gemspec
5
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,46 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ finance_engine (0.0.1)
5
+ distribution
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ byebug (3.5.1)
11
+ columnize (~> 0.8)
12
+ debugger-linecache (~> 1.2)
13
+ slop (~> 3.6)
14
+ coderay (1.1.0)
15
+ columnize (0.8.9)
16
+ debugger-linecache (1.2.0)
17
+ diff-lcs (1.2.5)
18
+ distribution (0.7.1)
19
+ method_source (0.8.2)
20
+ pry (0.10.1)
21
+ coderay (~> 1.1.0)
22
+ method_source (~> 0.8.1)
23
+ slop (~> 3.4)
24
+ pry-byebug (2.0.0)
25
+ byebug (~> 3.4)
26
+ pry (~> 0.10)
27
+ rake (10.3.2)
28
+ rspec (2.14.1)
29
+ rspec-core (~> 2.14.0)
30
+ rspec-expectations (~> 2.14.0)
31
+ rspec-mocks (~> 2.14.0)
32
+ rspec-core (2.14.8)
33
+ rspec-expectations (2.14.5)
34
+ diff-lcs (>= 1.1.3, < 2.0)
35
+ rspec-mocks (2.14.6)
36
+ slop (3.6.0)
37
+
38
+ PLATFORMS
39
+ ruby
40
+
41
+ DEPENDENCIES
42
+ bundler (~> 1.7)
43
+ finance_engine!
44
+ pry-byebug
45
+ rake (~> 10.0)
46
+ rspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 TODO: Write your name
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,67 @@
1
+ # FinanceEngine
2
+
3
+ Finance Engine (Fe) is a hopefully growing open source library to assist in financial calculations and demonstrations.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'finance_engine'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install finance_engine
20
+
21
+ ## Usage
22
+
23
+ At the moment there are only five limited modules. Here we will try to demonstrate the basic argument inputs, it is advisable to check the tests for further details.
24
+
25
+ 1) FA = FinanceEngine::Annuity
26
+
27
+ FA.present_value_perpetuity(annuity payment in dollars, rate of return, growth rate) - Will return the present value of a perpetuity.
28
+
29
+ FA.present_value_annuity(annuity payment in dollars, rate of return, n periods in payment, growth rate) - Will return the present value of an annuity with n periods remaining.
30
+
31
+ 2) FEE = FinanceEngine::EAY_EAR
32
+
33
+ FEE.calculate_effective_annual_yield(annual interest rate, compounding periods) - returns the effective annual yield given the effective annual rate and compounding periods.
34
+
35
+ FEE.calculate_effective_annual_rate(effective annual yield, compounding periods) - returns the annual rate of return given the effective annual yeld and compounding periods.
36
+
37
+ FEE.calculate_EAY_payment(payment amount, effecive annual rate, periods compounded, periods per year) - Calculates the dollar value of a payment in the future with compounding.
38
+
39
+ FEE.calculate_EAR_payment(payment amount, effecive annual rate, periods compounded, periods per year) - Calculates the dollar value of a payment in the future without compounding.
40
+
41
+ FEE.compare_EAR_EAY(payment amount, effecive annual rate, periods compounded, periods per year) - Calculates the dollar value difference between a payment calculated with effective yield and without.
42
+
43
+ 3) FE = FinanceEngine::Equity
44
+
45
+ FE.gordon_growth_model({ :rate => 0.05, :dividend => 100, :growth => 0.02, :value => 3333.33 }) - Using 3 of the 4 input values the Gordon Growth Model method will calculate the 4th input.
46
+
47
+ 4) FBS = FinanceEngine::Black_Scholes
48
+
49
+ FBS.new({ :current_stock_price => 100, :time => 5, :strike_price => 95, :risk_free_rate => 0.05, :volatility => 0.25 }) - After initializing a new instance of Black_Scholes run the build options method. This will create and store the put call and price data on the instance of Black Scholes. This is different from the other modules in that it will store the variables in the instance.
50
+
51
+ 5) FTVM = FinanceEngine::Time_Value_Money
52
+
53
+ FTVM.present_value_cash_flows(years, cashflows, rates) - Years, cashflows and rates are all arrays matching in length. This method will return the present value of a series of cash flows when given the time, amount and effective interest rates.
54
+
55
+ FTVM.future_value_cash_flows(years, cashflows, rates) - Years, cashflows and rates are all arrays matching in length. This method will return the future value of a series of cash flows when given the time, amount and effective interest rates.
56
+
57
+
58
+
59
+
60
+
61
+ ## Contributing
62
+
63
+ 1. Fork it ( https://github.com/[my-github-username]/finance_engine/fork )
64
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
65
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
66
+ 4. Push to the branch (`git push origin my-new-feature`)
67
+ 5. Create a new Pull Request
data/README.md~ ADDED
@@ -0,0 +1,65 @@
1
+ # FinanceEngine
2
+
3
+ Finance Engine (Fe) is a hopefully growing open source library to assist in financial calculations and demonstrations.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'finance_engine'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install finance_engine
20
+
21
+ ## Usage
22
+
23
+ At the moment there are only five limited modules. Here we will try to demonstrate the basic argument inputs, it is advisable to check the tests for further details.
24
+
25
+ 1) FA = FinanceEngine::Annuity
26
+
27
+ FA.present_value_perpetuity(annuity payment in dollars, rate of return, growth rate) - Will return the present value of a perpetuity.
28
+
29
+ FA.present_value_annuity(annuity payment in dollars, rate of return, n periods in payment, growth rate) - Will return the present value of an annuity with n periods remaining.
30
+
31
+ 2) FEE = FinanceEngine::EAY_EAR
32
+
33
+ FEE.calculate_effective_annual_yield(annual interest rate, compounding periods) - returns the effective annual yield given the effective annual rate and compounding periods.
34
+
35
+ FEE.calculate_effective_annual_rate(effective annual yield, compounding periods) - returns the annual rate of return given the effective annual yeld and compounding periods.
36
+
37
+ FEE.calculate_EAY_payment(payment amount, effecive annual rate, periods compounded, periods per year) - Calculates the dollar value of a payment in the future with compounding.
38
+
39
+ FEE.calculate_EAR_payment(payment amount, effecive annual rate, periods compounded, periods per year) - Calculates the dollar value of a payment in the future without compounding.
40
+
41
+ FEE.compare_EAR_EAY(payment amount, effecive annual rate, periods compounded, periods per year) - Calculates the dollar value difference between a payment calculated with effective yield and without.
42
+
43
+ 3) FE = FinanceEngine::Equity
44
+
45
+ FE.gordon_growth_model({ :rate => 0.05, :dividend => 100, :growth => 0.02, :value => 3333.33 }) - Using 3 of the 4 input values the Gordon Growth Model method will calculate the 4th input.
46
+
47
+ 4) FBS = FinanceEngine::Black_Scholes
48
+
49
+ FBS.new({ :current_stock_price => 100, :time => 5, :strike_price => 95, :risk_free_rate => 0.05, :volatility => 0.25 })
50
+
51
+ 5) FTVM = FinanceEngine::Time_Value_Money
52
+
53
+ FTVM.
54
+
55
+
56
+
57
+
58
+
59
+ ## Contributing
60
+
61
+ 1. Fork it ( https://github.com/[my-github-username]/finance_engine/fork )
62
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
63
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
64
+ 4. Push to the branch (`git push origin my-new-feature`)
65
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'finance_engine/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "finance_engine"
8
+ spec.version = FinanceEngine::VERSION
9
+ spec.authors = ["Jeffrey Penkar"]
10
+ spec.email = ["jspenkar@gmail.com"]
11
+ spec.summary = %q{Financial Engine Gem. Financial methods and tools.}
12
+ spec.description = %q{Financial Engine Gem. Functionality for put/call pricing, annuity valuation, Gordon Growht Model valuation, time value of money module, and hopefully more to come.}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rspec"
23
+ spec.add_development_dependency 'pry-byebug'
24
+ spec.add_development_dependency "rake", "~> 10.0"
25
+ spec.add_runtime_dependency "distribution"
26
+ end
@@ -0,0 +1,11 @@
1
+ module FinanceEngine
2
+ class Annuity
3
+ def self.present_value_perpetuity(annuity, rate, growth=0)
4
+ annuity*(1+growth)/(rate-growth)
5
+ end
6
+
7
+ def self.present_value_annuity(annuity, rate, periods, growth=0)
8
+ annuity /(rate - growth) *( 1 - ((1+growth)/(1+rate))**periods )
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,66 @@
1
+ module FinanceEngine
2
+ class EAY_EAR
3
+ def self.calculate_effective_annual_yield(annual_rate, periods)
4
+ (1+annual_rate/periods)**(periods)-1
5
+ end
6
+
7
+ def self.calculate_effective_annual_rate(annual_yield, periods)
8
+ ((annual_yield + 1)**(1/periods)-1)*periods
9
+ end
10
+
11
+ def self.calculate_EAY_payment(amt, rate, time, periods)
12
+ amt * ((1+rate/periods)**(time))
13
+ end
14
+
15
+ def self.calculate_EAR_payment(amt, rate, time, periods)
16
+ amt * ((1+rate)**(time.to_f/periods))
17
+ end
18
+
19
+ def self.continuous_compounding(amt,rate,time)
20
+ amt * (Math::E**(rate*time))
21
+ end
22
+
23
+ def self.compare_EAR_EAY_single_payment(amt,rate,time,periods)
24
+ calculate_EAY_payment(amt, rate, time, periods) - calculate_EAR_payment(amt, rate, time, periods)
25
+ end
26
+
27
+ def self.compare_EAR_Continuous_single_payment(amt,rate,time,periods)
28
+ continuous_compounding(amt,rate,time/periods) - calculate_EAR_payment(amt, rate, time, periods)
29
+ end
30
+
31
+ def self.compare_EAY_Continuous_single_payment(amt,rate,time,periods)
32
+ continuous_compounding(amt,rate,time/periods) - calculate_EAY_payment(amt, rate, time, periods)
33
+ end
34
+
35
+ def self.calculate_EAR_series(amt, rate, time, periods)
36
+ sum = 0
37
+ 1.upto(time) {|x| sum += calculate_EAR_payment(amt, rate, x, periods)}
38
+ sum
39
+ end
40
+
41
+ def self.calculate_EAY_series(amt, rate, time, periods)
42
+ sum = 0
43
+ 1.upto(time) {|x| sum += calculate_EAY_payment(amt, rate, x, periods)}
44
+ sum
45
+ end
46
+
47
+ def self.calculate_CC_series(amt, rate, time, periods)
48
+ sum = 0
49
+ 1.upto(time) {|x| sum += calculate_EAY_payment(amt, rate, time, periods)}
50
+ sum
51
+ end
52
+
53
+ def self.compare_EAR_EAY_series_payment(amt,rate,time,periods)
54
+ calculate_EAY_series(amt, rate, time, periods) - calculate_EAR_series(amt, rate, time, periods)
55
+ end
56
+
57
+ def self.compare_EAR_Continuous_series_payment(amt,rate,time,periods)
58
+ calculate_CC_series(amt, rate, time, periods) - calculate_EAR_series(amt, rate, time, periods)
59
+ end
60
+
61
+ def self.compare_EAY_Continuous_series_payment(amt,rate,time,periods)
62
+ calculate_CC_series(amt, rate, time, periods) - calculate_EAY_series(amt, rate, time, periods)
63
+ end
64
+
65
+ end
66
+ end
@@ -0,0 +1,27 @@
1
+ module FinanceEngine
2
+ class Equity
3
+ def self.gordon_growth_model(hash)
4
+ return ggm_value(hash) if hash[:value].nil?
5
+ return ggm_dividend(hash) if hash[:dividend].nil?
6
+ return ggm_rate(hash) if hash[:rate].nil?
7
+ return ggm_growth(hash) if hash[:growth].nil?
8
+ end
9
+
10
+ def self.ggm_value(hash)
11
+ hash[:dividend] / (hash[:rate] - hash[:growth])
12
+ end
13
+
14
+ def self.ggm_dividend(hash)
15
+ hash[:value] * (hash[:rate] - hash[:growth])
16
+ end
17
+
18
+ def self.ggm_rate(hash)
19
+ hash[:growth] + (hash[:dividend] / hash[:value])
20
+ end
21
+
22
+ def self.ggm_growth(hash)
23
+ hash[:rate] - (hash[:dividend] / hash[:value])
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,51 @@
1
+ require 'distribution'
2
+ module FinanceEngine
3
+ class Black_Scholes
4
+ attr_accessor :current_stock_price, :time, :strike_price, :risk_free_rate, :volatility, :d1, :d2, :call_price, :put_price
5
+ def initialize(hash)
6
+ @current_stock_price = hash[:price]
7
+ @strike_price = hash[:strike]
8
+ @time = hash[:time]
9
+ @risk_free_rate = hash[:riskfree]
10
+ @volatility = hash[:volatility]
11
+ @distr_normal = Distribution::Normal::Ruby_
12
+ end
13
+
14
+ def check_attr
15
+ msg = ''
16
+ msg += "Stock price is missing. " if @current_stock_price.nil?
17
+ msg += "Time period is missing. " if @time.nil?
18
+ msg += "Strike Price is missing. " if @strike_price.nil?
19
+ msg += "Risk free rate is missing. " if @risk_free_rate.nil?
20
+ msg += "Volatility rate is missing. " if @volatility.nil?
21
+ inputs = "{price: (Dollar Value), strike: (Dollar Value), time: (In Years), riskfree: (RF rate in decimal form (0.05)), volatility: (Volatility Percentage in decimal form (0.20))}"
22
+ # puts inputs if msg.length > 0
23
+ puts msg if msg.length > 0
24
+ end
25
+
26
+ def build_options
27
+ build_call_premium
28
+ build_put_premium
29
+ end
30
+
31
+ def build_call_premium
32
+ @d1 = (Math.log(@current_stock_price / @strike_price.to_f) + @time * (@risk_free_rate + ((@volatility ** 2) / 2))/ (@volatility * (@time**0.5)))
33
+ @d2 = (@d1 - (@volatility*(@time**0.5)))
34
+ @call_price = ( @current_stock_price * @distr_normal.cdf(@d1) ) - (@strike_price * Math::E**(@time * -@risk_free_rate) * @distr_normal.cdf(@d2) )
35
+ end
36
+
37
+ def build_put_premium
38
+ @put_price = ( @call_price + ( @strike_price * (Math::E**(@time * -@risk_free_rate)) ) - @current_stock_price )
39
+ end
40
+
41
+ def output
42
+ puts "Stock Call Price #{@call_price.round(4)}"
43
+ puts "Stock Put Price #{@put_price.round(4)}"
44
+ puts "Stock Price #{@current_stock_price}"
45
+ puts "Time #{@time}"
46
+ puts "Stock Strike Price #{@strike_price}"
47
+ puts "Stock Risk Free Rate #{@risk_free_rate}"
48
+ puts "Stock Volatility #{@volatility}"
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,101 @@
1
+ module FinanceEngine
2
+ class Time_Value_Money
3
+ def self.find_missing_variable(hash)
4
+ # attributes = {pv: present value, r: internal rate of return, fv: future value, n: number of payment periods, pmt: payment amount}
5
+ return find_fv(hash) if hash[:fv].nil?
6
+ return find_pv(hash) if hash[:pv].nil?
7
+ return find_r(hash) if hash[:r].nil?
8
+ return find_n(hash) if hash[:n].nil?
9
+ return find_pmt(hash) if hash[:pmt].nil?
10
+ end
11
+
12
+ def self.find_fv(hash)
13
+ pv = future_value_cash_flow({cash_flow: hash[:pv], time: hash[:n], rate: hash[:r]})
14
+ pmt = fv_annuity(hash[:pmt], hash[:n], hash[:r])
15
+ fv = pv.to_f + pmt.to_f
16
+ return fv
17
+ end
18
+
19
+ def self.find_pv(hash)
20
+ fv = present_value_cash_flow({cash_flow: hash[:fv], time: hash[:n], rate: hash[:r]})
21
+ pmt = pv_annuity(hash[:pmt], hash[:n], hash[:r])
22
+ pv = pmt + fv
23
+ return pv
24
+ end
25
+
26
+ # def self.find_r(hash)
27
+ # r = (hash[:fv]/hash[:pv])**((1/hash[:n])-1).to_f
28
+ # return r/100
29
+ # end
30
+
31
+ # def self.find_n(hash)
32
+ # # n = Math.log(1 - (hash[:fv]*hash[:r]/ hash[:pmt])) / Math.log(1+ hash[:r])
33
+ # # n += Math.log(hash[:fv]/hash[:pv]) / Math.log(1+ hash[:r])
34
+ # n = ((( hash[:pmt] *(1+hash[:r]) + -hash[:fv]/hash[:r]) / (hash[:pv] * hash[:r] + hash[:pmt]*(1+ hash[:r])))**(0.5))/((1+hash[:r])**(0.5))*100
35
+
36
+ # return n.round(4)
37
+ # end
38
+
39
+ #Calculates the annuity payment amount given the present value, future value, interest rate and amount of periods.
40
+ def self.find_pmt(hash)
41
+ # r[(PV - FV)/((1 + r)^n - 1) + PV]
42
+ # binding.pry
43
+ pmt = hash[:r] * ((hash[:pv] - hash[:fv])/((1+hash[:r])**(hash[:n])-1) + hash[:pv])
44
+ return pmt
45
+ end
46
+
47
+ #Calculates the present value of an annuity. Both formulas below, non-loop in use.
48
+ def self.pv_annuity(pmt,time,rate)
49
+ pv = pmt*(1-(1+rate)**-time)/rate
50
+ # pv = 0
51
+ # 1.upto(time) do |x|
52
+ # pv += pmt / ((1+rate)**x)
53
+ # end
54
+ return pv
55
+ end
56
+
57
+ #Calculates the future value of an annuity. Both formulas below, non-loop in use.
58
+ def self.fv_annuity(pmt,time,rate)
59
+ fv = pmt*((1+rate)**time -1)/rate
60
+ # fv = 0
61
+ # 1.upto(time) do |x|
62
+ # fv += pmt * ((1+rate)**(time-x))
63
+ # end
64
+ return fv
65
+ end
66
+
67
+ #Future value of a single cash flow taking in amount, rate and time as factors.
68
+ def self.future_value_cash_flow(hash)
69
+ cf = hash[:cash_flow]
70
+ rate = hash[:rate]
71
+ time = hash[:time]
72
+ return (cf * ((1 + rate)**time))
73
+ end
74
+
75
+ #Future value of a series of cash flows. Assumes payment occur at the end of period (inarrears).
76
+ def self.future_value_cash_flows(years, cashflows, rates, n)
77
+ future_value = 0
78
+ years.each_index do |x|
79
+ future_value += future_value_cash_flow({cash_flow: cashflows[x].to_f, rate: rates[x].to_f, time: n - years[x].to_f})
80
+ end
81
+ return future_value
82
+ end
83
+
84
+ #Present value of a single cash flow with hash input of amount, rate and time.
85
+ def self.present_value_cash_flow(hash)
86
+ cf = hash[:cash_flow]
87
+ rate = hash[:rate]
88
+ time = hash[:time]
89
+ return (cf / ((1 + rate)**time))
90
+ end
91
+
92
+ #Present value of a series of cash flows assuming varying interest rates.
93
+ def self.present_value_cash_flows(years, cashflows, rates)
94
+ present_value = 0
95
+ years.each_index do |x|
96
+ present_value += present_value_cash_flow({cash_flow: cashflows[x].to_f, rate: rates[x].to_f, time: years[x].to_f})
97
+ end
98
+ return present_value
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,3 @@
1
+ module FinanceEngine
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,15 @@
1
+ require "finance_engine/version"
2
+ require_relative 'finance_engine/optionpricing.rb'
3
+ require_relative 'finance_engine/tvm.rb'
4
+ require_relative 'finance_engine/eareay.rb'
5
+ require_relative 'finance_engine/annuity.rb'
6
+ require_relative 'finance_engine/gordon_growth_model.rb'
7
+
8
+ module FinanceEngine
9
+ def self.record=(x)
10
+ @record = x
11
+ end
12
+ def self.record
13
+ @record
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ require_relative '../spec_helper.rb'
2
+
3
+ describe FinanceEngine::Annuity do
4
+ it 'Should be able to find the present value of a growing or frozen perpetuity.' do
5
+ a = FinanceEngine::Annuity.present_value_perpetuity(100,0.05,0.02)
6
+ expect(a).to be_within(0.05).of(3400)
7
+ b = FinanceEngine::Annuity.present_value_perpetuity(100,0.05)
8
+ expect(b).to be_within(0.05).of(2000)
9
+ end
10
+
11
+ it 'Should be able to find the present value of a growing or frozen annuity.' do
12
+ a = FinanceEngine::Annuity.present_value_annuity(100, 0.05, 20, 0.02)
13
+ expect(a).to be_within(0.05).of(1466.55)
14
+ b = FinanceEngine::Annuity.present_value_annuity(100, 0.05, 20)
15
+ expect(b).to be_within(0.05).of(1246.20)
16
+ end
17
+ end
@@ -0,0 +1,74 @@
1
+ require_relative '../spec_helper.rb'
2
+
3
+ describe FinanceEngine::EAY_EAR do
4
+ it 'Should be able to calculate Effective Annual Yield' do
5
+ a = FinanceEngine::EAY_EAR.calculate_effective_annual_yield(0.05, 12)
6
+ expect(a).to be_within(0.005).of(0.0511)
7
+ end
8
+
9
+ it 'Should be able to calculate Effective Annual Rate' do
10
+ a = FinanceEngine::EAY_EAR.calculate_effective_annual_yield(0.0511, 12)
11
+ expect(a).to be_within(0.005).of(0.05)
12
+ end
13
+
14
+ it 'should be able to calculate a payment using EAR. $1000, 5%, over 2 years compounded monthly.' do
15
+ a = FinanceEngine::EAY_EAR.calculate_EAR_payment(1000,0.05,24,12)
16
+ expect(a).to be_within(0.05).of(1102.50)
17
+ end
18
+
19
+ it 'should be able to calculate a payment using EAY. $1000, 5%, over 2 years compounded monthly.' do
20
+ a = FinanceEngine::EAY_EAR.calculate_EAY_payment(1000,0.05,24,12)
21
+ expect(a).to be_within(0.05).of(1104.94)
22
+ end
23
+
24
+ it 'Should be able to calculate a payment assuming continuous compounding.' do
25
+ a = FinanceEngine::EAY_EAR.continuous_compounding(1000,0.05,2)
26
+ expect(a).to be_within(0.05).of(1105.17)
27
+ end
28
+
29
+ it 'Should be able to calculate the difference between EAR and EAY in dollar amounts.' do
30
+ a = FinanceEngine::EAY_EAR.compare_EAR_EAY_single_payment(1000,0.05,24,12)
31
+ expect(a).to be_within(0.05).of(2.44)
32
+ end
33
+
34
+ it 'Should be able to calculate the difference between EAY and continuous in dollar amounts.' do
35
+ a = FinanceEngine::EAY_EAR.compare_EAY_Continuous_single_payment(1000,0.05,24,12)
36
+ expect(a).to be_within(0.05).of(0.23)
37
+ end
38
+
39
+ it 'Should be able to calculate the difference between EAR and continuous in dollar amounts.' do
40
+ a = FinanceEngine::EAY_EAR.compare_EAR_Continuous_single_payment(1000,0.05,24,12)
41
+ expect(a).to be_within(0.05).of(2.67)
42
+ end
43
+
44
+ it 'Should be able to calculate the pv of a series of payments using EAR.' do
45
+ a = FinanceEngine::EAY_EAR.calculate_EAR_series(1000,0.05,24,12)
46
+ expect(a).to be_within(0.05).of(25261.28)
47
+ end
48
+
49
+ it 'Should be able to calculate the pv of a series of payments using EAR.' do
50
+ a = FinanceEngine::EAY_EAR.calculate_EAY_series(1000,0.05,24,12)
51
+ expect(a).to be_within(0.05).of(25290.86)
52
+ end
53
+
54
+ it 'Should be able to calculate the pv of a series of payments using Continuous Compounding.' do
55
+ a = FinanceEngine::EAY_EAR.calculate_CC_series(1000,0.05,24,12)
56
+ expect(a).to be_within(0.05).of(26518.59)
57
+ end
58
+
59
+ it 'Should be able to calculate the difference between EAR and EAY series of payment in dollar amounts.' do
60
+ a = FinanceEngine::EAY_EAR.compare_EAR_EAY_series_payment(1000,0.05,24,12)
61
+ expect(a).to be_within(0.05).of(29.58)
62
+ end
63
+
64
+ it 'Should be able to calculate the difference between EAY and continuous series of payment in dollar amounts.' do
65
+ a = FinanceEngine::EAY_EAR.compare_EAR_Continuous_series_payment(1000,0.05,24,12)
66
+ expect(a).to be_within(0.05).of(1257.31)
67
+ end
68
+
69
+ it 'Should be able to calculate the difference between EAY and continuous series of payment in dollar amounts.' do
70
+ a = FinanceEngine::EAY_EAR.compare_EAY_Continuous_series_payment(1000,0.05,24,12)
71
+ expect(a).to be_within(0.05).of(1227.73)
72
+ end
73
+
74
+ end
@@ -0,0 +1,42 @@
1
+ require_relative '../spec_helper.rb'
2
+
3
+ describe FinanceEngine::Equity do
4
+ it 'Should be able to calculate value given dividend, growth and rate of return.' do
5
+ hash = {dividend: 100, rate: 0.05, growth: 0.02}
6
+ a = FinanceEngine::Equity.ggm_value(hash)
7
+ expect(a).to be_within(0.005).of(3333.333)
8
+ end
9
+
10
+ it 'Should be able to calculate dividend given value, growth and rate of return.' do
11
+ hash = {value: 3333.33, rate: 0.05, growth: 0.02}
12
+ a = FinanceEngine::Equity.ggm_dividend(hash)
13
+ expect(a).to be_within(0.005).of(100)
14
+ end
15
+
16
+ it 'Should be able to calculate rate given value, growth and dividend of return.' do
17
+ hash = {value: 3333.33, dividend: 100, growth: 0.02}
18
+ a = FinanceEngine::Equity.ggm_rate(hash)
19
+ expect(a).to be_within(0.005).of(0.05)
20
+ end
21
+
22
+ it 'Should be able to calculate growth given value, rate and dividend of return.' do
23
+ hash = {value: 3333.33, dividend: 100, rate: 0.05}
24
+ a = FinanceEngine::Equity.ggm_growth(hash)
25
+ expect(a).to be_within(0.005).of(0.02)
26
+ end
27
+
28
+ it 'Should be able to calculate value, rate, div or growth depending on what is missing.' do
29
+ hash = {dividend: 100, rate: 0.05, growth: 0.02}
30
+ a = FinanceEngine::Equity.gordon_growth_model(hash)
31
+ expect(a).to be_within(0.005).of(3333.333)
32
+ hash = {value: 3333.33, rate: 0.05, growth: 0.02}
33
+ b = FinanceEngine::Equity.gordon_growth_model(hash)
34
+ expect(b).to be_within(0.005).of(100)
35
+ hash = {value: 3333.33, dividend: 100, growth: 0.02}
36
+ c = FinanceEngine::Equity.gordon_growth_model(hash)
37
+ expect(c).to be_within(0.005).of(0.05)
38
+ hash = {value: 3333.33, dividend: 100, rate: 0.05}
39
+ d = FinanceEngine::Equity.gordon_growth_model(hash)
40
+ expect(d).to be_within(0.005).of(0.02)
41
+ end
42
+ end
@@ -0,0 +1,31 @@
1
+ require_relative '../spec_helper.rb'
2
+
3
+ describe FinanceEngine::Black_Scholes do
4
+ it 'It should be able to accept variable for the Black Scholes model.' do
5
+ hash = {price: 25, strike: 30, time: 5, riskfree:0.05, volatility: 0.2}
6
+ a = FinanceEngine::Black_Scholes.new(hash)
7
+ expect(a.current_stock_price).to eq(25)
8
+ expect(a.time).to eq(5)
9
+ expect(a.strike_price).to eq(30)
10
+ expect(a.risk_free_rate).to eq(0.05)
11
+ expect(a.volatility).to eq(0.2)
12
+ end
13
+
14
+ it 'It should be able to calculate put and call prices.' do
15
+ hash = {price: 25, strike: 30, time: 5, riskfree:0.05, volatility: 0.2}
16
+ a = FinanceEngine::Black_Scholes.new(hash)
17
+ a.build_options
18
+ expect(a.put_price.round(4)).to eq(3.4068)
19
+ expect(a.call_price.round(4)).to eq(5.0428)
20
+ expect(a.d1.round(4)).to eq(0.6003)
21
+ expect(a.d2.round(4)).to eq(0.1531)
22
+ end
23
+
24
+
25
+ it 'It should be able to tell you what is missing.' do
26
+ hash = {strike: 30, time: 5, riskfree:0.05, volatility: 0.2}
27
+ a = FinanceEngine::Black_Scholes.new(hash)
28
+ STDOUT.should_receive(:puts).with("Stock price is missing. ")
29
+ a.check_attr
30
+ end
31
+ end
@@ -0,0 +1,121 @@
1
+ require_relative '../spec_helper.rb'
2
+
3
+ describe FinanceEngine::Time_Value_Money do
4
+ it 'Should be able to calculate a single cash flow\'s present value.' do
5
+ hash = {cash_flow: 100, time: 1, rate: 0.10}
6
+ a = FinanceEngine::Time_Value_Money.present_value_cash_flow(hash)
7
+ expect(a.round(4)).to eq(90.9091)
8
+ hash = {cash_flow: 1000, time: 2, rate: 0.05}
9
+ a = FinanceEngine::Time_Value_Money.present_value_cash_flow(hash)
10
+ expect(a.round(4)).to eq(907.0295)
11
+ end
12
+
13
+ it "Should be able to calculate the present value of a series of cash flows." do
14
+ years = [0,1,2,3,4]
15
+ cashflows = [-1000,250,250,250,250]
16
+ rates = [0.01,0.01,0.01,0.01,0.01]
17
+ a = FinanceEngine::Time_Value_Money.present_value_cash_flows(years, cashflows, rates)
18
+ expect(a.round(4)).to be_within(1).of(-24)
19
+ year1 = [1]; cashflow1 = [100]; rate1 = [0.1]
20
+ b = FinanceEngine::Time_Value_Money.present_value_cash_flows(year1, cashflow1, rate1)
21
+ expect(b.round(4)).to be_within(1).of(90)
22
+ end
23
+
24
+ it 'It should be able to calculate a single cash flow\'s future value.' do
25
+ hash = {cash_flow: 100, time: 2, rate: 0.10}
26
+ a = FinanceEngine::Time_Value_Money.future_value_cash_flow(hash)
27
+ expect(a.round(4)).to be_within(1).of(121.0)
28
+ hash = {cash_flow: 1000, time: 5, rate: 0.1}
29
+ a = FinanceEngine::Time_Value_Money.future_value_cash_flow(hash)
30
+ expect(a).to be_within(1).of(1610.0)
31
+ end
32
+
33
+ it "Should be able to calculate the future value of a series of cash flows." do
34
+ years = [0,1,2,3,4]; cashflows = [-1000,250,250,250,250]; rates = [0.01,0.01,0.01,0.01,0.01]
35
+ a = FinanceEngine::Time_Value_Money.future_value_cash_flows(years, cashflows, rates,4)
36
+ expect(a.round(4)).to be_within(1).of(-25)
37
+ year1 = [0]; cashflow1 = [100]; rate1 = [0.1]
38
+ b = FinanceEngine::Time_Value_Money.future_value_cash_flows(year1, cashflow1, rate1,1)
39
+ expect(b.round(4)).to be_within(1).of(110)
40
+ year1 = [1]; cashflow1 = [100]; rate1 = [0.1]
41
+ b = FinanceEngine::Time_Value_Money.future_value_cash_flows(year1, cashflow1, rate1,2)
42
+ expect(b.round(4)).to be_within(1).of(110)
43
+ end
44
+
45
+ it "Should be able to calculate the PV of an Annuity." do
46
+ a = FinanceEngine::Time_Value_Money.pv_annuity(100, 1, 0.1)
47
+ expect(a).to be_within(1).of(90)
48
+ a = FinanceEngine::Time_Value_Money.pv_annuity(100, 5, 0.1)
49
+ expect(a).to be_within(1).of(379)
50
+ end
51
+
52
+ it "Should be able to calculate the FV of an Annuity." do
53
+ a = FinanceEngine::Time_Value_Money.fv_annuity(100, 1, 0.1)
54
+ expect(a).to be_within(1).of(100)
55
+ a = FinanceEngine::Time_Value_Money.fv_annuity(100, 2, 0.1)
56
+ expect(a).to be_within(1).of(210)
57
+ a = FinanceEngine::Time_Value_Money.fv_annuity(100, 5, 0.1)
58
+ expect(a).to be_within(1).of(610)
59
+ end
60
+
61
+ it "Should be able to calculate the FV given n, t, r, and pv." do
62
+ hash = {pv: 1000,r: 0.10, n:5, pmt: 100}
63
+ a = FinanceEngine::Time_Value_Money.find_fv(hash)
64
+ expect(a).to be_within(1).of(2221)
65
+ hash = {pv: 0,r: 0.10, n:5, pmt: 100}
66
+ a = FinanceEngine::Time_Value_Money.find_fv(hash)
67
+ expect(a).to be_within(1).of(610)
68
+ hash = {pv: 1000,r: 0.10, n:5, pmt: 0}
69
+ a = FinanceEngine::Time_Value_Money.find_fv(hash)
70
+ expect(a).to be_within(1).of(1610)
71
+ end
72
+
73
+ it "Should be able to calculate the PV given n, t, r, and fv." do
74
+ hash = {fv: 1000, r: 0.10, n:5, pmt: 0}
75
+ a = FinanceEngine::Time_Value_Money.find_pv(hash)
76
+ expect(a).to be_within(1).of(620)
77
+ hash = {fv: 0, r: 0.10, n:5, pmt: 100}
78
+ a = FinanceEngine::Time_Value_Money.find_pv(hash)
79
+ expect(a).to be_within(1).of(380)
80
+ hash = {fv: 1000, r: 0.10, n:5, pmt: 100}
81
+ a = FinanceEngine::Time_Value_Money.find_pv(hash)
82
+ expect(a).to be_within(1).of(1000)
83
+ end
84
+
85
+ it "Should be able to calculate the payment given all else." do
86
+ hash = {fv: 0, n: 4, pv:-100, r: 0.1}
87
+ a = FinanceEngine::Time_Value_Money.find_pmt(hash)
88
+ expect(a).to be_within(1).of(-31)
89
+ hash = {fv: 1000, n: 10, pv:0, r: 0.1}
90
+ a = FinanceEngine::Time_Value_Money.find_pmt(hash)
91
+ expect(a).to be_within(1).of(-62.75)
92
+ hash = {fv: -1000, n: 10, pv:1000, r: 0.1}
93
+ a = FinanceEngine::Time_Value_Money.find_pmt(hash)
94
+ expect(a).to be_within(1).of(225.75)
95
+ end
96
+
97
+ xit "Should be able to calculate the rate given all else." do
98
+ hash = {fv: 200, n: 5, pv:-200, pmt: 10}
99
+ a = FinanceEngine::Time_Value_Money.find_r(hash)
100
+ expect(a).to eq(0.05)
101
+ end
102
+
103
+ xit "Should be able to calculate the N given pv, pmt, r, and fv." do
104
+ hash = {fv: 200, r: 0.10, pv:-50, pmt: 100}
105
+ a = FinanceEngine::Time_Value_Money.find_n(hash)
106
+ expect(a).to eq(1)
107
+ end
108
+
109
+ it 'Should be able to figure out what is missing from a set of parameters and start calc to figure out missing value.' do
110
+ a = FinanceEngine::Time_Value_Money.find_missing_variable({fv: 1000, r: 0.10, n:5, pmt: 0})
111
+ expect(a).to be_within(1).of(620)
112
+ b = FinanceEngine::Time_Value_Money.find_missing_variable({pv: 1000,r: 0.10, n:5, pmt: 100})
113
+ expect(b).to be_within(1).of(2221)
114
+ c = FinanceEngine::Time_Value_Money.find_missing_variable({fv: -1000, n: 10, pv:1000, r: 0.1})
115
+ expect(c).to be_within(1).of(225.75)
116
+ # d = FinanceEngine::Time_Value_Money.find_missing_variable({})
117
+
118
+ # e = FinanceEngine::Time_Value_Money.find_missing_variable({})
119
+
120
+ end
121
+ end
@@ -0,0 +1,3 @@
1
+ require 'rspec'
2
+ require 'pry-byebug'
3
+ require_relative '../lib/finance_engine.rb'
metadata ADDED
@@ -0,0 +1,142 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: finance_engine
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jeffrey Penkar
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-11-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry-byebug
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: distribution
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Financial Engine Gem. Functionality for put/call pricing, annuity valuation,
84
+ Gordon Growht Model valuation, time value of money module, and hopefully more to
85
+ come.
86
+ email:
87
+ - jspenkar@gmail.com
88
+ executables: []
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - Gemfile
93
+ - Gemfile.lock
94
+ - LICENSE.txt
95
+ - README.md
96
+ - README.md~
97
+ - Rakefile
98
+ - finance_engine.gemspec
99
+ - lib/finance_engine.rb
100
+ - lib/finance_engine/annuity.rb
101
+ - lib/finance_engine/eareay.rb
102
+ - lib/finance_engine/gordon_growth_model.rb
103
+ - lib/finance_engine/optionpricing.rb
104
+ - lib/finance_engine/tvm.rb
105
+ - lib/finance_engine/version.rb
106
+ - spec/entities/annuity_spec.rb
107
+ - spec/entities/eareay_spec.rb
108
+ - spec/entities/gordon_growth_model_spec.rb
109
+ - spec/entities/optionpricing_spec.rb
110
+ - spec/entities/tvm_spec.rb
111
+ - spec/spec_helper.rb
112
+ homepage: ''
113
+ licenses:
114
+ - MIT
115
+ metadata: {}
116
+ post_install_message:
117
+ rdoc_options: []
118
+ require_paths:
119
+ - lib
120
+ required_ruby_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ required_rubygems_version: !ruby/object:Gem::Requirement
126
+ requirements:
127
+ - - '>='
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ requirements: []
131
+ rubyforge_project:
132
+ rubygems_version: 2.4.2
133
+ signing_key:
134
+ specification_version: 4
135
+ summary: Financial Engine Gem. Financial methods and tools.
136
+ test_files:
137
+ - spec/entities/annuity_spec.rb
138
+ - spec/entities/eareay_spec.rb
139
+ - spec/entities/gordon_growth_model_spec.rb
140
+ - spec/entities/optionpricing_spec.rb
141
+ - spec/entities/tvm_spec.rb
142
+ - spec/spec_helper.rb