Skip to content

Commit

Permalink
Support ReqSecDefOptParams and its corresponding responses
Browse files Browse the repository at this point in the history
This involves supporting messages without a version field,
since the more recent messages eschew "version" for some reason.
  • Loading branch information
dimfeld committed Sep 28, 2017
1 parent 6a75972 commit d56075f
Show file tree
Hide file tree
Showing 3 changed files with 185 additions and 45 deletions.
35 changes: 35 additions & 0 deletions eclientsocket.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ const (
mUpdateDisplayGroup = 69
mUnsubscribeFromGroupEvents = 70
mStartAPI = 71
mRequestSecDefOptParams = 78
)

type serverHandshake struct {
Expand Down Expand Up @@ -1363,6 +1364,40 @@ func (c *CancelPositions) code() OutgoingMessageID { return mCancelPositions
func (c *CancelPositions) version() int64 { return 1 }
func (c *CancelPositions) write(b *bytes.Buffer) error { return nil }

// RequestSecDefOptParams is equivalent of IB API EClientSocket.reqSecDefOptParams
type RequestSecDefOptParams struct {
id int64
Symbol string
Exchange string
SecType string
ContractId int64
}

func (r *RequestSecDefOptParams) SetID(id int64) { r.id = id }

func (r *RequestSecDefOptParams) ID() int64 { return r.id }
func (r *RequestSecDefOptParams) code() OutgoingMessageID { return mRequestSecDefOptParams }
func (r *RequestSecDefOptParams) version() int64 { return -1 }
func (r *RequestSecDefOptParams) write(b *bytes.Buffer) error {
if err := writeInt(b, r.id); err != nil {
return err
}

if err := writeString(b, r.Symbol); err != nil {
return err
}

if err := writeString(b, r.Exchange); err != nil {
return err
}

if err := writeString(b, r.SecType); err != nil {
return err
}

return writeInt(b, r.ContractId)
}

// RequestAccountSummary is equivalent of IB API EClientSocket.reqAccountSummary()
type RequestAccountSummary struct {
id int64
Expand Down
14 changes: 12 additions & 2 deletions engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -538,7 +538,11 @@ func (v *header) write(b *bytes.Buffer) error {
if err := writeInt(b, v.code); err != nil {
return err
}
return writeInt(b, v.version)

if v.version != -1 {
return writeInt(b, v.version)
}
return nil
}

func (v *header) read(b *bufio.Reader) error {
Expand All @@ -547,7 +551,13 @@ func (v *header) read(b *bufio.Reader) error {
if v.code, err = readInt(b); err != nil {
return err
}
v.version, err = readInt(b)

if msgHasVersion(v.code) {
v.version, err = readInt(b)
} else {
v.version = -1
}

return err
}

Expand Down
181 changes: 138 additions & 43 deletions ereader.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,49 +14,51 @@ type IncomingMessageID int64

// Message types enum
const (
mTickPrice IncomingMessageID = 1
mTickSize = 2
mOrderStatus = 3
mErrorMessage = 4
mOpenOrder = 5
mAccountValue = 6
mPortfolioValue = 7
mAccountUpdateTime = 8
mNextValidID = 9
mContractData = 10
mExecutionData = 11
mMarketDepth = 12
mMarketDepthL2 = 13
mNewsBulletins = 14
mManagedAccounts = 15
mReceiveFA = 16
mHistoricalData = 17
mBondContractData = 18
mScannerParameters = 19
mScannerData = 20
mTickOptionComputation = 21
mTickGeneric = 45
mTickString = 46
mTickEFP = 47
mCurrentTime = 49
mRealtimeBars = 50
mFundamentalData = 51
mContractDataEnd = 52
mOpenOrderEnd = 53
mAccountDownloadEnd = 54
mExecutionDataEnd = 55
mDeltaNeutralValidation = 56
mTickSnapshotEnd = 57
mMarketDataType = 58
mCommissionReport = 59
mPosition = 61
mPositionEnd = 62
mAccountSummary = 63
mAccountSummaryEnd = 64
mVerifyMessageAPI = 65
mVerifyCompleted = 66
mDisplayGroupList = 67
mDisplayGroupUpdated = 68
mTickPrice IncomingMessageID = 1
mTickSize = 2
mOrderStatus = 3
mErrorMessage = 4
mOpenOrder = 5
mAccountValue = 6
mPortfolioValue = 7
mAccountUpdateTime = 8
mNextValidID = 9
mContractData = 10
mExecutionData = 11
mMarketDepth = 12
mMarketDepthL2 = 13
mNewsBulletins = 14
mManagedAccounts = 15
mReceiveFA = 16
mHistoricalData = 17
mBondContractData = 18
mScannerParameters = 19
mScannerData = 20
mTickOptionComputation = 21
mTickGeneric = 45
mTickString = 46
mTickEFP = 47
mCurrentTime = 49
mRealtimeBars = 50
mFundamentalData = 51
mContractDataEnd = 52
mOpenOrderEnd = 53
mAccountDownloadEnd = 54
mExecutionDataEnd = 55
mDeltaNeutralValidation = 56
mTickSnapshotEnd = 57
mMarketDataType = 58
mCommissionReport = 59
mPosition = 61
mPositionEnd = 62
mAccountSummary = 63
mAccountSummaryEnd = 64
mVerifyMessageAPI = 65
mVerifyCompleted = 66
mDisplayGroupList = 67
mDisplayGroupUpdated = 68
mSecurityDefinitionOptionParameter = 75
mSecurityDefinitionOptionParameterEnd = 76
)

// code2Msg is equivalent of EReader.processMsg() switch statement cases.
Expand Down Expand Up @@ -148,12 +150,28 @@ func code2Msg(code int64) (r Reply, err error) {
r = &DisplayGroupList{}
case int64(mDisplayGroupUpdated):
r = &DisplayGroupUpdated{}
case int64(mSecurityDefinitionOptionParameter):
r = &SecurityDefinitionOptionParameter{}
case int64(mSecurityDefinitionOptionParameterEnd):
r = &SecurityDefinitionOptionParameterEnd{}
default:
err = fmt.Errorf("Unsupported incoming message type %d", code)
}
return r, err
}

func msgHasVersion(code int64) bool {
switch code {
case int64(mSecurityDefinitionOptionParameter):
return false
case int64(mSecurityDefinitionOptionParameterEnd):
return false
default:
}

return true
}

// TickPrice holds bid, ask, last, etc. price information
type TickPrice struct {
id int64
Expand Down Expand Up @@ -1893,3 +1911,80 @@ func (d *DisplayGroupUpdated) read(b *bufio.Reader) (err error) {
d.ContractInfo, err = readString(b)
return err
}

type SecurityDefinitionOptionParameter struct {
id int64
Exchange string
ContractId int64
TradingClass string
Multiplier string
Expirations []string
Strikes []float64
}

func (s *SecurityDefinitionOptionParameter) ID() int64 { return s.id }
func (s *SecurityDefinitionOptionParameter) code() IncomingMessageID {
return mSecurityDefinitionOptionParameter
}
func (s *SecurityDefinitionOptionParameter) read(b *bufio.Reader) (err error) {
if s.id, err = readInt(b); err != nil {
return err
}

if s.Exchange, err = readString(b); err != nil {
return err
}

if s.ContractId, err = readInt(b); err != nil {
return err
}

if s.TradingClass, err = readString(b); err != nil {
return err
}

if s.Multiplier, err = readString(b); err != nil {
return err
}

numExpirations, err := readInt(b)
if err != nil {
return err
}

s.Expirations = make([]string, numExpirations)
for i := int64(0); i < numExpirations; i += 1 {
if s.Expirations[i], err = readString(b); err != nil {
return err
}
}

numStrikes, err := readInt(b)
if err != nil {
return err
}

s.Strikes = make([]float64, numStrikes)
for i := int64(0); i < numStrikes; i += 1 {
if s.Strikes[i], err = readFloat(b); err != nil {
return err
}
}

return nil

}

type SecurityDefinitionOptionParameterEnd struct {
id int64
}

// ID contains the TWS "reqId", which is used for reply correlation.
func (s *SecurityDefinitionOptionParameterEnd) ID() int64 { return s.id }
func (s *SecurityDefinitionOptionParameterEnd) code() IncomingMessageID {
return mSecurityDefinitionOptionParameterEnd
}
func (s *SecurityDefinitionOptionParameterEnd) read(b *bufio.Reader) (err error) {
s.id, err = readInt(b)
return err
}

0 comments on commit d56075f

Please sign in to comment.