rupee 0.1.6 → 0.1.7
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/.autotest +4 -0
- data/README.rdoc +5 -5
- data/ext/rupee/rupee.h +1 -0
- data/ext/rupee/statistics.c +111 -0
- data/lib/rupee/benchmark.rb +7 -10
- data/lib/rupee/option.rb +2 -1
- data/lib/rupee/version.rb +1 -1
- data/spec/c/option_spec.rb +23 -10
- data/spec/c/statistics_spec.rb +7 -0
- metadata +9 -8
- data/ext/rupee/distribution.c +0 -63
- data/spec/c/distribution_spec.rb +0 -7
data/.autotest
ADDED
data/README.rdoc
CHANGED
@@ -66,9 +66,9 @@ Fargo using the following (note that you only need to <tt>require</tt> the
|
|
66
66
|
wfc.change
|
67
67
|
#=> 0.17
|
68
68
|
|
69
|
-
<tt>wfc.get</tt> will return a hash of the requested information for the
|
70
|
-
Each valid parameter will also have its own utility method. The
|
71
|
-
update every <tt>wfc.frequency</tt> seconds (defaults to 15).
|
69
|
+
<tt>wfc.get</tt> will return a hash of the requested information for the
|
70
|
+
security. Each valid parameter will also have its own utility method. The
|
71
|
+
results will update every <tt>wfc.frequency</tt> seconds (defaults to 15).
|
72
72
|
|
73
73
|
Got it? Good. This will surely help you collect some rupees in real life.
|
74
74
|
|
@@ -95,8 +95,8 @@ faster than the same thing in Ruby.
|
|
95
95
|
Also, if you're doing a valuation on a one-off set of examples (e.g. in a Monte
|
96
96
|
Carlo simulation), you probably don't want to create an object every time.
|
97
97
|
Something like <tt>Rupee::Option.black_scholes ...</tt> should work just fine.
|
98
|
-
Creating a <tt>Rupee::Option</tt> object takes roughly the same amount of time
|
99
|
-
running <tt>Rupee::Option.black_scholes</tt> a dozen times.
|
98
|
+
Creating a <tt>Rupee::Option</tt> object takes roughly the same amount of time
|
99
|
+
as running <tt>Rupee::Option.black_scholes</tt> a dozen times.
|
100
100
|
|
101
101
|
However, if you're creating and reusing an object, I strongly recommend
|
102
102
|
preserving the object orientation of Ruby: the penalty for using a new instance
|
data/ext/rupee/rupee.h
CHANGED
@@ -0,0 +1,111 @@
|
|
1
|
+
#include "rupee.h"
|
2
|
+
|
3
|
+
#define PI 3.1415926536
|
4
|
+
|
5
|
+
double
|
6
|
+
cnd(z)
|
7
|
+
double z;
|
8
|
+
{
|
9
|
+
double L, K, dCND;
|
10
|
+
static const double b = 0.2316419;
|
11
|
+
static const double a1 = 0.31938153;
|
12
|
+
static const double a2 = 0.356563782;
|
13
|
+
static const double a3 = 1.781477937;
|
14
|
+
static const double a4 = 1.821255978;
|
15
|
+
static const double a5 = 1.330274429;
|
16
|
+
|
17
|
+
L = fabs(z);
|
18
|
+
K = 1.0 / (1.0 + b * L);
|
19
|
+
|
20
|
+
dCND = 1.0 - 1.0 / sqrt(2.0 * PI) *
|
21
|
+
exp(-L * L / 2.0) *
|
22
|
+
(a1 * K -
|
23
|
+
a2 * K * K +
|
24
|
+
a3 * K * K * K -
|
25
|
+
a4 * K * K * K * K +
|
26
|
+
a5 * K * K * K * K * K);
|
27
|
+
|
28
|
+
if (z < 0.0)
|
29
|
+
return 1.0 - dCND;
|
30
|
+
else
|
31
|
+
return dCND;
|
32
|
+
}
|
33
|
+
|
34
|
+
double
|
35
|
+
mean(values, len)
|
36
|
+
double *values;
|
37
|
+
int len;
|
38
|
+
{
|
39
|
+
double result;
|
40
|
+
int i;
|
41
|
+
result = 0;
|
42
|
+
|
43
|
+
for (i = 0; i < len; i++)
|
44
|
+
result += values[i];
|
45
|
+
|
46
|
+
return result / len;
|
47
|
+
}
|
48
|
+
|
49
|
+
double
|
50
|
+
std(values, len)
|
51
|
+
double *values;
|
52
|
+
int len;
|
53
|
+
{
|
54
|
+
double bar_x, result;
|
55
|
+
int i;
|
56
|
+
result = 0;
|
57
|
+
|
58
|
+
bar_x = mean(values, len);
|
59
|
+
|
60
|
+
for (i = 0; i < len; i++)
|
61
|
+
result += pow(values[i] - bar_x, 2);
|
62
|
+
|
63
|
+
return sqrt(result / (len - 1));
|
64
|
+
}
|
65
|
+
|
66
|
+
/* call-seq: cnd(z)
|
67
|
+
*
|
68
|
+
* Returns the standard normal cumulative distribution (has a mean of zero and
|
69
|
+
* a standard deviation of one).
|
70
|
+
*
|
71
|
+
* ==== Arguments
|
72
|
+
*
|
73
|
+
* * +z+ - The value for which you want the distribution
|
74
|
+
*/
|
75
|
+
static VALUE
|
76
|
+
rupee_cnd(self, _z)
|
77
|
+
VALUE self, _z;
|
78
|
+
{
|
79
|
+
return rb_float_new(cnd(NUM2DBL(_z)));
|
80
|
+
}
|
81
|
+
|
82
|
+
static VALUE
|
83
|
+
rupee_std(self, _values)
|
84
|
+
VALUE self, _values;
|
85
|
+
{
|
86
|
+
int len = RARRAY_LEN(_values);
|
87
|
+
double *values;
|
88
|
+
|
89
|
+
rtofa(values, _values, len);
|
90
|
+
|
91
|
+
return rb_float_new(std(values, len));
|
92
|
+
}
|
93
|
+
|
94
|
+
void
|
95
|
+
init_distribution()
|
96
|
+
{
|
97
|
+
VALUE klass, singleton;
|
98
|
+
|
99
|
+
#if 0
|
100
|
+
VALUE module = rb_define_module("Rupee");
|
101
|
+
#endif
|
102
|
+
|
103
|
+
klass = rb_define_class_under(module, "Statistics", rb_cObject);
|
104
|
+
singleton = rb_singleton_class(klass);
|
105
|
+
|
106
|
+
rb_define_singleton_method(klass, "cumulative_normal_distribution", rupee_cnd, 1);
|
107
|
+
rb_define_alias(singleton, "cnd", "cumulative_normal_distribution");
|
108
|
+
rb_define_singleton_method(klass, "standard_deviation", rupee_std, 1);
|
109
|
+
rb_define_alias(singleton, "std", "standard_deviation");
|
110
|
+
rb_define_alias(singleton, "stdev", "standard_deviation");
|
111
|
+
}
|
data/lib/rupee/benchmark.rb
CHANGED
@@ -7,10 +7,10 @@ module Rupee
|
|
7
7
|
# by Michael Neumann (with some revisions)
|
8
8
|
#
|
9
9
|
# http://www.espenhaug.com/black_scholes.html
|
10
|
-
def black_scholes(
|
10
|
+
def black_scholes(call_put_flag, s, x, t, r, v)
|
11
11
|
d1 = (Math.log(s / x) + (r + v * v / 2.0) * t) / (v * Math.sqrt(t))
|
12
12
|
d2 = d1 - v * Math.sqrt(t)
|
13
|
-
if
|
13
|
+
if call_put_flag == 'c'
|
14
14
|
s * cnd(d1) - x * Math.exp(-r * t) * cnd(d2)
|
15
15
|
else
|
16
16
|
x * Math.exp(-r * t) * cnd(-d2) - s * cnd(-d1)
|
@@ -19,12 +19,6 @@ module Rupee
|
|
19
19
|
|
20
20
|
private
|
21
21
|
|
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:
|
27
|
-
|
28
22
|
# Cumulative normal distribution
|
29
23
|
#
|
30
24
|
# by Michael Neumann (with some revisions)
|
@@ -34,9 +28,12 @@ module Rupee
|
|
34
28
|
l = x.abs
|
35
29
|
k = 1.0 / (1.0 + 0.2316419 * l)
|
36
30
|
w = 1.0 - 1.0 / Math.sqrt(2 * Math::PI) * Math.exp(-l * l / 2.0) *
|
37
|
-
(
|
31
|
+
( 0.31938153 * k +
|
32
|
+
-0.356563782 * (k ** 2) +
|
33
|
+
1.781477937 * (k ** 3) +
|
34
|
+
-1.821255978 * (k ** 4) +
|
35
|
+
1.330274429 * (k ** 5))
|
38
36
|
w = 1.0 - w if x < 0
|
39
|
-
return w
|
40
37
|
end
|
41
38
|
end
|
42
39
|
end
|
data/lib/rupee/option.rb
CHANGED
@@ -24,7 +24,8 @@ module Rupee
|
|
24
24
|
attr_alias :value, :price
|
25
25
|
|
26
26
|
def black_scholes
|
27
|
-
@value = self.class.black_scholes @type.to_s, @underlying, @strike,
|
27
|
+
@value = self.class.black_scholes @type.to_s, @underlying, @strike,
|
28
|
+
@time, @rate, @div_yield, @volatility
|
28
29
|
end
|
29
30
|
end
|
30
31
|
|
data/lib/rupee/version.rb
CHANGED
data/spec/c/option_spec.rb
CHANGED
@@ -2,14 +2,26 @@ require File.dirname(__FILE__) + "/../spec_helper"
|
|
2
2
|
|
3
3
|
describe Rupee::Option do
|
4
4
|
describe "European option valuation" do
|
5
|
+
before :each do
|
6
|
+
@tolerance = 0.0001
|
7
|
+
@call = Rupee::Option.new(
|
8
|
+
:underlying => 60,
|
9
|
+
:strike => 65,
|
10
|
+
:time => 0.25,
|
11
|
+
:rate => 0.08,
|
12
|
+
:div_yield => 0,
|
13
|
+
:volatility => 0.3
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
5
17
|
describe "using the Black-76 model" do
|
6
18
|
describe "on a call option of price $60, strike $65, time to expiry 0.25, risk-free rate 8%, and volatility 30%" do
|
7
19
|
it "should return $1.7202 for a call" do
|
8
|
-
Rupee::Option.black76("c", 60, 65, 0.25, 0.08, 0.3).
|
20
|
+
Rupee::Option.black76("c", 60, 65, 0.25, 0.08, 0.3).should be_within(@tolerance).of 1.7202
|
9
21
|
end
|
10
22
|
|
11
23
|
it "should return $6.6212 for a put" do
|
12
|
-
Rupee::Option.black76("p", 60, 65, 0.25, 0.08, 0.3).
|
24
|
+
Rupee::Option.black76("p", 60, 65, 0.25, 0.08, 0.3).should be_within(@tolerance).of 6.6212
|
13
25
|
end
|
14
26
|
end
|
15
27
|
end
|
@@ -17,13 +29,13 @@ describe Rupee::Option do
|
|
17
29
|
describe "using the generalized Black-Scholes model" do
|
18
30
|
describe "on a call option of price $60, strike $65, time to expiry 0.25, risk-free rate 8%, and volatility 30%" do
|
19
31
|
it "should return $1.7202 for a call" do
|
20
|
-
Rupee::Option.generalized_black_scholes("c", 60, 65, 0.25, 0.08, 0, 0.3).
|
21
|
-
Rupee::Option.gbs("c", 60, 65, 0.25, 0.08, 0, 0.3).
|
32
|
+
Rupee::Option.generalized_black_scholes("c", 60, 65, 0.25, 0.08, 0, 0.3).should be_within(@tolerance).of 1.7202
|
33
|
+
Rupee::Option.gbs("c", 60, 65, 0.25, 0.08, 0, 0.3).should be_within(@tolerance).of 1.7202
|
22
34
|
end
|
23
35
|
|
24
36
|
it "should return $6.6212 for a put" do
|
25
|
-
Rupee::Option.generalized_black_scholes("p", 60, 65, 0.25, 0.08, 0, 0.3).
|
26
|
-
Rupee::Option.gbs("p", 60, 65, 0.25, 0.08, 0, 0.3).
|
37
|
+
Rupee::Option.generalized_black_scholes("p", 60, 65, 0.25, 0.08, 0, 0.3).should be_within(@tolerance).of 6.6212
|
38
|
+
Rupee::Option.gbs("p", 60, 65, 0.25, 0.08, 0, 0.3).should be_within(@tolerance).of 6.6212
|
27
39
|
end
|
28
40
|
end
|
29
41
|
end
|
@@ -31,13 +43,14 @@ describe Rupee::Option do
|
|
31
43
|
describe "using the Black-Scholes model" do
|
32
44
|
describe "on a call option of price $60, strike $65, time to expiry 0.25, risk-free rate 8%, and volatility 30%" do
|
33
45
|
it "should return $1.7202 for a call" do
|
34
|
-
Rupee::Option.black_scholes("c", 60, 65, 0.25, 0.08, 0, 0.3).
|
35
|
-
Rupee::Option.bs("c", 60, 65, 0.25, 0.08, 0, 0.3).
|
46
|
+
Rupee::Option.black_scholes("c", 60, 65, 0.25, 0.08, 0, 0.3).should be_within(@tolerance).of 2.1334
|
47
|
+
Rupee::Option.bs("c", 60, 65, 0.25, 0.08, 0, 0.3).should be_within(@tolerance).of 2.1334
|
48
|
+
@call.black_scholes.should be_within(@tolerance).of 2.1334
|
36
49
|
end
|
37
50
|
|
38
51
|
it "should return $6.6212 for a put" do
|
39
|
-
Rupee::Option.black_scholes("p", 60, 65, 0.25, 0.08, 0, 0.3).
|
40
|
-
Rupee::Option.bs("p", 60, 65, 0.25, 0.08, 0, 0.3).
|
52
|
+
Rupee::Option.black_scholes("p", 60, 65, 0.25, 0.08, 0, 0.3).should be_within(@tolerance).of 5.8463
|
53
|
+
Rupee::Option.bs("p", 60, 65, 0.25, 0.08, 0, 0.3).should be_within(@tolerance).of 5.8463
|
41
54
|
end
|
42
55
|
end
|
43
56
|
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.
|
4
|
+
version: 0.1.7
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2011-09-29 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
16
|
-
requirement: &
|
16
|
+
requirement: &68970630 !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: *
|
24
|
+
version_requirements: *68970630
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &68970360 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: '2.0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *68970360
|
36
36
|
description: ! " rupee aims to provide user-friendly tools for
|
37
37
|
use in\n financial gems and applications.\n"
|
38
38
|
email:
|
@@ -42,6 +42,7 @@ extensions:
|
|
42
42
|
- ext/rupee/extconf.rb
|
43
43
|
extra_rdoc_files: []
|
44
44
|
files:
|
45
|
+
- .autotest
|
45
46
|
- .gitignore
|
46
47
|
- .rspec
|
47
48
|
- COPYING
|
@@ -49,12 +50,12 @@ files:
|
|
49
50
|
- README.rdoc
|
50
51
|
- Rakefile
|
51
52
|
- ext/rupee/bond.c
|
52
|
-
- ext/rupee/distribution.c
|
53
53
|
- ext/rupee/extconf.rb
|
54
54
|
- ext/rupee/future.c
|
55
55
|
- ext/rupee/option.c
|
56
56
|
- ext/rupee/rupee.c
|
57
57
|
- ext/rupee/rupee.h
|
58
|
+
- ext/rupee/statistics.c
|
58
59
|
- ext/rupee/util.c
|
59
60
|
- lib/rupee.rb
|
60
61
|
- lib/rupee/benchmark.rb
|
@@ -65,9 +66,9 @@ files:
|
|
65
66
|
- lib/rupee/version.rb
|
66
67
|
- rupee.gemspec
|
67
68
|
- spec/c/bond_spec.rb
|
68
|
-
- spec/c/distribution_spec.rb
|
69
69
|
- spec/c/future_spec.rb
|
70
70
|
- spec/c/option_spec.rb
|
71
|
+
- spec/c/statistics_spec.rb
|
71
72
|
- spec/import/quote_spec.rb
|
72
73
|
- spec/spec_helper.rb
|
73
74
|
- tasks/benchmark.rake
|
@@ -98,7 +99,7 @@ specification_version: 3
|
|
98
99
|
summary: Financial tools for Ruby
|
99
100
|
test_files:
|
100
101
|
- spec/c/bond_spec.rb
|
101
|
-
- spec/c/distribution_spec.rb
|
102
102
|
- spec/c/future_spec.rb
|
103
103
|
- spec/c/option_spec.rb
|
104
|
+
- spec/c/statistics_spec.rb
|
104
105
|
- spec/import/quote_spec.rb
|
data/ext/rupee/distribution.c
DELETED
@@ -1,63 +0,0 @@
|
|
1
|
-
#include "rupee.h"
|
2
|
-
|
3
|
-
#define PI 3.1415926536
|
4
|
-
|
5
|
-
double
|
6
|
-
cnd(z)
|
7
|
-
double z;
|
8
|
-
{
|
9
|
-
double L, K, dCND;
|
10
|
-
static const double b = 0.2316419;
|
11
|
-
static const double a1 = 0.31938153;
|
12
|
-
static const double a2 = 0.356563782;
|
13
|
-
static const double a3 = 1.781477937;
|
14
|
-
static const double a4 = 1.821255978;
|
15
|
-
static const double a5 = 1.330274429;
|
16
|
-
|
17
|
-
L = fabs(z);
|
18
|
-
K = 1.0 / (1.0 + b * L);
|
19
|
-
|
20
|
-
dCND = 1.0 - 1.0 / sqrt(2.0 * PI) *
|
21
|
-
exp(-L * L / 2.0) *
|
22
|
-
(a1 * K -
|
23
|
-
a2 * K * K +
|
24
|
-
a3 * K * K * K -
|
25
|
-
a4 * K * K * K * K +
|
26
|
-
a5 * K * K * K * K * K);
|
27
|
-
|
28
|
-
if (z < 0.0)
|
29
|
-
return 1.0 - dCND;
|
30
|
-
else
|
31
|
-
return dCND;
|
32
|
-
}
|
33
|
-
|
34
|
-
/* call-seq: cnd(z)
|
35
|
-
*
|
36
|
-
* Returns the standard normal cumulative distribution (has a mean of zero and
|
37
|
-
* a standard deviation of one).
|
38
|
-
*
|
39
|
-
* ==== Arguments
|
40
|
-
*
|
41
|
-
* * +z+ - The value for which you want the distribution
|
42
|
-
*/
|
43
|
-
static VALUE
|
44
|
-
rupee_cnd(self, rz)
|
45
|
-
VALUE self, rz;
|
46
|
-
{
|
47
|
-
return rb_float_new(cnd(NUM2DBL(rz)));
|
48
|
-
}
|
49
|
-
|
50
|
-
void
|
51
|
-
init_distribution()
|
52
|
-
{
|
53
|
-
VALUE klass, singleton;
|
54
|
-
|
55
|
-
#if 0
|
56
|
-
VALUE module = rb_define_module("Rupee");
|
57
|
-
#endif
|
58
|
-
|
59
|
-
klass = rb_define_class_under(module, "Distribution", rb_cObject);
|
60
|
-
singleton = rb_singleton_class(klass);
|
61
|
-
|
62
|
-
rb_define_singleton_method(klass, "cnd", rupee_cnd, 1);
|
63
|
-
}
|