rupee 0.1.6 → 0.1.7
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
-
}
|