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 }