class Trader::Currency

Attributes

code[R]

Public Class Methods

converter_for(_from, _to) click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 40
def self.converter_for(_from, _to)
  converter_for!(_from, _to) rescue nil
end
converter_for!(_from, _to) click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 44
def self.converter_for!(_from, _to)
  _from = _from.code if _from.is_a? Currency
  _to = _to.code if _to.is_a? Currency

  cv = converters[_from][_to] || comp_cache[_from][_to]

  if cv.nil?
    chains = []
    resolve_converter(_from, _to, [_from], chains)
    raise ArgumentError, "No converter registered for #{_from}/#{_to}" if chains.count == 0
    raise ArgumentError, "Ambiguous conversion path for #{_from}/#{_to}" if chains.count > 1
    comp_cache[_from][_to] = cv = build_compound_converter chains.first
  end

  cv
end
for_code(_code) click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 61
def self.for_code(_code)
  return _code if _code.is_a? Currency
  registry[_code.to_sym]
end
isolate_conversions() { || ... } click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 26
def self.isolate_conversions
  old_converters = @@converters
  old_cache = @@comp_cache

  begin
    @@converters = clone_converter_hash @@converters
    @@comp_cache = clone_converter_hash @@comp_cache
    yield
  ensure
    @@converters = old_converters
    @@comp_cache = old_cache
  end
end
new(_code) click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 68
def initialize(_code)
  @code = _code
end
register_conversion(_from, _to, _converter=nil, _options={}, &_block) click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 3
def self.register_conversion(_from, _to, _converter=nil, _options={}, &_block)
  if !_block.nil?
    _options = _converter || {}
    _converter = SyncConverter.new(_options.fetch(:interval, 60.0), &_block)
  elsif _converter.is_a? Numeric
    _converter = FixedConverter.new(_converter)
  end

  _converter = inverse(_converter) if _options[:inverse]

  converters[_from.to_sym][_to.to_sym] = _converter
  reset_comp_cache
end
register_resolution(*_chain) click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 17
def self.register_resolution(*_chain)
  converters[_chain.first][_chain.last] = build_compound_converter _chain
end
reset_converters() click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 21
def self.reset_converters
  converters.clear
  reset_comp_cache
end

Private Class Methods

build_compound_converter(_chain) click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 160
def self.build_compound_converter(_chain)
  CompoundConverter.new((_chain.count-1).times.map do |i|
    conv = converters[_chain[i]][_chain[i+1]]
    raise ArgumentError, "No converter registered for #{_chain[i]}/#{_chain[i+1]}" if conv.nil?
    conv
  end)
end
clone_converter_hash(_hash) click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 125
def self.clone_converter_hash(_hash)
  return nil if _hash.nil?
  h = Hash[_hash.map { |k,v| [k, v.clone] }]
  h.default_proc = proc { |h,k| h[k] = {} }
  h
end
comp_cache() click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 140
def self.comp_cache
  @@comp_cache ||= Hash.new { |h,k| h[k] = {} }
end
converters() click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 136
def self.converters
  @@converters ||= Hash.new { |h,k| h[k] = {} }
end
inverse(_converter) click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 168
def self.inverse(_converter)
  if _converter.is_a? InverseConverter
    _converter.other
  else
    InverseConverter.new _converter
  end
end
registry() click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 132
def self.registry
  @@registry ||= Hash.new { |h,k| h[k] = self.new(k) }
end
reset_comp_cache() click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 144
def self.reset_comp_cache
  @@comp_cache = nil
end
resolve_converter(_from, _to, _path, _result) click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 148
def self.resolve_converter(_from, _to, _path, _result)
  converters[_from].keys.each do |key|
    next if _path.include? key
    child_path = _path + [key]
    if key == _to
      _result << child_path
    else
      resolve_converter(key, _to, child_path, _result)
    end
  end
end

Public Instance Methods

compatible_with?(_currency) click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 78
def compatible_with?(_currency)
  _currency = klass.for_code _currency
  convertible_to? _currency and _currency.convertible_to? self
end
convert(_value, _to) click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 83
def convert(_value, _to)
  converter = klass.converter_for!(code, _to.to_sym)
  converter.apply _value
end
convertible_to?(_currency) click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 72
def convertible_to?(_currency)
  _currency = klass.for_code _currency
  return true if self == _currency
  !klass.converter_for(code, _currency.to_sym).nil?
end
pack(_value) click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 88
def pack(_value)
  if _value.is_a? Price
    raise StandardError, "Invalid value currency" if _value.currency != self
    return _value
  end

  Price.new self, _value
end
to_s() click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 115
def to_s
  code.to_s
end
to_sym() click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 119
def to_sym
  code
end
unpack(_value, _options={}) click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 97
def unpack(_value, _options={})
  _options = { default: _options } unless _options.is_a? Hash

  if _value.is_a? Price
    if _value.currency != self
      _value.currency.convert _value.amount, self
    else
      _value.amount
    end
  elsif _value.nil?
    Standard.amount _options[:default]
  elsif _options.fetch(:strict, true)
    raise ArgumentError, "Must provide a currency bound price"
  else
    Standard.amount _value
  end
end

Private Instance Methods

klass() click to toggle source
# File lib/trade-o-matic/structs/currency.rb, line 176
def klass
  self.class
end