/ Executors / src / orders / limit.jl
limit.jl
  1  using .Instances
  2  import .Instances: committed, PositionOpen, PositionClose, freecash
  3  using .OrderTypes:
  4      LimitOrderType, PositionSide, ExchangeID, ShortSellOrder, FOKOrderType, IOCOrderType
  5  using Strategies: NoMarginStrategy
  6  using Base: negate
  7  using .Misc: Long, Short
  8  using .Lang: @ifdebug
  9  import Base: fill!
 10  
 11  @doc "Union type representing limit order increase operations. Includes Buy and Sell Short orders."
 12  const IncreaseLimitOrder{A,E} = Union{LimitOrder{Buy,A,E},ShortLimitOrder{Sell,A,E}}
 13  
 14  @doc "Union type representing limit order reduction operations. Includes Sell and Buy Short orders."
 15  const ReduceLimitOrder{A,E} = Union{LimitOrder{Sell,A,E},ShortLimitOrder{Buy,A,E}}
 16  
 17  @doc "Type representing a limit trade, includes long position limit orders."
 18  const LimitTrade{S,A,E} = Trade{<:LimitOrderType{S},A,E,Long}
 19  
 20  @doc "Type representing a short limit trade, includes short position limit orders."
 21  const ShortLimitTrade{S,A,E} = Trade{<:LimitOrderType{S},A,E,Short}
 22  
 23  @doc "Type representing a limit buy trade, specific to long position buy limit orders."
 24  const LimitBuyTrade{A,E} = LimitTrade{Buy,A,E}
 25  
 26  @doc "Type representing a limit sell trade, specific to long position sell limit orders."
 27  const LimitSellTrade{A,E} = LimitTrade{Sell,A,E}
 28  
 29  @doc "Type representing a short limit buy trade, specific to short position buy limit orders."
 30  const ShortLimitBuyTrade{A,E} = ShortLimitTrade{Buy,A,E}
 31  
 32  @doc "Type representing a short limit sell trade, specific to short position sell limit orders."
 33  const ShortLimitSellTrade{A,E} = ShortLimitTrade{Sell,A,E}
 34  
 35  @doc "Union type representing limit trade increase operations. Includes Buy and Sell Short trades."
 36  const IncreaseLimitTrade{A,E} = Union{LimitBuyTrade{A,E},ShortLimitSellTrade{A,E}}
 37  
 38  @doc "Union type representing limit trade reduction operations. Includes Sell and Buy Short trades."
 39  const ReduceLimitTrade{A,E} = Union{LimitSellTrade{A,E},ShortLimitBuyTrade{A,E}}
 40  
 41  @doc """ Places a limit order in the strategy
 42  
 43  $(TYPEDSIGNATURES)
 44  
 45  This function places a limit order with specified parameters in the strategy `s`. The `type` argument specifies the type of the order. The `price` defaults to the current price at the given `date` if not provided. The `take` and `stop` arguments are optional and default to `nothing`. If `skipcommit` is true, the function will not commit the order. Additional arguments can be passed via `kwargs`.
 46  
 47  """
 48  function limitorder(
 49      s::Strategy,
 50      ai,
 51      amount;
 52      date,
 53      type,
 54      price=priceat(s, type, ai, date),
 55      take=nothing,
 56      stop=nothing,
 57      skipcommit=false,
 58      kwargs...,
 59  )
 60      @price! ai price take stop
 61      @amount! ai amount
 62      comm = Ref(committment(type, ai, price, amount))
 63      @debug "create limitorder:" ai = raw(ai) price amount comm[] is_comm = iscommittable(
 64          s, type, comm, ai
 65      ) free = freecash(ai, posside(ai))
 66      if skipcommit || iscommittable(s, type, comm, ai)
 67          basicorder(ai, price, amount, comm, SanitizeOff(); date, type, kwargs...)
 68      end
 69  end
 70  
 71  _cashfrom(s, _, o::IncreaseOrder) = st.freecash(s) + committed(o)
 72  _cashfrom(_, ai, o::ReduceOrder) = st.freecash(ai, positionside(o)()) + committed(o)
 73  
 74  @doc """ Checks if the provided trade is the last fill for the given asset instance.
 75  
 76  $(TYPEDSIGNATURES)
 77  """
 78  function islastfill(ai::AssetInstance, t::Trade{<:LimitOrderType})
 79      o = t.order
 80      t.amount != o.amount && isfilled(ai, o)
 81  end
 82  @doc """ Checks if the provided trade is the first fill for the given asset instance.
 83  
 84  $(TYPEDSIGNATURES)
 85  """
 86  function isfirstfill(::AssetInstance, t::Trade{<:LimitOrderType})
 87      o = t.order
 88      attr(o, :unfilled)[] == negate(t.amount)
 89  end
 90  
 91  @doc """ Adds a limit order to the pending orders of the strategy.
 92  
 93  $(TYPEDSIGNATURES)
 94  
 95  This function takes a strategy, a limit order of type LimitOrderType{S}, and an asset instance as arguments. It adds the limit order to the pending orders of the strategy. If `skipcommit` is set to false (default), the order is committed and held. Returns true if the order was successfully added, otherwise false.
 96  """
 97  function queue!(
 98      s::Strategy, o::Order{<:LimitOrderType{S}}, ai; skipcommit=false
 99  ) where {S<:OrderSide}
100      @debug "queue limitorder:" is_comm = iscommittable(s, o, ai)
101      # This is already done in general by the function that creates the order
102      skipcommit || iscommittable(s, o, ai) || return false
103      push!(s, ai, o)
104      @deassert hasorders(s, ai, positionside(o))
105      skipcommit || commit!(s, o, ai)
106      hold!(s, ai, o)
107      return true
108  end