rupee 0.1.3 → 0.1.5

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc ADDED
@@ -0,0 +1,103 @@
1
+ = Rupee - financial tools for Ruby
2
+
3
+ Homepage:: http://www.brymck.com
4
+ Author:: Bryan McKelvey
5
+ Copyright:: (c) 2011 Bryan McKelvey
6
+ License:: MIT
7
+
8
+ /|\
9
+ / | \
10
+ / | \
11
+ /_ / \ _\ RU PE E
12
+ | | | | _ _ _
13
+ | | | | | | | | |__o ____
14
+ | | | | | | | _ | __| |____|
15
+ | _| |_ | | | |/ / | |___
16
+ \ \ / / /_/|___/ \____|
17
+ \ | /
18
+ \ | /
19
+ \|/
20
+
21
+ == Installing
22
+
23
+ Note that you must have Ruby 1.8.7+ installed and the ability to compile native
24
+ extensions (standard on most platforms and available on Windows via
25
+ {DevKit}[http://rubyinstaller.org/downloads/]).
26
+
27
+ gem install rupee
28
+
29
+ You can also do things the hard way if you want to keep track of the repo:
30
+
31
+ git clone git://github.com/brymck/rupee.git
32
+ cd rupee
33
+ bundle update
34
+ rake install
35
+
36
+ After all that hard work, you can take a test drive by running something like
37
+ this in the Ruby console (i.e. <tt>irb</tt> in a command prompt):
38
+
39
+ require "rupee"
40
+ Rupee::Option.black_scholes "c", 60, 65, 0.25, 0.08, 0, 0.3
41
+ Rupee::Call.new(
42
+ :underlying => 60,
43
+ :strike => 65,
44
+ :time => 0.25,
45
+ :rate => 0.08,
46
+ :div_yield => 0.00,
47
+ :volatility => 0.3
48
+ ).black_scholes
49
+
50
+ both of which should return <tt>2.1334</tt>.
51
+
52
+ You should also be able to get the latest stock info for, for example, Wells
53
+ Fargo using the following (note that you only need to <tt>require</tt> the
54
+ <tt>quote</tt> module):
55
+
56
+ require "rupee/quote"
57
+ wfc = Rupee::Quote.new("WFC")
58
+
59
+ wfc.get :price, :change, :pct_change
60
+ #=> {:price=>24.96, :change=>0.17, :pct_change =>0.686}
61
+
62
+ wfc.price
63
+ #=> 24.96
64
+
65
+ wfc.change
66
+ #=> 0.17
67
+
68
+ <tt>wfc.get</tt> will return a hash of the requested information for the security.
69
+ Each valid parameter will also have its own utility method. The results will
70
+ update every <tt>wfc.frequency</tt> seconds (defaults to 15).
71
+
72
+ Got it? Good. This will surely help you collect some rupees in real life.
73
+
74
+ == Performance
75
+
76
+ This is just a simple benchmark I ran on my own laptop, where I value a simple
77
+ call option with Black-Scholes 100,000 times. You can test the same on yours
78
+ with rake, but in any case it makes the point that for the mathematical side
79
+ of finance a native extension has substantial benefits:
80
+
81
+ rake benchmark:black_scholes
82
+
83
+ Results:
84
+
85
+ user system total real
86
+ Rupee (class): 0.190000 0.000000 0.190000 ( 0.194001)
87
+ Rupee (one object): 0.180000 0.000000 0.180000 ( 0.183091)
88
+ Rupee (new object): 2.210000 0.000000 2.210000 ( 2.213351)
89
+ Pure Ruby: 2.320000 0.000000 2.320000 ( 2.324259)
90
+
91
+ In words, for math-intensive operations, using a C implementation is clearly
92
+ faster than the same thing in Ruby.
93
+
94
+ Also, if you're doing a valuation on a one-off set of examples (e.g. in a Monte
95
+ Carlo simulation), you probably don't want to create an object every time.
96
+ Something like <tt>Rupee::Option.black_scholes ...</tt> should work just fine.
97
+ Creating a <tt>Rupee::Option</tt> object takes roughly the same amount of time as
98
+ running <tt>Rupee::Option.black_scholes</tt> a dozen times.
99
+
100
+ However, if you're creating and reusing an object, I strongly recommend
101
+ preserving the object orientation of Ruby: the penalty for using a new instance
102
+ rather than calling the class method directly is almost entirely in the object
103
+ initialization itself.
data/ext/rupee/bond.c CHANGED
@@ -295,7 +295,7 @@ init_bond()
295
295
  rb_define_singleton_method(klass, "duration", duration_discrete, 3);
296
296
  rb_define_alias(singleton, "dur", "duration");
297
297
  rb_define_singleton_method(klass, "macaulay", macaulay_discrete, 3);
298
- rb_define_alias(singleton, "macaulary_duration", "macaulay");
298
+ rb_define_alias(singleton, "macaulay_duration", "macaulay");
299
299
  rb_define_singleton_method(klass, "price", price_discrete, 3);
300
300
  rb_define_alias(singleton, "value", "price");
301
301
  rb_define_singleton_method(klass, "yield_to_maturity", yield_to_maturity_discrete, 3);
@@ -53,7 +53,7 @@ init_distribution()
53
53
  VALUE klass, singleton;
54
54
 
55
55
  #if 0
56
- value module = rb_define_module("rupee");
56
+ VALUE module = rb_define_module("Rupee");
57
57
  #endif
58
58
 
59
59
  klass = rb_define_class_under(module, "Distribution", rb_cObject);
@@ -3,7 +3,9 @@ module Rupee
3
3
  class Benchmark
4
4
  class << self
5
5
  # Black-Scholes option price valuation
6
+ #
6
7
  # by Michael Neumann (with some revisions)
8
+ #
7
9
  # http://www.espenhaug.com/black_scholes.html
8
10
  def black_scholes(callPutFlag, s, x, t, r, v)
9
11
  d1 = (Math.log(s / x) + (r + v * v / 2.0) * t) / (v * Math.sqrt(t))
@@ -17,14 +19,16 @@ module Rupee
17
19
 
18
20
  private
19
21
 
20
- A1 = 0.31938153
21
- A2 = -0.356563782
22
- A3 = 1.781477937
23
- A4 = -1.821255978
24
- A5 = 1.330274429
22
+ A1 = 0.31938153 # :nodoc:
23
+ A2 = -0.356563782 # :nodoc:
24
+ A3 = 1.781477937 # :nodoc:
25
+ A4 = -1.821255978 # :nodoc:
26
+ A5 = 1.330274429 # :nodoc:
25
27
 
26
28
  # Cumulative normal distribution
29
+ #
27
30
  # by Michael Neumann (with some revisions)
31
+ #
28
32
  # http://www.espenhaug.com/black_scholes.html
29
33
  def cnd(x)
30
34
  l = x.abs
data/lib/rupee/option.rb CHANGED
@@ -2,28 +2,45 @@ require "rupee/security"
2
2
 
3
3
  module Rupee
4
4
  class Option < Security
5
- attr_accessor :type, :underlying, :strike, :time, :rate, :div_yield, :volatility, :price
6
- alias :rfr :rate
7
- alias :rfr= :rate=
8
- alias :risk_free_rate :rate
9
- alias :risk_free_rate= :rate=
10
- alias :value :price
11
- alias :value= :price=
5
+ # The type of the option. Accepts <tt>"call"</tt> and <tt>"put"</tt>.
6
+ attr_accessor :type
7
+ # The price of the underlying security
8
+ attr_accessor :underlying
9
+ # The strike price of the underlying security
10
+ attr_accessor :strike
11
+ # The remaining time to maturity
12
+ attr_accessor :time
13
+ # The risk-free rate
14
+ attr_accessor :rate
15
+ # The dividend yield
16
+ attr_accessor :div_yield
17
+ # The annualized price volatility
18
+ attr_accessor :volatility
19
+ # The price of the option
20
+ attr_accessor :price
21
+
22
+ attr_alias :rfr, :rate
23
+ attr_alias :risk_free_rate, :rate
24
+ attr_alias :value, :price
12
25
 
13
26
  def black_scholes
14
27
  @value = self.class.black_scholes @type.to_s, @underlying, @strike, @time, @rate, @div_yield, @volatility
15
28
  end
16
29
  end
17
30
 
31
+ # The same thing as Rupee::Option, but with the <tt>:type</tt> flag set to
32
+ # <tt>"call"</tt>
18
33
  class Call < Option
19
- def initialize(opts = {})
34
+ def initialize(opts = {}) # :nodoc:
20
35
  @type = "call"
21
36
  super
22
37
  end
23
38
  end
24
39
 
40
+ # The same thing as Rupee::Option, but with the <tt>:type</tt> flag set to
41
+ # <tt>"put"</tt>
25
42
  class Put < Option
26
- def initialize(opts = {})
43
+ def initialize(opts = {}) # :nodoc:
27
44
  @type = :put
28
45
  super
29
46
  end
data/lib/rupee/quote.rb CHANGED
@@ -3,7 +3,23 @@ autoload :Net, "net/http"
3
3
  autoload :URI, "uri"
4
4
 
5
5
  module Rupee
6
- # The quote and data import functionality in Rupee
6
+ # An object representing a security quote from an online source. With a
7
+ # Rupee::Quote object, you can retrieve the most recent information on a
8
+ # particular security using either the <tt>get</tt> method or the helper
9
+ # methods for each parameter (e.g. <tt>price</tt>, <tt>change</tt>):
10
+ #
11
+ # require "rupee/quote"
12
+ #
13
+ # wfc = Rupee::Quote.new("WFC")
14
+ #
15
+ # wfc.get :price, :change, :pct_change
16
+ # #=> {:price=>24.96, :change=>0.17, :pct_change =>0.686}
17
+ #
18
+ # wfc.price
19
+ # #=> 24.96
20
+ #
21
+ # wfc.change
22
+ # #=> 0.17
7
23
  class Quote
8
24
  # A ticker symbol
9
25
  attr_accessor :ticker
@@ -11,19 +27,29 @@ module Rupee
11
27
  # The name of the quote source
12
28
  attr_accessor :source
13
29
 
14
- # The cached HTML
15
- attr :html
16
-
17
30
  # The frequency in seconds that a quote's information should be updated
18
31
  attr_accessor :frequency
19
32
 
20
33
  # The time at which the next pull from the online quote source will occur
21
34
  attr :next_pull
22
35
 
36
+ # Creates a new Rupee::Quote object.
37
+ #
38
+ # wfc = Rupee::Quote.new("WFC")
39
+ #
40
+ # is equivalent to
41
+ #
42
+ # wfc = Rupee::Quote.new("WFC", :source => :bloomberg, :frequency => 15)
43
+ #
44
+ # Configuration options
45
+ #
46
+ # * <tt>:source</tt> - The name of the source (default is +:bloomberg+).
47
+ # * <tt>:frequency</tt> - How often the quote will seek new values from the
48
+ # quote source, in seconds (default is +15+).
23
49
  def initialize(ticker, opts = {})
24
50
  opts = { :source => :bloomberg, :frequency => 15 }.merge opts
25
51
  @ticker = ticker
26
- @source = Quote.sources[opts[:source]]
52
+ @source = shorten_source(Quote.sources[opts[:source]])
27
53
  @frequency = opts[:frequency]
28
54
  @next_pull = Time.now
29
55
  end
@@ -58,6 +84,9 @@ module Rupee
58
84
  end
59
85
  end
60
86
 
87
+ # call-seq: Rupee#price
88
+ #
89
+ # Blah
61
90
  [:price, :change, :pct_change, :date, :time, :bid, :ask, :open, :high,
62
91
  :low, :volume, :mkt_cap, :p_e].each do |method_name|
63
92
  define_method method_name do
@@ -65,7 +94,7 @@ module Rupee
65
94
  end
66
95
  end
67
96
 
68
- def frequency=(x)
97
+ def frequency=(x) # :nodoc:
69
98
  @next_pull += (x - @frequency)
70
99
  @frequency = x
71
100
  end
@@ -87,6 +116,10 @@ module Rupee
87
116
  end
88
117
  end
89
118
 
119
+ # Parses an object that might be a number
120
+ #
121
+ # parse "15" #=> 15
122
+ # parse "abc" #=> "abc"
90
123
  def parse(result)
91
124
  begin
92
125
  Float(result)
@@ -4,26 +4,26 @@ module Rupee
4
4
  # Automatically sets all arguments passed to <tt>initialize</tt> to
5
5
  # instance variables if they exist (think Rails mass assignment).
6
6
  #
7
- # require "rupee"
7
+ # require "rupee"
8
8
  #
9
- # call = Rupee::Call.new(
10
- # :underlying => 60,
11
- # :strike => 65,
12
- # :time => 0.25,
13
- # :rate => 0.08,
14
- # :div_yield => 0.00,
15
- # :volatility => 0.3
16
- # )
17
- # puts call.black_scholes
18
- # #=> 2.1333718619275794
9
+ # call = Rupee::Call.new(
10
+ # :underlying => 60,
11
+ # :strike => 65,
12
+ # :time => 0.25,
13
+ # :rate => 0.08,
14
+ # :div_yield => 0.00,
15
+ # :volatility => 0.3
16
+ # )
17
+ # puts call.black_scholes
18
+ # #=> 2.1333718619275794
19
19
  #
20
20
  # You still have the option of avoiding the creation of an object (and the
21
21
  # overhead it entails) by using the class methods directly:
22
22
  #
23
- # require "rupee"
23
+ # require "rupee"
24
24
  #
25
- # puts Rupee::Option.black_scholes "c", 60, 65, 0.25, 0.08, 0, 0.3
26
- # #=> 2.1333718619275794
25
+ # puts Rupee::Option.black_scholes "c", 60, 65, 0.25, 0.08, 0, 0.3
26
+ # #=> 2.1333718619275794
27
27
  def initialize(opts = {})
28
28
  opts.each do |key, value|
29
29
  writer = key.to_s.+("=").to_sym
@@ -32,5 +32,22 @@ module Rupee
32
32
  end
33
33
  end
34
34
  end
35
+
36
+ class << self
37
+ # Aliases an attribute, taking into account both its getter and setter
38
+ # methods. For example,
39
+ #
40
+ # attr_accessor :price
41
+ # attr_alias :value, :price
42
+ #
43
+ # would add both a <tt>value</tt> and a <tt>value=</tt> that are equivalent
44
+ # to their <tt>price</tt> counterparts.
45
+ def attr_alias(new_read, old_read)
46
+ alias_method(new_read, old_read) if method_defined?(old_read)
47
+ new_write = "#{new_read}="
48
+ old_write = "#{old_read}="
49
+ alias_method(new_write, old_write) if method_defined?(old_write)
50
+ end
51
+ end
35
52
  end
36
53
  end
data/lib/rupee/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module Rupee
2
2
  # The current version
3
- VERSION = "0.1.3"
3
+ VERSION = "0.1.5"
4
4
  end
data/spec/c/bond_spec.rb CHANGED
@@ -7,10 +7,9 @@ require File.dirname(__FILE__) + "/../spec_helper"
7
7
  # bond yield to maturity = 0.09
8
8
  # new bond price = 104.282
9
9
 
10
- TOLERANCE = 0.001
11
-
12
10
  describe Rupee::Bond do
13
11
  before :each do
12
+ @tolerance = 0.001
14
13
  @times = [1, 2, 3]
15
14
  @cflows = [10, 10, 110]
16
15
  @r = 0.09
@@ -18,39 +17,39 @@ describe Rupee::Bond do
18
17
 
19
18
  describe "with discrete discounting" do
20
19
  it "should produce an accurate price" do
21
- Rupee::Bond.price(@times, @cflows, @r).should be_within(TOLERANCE).of 102.531
20
+ Rupee::Bond.price(@times, @cflows, @r).should be_within(@tolerance).of 102.531
22
21
  end
23
22
 
24
23
  it "should produce an accurate duration" do
25
- Rupee::Bond.duration(@times, @cflows, @r).should be_within(TOLERANCE).of 2.73895
24
+ Rupee::Bond.duration(@times, @cflows, @r).should be_within(@tolerance).of 2.73895
26
25
  end
27
26
 
28
27
  it "should produce an accurate convexity" do
29
- Rupee::Bond.convexity(@times, @cflows, @r).should be_within(TOLERANCE).of 8.93248
28
+ Rupee::Bond.convexity(@times, @cflows, @r).should be_within(@tolerance).of 8.93248
30
29
  end
31
30
 
32
31
  it "should produce an accurate yield to maturity" do
33
32
  @price = Rupee::Bond.price(@times, @cflows, @r)
34
- Rupee::Bond.yield_to_maturity(@times, @cflows, @price).should be_within(TOLERANCE).of @r
33
+ Rupee::Bond.yield_to_maturity(@times, @cflows, @price).should be_within(@tolerance).of @r
35
34
  end
36
35
  end
37
36
 
38
37
  describe "with continuous discounting" do
39
38
  it "should produce an accurate price" do
40
- Rupee::Bond.continuous_price(@times, @cflows, @r).should be_within(TOLERANCE).of 101.464
39
+ Rupee::Bond.continuous_price(@times, @cflows, @r).should be_within(@tolerance).of 101.464
41
40
  end
42
41
 
43
42
  it "should produce an accurate duration" do
44
- Rupee::Bond.continuous_duration(@times, @cflows, @r).should be_within(TOLERANCE).of 2.73753
43
+ Rupee::Bond.continuous_duration(@times, @cflows, @r).should be_within(@tolerance).of 2.73753
45
44
  end
46
45
 
47
46
  it "should produce an accurate convexity" do
48
- Rupee::Bond.continuous_convexity(@times, @cflows, @r).should be_within(TOLERANCE).of 7.86779
47
+ Rupee::Bond.continuous_convexity(@times, @cflows, @r).should be_within(@tolerance).of 7.86779
49
48
  end
50
49
 
51
50
  it "should produce an accurate yield to maturity" do
52
51
  @price = Rupee::Bond.continuous_price(@times, @cflows, @r)
53
- Rupee::Bond.continuous_yield_to_maturity(@times, @cflows, @price).should be_within(TOLERANCE).of @r
52
+ Rupee::Bond.continuous_yield_to_maturity(@times, @cflows, @price).should be_within(@tolerance).of @r
54
53
  end
55
54
  end
56
55
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rupee
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2011-09-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: bundler
16
- requirement: &79757030 !ruby/object:Gem::Requirement
16
+ requirement: &84129210 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '1.0'
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *79757030
24
+ version_requirements: *84129210
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: rspec
27
- requirement: &79755150 !ruby/object:Gem::Requirement
27
+ requirement: &84128900 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '2.0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *79755150
35
+ version_requirements: *84128900
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: autotest
38
- requirement: &79754560 !ruby/object:Gem::Requirement
38
+ requirement: &84127610 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ~>
@@ -43,7 +43,7 @@ dependencies:
43
43
  version: '4.0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *79754560
46
+ version_requirements: *84127610
47
47
  description: rupee aims to provide user-friendly tools for use in financial gems and
48
48
  applications.
49
49
  email:
@@ -58,7 +58,7 @@ files:
58
58
  - .rspec
59
59
  - COPYING
60
60
  - Gemfile
61
- - README.md
61
+ - README.rdoc
62
62
  - Rakefile
63
63
  - ext/rupee/bond.c
64
64
  - ext/rupee/distribution.c
data/README.md DELETED
@@ -1,122 +0,0 @@
1
- Rupee - financial tools for Ruby
2
- ================================
3
-
4
- <table>
5
- <tr>
6
- <td>Homepage</td>
7
- <td><a href="http://www.brymck.com">www.brymck.com</a></td>
8
- </tr>
9
- <tr>
10
- <td>Author</td>
11
- <td>Bryan McKelvey</td>
12
- </tr>
13
- <tr>
14
- <td>Copyright</td>
15
- <td>(c) 2011 Bryan McKelvey</td>
16
- </tr>
17
- <tr>
18
- <td>License</td>
19
- <td>MIT</td>
20
- </tr>
21
- </table>
22
-
23
- [![Flattr this git repo](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=brymck&url=https://github.com/brymck/rupee&title=rupee&language=en_GB&tags=github&category=software)
24
-
25
- /|\
26
- / | \
27
- / | \
28
- /_ / \ _\ RU PE E
29
- | | | | _ _ _
30
- | | | | | | | | |__o ____
31
- | | | | | | | _ | __| |____|
32
- | _| |_ | | | |/ / | |___
33
- \ \ / / /_/|___/ \____|
34
- \ | /
35
- \ | /
36
- \|/ brymck
37
-
38
- Installing
39
- ----------
40
-
41
- Note that you must have Ruby 1.8.7+ installed and the ability to compile native
42
- extensions (standard on most platforms and available on Windows via
43
- [DevKit](http://rubyinstaller.org/downloads/)).
44
-
45
- gem install rupee
46
-
47
- You can also do things the hard way if you want to keep track of the repo:
48
-
49
- git clone git://github.com/brymck/rupee.git
50
- cd rupee
51
- bundle update
52
- rake install
53
-
54
- After all that hard work, you can take a test drive by running something like
55
- this in the Ruby console (i.e. `irb` in a command prompt):
56
-
57
- require "rupee"
58
- Rupee::Option.black_scholes "c", 60, 65, 0.25, 0.08, 0, 0.3
59
- Rupee::Call.new(
60
- :underlying => 60,
61
- :strike => 65,
62
- :time => 0.25,
63
- :rate => 0.08,
64
- :div_yield => 0.00,
65
- :volatility => 0.3
66
- ).black_scholes
67
-
68
- both of which should return `2.1334`.
69
-
70
- You should also be able to get the latest stock info for, for example, Wells
71
- Fargo using the following (note that you only need to `require` the `quote`
72
- module):
73
-
74
- require "rupee/quote"
75
- wfc = Rupee::Quote.new("WFC")
76
-
77
- wfc.get :price, :change, :pct_change
78
- #=> {:price=>24.96, :change=>0.17, :pct_change =>0.686}
79
-
80
- wfc.price
81
- #=> 24.96
82
-
83
- wfc.change
84
- #=> 0.17
85
-
86
- `wfc.get` will return a hash of the requested information for the security.
87
- Each valid parameter will also have its own utility method. The results will
88
- update every `wfc.frequency` seconds (defaults to 15).
89
-
90
- Got it? Good. This will surely help you collect some rupees in real life.
91
-
92
- Performance
93
- -----------
94
-
95
- This is just a simple benchmark I ran on my own laptop, where I value a simple
96
- call option with Black-Scholes 100,000 times. You can test the same on yours
97
- with rake, but in any case it makes the point that for the mathematical side
98
- of finance a native extension has substantial benefits:
99
-
100
- rake benchmark:black_scholes
101
-
102
- Results:
103
-
104
- user system total real
105
- Rupee (class): 0.190000 0.000000 0.190000 ( 0.194001)
106
- Rupee (one object): 0.180000 0.000000 0.180000 ( 0.183091)
107
- Rupee (new object): 2.210000 0.000000 2.210000 ( 2.213351)
108
- Pure Ruby: 2.320000 0.000000 2.320000 ( 2.324259)
109
-
110
- In words, for math-intensive operations, using a C implementation is clearly
111
- faster than the same thing in Ruby.
112
-
113
- Also, if you're doing a valuation on a one-off set of examples (e.g. in a Monte
114
- Carlo simulation), you probably don't want to create an object every time.
115
- Something like `Rupee::Option.black_scholes ...` should work just fine.
116
- Creating a `Rupee::Option` object takes roughly the same amount of time as
117
- running `Rupee::Option.black_scholes` a dozen times.
118
-
119
- However, if you're creating and reusing an object, I strongly recommend
120
- preserving the object orientation of Ruby: the penalty for using a new instance
121
- rather than calling the class method directly is almost entirely in the object
122
- initialization itself.