rupee 0.1.7 → 0.1.8
Sign up to get free protection for your applications and to get access to all the features.
- data/ext/rupee/rupee.h +6 -0
- data/ext/rupee/statistics.c +142 -10
- data/lib/rupee/version.rb +1 -1
- data/spec/c/bond_spec.rb +11 -11
- data/spec/c/future_spec.rb +2 -2
- data/spec/c/option_spec.rb +12 -12
- data/spec/c/statistics_spec.rb +45 -3
- data/spec/import/quote_spec.rb +3 -3
- data/spec/spec_helper.rb +1 -0
- metadata +5 -5
data/ext/rupee/rupee.h
CHANGED
@@ -16,7 +16,13 @@ double simple_df(double r, double time, bool discrete);
|
|
16
16
|
|
17
17
|
/* Statistics */
|
18
18
|
double cnd(double);
|
19
|
+
double corr(double *, double *, int);
|
20
|
+
double cov(double *, double *, int);
|
21
|
+
double mean(double *, int);
|
19
22
|
double std(double *, int);
|
23
|
+
double sum(double *, int);
|
24
|
+
double sum_prod(double *, double *, int);
|
25
|
+
double var(double *, int);
|
20
26
|
void init_distribution();
|
21
27
|
|
22
28
|
/* Options */
|
data/ext/rupee/statistics.c
CHANGED
@@ -32,35 +32,93 @@ cnd(z)
|
|
32
32
|
}
|
33
33
|
|
34
34
|
double
|
35
|
-
|
36
|
-
double *
|
35
|
+
sum_prod(xvals, yvals, len)
|
36
|
+
double *xvals, *yvals;
|
37
37
|
int len;
|
38
38
|
{
|
39
39
|
double result;
|
40
40
|
int i;
|
41
|
+
|
41
42
|
result = 0;
|
42
|
-
|
43
|
+
|
43
44
|
for (i = 0; i < len; i++)
|
44
|
-
result +=
|
45
|
+
result += xvals[i] * yvals[i];
|
46
|
+
|
47
|
+
return result;
|
48
|
+
}
|
49
|
+
|
50
|
+
double
|
51
|
+
corr(xvals, yvals, len)
|
52
|
+
double *xvals, *yvals;
|
53
|
+
int len;
|
54
|
+
{
|
55
|
+
return cov(xvals, yvals, len) / std(xvals, len) / std(yvals, len);
|
56
|
+
}
|
57
|
+
|
58
|
+
double
|
59
|
+
cov(xvals, yvals, len)
|
60
|
+
double *xvals, *yvals;
|
61
|
+
int len;
|
62
|
+
{
|
63
|
+
double result, x_bar, y_bar;
|
64
|
+
int i;
|
65
|
+
|
66
|
+
result = 0;
|
67
|
+
x_bar = mean(xvals, len);
|
68
|
+
y_bar = mean(yvals, len);
|
69
|
+
|
70
|
+
for (i = 0; i < len; i++)
|
71
|
+
result += (xvals[i] - x_bar) * (yvals[i] - y_bar);
|
45
72
|
|
46
73
|
return result / len;
|
47
74
|
}
|
48
75
|
|
49
76
|
double
|
50
|
-
|
77
|
+
var(values, len)
|
51
78
|
double *values;
|
52
79
|
int len;
|
53
80
|
{
|
54
|
-
double
|
81
|
+
double x_bar, result;
|
55
82
|
int i;
|
56
83
|
result = 0;
|
57
84
|
|
58
|
-
|
85
|
+
x_bar = mean(values, len);
|
59
86
|
|
60
87
|
for (i = 0; i < len; i++)
|
61
|
-
result += pow(values[i] -
|
88
|
+
result += pow(values[i] - x_bar, 2);
|
62
89
|
|
63
|
-
return
|
90
|
+
return result / len;
|
91
|
+
}
|
92
|
+
|
93
|
+
double
|
94
|
+
sum(values, len)
|
95
|
+
double *values;
|
96
|
+
int len;
|
97
|
+
{
|
98
|
+
double result;
|
99
|
+
int i;
|
100
|
+
result = 0;
|
101
|
+
|
102
|
+
for (i = 0; i < len; i++)
|
103
|
+
result += values[i];
|
104
|
+
|
105
|
+
return result;
|
106
|
+
}
|
107
|
+
|
108
|
+
double
|
109
|
+
mean(values, len)
|
110
|
+
double *values;
|
111
|
+
int len;
|
112
|
+
{
|
113
|
+
return sum(values, len) / len;
|
114
|
+
}
|
115
|
+
|
116
|
+
double
|
117
|
+
std(values, len)
|
118
|
+
double *values;
|
119
|
+
int len;
|
120
|
+
{
|
121
|
+
return sqrt(var(values, len));
|
64
122
|
}
|
65
123
|
|
66
124
|
/* call-seq: cnd(z)
|
@@ -79,18 +137,80 @@ rupee_cnd(self, _z)
|
|
79
137
|
return rb_float_new(cnd(NUM2DBL(_z)));
|
80
138
|
}
|
81
139
|
|
140
|
+
static VALUE
|
141
|
+
rupee_corr(self, _xvals, _yvals)
|
142
|
+
VALUE self, _xvals, _yvals;
|
143
|
+
{
|
144
|
+
int len = RARRAY_LEN(_xvals);
|
145
|
+
double xvals[len], yvals[len];
|
146
|
+
|
147
|
+
rtofa(xvals, _xvals, len);
|
148
|
+
rtofa(yvals, _yvals, len);
|
149
|
+
|
150
|
+
return rb_float_new(corr(xvals, yvals, len));
|
151
|
+
}
|
152
|
+
|
153
|
+
static VALUE
|
154
|
+
rupee_cov(self, _xvals, _yvals)
|
155
|
+
VALUE self, _xvals, _yvals;
|
156
|
+
{
|
157
|
+
int len = RARRAY_LEN(_xvals);
|
158
|
+
double xvals[len], yvals[len];
|
159
|
+
|
160
|
+
rtofa(xvals, _xvals, len);
|
161
|
+
rtofa(yvals, _yvals, len);
|
162
|
+
|
163
|
+
return rb_float_new(cov(xvals, yvals, len));
|
164
|
+
}
|
165
|
+
|
166
|
+
static VALUE
|
167
|
+
rupee_mean(self, _values)
|
168
|
+
VALUE self, _values;
|
169
|
+
{
|
170
|
+
int len = RARRAY_LEN(_values);
|
171
|
+
double values[len];
|
172
|
+
|
173
|
+
rtofa(values, _values, len);
|
174
|
+
|
175
|
+
return rb_float_new(mean(values, len));
|
176
|
+
}
|
177
|
+
|
82
178
|
static VALUE
|
83
179
|
rupee_std(self, _values)
|
84
180
|
VALUE self, _values;
|
85
181
|
{
|
86
182
|
int len = RARRAY_LEN(_values);
|
87
|
-
double
|
183
|
+
double values[len];
|
88
184
|
|
89
185
|
rtofa(values, _values, len);
|
90
186
|
|
91
187
|
return rb_float_new(std(values, len));
|
92
188
|
}
|
93
189
|
|
190
|
+
static VALUE
|
191
|
+
rupee_sum(self, _values)
|
192
|
+
VALUE self, _values;
|
193
|
+
{
|
194
|
+
int len = RARRAY_LEN(_values);
|
195
|
+
double values[len];
|
196
|
+
|
197
|
+
rtofa(values, _values, len);
|
198
|
+
|
199
|
+
return rb_float_new(sum(values, len));
|
200
|
+
}
|
201
|
+
|
202
|
+
static VALUE
|
203
|
+
rupee_var(self, _values)
|
204
|
+
VALUE self, _values;
|
205
|
+
{
|
206
|
+
int len = RARRAY_LEN(_values);
|
207
|
+
double values[len];
|
208
|
+
|
209
|
+
rtofa(values, _values, len);
|
210
|
+
|
211
|
+
return rb_float_new(var(values, len));
|
212
|
+
}
|
213
|
+
|
94
214
|
void
|
95
215
|
init_distribution()
|
96
216
|
{
|
@@ -103,9 +223,21 @@ init_distribution()
|
|
103
223
|
klass = rb_define_class_under(module, "Statistics", rb_cObject);
|
104
224
|
singleton = rb_singleton_class(klass);
|
105
225
|
|
226
|
+
rb_define_singleton_method(klass, "correlation", rupee_corr, 2);
|
227
|
+
rb_define_alias(singleton, "corr", "correlation");
|
228
|
+
rb_define_alias(singleton, "correl", "correlation");
|
229
|
+
rb_define_singleton_method(klass, "covariance", rupee_cov, 2);
|
230
|
+
rb_define_alias(singleton, "cov", "covariance");
|
231
|
+
rb_define_alias(singleton, "covar", "covariance");
|
106
232
|
rb_define_singleton_method(klass, "cumulative_normal_distribution", rupee_cnd, 1);
|
107
233
|
rb_define_alias(singleton, "cnd", "cumulative_normal_distribution");
|
234
|
+
rb_define_singleton_method(klass, "mean", rupee_mean, 1);
|
235
|
+
rb_define_alias(singleton, "average", "mean");
|
236
|
+
rb_define_alias(singleton, "avg", "mean");
|
108
237
|
rb_define_singleton_method(klass, "standard_deviation", rupee_std, 1);
|
109
238
|
rb_define_alias(singleton, "std", "standard_deviation");
|
110
239
|
rb_define_alias(singleton, "stdev", "standard_deviation");
|
240
|
+
rb_define_singleton_method(klass, "sum", rupee_sum, 1);
|
241
|
+
rb_define_singleton_method(klass, "variance", rupee_var, 1);
|
242
|
+
rb_define_alias(singleton, "var", "variance");
|
111
243
|
}
|
data/lib/rupee/version.rb
CHANGED
data/spec/c/bond_spec.rb
CHANGED
@@ -6,7 +6,7 @@ require File.dirname(__FILE__) + "/../spec_helper"
|
|
6
6
|
# bond yield to maturity = 0.09
|
7
7
|
# new bond price = 104.282
|
8
8
|
|
9
|
-
describe
|
9
|
+
describe Bond do
|
10
10
|
before :each do
|
11
11
|
@tolerance = 0.001
|
12
12
|
@times = [1, 2, 3]
|
@@ -16,7 +16,7 @@ describe Rupee::Bond do
|
|
16
16
|
|
17
17
|
describe "with discrete discounting" do
|
18
18
|
before :each do
|
19
|
-
@price =
|
19
|
+
@price = Bond.price(@times, @cflows, @r)
|
20
20
|
end
|
21
21
|
|
22
22
|
it "should produce an accurate price" do
|
@@ -24,38 +24,38 @@ describe Rupee::Bond do
|
|
24
24
|
end
|
25
25
|
|
26
26
|
it "should produce an accurate duration" do
|
27
|
-
|
27
|
+
Bond.duration(@times, @cflows, @r).should be_within(@tolerance).of 2.73895
|
28
28
|
end
|
29
29
|
|
30
30
|
it "should produce an accurate modified duration" do
|
31
|
-
|
31
|
+
Bond.modified(@times, @cflows, @price).should be_within(@tolerance).of 2.5128
|
32
32
|
end
|
33
33
|
|
34
34
|
it "should produce an accurate convexity" do
|
35
|
-
|
35
|
+
Bond.convexity(@times, @cflows, @r).should be_within(@tolerance).of 8.93248
|
36
36
|
end
|
37
37
|
|
38
38
|
it "should produce an accurate yield to maturity" do
|
39
|
-
|
39
|
+
Bond.yield_to_maturity(@times, @cflows, @price).should be_within(@tolerance).of @r
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
43
|
describe "with continuous discounting" do
|
44
44
|
it "should produce an accurate price" do
|
45
|
-
|
45
|
+
Bond.continuous_price(@times, @cflows, @r).should be_within(@tolerance).of 101.464
|
46
46
|
end
|
47
47
|
|
48
48
|
it "should produce an accurate duration" do
|
49
|
-
|
49
|
+
Bond.continuous_duration(@times, @cflows, @r).should be_within(@tolerance).of 2.73753
|
50
50
|
end
|
51
51
|
|
52
52
|
it "should produce an accurate convexity" do
|
53
|
-
|
53
|
+
Bond.continuous_convexity(@times, @cflows, @r).should be_within(@tolerance).of 7.86779
|
54
54
|
end
|
55
55
|
|
56
56
|
it "should produce an accurate yield to maturity" do
|
57
|
-
@price =
|
58
|
-
|
57
|
+
@price = Bond.continuous_price(@times, @cflows, @r)
|
58
|
+
Bond.continuous_yield_to_maturity(@times, @cflows, @price).should be_within(@tolerance).of @r
|
59
59
|
end
|
60
60
|
end
|
61
61
|
end
|
data/spec/c/future_spec.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/../spec_helper"
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe Future do
|
4
4
|
before :each do
|
5
5
|
@tolerance = 0.001
|
6
6
|
@underlying = 100
|
@@ -9,7 +9,7 @@ describe Rupee::Future do
|
|
9
9
|
end
|
10
10
|
|
11
11
|
it "should produce an accurate price" do
|
12
|
-
|
12
|
+
Future.price(@underlying, @rfr, @ttm).should(
|
13
13
|
be_within(@tolerance).of 105.127
|
14
14
|
)
|
15
15
|
end
|
data/spec/c/option_spec.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/../spec_helper"
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe Option do
|
4
4
|
describe "European option valuation" do
|
5
5
|
before :each do
|
6
6
|
@tolerance = 0.0001
|
7
|
-
@call =
|
7
|
+
@call = Option.new(
|
8
8
|
:underlying => 60,
|
9
9
|
:strike => 65,
|
10
10
|
:time => 0.25,
|
@@ -17,11 +17,11 @@ describe Rupee::Option do
|
|
17
17
|
describe "using the Black-76 model" do
|
18
18
|
describe "on a call option of price $60, strike $65, time to expiry 0.25, risk-free rate 8%, and volatility 30%" do
|
19
19
|
it "should return $1.7202 for a call" do
|
20
|
-
|
20
|
+
Option.black76("c", 60, 65, 0.25, 0.08, 0.3).should be_within(@tolerance).of 1.7202
|
21
21
|
end
|
22
22
|
|
23
23
|
it "should return $6.6212 for a put" do
|
24
|
-
|
24
|
+
Option.black76("p", 60, 65, 0.25, 0.08, 0.3).should be_within(@tolerance).of 6.6212
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
@@ -29,13 +29,13 @@ describe Rupee::Option do
|
|
29
29
|
describe "using the generalized Black-Scholes model" do
|
30
30
|
describe "on a call option of price $60, strike $65, time to expiry 0.25, risk-free rate 8%, and volatility 30%" do
|
31
31
|
it "should return $1.7202 for a call" do
|
32
|
-
|
33
|
-
|
32
|
+
Option.generalized_black_scholes("c", 60, 65, 0.25, 0.08, 0, 0.3).should be_within(@tolerance).of 1.7202
|
33
|
+
Option.gbs("c", 60, 65, 0.25, 0.08, 0, 0.3).should be_within(@tolerance).of 1.7202
|
34
34
|
end
|
35
35
|
|
36
36
|
it "should return $6.6212 for a put" do
|
37
|
-
|
38
|
-
|
37
|
+
Option.generalized_black_scholes("p", 60, 65, 0.25, 0.08, 0, 0.3).should be_within(@tolerance).of 6.6212
|
38
|
+
Option.gbs("p", 60, 65, 0.25, 0.08, 0, 0.3).should be_within(@tolerance).of 6.6212
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
@@ -43,14 +43,14 @@ describe Rupee::Option do
|
|
43
43
|
describe "using the Black-Scholes model" do
|
44
44
|
describe "on a call option of price $60, strike $65, time to expiry 0.25, risk-free rate 8%, and volatility 30%" do
|
45
45
|
it "should return $1.7202 for a call" do
|
46
|
-
|
47
|
-
|
46
|
+
Option.black_scholes("c", 60, 65, 0.25, 0.08, 0, 0.3).should be_within(@tolerance).of 2.1334
|
47
|
+
Option.bs("c", 60, 65, 0.25, 0.08, 0, 0.3).should be_within(@tolerance).of 2.1334
|
48
48
|
@call.black_scholes.should be_within(@tolerance).of 2.1334
|
49
49
|
end
|
50
50
|
|
51
51
|
it "should return $6.6212 for a put" do
|
52
|
-
|
53
|
-
|
52
|
+
Option.black_scholes("p", 60, 65, 0.25, 0.08, 0, 0.3).should be_within(@tolerance).of 5.8463
|
53
|
+
Option.bs("p", 60, 65, 0.25, 0.08, 0, 0.3).should be_within(@tolerance).of 5.8463
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
data/spec/c/statistics_spec.rb
CHANGED
@@ -1,7 +1,49 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/../spec_helper"
|
2
2
|
|
3
|
-
describe
|
4
|
-
|
5
|
-
|
3
|
+
describe Statistics do
|
4
|
+
before :each do
|
5
|
+
@tolerance = 0.0001
|
6
|
+
@values = [0, 1, 2, 3, 4]
|
7
|
+
@more_values = [0, 1, 2, 4, 8]
|
8
|
+
end
|
9
|
+
|
10
|
+
it "should return an accurate cumulative normal distribution" do
|
11
|
+
@result = Statistics.cnd(0)
|
12
|
+
@result.should be_within(@tolerance).of 0.5
|
13
|
+
Statistics.cumulative_normal_distribution(0).should == @result
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should return an accurate sum" do
|
17
|
+
Statistics.sum(@values).should == 10
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should return an accurate mean" do
|
21
|
+
Statistics.mean(@values).should == 2
|
22
|
+
Statistics.average(@values).should == 2
|
23
|
+
Statistics.avg(@values).should == 2
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should return an accurate standard deviation" do
|
27
|
+
@result = Statistics.standard_deviation(@values)
|
28
|
+
@result.should be_within(@tolerance).of 1.4142
|
29
|
+
Statistics.std(@values).should == @result
|
30
|
+
Statistics.stdev(@values).should == @result
|
31
|
+
end
|
32
|
+
|
33
|
+
it "should return an accurate variance" do
|
34
|
+
Statistics.variance(@values).should == 2
|
35
|
+
Statistics.var(@values).should == 2
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should return an accurate covariance" do
|
39
|
+
Statistics.covariance(@values, @more_values).should == 3.8
|
40
|
+
Statistics.cov(@values, @more_values).should == 3.8
|
41
|
+
Statistics.covar(@values, @more_values).should == 3.8
|
42
|
+
end
|
43
|
+
|
44
|
+
it "should return an accurate correlation" do
|
45
|
+
Statistics.correlation(@values, @more_values).should == 0.95
|
46
|
+
Statistics.corr(@values, @more_values).should == 0.95
|
47
|
+
Statistics.correl(@values, @more_values).should == 0.95
|
6
48
|
end
|
7
49
|
end
|
data/spec/import/quote_spec.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/../spec_helper"
|
2
2
|
|
3
|
-
describe
|
3
|
+
describe Quote do
|
4
4
|
it "should automatically have a Bloomberg source" do
|
5
|
-
|
5
|
+
Quote.sources.should include :bloomberg
|
6
6
|
end
|
7
7
|
|
8
8
|
describe "when pulling quotes" do
|
9
9
|
describe "without any parameters specified" do
|
10
10
|
before :each do
|
11
|
-
@wfc =
|
11
|
+
@wfc = Quote.new("WFC")
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should default to pulling the price" do
|
data/spec/spec_helper.rb
CHANGED
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.8
|
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: &85358040 !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: *85358040
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &85357630 !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: *85357630
|
36
36
|
description: ! " rupee aims to provide user-friendly tools for
|
37
37
|
use in\n financial gems and applications.\n"
|
38
38
|
email:
|