OrderEvent.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. package response
  2. import (
  3. "encoding/xml"
  4. "time"
  5. "log"
  6. "math"
  7. "regexp"
  8. )
  9. type ExecutionEvent struct {
  10. XMLName xml.Name `xml:"order"`
  11. OrderEvent
  12. }
  13. type Orders struct {
  14. XMLName xml.Name `xml:"orders"`
  15. Data []*OrderEvent `xml:"page>order"`
  16. HasMoreResults bool `xml:"hasMoreResults"`
  17. CorrelationId int64 `xml:"correlationId"`
  18. }
  19. //基本流程是:客户在我们的matcher里面
  20. //添加order
  21. //cancel order
  22. //close order
  23. //matcher 会发送对应的消息给mtf
  24. //mtf 根据orderId 找到对应的msg
  25. //然后找到对应的client,更新account的信息
  26. //并通知给client
  27. //matcher 和 外界交互的标示是 orderId
  28. //这个order id 联系原始的msg
  29. //在配对表中的订单信息
  30. type Order struct {
  31. XMLName xml.Name `xml:"order"`
  32. TimeInForce string `xml:"timeInForce"`
  33. InstructionId string `xml:"instructionId"`
  34. OriginalInstructionId string `xml:"originalInstructionId,omitempty"`
  35. OrderId string `xml:"orderId"`
  36. OpeningOrderId string `xml:"openingOrderId,omitempty"`
  37. AccountId int64 `xml:"accountId"`
  38. InstrumentId int64 `xml:"instrumentId"`
  39. Quantity float64 `xml:"quantity"`
  40. FilledQuantity float64 `xml:"matchedQuantity"`
  41. MatchedCost float64 `xml:"matchedCost"`
  42. CancelledQuantity float64 `xml:"cancelledQuantity"`
  43. LimitPrice float64 `xml:"price,omitempty"`
  44. Timestamp time.Time `xml:"-"`
  45. TimestampStr string `xml:"timestamp"`
  46. OrderType string `xml:"orderType"`
  47. OpenQuantity float64 `xml:"openQuantity"`
  48. OpenCost float64 `xml:"openCost"`
  49. CumulativeCost float64 `xml:"cumulativeCost"`
  50. Commission float64 `xml:"commission"`
  51. StopReferencePrice float64 `xml:"stopReferencePrice"`
  52. StopLossOffset float64 `xml:"stopLossOffset,omitempty"`
  53. StopProfitOffset float64 `xml:"stopProfitOffset,omitempty"`
  54. Margin float64 `xml:"-"`
  55. Profit float64 `xml:"-"`
  56. CurPrice float64 `xml:"-"`
  57. Currency string `xml:"-"`
  58. }
  59. func (order *Order) GetQuantity() float64 {
  60. dt := order.Quantity - order.FilledQuantity - order.CancelledQuantity
  61. return dt
  62. }
  63. //配对:从 buy 到 sell
  64. func (order *Order) MatchQuantity(other *Order) float64 {
  65. dt := order.Quantity - order.FilledQuantity - order.CancelledQuantity
  66. dt2 := other.Quantity - other.FilledQuantity - other.CancelledQuantity
  67. //dt >= 0 dt2 <= 0
  68. //dt >= dt2
  69. if math.Abs(dt + dt2) >= 1e-9 {
  70. order.FilledQuantity -= dt2
  71. other.FilledQuantity += dt2
  72. return -dt2
  73. }
  74. order.FilledQuantity += dt
  75. other.FilledQuantity -= dt
  76. return dt
  77. }
  78. //一次配对的信息
  79. type Execution struct {
  80. MatchId int64 `xml:"-"`
  81. Order *Order `xml:"-"`
  82. Price float64 `xml:"price,omitempty"`
  83. Quantity float64 `xml:"quantity,omitempty"`
  84. }
  85. type OrderEvent struct {
  86. XMLName xml.Name `xml:"order"`
  87. Order
  88. ExecutionId int64 `xml:"executions>executionId,omitempty"`
  89. Executions []Execution `xml:"executions>execution,omitempty"`
  90. Cancelleds []Execution `xml:"executions>orderCancelled,omitempty"`
  91. }
  92. func (this *OrderEvent) GetId() string {
  93. return this.InstructionId
  94. }
  95. func (this *OrderEvent) SetId(id string) {
  96. this.InstructionId = id
  97. }
  98. func (this *OrderEvent) SetAccountId(id int64) {
  99. this.AccountId = id
  100. }
  101. func (this *OrderEvent) Clone() interface{} {
  102. tmp := *this
  103. return &tmp
  104. }
  105. //
  106. //<executionId>144887230</executionId><execution><price>1.31301</price><quantity>1</quantity></execution>
  107. func NewOrderEvent(eventData string) (*OrderEvent, *ExecutionEvent) {
  108. r := OrderEvent{}
  109. data := replaceEmptyTag([]byte(eventData))
  110. err := xml.Unmarshal(data, &r)
  111. if err != nil {
  112. log.Println(eventData, err)
  113. return nil, nil
  114. }
  115. r.Timestamp = parseTime(r.TimestampStr)
  116. if r.ExecutionId != 0 {
  117. return &r, &ExecutionEvent{xml.Name{}, r}
  118. }
  119. return &r, nil
  120. }
  121. //挂单
  122. func (order *OrderEvent) IsExecution() bool {
  123. if order.ExecutionId == 0 {
  124. return false
  125. }
  126. if len(order.Executions) > 0 && sameSign(order.Quantity, order.Executions[0].Quantity) {
  127. return true
  128. }
  129. if len(order.Cancelleds) > 0 && sameSign(order.Quantity, order.Cancelleds[0].Quantity) {
  130. return true
  131. }
  132. return false
  133. }
  134. func sameSign(a float64, b float64) bool {
  135. if a == b {
  136. return true
  137. }
  138. if a > 0 && b > 0 {
  139. return true
  140. }
  141. if a <0 && b < 0 {
  142. return true
  143. }
  144. return false
  145. }
  146. func (order *OrderEvent) IsWorking() bool {
  147. dt := order.Quantity - order.FilledQuantity - order.CancelledQuantity
  148. return dt != 0 && (OrderType(order.OrderType) == "LIMIT" || OrderType(order.OrderType) == "STOP")
  149. }
  150. func (order *OrderEvent) IsStopProft() bool {
  151. if OrderType(order.OrderType) == "STOP_PROFIT_ORDER" || OrderType(order.OrderType) == "STOP_LOSS_ORDER" {
  152. return true
  153. }
  154. return false
  155. }
  156. //可以从活动列表中删除的订单
  157. func (order *OrderEvent) IsClosed() bool {
  158. dt := order.Quantity - order.FilledQuantity - order.CancelledQuantity
  159. //log.Println(dt, order.OpenQuantity, dt == 0 && order.OpenQuantity == 0)
  160. if dt == 0 && order.OpenQuantity == 0 {
  161. return true
  162. }
  163. return false
  164. }
  165. func (order *OrderEvent) SetClosed() {
  166. order.OpenQuantity = 0
  167. order.FilledQuantity = order.Quantity - order.CancelledQuantity
  168. }
  169. func parseTime(t string) time.Time {
  170. t1, err := time.Parse("2006-01-02T15:04:05", t)
  171. if err != nil {
  172. return time.Time{}
  173. }
  174. return t1
  175. }
  176. func OrderType(s string) string {
  177. switch s {
  178. case "STOP_COMPOUND_PRICE_LIMIT", "PRICE_LIMIT":
  179. return "LIMIT"
  180. case "STOP_COMPOUND_MARKET", "MARKET_ORDER":
  181. return "MARKET"
  182. case "STOP_ORDER":
  183. return "STOP"
  184. case "MARKET", "LIMIT",
  185. "CLOSE_OUT_ORDER", "CLOSE_OUT_ORDER_POSITION", "CLOSE_OUT_POSITION",
  186. "STOP_LOSS_MARKET_ORDER", "STOP_PROFIT_LIMIT_ORDER", "STOP_PROFIT_ORDER", "STOP_LOSS_ORDER",
  187. "SETTLEMENT_ORDER", "OFF_ORDERBOOK", "REVERSAL":
  188. return s
  189. }
  190. return "UNKNOWN"
  191. }
  192. func TimeInForce(s string) string {
  193. switch s {
  194. case "FillOrKill", "ImmediateOrCancel", "GoodForDay", "GoodTilCancelled":
  195. return s
  196. }
  197. return "Unknown"
  198. }
  199. type CompletedOrder struct {
  200. XMLName xml.Name `xml:"completedOrder"`
  201. OrderId string `xml:"orderId"`
  202. InstrumentId int64 `xml:"instrumentId"`
  203. OrderType string `xml:"orderType"`
  204. TimestampStr string `xml:"timestamp"`
  205. Timestamp time.Time `xml:"-"`
  206. RealisedProfit float64 `xml:"realisedProfit,omitempty"`
  207. Commission float64 `xml:"commission"`
  208. Quantity float64 `xml:"quantity"`
  209. FilledQuantity float64 `xml:"filledQuantity"`
  210. FilledCost float64 `xml:"filledCost"`
  211. CancelledQuantity float64 `xml:"cancelledQuantity"`
  212. Price float64 `xml:"price"`
  213. Status string `xml:"status"`
  214. }
  215. type CompletedOrders struct {
  216. XMLName xml.Name `xml:"res"`
  217. Data []*CompletedOrder `xml:"body>completedOrders>completedOrder"`
  218. HasMoreResults bool `xml:"body>hasMoreResults"`
  219. }
  220. var emptyTag = regexp.MustCompile("<[^/]+/>")
  221. func replaceEmptyTag(data []byte) []byte {
  222. return emptyTag.ReplaceAll(data, []byte(""))
  223. }
  224. func NewCompletedOrders(eventData string) (*CompletedOrders, error) {
  225. r := CompletedOrders{}
  226. data := []byte(eventData)
  227. data = replaceEmptyTag(data)
  228. err := xml.Unmarshal(data, &r)
  229. if err != nil {
  230. return nil, err
  231. }
  232. for i := 0; i < len(r.Data); i++ {
  233. r.Data[i].Timestamp = parseTime(r.Data[i].TimestampStr)
  234. }
  235. return &r, nil
  236. }
  237. type Activity struct {
  238. Description string `xml:"description"`
  239. TimestampStr string `xml:"timestamp"`
  240. Timestamp time.Time `xml:"-"`
  241. Username string `xml:"username"`
  242. }
  243. type Activitys struct {
  244. XMLName xml.Name `xml:"res"`
  245. Data []*Activity `xml:"body>activity>orderEvent"`
  246. HasMoreResults bool `xml:"body>hasMoreResults"`
  247. }
  248. func NewActivitys(eventData string) (*Activitys, error) {
  249. r := Activitys{}
  250. data := []byte(eventData)
  251. err := xml.Unmarshal(data, &r)
  252. if err != nil {
  253. return nil, err
  254. }
  255. for i := 0; i < len(r.Data); i++ {
  256. r.Data[i].Timestamp = parseTime(r.Data[i].TimestampStr)
  257. }
  258. return &r, nil
  259. }
  260. type AccountStatement struct {
  261. Id int64 `xml:"id"`
  262. TimestampStr string `xml:"timestamp"`
  263. Timestamp time.Time `xml:"-"`
  264. CorrelationId int64 `xml:"correlationId"`
  265. InstrumentId int64 `xml:"instrumentId"`
  266. InstrumentName string `xml:"instrumentName"`
  267. VolumeWeightedAvgPrice float64 `xml:"volumeWeightedAvgPrice"`
  268. MatchedQuantity float64 `xml:"matchedQuantity"`
  269. UnitPrice float64 `xml:"unitPrice"`
  270. Type string `xml:"type"`
  271. Currency string `xml:"currency"`
  272. Amount float64 `xml:"amount"`
  273. Quantity float64 `xml:"quantity"`
  274. OrderId string `xml:"orderId,omitempty"`
  275. MinimumCommission float64 `xml:"minimumCommission,omitempty"`
  276. CommissionRate float64 `xml:"commissionRate,omitempty"`
  277. OpeningPrice float64 `xml:"openingPrice,omitempty"`
  278. OpeningOrderId string `xml:"openingOrderId,omitempty"`
  279. ClosingOrderId string `xml:"closingOrderId,omitempty"`
  280. ClosingPrice float64 `xml:"closingPrice,omitempty"`
  281. OpenQuantity float64 `xml:"openQuantity,omitempty"`
  282. FundingSpread float64 `xml:"fundingSpread,omitempty"`
  283. }
  284. type AccountStatements struct {
  285. XMLName xml.Name `xml:"res"`
  286. Data []*AccountStatement `xml:"body>transactions>transaction"`
  287. HasMoreResults bool `xml:"body>hasMoreResults"`
  288. }
  289. func NewAccountStatements(eventData string) (*AccountStatements, error) {
  290. r := AccountStatements{}
  291. data := []byte(eventData)
  292. err := xml.Unmarshal(data, &r)
  293. if err != nil {
  294. return nil, err
  295. }
  296. for i := 0; i < len(r.Data); i++ {
  297. r.Data[i].Timestamp = parseTime(r.Data[i].TimestampStr)
  298. }
  299. return &r, nil
  300. }
  301. //OrderTransactions
  302. type OrderTransactions struct {
  303. XMLName xml.Name `xml:"res"`
  304. Data []*OrderTransaction `xml:"body>orderTransactions>orderTransaction"`
  305. HasMoreResults bool `xml:"body>hasMoreResults"`
  306. }
  307. type OrderTransaction struct {
  308. Id int64 `xml:"id"`
  309. TimestampStr string `xml:"timestamp"`
  310. Timestamp time.Time `xml:"-"`
  311. CancelledQuantity float64 `xml:"cancelledQuantity"`
  312. Data []*BrokerExecution `xml:"brokerExecutions>brokerExecution"`
  313. }
  314. type BrokerExecution struct {
  315. Quantity float64 `xml:"quantity"`
  316. Price float64 `xml:"price"`
  317. }
  318. func NewOrderTransactions(eventData string) (*OrderTransactions, error) {
  319. r := OrderTransactions{}
  320. data := []byte(eventData)
  321. err := xml.Unmarshal(data, &r)
  322. if err != nil {
  323. return nil, err
  324. }
  325. for i := 0; i < len(r.Data); i++ {
  326. r.Data[i].Timestamp = parseTime(r.Data[i].TimestampStr)
  327. }
  328. return &r, nil
  329. }