state.jl
1 using .PaperMode.Instances: amount_with_fees 2 using Base: negate 3 using .Executors: attr, committment, _check_unfillment, IncreaseLimitOrder, strategycash! 4 import Base: fill! 5 6 # NOTE: unfilled is always negative 7 function fill!(::NoMarginStrategy{Live}, ai::NoMarginInstance, o::BuyOrder, t::BuyTrade) 8 @deassert o isa IncreaseOrder && _check_unfillment(o) unfilled(o), typeof(o) 9 @deassert committed(o) == o.attrs.committed[] && committed(o) >= 0.0 10 # from neg to 0 (buy amount is pos) 11 attr(o, :unfilled)[] += t.amount + t.fees_base 12 @deassert ltxzero(ai, attr(o, :unfilled)[], Val(:amount)) || 13 gtxzero(ai, t.fees_base, Val(:amount)) ( 14 o, attr(o, :unfilled)[], t.amount, t.fees_base 15 ) 16 # from pos to 0 (buy size is neg) 17 attr(o, :committed)[] -= committment(ai, t) 18 @deassert gtxzero(ai, committed(o), Val(:price)) || 19 o isa MarketOrder || 20 gtxzero(ai, t.fees_base, Val(:amount)) ( 21 o, committed(o), attr(o, :unfilled)[], committment(ai, t), t.fees_base, t.fees 22 ) 23 end 24 function fill!(::LiveStrategy, ai::AssetInstance, o::SellOrder, t::SellTrade) 25 @deassert o isa SellOrder && _check_unfillment(o) 26 @deassert committed(o) == o.attrs.committed[] && gtxzero(ai, committed(o), Val(:amount)) 27 # from pos to 0 (sell amount is neg) 28 amt = amount_with_fees(t) 29 @ifdebug if o isa AnyMarketOrder 30 @info "AMOUNT: " amt attr(o, :unfilled) attr(o, :committed) o.amount 31 end 32 attr(o, :unfilled)[] += amt 33 @deassert gtxzero(ai, attr(o, :unfilled)[], Val(:amount)) 34 # from pos to 0 (sell amount is neg) 35 attr(o, :committed)[] += amt 36 @deassert gtxzero(ai, committed(o), Val(:cost)) ( 37 committed(o), attr(o, :unfilled)[], t.fees, t.fees_base 38 ) 39 end 40 function fill!( 41 ::MarginStrategy{Live}, ai::AssetInstance, o::ShortBuyOrder, t::ShortBuyTrade 42 ) 43 @deassert o isa ShortBuyOrder && _check_unfillment(o) o 44 @deassert committed(o) == o.attrs.committed[] && ltxzero(ai, committed(o), Val(:price)) 45 @deassert attr(o, :unfilled)[] < 0.0 46 amt = amount_with_fees(t) 47 attr(o, :unfilled)[] += amt # from neg to 0 (buy amount is pos) 48 @deassert ltxzero(ai, attr(o, :unfilled)[], Val(:amount)) 49 # NOTE: committment is always positive except for short buy orders 50 # where that's committed is shorted (negative) asset cash 51 @deassert t.amount > 0.0 && committed(o) < 0.0 (committed(o), trades(o)) 52 attr(o, :committed)[] += amt # from neg to 0 (buy amount is pos) 53 @deassert ltxzero(ai, committed(o), Val(:amount)) 54 end 55 56 @doc """ Fills an increase order for a margin strategy. 57 58 This function fills an increase order for a margin strategy based on a given trade. 59 It updates the unfilled and committed attributes of the order according to the trade. 60 61 Note: 62 When entering positions, the cash committed from the trade must be downsized by leverage (at the time of the trade). 63 """ 64 function fill!( 65 ::MarginStrategy{Live}, ai::MarginInstance, o::IncreaseOrder, t::IncreaseTrade 66 ) 67 @deassert o isa IncreaseOrder && _check_unfillment(o) o 68 @deassert committed(o) == o.attrs.committed[] && committed(o) > 0.0 t 69 attr(o, :unfilled)[] += t.amount 70 @deassert ltxzero(ai, attr(o, :unfilled)[], Val(:amount)) || o isa ShortSellOrder 71 @deassert t.value > 0.0 72 attr(o, :committed)[] -= committment(ai, t) 73 # Market order spending can exceed the estimated committment 74 # ShortSell limit orders can spend more than committed because of slippage 75 @deassert gtxzero(ai, committed(o), Val(:price)) || 76 o isa AnyMarketOrder || 77 o isa IncreaseLimitOrder 78 end 79 80 function Instances.cash!(s::LiveStrategy, ai, t::Trade) 81 @debug "trades: cash before" _module = LogWatchTrade cash(s).value cash(ai, posside(t)).value timestamp(ai, posside(t)) t.date 82 if timestamp(ai, posside(t)) <= t.date 83 @debug "trades: cash updating" _module = LogWatchTrade 84 strategycash!(s, ai, t) 85 cash!(ai, t) 86 @debug "trades: cash after" _module = LogWatchTrade cash(s).value cash(ai, posside(t)).value timestamp(ai, posside(t)) 87 end 88 end