class Ubea::OrderBook
Attributes
asks[R]
bids[R]
market[RW]
updated_at[RW]
Public Class Methods
new(hash)
click to toggle source
# File lib/ubea/order_book.rb, line 6 def initialize(hash) @asks = hash.delete(:asks).sort_by(&:price).freeze # buy @bids = hash.delete(:bids).sort_by(&:price).freeze # sell raise ArgumentError unless hash.empty? end
Public Instance Methods
best_offer_price_for_fiat_amount(type, fiat_amount, fiat_currency)
click to toggle source
# File lib/ubea/order_book.rb, line 55 def best_offer_price_for_fiat_amount(type, fiat_amount, fiat_currency) total_fiat_amount = 0 good_offers = [] offers = public_send(type).dup # asks or bids offers.reverse! if type == :bids offers.each do |offer| break if total_fiat_amount >= fiat_amount offer = offer.dup # NOTE: dup because we're gonna mess with its volume below offer.price = offer.price.exchange_to(fiat_currency) good_offers << offer total_fiat_amount += offer.price * offer.volume end if total_fiat_amount > fiat_amount substract_fiat = total_fiat_amount - fiat_amount substract_volume = substract_fiat / good_offers.last.price good_offers.last.volume -= substract_volume end total_weight_price = good_offers.map { |offer| offer.price * offer.volume }.inject(:+) || 0 total_volume = good_offers.map(&:volume).inject(:+) weighted_price = total_weight_price / total_volume Offer.new( price: good_offers.last.price, volume: total_volume, weighted_price: weighted_price, ) end
highest_bid()
click to toggle source
# File lib/ubea/order_book.rb, line 17 def highest_bid bids.last end
lowest_ask()
click to toggle source
# File lib/ubea/order_book.rb, line 21 def lowest_ask asks.first end
max_bid_price_for_volume(min_price, max_volume)
click to toggle source
# File lib/ubea/order_book.rb, line 44 def max_bid_price_for_volume(min_price, max_volume) filter = if min_price ->(price) { price >= min_price } else ->(_) { true } end interesting_bids = interesting_offers(bids, filter).reverse # reverse to start from most expensive best_offer_price_for_volume(interesting_bids, max_volume) end
min_ask_price_for_volume(max_price, max_volume)
click to toggle source
# File lib/ubea/order_book.rb, line 33 def min_ask_price_for_volume(max_price, max_volume) filter = if max_price ->(price) { price <= max_price } else ->(_) { true } end interesting_asks = interesting_offers(asks, filter) best_offer_price_for_volume(interesting_asks, max_volume) end
to_param()
click to toggle source
# File lib/ubea/order_book.rb, line 13 def to_param market.to_param end
weighted_asks_up_to(max_price)
click to toggle source
# File lib/ubea/order_book.rb, line 25 def weighted_asks_up_to(max_price) weighted_offers(asks, ->(price) { price <= max_price }) end
weighted_bids_down_to(min_price)
click to toggle source
# File lib/ubea/order_book.rb, line 29 def weighted_bids_down_to(min_price) weighted_offers(bids, ->(price) { price >= min_price }) end
Private Instance Methods
best_offer_price_for_volume(offers, max_volume)
click to toggle source
# File lib/ubea/order_book.rb, line 107 def best_offer_price_for_volume(offers, max_volume) total_volume = 0 good_offers = [] offers.each do |offer| if total_volume <= max_volume good_offers << offer.dup # NOTE: dup because we're gonna mess with its volume below total_volume += offer.volume end end if total_volume > max_volume substract_volume = total_volume - max_volume good_offers.last.volume -= substract_volume total_volume -= substract_volume end total_weight_price = good_offers.map { |offer| offer.price * offer.volume }.inject(:+) || 0 weighted_price = total_weight_price / total_volume Offer.new( price: good_offers.last.price, volume: total_volume, weighted_price: weighted_price, ) end
currency()
click to toggle source
# File lib/ubea/order_book.rb, line 134 def currency lowest_ask.price.currency end
interesting_offers(offers, condition)
click to toggle source
# File lib/ubea/order_book.rb, line 90 def interesting_offers(offers, condition) offers.select { |offer| condition.call(offer.price) } end
weighted_offers(offers, condition)
click to toggle source
# File lib/ubea/order_book.rb, line 94 def weighted_offers(offers, condition) interesting_offers = interesting_offers(offers, condition) total_volume = interesting_offers.map(&:volume).inject(:+) || 0 total_weight_price = interesting_offers.map { |offer| offer.price * offer.volume }.inject(:+) || 0 weighted_price = total_weight_price / total_volume Offer.new( price: Money.new(weighted_price, currency), volume: total_volume ) end