/ Executors / src / positions / utils.jl
utils.jl
  1  using .Instances: ispos
  2  using .OrderTypes: ByPos
  3  using .Lang: @caller
  4  
  5  @doc """ Returns a generator for orders matching a given position side and order side
  6  
  7  $(TYPEDSIGNATURES)
  8  
  9  This function iterates over the orders of a strategy, returning only those that match the provided position side and order side.
 10  
 11  """
 12  orders(s::Strategy, ai, pos::PositionSide, os::Type{<:OrderSide})
 13  function orders(s::Strategy, ai, pos::PositionSide, os::Type{<:OrderSide})
 14      (tup for tup in orders(s, ai, os) if ispos(pos, tup.second))
 15  end
 16  function orders(s::Strategy, ai, pos::PositionSide)
 17      (tup for bs in (Buy, Sell) for tup in orders(s, ai, pos, bs))
 18  end
 19  @doc """ Returns a generator for orders matching a given position side
 20  
 21  $(TYPEDSIGNATURES)
 22  
 23  This function iterates over the orders of a strategy for both Buy and Sell sides, returning those that match the provided position side.
 24  
 25  """
 26  orders(s::Strategy, ai, pos::PositionSide)
 27  @doc """ Returns a generator for short orders matching a given order side
 28  
 29  $(TYPEDSIGNATURES)
 30  
 31  This function utilizes the orders function to generate orders for the Short position side that match the provided order side.
 32  
 33  """
 34  shortorders(s::Strategy, ai, os::Type{<:OrderSide}) = orders(s, ai, Short(), os)
 35  @doc """ Returns a generator for long orders matching a given order side
 36  
 37  $(TYPEDSIGNATURES)
 38  
 39  This function utilizes the orders function to generate orders for the Long position side that match the provided order side.
 40  
 41  """
 42  longorders(s::Strategy, ai, os::Type{<:OrderSide}) = orders(s, ai, Long(), os)
 43  function shortorders(s::Strategy, ai)
 44      (orders(s, ai, Short(), Sell)..., orders(s, ai, Short(), Buy)...)
 45  end
 46  function longorders(s::Strategy, ai)
 47      (orders(s, ai, Long(), Buy)..., orders(s, ai, Long(), Sell)...)
 48  end
 49  
 50  function _hasorders(s::MarginStrategy, ai, ps::PositionSide, os::Type{<:OrderSide})
 51      for o in values(orders(s, ai, os))
 52          if positionside(o)() == ps
 53              return true
 54          end
 55      end
 56      return false
 57  end
 58  @doc """ Checks if there are any orders for a given position side
 59  
 60  $(TYPEDSIGNATURES)
 61  
 62  This function checks both Buy and Sell sides for any orders that match the provided position side in the Margin Strategy.
 63  
 64  """
 65  function hasorders(s::MarginStrategy, ai, ps::PositionSide)
 66      _hasorders(s, ai, ps, Buy) || _hasorders(s, ai, ps, Sell)
 67  end
 68  function hasorders(s::MarginStrategy, ai, ::Long, t::Type{<:OrderSide})
 69      hasorders(s, ai, t)
 70  end
 71  function hasorders(s::MarginStrategy, ai, ::Long, ::Type{Sell})
 72      _hasorders(s, ai, Long(), Sell)
 73  end
 74  function hasorders(s::MarginStrategy, ai, ::Short, ::Type{Buy})
 75      _hasorders(s, ai, Short(), Buy)
 76  end
 77  
 78  # NOTE: ByPos has higher priority than BySide for dispatching
 79  @assert !hasmethod(hasorders, Tuple{MarginStrategy, AssetInstance, BySide})
 80  function hasorders(s::MarginStrategy, ai, ::ByPos{Long})
 81      hasorders(s, ai, Long(), Buy) || hasorders(s, ai, Long(), Sell)
 82  end
 83  function hasorders(s::MarginStrategy, ai, ::ByPos{Short})
 84      _hasorders(s, ai, Short(), Buy) || _hasorders(s, ai, Short(), Sell)
 85  end
 86  
 87  function hasorders(s::MarginStrategy, ::ByPos{P}) where {P<:PositionSide}
 88      for ai in s.holdings
 89          _hasorders(s, ai, P(), Buy) && return true
 90          _hasorders(s, ai, P(), Sell) && return true
 91      end
 92      return false
 93  end
 94  
 95  function hasorders(s::MarginStrategy, ::ByPos{P}, ::Val{:universe}) where {P<:PositionSide}
 96      for ai in universe(s)
 97          _hasorders(s, ai, P(), Buy) && return true
 98          _hasorders(s, ai, P(), Sell) && return true
 99      end
100      return false
101  end
102  @doc """ Updates the position of the isolated strategy to the given position side at the specified date
103  
104  $(TYPEDSIGNATURES)
105  
106  This function updates the position of the strategy for the asset in question at the given date to the provided position side.
107  
108  """
109  function position!(s::IsolatedStrategy, ai, date::DateTime, p::PositionSide)
110      position!(s, ai, date, position(ai, p))
111  end
112  position!(::IsolatedStrategy, ai, ::DateTime, ::Nothing) = nothing
113  
114  position!(s::Strategy, args...) = @warn "`position!` not implemented for $(typeof(s))" @caller
115  
116  @doc "Non margin strategies don't have positions."
117  position!(s::NoMarginStrategy, args...; kwargs...) = nothing
118  positions!(s::NoMarginStrategy, args...; kwargs...) = nothing
119  
120  _commitside(::Long) = Sell
121  _commitside(::Short) = Buy
122  @doc """ Calculates the committed amount for a given position
123  
124  $(TYPEDSIGNATURES)
125  
126  This function sums the amounts of all the orders that match the given position in the Margin Strategy.
127  
128  """
129  function committed(s::MarginStrategy, ai::MarginInstance, ::ByPos{P}) where {P}
130      ans = zero(DFT)
131      for o in values(s, ai, P(), _commitside(P()))
132          ans += o.amount
133      end
134      ans
135  end