82 lines
1.5 KiB
Ruby
82 lines
1.5 KiB
Ruby
require "rbtree"
|
|
|
|
module Rex
|
|
class OrderBook
|
|
def initialize(matcher: Matcher.new)
|
|
@matcher = matcher
|
|
@sell_side = RBTree.new
|
|
@buy_side = RBTree.new
|
|
@order_ids = {} # order_id => order
|
|
@current_trade_id = 0
|
|
@current_order_id = 0
|
|
end
|
|
|
|
def add_order(order)
|
|
side = side_for_order(order)
|
|
order.id = next_order_id
|
|
|
|
side[order.price] ||= Limit.new(order.price)
|
|
side[order.price].add_order(order)
|
|
order_ids[order.id] = order
|
|
end
|
|
|
|
def add_and_match_order(order)
|
|
add_order(order)
|
|
@matcher.match(self)
|
|
end
|
|
|
|
def remove_order(order_id)
|
|
order = order_ids[order_id]
|
|
return nil if order.nil?
|
|
|
|
side = side_for_order(order)
|
|
|
|
limit = side[order.price]
|
|
limit.remove_order(order)
|
|
if limit.empty?
|
|
side.delete(limit.price)
|
|
end
|
|
|
|
order_ids.delete(order.id)
|
|
end
|
|
|
|
alias_method :cancel_order, :remove_order
|
|
|
|
def highest_buy_order
|
|
buy_side.last&.[](1)&.peek_first_order
|
|
end
|
|
|
|
def lowest_sell_order
|
|
sell_side.first&.[](1)&.peek_first_order
|
|
end
|
|
|
|
def best_buy_price
|
|
buy_side.last&.[](0)
|
|
end
|
|
|
|
def best_sell_price
|
|
sell_side.first&.[](0)
|
|
end
|
|
|
|
def next_trade_id
|
|
@current_trade_id += 1
|
|
end
|
|
|
|
private
|
|
|
|
attr_reader :order_ids, :buy_side, :sell_side
|
|
|
|
def next_order_id
|
|
@current_order_id += 1
|
|
end
|
|
|
|
def side_for_order(order)
|
|
if order.is_buy
|
|
buy_side
|
|
else
|
|
sell_side
|
|
end
|
|
end
|
|
end
|
|
end
|