position.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175
  1. package lmaxapi
  2. import "tickserver/api/lmaxapi/response"
  3. type PositionList struct {
  4. mtf *Mtf
  5. orderList *OrderList
  6. perSymbol map[int64]*response.PositionEvent
  7. }
  8. func NewPositionList(mtf *Mtf, orderList *OrderList) *PositionList {
  9. p := &PositionList{}
  10. p.mtf = mtf
  11. p.orderList = orderList
  12. p.perSymbol = make(map[int64]*response.PositionEvent)
  13. return p
  14. }
  15. func (this *PositionList) SetPosition(event *response.PositionEvent) {
  16. if event.OpenQuantity == 0 {
  17. this.updatePosition(event)
  18. this.perSymbol[event.InstrumentId] = event
  19. this.deleteClosed()
  20. return
  21. }
  22. inst := this.mtf.getInstument(event.InstrumentId)
  23. if inst != nil {
  24. event.Currency = inst.Currency
  25. }
  26. this.perSymbol[event.InstrumentId] = event
  27. this.updatePosition(event)
  28. }
  29. func (this *PositionList) GetPosition(id int64) *response.PositionEvent {
  30. if event, ok := this.perSymbol[id]; ok {
  31. tmp := *event
  32. return &tmp
  33. }
  34. return nil
  35. }
  36. func (this *PositionList) deleteClosed() (ret []*response.PositionEvent) {
  37. //delete closed order
  38. for key, position := range this.perSymbol {
  39. if position.OpenQuantity == 0 {
  40. ret = append(ret, position)
  41. delete(this.perSymbol, key)
  42. }
  43. }
  44. return
  45. }
  46. func (this *PositionList) GetPositions(iscopy bool) []*response.PositionEvent {
  47. ret := make([]*response.PositionEvent, len(this.perSymbol))
  48. i := 0
  49. for _, event := range this.perSymbol {
  50. if iscopy {
  51. tmp := *event
  52. ret[i] = &tmp
  53. } else {
  54. ret[i] = event
  55. }
  56. i++
  57. }
  58. return ret
  59. }
  60. func (this *PositionList) UpdateTick(event *TickEvent) (ret []*response.PositionEvent) {
  61. for _, position := range this.perSymbol {
  62. if position.InstrumentId == event.ob2.InstrumentId {
  63. this.updatePosition(position)
  64. if event.fetchUpdated {
  65. copyed := position
  66. if event.isCopy {
  67. tmp := *position
  68. copyed = &tmp
  69. }
  70. ret = append(ret, copyed)
  71. }
  72. }
  73. }
  74. return
  75. }
  76. func (this *PositionList) UpdateRate(event *RateEvent) (ret []*response.PositionEvent) {
  77. for _, position := range this.perSymbol {
  78. if position.Currency == event.erate.From {
  79. this.updatePosition(position)
  80. if event.fetchUpdated {
  81. copyed := position
  82. if event.isCopy {
  83. tmp := *position
  84. copyed = &tmp
  85. }
  86. ret = append(ret, copyed)
  87. }
  88. }
  89. }
  90. return
  91. }
  92. //order 更新了以后,更新position的基本信息
  93. func (this *PositionList) updateByOrder(instrumentId int64) *response.PositionEvent {
  94. orders, ok := this.orderList.perSymbol[instrumentId]
  95. if !ok || len(orders) == 0 {
  96. delete(this.perSymbol, instrumentId)
  97. return nil
  98. }
  99. position, ok := this.perSymbol[instrumentId]
  100. if !ok {
  101. position = &response.PositionEvent{}
  102. position.AccountId = orders[0].AccountId
  103. position.InstrumentId = orders[0].InstrumentId
  104. position.Valuation = 0
  105. position.CumulativeCost = 0
  106. this.perSymbol[instrumentId] = position
  107. }
  108. //开始计算4个值
  109. position.OpenQuantity = 0
  110. position.OpenCost = 0
  111. position.LongUnfilledCost = 0
  112. position.ShortUnfilledCost = 0
  113. position.LongUnfilledQuantity = 0
  114. position.ShortUnfilledQuantity = 0
  115. for i := 0; i < len(orders); i++ {
  116. position.OpenQuantity += orders[i].OpenQuantity
  117. position.OpenCost += orders[i].OpenCost
  118. dt := orders[i].Quantity - orders[i].FilledQuantity - orders[i].CancelledQuantity
  119. if orders[i].Quantity > 0 {
  120. position.LongUnfilledQuantity += dt
  121. position.LongUnfilledCost = dt * orders[i].LimitPrice
  122. } else {
  123. position.ShortUnfilledQuantity += dt
  124. position.ShortUnfilledCost += dt * orders[i].LimitPrice
  125. }
  126. }
  127. this.updatePosition(position)
  128. return position
  129. }
  130. func (this *PositionList) updatePosition(position *response.PositionEvent) error {
  131. instrument, exchangeRate, priceEvent, err := this.mtf.getInstrumentInfo(position.InstrumentId)
  132. if err != nil {
  133. return err
  134. }
  135. position.ExchangeRate = exchangeRate
  136. position.CurPrice = getPrice(position.OpenQuantity, priceEvent)
  137. if position.OpenQuantity == 0 {
  138. position.Margin = 0
  139. position.Profit = 0
  140. return nil
  141. }
  142. position.OpenPrice = position.OpenCost / (position.OpenQuantity * instrument.ContractSize)
  143. //margin
  144. margin := position.CurPrice * instrument.ContractSize * position.OpenQuantity * instrument.MarginRate
  145. if margin < 0 {
  146. margin = -margin
  147. }
  148. buy, sell := this.orderList.workingOrderMargin(position.InstrumentId)
  149. if position.OpenQuantity > 0 {
  150. buy += margin
  151. } else {
  152. sell += margin
  153. }
  154. if buy > sell {
  155. position.Margin = buy
  156. } else {
  157. position.Margin = sell
  158. }
  159. //计算整体的保证金
  160. //profit
  161. profit := (position.CurPrice - position.OpenPrice) * instrument.ContractSize * position.OpenQuantity
  162. position.Profit = profit
  163. return nil
  164. }