oanda_exchange 0.7.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/oanda_exchange/config.rb +47 -0
- data/lib/oanda_exchange/oanda.rb +115 -0
- data/lib/oanda_exchange/oanda_bank.rb +9 -0
- data/lib/oanda_exchange/stubs.rb +15 -0
- data/lib/oanda_exchange/version.rb +3 -0
- data/lib/oanda_exchange.rb +4 -0
- metadata +105 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2b1d160d29dac99403a86bc2394f350213463605
|
4
|
+
data.tar.gz: 19361f24d1c532b5e7ad41423da6e21e7d2cd342
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6f2818ace9293814792533b89598f1b1f2cb021cf707ad406e1f23290757b727132f456bbdf6ad3e43f30564083c21330c56f391162e6388c98973330ccaf39b
|
7
|
+
data.tar.gz: 994f549e9dcc730a400d72799ef50a44ed0aa82283f3f6d59aa737bfe84680cfde3c7c47d958305796003c2bd811461d8aa71d6a7691d1f09b1951d14827675a
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "logger"
|
2
|
+
require "active_support/core_ext/hash"
|
3
|
+
|
4
|
+
module OandaExchange
|
5
|
+
class Config
|
6
|
+
|
7
|
+
def self.get
|
8
|
+
@@config ||= YAML::load_file(File.join(root, "config", "oanda_api.yml")).symbolize_keys or raise Exception.new("Error on loading configuration file for OANDA API")
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.root
|
12
|
+
rails_root || "."
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.logger
|
16
|
+
@@logger ||= rails_logger || Logger.new(STDOUT)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.env
|
20
|
+
rails_env || ENV["ENV"] || "development"
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.rails_env
|
24
|
+
if defined?(Rails)
|
25
|
+
Rails.env
|
26
|
+
elsif defined?(RAILS_ENV)
|
27
|
+
RAILS_ENV
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.rails_root
|
32
|
+
if defined?(Rails)
|
33
|
+
Rails.root
|
34
|
+
elsif defined?(RAILS_ENV)
|
35
|
+
RAILS_ROOT
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.rails_logger
|
40
|
+
if defined?(Rails)
|
41
|
+
Rails.logger
|
42
|
+
elsif defined?(RAILS_DEFAULT_LOGGER)
|
43
|
+
RAILS_DEFAULT_LOGGER
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require "rest-client"
|
2
|
+
require "active_support/core_ext/object/blank"
|
3
|
+
require "active_support/core_ext/enumerable"
|
4
|
+
require "active_support/core_ext/big_decimal"
|
5
|
+
require "active_support/core_ext/hash/conversions"
|
6
|
+
|
7
|
+
class Oanda
|
8
|
+
|
9
|
+
attr_accessor :base_currency, :quote_currency, :date, :days, :amount, :response, :resp_hash, :interbank, :price
|
10
|
+
|
11
|
+
PRECISION = 8
|
12
|
+
|
13
|
+
def self.exchange(base_currency, options = {})
|
14
|
+
new.exchange(base_currency, options)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.currencies
|
18
|
+
new.currencies
|
19
|
+
end
|
20
|
+
|
21
|
+
def exchange(base_currency, options = {})
|
22
|
+
raise Exception.new("no base currency specified") if base_currency.blank?
|
23
|
+
raise Exception.new("no quote currency specified") if options[:to].blank?
|
24
|
+
self.price = options[:price] == :midpoint ? [:ask, :bid] : [options[:price] || :bid]
|
25
|
+
self.base_currency = base_currency.to_s.upcase
|
26
|
+
self.quote_currency = options[:to].to_s.upcase
|
27
|
+
self.date = options[:date] || Date.today
|
28
|
+
self.days = options[:days] || 1
|
29
|
+
self.amount = options[:amount] || 1
|
30
|
+
self.interbank = options[:interbank] || 0
|
31
|
+
self.response = exchange_request(build_request)
|
32
|
+
self.resp_hash = Hash.from_xml(response)["RESPONSE"]
|
33
|
+
average_rate = calculate_average_rate
|
34
|
+
self.interbank = average_rate * interbank.to_f / 100
|
35
|
+
base_currency == quote_currency ? average_rate : average_rate - interbank
|
36
|
+
end
|
37
|
+
|
38
|
+
def currencies
|
39
|
+
self.response = currencies_request
|
40
|
+
self.resp_hash = Hash.from_xml response
|
41
|
+
extract_currencies
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
def api_request(request_string, &block)
|
46
|
+
OandaExchange::Config.logger.debug "OANDA API: request body\n#{request_string}"
|
47
|
+
resp = yield request_string
|
48
|
+
OandaExchange::Config.logger.debug "OANDA API: response #{resp.code}\n#{resp.body}"
|
49
|
+
raise Exception.new("Unexpected response code from OANDA API. See log entries with debug level to get more information.") unless resp.code == 200
|
50
|
+
resp.body
|
51
|
+
end
|
52
|
+
|
53
|
+
def exchange_request(request_string)
|
54
|
+
api_request request_string do
|
55
|
+
OandaExchange::Config.logger.debug "OANDA API: request \n#{config[:exchange_service_url]}"
|
56
|
+
OandaExchange::Config.logger.info "OANDA API: requesting #{base_currency} conversion into #{quote_currency}"
|
57
|
+
RestClient.get "#{config[:exchange_service_url]}", :params => {:fxmlrequest => request_string}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def currencies_request
|
62
|
+
api_request "" do
|
63
|
+
OandaExchange::Config.logger.debug "OANDA API: request \n#{config[:currencies_url]}"
|
64
|
+
RestClient.get "#{config[:currencies_url]}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
69
|
+
protected
|
70
|
+
|
71
|
+
def extract_currencies
|
72
|
+
resp_hash['CURRENCYCODES']['CURRENCY'].inject({}) do |hash, node|
|
73
|
+
hash.merge node['CODE'] => node['COUNTRY']
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def calculate_average_rate
|
78
|
+
average extract_exchange_rates
|
79
|
+
end
|
80
|
+
|
81
|
+
def extract_exchange_rates
|
82
|
+
extract_rates.reject{|values| values.include?("na")}.map do |values|
|
83
|
+
average values.map{|v| BigDecimal.new(v, PRECISION)}
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def average(values)
|
88
|
+
(values.sum / values.size).round(PRECISION) rescue BigDecimal.new('0', PRECISION)
|
89
|
+
end
|
90
|
+
|
91
|
+
def extract_rates
|
92
|
+
rates = resp_hash["CONVERSION"].is_a?(Array) ? resp_hash["CONVERSION"] : [resp_hash["CONVERSION"]]
|
93
|
+
rates.map{|hash| price_value(hash)}
|
94
|
+
end
|
95
|
+
|
96
|
+
def price_value(hash)
|
97
|
+
price.map{|p| hash[p.to_s.upcase]}
|
98
|
+
end
|
99
|
+
|
100
|
+
def build_request
|
101
|
+
{
|
102
|
+
:date => date.strftime('%m/%d/%Y'),
|
103
|
+
:client_id => config[:client_id],
|
104
|
+
:exch => base_currency,
|
105
|
+
:expr => quote_currency,
|
106
|
+
:nprices => days,
|
107
|
+
:amount => amount
|
108
|
+
}.to_xml(:dasherize => false, :skip_types => true, :root => :convert)
|
109
|
+
end
|
110
|
+
|
111
|
+
def config
|
112
|
+
OandaExchange::Config.get
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module OandaExchange::Stubs
|
2
|
+
require 'rspec/mocks/standalone' if defined? RSpec
|
3
|
+
|
4
|
+
DEFAULT_CURRENCIES = {"USD" => "US Dollar", "EUR" => "Euro"}
|
5
|
+
DEFAULT_RATES = {"USD" => 1, "other" => 1.5}
|
6
|
+
|
7
|
+
def self.stub!(options = {})
|
8
|
+
raise "RSpec stub library required" unless Object.respond_to? :stub!
|
9
|
+
rates = options[:rates] || DEFAULT_RATES
|
10
|
+
Oanda.stub!(:exchange) do |cur, opts|
|
11
|
+
BigDecimal.new((opts[:amount] || 0).to_s, 5) * (rates[cur] || rates["other"] || 1)
|
12
|
+
end
|
13
|
+
Oanda.stub!(:currencies).and_return(options[:currencies] || DEFAULT_CURRENCIES)
|
14
|
+
end
|
15
|
+
end
|
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: oanda_exchange
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.7.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dieter Pisarewski
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-12-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: builder
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - '>='
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: money
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rest-client
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ~>
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '1.6'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '1.6'
|
69
|
+
description: OANDA Exchange API
|
70
|
+
email:
|
71
|
+
- dieter.pisarewski@arvatosystems.com
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- lib/oanda_exchange/config.rb
|
77
|
+
- lib/oanda_exchange/oanda.rb
|
78
|
+
- lib/oanda_exchange/oanda_bank.rb
|
79
|
+
- lib/oanda_exchange/stubs.rb
|
80
|
+
- lib/oanda_exchange/version.rb
|
81
|
+
- lib/oanda_exchange.rb
|
82
|
+
homepage: http://www.arvatosystems-us.com/
|
83
|
+
licenses: []
|
84
|
+
metadata: {}
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options: []
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
94
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
95
|
+
requirements:
|
96
|
+
- - '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
requirements: []
|
100
|
+
rubyforge_project:
|
101
|
+
rubygems_version: 2.0.14
|
102
|
+
signing_key:
|
103
|
+
specification_version: 4
|
104
|
+
summary: API for OANDA Exchange Services
|
105
|
+
test_files: []
|