123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175 |
- package lmaxapi
- import "tickserver/api/lmaxapi/response"
- type PositionList struct {
- mtf *Mtf
- orderList *OrderList
- perSymbol map[int64]*response.PositionEvent
- }
- func NewPositionList(mtf *Mtf, orderList *OrderList) *PositionList {
- p := &PositionList{}
- p.mtf = mtf
- p.orderList = orderList
- p.perSymbol = make(map[int64]*response.PositionEvent)
- return p
- }
- func (this *PositionList) SetPosition(event *response.PositionEvent) {
- if event.OpenQuantity == 0 {
- this.updatePosition(event)
- this.perSymbol[event.InstrumentId] = event
- this.deleteClosed()
- return
- }
- inst := this.mtf.getInstument(event.InstrumentId)
- if inst != nil {
- event.Currency = inst.Currency
- }
- this.perSymbol[event.InstrumentId] = event
- this.updatePosition(event)
- }
- func (this *PositionList) GetPosition(id int64) *response.PositionEvent {
- if event, ok := this.perSymbol[id]; ok {
- tmp := *event
- return &tmp
- }
- return nil
- }
- func (this *PositionList) deleteClosed() (ret []*response.PositionEvent) {
- //delete closed order
- for key, position := range this.perSymbol {
- if position.OpenQuantity == 0 {
- ret = append(ret, position)
- delete(this.perSymbol, key)
- }
- }
- return
- }
- func (this *PositionList) GetPositions(iscopy bool) []*response.PositionEvent {
- ret := make([]*response.PositionEvent, len(this.perSymbol))
- i := 0
- for _, event := range this.perSymbol {
- if iscopy {
- tmp := *event
- ret[i] = &tmp
- } else {
- ret[i] = event
- }
- i++
- }
- return ret
- }
- func (this *PositionList) UpdateTick(event *TickEvent) (ret []*response.PositionEvent) {
- for _, position := range this.perSymbol {
- if position.InstrumentId == event.ob2.InstrumentId {
- this.updatePosition(position)
- if event.fetchUpdated {
- copyed := position
- if event.isCopy {
- tmp := *position
- copyed = &tmp
- }
- ret = append(ret, copyed)
- }
- }
- }
- return
- }
- func (this *PositionList) UpdateRate(event *RateEvent) (ret []*response.PositionEvent) {
- for _, position := range this.perSymbol {
- if position.Currency == event.erate.From {
- this.updatePosition(position)
- if event.fetchUpdated {
- copyed := position
- if event.isCopy {
- tmp := *position
- copyed = &tmp
- }
- ret = append(ret, copyed)
- }
- }
- }
- return
- }
- //order 更新了以后,更新position的基本信息
- func (this *PositionList) updateByOrder(instrumentId int64) *response.PositionEvent {
- orders, ok := this.orderList.perSymbol[instrumentId]
- if !ok || len(orders) == 0 {
- delete(this.perSymbol, instrumentId)
- return nil
- }
- position, ok := this.perSymbol[instrumentId]
- if !ok {
- position = &response.PositionEvent{}
- position.AccountId = orders[0].AccountId
- position.InstrumentId = orders[0].InstrumentId
- position.Valuation = 0
- position.CumulativeCost = 0
- this.perSymbol[instrumentId] = position
- }
- //开始计算4个值
- position.OpenQuantity = 0
- position.OpenCost = 0
- position.LongUnfilledCost = 0
- position.ShortUnfilledCost = 0
- position.LongUnfilledQuantity = 0
- position.ShortUnfilledQuantity = 0
- for i := 0; i < len(orders); i++ {
- position.OpenQuantity += orders[i].OpenQuantity
- position.OpenCost += orders[i].OpenCost
- dt := orders[i].Quantity - orders[i].FilledQuantity - orders[i].CancelledQuantity
- if orders[i].Quantity > 0 {
- position.LongUnfilledQuantity += dt
- position.LongUnfilledCost = dt * orders[i].LimitPrice
- } else {
- position.ShortUnfilledQuantity += dt
- position.ShortUnfilledCost += dt * orders[i].LimitPrice
- }
- }
- this.updatePosition(position)
- return position
- }
- func (this *PositionList) updatePosition(position *response.PositionEvent) error {
- instrument, exchangeRate, priceEvent, err := this.mtf.getInstrumentInfo(position.InstrumentId)
- if err != nil {
- return err
- }
- position.ExchangeRate = exchangeRate
- position.CurPrice = getPrice(position.OpenQuantity, priceEvent)
- if position.OpenQuantity == 0 {
- position.Margin = 0
- position.Profit = 0
- return nil
- }
- position.OpenPrice = position.OpenCost / (position.OpenQuantity * instrument.ContractSize)
- //margin
- margin := position.CurPrice * instrument.ContractSize * position.OpenQuantity * instrument.MarginRate
- if margin < 0 {
- margin = -margin
- }
- buy, sell := this.orderList.workingOrderMargin(position.InstrumentId)
- if position.OpenQuantity > 0 {
- buy += margin
- } else {
- sell += margin
- }
- if buy > sell {
- position.Margin = buy
- } else {
- position.Margin = sell
- }
- //计算整体的保证金
- //profit
- profit := (position.CurPrice - position.OpenPrice) * instrument.ContractSize * position.OpenQuantity
- position.Profit = profit
- return nil
- }
|