rupee 0.1.7 → 0.1.8
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/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:
|