Skip to content

Commit

Permalink
Added basic currencies
Browse files Browse the repository at this point in the history
  • Loading branch information
brymck committed Oct 1, 2011
1 parent 1c63645 commit 9cce433
Show file tree
Hide file tree
Showing 11 changed files with 203 additions and 35 deletions.
15 changes: 10 additions & 5 deletions lib/rupee.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
require "rupee/rupee" # keep this as the first require
require "rupee/version"
require "rupee/security"
require "rupee/option.rb"

# Rupee aims to provide user-friendly tools for use in financial applications.
# The gem is in its development stages, but it currently offers:
Expand All @@ -18,7 +16,14 @@

# This module contains all modules and classes associated with Rupee
module Rupee
# autoload :Option, "rupee/option.rb"
autoload :Calendar, "rupee/calendar"
autoload :Quote, "rupee/quote"
autoload :Security, "rupee/security"

autoload :Calendar, "rupee/calendar"
autoload :Call, "rupee/option"
autoload :Currency, "rupee/currency"
autoload :DayCount, "rupee/day_count"
autoload :Option, "rupee/option"
autoload :Put, "rupee/option"
autoload :Quote, "rupee/quote"
autoload :YieldCurve, "rupee/yield_curve"
end
53 changes: 53 additions & 0 deletions lib/rupee/currency.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# encoding: utf-8
module Rupee
# A holder for currencies
class Currency
autoload :GBP, "rupee/currency/gbp"
autoload :Pound, "rupee/currency/gbp"
autoload :EUR, "rupee/currency/eur"
autoload :Euro, "rupee/currency/eur"
autoload :JPY, "rupee/currency/jpy"
autoload :Yen, "rupee/currency/jpy"
autoload :USD, "rupee/currency/usd"
autoload :Dollar, "rupee/currency/usd"

# A simple description of the currency
attr :description
# The currency symbol ($, ¥, £, etc.)
attr :symbol
# The default number of decimal places
attr :decimal_places
# The delimiter for thousands places
attr :delimiter
# The separator for ones and decimals
attr :separator

# Create a new currency
def initialize(description, opts = {})
opts = {
:symbol => "$",
:decimal_places => 2,
:delimiter => ",",
:separator => "."
}.merge opts

@description = description
@symbol = opts[:symbol]
@decimal_places = opts[:decimal_places]
@delimiter = opts[:delimiter]
@separator = opts[:separator]
end

# Returns a number using the currency's specified format
def format(number)
parts = number.round(@decimal_places).to_s.split(".")
parts[0].gsub! /(\d)(?=(\d\d\d)+(?!\d))/, "\\1#{@delimiter}"

if @decimal_places > 0
parts[1] = parts[1].ljust @decimal_places, "0"
end

"#{@symbol}#{parts.join @separator}"
end
end
end
10 changes: 10 additions & 0 deletions lib/rupee/currency/eur.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# encoding: utf-8
module Rupee
class Currency
# The euro
EUR = Currency.new "Euro", :symbol => "€"

# Alias for the euro
Euro = EUR
end
end
10 changes: 10 additions & 0 deletions lib/rupee/currency/gbp.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# encoding: utf-8
module Rupee
class Currency
# The British pound sterling
GBP = Currency.new "British pound sterling", :symbol => "£"

# Alias for the British pound
Pound = GBP
end
end
10 changes: 10 additions & 0 deletions lib/rupee/currency/jpy.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# encoding: utf-8
module Rupee
class Currency
# The Japanese yen
JPY = Currency.new "Japanese yen", :symbol => "¥", :decimal_places => 0

# Alias for the Japanese yen
Yen = JPY
end
end
9 changes: 9 additions & 0 deletions lib/rupee/currency/usd.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module Rupee
class Currency
# The US dollar
USD = Currency.new "US dollar"

# Alias for the US dollar
Dollar = USD
end
end
4 changes: 4 additions & 0 deletions lib/rupee/day_count.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
module Rupee
class DayCount
end
end
19 changes: 12 additions & 7 deletions lib/rupee/quote.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,16 +69,21 @@ def get(*params)
@next_pull = now + @frequency
@results = {}
url = URI.parse(@source.url % ticker)
html = Net::HTTP.start(url.host, url.port) do |http|
res = Net::HTTP.start(url.host, url.port) do |http|
http.get url.request_uri
end.body
end

@source.params.each do |param, regex|
begin
@results[param] = parse(regex.match(html)[1])
rescue
@results[param] = nil
case res
when Net::HTTPSuccess
@source.params.each do |param, regex|
begin
@results[param] = parse(regex.match(res.body)[1])
rescue
@results[param] = nil
end
end
else
res.error!
end
end

Expand Down
12 changes: 12 additions & 0 deletions lib/rupee/yield_curve.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module Rupee
class YieldCurve
def initialize(description = "", opts = {})
opts = {
:currency => :usd
:interpolation => :cubic_spline
}.merge opts

@description = description
end
end
end
25 changes: 25 additions & 0 deletions spec/ruby/currency_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# encoding: utf-8
require File.dirname(__FILE__) + "/../spec_helper"

describe Currency do
it "should at least have the dollar, euro, pound and yen" do
Currency::USD.should_not be_nil
Currency::EUR.should_not be_nil
Currency::GBP.should_not be_nil
Currency::JPY.should_not be_nil
end

it "should have more readable aliases for the dollar, euro, pound and yen" do
Currency::Dollar.should be Currency::USD
Currency::Euro.should be Currency::EUR
Currency::Pound.should be Currency::GBP
Currency::Yen.should be Currency::JPY
end

it "should apply the correct format for the dollar, euro, pound and yen" do
Currency::USD.format(1_234_567.89).should == "$1,234,567.89"
Currency::EUR.format(1_234_567.89).should == "€1,234,567.89"
Currency::GBP.format(1_234_567.89).should == "£1,234,567.89"
Currency::JPY.format(1_234_567.89).should == "¥1,234,568"
end
end
71 changes: 48 additions & 23 deletions spec/ruby/quote_spec.rb
Original file line number Diff line number Diff line change
@@ -1,51 +1,76 @@
require File.dirname(__FILE__) + "/../spec_helper"

describe Quote do
# Attempts to run the block and submits a pending message if a socket error
# occurs, the most common cause of which is that the user isn't connected to
# the internet
def run_if_connected(&block)
begin
block.call
rescue SocketError
pending "Socket error: you're probably not connected to the internet"
end
end

it "should automatically have a Bloomberg source" do
Quote.sources.should include :bloomberg
end

describe "when pulling quotes" do
describe "without any parameters specified" do
before :each do
@wfc = Quote.new(:wfc)
end
describe "without any parameters specified" do
before :each do
@wfc = Quote.new(:wfc)
end

it "should default to pulling the price" do
it "should default to pulling the price" do
run_if_connected do
@wfc.get.should == @wfc.price
end
end

it "should return a price" do
it "should return a price" do
run_if_connected do
@wfc.price.should be_a_kind_of Float
end
end

it "should reflect changes to frequency in next pull time" do
freq_change = 5
orig_freq = @wfc.frequency
orig_pull = @wfc.next_pull
@wfc.frequency -= freq_change
@wfc.next_pull.should == orig_pull - freq_change
[:price, :change, :pct_chg].each do |param|
it "should return a #{param}" do
run_if_connected do
@wfc.price.should be_a_kind_of Float
end
end
end

describe "specifying Google Finance as the quote service" do
before :each do
@goog = Quote.new("GOOG", :source => :google)
end
it "should reflect changes to frequency in next pull time" do
freq_change = 5
orig_freq = @wfc.frequency
orig_pull = @wfc.next_pull
@wfc.frequency -= freq_change
@wfc.next_pull.should == orig_pull - freq_change
end
end

describe "specifying Google Finance as the quote service" do
before :each do
@goog = Quote.new("GOOG", :source => :google)
end

it "should have around the same price as Bloomberg" do
it "should have around the same price as Bloomberg" do
run_if_connected do
bb_price = Quote.new("GOOG").price
bb_price.should be_a_kind_of Float
@goog.price.should be_within(0.05).of bb_price
end
end
end

describe "specifying Yahoo! Finance as the quote service" do
before :each do
@yahoo = Quote.new("YHOO", :source => :yahoo)
end
describe "specifying Yahoo! Finance as the quote service" do
before :each do
@yahoo = Quote.new("YHOO", :source => :yahoo)
end

it "should have around the same price as Bloomberg" do
it "should have around the same price as Bloomberg" do
run_if_connected do
bb_price = Quote.new("YHOO").price
bb_price.should be_a_kind_of Float
@yahoo.price.should be_within(0.05).of bb_price
Expand Down

0 comments on commit 9cce433

Please sign in to comment.