A couple of things/definitions/conventions:
* a *low level message* is some data prefixed with its size
* a *high level message* is a list of fields separated by the NULL character; the fields are all strings; the message ID is the first field, the come others whose number and semantics depend on the message itself
* a *request* is a message from client to TWS/IBGW (IB Gateway)
* an *answer* is a message from TWS/IBGW to client
How the code is organized:
* *comm* module: has tools that know how to handle (eg: encode/decode) low and high level messages
* *Connection*: glorified socket
* *Reader*: thread that uses Connection to read packets, transform to low level messages and put in a Queue
* *Decoder*: knows how to take a low level message and decode into high level message
* *Client*:
+ knows to send requests
+ has the message loop which takes low level messages from Queue and uses Decoder to tranform into high level message with which it then calls the corresponding Wrapper method
* *Wrapper*: class that needs to be subclassed by the user so that it can get the incoming messages
The info/data flow is:
* receiving:
+ *Connection.recv_msg()* (which is essentially a socket) receives the packets
- uses *Connection._recv_all_msgs()* which tries to combine smaller packets into bigger ones based on some trivial heuristic
+ *Reader.run()* uses *Connection.recv_msg()* to get a packet and then uses *comm.read_msg()* to try to make it a low level message. If that can't be done yet (size prefix says so) then it waits for more packets
+ if a full low level message is received then it is placed in the Queue (remember this is a standalone thread)
+ the main thread runs the *Client.run()* loop which:
- gets a low level message from Queue
- uses *comm.py* to translate into high level message (fields)
- uses *Decoder.interpret()* to act based on that message
+ *Decoder.interpret()* will translate the fields into function parameters of the correct type and call with the correct/corresponding method of *Wrapper* class
* sending:
+ *Client* class has methods that implement the _requests_. The user will call those request methods with the needed parameters and *Client* will send them to the TWS/IBGW.
Implementation notes:
* the *Decoder* has two ways of handling a message (esentially decoding the fields)
+ some message very neatly map to a function call; meaning that the number of fields and order are the same as the method parameters. For example: Wrapper.tickSize(). In this case a simple mapping is made between the incoming msg id and the Wrapper method:
IN.TICK_SIZE: HandleInfo(wrap=Wrapper.tickSize),
+ other messages are more complex, depend on version number heavily or need field massaging. In this case the incoming message id is mapped to a processing function that will do all that and call the Wrapper method at the end. For example:
IN.TICK_PRICE: HandleInfo(proc=processTickPriceMsg),
Instalation notes:
* you can use this to build a source distribution
python3 setup.py sdist
* you can use this to build a wheel
python3 setup.py bdist_wheel
* you can use this to install the wheel
python3 -m pip install --user --upgrade dist/ibapi-9.75.1-py3-none-any.whl
Raw data
{
"_id": null,
"home_page": "https://interactivebrokers.github.io/tws-api",
"name": "nautilus-ibapi",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": null,
"author": "IBG LLC",
"author_email": "dnastase@interactivebrokers.com",
"download_url": "https://files.pythonhosted.org/packages/09/94/b293e58248ae72b66f3a0fd2ed3a89d75011bc111745f5351aa28d117bd7/nautilus_ibapi-10.19.4.tar.gz",
"platform": null,
"description": "A couple of things/definitions/conventions:\n* a *low level message* is some data prefixed with its size\n* a *high level message* is a list of fields separated by the NULL character; the fields are all strings; the message ID is the first field, the come others whose number and semantics depend on the message itself\n* a *request* is a message from client to TWS/IBGW (IB Gateway)\n* an *answer* is a message from TWS/IBGW to client\n\n\nHow the code is organized:\n* *comm* module: has tools that know how to handle (eg: encode/decode) low and high level messages\n* *Connection*: glorified socket\n* *Reader*: thread that uses Connection to read packets, transform to low level messages and put in a Queue\n* *Decoder*: knows how to take a low level message and decode into high level message\n* *Client*:\n + knows to send requests\n + has the message loop which takes low level messages from Queue and uses Decoder to tranform into high level message with which it then calls the corresponding Wrapper method\n* *Wrapper*: class that needs to be subclassed by the user so that it can get the incoming messages\n\n\nThe info/data flow is:\n\n* receiving:\n + *Connection.recv_msg()* (which is essentially a socket) receives the packets\n - uses *Connection._recv_all_msgs()* which tries to combine smaller packets into bigger ones based on some trivial heuristic\n + *Reader.run()* uses *Connection.recv_msg()* to get a packet and then uses *comm.read_msg()* to try to make it a low level message. If that can't be done yet (size prefix says so) then it waits for more packets\n + if a full low level message is received then it is placed in the Queue (remember this is a standalone thread)\n + the main thread runs the *Client.run()* loop which:\n - gets a low level message from Queue\n - uses *comm.py* to translate into high level message (fields)\n - uses *Decoder.interpret()* to act based on that message\n + *Decoder.interpret()* will translate the fields into function parameters of the correct type and call with the correct/corresponding method of *Wrapper* class\n\n* sending:\n + *Client* class has methods that implement the _requests_. The user will call those request methods with the needed parameters and *Client* will send them to the TWS/IBGW.\n\n\nImplementation notes:\n\n* the *Decoder* has two ways of handling a message (esentially decoding the fields)\n + some message very neatly map to a function call; meaning that the number of fields and order are the same as the method parameters. For example: Wrapper.tickSize(). In this case a simple mapping is made between the incoming msg id and the Wrapper method:\n\n IN.TICK_SIZE: HandleInfo(wrap=Wrapper.tickSize), \n\n + other messages are more complex, depend on version number heavily or need field massaging. In this case the incoming message id is mapped to a processing function that will do all that and call the Wrapper method at the end. For example:\n\n IN.TICK_PRICE: HandleInfo(proc=processTickPriceMsg), \n\n\nInstalation notes:\n\n* you can use this to build a source distribution\n\npython3 setup.py sdist\n\n* you can use this to build a wheel\n\npython3 setup.py bdist_wheel\n\n* you can use this to install the wheel\n\npython3 -m pip install --user --upgrade dist/ibapi-9.75.1-py3-none-any.whl\n\n\n",
"bugtrack_url": null,
"license": "IB API Non-Commercial License or the IB API Commercial License",
"summary": "Python IB API",
"version": "10.19.4",
"project_urls": {
"Homepage": "https://interactivebrokers.github.io/tws-api",
"Repository": "https://interactivebrokers.github.io/tws-api"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "d21ccfbab96ef72ddd22b4668135899ff56b7a87d08780e57a660c16a188f298",
"md5": "28337a0108116a98a5048896ab18f06e",
"sha256": "61f40762a0a18ef6fee57212c7092d5f42c22f72cf3a08c052cb2be68af4f413"
},
"downloads": -1,
"filename": "nautilus_ibapi-10.19.4-py3-none-any.whl",
"has_sig": false,
"md5_digest": "28337a0108116a98a5048896ab18f06e",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.9",
"size": 71867,
"upload_time": "2024-08-30T07:25:59",
"upload_time_iso_8601": "2024-08-30T07:25:59.184211Z",
"url": "https://files.pythonhosted.org/packages/d2/1c/cfbab96ef72ddd22b4668135899ff56b7a87d08780e57a660c16a188f298/nautilus_ibapi-10.19.4-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "0994b293e58248ae72b66f3a0fd2ed3a89d75011bc111745f5351aa28d117bd7",
"md5": "ab3af0ec67ef5085950b9a8a9638d9ed",
"sha256": "fdfae46b9de577d8b7a396c6345c3b60391155f999c80b0c4021968016685aae"
},
"downloads": -1,
"filename": "nautilus_ibapi-10.19.4.tar.gz",
"has_sig": false,
"md5_digest": "ab3af0ec67ef5085950b9a8a9638d9ed",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 62707,
"upload_time": "2024-08-30T07:26:00",
"upload_time_iso_8601": "2024-08-30T07:26:00.654153Z",
"url": "https://files.pythonhosted.org/packages/09/94/b293e58248ae72b66f3a0fd2ed3a89d75011bc111745f5351aa28d117bd7/nautilus_ibapi-10.19.4.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-08-30 07:26:00",
"github": false,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"lcname": "nautilus-ibapi"
}