rupee 0.1.5 → 0.1.6
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/README.rdoc +5 -4
- data/ext/rupee/bond.c +20 -0
- data/lib/rupee/quote/source.rb +9 -8
- data/lib/rupee/quote.rb +5 -21
- data/lib/rupee/version.rb +1 -1
- data/rupee.gemspec +19 -17
- data/spec/c/bond_spec.rb +9 -3
- data/spec/c/future_spec.rb +4 -1
- metadata +8 -20
- data/.autotest +0 -2
data/README.rdoc
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
= Rupee - financial tools for Ruby
|
2
2
|
|
3
|
-
Homepage::
|
4
|
-
Author::
|
5
|
-
Copyright::
|
6
|
-
License::
|
3
|
+
Homepage:: http://www.brymck.com
|
4
|
+
Author:: Bryan McKelvey
|
5
|
+
Copyright:: (c) 2011 Bryan McKelvey
|
6
|
+
License:: MIT
|
7
|
+
Documentation:: http://rdoc.info/github/brymck/rupee/master/frames
|
7
8
|
|
8
9
|
/|\
|
9
10
|
/ | \
|
data/ext/rupee/bond.c
CHANGED
@@ -224,6 +224,24 @@ macaulay_discrete(self, _times, _cflows, _price)
|
|
224
224
|
return macaulay(self, _times, _cflows, _price, true);
|
225
225
|
}
|
226
226
|
|
227
|
+
// Modified duration of a discretely compounded bond
|
228
|
+
static VALUE
|
229
|
+
modified_discrete(self, _times, _cflows, _price)
|
230
|
+
VALUE self, _times, _cflows, _price;
|
231
|
+
{
|
232
|
+
int len = RARRAY_LEN(_cflows);
|
233
|
+
double y, D, times[len], cflows[len], price;
|
234
|
+
|
235
|
+
rtofa(times, _times, len);
|
236
|
+
rtofa(cflows, _cflows, len);
|
237
|
+
price = NUM2DBL(_price);
|
238
|
+
|
239
|
+
y = bond_ytm(times, cflows, price, len, true);
|
240
|
+
D = bond_dur(times, cflows, y, len, true);
|
241
|
+
|
242
|
+
return rb_float_new(D / (1 + y));
|
243
|
+
};
|
244
|
+
|
227
245
|
// Price of a continuously compounded bond
|
228
246
|
static VALUE
|
229
247
|
price_continuous(self, _times, _cflows, _r)
|
@@ -296,6 +314,8 @@ init_bond()
|
|
296
314
|
rb_define_alias(singleton, "dur", "duration");
|
297
315
|
rb_define_singleton_method(klass, "macaulay", macaulay_discrete, 3);
|
298
316
|
rb_define_alias(singleton, "macaulay_duration", "macaulay");
|
317
|
+
rb_define_singleton_method(klass, "modified", modified_discrete, 3);
|
318
|
+
rb_define_alias(singleton, "modified_duration", "modified");
|
299
319
|
rb_define_singleton_method(klass, "price", price_discrete, 3);
|
300
320
|
rb_define_alias(singleton, "value", "price");
|
301
321
|
rb_define_singleton_method(klass, "yield_to_maturity", yield_to_maturity_discrete, 3);
|
data/lib/rupee/quote/source.rb
CHANGED
@@ -4,14 +4,14 @@ module Rupee
|
|
4
4
|
class Source
|
5
5
|
# The name of the source
|
6
6
|
attr :name
|
7
|
-
|
7
|
+
# The full URL for where the security information is located, where
|
8
|
+
# <tt>%s</tt> is a query parameter
|
9
|
+
attr :url
|
8
10
|
# The parameters available
|
9
11
|
attr :params
|
10
12
|
|
11
|
-
def initialize(name,
|
12
|
-
@name = name
|
13
|
-
@aliases = aliases
|
14
|
-
@params = params
|
13
|
+
def initialize(name, url, params = {})
|
14
|
+
@name, @url, @params = name, url, params
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
@@ -27,7 +27,8 @@ module Rupee
|
|
27
27
|
@sources ||= {}
|
28
28
|
|
29
29
|
# Bloomberg
|
30
|
-
@sources[:bloomberg] = Source.new(:bloomberg,
|
30
|
+
@sources[:bloomberg] = Source.new(:bloomberg,
|
31
|
+
"http://www.bloomberg.com/apps/quote?ticker=%s",
|
31
32
|
:price => /(?:PRICE|VALUE): <span class="amount">([0-9.,NA-]{1,})/,
|
32
33
|
:change => /Change<\/td>\n<td class="value[^>]+>([0-9.,NA-]{1,})/,
|
33
34
|
:pct_change => /Change<\/td>\n<td class="value[^>]+>[0-9.,NA-]{1,} \(([0-9NA.,-]{1,})\%/,
|
@@ -41,8 +42,8 @@ module Rupee
|
|
41
42
|
:volume => /Volume<\/td>\n<td class="value[^>]+>([0-9.,NA-]{1,})/,
|
42
43
|
:mkt_cap => /Market Cap[^<]+<\/td>\n<td class="value">([0-9.,NA-]{1,})/,
|
43
44
|
:p_e => /Price\/Earnings[^<]+<\/td>\n<td class="value">([0-9.,NA-]{1,})/)
|
44
|
-
@sources[:yahoo] = Source.new(:yahoo)
|
45
|
-
@sources[:google] = Source.new(:google)
|
45
|
+
@sources[:yahoo] = Source.new(:yahoo, "yahoo.com")
|
46
|
+
@sources[:google] = Source.new(:google, "google.com")
|
46
47
|
@default_source = :bloomberg
|
47
48
|
end
|
48
49
|
end
|
data/lib/rupee/quote.rb
CHANGED
@@ -49,7 +49,7 @@ module Rupee
|
|
49
49
|
def initialize(ticker, opts = {})
|
50
50
|
opts = { :source => :bloomberg, :frequency => 15 }.merge opts
|
51
51
|
@ticker = ticker
|
52
|
-
@source =
|
52
|
+
@source = Quote.sources[opts[:source]]
|
53
53
|
@frequency = opts[:frequency]
|
54
54
|
@next_pull = Time.now
|
55
55
|
end
|
@@ -61,10 +61,9 @@ module Rupee
|
|
61
61
|
|
62
62
|
if now >= @next_pull
|
63
63
|
@next_pull = now + @frequency
|
64
|
-
url = BLOOMBERG_URL % ticker
|
65
64
|
@results = {}
|
66
|
-
url = URI.parse(url)
|
67
|
-
|
65
|
+
url = URI.parse(@source.url % ticker)
|
66
|
+
html = Net::HTTP.start(url.host, url.port) do |http|
|
68
67
|
http.get url.request_uri
|
69
68
|
end.body
|
70
69
|
|
@@ -84,9 +83,9 @@ module Rupee
|
|
84
83
|
end
|
85
84
|
end
|
86
85
|
|
87
|
-
# call-seq:
|
86
|
+
# call-seq: #price
|
88
87
|
#
|
89
|
-
#
|
88
|
+
# Test
|
90
89
|
[:price, :change, :pct_change, :date, :time, :bid, :ask, :open, :high,
|
91
90
|
:low, :volume, :mkt_cap, :p_e].each do |method_name|
|
92
91
|
define_method method_name do
|
@@ -101,21 +100,6 @@ module Rupee
|
|
101
100
|
|
102
101
|
private
|
103
102
|
|
104
|
-
# The URL for Bloomberg's quotes service
|
105
|
-
BLOOMBERG_URL = "http://www.bloomberg.com/apps/quote?ticker=%s"
|
106
|
-
|
107
|
-
# Returns an intepretation of an abbreviated source name
|
108
|
-
def shorten_source(source)
|
109
|
-
case source.downcase.to_sym
|
110
|
-
when :"", :bloomberg, :bberg, :bb, :b
|
111
|
-
:bloomberg
|
112
|
-
when :google, :goog, :g
|
113
|
-
:google
|
114
|
-
when :yahoo!, :yahoo, :yhoo, :y!, :y
|
115
|
-
:yahoo
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
103
|
# Parses an object that might be a number
|
120
104
|
#
|
121
105
|
# parse "15" #=> 15
|
data/lib/rupee/version.rb
CHANGED
data/rupee.gemspec
CHANGED
@@ -3,25 +3,27 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
require "rupee/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
|
-
s.name
|
7
|
-
s.version
|
8
|
-
s.authors
|
9
|
-
s.email
|
10
|
-
s.homepage
|
11
|
-
s.summary
|
12
|
-
s.description
|
6
|
+
s.name = "rupee"
|
7
|
+
s.version = Rupee::VERSION
|
8
|
+
s.authors = ["Bryan McKelvey"]
|
9
|
+
s.email = ["bryan.mckelvey@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/brymck/rupee"
|
11
|
+
s.summary = "Financial tools for Ruby"
|
12
|
+
s.description = <<-eos
|
13
|
+
rupee aims to provide user-friendly tools for use in
|
14
|
+
financial gems and applications.
|
15
|
+
eos
|
13
16
|
|
14
17
|
s.rubyforge_project = "rupee"
|
15
18
|
|
16
|
-
s.files
|
17
|
-
s.test_files
|
18
|
-
s.executables
|
19
|
-
|
20
|
-
|
19
|
+
s.files = `git ls-files`.split("\n")
|
20
|
+
s.test_files = `git ls-files -- spec/**/*_spec.rb`.split("\n")
|
21
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map do |f|
|
22
|
+
File.basename(f)
|
23
|
+
end
|
24
|
+
s.extensions = "ext/rupee/extconf.rb"
|
25
|
+
s.require_paths = ["lib", "ext"]
|
21
26
|
|
22
|
-
|
23
|
-
s.add_development_dependency "
|
24
|
-
s.add_development_dependency "rspec", "~> 2.0"
|
25
|
-
s.add_development_dependency "autotest", "~> 4.0"
|
26
|
-
# s.add_runtime_dependency "rest-client"
|
27
|
+
s.add_development_dependency "bundler", "~> 1.0"
|
28
|
+
s.add_development_dependency "rspec", "~> 2.0"
|
27
29
|
end
|
data/spec/c/bond_spec.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/../spec_helper"
|
2
2
|
|
3
3
|
# Discrete discounting
|
4
|
-
# bond duration modified = 2.5128
|
5
4
|
# new bond price = 100
|
6
5
|
#Continous discounting
|
7
6
|
# bond yield to maturity = 0.09
|
@@ -16,20 +15,27 @@ describe Rupee::Bond do
|
|
16
15
|
end
|
17
16
|
|
18
17
|
describe "with discrete discounting" do
|
18
|
+
before :each do
|
19
|
+
@price = Rupee::Bond.price(@times, @cflows, @r)
|
20
|
+
end
|
21
|
+
|
19
22
|
it "should produce an accurate price" do
|
20
|
-
|
23
|
+
@price.should be_within(@tolerance).of 102.531
|
21
24
|
end
|
22
25
|
|
23
26
|
it "should produce an accurate duration" do
|
24
27
|
Rupee::Bond.duration(@times, @cflows, @r).should be_within(@tolerance).of 2.73895
|
25
28
|
end
|
26
29
|
|
30
|
+
it "should produce an accurate modified duration" do
|
31
|
+
Rupee::Bond.modified(@times, @cflows, @price).should be_within(@tolerance).of 2.5128
|
32
|
+
end
|
33
|
+
|
27
34
|
it "should produce an accurate convexity" do
|
28
35
|
Rupee::Bond.convexity(@times, @cflows, @r).should be_within(@tolerance).of 8.93248
|
29
36
|
end
|
30
37
|
|
31
38
|
it "should produce an accurate yield to maturity" do
|
32
|
-
@price = Rupee::Bond.price(@times, @cflows, @r)
|
33
39
|
Rupee::Bond.yield_to_maturity(@times, @cflows, @price).should be_within(@tolerance).of @r
|
34
40
|
end
|
35
41
|
end
|
data/spec/c/future_spec.rb
CHANGED
@@ -2,12 +2,15 @@ require File.dirname(__FILE__) + "/../spec_helper"
|
|
2
2
|
|
3
3
|
describe Rupee::Future do
|
4
4
|
before :each do
|
5
|
+
@tolerance = 0.001
|
5
6
|
@underlying = 100
|
6
7
|
@rfr = 0.10
|
7
8
|
@ttm = 0.5
|
8
9
|
end
|
9
10
|
|
10
11
|
it "should produce an accurate price" do
|
11
|
-
Rupee::Future.price(@underlying, @rfr, @ttm).should
|
12
|
+
Rupee::Future.price(@underlying, @rfr, @ttm).should(
|
13
|
+
be_within(@tolerance).of 105.127
|
14
|
+
)
|
12
15
|
end
|
13
16
|
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.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-09-
|
12
|
+
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: &70967150 !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: *70967150
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rspec
|
27
|
-
requirement: &
|
27
|
+
requirement: &70966890 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,20 +32,9 @@ dependencies:
|
|
32
32
|
version: '2.0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
36
|
-
-
|
37
|
-
|
38
|
-
requirement: &84127610 !ruby/object:Gem::Requirement
|
39
|
-
none: false
|
40
|
-
requirements:
|
41
|
-
- - ~>
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: '4.0'
|
44
|
-
type: :development
|
45
|
-
prerelease: false
|
46
|
-
version_requirements: *84127610
|
47
|
-
description: rupee aims to provide user-friendly tools for use in financial gems and
|
48
|
-
applications.
|
35
|
+
version_requirements: *70966890
|
36
|
+
description: ! " rupee aims to provide user-friendly tools for
|
37
|
+
use in\n financial gems and applications.\n"
|
49
38
|
email:
|
50
39
|
- bryan.mckelvey@gmail.com
|
51
40
|
executables: []
|
@@ -53,7 +42,6 @@ extensions:
|
|
53
42
|
- ext/rupee/extconf.rb
|
54
43
|
extra_rdoc_files: []
|
55
44
|
files:
|
56
|
-
- .autotest
|
57
45
|
- .gitignore
|
58
46
|
- .rspec
|
59
47
|
- COPYING
|
data/.autotest
DELETED