Class: Currency::Exchange::Rate::Deriver

Inherits:
Source::Base show all
Defined in:
lib/currency/exchange/rate/deriver.rb

Overview

The Currency::Exchange::Rate::Deriver class calculates derived rates from base Rates from a rate Source by pivoting against a pivot currency or by generating reciprocals.

Instance Attribute Summary collapse

Attributes inherited from Source::Base

#time_quantitizer, #verbose

Instance Method Summary collapse

Methods inherited from Source::Base

#__subclass_responsibility, #clear_rate, #convert, #get_rates, #new_rate, #normalize_time, #rate, #to_s

Constructor Details

#initialize(opt = { }) ⇒ Deriver

Returns a new instance of Deriver.



22
23
24
25
26
27
28
# File 'lib/currency/exchange/rate/deriver.rb', line 22

def initialize(opt = { })
  @source = nil
  @pivot_currency = nil
  @derived_rates = { }
  @all_rates = { }
  super
end

Instance Attribute Details

#sourceObject

The source for base rates.



14
15
16
# File 'lib/currency/exchange/rate/deriver.rb', line 14

def source
  @source
end

Instance Method Details

#all_rates(time = nil) ⇒ Object

Computes all rates. time is assumed to be normalized.



60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/currency/exchange/rate/deriver.rb', line 60

def all_rates(time = nil)
  if x = @all_rates["#{time}"]
    return x 
  end

  x = @all_rates["#{time}"] = [ ]
  
  currencies = self.currencies

  currencies.each do | c1 |
    currencies.each do | c2 |
      next if c1 == c2 
      c1 = ::Currency::Currency.get(c1)
      c2 = ::Currency::Currency.get(c2)
      rate = rate(c1, c2, time)
      x << rate
    end
  end

  x
end

#available?(time = nil) ⇒ Boolean

Returns true if the underlying rate provider is available.

Returns:

  • (Boolean)


149
150
151
# File 'lib/currency/exchange/rate/deriver.rb', line 149

def available?(time = nil)
  source.available?(time)
end

#clear_ratesObject

Flush all cached Rates.



43
44
45
46
47
48
# File 'lib/currency/exchange/rate/deriver.rb', line 43

def clear_rates
  @derived_rates.clear
  @all_rates.clear
  @source.clear_rates
  super
end

#currenciesObject

Return all currencies.



37
38
39
# File 'lib/currency/exchange/rate/deriver.rb', line 37

def currencies
  @source.currencies
end

#get_rate(c1, c2, time) ⇒ Object

Determines and creates the Rate between Currency c1 and c2.

May attempt to use a pivot currency to bridge between rates.



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/currency/exchange/rate/deriver.rb', line 88

def get_rate(c1, c2, time)
  rate = get_rate_reciprocal(c1, c2, time)
  
  # Attempt to use pivot_currency to bridge
  # between Rates.
  unless rate
    pc = ::Currency::Currency.get(pivot_currency)
    
    if pc &&
        (rate_1 = get_rate_reciprocal(c1, pc, time)) && 
        (rate_2 = get_rate_reciprocal(pc, c2, time))
      c1_to_c2_rate = rate_1.rate * rate_2.rate
      rate = new_rate(c1, c2, 
                      c1_to_c2_rate, 
                      rate_1.date || rate_2.date || time, 
                      "pivot(#{pc.code},#{rate_1.derived || "#{rate_1.c1.code}#{rate_1.c2.code}"},#{rate_2.derived || "#{rate_2.c1}#{rate_2.c2}"})")
    end
  end
  
  rate
end

#get_rate_base(c1, c2, time) ⇒ Object

Returns a base Rate from the Source.



133
134
135
136
137
138
139
140
# File 'lib/currency/exchange/rate/deriver.rb', line 133

def get_rate_base(c1, c2, time)
  if c1 == c2
    # Identity rates are timeless.
    new_rate(c1, c2, 1.0, nil, "identity")
  else
    source.rate(c1, c2, time)
  end
end

#get_rate_base_cached(c1, c2, time) ⇒ Object

Returns a cached base Rate.



126
127
128
129
# File 'lib/currency/exchange/rate/deriver.rb', line 126

def get_rate_base_cached(c1, c2, time)
  rate = (@rate["#{c1}:#{c2}:#{time}"] ||= get_rate_base(c1, c2, time))
  rate
end

#get_rate_reciprocal(c1, c2, time) ⇒ Object

Get a matching base rate or its reciprocal.



112
113
114
115
116
117
118
119
120
121
# File 'lib/currency/exchange/rate/deriver.rb', line 112

def get_rate_reciprocal(c1, c2, time)
  rate = get_rate_base_cached(c1, c2, time)
  unless rate
    if rate = get_rate_base_cached(c2, c1, time)
      rate = (@rate["#{c1}:#{c2}:#{time}"] ||= rate.reciprocal)
    end
  end
  
  rate
end

#load_rates(time = nil) ⇒ Object



143
144
145
# File 'lib/currency/exchange/rate/deriver.rb', line 143

def load_rates(time = nil)
  all_rates(time)
end

#nameObject



17
18
19
# File 'lib/currency/exchange/rate/deriver.rb', line 17

def name
  source.name
end

#pivot_currencyObject



31
32
33
# File 'lib/currency/exchange/rate/deriver.rb', line 31

def pivot_currency
  @pivot_currency || @source.pivot_currency || :USD
end

#rates(time = nil) ⇒ Object

Returns all combinations of rates except identity rates.



52
53
54
55
# File 'lib/currency/exchange/rate/deriver.rb', line 52

def rates(time = nil)
  time = time && normalize_time(time)
  all_rates(time)
end