options_library 1.0.0 → 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Manifest CHANGED
@@ -1,5 +1,6 @@
1
+ Manifest
2
+ README.md
1
3
  Rakefile
2
4
  lib/options_library.rb
3
5
  lib/options_library/option_calculator.rb
4
6
  options_library.gemspec
5
- Manifest
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ Initial Author
2
+ --------------
3
+ Dan Tylenda-Emmons
4
+ Twitter: @CoderTrader
5
+ Email: jrubyist@gmail.com
6
+
7
+ Options Library
8
+ ===============
9
+
10
+ A pure Ruby implementation of the classic Black-Scholes option model for pricing Calls or Puts.
11
+
12
+ Goals
13
+ -------
14
+
15
+ * Provide the Open Source Ruby, JRuby and StockTwits communities with a publicly available model for computing option prices.
16
+ * Allow users of the library to compute price and greeks: delta, gamma, theta, vega and rho.
17
+ * To aid others in the understanding of how price and sensitivities to other factors are computed on a theoretical basis.
18
+ * To allo users of the library to extend or contribute back to the project so that it may be improved upon.
19
+
20
+
21
+ Installation
22
+ -----------
23
+
24
+ gem install options_library
25
+
26
+
27
+ Usage
28
+ -----
29
+
30
+ require 'rubygems'
31
+ require 'options_library'
32
+
33
+ # Option::Calculator.price_call( underlying, strike, time, interest, sigma, dividend )
34
+ call_price = Option::Calculator.price_call( 94.5, 90.5, 0.015, 0.01, 0.4875, 0.0 )
35
+
36
+ Testing
37
+ -------
38
+
39
+ To run the tests:
40
+
41
+ $ rake
42
+
43
+ To add tests see the `Commands` section earlier in this
44
+ README.
45
+
46
+
47
+ Contributing
48
+ ------------
49
+
50
+ 1. Fork it.
51
+ 2. Create a branch (`git checkout -b my_options_library`)
52
+ 3. Commit your changes (`git commit -am "Added Hull-White Model"`)
53
+ 4. Push to the branch (`git push origin my_options_library`)
54
+ 5. Create an [Issue][1] with a link to your branch
55
+ 6. Enjoy a fresh cup of coffee and wait
56
+
57
+ [1]: http://github.com/github/markup/issues
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
  require 'rake'
3
3
  require 'echoe'
4
4
 
5
- Echoe.new('options_library', '1.0.0') do |p|
5
+ Echoe.new('options_library', '1.0.2') do |p|
6
6
  p.description = 'A gem used to calc the price of an option.'
7
7
  p.url = 'http://github.com/codertrader/options_library'
8
8
  p.author = 'Dan Tylenda-Emmons'
@@ -5,121 +5,126 @@
5
5
  module Option
6
6
  class Calculator
7
7
  class << self
8
+ # used for finding implied vol based on a market (target) price
9
+ LOW_VOL, HIGH_VOL, VOL_TOLERANCE = 0.0, 5.0, 0.0001
10
+
11
+ # used for min/max normal distribution
12
+ MIN_Z_SCORE, MAX_Z_SCORE = -8.0, +8.0
8
13
 
9
- include Math
14
+ include Math
10
15
 
11
- # computes the call price sensitivity to a change in underlying price
12
- def delta_call( underlying, strike, time, interest, sigma, dividend )
13
- norm_sdist( d_one( underlying, strike, time, interest, sigma, dividend ) )
14
- end
16
+ # computes the call price sensitivity to a change in underlying price
17
+ def delta_call( underlying, strike, time, interest, sigma, dividend )
18
+ norm_sdist( d_one( underlying, strike, time, interest, sigma, dividend ) )
19
+ end
15
20
 
16
- # computes the put price sensitivity to a change in underlying price
17
- def delta_put( underlying, strike, time, interest, sigma, dividend )
18
- call_delta( underlying, strike, time, interest, sigma, dividend ) - 1
19
- end
21
+ # computes the put price sensitivity to a change in underlying price
22
+ def delta_put( underlying, strike, time, interest, sigma, dividend )
23
+ delta_call( underlying, strike, time, interest, sigma, dividend ) - 1
24
+ end
20
25
 
21
- # computes the option price sensitivity to a change in delta
22
- def gamma( underlying, strike, time, interest, sigma, dividend )
23
- phi( d_one( underlying, strike, time, interest, sigma, dividend ) ) / ( underlying * sigma * sqrt(time) )
24
- end
26
+ # computes the option price sensitivity to a change in delta
27
+ def gamma( underlying, strike, time, interest, sigma, dividend )
28
+ phi( d_one( underlying, strike, time, interest, sigma, dividend ) ) / ( underlying * sigma * sqrt(time) )
29
+ end
25
30
 
26
- # computes the option price sensitivity to a change in volatility
27
- def vega( underlying, strike, time, interest, sigma, dividend )
28
- 0.01 * underlying * sqrt(time) * phi(d_one(underlying, strike, time, interest, sigma, dividend))
29
- end
31
+ # computes the option price sensitivity to a change in volatility
32
+ def vega( underlying, strike, time, interest, sigma, dividend )
33
+ 0.01 * underlying * sqrt(time) * phi(d_one(underlying, strike, time, interest, sigma, dividend))
34
+ end
30
35
 
31
- # computes the fair value of the call based on the knowns and assumed volatility (sigma)
32
- def price_call( underlying, strike, time, interest, sigma, dividend )
33
- d1 = d_one( underlying, strike, time, interest, sigma, dividend )
34
- discounted_underlying = exp(-1.0 * dividend * time) * underlying
35
- probability_weighted_value_of_being_exercised = discounted_underlying * norm_sdist( d1 )
36
+ # computes the fair value of the call based on the knowns and assumed volatility (sigma)
37
+ def price_call( underlying, strike, time, interest, sigma, dividend )
38
+ d1 = d_one( underlying, strike, time, interest, sigma, dividend )
39
+ discounted_underlying = exp(-1.0 * dividend * time) * underlying
40
+ probability_weighted_value_of_being_exercised = discounted_underlying * norm_sdist( d1 )
36
41
 
37
- d2 = d1 - ( sigma * sqrt(time) )
38
- discounted_strike = exp(-1.0 * interest * time) * strike
39
- probability_weighted_value_of_discounted_strike = discounted_strike * norm_sdist( d2 )
42
+ d2 = d1 - ( sigma * sqrt(time) )
43
+ discounted_strike = exp(-1.0 * interest * time) * strike
44
+ probability_weighted_value_of_discounted_strike = discounted_strike * norm_sdist( d2 )
40
45
 
41
- expected_value = probability_weighted_value_of_being_exercised - probability_weighted_value_of_discounted_strike
42
- end
46
+ expected_value = probability_weighted_value_of_being_exercised - probability_weighted_value_of_discounted_strike
47
+ end
43
48
 
44
- # computes the fair value of the put based on the knowns and assumed volatility (sigma)
45
- def price_put( underlying, strike, time, interest, sigma, dividend )
46
- d2 = d_two( underlying, strike, time, interest, sigma, dividend )
47
- discounted_strike = strike * exp(-1.0 * interest * time)
48
- probabiltity_weighted_value_of_discounted_strike = discounted_strike * norm_sdist( -1.0 * d2 )
49
+ # computes the fair value of the put based on the knowns and assumed volatility (sigma)
50
+ def price_put( underlying, strike, time, interest, sigma, dividend )
51
+ d2 = d_two( underlying, strike, time, interest, sigma, dividend )
52
+ discounted_strike = strike * exp(-1.0 * interest * time)
53
+ probabiltity_weighted_value_of_discounted_strike = discounted_strike * norm_sdist( -1.0 * d2 )
49
54
 
50
- d1 = d2 + ( sigma * sqrt(time) )
51
- discounted_underlying = underlying * exp(-1.0 * dividend * time)
52
- probability_weighted_value_of_being_exercised = discounted_underlying * norm_sdist( -1.0 * d1 )
55
+ d1 = d2 + ( sigma * sqrt(time) )
56
+ discounted_underlying = underlying * exp(-1.0 * dividend * time)
57
+ probability_weighted_value_of_being_exercised = discounted_underlying * norm_sdist( -1.0 * d1 )
53
58
 
54
- expected_value = probabiltity_weighted_value_of_discounted_strike - probability_weighted_value_of_being_exercised
55
- end
59
+ expected_value = probabiltity_weighted_value_of_discounted_strike - probability_weighted_value_of_being_exercised
60
+ end
56
61
 
57
- # finds the implied volatility based on the target_price passed in.
58
- def implied_vol_call( underlying, strike, time, interest, target_price, dividend )
59
- low, high = 0, 5
62
+ # finds the implied volatility based on the target_price passed in.
63
+ def implied_vol_call( underlying, strike, time, interest, target_price, dividend )
64
+ low, high = LOW_VOL, HIGH_VOL
60
65
 
61
- while( high - low > 0.0001 )
62
- if( call_option( underlying, strike, time, interest, (high+low)/2.0, dividend ) > target_price )
63
- high = (high + low) / 2.0
64
- else
65
- low = (high + low) / 2.0
66
- end
67
- end
66
+ while( high - low > VOL_TOLERANCE )
67
+ if( price_call( underlying, strike, time, interest, (high+low)/2.0, dividend ) > target_price )
68
+ high = (high + low) / 2.0
69
+ else
70
+ low = (high + low) / 2.0
71
+ end
72
+ end
68
73
 
69
- (high + low) / 2.0
74
+ (high + low) / 2.0
70
75
  end
71
76
 
72
- # finds the implied volatility based on the target_price passed in.
73
- def implied_vol_put( underlying, strike, time, interest, target_price, dividend )
74
- low, high = 0, 5
77
+ # finds the implied volatility based on the target_price passed in.
78
+ def implied_vol_put( underlying, strike, time, interest, target_price, dividend )
79
+ low, high = LOW_VOL, HIGH_VOL
75
80
 
76
- while( high - low > 0.0001 )
77
- if( put_option( underlying, strike, time, interest, (high+low)/2.0, dividend ) > target_price )
78
- high = (high + low) / 2.0
79
- else
80
- low = (high + low) / 2.0
81
- end
82
- end
81
+ while( high - low > VOL_TOLERANCE )
82
+ if( price_put( underlying, strike, time, interest, (high+low)/2.0, dividend ) > target_price )
83
+ high = (high + low) / 2.0
84
+ else
85
+ low = (high + low) / 2.0
86
+ end
87
+ end
83
88
 
84
- (high + low) / 2.0
85
- end
89
+ (high + low) / 2.0
90
+ end
86
91
 
87
- # probability of being exercised at maturity (must be greater than d2 by (sigma*sqrt(time)) if exercised)
88
- def d_one( underlying, strike, time, interest, sigma, dividend )
89
- numerator = ( log(underlying / strike) + (interest - dividend + 0.5 * sigma ** 2.0 ) * time)
90
- denominator = ( sigma * sqrt(time) )
91
- numerator / denominator
92
- end
92
+ # probability of being exercised at maturity (must be greater than d2 by (sigma*sqrt(time)) if exercised)
93
+ def d_one( underlying, strike, time, interest, sigma, dividend )
94
+ numerator = ( log(underlying / strike) + (interest - dividend + 0.5 * sigma ** 2.0 ) * time)
95
+ denominator = ( sigma * sqrt(time) )
96
+ numerator / denominator
97
+ end
93
98
 
94
- # probability of underlying reaching the strike price (must be smaller than d1 by (sigma*sqrt(time)) if exercised.
95
- def d_two( underlying, strike, time, interest, sigma, dividend )
96
- d_one( underlying, strike, time, interest, sigma, dividend ) - ( sigma * sqrt(time) )
97
- end
99
+ # probability of underlying reaching the strike price (must be smaller than d1 by (sigma*sqrt(time)) if exercised.
100
+ def d_two( underlying, strike, time, interest, sigma, dividend )
101
+ d_one( underlying, strike, time, interest, sigma, dividend ) - ( sigma * sqrt(time) )
102
+ end
98
103
 
99
- # Normal Standard Distribution
100
- # using Taylor's approximation
101
- def norm_sdist( z )
102
- return 0.0 if z < -8.0
103
- return 1.0 if z > +8.0
104
+ # Normal Standard Distribution
105
+ # using Taylor's approximation
106
+ def norm_sdist( z )
107
+ return 0.0 if z < MIN_Z_SCORE
108
+ return 1.0 if z > MAX_Z_SCORE
104
109
 
105
- i, sum, term = 3.0, 0.0, z
110
+ i, sum, term = 3.0, 0.0, z
106
111
 
107
- while( sum + term != sum )
108
- sum = sum + term
109
- term = term * z * z / i
110
- i += 2.0
111
- end
112
+ while( sum + term != sum )
113
+ sum = sum + term
114
+ term = term * z * z / i
115
+ i += 2.0
116
+ end
112
117
 
113
- 0.5 + sum * phi(z)
114
- end
115
-
116
- # Standard Gaussian pdf
117
- def phi(x)
118
- numerator = exp(-1.0 * x*x / 2.0)
119
- denominator = sqrt(2.0 * PI)
120
- numerator / denominator
121
- end
118
+ 0.5 + sum * phi(z)
119
+ end
122
120
 
123
- end
121
+ # Standard Gaussian pdf
122
+ def phi(x)
123
+ numerator = exp(-1.0 * x*x / 2.0)
124
+ denominator = sqrt(2.0 * PI)
125
+ numerator / denominator
126
+ end
127
+
128
+ end
124
129
  end
125
130
  end
@@ -2,17 +2,17 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{options_library}
5
- s.version = "1.0.0"
5
+ s.version = "1.0.2"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Dan Tylenda-Emmons"]
9
- s.date = %q{2011-02-13}
9
+ s.date = %q{2011-02-16}
10
10
  s.description = %q{A gem used to calc the price of an option.}
11
11
  s.email = %q{jrubyist@gmail.com}
12
- s.extra_rdoc_files = ["lib/options_library.rb", "lib/options_library/option_calculator.rb"]
13
- s.files = ["Rakefile", "lib/options_library.rb", "lib/options_library/option_calculator.rb", "options_library.gemspec", "Manifest"]
12
+ s.extra_rdoc_files = ["README.md", "lib/options_library.rb", "lib/options_library/option_calculator.rb"]
13
+ s.files = ["Manifest", "README.md", "Rakefile", "lib/options_library.rb", "lib/options_library/option_calculator.rb", "options_library.gemspec"]
14
14
  s.homepage = %q{http://github.com/codertrader/options_library}
15
- s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Options_library"]
15
+ s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Options_library", "--main", "README.md"]
16
16
  s.require_paths = ["lib"]
17
17
  s.rubyforge_project = %q{options_library}
18
18
  s.rubygems_version = %q{1.5.2}
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: options_library
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 1.0.0
5
+ version: 1.0.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Dan Tylenda-Emmons
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-02-13 00:00:00 -06:00
13
+ date: 2011-02-16 00:00:00 -06:00
14
14
  default_executable:
15
15
  dependencies: []
16
16
 
@@ -21,14 +21,16 @@ executables: []
21
21
  extensions: []
22
22
 
23
23
  extra_rdoc_files:
24
+ - README.md
24
25
  - lib/options_library.rb
25
26
  - lib/options_library/option_calculator.rb
26
27
  files:
28
+ - Manifest
29
+ - README.md
27
30
  - Rakefile
28
31
  - lib/options_library.rb
29
32
  - lib/options_library/option_calculator.rb
30
33
  - options_library.gemspec
31
- - Manifest
32
34
  has_rdoc: true
33
35
  homepage: http://github.com/codertrader/options_library
34
36
  licenses: []
@@ -39,6 +41,8 @@ rdoc_options:
39
41
  - --inline-source
40
42
  - --title
41
43
  - Options_library
44
+ - --main
45
+ - README.md
42
46
  require_paths:
43
47
  - lib
44
48
  required_ruby_version: !ruby/object:Gem::Requirement