123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374 |
- package response
- import (
- "encoding/xml"
- "time"
- "log"
- "math"
- "regexp"
- )
- type ExecutionEvent struct {
- XMLName xml.Name `xml:"order"`
- OrderEvent
- }
- type Orders struct {
- XMLName xml.Name `xml:"orders"`
- Data []*OrderEvent `xml:"page>order"`
- HasMoreResults bool `xml:"hasMoreResults"`
- CorrelationId int64 `xml:"correlationId"`
- }
- //基本流程是:客户在我们的matcher里面
- //添加order
- //cancel order
- //close order
- //matcher 会发送对应的消息给mtf
- //mtf 根据orderId 找到对应的msg
- //然后找到对应的client,更新account的信息
- //并通知给client
- //matcher 和 外界交互的标示是 orderId
- //这个order id 联系原始的msg
- //在配对表中的订单信息
- type Order struct {
- XMLName xml.Name `xml:"order"`
- TimeInForce string `xml:"timeInForce"`
- InstructionId string `xml:"instructionId"`
- OriginalInstructionId string `xml:"originalInstructionId,omitempty"`
- OrderId string `xml:"orderId"`
- OpeningOrderId string `xml:"openingOrderId,omitempty"`
- AccountId int64 `xml:"accountId"`
- InstrumentId int64 `xml:"instrumentId"`
- Quantity float64 `xml:"quantity"`
- FilledQuantity float64 `xml:"matchedQuantity"`
- MatchedCost float64 `xml:"matchedCost"`
- CancelledQuantity float64 `xml:"cancelledQuantity"`
- LimitPrice float64 `xml:"price,omitempty"`
- Timestamp time.Time `xml:"-"`
- TimestampStr string `xml:"timestamp"`
- OrderType string `xml:"orderType"`
- OpenQuantity float64 `xml:"openQuantity"`
- OpenCost float64 `xml:"openCost"`
- CumulativeCost float64 `xml:"cumulativeCost"`
- Commission float64 `xml:"commission"`
- StopReferencePrice float64 `xml:"stopReferencePrice"`
- StopLossOffset float64 `xml:"stopLossOffset,omitempty"`
- StopProfitOffset float64 `xml:"stopProfitOffset,omitempty"`
- Margin float64 `xml:"-"`
- Profit float64 `xml:"-"`
- CurPrice float64 `xml:"-"`
- Currency string `xml:"-"`
- }
- func (order *Order) GetQuantity() float64 {
- dt := order.Quantity - order.FilledQuantity - order.CancelledQuantity
- return dt
- }
- //配对:从 buy 到 sell
- func (order *Order) MatchQuantity(other *Order) float64 {
- dt := order.Quantity - order.FilledQuantity - order.CancelledQuantity
- dt2 := other.Quantity - other.FilledQuantity - other.CancelledQuantity
- //dt >= 0 dt2 <= 0
- //dt >= dt2
- if math.Abs(dt + dt2) >= 1e-9 {
- order.FilledQuantity -= dt2
- other.FilledQuantity += dt2
- return -dt2
- }
- order.FilledQuantity += dt
- other.FilledQuantity -= dt
- return dt
- }
- //一次配对的信息
- type Execution struct {
- MatchId int64 `xml:"-"`
- Order *Order `xml:"-"`
- Price float64 `xml:"price,omitempty"`
- Quantity float64 `xml:"quantity,omitempty"`
- }
- type OrderEvent struct {
- XMLName xml.Name `xml:"order"`
- Order
- ExecutionId int64 `xml:"executions>executionId,omitempty"`
- Executions []Execution `xml:"executions>execution,omitempty"`
- Cancelleds []Execution `xml:"executions>orderCancelled,omitempty"`
- }
- func (this *OrderEvent) GetId() string {
- return this.InstructionId
- }
- func (this *OrderEvent) SetId(id string) {
- this.InstructionId = id
- }
- func (this *OrderEvent) SetAccountId(id int64) {
- this.AccountId = id
- }
- func (this *OrderEvent) Clone() interface{} {
- tmp := *this
- return &tmp
- }
- //
- //<executionId>144887230</executionId><execution><price>1.31301</price><quantity>1</quantity></execution>
- func NewOrderEvent(eventData string) (*OrderEvent, *ExecutionEvent) {
- r := OrderEvent{}
- data := replaceEmptyTag([]byte(eventData))
- err := xml.Unmarshal(data, &r)
- if err != nil {
- log.Println(eventData, err)
- return nil, nil
- }
- r.Timestamp = parseTime(r.TimestampStr)
- if r.ExecutionId != 0 {
- return &r, &ExecutionEvent{xml.Name{}, r}
- }
- return &r, nil
- }
- //挂单
- func (order *OrderEvent) IsExecution() bool {
- if order.ExecutionId == 0 {
- return false
- }
- if len(order.Executions) > 0 && sameSign(order.Quantity, order.Executions[0].Quantity) {
- return true
- }
- if len(order.Cancelleds) > 0 && sameSign(order.Quantity, order.Cancelleds[0].Quantity) {
- return true
- }
- return false
- }
- func sameSign(a float64, b float64) bool {
- if a == b {
- return true
- }
- if a > 0 && b > 0 {
- return true
- }
- if a <0 && b < 0 {
- return true
- }
- return false
- }
- func (order *OrderEvent) IsWorking() bool {
- dt := order.Quantity - order.FilledQuantity - order.CancelledQuantity
- return dt != 0 && (OrderType(order.OrderType) == "LIMIT" || OrderType(order.OrderType) == "STOP")
- }
- func (order *OrderEvent) IsStopProft() bool {
- if OrderType(order.OrderType) == "STOP_PROFIT_ORDER" || OrderType(order.OrderType) == "STOP_LOSS_ORDER" {
- return true
- }
- return false
- }
- //可以从活动列表中删除的订单
- func (order *OrderEvent) IsClosed() bool {
- dt := order.Quantity - order.FilledQuantity - order.CancelledQuantity
- //log.Println(dt, order.OpenQuantity, dt == 0 && order.OpenQuantity == 0)
- if dt == 0 && order.OpenQuantity == 0 {
- return true
- }
- return false
- }
- func (order *OrderEvent) SetClosed() {
- order.OpenQuantity = 0
- order.FilledQuantity = order.Quantity - order.CancelledQuantity
- }
- func parseTime(t string) time.Time {
- t1, err := time.Parse("2006-01-02T15:04:05", t)
- if err != nil {
- return time.Time{}
- }
- return t1
- }
- func OrderType(s string) string {
- switch s {
- case "STOP_COMPOUND_PRICE_LIMIT", "PRICE_LIMIT":
- return "LIMIT"
- case "STOP_COMPOUND_MARKET", "MARKET_ORDER":
- return "MARKET"
- case "STOP_ORDER":
- return "STOP"
- case "MARKET", "LIMIT",
- "CLOSE_OUT_ORDER", "CLOSE_OUT_ORDER_POSITION", "CLOSE_OUT_POSITION",
- "STOP_LOSS_MARKET_ORDER", "STOP_PROFIT_LIMIT_ORDER", "STOP_PROFIT_ORDER", "STOP_LOSS_ORDER",
- "SETTLEMENT_ORDER", "OFF_ORDERBOOK", "REVERSAL":
- return s
- }
- return "UNKNOWN"
- }
- func TimeInForce(s string) string {
- switch s {
- case "FillOrKill", "ImmediateOrCancel", "GoodForDay", "GoodTilCancelled":
- return s
- }
- return "Unknown"
- }
- type CompletedOrder struct {
- XMLName xml.Name `xml:"completedOrder"`
- OrderId string `xml:"orderId"`
- InstrumentId int64 `xml:"instrumentId"`
- OrderType string `xml:"orderType"`
- TimestampStr string `xml:"timestamp"`
- Timestamp time.Time `xml:"-"`
- RealisedProfit float64 `xml:"realisedProfit,omitempty"`
- Commission float64 `xml:"commission"`
- Quantity float64 `xml:"quantity"`
- FilledQuantity float64 `xml:"filledQuantity"`
- FilledCost float64 `xml:"filledCost"`
- CancelledQuantity float64 `xml:"cancelledQuantity"`
- Price float64 `xml:"price"`
- Status string `xml:"status"`
- }
- type CompletedOrders struct {
- XMLName xml.Name `xml:"res"`
- Data []*CompletedOrder `xml:"body>completedOrders>completedOrder"`
- HasMoreResults bool `xml:"body>hasMoreResults"`
- }
- var emptyTag = regexp.MustCompile("<[^/]+/>")
- func replaceEmptyTag(data []byte) []byte {
- return emptyTag.ReplaceAll(data, []byte(""))
- }
- func NewCompletedOrders(eventData string) (*CompletedOrders, error) {
- r := CompletedOrders{}
- data := []byte(eventData)
- data = replaceEmptyTag(data)
- err := xml.Unmarshal(data, &r)
- if err != nil {
- return nil, err
- }
- for i := 0; i < len(r.Data); i++ {
- r.Data[i].Timestamp = parseTime(r.Data[i].TimestampStr)
- }
- return &r, nil
- }
- type Activity struct {
- Description string `xml:"description"`
- TimestampStr string `xml:"timestamp"`
- Timestamp time.Time `xml:"-"`
- Username string `xml:"username"`
- }
- type Activitys struct {
- XMLName xml.Name `xml:"res"`
- Data []*Activity `xml:"body>activity>orderEvent"`
- HasMoreResults bool `xml:"body>hasMoreResults"`
- }
- func NewActivitys(eventData string) (*Activitys, error) {
- r := Activitys{}
- data := []byte(eventData)
- err := xml.Unmarshal(data, &r)
- if err != nil {
- return nil, err
- }
- for i := 0; i < len(r.Data); i++ {
- r.Data[i].Timestamp = parseTime(r.Data[i].TimestampStr)
- }
- return &r, nil
- }
- type AccountStatement struct {
- Id int64 `xml:"id"`
- TimestampStr string `xml:"timestamp"`
- Timestamp time.Time `xml:"-"`
- CorrelationId int64 `xml:"correlationId"`
- InstrumentId int64 `xml:"instrumentId"`
- InstrumentName string `xml:"instrumentName"`
- VolumeWeightedAvgPrice float64 `xml:"volumeWeightedAvgPrice"`
- MatchedQuantity float64 `xml:"matchedQuantity"`
- UnitPrice float64 `xml:"unitPrice"`
- Type string `xml:"type"`
- Currency string `xml:"currency"`
- Amount float64 `xml:"amount"`
- Quantity float64 `xml:"quantity"`
- OrderId string `xml:"orderId,omitempty"`
- MinimumCommission float64 `xml:"minimumCommission,omitempty"`
- CommissionRate float64 `xml:"commissionRate,omitempty"`
- OpeningPrice float64 `xml:"openingPrice,omitempty"`
- OpeningOrderId string `xml:"openingOrderId,omitempty"`
- ClosingOrderId string `xml:"closingOrderId,omitempty"`
- ClosingPrice float64 `xml:"closingPrice,omitempty"`
- OpenQuantity float64 `xml:"openQuantity,omitempty"`
- FundingSpread float64 `xml:"fundingSpread,omitempty"`
- }
- type AccountStatements struct {
- XMLName xml.Name `xml:"res"`
- Data []*AccountStatement `xml:"body>transactions>transaction"`
- HasMoreResults bool `xml:"body>hasMoreResults"`
- }
- func NewAccountStatements(eventData string) (*AccountStatements, error) {
- r := AccountStatements{}
- data := []byte(eventData)
- err := xml.Unmarshal(data, &r)
- if err != nil {
- return nil, err
- }
- for i := 0; i < len(r.Data); i++ {
- r.Data[i].Timestamp = parseTime(r.Data[i].TimestampStr)
- }
- return &r, nil
- }
- //OrderTransactions
- type OrderTransactions struct {
- XMLName xml.Name `xml:"res"`
- Data []*OrderTransaction `xml:"body>orderTransactions>orderTransaction"`
- HasMoreResults bool `xml:"body>hasMoreResults"`
- }
- type OrderTransaction struct {
- Id int64 `xml:"id"`
- TimestampStr string `xml:"timestamp"`
- Timestamp time.Time `xml:"-"`
- CancelledQuantity float64 `xml:"cancelledQuantity"`
- Data []*BrokerExecution `xml:"brokerExecutions>brokerExecution"`
- }
- type BrokerExecution struct {
- Quantity float64 `xml:"quantity"`
- Price float64 `xml:"price"`
- }
- func NewOrderTransactions(eventData string) (*OrderTransactions, error) {
- r := OrderTransactions{}
- data := []byte(eventData)
- err := xml.Unmarshal(data, &r)
- if err != nil {
- return nil, err
- }
- for i := 0; i < len(r.Data); i++ {
- r.Data[i].Timestamp = parseTime(r.Data[i].TimestampStr)
- }
- return &r, nil
- }
|