71 lines
1.6 KiB
Ruby
71 lines
1.6 KiB
Ruby
# encoding: UTF-8
|
|
# frozen_string_literal: true
|
|
|
|
require_relative 'constants'
|
|
|
|
module Matching
|
|
class LimitOrder < BaseOrder
|
|
|
|
attr_reader :price
|
|
|
|
def initialize(attrs)
|
|
super
|
|
@price = attrs[:price].to_d
|
|
|
|
raise OrderError.new(self, 'Order is not valid') unless valid?(attrs)
|
|
end
|
|
|
|
def trade_with(counter_order, _counter_book)
|
|
if counter_order.is_a?(MarketOrder)
|
|
raise MarketOrderbookError.new(order, 'market order in orderbook detected')
|
|
end
|
|
|
|
return unless crossed?(counter_order.price)
|
|
|
|
trade_price = counter_order.price
|
|
trade_volume = [volume, counter_order.volume].min
|
|
trade_funds = trade_price * trade_volume
|
|
[trade_price, trade_volume, trade_funds]
|
|
end
|
|
|
|
def fill(_trade_price, trade_volume, _trade_funds)
|
|
raise NotEnoughVolume if trade_volume > @volume
|
|
@volume -= trade_volume
|
|
end
|
|
|
|
def filled?
|
|
volume <= ZERO
|
|
end
|
|
|
|
def crossed?(price)
|
|
if type == :ask
|
|
price >= @price # if people offer price higher or equal than ask limit
|
|
else
|
|
price <= @price # if people offer price lower or equal than bid limit
|
|
end
|
|
end
|
|
|
|
def label
|
|
"%d/$%s/%s" % [id, price.to_s('F'), volume.to_s('F')]
|
|
end
|
|
|
|
def valid?(_attrs)
|
|
type.in?(%i[ask bid]) && \
|
|
id.present? && \
|
|
timestamp.present? && \
|
|
market.present? && \
|
|
price > ZERO
|
|
end
|
|
|
|
def attributes
|
|
{ id: @id,
|
|
timestamp: @timestamp,
|
|
type: @type,
|
|
volume: @volume,
|
|
price: @price,
|
|
market: @market,
|
|
ord_type: 'limit' }
|
|
end
|
|
end
|
|
end
|