Skip to content

Commit db70d64

Browse files
committed
Added reqMktData/reqMktDepth protobuf support
1 parent 56cc4de commit db70d64

38 files changed

+3495
-9
lines changed

client.go

Lines changed: 153 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -703,6 +703,11 @@ func (c *EClient) TWSConnectionTime() string {
703703
// mktDataOptions is for internal use only.Use default value XYZ.
704704
func (c *EClient) ReqMktData(reqID TickerID, contract *Contract, genericTickList string, snapshot bool, regulatorySnapshot bool, mktDataOptions []TagValue) {
705705

706+
if c.useProtoBuf(REQ_MKT_DATA) {
707+
c.reqMarketDataProtoBuf(createMarketDataRequestProto(reqID, contract, genericTickList, snapshot, regulatorySnapshot, mktDataOptions))
708+
return
709+
}
710+
706711
if !c.IsConnected() {
707712
c.wrapper.Error(reqID, currentTimeMillis(), NOT_CONNECTED.Code, NOT_CONNECTED.Msg, "")
708713
return
@@ -784,9 +789,40 @@ func (c *EClient) ReqMktData(reqID TickerID, contract *Contract, genericTickList
784789
c.reqChan <- me.Bytes()
785790
}
786791

792+
func (c *EClient) reqMarketDataProtoBuf(marketDataRequestProto *protobuf.MarketDataRequest) {
793+
794+
reqID := NO_VALID_ID
795+
if marketDataRequestProto.ReqId != nil {
796+
reqID = int64(*marketDataRequestProto.ReqId)
797+
}
798+
799+
if !c.IsConnected() {
800+
c.wrapper.Error(reqID, currentTimeMillis(), NOT_CONNECTED.Code, NOT_CONNECTED.Msg, "")
801+
return
802+
}
803+
804+
me := NewMsgEncoder(30, c)
805+
me.encodeMsgID(REQ_MKT_DATA + PROTOBUF_MSG_ID)
806+
807+
msg, err := proto.Marshal(marketDataRequestProto)
808+
if err != nil {
809+
c.wrapper.Error(reqID, currentTimeMillis(), 0, "Failed to marshal MarketDataRequest: "+err.Error(), "")
810+
return
811+
}
812+
813+
me.encodeProto(msg)
814+
815+
c.reqChan <- me.Bytes()
816+
}
817+
787818
// CancelMktData stops the market data flow for the specified TickerId.
788819
func (c *EClient) CancelMktData(reqID TickerID) {
789820

821+
if c.useProtoBuf(CANCEL_MKT_DATA) {
822+
c.cancelMarketDataProtoBuf(createCancelMarketDataProto(reqID))
823+
return
824+
}
825+
790826
if !c.IsConnected() {
791827
c.wrapper.Error(reqID, currentTimeMillis(), NOT_CONNECTED.Code, NOT_CONNECTED.Msg, "")
792828
return
@@ -801,6 +837,32 @@ func (c *EClient) CancelMktData(reqID TickerID) {
801837
c.reqChan <- me.Bytes()
802838
}
803839

840+
func (c *EClient) cancelMarketDataProtoBuf(cancelMarketDataProto *protobuf.CancelMarketData) {
841+
842+
reqID := NO_VALID_ID
843+
if cancelMarketDataProto.ReqId != nil {
844+
reqID = int64(*cancelMarketDataProto.ReqId)
845+
}
846+
847+
if !c.IsConnected() {
848+
c.wrapper.Error(reqID, currentTimeMillis(), NOT_CONNECTED.Code, NOT_CONNECTED.Msg, "")
849+
return
850+
}
851+
852+
me := NewMsgEncoder(3, c)
853+
me.encodeMsgID(CANCEL_MKT_DATA + PROTOBUF_MSG_ID)
854+
855+
msg, err := proto.Marshal(cancelMarketDataProto)
856+
if err != nil {
857+
c.wrapper.Error(reqID, currentTimeMillis(), 0, "Failed to marshal CancelMarketData: "+err.Error(), "")
858+
return
859+
}
860+
861+
me.encodeProto(msg)
862+
863+
c.reqChan <- me.Bytes()
864+
}
865+
804866
// ReqMarketDataType changes the market data type.
805867
//
806868
// The API can receive frozen market data from Trader Workstation. Frozen market data is the last data recorded in our system.
@@ -815,6 +877,11 @@ func (c *EClient) CancelMktData(reqID TickerID) {
815877
// 4 -> delayed frozen market data
816878
func (c *EClient) ReqMarketDataType(marketDataType int64) {
817879

880+
if c.useProtoBuf(REQ_MARKET_DATA_TYPE) {
881+
c.reqMarketDataTypeProtoBuf(createMarketDataTypeRequestProto(marketDataType))
882+
return
883+
}
884+
818885
if !c.IsConnected() {
819886
c.wrapper.Error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.Code, NOT_CONNECTED.Msg, "")
820887
return
@@ -839,6 +906,27 @@ func (c *EClient) ReqMarketDataType(marketDataType int64) {
839906
c.reqChan <- me.Bytes()
840907
}
841908

909+
func (c *EClient) reqMarketDataTypeProtoBuf(marketDataTypeRequestProto *protobuf.MarketDataTypeRequest) {
910+
911+
if !c.IsConnected() {
912+
c.wrapper.Error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.Code, NOT_CONNECTED.Msg, "")
913+
return
914+
}
915+
916+
me := NewMsgEncoder(3, c)
917+
me.encodeMsgID(REQ_MARKET_DATA_TYPE + PROTOBUF_MSG_ID)
918+
919+
msg, err := proto.Marshal(marketDataTypeRequestProto)
920+
if err != nil {
921+
c.wrapper.Error(NO_VALID_ID, currentTimeMillis(), 0, "Failed to marshal MarketDataTypeRequest: "+err.Error(), "")
922+
return
923+
}
924+
925+
me.encodeProto(msg)
926+
927+
c.reqChan <- me.Bytes()
928+
}
929+
842930
// ReqSmartComponents request the smartComponents.
843931
func (c *EClient) ReqSmartComponents(reqID int64, bboExchange string) {
844932

@@ -1855,13 +1943,14 @@ func (c *EClient) PlaceOrder(orderID OrderID, contract *Contract, order *Order)
18551943
if contract.Exchange == "IBKRATS" {
18561944
me.encodeIntMax(order.MinTradeQty)
18571945
}
1858-
if order.OrderType == "PEG BEST" {
1946+
switch order.OrderType {
1947+
case "PEG BEST":
18591948
me.encodeIntMax(order.MinCompeteSize)
18601949
me.encodeFloatMax(order.CompeteAgainstBestOffset)
18611950
if order.CompeteAgainstBestOffset == COMPETE_AGAINST_BEST_OFFSET_UP_TO_MID {
18621951
sendMidOffsets = true
18631952
}
1864-
} else if order.OrderType == "PEG MID" {
1953+
case "PEG MID":
18651954
sendMidOffsets = true
18661955
}
18671956
if sendMidOffsets {
@@ -2809,6 +2898,11 @@ func (c *EClient) ReqMktDepthExchanges() {
28092898
// mktDepthOptions is for internal use only. Use default value XYZ.
28102899
func (c *EClient) ReqMktDepth(reqID int64, contract *Contract, numRows int, isSmartDepth bool, mktDepthOptions []TagValue) {
28112900

2901+
if c.useProtoBuf(REQ_MKT_DEPTH) {
2902+
c.reqMarketDepthProtoBuf(createMarketDepthRequestProto(reqID, contract, int64(numRows), isSmartDepth, mktDepthOptions))
2903+
return
2904+
}
2905+
28122906
if !c.IsConnected() {
28132907
c.wrapper.Error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.Code, NOT_CONNECTED.Msg, "")
28142908
return
@@ -2878,9 +2972,40 @@ func (c *EClient) ReqMktDepth(reqID int64, contract *Contract, numRows int, isSm
28782972
c.reqChan <- me.Bytes()
28792973
}
28802974

2975+
func (c *EClient) reqMarketDepthProtoBuf(marketDepthRequestProto *protobuf.MarketDepthRequest) {
2976+
2977+
reqID := NO_VALID_ID
2978+
if marketDepthRequestProto.ReqId != nil {
2979+
reqID = int64(*marketDepthRequestProto.ReqId)
2980+
}
2981+
2982+
if !c.IsConnected() {
2983+
c.wrapper.Error(reqID, currentTimeMillis(), NOT_CONNECTED.Code, NOT_CONNECTED.Msg, "")
2984+
return
2985+
}
2986+
2987+
me := NewMsgEncoder(17, c)
2988+
me.encodeMsgID(REQ_MKT_DEPTH + PROTOBUF_MSG_ID)
2989+
2990+
msg, err := proto.Marshal(marketDepthRequestProto)
2991+
if err != nil {
2992+
c.wrapper.Error(reqID, currentTimeMillis(), 0, "Failed to marshal MarketDepthRequest: "+err.Error(), "")
2993+
return
2994+
}
2995+
2996+
me.encodeProto(msg)
2997+
2998+
c.reqChan <- me.Bytes()
2999+
}
3000+
28813001
// CancelMktDepth cancels market depth updates.
28823002
func (c *EClient) CancelMktDepth(reqID int64, isSmartDepth bool) {
28833003

3004+
if c.useProtoBuf(CANCEL_MKT_DEPTH) {
3005+
c.cancelMarketDepthProtoBuf(createCancelMarketDepthProto(reqID, isSmartDepth))
3006+
return
3007+
}
3008+
28843009
if !c.IsConnected() {
28853010
c.wrapper.Error(NO_VALID_ID, currentTimeMillis(), NOT_CONNECTED.Code, NOT_CONNECTED.Msg, "")
28863011
return
@@ -2906,6 +3031,32 @@ func (c *EClient) CancelMktDepth(reqID int64, isSmartDepth bool) {
29063031
c.reqChan <- me.Bytes()
29073032
}
29083033

3034+
func (c *EClient) cancelMarketDepthProtoBuf(cancelMarketDepthProto *protobuf.CancelMarketDepth) {
3035+
3036+
reqID := NO_VALID_ID
3037+
if cancelMarketDepthProto.ReqId != nil {
3038+
reqID = int64(*cancelMarketDepthProto.ReqId)
3039+
}
3040+
3041+
if !c.IsConnected() {
3042+
c.wrapper.Error(reqID, currentTimeMillis(), NOT_CONNECTED.Code, NOT_CONNECTED.Msg, "")
3043+
return
3044+
}
3045+
3046+
me := NewMsgEncoder(4, c)
3047+
me.encodeMsgID(REQ_MKT_DEPTH + PROTOBUF_MSG_ID)
3048+
3049+
msg, err := proto.Marshal(cancelMarketDepthProto)
3050+
if err != nil {
3051+
c.wrapper.Error(reqID, currentTimeMillis(), 0, "Failed to marshal CancelMarketDepth: "+err.Error(), "")
3052+
return
3053+
}
3054+
3055+
me.encodeProto(msg)
3056+
3057+
c.reqChan <- me.Bytes()
3058+
}
3059+
29093060
// ##########################################################################
29103061
// # News Bulletins
29113062
// ##########################################################################

client_utils.go

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -923,3 +923,104 @@ func createContractDataRequestProto(reqID int64, contract *Contract) *protobuf.C
923923
contractDataRequestProto.Contract = createContractProto(contract, nil)
924924
return contractDataRequestProto
925925
}
926+
927+
func createMarketDataRequestProto(reqID int64, contract *Contract, genericTickList string, snapshot bool, regulatorySnapshot bool, marketDataOptionsList []TagValue) *protobuf.MarketDataRequest {
928+
marketDataRequestProto := &protobuf.MarketDataRequest{}
929+
if isValidInt64Value(reqID) {
930+
id := int32(reqID)
931+
marketDataRequestProto.ReqId = &id
932+
}
933+
marketDataRequestProto.Contract = createContractProto(contract, nil)
934+
if !stringIsEmpty(genericTickList) {
935+
marketDataRequestProto.GenericTickList = &genericTickList
936+
}
937+
938+
if snapshot {
939+
marketDataRequestProto.Snapshot = &snapshot
940+
}
941+
942+
if regulatorySnapshot {
943+
marketDataRequestProto.RegulatorySnapshot = &regulatorySnapshot
944+
}
945+
946+
marketDataOptionsMap := createStringStringMap(marketDataOptionsList)
947+
if len(marketDataOptionsMap) > 0 {
948+
if marketDataRequestProto.MarketDataOptions == nil {
949+
marketDataRequestProto.MarketDataOptions = make(map[string]string)
950+
}
951+
for key, value := range marketDataOptionsMap {
952+
marketDataRequestProto.MarketDataOptions[key] = value
953+
}
954+
}
955+
956+
return marketDataRequestProto
957+
}
958+
959+
func createMarketDepthRequestProto(reqID int64, contract *Contract, numRows int64, isSmartDepth bool, marketDepthOptionsList []TagValue) *protobuf.MarketDepthRequest {
960+
marketDepthRequestProto := &protobuf.MarketDepthRequest{}
961+
962+
if isValidInt64Value(reqID) {
963+
id := int32(reqID)
964+
marketDepthRequestProto.ReqId = &id
965+
}
966+
967+
marketDepthRequestProto.Contract = createContractProto(contract, nil)
968+
969+
if isValidInt64Value(numRows) {
970+
nr := int32(numRows)
971+
marketDepthRequestProto.NumRows = &nr
972+
}
973+
974+
if isSmartDepth {
975+
marketDepthRequestProto.IsSmartDepth = &isSmartDepth
976+
}
977+
978+
marketDepthOptionsMap := createStringStringMap(marketDepthOptionsList)
979+
if len(marketDepthOptionsMap) > 0 {
980+
if marketDepthRequestProto.MarketDepthOptions == nil {
981+
marketDepthRequestProto.MarketDepthOptions = make(map[string]string)
982+
}
983+
for key, value := range marketDepthOptionsMap {
984+
marketDepthRequestProto.MarketDepthOptions[key] = value
985+
}
986+
}
987+
988+
return marketDepthRequestProto
989+
}
990+
991+
func createMarketDataTypeRequestProto(marketDataType int64) *protobuf.MarketDataTypeRequest {
992+
marketDataTypeRequestProto := &protobuf.MarketDataTypeRequest{}
993+
994+
if isValidInt64Value(marketDataType) {
995+
mdt := int32(marketDataType)
996+
marketDataTypeRequestProto.MarketDataType = &mdt
997+
}
998+
999+
return marketDataTypeRequestProto
1000+
}
1001+
1002+
func createCancelMarketDataProto(reqID int64) *protobuf.CancelMarketData {
1003+
cancelMarketDataProto := &protobuf.CancelMarketData{}
1004+
1005+
if isValidInt64Value(reqID) {
1006+
id := int32(reqID)
1007+
cancelMarketDataProto.ReqId = &id
1008+
}
1009+
1010+
return cancelMarketDataProto
1011+
}
1012+
1013+
func createCancelMarketDepthProto(reqID int64, isSmartDepth bool) *protobuf.CancelMarketDepth {
1014+
cancelMarketDepthProto := &protobuf.CancelMarketDepth{}
1015+
1016+
if isValidInt64Value(reqID) {
1017+
id := int32(reqID)
1018+
cancelMarketDepthProto.ReqId = &id
1019+
}
1020+
1021+
if isSmartDepth {
1022+
cancelMarketDepthProto.IsSmartDepth = &isSmartDepth
1023+
}
1024+
1025+
return cancelMarketDepthProto
1026+
}

0 commit comments

Comments
 (0)