class Gekko::Order
Represents a trade order. Trade orders can be either buy (bid) or sell (ask) orders. All orders are identified by an UUID, and must specify a size, and an optional expiration timestamp.
Constants
- TRL_STOP_PCT_MULTIPLIER
Multiplier applied to the trailing STOP percentage to be able to pass it around as integer
Attributes
Public Class Methods
Initializes a Gekko::Order
subclass from a Hash
instance
@param hsh [Hash] The order data @return [Gekko::Order] A trade order
# File lib/gekko/order.rb, line 186 def self.from_hash(hsh) h = symbolize_keys(hsh) order = (h[:price] ? LimitOrder : MarketOrder).from_hash(h) if h[:stop] order.stop_price = h[:stop][:price] order.stop_offset = h[:stop][:offset] order.stop_percent = h[:stop][:percent] end order end
# File lib/gekko/order.rb, line 20 def initialize(side, id, uid, size, opts = {}) @id = id @uid = uid @side = side && side.to_sym @size = size @remaining = @size @expiration = opts[:expiration] @created_at = Time.now.to_f @post_only = opts[:post_only] @stop_price = opts[:stop_price] @stop_percent = opts[:stop_percent] @stop_offset = opts[:stop_offset] raise 'Orders must have an UUID' unless @id && @id.is_a?(UUID) raise 'Orders must have a user ID' unless @uid && @uid.is_a?(UUID) raise 'Side must be either :bid or :ask' unless [:bid, :ask].include?(@side) raise 'Size must be a positive integer' if (@size && (!@size.is_a?(Fixnum) || @size <= 0)) raise 'Stop price must be a positive integer' if (@stop_price && (!@stop_price.is_a?(Fixnum) || @stop_price <= 0)) raise 'Trailing percentage must be a positive integer' if (@stop_percent && (!@stop_percent.is_a?(Fixnum) || @stop_percent <= 0 || @stop_percent >= TRL_STOP_PCT_MULTIPLIER)) raise 'Trailing offset must be a positive integer' if (@stop_offset && (!@stop_offset.is_a?(Fixnum) || @stop_offset <= 0)) raise 'Expiration must be omitted or be an integer' unless (@expiration.nil? || (@expiration.is_a?(Fixnum) && @expiration > 0)) raise 'The order creation timestamp can''t be nil' if !@created_at if (((@stop_price && 1 )|| 0) + ((@stop_percent && 1 ) || 0) + ((@stop_offset && 1) || 0)) > 1 raise 'Stop orders must specify exactly one of either stop price, trailing percentage, or trailing offset.' end end
Public Instance Methods
Returns true
if this order is a sell order
# File lib/gekko/order.rb, line 125 def ask? !bid? end
Returns true
if this order is a buy order
# File lib/gekko/order.rb, line 118 def bid? side == :bid end
Returns true
if this order can execute against limit_order
@param limit_order [LimitOrder] The limit order against which we want
to know if an execution is possible
# File lib/gekko/order.rb, line 54 def crosses?(limit_order) if limit_order raise 'Can not test againt a market order' unless limit_order.is_a?(LimitOrder) if bid? ^ limit_order.bid? is_a?(MarketOrder) || (bid? && (price >= limit_order.price)) || (ask? && (price <= limit_order.price)) end end end
Returns true
if this order is expired
# File lib/gekko/order.rb, line 140 def expired? expiration && (expiration <= Time.now.to_i) end
Returns true
if this order isn’t supposed to stick around in the order book
# File lib/gekko/order.rb, line 133 def fill_or_kill? is_a?(Gekko::MarketOrder) end
Creates a message in order to print it ont the tape
@param type [Symbol] The type of message we’re printing @param extra_attrs [Hash] The extra attributes we’re including
in the message
@return [Hash] The message we’ll print on the tape
# File lib/gekko/order.rb, line 95 def message(type, extra_attrs = {}) hsh = { type: type, order_id: id.to_s, side: side, size: size, remaining: remaining, price: price, expiration: expiration }.merge(extra_attrs) if is_a?(Gekko::MarketOrder) hsh.delete(:price) hsh[:quote_margin] = quote_margin hsh[:remaining_quote_margin] = remaining_quote_margin end hsh end
Returns true
if the given price should trigger this order’s execution.
@param p [Fixnum] The price to which we want to compare the STOP price @return [Boolean] Whether this order should trigger
# File lib/gekko/order.rb, line 79 def should_trigger?(p) p || raise("Provided price can't be nil") stop? || raise("Called Order#should_trigger? on a non-stop order") (bid? && (stop_price <= p)) || (ask? && (stop_price >= p)) end
Returns true
if the order is a STOP order, false
otherwise
@return [Boolean] Whether this order is a STOP
# File lib/gekko/order.rb, line 69 def stop? !!(stop_price || stop_percent || stop_offset) end
Returns a Hash
representation of this Order
instance
@return [Hash] The serializable representation
# File lib/gekko/order.rb, line 149 def to_hash hsh = { id: id.to_s, uid: uid.to_s, side: side, size: size, price: price, remaining: remaining, expiration: expiration, created_at: created_at } if is_a?(Gekko::MarketOrder) hsh.delete(:price) hsh[:quote_margin] = quote_margin hsh[:remaining_quote_margin] = remaining_quote_margin end if stop? hsh.merge!({ stop: { price: stop_price, offset: stop_offset, percent: stop_percent } }) end hsh end
Updates the stop price according to either the stop_percent
or or the stop_offset
attributes
@param p [Fixnum] The price used to update the stop_price
# File lib/gekko/order.rb, line 206 def update_trailing_stop(p) sign = bid? ? 1 : -1 if stop_percent new_price = p + (p * stop_percent * sign / TRL_STOP_PCT_MULTIPLIER).round self.stop_price = new_price if (bid? && (new_price < stop_price)) || (ask? && (new_price > stop_price)) elsif stop_offset new_price = p + stop_offset * sign self.stop_price = new_price if (bid? && (new_price < stop_price)) || (ask? && (new_price > stop_price)) end end