package lmaxapi import "tickserver/api/lmaxapi/response" import "log" import "math" type OrderList struct { data []*response.OrderEvent perSymbol map[int64][]*response.OrderEvent mtf *Mtf } func NewOrderList(mtf *Mtf) *OrderList { list := &OrderList{} list.mtf = mtf list.perSymbol = make(map[int64][]*response.OrderEvent) return list } //mtf 中发生了执行,需要更新订单以及 其他的订单 func (list *OrderList) UpdateOrder(event *response.OrderEvent) []*response.OrderEvent { order := list.get(event) var matchedQuantity float64 if order == nil { matchedQuantity = event.FilledQuantity } else { matchedQuantity = event.FilledQuantity - order.FilledQuantity } //更新openquantify var updatedOrder []*response.OrderEvent if item, ok := list.perSymbol[event.InstrumentId]; ok && matchedQuantity != 0 { for i := 0; i < len(item); i++ { if item[i].OpenQuantity == 0 || sameSign(item[i].OpenQuantity, event.FilledQuantity) { continue } tmp := *item[i] updatedOrder = append(updatedOrder, &tmp) if math.Abs(item[i].OpenQuantity) > math.Abs(matchedQuantity) { rate := item[i].MatchedCost / item[i].FilledQuantity item[i].OpenQuantity += matchedQuantity item[i].OpenCost = rate * item[i].OpenQuantity matchedQuantity = 0 } else { matchedQuantity += item[i].OpenQuantity item[i].OpenQuantity = 0 item[i].OpenCost = 0 } if matchedQuantity == 0 { break } } log.Println("event info:", event.MatchedCost, event.FilledQuantity, matchedQuantity) rate := event.MatchedCost / event.FilledQuantity event.OpenQuantity += matchedQuantity event.OpenCost = rate * event.OpenQuantity } tmp := *event updatedOrder = append(updatedOrder, &tmp) //opencost 更新结束 list.SetOrder(event) return updatedOrder } func (list *OrderList) get(event *response.OrderEvent) *response.OrderEvent { if item, ok := list.perSymbol[event.InstrumentId]; ok { for i := 0; i < len(item); i++ { if item[i].OrderId == event.OrderId { return item[i] } } } return nil } func (list *OrderList) SetOrder(event *response.OrderEvent) string { if event.IsStopProft() { return "stoploss" } if item, ok := list.perSymbol[event.InstrumentId]; ok { for i := 0; i < len(item); i++ { if item[i].OrderId == event.OrderId { //对订单的保证金之类的信息进行更新 list.updateOrder(event) *item[i] = *event if event.IsClosed() { log.Println(event.OrderId, "closed") list.perSymbol[event.InstrumentId] = list.deleteOrder(list.perSymbol[event.InstrumentId], event) list.data = list.deleteOrder(list.data, event) return "closed" } return "update" } } } //新增数据 inst := list.mtf.getInstument(event.InstrumentId) if inst != nil { event.Currency = inst.Currency } list.updateOrder(event) if event.IsClosed() { return "closed" } list.perSymbol[event.InstrumentId] = append(list.perSymbol[event.InstrumentId], event) list.data = append(list.data, event) return "add" } func (list *OrderList) deleteOrder(data []*response.OrderEvent, event *response.OrderEvent) []*response.OrderEvent { for i := 0; i < len(data); i++ { if data[i].OrderId == event.OrderId { data = append(data[:i], data[i+1:]...) return data } } return data } // 一些辅助函数 func (list *OrderList) GetOrders(iscopy bool) []*response.OrderEvent { if !iscopy { return list.data } ret := make([]*response.OrderEvent, len(list.data)) for i := 0; i < len(list.data); i++ { tmp := *list.data[i] ret[i] = &tmp } return ret } //接下来就是updateOne的问题了,我们要根据各种各样的情况来更新订单。 func (list *OrderList) updateWorkingOrder(order *response.OrderEvent, instrument *response.Instrument, exchangeRate *response.ExchangeRateEvent, priceEvent *response.OrderBookEvent) error { //价格 ask := priceEvent.AskPrices[0].Price bid := priceEvent.BidPrices[0].Price if order.Quantity > 0 { order.CurPrice = ask } else { order.CurPrice = bid } dt := order.Quantity - order.FilledQuantity - order.CancelledQuantity //margin: 实际上有两个部分,一个是已经成交部分的margin/一个是挂单的margin //因为margin 对整体position有效,所以这里我们不做处理,只计算挂单的margin,对后面的计算有用 margin := order.LimitPrice * instrument.ContractSize * dt * instrument.MarginRate if margin < 0 { margin = -margin } order.Margin = margin if order.OpenQuantity == 0 { order.Profit = 0 return nil } //盈利情况,已经开仓部分的盈利,实际上这个没有用,只是为了计算而计算。 openprice := order.OpenCost / (order.OpenQuantity * instrument.ContractSize) profit := (order.CurPrice - openprice) * instrument.ContractSize * order.OpenQuantity order.Profit = profit return nil } func (list *OrderList) updateMarketOrder(order *response.OrderEvent, instrument *response.Instrument, exchangeRate *response.ExchangeRateEvent, priceEvent *response.OrderBookEvent) error { //margin order.CurPrice = getPrice(order.Quantity, priceEvent) cost := order.CurPrice * order.Quantity * instrument.ContractSize if cost < 0 { cost = -cost } margin := cost * instrument.MarginRate order.Margin = margin //profit if order.OpenQuantity == 0 { order.Profit = 0 return nil } openprice := order.OpenCost / (order.OpenQuantity * instrument.ContractSize) profit := (order.CurPrice - openprice) * instrument.ContractSize * order.OpenQuantity order.Profit = profit return nil } func (list *OrderList) updateOrder(order *response.OrderEvent) error { if order.IsClosed() { //等待删除的对象 return nil } instrument, exchangeRate, priceEvent, err := list.mtf.getInstrumentInfo(order.InstrumentId) if err != nil { return err } //working order if order.IsWorking() { err = list.updateWorkingOrder(order, instrument, exchangeRate, priceEvent) } else { err = list.updateMarketOrder(order, instrument, exchangeRate, priceEvent) } return nil } func (list *OrderList) deleteClosed() { //delete closed order tmp := list.data[0:0] for i := 0; i < len(list.data); i++ { if !list.data[i].IsClosed() { tmp = append(tmp, list.data[i]) } else { //删除这个订单 symbol := list.data[i].InstrumentId data := list.perSymbol[symbol] for k := 0; k < len(data); k++ { if data[k] == list.data[i] { list.perSymbol[symbol] = append(data[:k], data[k+1:]...) } } } } list.data = tmp } func (list *OrderList) UpdateTick(event *TickEvent) (ret []*response.OrderEvent) { //do other things for i := 0; i < len(list.data); i++ { if list.data[i].InstrumentId == event.ob2.InstrumentId { //货币对匹配 list.updateOrder(list.data[i]) if event.fetchUpdated { copyed := list.data[i] if event.isCopy { tmp := *list.data[i] copyed = &tmp } ret = append(ret, copyed) } } } return } func (list *OrderList) UpdateRate(event *RateEvent) (ret []*response.OrderEvent) { //do other things for i := 0; i < len(list.data); i++ { if list.data[i].Currency == event.erate.From { //货币对匹配 list.updateOrder(list.data[i]) if event.fetchUpdated { copyed := list.data[i] if event.isCopy { tmp := *list.data[i] copyed = &tmp } ret = append(ret, copyed) } } } return } func (list *OrderList) workingOrderMargin(instrumentId int64) (float64, float64) { buy := 0.0 sell := 0.0 for i := 0; i < len(list.data); i++ { o := list.data[i] if o.InstrumentId == instrumentId && o.IsWorking() { if o.Quantity > 0 { buy += o.Margin } else { sell += o.Margin } } } return buy, sell } func getPrice(qty float64, priceEvent *response.OrderBookEvent) float64 { ask := priceEvent.AskPrices[0].Price bid := priceEvent.BidPrices[0].Price if qty > 0 { return bid } return ask }