├── .gitattributes ├── .gitignore ├── CHANGELOG.md ├── IB ├── API_VersionNum.txt ├── shared │ ├── CommissionReport.h │ ├── CommonDefs.h │ ├── Contract.h │ ├── EClient.h │ ├── EClientSocketBase.h │ ├── EClientSocketBaseImpl.h │ ├── EWrapper.h │ ├── Execution.h │ ├── HScrollListBox.cpp │ ├── HScrollListBox.h │ ├── IBString.h │ ├── Order.h │ ├── OrderState.h │ ├── ScannerSubscription.h │ ├── TagValue.h │ ├── TwsSocketClientErrors.h │ └── shared_ptr.h ├── src │ ├── EClientSocketBase.cpp │ ├── EPosixClientSocket.cpp │ ├── EPosixClientSocket.h │ └── EPosixClientSocketPlatform.h ├── swig_wrap.cpp └── swig_wrap.h ├── LICENSE ├── MANIFEST.in ├── README.rst ├── examples ├── contractdetails.py ├── customerror.py ├── historicaldata.py └── placeorder.py ├── patches ├── gcc_4_7 ├── mfc_msc_mixup ├── remove_stdafx └── shared_ptr_bool_conv ├── setup.py ├── swigibpy.py └── swigify_ib.i /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /.project 2 | /.pydevproject 3 | /_swigibpy.* 4 | /build 5 | .DS_Store 6 | /MANIFEST 7 | /dist 8 | *.egg-info 9 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## [Unreleased](https://github.com/Komnomnomnom/swigibpy/tree/HEAD) 4 | ### New Features 5 | * Update to TWS v9.71 API 6 | * Auto-reconnect support (disabled by default, enable using `reconnect_auto` 7 | argument in `EPosixClientSocket` constructor). 8 | * Raise `NotImplementedError` when `EWrapper` method missing. 9 | * Improved error handling, introduction of `EWrapper.pyError` method. 10 | * `EWrapperVerbose` and `EWrapperQuiet` utility classes 11 | * Improved polling behaviour 12 | * Improved documentation. 13 | 14 | ### Deprecated 15 | * `eConnect` argument `poll_auto`, use `poll_auto` argument in 16 | `EPosixClientSocket` constructor instead. 17 | 18 | ### Bug Fixes 19 | * Some small Python 3 fixes 20 | 21 | ### Thanks 22 | * [@sandrinr](https://github.com/sandrinr) 23 | 24 | [Full Changelog](https://github.com/Komnomnomnom/swigibpy/compare/0.4.1...HEAD) 25 | 26 | **Merged pull requests:** 27 | 28 | - Handle OSError during select [\#33](https://github.com/Komnomnomnom/swigibpy/pull/33) ([sandrinr](https://github.com/sandrinr)) 29 | 30 | - Fix eConnect wrapping [\#32](https://github.com/Komnomnomnom/swigibpy/pull/32) ([sandrinr](https://github.com/sandrinr)) 31 | 32 | - Fix dict iteration in Python 3 [\#29](https://github.com/Komnomnomnom/swigibpy/pull/29) ([sandrinr](https://github.com/sandrinr)) 33 | 34 | ## [0.4.1](https://github.com/Komnomnomnom/swigibpy/tree/0.4.1) (2013-05-04) 35 | * Fix for exception bubbling up and killing poller #19 36 | * Remove swigibpy custom exceptions 37 | 38 | ## [0.4](https://github.com/Komnomnomnom/swigibpy/tree/0.4) (2013-03-24) 39 | * Support for TWS Contract and Order ComboLegs and AlgoParams (#7) 40 | * Update to TWS v9.68 API. 41 | * Support for GCC 4.7+ 42 | * Remove TWS's (false) dependency on MFC (#17 thanks Koneski) 43 | * Better support for custom error handling (#15, #18) 44 | 45 | ## [0.3](https://github.com/Komnomnomnom/swigibpy/tree/0.3) (2012-08-08) 46 | * Allow customisation of poll interval #5 47 | * Support for comboleg vector #3 48 | * Python 3 supprt #4 49 | 50 | ## [0.2.3](https://github.com/Komnomnomnom/swigibpy/tree/0.2.3) (2012-04-03) 51 | * Update to TWS API v9.66 52 | 53 | ## [0.2.2](https://github.com/Komnomnomnom/swigibpy/tree/0.2.2) (2011-10-10) 54 | 55 | * Added Windows support. 56 | 57 | ## [0.2.1](https://github.com/Komnomnomnom/swigibpy/tree/0.2.1) (2011-09-19) 58 | 59 | * Added missing TWS types (Order, OrderState etc) 60 | 61 | ## [0.2](https://github.com/Komnomnomnom/swigibpy/tree/0.2) (2011-08-31) 62 | 63 | * Support for TWS API 9.65. 64 | * Built in TWS message polling 65 | * Rewrote interface file to use shadowing rather than renaming and subclassing 66 | -------------------------------------------------------------------------------- /IB/API_VersionNum.txt: -------------------------------------------------------------------------------- 1 | API_Version=9.71 2 | -------------------------------------------------------------------------------- /IB/shared/CommissionReport.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #ifndef commissionreport_def 5 | #define commissionreport_def 6 | 7 | #include "IBString.h" 8 | 9 | struct CommissionReport 10 | { 11 | CommissionReport() 12 | { 13 | commission = 0; 14 | realizedPNL = 0; 15 | yield = 0; 16 | yieldRedemptionDate = 0; 17 | } 18 | 19 | // commission report fields 20 | IBString execId; 21 | double commission; 22 | IBString currency; 23 | double realizedPNL; 24 | double yield; 25 | int yieldRedemptionDate; // YYYYMMDD format 26 | }; 27 | 28 | #endif // commissionreport_def 29 | -------------------------------------------------------------------------------- /IB/shared/CommonDefs.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #ifndef common_defs_h_INCLUDED 5 | #define common_defs_h_INCLUDED 6 | 7 | typedef long TickerId; 8 | typedef long OrderId; 9 | 10 | enum faDataType { GROUPS=1, PROFILES, ALIASES } ; 11 | 12 | inline const char* faDataTypeStr ( faDataType pFaDataType ) 13 | { 14 | switch (pFaDataType) { 15 | case GROUPS: 16 | return "GROUPS" ; 17 | break ; 18 | case PROFILES: 19 | return "PROFILES" ; 20 | break ; 21 | case ALIASES: 22 | return "ALIASES" ; 23 | break ; 24 | } 25 | return 0 ; 26 | } 27 | 28 | enum MarketDataType { 29 | REALTIME = 1, 30 | FROZEN = 2 31 | }; 32 | 33 | #endif /* common_defs_h_INCLUDED */ 34 | -------------------------------------------------------------------------------- /IB/shared/Contract.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #ifndef contract_def 5 | #define contract_def 6 | 7 | #include "TagValue.h" 8 | 9 | /* 10 | SAME_POS = open/close leg value is same as combo 11 | OPEN_POS = open 12 | CLOSE_POS = close 13 | UNKNOWN_POS = unknown 14 | */ 15 | enum LegOpenClose { SAME_POS, OPEN_POS, CLOSE_POS, UNKNOWN_POS }; 16 | 17 | struct ComboLeg 18 | { 19 | ComboLeg() 20 | : conId(0) 21 | , ratio(0) 22 | , openClose(0) 23 | , shortSaleSlot(0) 24 | , exemptCode(-1) 25 | { 26 | } 27 | 28 | long conId; 29 | long ratio; 30 | IBString action; //BUY/SELL/SSHORT 31 | 32 | IBString exchange; 33 | long openClose; // LegOpenClose enum values 34 | 35 | // for stock legs when doing short sale 36 | long shortSaleSlot; // 1 = clearing broker, 2 = third party 37 | IBString designatedLocation; 38 | int exemptCode; 39 | 40 | bool operator==( const ComboLeg &other) const 41 | { 42 | return (conId == other.conId && 43 | ratio == other.ratio && 44 | openClose == other.openClose && 45 | shortSaleSlot == other.shortSaleSlot && 46 | (Compare(action, other.action) == 0) && 47 | (Compare(exchange, other.exchange) == 0) && 48 | (Compare(designatedLocation, other.designatedLocation) == 0) && 49 | exemptCode == other.exemptCode); 50 | } 51 | }; 52 | 53 | struct UnderComp 54 | { 55 | UnderComp() 56 | : conId(0) 57 | , delta(0) 58 | , price(0) 59 | {} 60 | 61 | long conId; 62 | double delta; 63 | double price; 64 | }; 65 | 66 | typedef shared_ptr ComboLegSPtr; 67 | 68 | struct Contract 69 | { 70 | Contract() 71 | : conId(0) 72 | , strike(0) 73 | , includeExpired(false) 74 | , comboLegs(NULL) 75 | , underComp(NULL) 76 | { 77 | } 78 | 79 | long conId; 80 | IBString symbol; 81 | IBString secType; 82 | IBString expiry; 83 | double strike; 84 | IBString right; 85 | IBString multiplier; 86 | IBString exchange; 87 | IBString primaryExchange; // pick an actual (ie non-aggregate) exchange that the contract trades on. DO NOT SET TO SMART. 88 | IBString currency; 89 | IBString localSymbol; 90 | IBString tradingClass; 91 | bool includeExpired; 92 | IBString secIdType; // CUSIP;SEDOL;ISIN;RIC 93 | IBString secId; 94 | 95 | // COMBOS 96 | IBString comboLegsDescrip; // received in open order 14 and up for all combos 97 | 98 | // combo legs 99 | typedef std::vector ComboLegList; 100 | typedef shared_ptr ComboLegListSPtr; 101 | 102 | ComboLegListSPtr comboLegs; 103 | 104 | // delta neutral 105 | UnderComp* underComp; 106 | 107 | public: 108 | 109 | // Helpers 110 | static void CloneComboLegs(ComboLegListSPtr& dst, const ComboLegListSPtr& src); 111 | }; 112 | 113 | struct ContractDetails 114 | { 115 | ContractDetails() 116 | : minTick(0) 117 | , priceMagnifier(0) 118 | , underConId(0) 119 | , evMultiplier(0) 120 | , callable(false) 121 | , putable(false) 122 | , coupon(0) 123 | , convertible(false) 124 | , nextOptionPartial(false) 125 | { 126 | } 127 | 128 | Contract summary; 129 | IBString marketName; 130 | double minTick; 131 | IBString orderTypes; 132 | IBString validExchanges; 133 | long priceMagnifier; 134 | int underConId; 135 | IBString longName; 136 | IBString contractMonth; 137 | IBString industry; 138 | IBString category; 139 | IBString subcategory; 140 | IBString timeZoneId; 141 | IBString tradingHours; 142 | IBString liquidHours; 143 | IBString evRule; 144 | double evMultiplier; 145 | 146 | TagValueListSPtr secIdList; 147 | 148 | // BOND values 149 | IBString cusip; 150 | IBString ratings; 151 | IBString descAppend; 152 | IBString bondType; 153 | IBString couponType; 154 | bool callable; 155 | bool putable; 156 | double coupon; 157 | bool convertible; 158 | IBString maturity; 159 | IBString issueDate; 160 | IBString nextOptionDate; 161 | IBString nextOptionType; 162 | bool nextOptionPartial; 163 | IBString notes; 164 | }; 165 | 166 | inline void 167 | Contract::CloneComboLegs(ComboLegListSPtr& dst, const ComboLegListSPtr& src) 168 | { 169 | if (!src.get()) 170 | return; 171 | 172 | dst->reserve(src->size()); 173 | 174 | ComboLegList::const_iterator iter = src->begin(); 175 | const ComboLegList::const_iterator iterEnd = src->end(); 176 | 177 | for (; iter != iterEnd; ++iter) { 178 | const ComboLeg* leg = iter->get(); 179 | if (!leg) 180 | continue; 181 | dst->push_back(ComboLegSPtr(new ComboLeg(*leg))); 182 | } 183 | } 184 | 185 | 186 | #endif 187 | -------------------------------------------------------------------------------- /IB/shared/EClient.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #ifndef eclient_def 5 | #define eclient_def 6 | 7 | #include "CommonDefs.h" 8 | #include "IBString.h" 9 | #include "TagValue.h" 10 | 11 | struct Contract; 12 | struct Order; 13 | struct ExecutionFilter; 14 | struct ScannerSubscription; 15 | 16 | class EClient 17 | { 18 | public: 19 | virtual ~EClient() {} 20 | virtual bool eConnect( const char *host, unsigned int port, int clientId = 0, bool extraAuth = 0) = 0; 21 | virtual void eDisconnect() = 0; 22 | virtual int serverVersion() = 0; 23 | virtual IBString TwsConnectionTime() = 0; 24 | virtual void reqMktData( TickerId id, const Contract &contract, 25 | const IBString& genericTicks, bool snapshot, const TagValueListSPtr& mktDataOptions) = 0; 26 | virtual void cancelMktData( TickerId id) = 0; 27 | virtual void placeOrder( OrderId id, const Contract &contract, const Order &order) = 0; 28 | virtual void cancelOrder( OrderId id) = 0; 29 | virtual void reqOpenOrders() = 0; 30 | virtual void reqAccountUpdates(bool subscribe, const IBString& acctCode) = 0; 31 | virtual void reqExecutions(int reqId, const ExecutionFilter& filter) = 0; 32 | virtual void reqIds( int numIds) = 0; 33 | virtual bool checkMessages() = 0; 34 | virtual void reqContractDetails( int reqId, const Contract &contract) = 0; 35 | virtual void reqMktDepth( TickerId id, const Contract &contract, int numRows, const TagValueListSPtr& mktDepthOptions) = 0; 36 | virtual void cancelMktDepth( TickerId id) = 0; 37 | virtual void reqNewsBulletins( bool allMsgs) = 0; 38 | virtual void cancelNewsBulletins() = 0; 39 | virtual void setServerLogLevel(int level) = 0; 40 | virtual void reqAutoOpenOrders(bool bAutoBind) = 0; 41 | virtual void reqAllOpenOrders() = 0; 42 | virtual void reqManagedAccts() = 0; 43 | virtual void requestFA(faDataType pFaDataType) = 0; 44 | virtual void replaceFA(faDataType pFaDataType, const IBString& cxml) = 0; 45 | virtual void reqHistoricalData( TickerId id, const Contract &contract, 46 | const IBString &endDateTime, const IBString &durationStr, const IBString &barSizeSetting, 47 | const IBString &whatToShow, int useRTH, int formatDate, const TagValueListSPtr& chartOptions) = 0; 48 | virtual void exerciseOptions( TickerId id, const Contract &contract, 49 | int exerciseAction, int exerciseQuantity, const IBString &account, int override) = 0; 50 | virtual void cancelHistoricalData( TickerId tickerId ) = 0; 51 | virtual void reqRealTimeBars( TickerId id, const Contract &contract, int barSize, 52 | const IBString &whatToShow, bool useRTH, const TagValueListSPtr& realTimeBarsOptions) = 0; 53 | virtual void cancelRealTimeBars( TickerId tickerId) = 0; 54 | virtual void cancelScannerSubscription( int tickerId) = 0; 55 | virtual void reqScannerParameters() = 0; 56 | virtual void reqScannerSubscription( int tickerId, const ScannerSubscription &subscription, const TagValueListSPtr& scannerSubscriptionOptions) = 0; 57 | virtual void reqCurrentTime() = 0; 58 | virtual void reqFundamentalData( TickerId reqId, const Contract&, const IBString& reportType) = 0; 59 | virtual void cancelFundamentalData( TickerId reqId) = 0; 60 | virtual void calculateImpliedVolatility( TickerId reqId, const Contract &contract, double optionPrice, double underPrice) = 0; 61 | virtual void calculateOptionPrice( TickerId reqId, const Contract &contract, double volatility, double underPrice) = 0; 62 | virtual void cancelCalculateImpliedVolatility( TickerId reqId) = 0; 63 | virtual void cancelCalculateOptionPrice( TickerId reqId) = 0; 64 | virtual void reqGlobalCancel() = 0; 65 | virtual void reqMarketDataType( int marketDataType) = 0; 66 | virtual void reqPositions() = 0; 67 | virtual void cancelPositions() = 0; 68 | virtual void reqAccountSummary( int reqId, const IBString& groupName, const IBString& tags) = 0; 69 | virtual void cancelAccountSummary( int reqId) = 0; 70 | virtual void verifyRequest( const IBString& apiName, const IBString& apiVersion) = 0; 71 | virtual void verifyMessage( const IBString& apiData) = 0; 72 | virtual void queryDisplayGroups( int reqId) = 0; 73 | virtual void subscribeToGroupEvents( int reqId, int groupId) = 0; 74 | virtual void updateDisplayGroup( int reqId, const IBString& contractInfo) = 0; 75 | virtual void unsubscribeFromGroupEvents( int reqId) = 0; 76 | 77 | private: 78 | }; 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /IB/shared/EClientSocketBase.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #ifndef eclientsocketbase_h__INCLUDED 5 | #define eclientsocketbase_h__INCLUDED 6 | 7 | #include "EClient.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | class EWrapper; 14 | 15 | class EClientSocketBase : public EClient 16 | { 17 | public: 18 | 19 | explicit EClientSocketBase(EWrapper *ptr); 20 | ~EClientSocketBase(); 21 | 22 | virtual bool eConnect(const char *host, unsigned int port, int clientId = 0, bool extraAuth = false) = 0; 23 | virtual void eDisconnect() = 0; 24 | 25 | int clientId() const { return m_clientId; } 26 | 27 | protected: 28 | 29 | void eConnectBase(); 30 | void eDisconnectBase(); 31 | 32 | public: 33 | 34 | // connection state 35 | bool isConnected() const; 36 | 37 | protected: 38 | 39 | // access to protected variables 40 | EWrapper * getWrapper() const; 41 | void setClientId( int clientId); 42 | void setExtraAuth( bool extraAuth); 43 | 44 | public: 45 | 46 | bool isInBufferEmpty() const; 47 | bool isOutBufferEmpty() const; 48 | 49 | // override virtual funcs from EClient 50 | int serverVersion(); 51 | IBString TwsConnectionTime(); 52 | void reqMktData(TickerId id, const Contract &contract, 53 | const IBString &genericTicks, bool snapshot, const TagValueListSPtr& mktDataOptions); 54 | void cancelMktData(TickerId id); 55 | void placeOrder(OrderId id, const Contract &contract, const Order &order); 56 | void cancelOrder(OrderId id) ; 57 | void reqOpenOrders(); 58 | void reqAccountUpdates(bool subscribe, const IBString& acctCode); 59 | void reqExecutions(int reqId, const ExecutionFilter& filter); 60 | void reqIds(int numIds); 61 | bool checkMessages(); 62 | void reqContractDetails(int reqId, const Contract &contract); 63 | void reqMktDepth(TickerId tickerId, const Contract &contract, int numRows, const TagValueListSPtr& mktDepthOptions); 64 | void cancelMktDepth(TickerId tickerId); 65 | void reqNewsBulletins(bool allMsgs); 66 | void cancelNewsBulletins(); 67 | void setServerLogLevel(int level); 68 | void reqAutoOpenOrders(bool bAutoBind); 69 | void reqAllOpenOrders(); 70 | void reqManagedAccts(); 71 | void requestFA(faDataType pFaDataType); 72 | void replaceFA(faDataType pFaDataType, const IBString& cxml); 73 | void reqHistoricalData( TickerId id, const Contract &contract, 74 | const IBString &endDateTime, const IBString &durationStr, 75 | const IBString & barSizeSetting, const IBString &whatToShow, 76 | int useRTH, int formatDate, const TagValueListSPtr& chartOptions); 77 | void exerciseOptions(TickerId tickerId, const Contract &contract, 78 | int exerciseAction, int exerciseQuantity, 79 | const IBString &account, int override); 80 | void cancelHistoricalData(TickerId tickerId ); 81 | void reqRealTimeBars(TickerId id, const Contract &contract, int barSize, 82 | const IBString &whatToShow, bool useRTH, const TagValueListSPtr& realTimeBarsOptions); 83 | void cancelRealTimeBars(TickerId tickerId ); 84 | void cancelScannerSubscription(int tickerId); 85 | void reqScannerParameters(); 86 | void reqScannerSubscription(int tickerId, const ScannerSubscription &subscription, const TagValueListSPtr& scannerSubscriptionOptions); 87 | void reqCurrentTime(); 88 | void reqFundamentalData(TickerId reqId, const Contract&, const IBString& reportType); 89 | void cancelFundamentalData(TickerId reqId); 90 | void calculateImpliedVolatility(TickerId reqId, const Contract &contract, double optionPrice, double underPrice); 91 | void calculateOptionPrice(TickerId reqId, const Contract &contract, double volatility, double underPrice); 92 | void cancelCalculateImpliedVolatility(TickerId reqId); 93 | void cancelCalculateOptionPrice(TickerId reqId); 94 | void reqGlobalCancel(); 95 | void reqMarketDataType(int marketDataType); 96 | void reqPositions(); 97 | void cancelPositions(); 98 | void reqAccountSummary( int reqId, const IBString& groupName, const IBString& tags); 99 | void cancelAccountSummary( int reqId); 100 | void verifyRequest( const IBString& apiName, const IBString& apiVersion); 101 | void verifyMessage( const IBString& apiData); 102 | void queryDisplayGroups( int reqId); 103 | void subscribeToGroupEvents( int reqId, int groupId); 104 | void updateDisplayGroup( int reqId, const IBString& contractInfo); 105 | void unsubscribeFromGroupEvents( int reqId); 106 | 107 | private: 108 | 109 | virtual int send(const char* buf, size_t sz) = 0; 110 | virtual int receive(char* buf, size_t sz) = 0; 111 | 112 | protected: 113 | 114 | int sendBufferedData(); 115 | 116 | private: 117 | 118 | int bufferedSend(const char* buf, size_t sz); 119 | int bufferedSend(const std::string& msg); 120 | 121 | // read and buffer what's available 122 | int bufferedRead(); 123 | 124 | // try to process connection request ack 125 | int processConnectAck(const char*& ptr, const char* endPtr); 126 | 127 | // try to process single msg 128 | int processMsg(const char*& ptr, const char* endPtr); 129 | 130 | void startApi(); 131 | 132 | static bool CheckOffset(const char* ptr, const char* endPtr); 133 | static const char* FindFieldEnd(const char* ptr, const char* endPtr); 134 | 135 | // decoders 136 | static bool DecodeField(bool&, const char*& ptr, const char* endPtr); 137 | static bool DecodeField(int&, const char*& ptr, const char* endPtr); 138 | static bool DecodeField(long&, const char*& ptr, const char* endPtr); 139 | static bool DecodeField(double&, const char*& ptr, const char* endPtr); 140 | static bool DecodeField(IBString&, const char*& ptr, const char* endPtr); 141 | 142 | static bool DecodeFieldMax(int&, const char*& ptr, const char* endPtr); 143 | static bool DecodeFieldMax(long&, const char*& ptr, const char* endPtr); 144 | static bool DecodeFieldMax(double&, const char*& ptr, const char* endPtr); 145 | 146 | // encoders 147 | template static void EncodeField(std::ostream&, T); 148 | 149 | // "max" encoders 150 | static void EncodeFieldMax(std::ostream& os, int); 151 | static void EncodeFieldMax(std::ostream& os, double); 152 | 153 | // socket state 154 | virtual bool isSocketOK() const = 0; 155 | 156 | protected: 157 | 158 | void onConnectBase(); 159 | 160 | private: 161 | 162 | typedef std::vector BytesVec; 163 | 164 | private: 165 | 166 | static void CleanupBuffer(BytesVec&, int processed); 167 | 168 | private: 169 | 170 | EWrapper *m_pEWrapper; 171 | 172 | BytesVec m_inBuffer; 173 | BytesVec m_outBuffer; 174 | 175 | int m_clientId; 176 | 177 | bool m_connected; 178 | bool m_extraAuth; 179 | int m_serverVersion; 180 | IBString m_TwsTime; 181 | 182 | }; 183 | 184 | template<> void EClientSocketBase::EncodeField(std::ostream& os, bool); 185 | template<> void EClientSocketBase::EncodeField(std::ostream& os, double); 186 | 187 | #endif 188 | -------------------------------------------------------------------------------- /IB/shared/EWrapper.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #ifndef ewrapper_def 5 | #define ewrapper_def 6 | 7 | #include "CommonDefs.h" 8 | #include "IBString.h" 9 | 10 | enum TickType { BID_SIZE, BID, ASK, ASK_SIZE, LAST, LAST_SIZE, 11 | HIGH, LOW, VOLUME, CLOSE, 12 | BID_OPTION_COMPUTATION, 13 | ASK_OPTION_COMPUTATION, 14 | LAST_OPTION_COMPUTATION, 15 | MODEL_OPTION, 16 | OPEN, 17 | LOW_13_WEEK, 18 | HIGH_13_WEEK, 19 | LOW_26_WEEK, 20 | HIGH_26_WEEK, 21 | LOW_52_WEEK, 22 | HIGH_52_WEEK, 23 | AVG_VOLUME, 24 | OPEN_INTEREST, 25 | OPTION_HISTORICAL_VOL, 26 | OPTION_IMPLIED_VOL, 27 | OPTION_BID_EXCH, 28 | OPTION_ASK_EXCH, 29 | OPTION_CALL_OPEN_INTEREST, 30 | OPTION_PUT_OPEN_INTEREST, 31 | OPTION_CALL_VOLUME, 32 | OPTION_PUT_VOLUME, 33 | INDEX_FUTURE_PREMIUM, 34 | BID_EXCH, 35 | ASK_EXCH, 36 | AUCTION_VOLUME, 37 | AUCTION_PRICE, 38 | AUCTION_IMBALANCE, 39 | MARK_PRICE, 40 | BID_EFP_COMPUTATION, 41 | ASK_EFP_COMPUTATION, 42 | LAST_EFP_COMPUTATION, 43 | OPEN_EFP_COMPUTATION, 44 | HIGH_EFP_COMPUTATION, 45 | LOW_EFP_COMPUTATION, 46 | CLOSE_EFP_COMPUTATION, 47 | LAST_TIMESTAMP, 48 | SHORTABLE, 49 | FUNDAMENTAL_RATIOS, 50 | RT_VOLUME, 51 | HALTED, 52 | BID_YIELD, 53 | ASK_YIELD, 54 | LAST_YIELD, 55 | CUST_OPTION_COMPUTATION, 56 | TRADE_COUNT, 57 | TRADE_RATE, 58 | VOLUME_RATE, 59 | LAST_RTH_TRADE, 60 | NOT_SET }; 61 | 62 | inline bool isPrice( TickType tickType) { 63 | return tickType == BID || tickType == ASK || tickType == LAST; 64 | } 65 | 66 | struct Contract; 67 | struct ContractDetails; 68 | struct Order; 69 | struct OrderState; 70 | struct Execution; 71 | struct UnderComp; 72 | struct CommissionReport; 73 | 74 | class EWrapper 75 | { 76 | public: 77 | virtual ~EWrapper() {}; 78 | 79 | virtual void tickPrice( TickerId tickerId, TickType field, double price, int canAutoExecute) = 0; 80 | virtual void tickSize( TickerId tickerId, TickType field, int size) = 0; 81 | virtual void tickOptionComputation( TickerId tickerId, TickType tickType, double impliedVol, double delta, 82 | double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice) = 0; 83 | virtual void tickGeneric(TickerId tickerId, TickType tickType, double value) = 0; 84 | virtual void tickString(TickerId tickerId, TickType tickType, const IBString& value) = 0; 85 | virtual void tickEFP(TickerId tickerId, TickType tickType, double basisPoints, const IBString& formattedBasisPoints, 86 | double totalDividends, int holdDays, const IBString& futureExpiry, double dividendImpact, double dividendsToExpiry) = 0; 87 | virtual void orderStatus( OrderId orderId, const IBString &status, int filled, 88 | int remaining, double avgFillPrice, int permId, int parentId, 89 | double lastFillPrice, int clientId, const IBString& whyHeld) = 0; 90 | virtual void openOrder( OrderId orderId, const Contract&, const Order&, const OrderState&) = 0; 91 | virtual void openOrderEnd() = 0; 92 | virtual void winError( const IBString &str, int lastError) = 0; 93 | virtual void connectionClosed() = 0; 94 | virtual void updateAccountValue(const IBString& key, const IBString& val, 95 | const IBString& currency, const IBString& accountName) = 0; 96 | virtual void updatePortfolio( const Contract& contract, int position, 97 | double marketPrice, double marketValue, double averageCost, 98 | double unrealizedPNL, double realizedPNL, const IBString& accountName) = 0; 99 | virtual void updateAccountTime(const IBString& timeStamp) = 0; 100 | virtual void accountDownloadEnd(const IBString& accountName) = 0; 101 | virtual void nextValidId( OrderId orderId) = 0; 102 | virtual void contractDetails( int reqId, const ContractDetails& contractDetails) = 0; 103 | virtual void bondContractDetails( int reqId, const ContractDetails& contractDetails) = 0; 104 | virtual void contractDetailsEnd( int reqId) = 0; 105 | virtual void execDetails( int reqId, const Contract& contract, const Execution& execution) =0; 106 | virtual void execDetailsEnd( int reqId) =0; 107 | virtual void error(const int id, const int errorCode, const IBString errorString) = 0; 108 | virtual void updateMktDepth(TickerId id, int position, int operation, int side, 109 | double price, int size) = 0; 110 | virtual void updateMktDepthL2(TickerId id, int position, IBString marketMaker, int operation, 111 | int side, double price, int size) = 0; 112 | virtual void updateNewsBulletin(int msgId, int msgType, const IBString& newsMessage, const IBString& originExch) = 0; 113 | virtual void managedAccounts( const IBString& accountsList) = 0; 114 | virtual void receiveFA(faDataType pFaDataType, const IBString& cxml) = 0; 115 | virtual void historicalData(TickerId reqId, const IBString& date, double open, double high, 116 | double low, double close, int volume, int barCount, double WAP, int hasGaps) = 0; 117 | virtual void scannerParameters(const IBString &xml) = 0; 118 | virtual void scannerData(int reqId, int rank, const ContractDetails &contractDetails, 119 | const IBString &distance, const IBString &benchmark, const IBString &projection, 120 | const IBString &legsStr) = 0; 121 | virtual void scannerDataEnd(int reqId) = 0; 122 | virtual void realtimeBar(TickerId reqId, long time, double open, double high, double low, double close, 123 | long volume, double wap, int count) = 0; 124 | virtual void currentTime(long time) = 0; 125 | virtual void fundamentalData(TickerId reqId, const IBString& data) = 0; 126 | virtual void deltaNeutralValidation(int reqId, const UnderComp& underComp) = 0; 127 | virtual void tickSnapshotEnd( int reqId) = 0; 128 | virtual void marketDataType( TickerId reqId, int marketDataType) = 0; 129 | virtual void commissionReport( const CommissionReport &commissionReport) = 0; 130 | virtual void position( const IBString& account, const Contract& contract, int position, double avgCost) = 0; 131 | virtual void positionEnd() = 0; 132 | virtual void accountSummary( int reqId, const IBString& account, const IBString& tag, const IBString& value, const IBString& curency) = 0; 133 | virtual void accountSummaryEnd( int reqId) = 0; 134 | virtual void verifyMessageAPI( const IBString& apiData) = 0; 135 | virtual void verifyCompleted( bool isSuccessful, const IBString& errorText) = 0; 136 | virtual void displayGroupList( int reqId, const IBString& groups) = 0; 137 | virtual void displayGroupUpdated( int reqId, const IBString& contractInfo) = 0; 138 | }; 139 | 140 | 141 | #endif 142 | -------------------------------------------------------------------------------- /IB/shared/Execution.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #ifndef execution_def 5 | #define execution_def 6 | 7 | #include "IBString.h" 8 | 9 | struct Execution 10 | { 11 | Execution() 12 | { 13 | shares = 0; 14 | price = 0; 15 | permId = 0; 16 | clientId = 0; 17 | orderId = 0; 18 | cumQty = 0; 19 | avgPrice = 0; 20 | evMultiplier = 0; 21 | } 22 | 23 | IBString execId; 24 | IBString time; 25 | IBString acctNumber; 26 | IBString exchange; 27 | IBString side; 28 | int shares; 29 | double price; 30 | int permId; 31 | long clientId; 32 | long orderId; 33 | int liquidation; 34 | int cumQty; 35 | double avgPrice; 36 | IBString orderRef; 37 | IBString evRule; 38 | double evMultiplier; 39 | }; 40 | 41 | struct ExecutionFilter 42 | { 43 | ExecutionFilter() 44 | : m_clientId(0) 45 | { 46 | } 47 | 48 | // Filter fields 49 | long m_clientId; 50 | IBString m_acctCode; 51 | IBString m_time; 52 | IBString m_symbol; 53 | IBString m_secType; 54 | IBString m_exchange; 55 | IBString m_side; 56 | }; 57 | 58 | #endif // execution_def 59 | -------------------------------------------------------------------------------- /IB/shared/HScrollListBox.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #include "stdafx.h" 5 | #include "HScrollListBox.h" 6 | 7 | #ifdef _DEBUG 8 | #define new DEBUG_NEW 9 | #undef THIS_FILE 10 | static char THIS_FILE[] = __FILE__; 11 | #endif 12 | 13 | ///////////////////////////////////////////////////////////////////////////// 14 | BEGIN_MESSAGE_MAP(CHScrollListBox, CListBox) 15 | //{{AFX_MSG_MAP(CHScrollListBox) 16 | // NOTE - the ClassWizard will add and remove mapping macros here. 17 | //}}AFX_MSG_MAP 18 | ON_MESSAGE(LB_ADDSTRING, OnAddString) 19 | ON_MESSAGE(LB_INSERTSTRING, OnInsertString) 20 | ON_MESSAGE(LB_DELETESTRING, OnDeleteString) 21 | ON_MESSAGE(LB_RESETCONTENT, OnResetContent) 22 | END_MESSAGE_MAP() 23 | 24 | ///////////////////////////////////////////////////////////////////////////// 25 | // CHScrollListBox 26 | ///////////////////////////////////////////////////////////////////////////// 27 | CHScrollListBox::CHScrollListBox() 28 | { 29 | } 30 | 31 | CHScrollListBox::~CHScrollListBox() 32 | { 33 | } 34 | 35 | ///////////////////////////////////////////////////////////////////////////// 36 | // CHScrollListBox message handlers 37 | /////////////////////////////////////////////////////////////////////////////// 38 | int CHScrollListBox::GetTextLen(LPCTSTR lpszText) 39 | { 40 | ASSERT(AfxIsValidString(lpszText)); 41 | 42 | CDC *pDC = GetDC(); 43 | ASSERT(pDC); 44 | CSize size; 45 | 46 | if ( pDC ) 47 | { 48 | CFont* pOldFont = pDC->SelectObject(GetFont()); 49 | if ( pOldFont ) 50 | { 51 | size = pDC->GetTextExtent(lpszText, (int) _tcslen(lpszText)); 52 | pDC->SelectObject(pOldFont); 53 | } 54 | ReleaseDC(pDC); 55 | } 56 | 57 | return size.cx +5; // add some whitespace 58 | } 59 | 60 | void CHScrollListBox::ResetHExtent() 61 | { 62 | if (GetCount() == 0) 63 | { 64 | SetHorizontalExtent(0); 65 | return; 66 | } 67 | 68 | CWaitCursor WaitCursor; 69 | int iMaxHExtent = 0; 70 | for (int i = 0; i < GetCount(); i++) 71 | { 72 | CString csText; 73 | GetText(i, csText); 74 | if ( int iExt = GetTextLen(csText) > iMaxHExtent ) 75 | iMaxHExtent = iExt; 76 | } 77 | 78 | SetHorizontalExtent(iMaxHExtent); 79 | } 80 | 81 | void CHScrollListBox::SetNewHExtent(LPCTSTR lpszNewString) 82 | { 83 | int iExt = GetTextLen(lpszNewString); 84 | if ( iExt > GetHorizontalExtent()) 85 | SetHorizontalExtent(iExt); 86 | } 87 | 88 | // Event handlers 89 | LRESULT CHScrollListBox::OnAddString(WPARAM wParam, LPARAM lParam) 90 | { 91 | LRESULT lResult = Default(); 92 | if ( !((lResult == LB_ERR) || (lResult == LB_ERRSPACE)) ) 93 | SetNewHExtent((LPCTSTR) lParam); 94 | 95 | return lResult; 96 | } 97 | 98 | LRESULT CHScrollListBox::OnInsertString(WPARAM wParam, LPARAM lParam) 99 | { 100 | LRESULT lResult = Default(); 101 | if ( !((lResult == LB_ERR) || (lResult == LB_ERRSPACE)) ) 102 | SetNewHExtent((LPCTSTR) lParam); 103 | 104 | return lResult; 105 | } 106 | 107 | LRESULT CHScrollListBox::OnDeleteString(WPARAM wParam, LPARAM lParam) 108 | { 109 | LRESULT lResult = Default(); 110 | if ( !((lResult == LB_ERR) || (lResult == LB_ERRSPACE)) ) 111 | ResetHExtent(); 112 | 113 | return lResult; 114 | } 115 | 116 | LRESULT CHScrollListBox::OnResetContent(WPARAM wParam, LPARAM lParam) 117 | { 118 | LRESULT lResult = Default(); 119 | SetHorizontalExtent(0); 120 | 121 | return lResult; 122 | } 123 | 124 | -------------------------------------------------------------------------------- /IB/shared/HScrollListBox.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #if !defined(CHSCROLLLISTBOX_H) 5 | #define CHSCROLLLISTBOX_H 6 | 7 | ///////////////////////////////////////////////////////////////////////////// 8 | // CHScrollListBox window 9 | ///////////////////////////////////////////////////////////////////////////// 10 | class CHScrollListBox : public CListBox 11 | { 12 | // Construction 13 | public: 14 | CHScrollListBox(); 15 | 16 | public: 17 | 18 | // Overrides 19 | // ClassWizard generated virtual function overrides 20 | //{{AFX_VIRTUAL(CHScrollListBox) 21 | //}}AFX_VIRTUAL 22 | 23 | // Implementation 24 | public: 25 | virtual ~CHScrollListBox(); 26 | 27 | // Generated message map functions 28 | protected: 29 | //{{AFX_MSG(CHScrollListBox) 30 | // NOTE - the ClassWizard will add and remove member functions here. 31 | //}}AFX_MSG 32 | 33 | afx_msg LRESULT OnAddString(WPARAM wParam, LPARAM lParam); 34 | afx_msg LRESULT OnInsertString(WPARAM wParam, LPARAM lParam); 35 | afx_msg LRESULT OnDeleteString(WPARAM wParam, LPARAM lParam); 36 | afx_msg LRESULT OnResetContent(WPARAM wParam, LPARAM lParam); 37 | 38 | DECLARE_MESSAGE_MAP() 39 | 40 | private: 41 | void ResetHExtent(); 42 | void SetNewHExtent(LPCTSTR lpszNewString); 43 | int GetTextLen(LPCTSTR lpszText); 44 | 45 | }; 46 | 47 | ///////////////////////////////////////////////////////////////////////////// 48 | 49 | //{{AFX_INSERT_LOCATION}} 50 | // Microsoft Visual C++ will insert additional declarations immediately before the previous line. 51 | 52 | #endif // !defined(CHSCROLLLISTBOX_H) 53 | -------------------------------------------------------------------------------- /IB/shared/IBString.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #ifndef ibstring_h__INCLUDED 5 | #define ibstring_h__INCLUDED 6 | 7 | #ifdef IB_USE_STD_STRING 8 | #include 9 | typedef std::string IBString; 10 | #else 11 | #include 12 | typedef CString IBString; 13 | #endif 14 | 15 | #include 16 | 17 | inline bool IsEmpty(const IBString& str) 18 | { 19 | #ifdef IB_USE_STD_STRING 20 | return str.empty(); 21 | #else 22 | return str.IsEmpty(); 23 | #endif 24 | }; 25 | 26 | inline void Empty(IBString& str) 27 | { 28 | #ifdef IB_USE_STD_STRING 29 | str.erase(); 30 | #else 31 | str.Empty(); 32 | #endif 33 | }; 34 | 35 | inline bool Compare(IBString str, const char* strToCompare) 36 | { 37 | #ifdef IB_USE_STD_STRING 38 | return str.compare(strToCompare); 39 | #else 40 | return str.CompareNoCase(strToCompare); 41 | #endif 42 | }; 43 | 44 | inline bool Compare(IBString str, IBString strToCompare) 45 | { 46 | #ifdef IB_USE_STD_STRING 47 | return str.compare(strToCompare); 48 | #else 49 | return str.CompareNoCase(strToCompare); 50 | #endif 51 | }; 52 | 53 | inline double Atof(IBString str) 54 | { 55 | #ifdef IB_USE_STD_STRING 56 | return atof(str.c_str()); 57 | #else 58 | return atof(str); 59 | #endif 60 | }; 61 | 62 | inline int Atoi(IBString str) 63 | { 64 | #ifdef IB_USE_STD_STRING 65 | return atoi(str.c_str()); 66 | #else 67 | return atoi(str); 68 | #endif 69 | }; 70 | 71 | #endif 72 | 73 | 74 | -------------------------------------------------------------------------------- /IB/shared/Order.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #ifndef order_def 5 | #define order_def 6 | 7 | #include "TagValue.h" 8 | 9 | #include 10 | #include 11 | 12 | #define UNSET_DOUBLE DBL_MAX 13 | #define UNSET_INTEGER INT_MAX 14 | 15 | enum Origin { CUSTOMER, 16 | FIRM, 17 | UNKNOWN }; 18 | 19 | enum AuctionStrategy { AUCTION_UNSET = 0, 20 | AUCTION_MATCH = 1, 21 | AUCTION_IMPROVEMENT = 2, 22 | AUCTION_TRANSPARENT = 3 }; 23 | 24 | struct OrderComboLeg 25 | { 26 | OrderComboLeg() 27 | { 28 | price = UNSET_DOUBLE; 29 | } 30 | 31 | double price; 32 | 33 | bool operator==( const OrderComboLeg &other) const 34 | { 35 | return (price == other.price); 36 | } 37 | }; 38 | 39 | typedef shared_ptr OrderComboLegSPtr; 40 | 41 | struct Order 42 | { 43 | Order() 44 | { 45 | // order identifier 46 | orderId = 0; 47 | clientId = 0; 48 | permId = 0; 49 | 50 | // main order fields 51 | totalQuantity = 0; 52 | lmtPrice = UNSET_DOUBLE; 53 | auxPrice = UNSET_DOUBLE; 54 | 55 | // extended order fields 56 | activeStartTime = ""; 57 | activeStopTime = ""; 58 | ocaType = 0; 59 | transmit = true; 60 | parentId = 0; 61 | blockOrder = false; 62 | sweepToFill = false; 63 | displaySize = 0; 64 | triggerMethod = 0; 65 | outsideRth = false; 66 | hidden = false; 67 | allOrNone = false; 68 | minQty = UNSET_INTEGER; 69 | percentOffset = UNSET_DOUBLE; 70 | overridePercentageConstraints = false; 71 | trailStopPrice = UNSET_DOUBLE; 72 | trailingPercent = UNSET_DOUBLE; 73 | 74 | // institutional (ie non-cleared) only 75 | openClose = "O"; 76 | origin = CUSTOMER; 77 | shortSaleSlot = 0; 78 | exemptCode = -1; 79 | 80 | // SMART routing only 81 | discretionaryAmt = 0; 82 | eTradeOnly = true; 83 | firmQuoteOnly = true; 84 | nbboPriceCap = UNSET_DOUBLE; 85 | optOutSmartRouting = false; 86 | 87 | // BOX exchange orders only 88 | auctionStrategy = AUCTION_UNSET; 89 | startingPrice = UNSET_DOUBLE; 90 | stockRefPrice = UNSET_DOUBLE; 91 | delta = UNSET_DOUBLE; 92 | 93 | // pegged to stock and VOL orders only 94 | stockRangeLower = UNSET_DOUBLE; 95 | stockRangeUpper = UNSET_DOUBLE; 96 | 97 | // VOLATILITY ORDERS ONLY 98 | volatility = UNSET_DOUBLE; 99 | volatilityType = UNSET_INTEGER; // 1=daily, 2=annual 100 | deltaNeutralOrderType = ""; 101 | deltaNeutralAuxPrice = UNSET_DOUBLE; 102 | deltaNeutralConId = 0; 103 | deltaNeutralSettlingFirm = ""; 104 | deltaNeutralClearingAccount = ""; 105 | deltaNeutralClearingIntent = ""; 106 | deltaNeutralOpenClose = ""; 107 | deltaNeutralShortSale = false; 108 | deltaNeutralShortSaleSlot = 0; 109 | deltaNeutralDesignatedLocation = ""; 110 | continuousUpdate = false; 111 | referencePriceType = UNSET_INTEGER; // 1=Average, 2 = BidOrAsk 112 | 113 | // COMBO ORDERS ONLY 114 | basisPoints = UNSET_DOUBLE; // EFP orders only 115 | basisPointsType = UNSET_INTEGER; // EFP orders only 116 | 117 | // SCALE ORDERS ONLY 118 | scaleInitLevelSize = UNSET_INTEGER; 119 | scaleSubsLevelSize = UNSET_INTEGER; 120 | scalePriceIncrement = UNSET_DOUBLE; 121 | scalePriceAdjustValue = UNSET_DOUBLE; 122 | scalePriceAdjustInterval = UNSET_INTEGER; 123 | scaleProfitOffset = UNSET_DOUBLE; 124 | scaleAutoReset = false; 125 | scaleInitPosition = UNSET_INTEGER; 126 | scaleInitFillQty = UNSET_INTEGER; 127 | scaleRandomPercent = false; 128 | scaleTable = ""; 129 | 130 | // What-if 131 | whatIf = false; 132 | 133 | // Not Held 134 | notHeld = false; 135 | } 136 | 137 | // order identifier 138 | long orderId; 139 | long clientId; 140 | long permId; 141 | 142 | // main order fields 143 | IBString action; 144 | long totalQuantity; 145 | IBString orderType; 146 | double lmtPrice; 147 | double auxPrice; 148 | 149 | // extended order fields 150 | IBString tif; // "Time in Force" - DAY, GTC, etc. 151 | IBString activeStartTime; // for GTC orders 152 | IBString activeStopTime; // for GTC orders 153 | IBString ocaGroup; // one cancels all group name 154 | int ocaType; // 1 = CANCEL_WITH_BLOCK, 2 = REDUCE_WITH_BLOCK, 3 = REDUCE_NON_BLOCK 155 | IBString orderRef; // order reference 156 | bool transmit; // if false, order will be created but not transmited 157 | long parentId; // Parent order Id, to associate Auto STP or TRAIL orders with the original order. 158 | bool blockOrder; 159 | bool sweepToFill; 160 | int displaySize; 161 | int triggerMethod; // 0=Default, 1=Double_Bid_Ask, 2=Last, 3=Double_Last, 4=Bid_Ask, 7=Last_or_Bid_Ask, 8=Mid-point 162 | bool outsideRth; 163 | bool hidden; 164 | IBString goodAfterTime; // Format: 20060505 08:00:00 {time zone} 165 | IBString goodTillDate; // Format: 20060505 08:00:00 {time zone} 166 | IBString rule80A; // Individual = 'I', Agency = 'A', AgentOtherMember = 'W', IndividualPTIA = 'J', AgencyPTIA = 'U', AgentOtherMemberPTIA = 'M', IndividualPT = 'K', AgencyPT = 'Y', AgentOtherMemberPT = 'N' 167 | bool allOrNone; 168 | int minQty; 169 | double percentOffset; // REL orders only 170 | bool overridePercentageConstraints; 171 | double trailStopPrice; // TRAILLIMIT orders only 172 | double trailingPercent; 173 | 174 | // financial advisors only 175 | IBString faGroup; 176 | IBString faProfile; 177 | IBString faMethod; 178 | IBString faPercentage; 179 | 180 | // institutional (ie non-cleared) only 181 | IBString openClose; // O=Open, C=Close 182 | Origin origin; // 0=Customer, 1=Firm 183 | int shortSaleSlot; // 1 if you hold the shares, 2 if they will be delivered from elsewhere. Only for Action="SSHORT 184 | IBString designatedLocation; // set when slot=2 only. 185 | int exemptCode; 186 | 187 | // SMART routing only 188 | double discretionaryAmt; 189 | bool eTradeOnly; 190 | bool firmQuoteOnly; 191 | double nbboPriceCap; 192 | bool optOutSmartRouting; 193 | 194 | // BOX exchange orders only 195 | int auctionStrategy; // AUCTION_MATCH, AUCTION_IMPROVEMENT, AUCTION_TRANSPARENT 196 | double startingPrice; 197 | double stockRefPrice; 198 | double delta; 199 | 200 | // pegged to stock and VOL orders only 201 | double stockRangeLower; 202 | double stockRangeUpper; 203 | 204 | // VOLATILITY ORDERS ONLY 205 | double volatility; 206 | int volatilityType; // 1=daily, 2=annual 207 | IBString deltaNeutralOrderType; 208 | double deltaNeutralAuxPrice; 209 | long deltaNeutralConId; 210 | IBString deltaNeutralSettlingFirm; 211 | IBString deltaNeutralClearingAccount; 212 | IBString deltaNeutralClearingIntent; 213 | IBString deltaNeutralOpenClose; 214 | bool deltaNeutralShortSale; 215 | int deltaNeutralShortSaleSlot; 216 | IBString deltaNeutralDesignatedLocation; 217 | bool continuousUpdate; 218 | int referencePriceType; // 1=Average, 2 = BidOrAsk 219 | 220 | // COMBO ORDERS ONLY 221 | double basisPoints; // EFP orders only 222 | int basisPointsType; // EFP orders only 223 | 224 | // SCALE ORDERS ONLY 225 | int scaleInitLevelSize; 226 | int scaleSubsLevelSize; 227 | double scalePriceIncrement; 228 | double scalePriceAdjustValue; 229 | int scalePriceAdjustInterval; 230 | double scaleProfitOffset; 231 | bool scaleAutoReset; 232 | int scaleInitPosition; 233 | int scaleInitFillQty; 234 | bool scaleRandomPercent; 235 | IBString scaleTable; 236 | 237 | // HEDGE ORDERS 238 | IBString hedgeType; // 'D' - delta, 'B' - beta, 'F' - FX, 'P' - pair 239 | IBString hedgeParam; // 'beta=X' value for beta hedge, 'ratio=Y' for pair hedge 240 | 241 | // Clearing info 242 | IBString account; // IB account 243 | IBString settlingFirm; 244 | IBString clearingAccount; // True beneficiary of the order 245 | IBString clearingIntent; // "" (Default), "IB", "Away", "PTA" (PostTrade) 246 | 247 | // ALGO ORDERS ONLY 248 | IBString algoStrategy; 249 | 250 | TagValueListSPtr algoParams; 251 | TagValueListSPtr smartComboRoutingParams; 252 | 253 | // What-if 254 | bool whatIf; 255 | 256 | // Not Held 257 | bool notHeld; 258 | 259 | // order combo legs 260 | typedef std::vector OrderComboLegList; 261 | typedef shared_ptr OrderComboLegListSPtr; 262 | 263 | OrderComboLegListSPtr orderComboLegs; 264 | 265 | TagValueListSPtr orderMiscOptions; 266 | 267 | public: 268 | 269 | // Helpers 270 | static void CloneOrderComboLegs(OrderComboLegListSPtr& dst, const OrderComboLegListSPtr& src); 271 | }; 272 | 273 | inline void 274 | Order::CloneOrderComboLegs(OrderComboLegListSPtr& dst, const OrderComboLegListSPtr& src) 275 | { 276 | if (!src.get()) 277 | return; 278 | 279 | dst->reserve(src->size()); 280 | 281 | OrderComboLegList::const_iterator iter = src->begin(); 282 | const OrderComboLegList::const_iterator iterEnd = src->end(); 283 | 284 | for (; iter != iterEnd; ++iter) { 285 | const OrderComboLeg* leg = iter->get(); 286 | if (!leg) 287 | continue; 288 | dst->push_back(OrderComboLegSPtr(new OrderComboLeg(*leg))); 289 | } 290 | } 291 | 292 | #endif 293 | -------------------------------------------------------------------------------- /IB/shared/OrderState.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #ifndef ORDER_STATE_H__INCLUDED 5 | #define ORDER_STATE_H__INCLUDED 6 | 7 | #include "Order.h" 8 | 9 | struct OrderState { 10 | 11 | explicit OrderState() 12 | : 13 | commission(UNSET_DOUBLE), 14 | minCommission(UNSET_DOUBLE), 15 | maxCommission(UNSET_DOUBLE) 16 | {} 17 | 18 | IBString status; 19 | 20 | IBString initMargin; 21 | IBString maintMargin; 22 | IBString equityWithLoan; 23 | 24 | double commission; 25 | double minCommission; 26 | double maxCommission; 27 | IBString commissionCurrency; 28 | 29 | IBString warningText; 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /IB/shared/ScannerSubscription.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #ifndef scanner_def 5 | #define scanner_def 6 | 7 | #include 8 | #include 9 | 10 | #include "IBString.h" 11 | 12 | #define UNSET_DOUBLE DBL_MAX 13 | #define UNSET_INTEGER INT_MAX 14 | #define NO_ROW_NUMBER_SPECIFIED -1; 15 | 16 | struct ScannerSubscription { 17 | ScannerSubscription() { 18 | numberOfRows = NO_ROW_NUMBER_SPECIFIED; 19 | abovePrice = DBL_MAX; 20 | belowPrice = DBL_MAX; 21 | aboveVolume = INT_MAX; 22 | marketCapAbove = DBL_MAX; 23 | marketCapBelow = DBL_MAX; 24 | couponRateAbove = DBL_MAX; 25 | couponRateBelow = DBL_MAX; 26 | excludeConvertible = 0; 27 | averageOptionVolumeAbove = 0; 28 | } 29 | int numberOfRows; 30 | IBString instrument; 31 | IBString locationCode; 32 | IBString scanCode; 33 | double abovePrice; 34 | double belowPrice; 35 | int aboveVolume; 36 | double marketCapAbove; 37 | double marketCapBelow; 38 | IBString moodyRatingAbove; 39 | IBString moodyRatingBelow; 40 | IBString spRatingAbove; 41 | IBString spRatingBelow; 42 | IBString maturityDateAbove; 43 | IBString maturityDateBelow; 44 | double couponRateAbove; 45 | double couponRateBelow; 46 | int excludeConvertible; 47 | int averageOptionVolumeAbove; 48 | IBString scannerSettingPairs; 49 | IBString stockTypeFilter; 50 | }; 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /IB/shared/TagValue.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #ifndef tagvalue_def 5 | #define tagvalue_def 6 | 7 | #include "shared_ptr.h" 8 | #include "IBString.h" 9 | 10 | #include 11 | 12 | struct TagValue 13 | { 14 | TagValue() {} 15 | TagValue(const IBString& p_tag, const IBString& p_value) 16 | : tag(p_tag), value(p_value) 17 | {} 18 | 19 | IBString tag; 20 | IBString value; 21 | }; 22 | 23 | typedef shared_ptr TagValueSPtr; 24 | typedef std::vector TagValueList; 25 | typedef shared_ptr TagValueListSPtr; 26 | 27 | #endif 28 | 29 | -------------------------------------------------------------------------------- /IB/shared/TwsSocketClientErrors.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #ifndef tswsocketclienterrors_def 5 | #define tswsocketclienterrors_def 6 | 7 | static const int NO_VALID_ID = -1; 8 | static const int NO_VALID_ERROR_CODE = 0; 9 | static const int SYSTEM_ERROR = 600; 10 | 11 | class CodeMsgPair { 12 | public: 13 | CodeMsgPair(int code, IBString msg) : m_errorCode(code), m_errorMsg(msg) { 14 | } 15 | private: 16 | int m_errorCode; 17 | IBString m_errorMsg; 18 | public: 19 | int code() const { return m_errorCode; } 20 | const IBString& msg() const { return m_errorMsg; } 21 | }; 22 | 23 | static const CodeMsgPair ALREADY_CONNECTED(501, "Already connected."); 24 | static const CodeMsgPair CONNECT_FAIL(502, "Couldn't connect to TWS. Confirm that \"Enable ActiveX and Socket Clients\" is enabled on the TWS \"Configure->API\" menu."); 25 | static const CodeMsgPair UPDATE_TWS(503, "The TWS is out of date and must be upgraded."); 26 | static const CodeMsgPair NOT_CONNECTED(504, "Not connected"); 27 | static const CodeMsgPair UNKNOWN_ID(505, "Fatal Error: Unknown message id."); 28 | static const CodeMsgPair ZERO_BYTE_READ(506, "Unexplained zero bytes read."); 29 | static const CodeMsgPair NULL_STRING_READ(507, "Null string read when expecting integer"); 30 | static const CodeMsgPair NO_BYTES_READ(508, "Error: no bytes read or no null terminator found"); 31 | static const CodeMsgPair SOCKET_EXCEPTION(509, "Exception caught while reading socket - "); 32 | static const CodeMsgPair FAIL_CREATE_SOCK(520, "Failed to create socket"); 33 | static const CodeMsgPair FAIL_CONNECT_TWS(521, "Couldn't connect to TWS."); 34 | static const CodeMsgPair FAIL_SEND_FA_REQUEST(522, "FA Information Request Sending Error - "); 35 | static const CodeMsgPair FAIL_SEND_FA_REPLACE(523, "FA Information Replace Sending Error - "); 36 | static const CodeMsgPair FAIL_SEND_REQSCANNER(524, "Request Scanner Subscription Sending Error - "); 37 | static const CodeMsgPair FAIL_SEND_CANSCANNER(525, "Cancel Scanner Subscription Sending Error - "); 38 | static const CodeMsgPair FAIL_SEND_REQSCANNERPARAMETERS(526, "Request Scanner Parameter Sending Error - "); 39 | static const CodeMsgPair FAIL_SEND_REQHISTDATA(527, "Request Historical Data Sending Error - "); 40 | static const CodeMsgPair FAIL_SEND_CANHISTDATA(528, "Cancel Historical Data Sending Error - "); 41 | static const CodeMsgPair FAIL_SEND_REQRTBARS(529, "Request Real-time Bar Data Sending Error - "); 42 | static const CodeMsgPair FAIL_SEND_CANRTBARS(530, "Cancel Real-time Bar Data Sending Error - "); 43 | static const CodeMsgPair FAIL_SEND_REQCURRTIME(531, "Request Current Time Sending Error - "); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /IB/shared/shared_ptr.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #ifndef shared_ptr_h_INCLUDED 5 | #define shared_ptr_h_INCLUDED 6 | 7 | // 8 | // Implements a subset of shared_prt found at www.boost.org. 9 | // Uses a singly linked circular list instead of a reference counter. 10 | // Avoids extra heap allocation needed to get a shared reference counter, 11 | // but sizeof(shared_ptr) == sizeof(void*) * 3 compared to sizeof(void*) * 2 12 | // 13 | // See "Handles and Exception Safety, Part 4: Tracking References without Counters" 14 | // by Andrew Koenig and Barbara E. Moo, Feb. 2003 C++ Users Journal 15 | // 16 | namespace shared_ptr_defs { 17 | 18 | class Use { 19 | public: 20 | 21 | Use() { forward_ = this; back_ = this; } 22 | ~Use() { remove(); } 23 | 24 | Use(const Use& u) { insert(u); } 25 | Use& operator=(const Use& u) 26 | { 27 | if (this != &u) { 28 | remove(); 29 | insert(u); 30 | } 31 | return *this; 32 | } 33 | bool only() const { return this == this->forward_; } 34 | private: 35 | mutable const Use *forward_; 36 | mutable const Use *back_; 37 | 38 | void insert(const Use& u) const { 39 | this->back_ = &u; 40 | this->forward_ = u.forward_; 41 | u.forward_->back_ = this; 42 | u.forward_ = this; 43 | } 44 | 45 | void remove() const { 46 | this->forward_->back_ = this->back_; 47 | this->back_->forward_ = this->forward_; 48 | } 49 | }; 50 | 51 | } // end of namespace shared_ptr_defs 52 | 53 | template class shared_ptr { 54 | public: 55 | 56 | typedef shared_ptr_defs::Use Use; 57 | 58 | template friend class shared_ptr; 59 | 60 | explicit shared_ptr(X* ptr = 0) : ptr_(ptr) {} 61 | 62 | ~shared_ptr() { if (use_.only()) delete ptr_; } 63 | 64 | template 65 | shared_ptr(const shared_ptr& other) 66 | : ptr_(other.ptr_), 67 | use_(other.use_) 68 | {} 69 | 70 | shared_ptr& operator=(const shared_ptr& other) { 71 | if ( &use_ == &other.use_ ) { return *this; } 72 | if ( use_.only() ) { delete ptr_; } 73 | use_ = other.use_; 74 | ptr_ = other.ptr_; 75 | return *this; 76 | } 77 | 78 | X& operator*() const { return *ptr_; } 79 | X* operator->() const { return ptr_; } 80 | operator bool() const { return ptr_ != 0; } 81 | X* get() const { return ptr_; } 82 | bool only() const { return use_.only(); } 83 | 84 | void reset(X* ptr = 0) { 85 | if ( use_.only() ) { delete ptr_; } 86 | ptr_ = ptr; 87 | use_ = Use(); 88 | } 89 | 90 | private: 91 | 92 | X *ptr_; 93 | Use use_; 94 | }; 95 | 96 | #endif /* shared_ptr_h_INCLUDED */ 97 | -------------------------------------------------------------------------------- /IB/src/EClientSocketBase.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #include "EClientSocketBaseImpl.h" 5 | 6 | -------------------------------------------------------------------------------- /IB/src/EPosixClientSocket.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #include "EPosixClientSocket.h" 5 | 6 | #include "EPosixClientSocketPlatform.h" 7 | #include "TwsSocketClientErrors.h" 8 | #include "EWrapper.h" 9 | 10 | #include 11 | 12 | /////////////////////////////////////////////////////////// 13 | // member funcs 14 | EPosixClientSocket::EPosixClientSocket( EWrapper *ptr) : EClientSocketBase( ptr) 15 | { 16 | m_fd = -1; 17 | } 18 | 19 | EPosixClientSocket::~EPosixClientSocket() 20 | { 21 | } 22 | 23 | bool EPosixClientSocket::eConnect( const char *host, unsigned int port, int clientId, bool extraAuth) 24 | { 25 | // reset errno 26 | errno = 0; 27 | 28 | // already connected? 29 | if( m_fd >= 0) { 30 | errno = EISCONN; 31 | getWrapper()->error( NO_VALID_ID, ALREADY_CONNECTED.code(), ALREADY_CONNECTED.msg()); 32 | return false; 33 | } 34 | 35 | // initialize Winsock DLL (only for Windows) 36 | if ( !SocketsInit()) { 37 | return false; 38 | } 39 | 40 | // create socket 41 | m_fd = socket(AF_INET, SOCK_STREAM, 0); 42 | 43 | // cannot create socket 44 | if( m_fd < 0) { 45 | // uninitialize Winsock DLL (only for Windows) 46 | SocketsDestroy(); 47 | getWrapper()->error( NO_VALID_ID, FAIL_CREATE_SOCK.code(), FAIL_CREATE_SOCK.msg()); 48 | return false; 49 | } 50 | 51 | // use local machine if no host passed in 52 | if ( !( host && *host)) { 53 | host = "127.0.0.1"; 54 | } 55 | 56 | // starting to connect to server 57 | struct sockaddr_in sa; 58 | memset( &sa, 0, sizeof(sa)); 59 | sa.sin_family = AF_INET; 60 | sa.sin_port = htons( port); 61 | sa.sin_addr.s_addr = inet_addr( host); 62 | 63 | // try to connect 64 | if( (connect( m_fd, (struct sockaddr *) &sa, sizeof( sa))) < 0) { 65 | // error connecting 66 | SocketClose( m_fd); 67 | m_fd = -1; 68 | // uninitialize Winsock DLL (only for Windows) 69 | SocketsDestroy(); 70 | getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg()); 71 | return false; 72 | } 73 | 74 | // set client id 75 | setClientId( clientId); 76 | setExtraAuth( extraAuth); 77 | 78 | onConnectBase(); 79 | 80 | while( isSocketOK() && !isConnected()) { 81 | if ( !checkMessages()) { 82 | // uninitialize Winsock DLL (only for Windows) 83 | SocketsDestroy(); 84 | getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg()); 85 | return false; 86 | } 87 | } 88 | 89 | 90 | // set socket to non-blocking state 91 | if ( !SetSocketNonBlocking(m_fd)){ 92 | // error setting socket to non-blocking 93 | SocketsDestroy(); 94 | getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg()); 95 | return false; 96 | } 97 | 98 | // successfully connected 99 | return true; 100 | } 101 | 102 | void EPosixClientSocket::eDisconnect() 103 | { 104 | if ( m_fd >= 0 ) 105 | // close socket 106 | SocketClose( m_fd); 107 | m_fd = -1; 108 | // uninitialize Winsock DLL (only for Windows) 109 | SocketsDestroy(); 110 | eDisconnectBase(); 111 | } 112 | 113 | bool EPosixClientSocket::isSocketOK() const 114 | { 115 | return ( m_fd >= 0); 116 | } 117 | 118 | int EPosixClientSocket::fd() const 119 | { 120 | return m_fd; 121 | } 122 | 123 | int EPosixClientSocket::send(const char* buf, size_t sz) 124 | { 125 | if( sz <= 0) 126 | return 0; 127 | 128 | int nResult = ::send( m_fd, buf, sz, 0); 129 | 130 | if( nResult == -1 && !handleSocketError()) { 131 | return -1; 132 | } 133 | if( nResult <= 0) { 134 | return 0; 135 | } 136 | return nResult; 137 | } 138 | 139 | int EPosixClientSocket::receive(char* buf, size_t sz) 140 | { 141 | if( sz <= 0) 142 | return 0; 143 | 144 | int nResult = ::recv( m_fd, buf, sz, 0); 145 | 146 | if( nResult == -1 && !handleSocketError()) { 147 | return -1; 148 | } 149 | if( nResult <= 0) { 150 | return 0; 151 | } 152 | return nResult; 153 | } 154 | 155 | /////////////////////////////////////////////////////////// 156 | // callbacks from socket 157 | 158 | void EPosixClientSocket::onConnect() 159 | { 160 | if( !handleSocketError()) 161 | return; 162 | 163 | onConnectBase(); 164 | } 165 | 166 | void EPosixClientSocket::onReceive() 167 | { 168 | if( !handleSocketError()) 169 | return; 170 | 171 | checkMessages(); 172 | } 173 | 174 | void EPosixClientSocket::onSend() 175 | { 176 | if( !handleSocketError()) 177 | return; 178 | 179 | sendBufferedData(); 180 | } 181 | 182 | void EPosixClientSocket::onClose() 183 | { 184 | if( !handleSocketError()) 185 | return; 186 | 187 | eDisconnect(); 188 | getWrapper()->connectionClosed(); 189 | } 190 | 191 | void EPosixClientSocket::onError() 192 | { 193 | handleSocketError(); 194 | } 195 | 196 | /////////////////////////////////////////////////////////// 197 | // helper 198 | bool EPosixClientSocket::handleSocketError() 199 | { 200 | // no error 201 | if( errno == 0) 202 | return true; 203 | 204 | // Socket is already connected 205 | if( errno == EISCONN) { 206 | return true; 207 | } 208 | 209 | if( errno == EWOULDBLOCK) 210 | return false; 211 | 212 | if( errno == ECONNREFUSED) { 213 | getWrapper()->error( NO_VALID_ID, CONNECT_FAIL.code(), CONNECT_FAIL.msg()); 214 | } 215 | else { 216 | getWrapper()->error( NO_VALID_ID, SOCKET_EXCEPTION.code(), 217 | SOCKET_EXCEPTION.msg() + strerror(errno)); 218 | } 219 | // reset errno 220 | errno = 0; 221 | eDisconnect(); 222 | return false; 223 | } 224 | -------------------------------------------------------------------------------- /IB/src/EPosixClientSocket.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #ifndef eposixclientsocket_def 5 | #define eposixclientsocket_def 6 | 7 | #include "EClientSocketBase.h" 8 | 9 | class EWrapper; 10 | 11 | class EPosixClientSocket : public EClientSocketBase 12 | { 13 | public: 14 | 15 | explicit EPosixClientSocket( EWrapper *ptr); 16 | ~EPosixClientSocket(); 17 | 18 | // override virtual funcs from EClient 19 | bool eConnect( const char *host, unsigned int port, int clientId = 0, bool extraAuth = false); 20 | void eDisconnect(); 21 | 22 | bool isSocketOK() const; 23 | int fd() const; 24 | 25 | private: 26 | 27 | int send( const char* buf, size_t sz); 28 | int receive( char* buf, size_t sz); 29 | 30 | public: 31 | // callback from socket 32 | void onReceive(); 33 | void onSend(); 34 | void onError(); 35 | 36 | private: 37 | 38 | void onConnect(); 39 | void onClose(); 40 | 41 | public: 42 | // helper 43 | bool handleSocketError(); 44 | 45 | private: 46 | 47 | int m_fd; 48 | }; 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /IB/src/EPosixClientSocketPlatform.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2013 Interactive Brokers LLC. All rights reserved. This code is subject to the terms 2 | * and conditions of the IB API Non-Commercial License or the IB API Commercial License, as applicable. */ 3 | 4 | #ifndef eposixclientsocketcommon_def 5 | #define eposixclientsocketcommon_def 6 | 7 | #ifdef _WIN32 8 | // Windows 9 | // includes 10 | #include 11 | #include 12 | 13 | // defines 14 | #define EISCONN WSAEISCONN 15 | #define EWOULDBLOCK WSAEWOULDBLOCK 16 | #define ECONNREFUSED WSAECONNREFUSED 17 | 18 | // helpers 19 | inline bool SocketsInit( void) { 20 | WSADATA data; 21 | return ( !WSAStartup( MAKEWORD(2, 2), &data)); 22 | }; 23 | inline bool SocketsDestroy() { return ( !WSACleanup()); }; 24 | inline int SocketClose(int sockfd) { return closesocket( sockfd); }; 25 | 26 | inline bool SetSocketNonBlocking(int sockfd) { 27 | unsigned long mode = 1; 28 | return ( ioctlsocket( sockfd, FIONBIO, &mode) == 0); 29 | }; 30 | 31 | #else 32 | // LINUX 33 | // includes 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | 40 | // helpers 41 | inline bool SocketsInit() { return true; }; 42 | inline bool SocketsDestroy() { return true; }; 43 | inline int SocketClose(int sockfd) { return close( sockfd); }; 44 | 45 | inline bool SetSocketNonBlocking(int sockfd) { 46 | // get socket flags 47 | int flags = fcntl(sockfd, F_GETFL); 48 | if (flags == -1) 49 | return false; 50 | 51 | // set non-blocking mode 52 | return ( fcntl(sockfd, F_SETFL, flags | O_NONBLOCK) == 0); 53 | }; 54 | 55 | #endif 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /IB/swig_wrap.h: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------------- 2 | * This file was automatically generated by SWIG (http://www.swig.org). 3 | * Version 3.0.7 4 | * 5 | * This file is not intended to be easily readable and contains a number of 6 | * coding conventions designed to improve portability and efficiency. Do not make 7 | * changes to this file unless you know what you are doing--modify the SWIG 8 | * interface file instead. 9 | * ----------------------------------------------------------------------------- */ 10 | 11 | #ifndef SWIG_swigibpy_WRAP_H_ 12 | #define SWIG_swigibpy_WRAP_H_ 13 | 14 | #include 15 | #include 16 | 17 | 18 | class SwigDirector_EWrapper : public EWrapper, public Swig::Director { 19 | 20 | public: 21 | SwigDirector_EWrapper(PyObject *self); 22 | virtual ~SwigDirector_EWrapper(); 23 | virtual void tickPrice(TickerId tickerId, TickType field, double price, int canAutoExecute); 24 | virtual void tickSize(TickerId tickerId, TickType field, int size); 25 | virtual void tickOptionComputation(TickerId tickerId, TickType tickType, double impliedVol, double delta, double optPrice, double pvDividend, double gamma, double vega, double theta, double undPrice); 26 | virtual void tickGeneric(TickerId tickerId, TickType tickType, double value); 27 | virtual void tickString(TickerId tickerId, TickType tickType, IBString const &value); 28 | virtual void tickEFP(TickerId tickerId, TickType tickType, double basisPoints, IBString const &formattedBasisPoints, double totalDividends, int holdDays, IBString const &futureExpiry, double dividendImpact, double dividendsToExpiry); 29 | virtual void orderStatus(OrderId orderId, IBString const &status, int filled, int remaining, double avgFillPrice, int permId, int parentId, double lastFillPrice, int clientId, IBString const &whyHeld); 30 | virtual void openOrder(OrderId orderId, Contract const &arg0, Order const &arg1, OrderState const &arg2); 31 | virtual void openOrderEnd(); 32 | virtual void winError(IBString const &str, int lastError); 33 | virtual void connectionClosed(); 34 | virtual void updateAccountValue(IBString const &key, IBString const &val, IBString const ¤cy, IBString const &accountName); 35 | virtual void updatePortfolio(Contract const &contract, int position, double marketPrice, double marketValue, double averageCost, double unrealizedPNL, double realizedPNL, IBString const &accountName); 36 | virtual void updateAccountTime(IBString const &timeStamp); 37 | virtual void accountDownloadEnd(IBString const &accountName); 38 | virtual void nextValidId(OrderId orderId); 39 | virtual void contractDetails(int reqId, ContractDetails const &contractDetails); 40 | virtual void bondContractDetails(int reqId, ContractDetails const &contractDetails); 41 | virtual void contractDetailsEnd(int reqId); 42 | virtual void execDetails(int reqId, Contract const &contract, Execution const &execution); 43 | virtual void execDetailsEnd(int reqId); 44 | virtual void error(int const id, int const errorCode, IBString const errorString); 45 | virtual void updateMktDepth(TickerId id, int position, int operation, int side, double price, int size); 46 | virtual void updateMktDepthL2(TickerId id, int position, IBString marketMaker, int operation, int side, double price, int size); 47 | virtual void updateNewsBulletin(int msgId, int msgType, IBString const &newsMessage, IBString const &originExch); 48 | virtual void managedAccounts(IBString const &accountsList); 49 | virtual void receiveFA(faDataType pFaDataType, IBString const &cxml); 50 | virtual void historicalData(TickerId reqId, IBString const &date, double open, double high, double low, double close, int volume, int barCount, double WAP, int hasGaps); 51 | virtual void scannerParameters(IBString const &xml); 52 | virtual void scannerData(int reqId, int rank, ContractDetails const &contractDetails, IBString const &distance, IBString const &benchmark, IBString const &projection, IBString const &legsStr); 53 | virtual void scannerDataEnd(int reqId); 54 | virtual void realtimeBar(TickerId reqId, long time, double open, double high, double low, double close, long volume, double wap, int count); 55 | virtual void currentTime(long time); 56 | virtual void fundamentalData(TickerId reqId, IBString const &data); 57 | virtual void deltaNeutralValidation(int reqId, UnderComp const &underComp); 58 | virtual void tickSnapshotEnd(int reqId); 59 | virtual void marketDataType(TickerId reqId, int marketDataType); 60 | virtual void commissionReport(CommissionReport const &commissionReport); 61 | virtual void position(IBString const &account, Contract const &contract, int position, double avgCost); 62 | virtual void positionEnd(); 63 | virtual void accountSummary(int reqId, IBString const &account, IBString const &tag, IBString const &value, IBString const &curency); 64 | virtual void accountSummaryEnd(int reqId); 65 | virtual void verifyMessageAPI(IBString const &apiData); 66 | virtual void verifyCompleted(bool isSuccessful, IBString const &errorText); 67 | virtual void displayGroupList(int reqId, IBString const &groups); 68 | virtual void displayGroupUpdated(int reqId, IBString const &contractInfo); 69 | 70 | /* Internal director utilities */ 71 | public: 72 | bool swig_get_inner(const char *swig_protected_method_name) const { 73 | std::map::const_iterator iv = swig_inner.find(swig_protected_method_name); 74 | return (iv != swig_inner.end() ? iv->second : false); 75 | } 76 | void swig_set_inner(const char *swig_protected_method_name, bool swig_val) const { 77 | swig_inner[swig_protected_method_name] = swig_val; 78 | } 79 | private: 80 | mutable std::map swig_inner; 81 | 82 | #if defined(SWIG_PYTHON_DIRECTOR_VTABLE) 83 | /* VTable implementation */ 84 | PyObject *swig_get_method(size_t method_index, const char *method_name) const { 85 | PyObject *method = vtable[method_index]; 86 | if (!method) { 87 | swig::SwigVar_PyObject name = SWIG_Python_str_FromChar(method_name); 88 | method = PyObject_GetAttr(swig_get_self(), name); 89 | if (!method) { 90 | std::string msg = "Method in class EWrapper doesn't exist, undefined "; 91 | msg += method_name; 92 | Swig::DirectorMethodException::raise(msg.c_str()); 93 | } 94 | vtable[method_index] = method; 95 | } 96 | return method; 97 | } 98 | private: 99 | mutable swig::SwigVar_PyObject vtable[46]; 100 | #endif 101 | 102 | }; 103 | 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011-2015, Kieran O'Mahony 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | Neither the name of Kieran O'Mahony nor the names of contributors 15 | may be used to endorse or promote products derived from this software 16 | without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 28 | THE POSSIBILITY OF SUCH DAMAGE. 29 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include *.py 2 | include *.i 3 | include examples/*.py 4 | include IB/*/*.cpp 5 | include IB/*/*.h 6 | include IB/*.cpp 7 | include IB/*.h 8 | include IB/*.txt 9 | include patches/* 10 | include README.rst 11 | include CHANGELOG.md 12 | include LICENSE 13 | include MANIFEST.in 14 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | swigibpy 2 | ======== 3 | 4 | :version: 0.5.0 5 | 6 | An `Interactive Brokers`_ Python API, auto-generated from the official C++ API 7 | using `SWIG`_. 8 | 9 | Installation 10 | ============ 11 | 12 | Use pip (recommended) 13 | 14 | .. code:: sh 15 | 16 | pip install swigibpy 17 | 18 | Alternatively download `a release`_, extract it and run 19 | 20 | .. code:: sh 21 | 22 | python setup.py install 23 | 24 | Getting Started 25 | =============== 26 | 27 | TWS or IB Gateway must be running. To use **swigibpy** simply import the 28 | ``swigibpy`` module into your code, define an ``EWrapper`` sub-class and create 29 | a ``swigibpy.EPosixClientSocket`` instance. 30 | 31 | Use the methods of your ``swigibpy.EPosixClientSocket`` instance to send 32 | requests to Interactive Brokers. All requests are asynchronous and any 33 | responses, notifications and warnings are handled by the methods of your 34 | ``EWrapper`` subclass. 35 | 36 | In the following simple example a request is made to Interactive Brokers for 37 | some historical data for the GOOG ticker, and the response is printed to the 38 | console. 39 | 40 | .. code:: python 41 | 42 | from datetime import datetime 43 | 44 | import swigibpy 45 | 46 | 47 | class MyEWrapper(swigibpy.EWrapperVerbose): 48 | 49 | def historicalData(self, reqId, date, open, high, low, close, volume, 50 | barCount, WAP, hasGaps): 51 | 52 | if date[:8] == 'finished': 53 | print("History request complete") 54 | else: 55 | date = datetime.strptime(date, "%Y%m%d").strftime("%d %b %Y") 56 | print(("History %s - Open: %s, High: %s, Low: %s, Close: " 57 | "%s, Volume: %d") % (date, open, high, low, close, volume)) 58 | 59 | myWrapper = MyEWrapper() 60 | 61 | tws = swigibpy.EPosixClientSocket(myWrapper, reconnect_auto=True) 62 | 63 | tws.eConnect("", 7496, 42) 64 | 65 | contract = swigibpy.Contract() 66 | contract.exchange = "SMART" 67 | contract.symbol = "GOOG" 68 | contract.secType = "STK" 69 | contract.currency = "USD" 70 | today = datetime.today() 71 | 72 | tws.reqHistoricalData(2, contract, today.strftime("%Y%m%d %H:%M:%S %Z"), 73 | "1 W", "1 day", "TRADES", 0, 1, None) 74 | 75 | 76 | 77 | See the `examples`_ for some more simple demos of using **swigibpy**. For a 78 | more in-depth introduction Rob Carver has written a nice series of blog posts 79 | on `getting started with swigibpy and the Interative Brokers API`_. 80 | 81 | For documentation on the methods of ``EPosixClientSocket``, ``EWrapper`` and 82 | other API reference refer to the `C++ API documentation`_. 83 | 84 | Note that unlike the C++ API **swigibpy** will automatically poll 85 | TWS for messages, see `Message Polling`_ for more about this. 86 | 87 | Error Handling 88 | -------------- 89 | 90 | If TWS reports an error then the ``EWrapper`` methods ``error`` and 91 | ``winError`` will be called as described in the TWS `C++ API documentation`_. 92 | 93 | Additionally **swigibpy** augments ``EWrapper`` with an extra error handling 94 | method. 95 | 96 | .. code:: python 97 | 98 | def pyError(self, type, value, traceback) 99 | 100 | which will be called if an exception is raised during execution of one of your 101 | ``EWrapper`` Python methods. The default behaviour is to print the exception to 102 | standard error, but you can override the ``pyError`` method to implement your own 103 | handling. See the `python docs for sys.exc_info()`_ for details on the 104 | method's arguments. 105 | 106 | EWrapper Utility Classes 107 | ------------------------ 108 | 109 | Normally subclassing ``EWrapper`` means having to tiresomely provide an 110 | implementation for every method defined by ``EWrapper``. Happily **swigibpy** 111 | adds two ``EWrapper`` subclasses which can help. 112 | 113 | ``EWrapperVerbose`` implements every ``EWrapper`` method and by default just 114 | prints a message to standard out every time one of its methods is invoked. The 115 | message printed includes the arguments that were passed. Useful for development 116 | and debugging. 117 | 118 | ``EWrapperQuiet`` implements every ``EWrapper`` method and silently ignores 119 | any calls that have not been implemented by you. Useful if you are not 120 | interested in defining every ``EWrapper`` method. 121 | 122 | Auto-reconnect 123 | -------------- 124 | 125 | **swigibpy** can automatically reconnect to TWS / IB Gateway in case of 126 | connection loss or restart. To enable this behaviour use the ``reconnect_auto`` 127 | argument added to ``EPosixClientSocket``. 128 | 129 | .. code:: python 130 | 131 | tws = EPosixClientSocket(mywrapper, reconnect_auto=True) 132 | 133 | Auto-reconnect is disabled by default. 134 | 135 | Notes 136 | ----- 137 | 138 | The ``yield`` parameter in ``CommissionReport`` clashes with a Python reserved 139 | keyword so it is renamed to ``_yield``. 140 | 141 | Advanced Usage 142 | -------------- 143 | 144 | Message Polling 145 | +++++++++++++++ 146 | 147 | By default **swigibpy** will create a background thread (``swigibpy.TWSPoller``) 148 | to automatically poll TWS for messages. If you wish to disable this behaviour 149 | and handle polling yourself use the ``poll_auto`` argument added to 150 | ``EPosixClientSocket`` 151 | 152 | .. code:: python 153 | 154 | tws = EPosixClientSocket(mywrapper, poll_auto=False) 155 | 156 | or 157 | 158 | .. code:: python 159 | 160 | tws = EPosixClientSocket(mywrapper) 161 | ... 162 | tws.poll_auto = False 163 | 164 | The TWS C++ API performs non-blocking socket I/O to communicate with TWS, 165 | **swigibpy**'s background thread uses socket select to poll for incoming messages. 166 | 167 | 168 | Patches 169 | +++++++ 170 | 171 | Apart from a few trivial `patches`_ to aid compilation and interoperability 172 | with Python **swigibpy** does not alter the TWS C++ API code in any way. 173 | 174 | Contribute 175 | ========== 176 | 177 | **swigibpy** is open source so feel free to get involved. If something doesn't 178 | work, or you'd like to add a feature, example or some documentation please 179 | `create a pull request`_, if you need help `open an issue`_. 180 | 181 | For development switch to the swigibpy code directory and build the extension 182 | in the current dir. 183 | 184 | .. code:: sh 185 | 186 | python setup.py build_ext --inplace 187 | 188 | Apart from the `patches`_ all of **swigibpy**'s code is defined in a SWIG 189 | `interface file`_. The C++ and Python wrapper is then generated using SWIG. 190 | 191 | The TWS API included in the repository has already been patched and the 192 | repository already includes the SWIG generated code but if you modify the 193 | interface file or need to rerun these steps the commands are 194 | 195 | .. code:: sh 196 | 197 | python setup.py swigify 198 | 199 | to regenerate the SWIG wrappers (SWIG 3.0+ required), and 200 | 201 | .. code:: sh 202 | 203 | python setup.py patchify 204 | 205 | to reapply the patches to the TWS API (specify the option ``-r`` if you want to 206 | un-apply the patches and get back to unaltered TWS code). 207 | 208 | Windows Users 209 | ============= 210 | 211 | **swigibpy** provides a wrapper around the TWS C++ API so it must be 212 | compiled for your target platform during installation. While this should 213 | 'just work' for Linux and OSX, Windows users might need to do some extra work. 214 | 215 | Only some basic tips are given here, for more see `Installing Python Modules`_ 216 | in the official documentation. 217 | 218 | MinGW Compilation 219 | ----------------- 220 | 221 | Download and install `MinGW`_ and follow the steps to `add MinGW 222 | to your path`_. 223 | 224 | To get pip to use MinGW as the compiler edit or create a 225 | file named ``distutils.cfg`` in ``[PYTHON LOCATION]\Lib\distutils`` where 226 | ``[PYTHON LOCATION]`` is the path to your Python install, e.g. ``C:\Python27``. 227 | Add the following to ``distutils.cfg``. 228 | 229 | .. code:: cfg 230 | 231 | [build] 232 | compiler=mingw32 233 | 234 | then use the pip command given above in `Installation`_ and with a bit of luck, 235 | you're done! 236 | 237 | Alternatively you can download `a release`_ and build the package directly. To 238 | build and install manually use 239 | 240 | .. code:: sh 241 | 242 | python setup.py build -c mingw32 243 | python setup.py install 244 | 245 | This has been verified to work using MinGW and Python 2.7 on Windows 7, Vista, 246 | and XP. 247 | 248 | Visual Studio Compilation 249 | ------------------------- 250 | 251 | Several users have reported success building **swigibpy** with Visual Studio, 252 | with a few caveats: 253 | 254 | * Distutils has issues building with anything later than Visual Studio 2008 255 | (version 9). 256 | * Visual Studio 11 doesn't like the ``/MD`` compile flag, which distutils adds. 257 | For a workaround see `here`_. 258 | 259 | License 260 | ======= 261 | 262 | **swigibpy** original code is free software under the `New BSD license`_. 263 | 264 | Interactive Brokers propriety C++ API is copyright Interactive Brokers LLC. 265 | **swigibpy** is in no way supported or endorsed by Interactive Brokers LLC. 266 | 267 | -------------- 268 | 269 | .. _Interactive Brokers: http://www.interactivebrokers.com/ 270 | .. _SWIG: http://www.swig.org/ 271 | .. _a release: https://github.com/Komnomnomnom/swigibpy/releases 272 | .. _C++ API documentation: http://www.interactivebrokers.com/en/software/api/api.htm 273 | .. _MinGW: http://www.mingw.org/ 274 | .. _add MinGW to your path: http://www.mingw.org/wiki/Getting_Started#toc7 275 | .. _here: https://github.com/Komnomnomnom/swigibpy/issues/2 276 | .. _patches: https://github.com/Komnomnomnom/swigibpy/tree/master/patches 277 | .. _examples: https://github.com/Komnomnomnom/swigibpy/tree/master/examples 278 | .. _getting started with swigibpy and the Interative Brokers API: http://qoppac.blogspot.co.uk/2014/03/using-swigibpy-so-that-python-will-play.html 279 | .. _python docs for sys.exc_info(): https://docs.python.org/2/library/sys.html#sys.exc_info 280 | .. _open an issue: https://github.com/Komnomnomnom/swigibpy/issues 281 | .. _create a pull request: https://github.com/Komnomnomnom/swigibpy/pulls 282 | .. _Installing Python Modules: https://docs.python.org/2/install/ 283 | .. _New BSD License: https://github.com/Komnomnomnom/swigibpy/blob/master/LICENSE 284 | .. _interface file: https://github.com/Komnomnomnom/swigibpy/blob/master/swigify_ib.i 285 | -------------------------------------------------------------------------------- /examples/contractdetails.py: -------------------------------------------------------------------------------- 1 | '''Simple example of requesting using the SWIG generated TWS wrapper to 2 | request contract details from Interactive Brokers. 3 | 4 | ''' 5 | 6 | from datetime import datetime 7 | from threading import Event 8 | 9 | from swigibpy import EWrapper, EPosixClientSocket, Contract 10 | 11 | 12 | WAIT_TIME = 10.0 13 | 14 | 15 | ### 16 | 17 | 18 | class ContractDetailsExample(EWrapper): 19 | '''Callback object passed to TWS, these functions will be called directly 20 | by TWS. 21 | 22 | ''' 23 | 24 | def __init__(self): 25 | super(ContractDetailsExample, self).__init__() 26 | self.got_contract = Event() 27 | 28 | def orderStatus(self, id, status, filled, remaining, avgFillPrice, permId, 29 | parentId, lastFilledPrice, clientId, whyHeld): 30 | pass 31 | 32 | def openOrder(self, orderID, contract, order, orderState): 33 | pass 34 | 35 | def nextValidId(self, orderId): 36 | '''Always called by TWS but not relevant for our example''' 37 | pass 38 | 39 | def openOrderEnd(self): 40 | '''Always called by TWS but not relevant for our example''' 41 | pass 42 | 43 | def managedAccounts(self, openOrderEnd): 44 | '''Called by TWS but not relevant for our example''' 45 | pass 46 | 47 | def contractDetailsEnd(self, reqId): 48 | print("Contract details request complete, (request id %i)" % reqId) 49 | 50 | def contractDetails(self, reqId, contractDetails): 51 | print("Contract details received (request id %i):" % reqId) 52 | print("callable: %s" % contractDetails.callable) 53 | print("category: %s" % contractDetails.category) 54 | print("contractMonth: %s" % contractDetails.contractMonth) 55 | print("convertible: %s" % contractDetails.convertible) 56 | print("coupon: %s" % contractDetails.coupon) 57 | print("industry: %s" % contractDetails.industry) 58 | print("liquidHours: %s" % contractDetails.liquidHours) 59 | print("longName: %s" % contractDetails.longName) 60 | print("marketName: %s" % contractDetails.marketName) 61 | print("minTick: %s" % contractDetails.minTick) 62 | print("nextOptionPartial: %s" % contractDetails.nextOptionPartial) 63 | print("orderTypes: %s" % contractDetails.orderTypes) 64 | print("priceMagnifier: %s" % contractDetails.priceMagnifier) 65 | print("putable: %s" % contractDetails.putable) 66 | if contractDetails.secIdList is not None: 67 | for secId in contractDetails.secIdList: 68 | print("secIdList: %s" % secId) 69 | else: 70 | print("secIdList: None") 71 | 72 | print("subcategory: %s" % contractDetails.subcategory) 73 | print("tradingHours: %s" % contractDetails.tradingHours) 74 | print("timeZoneId: %s" % contractDetails.timeZoneId) 75 | print("underConId: %s" % contractDetails.underConId) 76 | print("evRule: %s" % contractDetails.evRule) 77 | print("evMultiplier: %s" % contractDetails.evMultiplier) 78 | 79 | contract = contractDetails.summary 80 | 81 | print("\nContract Summary:") 82 | print("exchange: %s" % contract.exchange) 83 | print("symbol: %s" % contract.symbol) 84 | print("secType: %s" % contract.secType) 85 | print("currency: %s" % contract.currency) 86 | print("tradingClass: %s" % contract.tradingClass) 87 | if contract.comboLegs is not None: 88 | for comboLeg in contract.comboLegs: 89 | print("comboLegs: %s - %s" % 90 | (comboLeg.action, comboLeg.exchange)) 91 | else: 92 | print("comboLegs: None") 93 | 94 | print("\nBond Values:") 95 | print("bondType: %s" % contractDetails.bondType) 96 | print("couponType: %s" % contractDetails.couponType) 97 | print("cusip: %s" % contractDetails.cusip) 98 | print("descAppend: %s" % contractDetails.descAppend) 99 | print("issueDate: %s" % contractDetails.issueDate) 100 | print("maturity: %s" % contractDetails.maturity) 101 | print("nextOptionDate: %s" % contractDetails.nextOptionDate) 102 | print("nextOptionType: %s" % contractDetails.nextOptionType) 103 | print("notes: %s" % contractDetails.notes) 104 | print("ratings: %s" % contractDetails.ratings) 105 | print("validExchanges: %s" % contractDetails.validExchanges) 106 | 107 | self.got_contract.set() 108 | 109 | 110 | # Instantiate our callback object 111 | callback = ContractDetailsExample() 112 | 113 | # Instantiate a socket object, allowing us to call TWS directly. Pass our 114 | # callback object so TWS can respond. 115 | tws = EPosixClientSocket(callback) 116 | 117 | # Connect to tws running on localhost 118 | if not tws.eConnect("", 7496, 42): 119 | raise RuntimeError('Failed to connect to TWS') 120 | 121 | # Simple contract for GOOG 122 | contract = Contract() 123 | contract.exchange = "SMART" 124 | contract.symbol = "GOOG" 125 | contract.secType = "STK" 126 | contract.currency = "USD" 127 | today = datetime.today() 128 | 129 | print("Requesting contract details...") 130 | 131 | # Perform the request 132 | tws.reqContractDetails( 133 | 42, # reqId, 134 | contract, # contract, 135 | ) 136 | 137 | print("\n====================================================================") 138 | print(" Contract details requested, waiting %ds for TWS responses" % WAIT_TIME) 139 | print("====================================================================\n") 140 | 141 | 142 | try: 143 | callback.got_contract.wait(timeout=WAIT_TIME) 144 | except KeyboardInterrupt: 145 | pass 146 | finally: 147 | if not callback.got_contract.is_set(): 148 | print('Failed to get contract within %d seconds' % WAIT_TIME) 149 | 150 | print("\nDisconnecting...") 151 | tws.eDisconnect() 152 | -------------------------------------------------------------------------------- /examples/customerror.py: -------------------------------------------------------------------------------- 1 | '''Simple example of using custom error hanlding with the SWIG generated TWS 2 | wrapper. 3 | 4 | Check http://www.interactivebrokers.com/en/software/api/api.htm -> 'Reference 5 | Tables' -> 'API Message Codes' for error codes and their interpretation. 6 | 7 | ''' 8 | 9 | import sys 10 | from datetime import datetime 11 | from threading import Event 12 | 13 | from swigibpy import EWrapper, EPosixClientSocket, Contract 14 | 15 | 16 | WAIT_TIME = 10.0 17 | 18 | 19 | ### 20 | 21 | 22 | class CustomErrorExample(EWrapper): 23 | '''Callback object passed to TWS, these functions will be called directly 24 | by TWS. 25 | 26 | ''' 27 | 28 | def __init__(self): 29 | super(CustomErrorExample, self).__init__() 30 | self.got_err = Event() 31 | 32 | def orderStatus(self, id, status, filled, remaining, avgFillPrice, permId, 33 | parentId, lastFilledPrice, clientId, whyHeld): 34 | pass 35 | 36 | def openOrder(self, orderID, contract, order, orderState): 37 | pass 38 | 39 | def nextValidId(self, orderId): 40 | '''Always called by TWS but not relevant for our example''' 41 | pass 42 | 43 | def openOrderEnd(self): 44 | '''Always called by TWS but not relevant for our example''' 45 | pass 46 | 47 | def managedAccounts(self, openOrderEnd): 48 | '''Called by TWS but not relevant for our example''' 49 | pass 50 | 51 | def historicalData(self, reqId, date, open, high, 52 | low, close, volume, 53 | barCount, WAP, hasGaps): 54 | 55 | pass 56 | 57 | def error(self, id, errCode, errString): 58 | 59 | if errCode == 165 or (errCode >= 2100 and errCode <= 2110): 60 | print("TWS warns %s" % errString) 61 | elif errCode == 502: 62 | print('Looks like TWS is not running, ' 63 | 'start it up and try again') 64 | sys.exit() 65 | elif errCode == 501: 66 | print("TWS reports error in client: %s" % errString) 67 | elif errCode >= 1100 and errCode < 2100: 68 | print("TWS reports system error: %s" % errString) 69 | elif errCode == 321: 70 | print("TWS complaining about bad request: %s" % errString) 71 | else: 72 | super(CustomErrorExample, self).error(id, errCode, errString) 73 | self.got_err.set() 74 | 75 | def winError(self, msg, lastError): 76 | print("TWS reports API error: %s" % msg) 77 | self.got_err.set() 78 | 79 | def pyError(self, type, val, tb): 80 | sys.print_exception(type, val, tb) 81 | 82 | 83 | # Instantiate our callback object 84 | callback = CustomErrorExample() 85 | 86 | # Instantiate a socket object, allowing us to call TWS directly. Pass our 87 | # callback object so TWS can respond. 88 | tws = EPosixClientSocket(callback) 89 | 90 | # Connect to tws running on localhost 91 | if not tws.eConnect("", 7496, 42): 92 | raise RuntimeError('Failed to connect to TWS') 93 | 94 | # Simple (badly formed) contract 95 | contract = Contract() 96 | contract.exchange = "SMART" 97 | contract.secType = "STK" 98 | today = datetime.today() 99 | 100 | print("Sending bad request for historical data") 101 | 102 | # Request some historical data. 103 | tws.reqHistoricalData( 104 | 2, # tickerId, 105 | contract, # contract, 106 | today.strftime("%Y%m%d %H:%M:%S %Z"), # endDateTime, 107 | "1 W", # durationStr, 108 | "1 day", # barSizeSetting, 109 | "TRADES", # whatToShow, 110 | 0, # useRTH, 111 | 1, # formatDate 112 | None # chartOptions 113 | ) 114 | 115 | print("\n====================================================================") 116 | print(" Waiting %ds for TWS responses" % WAIT_TIME) 117 | print("====================================================================\n") 118 | 119 | 120 | try: 121 | callback.got_err.wait(timeout=WAIT_TIME) 122 | except KeyboardInterrupt: 123 | pass 124 | finally: 125 | if not callback.got_err.is_set(): 126 | print('Failed to get response within %d seconds' % WAIT_TIME) 127 | 128 | print("\nDisconnecting...") 129 | tws.eDisconnect() 130 | -------------------------------------------------------------------------------- /examples/historicaldata.py: -------------------------------------------------------------------------------- 1 | '''Simple example of using the SWIG generated TWS wrapper to request historical 2 | data from interactive brokers. 3 | 4 | Note: 5 | * Communication with TWS is asynchronous; requests to TWS are made through the 6 | EPosixClientSocket class and TWS responds at some later time via the functions 7 | in our EWrapper subclass. 8 | * If you're using a demo account TWS will only respond with a limited time 9 | period, no matter what is requested. Also the data returned is probably wholly 10 | unreliable. 11 | 12 | ''' 13 | 14 | from datetime import datetime 15 | from threading import Event 16 | 17 | from swigibpy import EWrapper, EPosixClientSocket, Contract 18 | 19 | 20 | WAIT_TIME = 10.0 21 | 22 | ### 23 | 24 | 25 | class HistoricalDataExample(EWrapper): 26 | '''Callback object passed to TWS, these functions will be called directly 27 | by TWS. 28 | 29 | ''' 30 | 31 | def __init__(self): 32 | super(HistoricalDataExample, self).__init__() 33 | self.got_history = Event() 34 | 35 | def orderStatus(self, id, status, filled, remaining, avgFillPrice, permId, 36 | parentId, lastFilledPrice, clientId, whyHeld): 37 | pass 38 | 39 | def openOrder(self, orderID, contract, order, orderState): 40 | pass 41 | 42 | def nextValidId(self, orderId): 43 | '''Always called by TWS but not relevant for our example''' 44 | pass 45 | 46 | def openOrderEnd(self): 47 | '''Always called by TWS but not relevant for our example''' 48 | pass 49 | 50 | def managedAccounts(self, openOrderEnd): 51 | '''Called by TWS but not relevant for our example''' 52 | pass 53 | 54 | def historicalData(self, reqId, date, open, high, 55 | low, close, volume, 56 | barCount, WAP, hasGaps): 57 | 58 | if date[:8] == 'finished': 59 | print("History request complete") 60 | self.got_history.set() 61 | else: 62 | date = datetime.strptime(date, "%Y%m%d").strftime("%d %b %Y") 63 | print(("History %s - Open: %s, High: %s, Low: %s, Close: " 64 | "%s, Volume: %d") % (date, open, high, low, close, volume)) 65 | 66 | 67 | # Instantiate our callback object 68 | callback = HistoricalDataExample() 69 | 70 | # Instantiate a socket object, allowing us to call TWS directly. Pass our 71 | # callback object so TWS can respond. 72 | tws = EPosixClientSocket(callback, reconnect_auto=True) 73 | 74 | # Connect to tws running on localhost 75 | if not tws.eConnect("", 7496, 42): 76 | raise RuntimeError('Failed to connect to TWS') 77 | 78 | # Simple contract for GOOG 79 | contract = Contract() 80 | contract.exchange = "SMART" 81 | contract.symbol = "GOOG" 82 | contract.secType = "STK" 83 | contract.currency = "USD" 84 | today = datetime.today() 85 | 86 | print("Requesting historical data for %s" % contract.symbol) 87 | 88 | # Request some historical data. 89 | tws.reqHistoricalData( 90 | 2, # tickerId, 91 | contract, # contract, 92 | today.strftime("%Y%m%d %H:%M:%S %Z"), # endDateTime, 93 | "1 W", # durationStr, 94 | "1 day", # barSizeSetting, 95 | "TRADES", # whatToShow, 96 | 0, # useRTH, 97 | 1, # formatDate 98 | None # chartOptions 99 | ) 100 | 101 | print("\n====================================================================") 102 | print(" History requested, waiting %ds for TWS responses" % WAIT_TIME) 103 | print("====================================================================\n") 104 | 105 | 106 | try: 107 | callback.got_history.wait(timeout=WAIT_TIME) 108 | except KeyboardInterrupt: 109 | pass 110 | finally: 111 | if not callback.got_history.is_set(): 112 | print('Failed to get history within %d seconds' % WAIT_TIME) 113 | 114 | print("\nDisconnecting...") 115 | tws.eDisconnect() 116 | -------------------------------------------------------------------------------- /examples/placeorder.py: -------------------------------------------------------------------------------- 1 | '''Simple example of using the SWIG generated TWS wrapper to place an order 2 | with interactive brokers. 3 | 4 | ''' 5 | 6 | import sys 7 | from threading import Event 8 | 9 | from swigibpy import (EWrapper, EPosixClientSocket, Contract, Order, TagValue, 10 | TagValueList) 11 | 12 | 13 | WAIT_TIME = 10.0 14 | 15 | 16 | try: 17 | # Python 2 compatibility 18 | input = raw_input 19 | from Queue import Queue 20 | except: 21 | from queue import Queue 22 | 23 | ### 24 | 25 | 26 | class PlaceOrderExample(EWrapper): 27 | '''Callback object passed to TWS, these functions will be called directly 28 | by TWS. 29 | 30 | ''' 31 | 32 | def __init__(self): 33 | super(PlaceOrderExample, self).__init__() 34 | self.order_filled = Event() 35 | self.order_ids = Queue() 36 | 37 | def openOrderEnd(self): 38 | '''Not relevant for our example''' 39 | pass 40 | 41 | def execDetails(self, id, contract, execution): 42 | '''Not relevant for our example''' 43 | pass 44 | 45 | def managedAccounts(self, openOrderEnd): 46 | '''Not relevant for our example''' 47 | pass 48 | 49 | ############### 50 | 51 | def nextValidId(self, validOrderId): 52 | '''Capture the next order id''' 53 | self.order_ids.put(validOrderId) 54 | 55 | def orderStatus(self, id, status, filled, remaining, avgFillPrice, permId, 56 | parentId, lastFilledPrice, clientId, whyHeld): 57 | 58 | print(("Order #%s - %s (filled %d, remaining %d, avgFillPrice %f," 59 | "last fill price %f)") % 60 | (id, status, filled, remaining, avgFillPrice, lastFilledPrice)) 61 | if remaining <= 0: 62 | self.order_filled.set() 63 | 64 | def openOrder(self, orderID, contract, order, orderState): 65 | 66 | print("Order opened for %s" % contract.symbol) 67 | 68 | def commissionReport(self, commissionReport): 69 | print 'Commission %s %s P&L: %s' % (commissionReport.currency, 70 | commissionReport.commission, 71 | commissionReport.realizedPNL) 72 | 73 | prompt = input("WARNING: This example will place an order on your IB " 74 | "account, are you sure? (Type yes to continue): ") 75 | if prompt.lower() != 'yes': 76 | sys.exit() 77 | 78 | # Instantiate our callback object 79 | callback = PlaceOrderExample() 80 | 81 | # Instantiate a socket object, allowing us to call TWS directly. Pass our 82 | # callback object so TWS can respond. 83 | tws = EPosixClientSocket(callback) 84 | 85 | # Connect to tws running on localhost 86 | if not tws.eConnect("", 7496, 42): 87 | raise RuntimeError('Failed to connect to TWS') 88 | 89 | # Simple contract for GOOG 90 | contract = Contract() 91 | contract.symbol = "IBM" 92 | contract.secType = "STK" 93 | contract.exchange = "SMART" 94 | contract.currency = "USD" 95 | 96 | print('Waiting for valid order id') 97 | order_id = callback.order_ids.get(timeout=WAIT_TIME) 98 | if not order_id: 99 | raise RuntimeError('Failed to receive order id after %ds' % WAIT_TIME) 100 | 101 | # Order details 102 | algoParams = TagValueList() 103 | algoParams.append(TagValue("componentSize", "3")) 104 | algoParams.append(TagValue("timeBetweenOrders", "60")) 105 | algoParams.append(TagValue("randomizeTime20", "1")) 106 | algoParams.append(TagValue("randomizeSize55", "1")) 107 | algoParams.append(TagValue("giveUp", "1")) 108 | algoParams.append(TagValue("catchUp", "1")) 109 | algoParams.append(TagValue("waitForFill", "1")) 110 | algoParams.append(TagValue("startTime", "20110302-14:30:00 GMT")) 111 | algoParams.append(TagValue("endTime", "20110302-21:00:00 GMT")) 112 | 113 | order = Order() 114 | order.action = 'BUY' 115 | order.lmtPrice = 140 116 | order.orderType = 'LMT' 117 | order.totalQuantity = 10 118 | order.algoStrategy = "AD" 119 | order.tif = 'DAT' 120 | order.algoParams = algoParams 121 | #order.transmit = False 122 | 123 | 124 | print("Placing order for %d %s's (id: %d)" % (order.totalQuantity, 125 | contract.symbol, order_id)) 126 | 127 | # Place the order 128 | tws.placeOrder( 129 | order_id, # orderId, 130 | contract, # contract, 131 | order # order 132 | ) 133 | 134 | print("\n====================================================================") 135 | print(" Order placed, waiting %ds for TWS responses" % WAIT_TIME) 136 | print("====================================================================\n") 137 | 138 | 139 | print("Waiting for order to be filled..") 140 | 141 | try: 142 | callback.order_filled.wait(WAIT_TIME) 143 | except KeyboardInterrupt: 144 | pass 145 | finally: 146 | if not callback.order_filled.is_set(): 147 | print('Failed to fill order') 148 | 149 | print("\nDisconnecting...") 150 | tws.eDisconnect() 151 | -------------------------------------------------------------------------------- /patches/gcc_4_7: -------------------------------------------------------------------------------- 1 | diff --git a/IB/src/EPosixClientSocketPlatform.h b/IB/src/EPosixClientSocketPlatform.h 2 | index ae0cae3..4fb492a 100644 3 | --- a/IB/src/EPosixClientSocketPlatform.h 4 | +++ b/IB/src/EPosixClientSocketPlatform.h 5 | @@ -34,6 +34,7 @@ 6 | #include 7 | #include 8 | #include 9 | + #include 10 | #include 11 | 12 | // helpers 13 | -------------------------------------------------------------------------------- /patches/mfc_msc_mixup: -------------------------------------------------------------------------------- 1 | diff --git a/IB/shared/EClientSocketBaseImpl.h b/IB/shared/EClientSocketBaseImpl.h 2 | index 1dc4e78..06511ac 100644 3 | --- a/IB/shared/EClientSocketBaseImpl.h 4 | +++ b/IB/shared/EClientSocketBaseImpl.h 5 | @@ -464,7 +464,7 @@ static IBString errMsg(std::exception e) { 6 | } 7 | 8 | 9 | -#ifdef _MSC_VER 10 | +#ifdef _MFC_VER 11 | static IBString errMsg(CException *e) { 12 | // return the error associated with this exception 13 | char buf[1024]; 14 | @@ -2752,7 +2752,7 @@ int EClientSocketBase::processConnectAck(const char*& beginPtr, const char* endP 15 | beginPtr = ptr; 16 | return processed; 17 | } 18 | -#ifdef _MSC_VER 19 | +#ifdef _MFC_VER 20 | catch( CException* e) { 21 | m_pEWrapper->error( NO_VALID_ID, SOCKET_EXCEPTION.code(), 22 | SOCKET_EXCEPTION.msg() + errMsg(e)); 23 | @@ -4127,7 +4127,7 @@ int EClientSocketBase::processMsg(const char*& beginPtr, const char* endPtr) 24 | return processed; 25 | } 26 | 27 | -#ifdef _MSC_VER 28 | +#ifdef _MFC_VER 29 | catch( CException* e) { 30 | m_pEWrapper->error( NO_VALID_ID, SOCKET_EXCEPTION.code(), 31 | SOCKET_EXCEPTION.msg() + errMsg(e)); 32 | -------------------------------------------------------------------------------- /patches/remove_stdafx: -------------------------------------------------------------------------------- 1 | diff --git a/IB/shared/EClientSocketBaseImpl.h b/IB/shared/EClientSocketBaseImpl.h 2 | index 1dc4e78..9350b43 100644 3 | --- a/IB/shared/EClientSocketBaseImpl.h 4 | +++ b/IB/shared/EClientSocketBaseImpl.h 5 | @@ -4,7 +4,7 @@ 6 | #ifndef eclientsocketbaseimpl_h__INCLUDED 7 | #define eclientsocketbaseimpl_h__INCLUDED 8 | 9 | -#include "StdAfx.h" 10 | +//#include "StdAfx.h" 11 | #include "EClientSocketBase.h" 12 | 13 | #include "EWrapper.h" 14 | -------------------------------------------------------------------------------- /patches/shared_ptr_bool_conv: -------------------------------------------------------------------------------- 1 | diff --git a/IB/shared/shared_ptr.h b/IB/shared/shared_ptr.h 2 | index 20a5d7f..839434b 100644 3 | --- a/IB/shared/shared_ptr.h 4 | +++ b/IB/shared/shared_ptr.h 5 | @@ -77,6 +77,7 @@ public: 6 | 7 | X& operator*() const { return *ptr_; } 8 | X* operator->() const { return ptr_; } 9 | + operator bool() const { return ptr_ != 0; } 10 | X* get() const { return ptr_; } 11 | bool only() const { return use_.only(); } 12 | 13 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | """Setup file for packaging swigibpy""" 2 | 3 | import re 4 | import subprocess 5 | import sys 6 | from os import chdir, getcwd, listdir 7 | from os.path import join, dirname, abspath 8 | from sysconfig import get_platform 9 | 10 | try: 11 | from setuptools.command.build_ext import build_ext 12 | from setuptools import setup, Extension, Command 13 | except: 14 | from distutils.command.build_ext import build_ext 15 | from distutils import setup, Extension, Command 16 | 17 | ### 18 | 19 | IB_DIR = 'IB' 20 | VERSION = '0.5.0' 21 | 22 | root_dir = abspath(dirname(__file__)) 23 | libraries = [] 24 | 25 | if(get_platform().startswith('win')): 26 | libraries.append('ws2_32') 27 | 28 | ib_module = Extension('_swigibpy', 29 | sources=[IB_DIR + 30 | '/src/EClientSocketBase.cpp', 31 | IB_DIR + 32 | '/src/EPosixClientSocket.cpp', 33 | IB_DIR + '/swig_wrap.cpp'], 34 | include_dirs=[IB_DIR, 35 | IB_DIR + '/src', 36 | IB_DIR + '/shared'], 37 | define_macros=[('IB_USE_STD_STRING', '1')], 38 | libraries=libraries 39 | ) 40 | 41 | 42 | class Swigify(Command): 43 | description = "Regenerate swigibpy's wrapper code (requires SWIG)" 44 | user_options = [] 45 | 46 | def initialize_options(self): 47 | self.swig_opts = None 48 | self.cwd = None 49 | 50 | def finalize_options(self): 51 | self.cwd = getcwd() 52 | self.swig_opts = [ 53 | '-v', 54 | '-c++', 55 | '-python', 56 | '-threads', 57 | '-keyword', 58 | '-w511', 59 | '-outdir', 60 | root_dir, 61 | '-modern', 62 | '-fastdispatch', 63 | '-nosafecstrings', 64 | '-noproxydel', 65 | '-fastproxy', 66 | '-fastinit', 67 | '-fastunpack', 68 | '-fastquery', 69 | '-modernargs', 70 | '-nobuildnone' 71 | ] 72 | 73 | def run(self): 74 | chdir(join(root_dir, IB_DIR)) 75 | try: 76 | swig_cmd = ['swig'] + self.swig_opts + ['-o', 'swig_wrap.cpp'] 77 | swig_cmd.append(join(root_dir, 'swigify_ib.i')) 78 | print('Running SWIG command: %s' % ' '.join(swig_cmd)) 79 | subprocess.check_call(swig_cmd) 80 | 81 | print('Removing boost namespace') 82 | 83 | # Remove boost namespace, added to support IB's custom shared_ptr 84 | swig_files = [ 85 | join(root_dir, IB_DIR, 'swig_wrap.cpp'), 86 | join(root_dir, IB_DIR, 'swig_wrap.h'), 87 | join(root_dir, 'swigibpy.py') 88 | ] 89 | 90 | for swig_file in swig_files: 91 | with open(swig_file, 'r+') as swig_file_handle: 92 | contents = swig_file_handle.read() 93 | contents = contents.replace( 94 | "boost::shared_ptr", "shared_ptr") 95 | contents = re.sub( 96 | r'(shared_ptr<[^>]+>\([^)]+ )' 97 | r'(SWIG_NO_NULL_DELETER_0)\)', 98 | r'\1)', 99 | contents 100 | ) 101 | swig_file_handle.seek(0) 102 | swig_file_handle.truncate() 103 | swig_file_handle.write(contents) 104 | except subprocess.CalledProcessError as cpe: 105 | pass 106 | finally: 107 | chdir(self.cwd) 108 | 109 | 110 | class Patchify(Command): 111 | description = "Apply swigibpy's patches to the TWS API" 112 | user_options = [ 113 | ('reverse', 'r', 'Un-apply the patches') 114 | ] 115 | 116 | def initialize_options(self): 117 | self.cwd = None 118 | self.reverse = False 119 | self.patch_opts = ['-v'] 120 | 121 | def finalize_options(self): 122 | self.cwd = getcwd() 123 | if self.reverse: 124 | self.patch_opts.append('-R') 125 | 126 | def run(self): 127 | chdir(root_dir) 128 | for patch in listdir(join(root_dir, 'patches')): 129 | patch_cmd = ['git', 'apply'] + self.patch_opts 130 | patch_cmd.append(join(root_dir, 'patches', patch)) 131 | subprocess.call(patch_cmd) 132 | chdir(self.cwd) 133 | 134 | 135 | class SwigibpyBuildExt(build_ext): 136 | def build_extensions(self): 137 | compiler = self.compiler.compiler_type 138 | if compiler == 'msvc': 139 | extra = ('/D_CRT_SECURE_NO_DEPRECATE', 140 | '/EHsc', '/wd4355', '/wd4800') 141 | else: 142 | extra = ('-Wno-switch',) 143 | for ext in self.extensions: 144 | ext.extra_compile_args += extra 145 | build_ext.build_extensions(self) 146 | 147 | 148 | readme = open(join(root_dir, 'README.rst')) 149 | setup(version=VERSION, 150 | name='swigibpy', 151 | author="Kieran O'Mahony", 152 | author_email="kieranom@gmail.com", 153 | url="https://github.com/Komnomnomnom/swigibpy/", 154 | license='New BSD License', 155 | description="""Third party Python API for Interactive Brokers""", 156 | long_description=readme.read(), 157 | keywords=["interactive brokers", "tws"], 158 | ext_modules=[ib_module], 159 | py_modules=["swigibpy"], 160 | cmdclass={ 161 | 'build_ext': SwigibpyBuildExt, 162 | 'swigify': Swigify, 163 | 'patchify': Patchify, 164 | }, 165 | classifiers=[ 166 | "Programming Language :: Python", 167 | "Programming Language :: Python :: 2", 168 | "Programming Language :: Python :: 3", 169 | "Development Status :: 4 - Beta", 170 | "Environment :: Other Environment", 171 | "Intended Audience :: Developers", 172 | "License :: OSI Approved :: BSD License", 173 | "Operating System :: OS Independent", 174 | "Topic :: Software Development :: Libraries :: Python Modules", 175 | "Topic :: Office/Business :: Financial", 176 | ], 177 | ) 178 | readme.close() 179 | -------------------------------------------------------------------------------- /swigify_ib.i: -------------------------------------------------------------------------------- 1 | /* 2 | SWIG interface file for Interactive Brokers API. 3 | */ 4 | 5 | %module(directors="1", docstring="Python wrapper for Interactive Brokers TWS C++ API") swigibpy 6 | 7 | /* Turn on auto-generated docstrings */ 8 | %feature("autodoc", "1"); 9 | 10 | /* auto convert std::string and typedefs to Python strings */ 11 | %include "std_string.i" 12 | typedef std::string IBString; 13 | 14 | /* auto convert std::vector to Python lists */ 15 | %include "std_vector.i" 16 | 17 | /* use boost template to generate shared pointer handling */ 18 | %include 19 | 20 | /* Inclusions for generated cpp file */ 21 | %{ 22 | #include "shared/shared_ptr.h" 23 | 24 | #include "shared/IBString.h" 25 | #include "shared/EClient.h" 26 | #include "shared/EClientSocketBase.h" 27 | 28 | #include "src/EPosixClientSocket.h" 29 | #include "shared/EWrapper.h" 30 | 31 | #include "shared/CommissionReport.h" 32 | #include "shared/CommonDefs.h" 33 | #include "shared/Contract.h" 34 | #include "shared/Execution.h" 35 | #include "shared/Order.h" 36 | #include "shared/OrderState.h" 37 | #include "shared/ScannerSubscription.h" 38 | #include "shared/TagValue.h" 39 | %} 40 | 41 | 42 | /* Shared Pointers */ 43 | %shared_ptr(ComboLeg) 44 | %shared_ptr(std::vector >) 45 | 46 | %shared_ptr(OrderComboLeg) 47 | %shared_ptr(std::vector >) 48 | 49 | %shared_ptr(TagValue) 50 | %shared_ptr(std::vector >) 51 | 52 | /* Vector (list) containers */ 53 | %template(ComboLegList) std::vector >; 54 | %template(OrderComboLegList) std::vector >; 55 | %template(TagValueList) std::vector >; 56 | 57 | /* 58 | TWS use their own shared_ptr class, need to fool SWIG into thinking 59 | it's the standard boost::shared_ptr. 60 | This means the generated cpp file must be post-processed to remove 61 | references to boost (see setup.py). 62 | */ 63 | #define shared_ptr boost::shared_ptr 64 | 65 | /*EWrapper will be subclassed in Python*/ 66 | %feature("director") EWrapper; 67 | %feature("director:except") { 68 | if ($error != NULL) { 69 | 70 | if ( !( PyErr_ExceptionMatches(PyExc_SystemExit) || 71 | PyErr_ExceptionMatches(PyExc_SystemError) || 72 | PyErr_ExceptionMatches(PyExc_KeyboardInterrupt) ) ) 73 | { 74 | PyObject *value = 0; 75 | PyObject *traceback = 0; 76 | 77 | PyErr_Fetch(&$error, &value, &traceback); 78 | PyErr_NormalizeException(&$error, &value, &traceback); 79 | 80 | { 81 | if (value == NULL) { 82 | value = Py_None; 83 | } 84 | if (traceback == NULL) { 85 | traceback = Py_None; 86 | } 87 | swig::SwigVar_PyObject swig_method_name = SWIG_Python_str_FromChar((char *) "pyError"); 88 | swig::SwigVar_PyObject result = PyObject_CallMethodObjArgs(swig_get_self(), (PyObject *) swig_method_name, $error, value, traceback, NULL); 89 | } 90 | 91 | Py_XDECREF($error); 92 | Py_XDECREF(value); 93 | Py_XDECREF(traceback); 94 | 95 | $error = PyErr_Occurred(); 96 | if ($error != NULL) { 97 | PyErr_Print(); 98 | throw Swig::DirectorMethodException(); 99 | } 100 | } 101 | else 102 | { 103 | throw Swig::DirectorMethodException(); 104 | } 105 | } 106 | } 107 | 108 | /* Exception handling */ 109 | %include exception.i 110 | %exception { 111 | // most errors should be propagated through to EWrapper->error, 112 | // others should be added here as and when needed / encountered. 113 | try { 114 | $action 115 | } catch(Swig::DirectorPureVirtualException &e) { 116 | /* Call to pure virtual method, raise not implemented error */ 117 | PyErr_SetString(PyExc_NotImplementedError, "$decl not implemented"); 118 | SWIG_fail; 119 | } catch(Swig::DirectorException &e) { 120 | /* Fail if there is a problem in the director proxy transport */ 121 | SWIG_fail; 122 | } catch(std::exception& e) { 123 | /* Convert standard error to Exception */ 124 | PyErr_SetString(PyExc_Exception, const_cast(e.what())); 125 | SWIG_fail; 126 | } catch(...) { 127 | /* Final catch all, results in runtime error */ 128 | PyErr_SetString(PyExc_RuntimeError, "Unknown error caught in Interactive Brokers SWIG wrapper..."); 129 | SWIG_fail; 130 | } 131 | } 132 | 133 | /* Grab the header files to be wrapped */ 134 | %include "shared/CommissionReport.h" 135 | %include "shared/CommonDefs.h" 136 | %include "shared/Contract.h" 137 | %include "shared/EClient.h" 138 | %include "shared/EClientSocketBase.h" 139 | %include "shared/Execution.h" 140 | %include "shared/Order.h" 141 | %include "shared/OrderState.h" 142 | %include "shared/ScannerSubscription.h" 143 | %include "shared/TagValue.h" 144 | 145 | %pythonbegin %{ 146 | import warnings 147 | import sys 148 | import threading 149 | import select 150 | from traceback import print_exc, print_exception 151 | %} 152 | 153 | /* Customise EPosixClientSocket so that TWS is automatically polled for messages when we are connected to it */ 154 | %pythoncode %{ 155 | 156 | class TWSPoller(threading.Thread): 157 | '''Continually polls TWS for any outstanding messages. 158 | 159 | Loops indefinitely until killed or a system error occurs. 160 | 161 | Uses socket select to poll for input and calls TWS's 162 | `EClientSocketBase::checkMessages` function. 163 | ''' 164 | 165 | MAX_BACKOFF = 5000 166 | 167 | def __init__(self, tws, wrapper): 168 | super(TWSPoller, self).__init__() 169 | self.daemon = True 170 | self._tws = tws 171 | self._wrapper = wrapper 172 | self._stop_evt = threading.Event() 173 | self._connected_evt = threading.Event() 174 | 175 | self.tws_connected(tws.isConnected()) 176 | 177 | def stop_poller(self): 178 | self._stop_evt.set() 179 | 180 | def tws_connected(self, flag): 181 | if flag: 182 | self._connected_evt.set() 183 | else: 184 | self._connected_evt.clear() 185 | 186 | def run(self): 187 | modules = sys.modules 188 | try: 189 | self._run() 190 | except: 191 | # ignore errors raised during interpreter shutdown. 192 | if modules: 193 | raise 194 | 195 | def _run(self): 196 | '''Continually poll TWS''' 197 | stop = self._stop_evt 198 | connected = self._connected_evt 199 | tws = self._tws 200 | 201 | fd = tws.fd() 202 | pollfd = [fd] 203 | 204 | while not stop.is_set(): 205 | while (not connected.is_set() or not tws.isConnected()) and not stop.is_set(): 206 | connected.clear() 207 | backoff = 0 208 | retries = 0 209 | 210 | while not connected.is_set() and not stop.is_set(): 211 | if tws.reconnect_auto and not tws.reconnect(): 212 | if backoff < self.MAX_BACKOFF: 213 | retries += 1 214 | backoff = min(2**(retries + 1), self.MAX_BACKOFF) 215 | connected.wait(backoff / 1000.) 216 | else: 217 | connected.wait(1) 218 | fd = tws.fd() 219 | pollfd = [fd] 220 | 221 | if fd > 0: 222 | try: 223 | evtin, _evtout, evterr = select.select(pollfd, [], pollfd, 1) 224 | except select.error: 225 | connected.clear() 226 | continue 227 | else: 228 | if fd in evtin: 229 | try: 230 | if not tws.checkMessages(): 231 | tws.eDisconnect(stop_polling=False) 232 | continue 233 | except (SystemExit, SystemError, KeyboardInterrupt): 234 | break 235 | except: 236 | try: 237 | self._wrapper.pyError(*sys.exc_info()) 238 | except: 239 | print_exc() 240 | elif fd in evterr: 241 | connected.clear() 242 | continue 243 | %} 244 | 245 | %feature("shadow") EPosixClientSocket::EPosixClientSocket(EWrapper *ptr) %{ 246 | def __init__(self, ewrapper, poll_auto=True, reconnect_auto=False): 247 | '''Create an EPosixClientSocket to comunicate with Interactive Brokers. 248 | 249 | Parameters 250 | ---------- 251 | ewrapper : EWrapper subclass to which responses will be dispatched. 252 | poll_auto : boolean, if True automatically poll for messages with a 253 | background thread. Default True 254 | reconnect_auto : boolean, if True automatically reconnect to TWS if 255 | the connection is lost. Default False 256 | ''' 257 | _swigibpy.EPosixClientSocket_swiginit(self, $action(ewrapper)) 258 | 259 | # store a reference to EWrapper on the Python side (C++ member is protected so inaccessible from Python). 260 | self._ewrapper = ewrapper 261 | 262 | self._connect_lock = threading.Lock() 263 | self.poller = None 264 | self._poll_auto = poll_auto 265 | self.reconnect_auto = reconnect_auto 266 | self._connect_args = None 267 | %} 268 | %feature("shadow") EClientSocketBase::eConnect(const char *host, unsigned int port, int clientId=0, bool extraAuth=false) %{ 269 | def eConnect(self, host, port, clientId=0, extraAuth=False, **kwargs): 270 | if "poll_auto" in kwargs: 271 | warnings.warn("eConnect argument 'poll_auto' is deprecated, use 'poll_auto' arg in constructor instead", DeprecationWarning) 272 | self.poll_auto = kwargs.pop('poll_auto') 273 | 274 | with self._connect_lock: 275 | success = $action(self, host, port, clientId, extraAuth) 276 | 277 | if success: 278 | self._connect_args = ((host, port, clientId, extraAuth), kwargs) 279 | if self.isConnected(): 280 | self._startPolling() 281 | if self.poller is not None: 282 | self.poller.tws_connected(True) 283 | return success 284 | %} 285 | %feature("shadow") EClientSocketBase::eDisconnect() %{ 286 | def eDisconnect(self, stop_polling=True): 287 | if stop_polling: 288 | self._stopPolling() 289 | val = $action(self) 290 | if self.poller is not None: 291 | self.poller.tws_connected(False) 292 | return val 293 | %} 294 | %extend EPosixClientSocket { 295 | %pythoncode { 296 | 297 | def reconnect(self): 298 | if self._connect_args is None: 299 | return 300 | return self.eConnect(*self._connect_args[0], **self._connect_args[1]) 301 | 302 | def _startPolling(self): 303 | if not self.poll_auto: 304 | return 305 | if self.poller is None or not self.poller.is_alive(): 306 | self.poller = TWSPoller(self, self._ewrapper) 307 | self.poller.start() 308 | 309 | def _stopPolling(self): 310 | if self.poller is not None: 311 | self.poller.stop_poller() 312 | 313 | @property 314 | def poll_auto(self): 315 | return self._poll_auto 316 | 317 | @poll_auto.setter 318 | def poll_auto(self, val): 319 | self._poll_auto = val 320 | if val: 321 | self._startPolling() 322 | else: 323 | self._stopPolling() 324 | } 325 | } 326 | 327 | %include "src/EPosixClientSocket.h" 328 | 329 | %feature("shadow") EWrapper::winError(const IBString &, int) %{ 330 | def winError(self, str, lastError): 331 | '''Error in TWS API library''' 332 | sys.stderr.write("TWS ERROR - %s: %s\n" % (lastError, str)) 333 | %} 334 | %feature("shadow") EWrapper::error(const int, const int, const IBString) %{ 335 | def error(self, id, errorCode, errorString): 336 | '''Error during communication with TWS''' 337 | if errorCode == 165: # Historical data sevice message 338 | sys.stderr.write("TWS INFO - %s: %s\n" % (errorCode, errorString)) 339 | elif errorCode >= 501 and errorCode < 600: # Socket read failed 340 | sys.stderr.write("TWS CLIENT-ERROR - %s: %s\n" % (errorCode, errorString)) 341 | elif errorCode >= 100 and errorCode < 1100: 342 | sys.stderr.write("TWS ERROR - %s: %s\n" % (errorCode, errorString)) 343 | elif errorCode >= 1100 and errorCode < 2100: 344 | sys.stderr.write("TWS SYSTEM-ERROR - %s: %s\n" % (errorCode, errorString)) 345 | elif errorCode in (2104, 2106, 2108): 346 | sys.stderr.write("TWS INFO - %s: %s\n" % (errorCode, errorString)) 347 | elif errorCode >= 2100 and errorCode <= 2110: 348 | sys.stderr.write("TWS WARNING - %s: %s\n" % (errorCode, errorString)) 349 | else: 350 | sys.stderr.write("TWS ERROR - %s: %s\n" % (errorCode, errorString)) 351 | %} 352 | 353 | %extend EWrapper { 354 | %pythoncode { 355 | def pyError(self, type, value, traceback): 356 | '''Handles an error thrown during invocation of an EWrapper method. 357 | 358 | Arguments are those provided by sys.exc_info() 359 | ''' 360 | sys.stderr.write("Exception thrown during EWrapper method dispatch:\n") 361 | print_exception(type, value, traceback) 362 | } 363 | } 364 | %include "shared/EWrapper.h" 365 | 366 | %pythoncode %{ 367 | 368 | class EWrapperVerbose(EWrapper): 369 | '''Implements all EWrapper methods and prints to standard out when a method 370 | is invoked. 371 | ''' 372 | 373 | def _print_call(self, name, *args, **kwargs): 374 | argspec = [] 375 | if args: 376 | argspec.append(', '.join(str(a) for a in args)) 377 | if kwargs: 378 | argspec.append(', '.join('%s=%s' for k, v in kwargs.items())) 379 | print('TWS call ignored - %s(%s)' % (name, ', '.join(argspec))) 380 | 381 | class EWrapperQuiet(EWrapper): 382 | '''Implements all EWrapper methods and ignores method calls.''' 383 | 384 | def _ignore_call(self, *args, **kwargs): 385 | pass 386 | 387 | def _make_printer(name): 388 | return lambda self, *a, **kw: self._print_call(name, *a, **kw) 389 | 390 | for name, attr in EWrapper.__dict__.items(): 391 | if name[0] == '_' or not callable(attr) or name in ('error', 'winError', 'pyError'): 392 | continue 393 | 394 | setattr(EWrapperQuiet, name, EWrapperQuiet.__dict__['_ignore_call']) 395 | setattr(EWrapperVerbose, name, _make_printer(name)) 396 | %} 397 | --------------------------------------------------------------------------------