rupee 0.2.4 → 0.2.5
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/lib/rupee.rb +11 -5
- data/lib/rupee/currency.rb +54 -0
- data/lib/rupee/currency/eur.rb +10 -0
- data/lib/rupee/currency/gbp.rb +10 -0
- data/lib/rupee/currency/jpy.rb +10 -0
- data/lib/rupee/currency/usd.rb +9 -0
- data/lib/rupee/custom.rb +46 -0
- data/lib/rupee/day_count.rb +4 -0
- data/lib/rupee/quote.rb +12 -7
- data/lib/rupee/version.rb +1 -1
- data/lib/rupee/yield_curve.rb +12 -0
- data/spec/ruby/currency_spec.rb +25 -0
- data/spec/ruby/generic_spec.rb +19 -0
- data/spec/ruby/quote_spec.rb +48 -23
- metadata +56 -50
- data/lib/rupee/generators/install.rb +0 -0
data/lib/rupee.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
require "rupee/rupee" # keep this as the first require
|
2
2
|
require "rupee/version"
|
3
|
-
require "rupee/security"
|
4
|
-
require "rupee/option.rb"
|
5
3
|
|
6
4
|
# Rupee aims to provide user-friendly tools for use in financial applications.
|
7
5
|
# The gem is in its development stages, but it currently offers:
|
@@ -18,7 +16,15 @@ require "rupee/option.rb"
|
|
18
16
|
|
19
17
|
# This module contains all modules and classes associated with Rupee
|
20
18
|
module Rupee
|
21
|
-
|
22
|
-
|
23
|
-
autoload :
|
19
|
+
autoload :Security, "rupee/security"
|
20
|
+
|
21
|
+
autoload :Calendar, "rupee/calendar"
|
22
|
+
autoload :Custom, "rupee/custom"
|
23
|
+
autoload :Call, "rupee/option"
|
24
|
+
autoload :Currency, "rupee/currency"
|
25
|
+
autoload :DayCount, "rupee/day_count"
|
26
|
+
autoload :Option, "rupee/option"
|
27
|
+
autoload :Put, "rupee/option"
|
28
|
+
autoload :Quote, "rupee/quote"
|
29
|
+
autoload :YieldCurve, "rupee/yield_curve"
|
24
30
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Rupee
|
3
|
+
# A holder for currencies
|
4
|
+
class Currency
|
5
|
+
# Default currencies, autoloaded as required
|
6
|
+
autoload :GBP, "rupee/currency/gbp"
|
7
|
+
autoload :POUND, "rupee/currency/gbp"
|
8
|
+
autoload :EUR, "rupee/currency/eur"
|
9
|
+
autoload :EURO, "rupee/currency/eur"
|
10
|
+
autoload :JPY, "rupee/currency/jpy"
|
11
|
+
autoload :YEN, "rupee/currency/jpy"
|
12
|
+
autoload :USD, "rupee/currency/usd"
|
13
|
+
autoload :DOLLAR, "rupee/currency/usd"
|
14
|
+
|
15
|
+
# A simple description of the currency
|
16
|
+
attr :description
|
17
|
+
# The currency symbol ($, ¥, £, etc.)
|
18
|
+
attr :symbol
|
19
|
+
# The default number of decimal places
|
20
|
+
attr :decimal_places
|
21
|
+
# The delimiter for thousands places
|
22
|
+
attr :delimiter
|
23
|
+
# The separator for ones and decimals
|
24
|
+
attr :separator
|
25
|
+
|
26
|
+
# Create a new currency
|
27
|
+
def initialize(description, opts = {})
|
28
|
+
opts = {
|
29
|
+
:symbol => "$",
|
30
|
+
:decimal_places => 2,
|
31
|
+
:delimiter => ",",
|
32
|
+
:separator => "."
|
33
|
+
}.merge opts
|
34
|
+
|
35
|
+
@description = description
|
36
|
+
@symbol = opts[:symbol]
|
37
|
+
@decimal_places = opts[:decimal_places]
|
38
|
+
@delimiter = opts[:delimiter]
|
39
|
+
@separator = opts[:separator]
|
40
|
+
end
|
41
|
+
|
42
|
+
# Returns a number using the currency's specified format
|
43
|
+
def format(number)
|
44
|
+
parts = number.round(@decimal_places).to_s.split(".")
|
45
|
+
parts[0].gsub! /(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{@delimiter}"
|
46
|
+
|
47
|
+
if @decimal_places > 0
|
48
|
+
parts[1] = parts[1].ljust @decimal_places, "0"
|
49
|
+
end
|
50
|
+
|
51
|
+
"#{@symbol}#{parts.join @separator}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/rupee/custom.rb
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
module Rupee
|
2
|
+
# Under construction
|
3
|
+
#
|
4
|
+
# A custom security that allows the user to specify cash flows, discount
|
5
|
+
# curves, payout curves, calendars, currencies, daycounts, roll day
|
6
|
+
# conventions, etc.
|
7
|
+
class Custom < Security
|
8
|
+
# The Calendar object
|
9
|
+
attr :calendar
|
10
|
+
# The security's Currency
|
11
|
+
attr :currency
|
12
|
+
|
13
|
+
# Build a custom security
|
14
|
+
def initialize(opts = {})
|
15
|
+
opts = {
|
16
|
+
:calendar => :us,
|
17
|
+
:currency => :usd
|
18
|
+
}.merge opts
|
19
|
+
|
20
|
+
self.calendar = opts[:calendar]
|
21
|
+
self.currency = opts[:currency]
|
22
|
+
end
|
23
|
+
|
24
|
+
def calendar=(x) # :nodoc:
|
25
|
+
@calendar = to_instance(x, Calendar)
|
26
|
+
end
|
27
|
+
|
28
|
+
def currency=(x) # :nodoc:
|
29
|
+
@currency = to_instance(x, Currency)
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
# Converts the supplied value to an instance of the specified class (if it
|
35
|
+
# isn't already one)
|
36
|
+
def to_instance(x, constant)
|
37
|
+
x = x.upcase
|
38
|
+
|
39
|
+
if x.instance_of?(constant)
|
40
|
+
x
|
41
|
+
else
|
42
|
+
constant.const_get(x)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
data/lib/rupee/quote.rb
CHANGED
@@ -69,16 +69,21 @@ module Rupee
|
|
69
69
|
@next_pull = now + @frequency
|
70
70
|
@results = {}
|
71
71
|
url = URI.parse(@source.url % ticker)
|
72
|
-
|
72
|
+
res = Net::HTTP.start(url.host, url.port) do |http|
|
73
73
|
http.get url.request_uri
|
74
|
-
end
|
74
|
+
end
|
75
75
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
76
|
+
case res
|
77
|
+
when Net::HTTPSuccess
|
78
|
+
@source.params.each do |param, regex|
|
79
|
+
begin
|
80
|
+
@results[param] = parse(regex.match(res.body)[1])
|
81
|
+
rescue
|
82
|
+
@results[param] = nil
|
83
|
+
end
|
81
84
|
end
|
85
|
+
else
|
86
|
+
res.error!
|
82
87
|
end
|
83
88
|
end
|
84
89
|
|
data/lib/rupee/version.rb
CHANGED
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require File.dirname(__FILE__) + "/../spec_helper"
|
3
|
+
|
4
|
+
describe Currency do
|
5
|
+
it "should at least have the dollar, euro, pound and yen" do
|
6
|
+
Currency::USD.should_not be_nil
|
7
|
+
Currency::EUR.should_not be_nil
|
8
|
+
Currency::GBP.should_not be_nil
|
9
|
+
Currency::JPY.should_not be_nil
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should have more readable aliases for the dollar, euro, pound and yen" do
|
13
|
+
Currency::DOLLAR.should be Currency::USD
|
14
|
+
Currency::EURO.should be Currency::EUR
|
15
|
+
Currency::POUND.should be Currency::GBP
|
16
|
+
Currency::YEN.should be Currency::JPY
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should apply the correct format for the dollar, euro, pound and yen" do
|
20
|
+
Currency::USD.format(1_234_567.89).should == "$1,234,567.89"
|
21
|
+
Currency::EUR.format(1_234_567.89).should == "€1,234,567.89"
|
22
|
+
Currency::GBP.format(1_234_567.89).should == "£1,234,567.89"
|
23
|
+
Currency::JPY.format(1_234_567.89).should == "¥1,234,568"
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require File.dirname(__FILE__) + "/../spec_helper"
|
2
|
+
|
3
|
+
describe Rupee do
|
4
|
+
it "should produce no errors when loading all constants two levels deep" do
|
5
|
+
Rupee.constants.each do |c|
|
6
|
+
# Get classes and constants
|
7
|
+
const = Rupee.const_get(c)
|
8
|
+
const.should_not be_nil
|
9
|
+
|
10
|
+
# Get subconstants if original constant has a constants method (or, more
|
11
|
+
# generally, is a class)
|
12
|
+
if const.respond_to?(:constants)
|
13
|
+
const.constants.each do |sc|
|
14
|
+
const.const_get(sc).should_not be_nil
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/spec/ruby/quote_spec.rb
CHANGED
@@ -1,51 +1,76 @@
|
|
1
1
|
require File.dirname(__FILE__) + "/../spec_helper"
|
2
2
|
|
3
3
|
describe Quote do
|
4
|
+
# Attempts to run the block and submits a pending message if a socket error
|
5
|
+
# occurs, the most common cause of which is that the user isn't connected to
|
6
|
+
# the internet
|
7
|
+
def run_if_connected(&block)
|
8
|
+
begin
|
9
|
+
block.call
|
10
|
+
rescue SocketError
|
11
|
+
pending "Socket error: you're probably not connected to the internet"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
4
15
|
it "should automatically have a Bloomberg source" do
|
5
16
|
Quote.sources.should include :bloomberg
|
6
17
|
end
|
7
18
|
|
8
|
-
describe "
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
end
|
19
|
+
describe "without any parameters specified" do
|
20
|
+
before :each do
|
21
|
+
@wfc = Quote.new(:wfc)
|
22
|
+
end
|
13
23
|
|
14
|
-
|
24
|
+
it "should default to pulling the price" do
|
25
|
+
run_if_connected do
|
15
26
|
@wfc.get.should == @wfc.price
|
16
27
|
end
|
28
|
+
end
|
17
29
|
|
18
|
-
|
30
|
+
it "should return a price" do
|
31
|
+
run_if_connected do
|
19
32
|
@wfc.price.should be_a_kind_of Float
|
20
33
|
end
|
34
|
+
end
|
21
35
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
@wfc.next_pull.should == orig_pull - freq_change
|
36
|
+
[:change, :pct_chg].each do |param|
|
37
|
+
it "should have a #{param}" do
|
38
|
+
run_if_connected do
|
39
|
+
@wfc.price.should be_a_kind_of Float
|
40
|
+
end
|
28
41
|
end
|
29
42
|
end
|
30
43
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
44
|
+
it "should reflect changes to frequency in next pull time" do
|
45
|
+
freq_change = 5
|
46
|
+
orig_freq = @wfc.frequency
|
47
|
+
orig_pull = @wfc.next_pull
|
48
|
+
@wfc.frequency -= freq_change
|
49
|
+
@wfc.next_pull.should == orig_pull - freq_change
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "specifying Google Finance as the quote service" do
|
54
|
+
before :each do
|
55
|
+
@goog = Quote.new("GOOG", :source => :google)
|
56
|
+
end
|
35
57
|
|
36
|
-
|
58
|
+
it "should have around the same price as Bloomberg" do
|
59
|
+
run_if_connected do
|
37
60
|
bb_price = Quote.new("GOOG").price
|
38
61
|
bb_price.should be_a_kind_of Float
|
39
62
|
@goog.price.should be_within(0.05).of bb_price
|
40
63
|
end
|
41
64
|
end
|
65
|
+
end
|
42
66
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
67
|
+
describe "specifying Yahoo! Finance as the quote service" do
|
68
|
+
before :each do
|
69
|
+
@yahoo = Quote.new("YHOO", :source => :yahoo)
|
70
|
+
end
|
47
71
|
|
48
|
-
|
72
|
+
it "should have around the same price as Bloomberg" do
|
73
|
+
run_if_connected do
|
49
74
|
bb_price = Quote.new("YHOO").price
|
50
75
|
bb_price.should be_a_kind_of Float
|
51
76
|
@yahoo.price.should be_within(0.05).of bb_price
|
metadata
CHANGED
@@ -1,60 +1,58 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: rupee
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.5
|
4
5
|
prerelease:
|
5
|
-
version: 0.2.4
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Bryan McKelvey
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2011-10-01 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
16
15
|
name: bundler
|
17
|
-
|
18
|
-
requirement: &id001 !ruby/object:Gem::Requirement
|
16
|
+
requirement: &79191280 !ruby/object:Gem::Requirement
|
19
17
|
none: false
|
20
|
-
requirements:
|
18
|
+
requirements:
|
21
19
|
- - ~>
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version:
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '1.0'
|
24
22
|
type: :development
|
25
|
-
version_requirements: *id001
|
26
|
-
- !ruby/object:Gem::Dependency
|
27
|
-
name: rspec
|
28
23
|
prerelease: false
|
29
|
-
|
24
|
+
version_requirements: *79191280
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rspec
|
27
|
+
requirement: &79191010 !ruby/object:Gem::Requirement
|
30
28
|
none: false
|
31
|
-
requirements:
|
29
|
+
requirements:
|
32
30
|
- - ~>
|
33
|
-
- !ruby/object:Gem::Version
|
34
|
-
version:
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '2.0'
|
35
33
|
type: :development
|
36
|
-
version_requirements: *id002
|
37
|
-
- !ruby/object:Gem::Dependency
|
38
|
-
name: sdoc
|
39
34
|
prerelease: false
|
40
|
-
|
35
|
+
version_requirements: *79191010
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: sdoc
|
38
|
+
requirement: &79190780 !ruby/object:Gem::Requirement
|
41
39
|
none: false
|
42
|
-
requirements:
|
40
|
+
requirements:
|
43
41
|
- - ~>
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version:
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0.3'
|
46
44
|
type: :development
|
47
|
-
|
48
|
-
|
49
|
-
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *79190780
|
47
|
+
description: ! " rupee aims to provide user-friendly tools for
|
48
|
+
use in\n financial gems and applications.\n"
|
49
|
+
email:
|
50
50
|
- bryan.mckelvey@gmail.com
|
51
51
|
executables: []
|
52
|
-
|
53
|
-
extensions:
|
52
|
+
extensions:
|
54
53
|
- ext/rupee/extconf.rb
|
55
54
|
extra_rdoc_files: []
|
56
|
-
|
57
|
-
files:
|
55
|
+
files:
|
58
56
|
- .autotest
|
59
57
|
- .gitignore
|
60
58
|
- .rspec
|
@@ -74,54 +72,62 @@ files:
|
|
74
72
|
- lib/rupee/calendar.rb
|
75
73
|
- lib/rupee/calendar/japan.rb
|
76
74
|
- lib/rupee/calendar/us.rb
|
77
|
-
- lib/rupee/
|
75
|
+
- lib/rupee/currency.rb
|
76
|
+
- lib/rupee/currency/eur.rb
|
77
|
+
- lib/rupee/currency/gbp.rb
|
78
|
+
- lib/rupee/currency/jpy.rb
|
79
|
+
- lib/rupee/currency/usd.rb
|
80
|
+
- lib/rupee/custom.rb
|
81
|
+
- lib/rupee/day_count.rb
|
78
82
|
- lib/rupee/option.rb
|
79
83
|
- lib/rupee/quote.rb
|
80
84
|
- lib/rupee/quote/source.rb
|
81
85
|
- lib/rupee/security.rb
|
82
86
|
- lib/rupee/version.rb
|
87
|
+
- lib/rupee/yield_curve.rb
|
83
88
|
- rupee.gemspec
|
84
89
|
- spec/native/bond_spec.rb
|
85
90
|
- spec/native/future_spec.rb
|
86
91
|
- spec/native/option_spec.rb
|
87
92
|
- spec/native/statistics_spec.rb
|
88
93
|
- spec/ruby/calendar_spec.rb
|
94
|
+
- spec/ruby/currency_spec.rb
|
95
|
+
- spec/ruby/generic_spec.rb
|
89
96
|
- spec/ruby/quote_spec.rb
|
90
97
|
- spec/spec_helper.rb
|
91
98
|
- tasks/benchmark.rake
|
92
99
|
- test_rubies
|
93
100
|
homepage: https://github.com/brymck/rupee
|
94
101
|
licenses: []
|
95
|
-
|
96
102
|
post_install_message:
|
97
103
|
rdoc_options: []
|
98
|
-
|
99
|
-
require_paths:
|
104
|
+
require_paths:
|
100
105
|
- lib
|
101
106
|
- ext
|
102
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
108
|
none: false
|
104
|
-
requirements:
|
105
|
-
- -
|
106
|
-
- !ruby/object:Gem::Version
|
107
|
-
version:
|
108
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
|
+
requirements:
|
110
|
+
- - ! '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
114
|
none: false
|
110
|
-
requirements:
|
111
|
-
- -
|
112
|
-
- !ruby/object:Gem::Version
|
113
|
-
version:
|
115
|
+
requirements:
|
116
|
+
- - ! '>='
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '0'
|
114
119
|
requirements: []
|
115
|
-
|
116
120
|
rubyforge_project: rupee
|
117
121
|
rubygems_version: 1.8.10
|
118
122
|
signing_key:
|
119
123
|
specification_version: 3
|
120
124
|
summary: Financial tools for Ruby
|
121
|
-
test_files:
|
125
|
+
test_files:
|
122
126
|
- spec/native/bond_spec.rb
|
123
127
|
- spec/native/future_spec.rb
|
124
128
|
- spec/native/option_spec.rb
|
125
129
|
- spec/native/statistics_spec.rb
|
126
130
|
- spec/ruby/calendar_spec.rb
|
131
|
+
- spec/ruby/currency_spec.rb
|
132
|
+
- spec/ruby/generic_spec.rb
|
127
133
|
- spec/ruby/quote_spec.rb
|
File without changes
|