123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- 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
- }
|