ibflex2 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ibflex2-1.0.0/LICENSE.txt +19 -0
- ibflex2-1.0.0/PKG-INFO +208 -0
- ibflex2-1.0.0/README.rst +161 -0
- ibflex2-1.0.0/ibflex/Types.py +2823 -0
- ibflex2-1.0.0/ibflex/__init__.py +19 -0
- ibflex2-1.0.0/ibflex/__version__.py +26 -0
- ibflex2-1.0.0/ibflex/client.py +259 -0
- ibflex2-1.0.0/ibflex/enums.py +295 -0
- ibflex2-1.0.0/ibflex/parser.py +487 -0
- ibflex2-1.0.0/ibflex/py.typed +0 -0
- ibflex2-1.0.0/ibflex/utils.py +16 -0
- ibflex2-1.0.0/ibflex2.egg-info/PKG-INFO +208 -0
- ibflex2-1.0.0/ibflex2.egg-info/SOURCES.txt +21 -0
- ibflex2-1.0.0/ibflex2.egg-info/dependency_links.txt +1 -0
- ibflex2-1.0.0/ibflex2.egg-info/entry_points.txt +2 -0
- ibflex2-1.0.0/ibflex2.egg-info/requires.txt +3 -0
- ibflex2-1.0.0/ibflex2.egg-info/top_level.txt +1 -0
- ibflex2-1.0.0/setup.cfg +14 -0
- ibflex2-1.0.0/setup.py +77 -0
- ibflex2-1.0.0/tests/test_client.py +154 -0
- ibflex2-1.0.0/tests/test_parser.py +540 -0
- ibflex2-1.0.0/tests/test_types.py +1989 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
Copyright (c) 2017 Christopher Singley
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
4
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
5
|
+
the Software without restriction, including without limitation the rights to
|
|
6
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
7
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
|
8
|
+
so, subject to the following conditions:
|
|
9
|
+
|
|
10
|
+
The above copyright notice and this permission notice shall be included in all
|
|
11
|
+
copies or substantial portions of the Software.
|
|
12
|
+
|
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
19
|
+
SOFTWARE.
|
ibflex2-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ibflex2
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: ('Parse Interactive Brokers Flex XML reports and convert to Python types (maintained fork)',)
|
|
5
|
+
Home-page: https://github.com/robcohen/ibflex2
|
|
6
|
+
Download-URL: https://github.com/robcohen/ibflex2/tarball/1.0.0
|
|
7
|
+
Author: Christopher Singley
|
|
8
|
+
Author-email: csingley@gmail.com
|
|
9
|
+
License: MIT
|
|
10
|
+
Keywords: Interactive Brokers,ibkr,flex,xml
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
14
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
15
|
+
Classifier: Topic :: Utilities
|
|
16
|
+
Classifier: Topic :: Office/Business
|
|
17
|
+
Classifier: Topic :: Office/Business :: Financial
|
|
18
|
+
Classifier: Topic :: Office/Business :: Financial :: Accounting
|
|
19
|
+
Classifier: Topic :: Office/Business :: Financial :: Investment
|
|
20
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
21
|
+
Classifier: Operating System :: OS Independent
|
|
22
|
+
Classifier: Natural Language :: English
|
|
23
|
+
Classifier: Programming Language :: Python
|
|
24
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
25
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
26
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
27
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
28
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
29
|
+
Requires-Python: >=3.9
|
|
30
|
+
Description-Content-Type: text/x-rst
|
|
31
|
+
License-File: LICENSE.txt
|
|
32
|
+
Provides-Extra: web
|
|
33
|
+
Requires-Dist: requests; extra == "web"
|
|
34
|
+
Dynamic: author
|
|
35
|
+
Dynamic: author-email
|
|
36
|
+
Dynamic: classifier
|
|
37
|
+
Dynamic: description
|
|
38
|
+
Dynamic: description-content-type
|
|
39
|
+
Dynamic: download-url
|
|
40
|
+
Dynamic: home-page
|
|
41
|
+
Dynamic: keywords
|
|
42
|
+
Dynamic: license
|
|
43
|
+
Dynamic: license-file
|
|
44
|
+
Dynamic: provides-extra
|
|
45
|
+
Dynamic: requires-python
|
|
46
|
+
Dynamic: summary
|
|
47
|
+
|
|
48
|
+
=========================================================
|
|
49
|
+
Python parser for Interactive Brokers Flex XML statements
|
|
50
|
+
=========================================================
|
|
51
|
+
|
|
52
|
+
.. note::
|
|
53
|
+
|
|
54
|
+
**This is a maintained fork of** `ibflex <https://github.com/csingley/ibflex>`_.
|
|
55
|
+
|
|
56
|
+
The original package on PyPI (v0.15) was last updated in January 2021 and crashes
|
|
57
|
+
on modern Interactive Brokers Flex reports. This fork publishes current updates to PyPI.
|
|
58
|
+
|
|
59
|
+
Install with: ``pip install ibflex2``
|
|
60
|
+
|
|
61
|
+
If the original package is updated on PyPI, this fork will be deprecated.
|
|
62
|
+
|
|
63
|
+
----
|
|
64
|
+
|
|
65
|
+
``ibflex`` is a Python library for converting brokerage statement data in
|
|
66
|
+
Interactive Brokers' Flex XML format into standard Python data structures,
|
|
67
|
+
so it can be conveniently processed and analyzed with Python scripts.
|
|
68
|
+
|
|
69
|
+
*N.B. This module has nothing to do with programmatic trading.
|
|
70
|
+
It's about reading brokerage reports.*
|
|
71
|
+
|
|
72
|
+
``ibflex`` is compatible with Python version 3.7+. The parser has no
|
|
73
|
+
dependencies beyond the Python standard library (although the optional client
|
|
74
|
+
for fetching Flex Statements from Interactive Brokers' server does depend
|
|
75
|
+
on `requests`_ ).
|
|
76
|
+
|
|
77
|
+
**This module is alpha software!** It works and it's useful, but the
|
|
78
|
+
API, data structures, etc. are likely to see major changes. Several XML
|
|
79
|
+
schemata are missing, and a few of the more newly-introduced attributes
|
|
80
|
+
for the existing schemata. There are probably bugs.
|
|
81
|
+
|
|
82
|
+
`Pull requests`_ are welcome. If you're submitting a pull request for an updated
|
|
83
|
+
type, please do me a favor and include a test case based on your real-world data
|
|
84
|
+
(censored to remove any personal information) in `tests.test_types.py`. You should
|
|
85
|
+
easily be able to cut&paste one of the existing `unittest.TestCase` subclasses in
|
|
86
|
+
that file and adapt it to your own data. Thanks very much; my own datastream does
|
|
87
|
+
not have full coverage of the object model!
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
Installation
|
|
91
|
+
============
|
|
92
|
+
::
|
|
93
|
+
|
|
94
|
+
pip install ibflex2
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
Flex Parser
|
|
98
|
+
===========
|
|
99
|
+
The primary facility provided is the ``ibflex.parser`` module, which parses
|
|
100
|
+
Flex-format XML data into a hierarchy of Python objects whose structure
|
|
101
|
+
corresponds to that of the original Flex statements, with the data converted
|
|
102
|
+
into appropriate Python types (datetime.datetime, decimal.Decimal, etc.)
|
|
103
|
+
|
|
104
|
+
Usage example:
|
|
105
|
+
|
|
106
|
+
.. code:: python
|
|
107
|
+
|
|
108
|
+
In [1]: from ibflex import parser
|
|
109
|
+
|
|
110
|
+
In [2]: response = parser.parse("2017-01_ibkr.xml")
|
|
111
|
+
|
|
112
|
+
In [3]: response
|
|
113
|
+
Out[3]: FlexQueryResponse(queryName='SCP Everything', type='AF', len(FlexStatements)=1)
|
|
114
|
+
|
|
115
|
+
In [4]: stmt = response.FlexStatements[0]
|
|
116
|
+
|
|
117
|
+
In [5]: stmt
|
|
118
|
+
Out[5]: FlexStatement(accountId='U770993', fromDate=datetime.date(2017, 1, 2), toDate=datetime.date(2017, 1, 31), period=None, whenGenerated=datetime.datetime(2017, 5, 10, 11, 41, 38), len(CashReport)=3, len(EquitySummaryInBase)=23, len(StmtFunds)=344, len(ChangeInPositionValues)=2, len(OpenPositions)=2140, len(FxPositions)=1, len(Trades)=339, len(CorporateActions)=1, len(CashTransactions)=4, len(InterestAccruals)=1, len(ChangeInDividendAccruals)=5, len(OpenDividendAccruals)=2, len(SecuritiesInfo)=30, len(ConversionRates)=550)
|
|
119
|
+
|
|
120
|
+
In [6]: trade = stmt.Trades[-1]
|
|
121
|
+
|
|
122
|
+
In [7]: trade
|
|
123
|
+
Out[7]: Trade(transactionType=<TradeType.EXCHTRADE: 'ExchTrade'>, openCloseIndicator=<OpenClose.CLOSE: 'C'>, buySell=<BuySell.SELL: 'SELL'>, orderType=<OrderType.LIMIT: 'LMT'>, assetCategory=<AssetClass.STOCK: 'STK'>, accountId='U770993', currency='USD', fxRateToBase=Decimal('1'), symbol='WMIH', description='WMIH CORP', conid='105068604', cusip=None, isin=None, listingExchange=None, multiplier=Decimal('1'), strike=None, expiry=None, putCall=None, tradeID='1742757182', reportDate=datetime.date(2017, 1, 30), tradeDate=datetime.date(2017, 1, 30), tradeTime=datetime.time(15, 39, 36), settleDateTarget=datetime.date(2017, 2, 2), exchange='BYX', quantity=Decimal('-8'), tradePrice=Decimal('1.4'), tradeMoney=Decimal('-11.2'), taxes=Decimal('0'), ibCommission=Decimal('-0.00680792'), ibCommissionCurrency='USD', netCash=Decimal('11.19319208'), netCashInBase=None, closePrice=Decimal('1.4'), notes=(<Code.PARTIAL: 'P'>,), cost=Decimal('-10.853621'), mtmPnl=Decimal('0'), origTradePrice=Decimal('0'), origTradeDate=None, origTradeID=None, origOrderID='0', openDateTime=None, fifoPnlRealized=Decimal('0.339571'), capitalGainsPnl=None, levelOfDetail='EXECUTION', ibOrderID='865480117', orderTime=datetime.datetime(2017, 1, 30, 15, 39, 36), changeInPrice=Decimal('0'), changeInQuantity=Decimal('0'), proceeds=Decimal('11.2'), fxPnl=Decimal('0'), clearingFirmID=None, transactionID='7248583136', holdingPeriodDateTime=None, ibExecID='0001090f.588f449a.01.01', brokerageOrderID=None, orderReference=None, volatilityOrderLink=None, exchOrderId=None, extExecID='S2367553204796', traderID=None, isAPIOrder=False, acctAlias='SCP 0-0', model=None, securityID=None, securityIDType=None, principalAdjustFactor=None, dateTime=None, underlyingConid=None, underlyingSecurityID=None, underlyingSymbol=None, underlyingListingExchange=None, issuer=None, sedol=None, whenRealized=None, whenReopened=None)
|
|
124
|
+
|
|
125
|
+
In [8]: print(f"{trade.tradeDate} {trade.buySell.name} {abs(trade.quantity)} {trade.symbol} @ {trade.tradePrice} {trade.currency}")
|
|
126
|
+
2017-01-30 SELL 8 WMIH @ 1.4 USD
|
|
127
|
+
|
|
128
|
+
In [9]: pos = stmt.OpenPositions[-1]
|
|
129
|
+
|
|
130
|
+
In [10]: pos
|
|
131
|
+
Out[10]: OpenPosition(side=<LongShort.SHORT: 'Short'>, assetCategory=<AssetClass.STOCK: 'STK'>, accountId='U770993', currency='USD', fxRateToBase=Decimal('1'), reportDate=datetime.date(2017, 1, 31), symbol='VXX', description='IPATH S&P 500 VIX S/T FU ETN', conid='242500577', securityID=None, cusip=None, isin=None, multiplier=Decimal('1'), position=Decimal('-75'), markPrice=Decimal('19.42'), positionValue=Decimal('-1456.5'), openPrice=Decimal('109.210703693'), costBasisPrice=Decimal('109.210703693'), costBasisMoney=Decimal('-8190.802777'), fifoPnlUnrealized=Decimal('6734.302777'), levelOfDetail='LOT', openDateTime=datetime.datetime(2015, 8, 24, 9, 28, 9), holdingPeriodDateTime=datetime.datetime(2015, 8, 24, 9, 28, 9), securityIDType=None, issuer=None, underlyingConid=None, underlyingSymbol=None, code=(), originatingOrderID='699501861', originatingTransactionID='5634129129', accruedInt=None, acctAlias='SCP 0-0', model=None, sedol=None, percentOfNAV=None, strike=None, expiry=None, putCall=None, principalAdjustFactor=None, listingExchange=None, underlyingSecurityID=None, underlyingListingExchange=None, positionValueInBase=None, unrealizedCapitalGainsPnl=None, unrealizedlFxPnl=None)
|
|
132
|
+
|
|
133
|
+
In [11]: print(f"{trade.tradeDate} {trade.buySell.name} {abs(trade.quantity)} {trade.symbol} @ {trade.tradePrice} {trade.currency}")
|
|
134
|
+
2017-01-30 SELL 8 WMIH @ 1.4 USD
|
|
135
|
+
|
|
136
|
+
In [12]: [sec for sec in stmt.SecuritiesInfo if sec.conid == trade.conid][0]
|
|
137
|
+
Out[12]: SecurityInfo(assetCategory=<AssetClass.STOCK: 'STK'>, symbol='WMIH', description='WMIH CORP', conid='105068604', securityID=None, cusip=None, isin=None, listingExchange=None, underlyingSecurityID=None, underlyingListingExchange=None, underlyingConid=None, underlyingCategory=None, subCategory=None, multiplier=Decimal('1'), strike=None, expiry=None, maturity=None, issueDate=None, type=None, sedol=None, securityIDType=None, underlyingSymbol=None, issuer=None, putCall=None, principalAdjustFactor=Decimal('1'), code=())
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
Flex Query Report Configuration
|
|
141
|
+
===============================
|
|
142
|
+
Configure Flex statements through `Interactive Brokers account management`_ .
|
|
143
|
+
Reports > Flex Queries > Custom Flex Queries > Configure
|
|
144
|
+
|
|
145
|
+
You can configure whatever you like and ibflex should parse it, with these exceptions:
|
|
146
|
+
|
|
147
|
+
* You can't use European-style date formats (dd/MM/yy or dd/MM/yyyy).
|
|
148
|
+
Just accept the default (yyyyMMdd) or get with the program and use ISO-8601 (yyyy-MM-dd).
|
|
149
|
+
|
|
150
|
+
* You should use some delimiter between dates & times. The default delimiter
|
|
151
|
+
(semicolon) is fastest to process.
|
|
152
|
+
|
|
153
|
+
* For the Trades section of the statement, you can't select the options at the
|
|
154
|
+
top for "Symbol Summary", "Asset Class", or "Orders". These will blow up
|
|
155
|
+
the parser. It's fine to check the box for "Asset Class" down below, along
|
|
156
|
+
with the other selections for XML attributes.
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
Flex Client
|
|
160
|
+
===========
|
|
161
|
+
Once you've defined various Flex queries, you can generate an access token
|
|
162
|
+
that will allow you to generate statements and download them through the web
|
|
163
|
+
API, instead of logging in to get them.
|
|
164
|
+
|
|
165
|
+
Reports > Settings > FlexWeb Service
|
|
166
|
+
|
|
167
|
+
Once you've got that set up - armed with the token, and the ID# of the desired
|
|
168
|
+
Flex query - ``ibflex.client`` contains the facilities necessary to retrieve
|
|
169
|
+
them:
|
|
170
|
+
|
|
171
|
+
.. code:: python
|
|
172
|
+
|
|
173
|
+
In [1]: from ibflex import client
|
|
174
|
+
In [2]: token = '111111111111111111111111'
|
|
175
|
+
In [3]: query_id = '111111'
|
|
176
|
+
In [4]: response = client.download(token, query_id)
|
|
177
|
+
In [5]: response[:215]
|
|
178
|
+
Out[5]: b'<FlexQueryResponse queryName="Get Everything" type="AF">\n<FlexStatements count="1">\n<FlexStatement accountId="U111111" fromDate="2018-01-01" toDate="2018-01-31" period="LastMonth" whenGenerated="2018-02-01;211353">\n'
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
You can also just execute client.main() as a script:
|
|
182
|
+
|
|
183
|
+
.. code:: bash
|
|
184
|
+
|
|
185
|
+
$ python client.py -t 111111111111111111111111 -q 111111 > 2018-01_ibkr.xml
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
Finally, setup.py installs a script at ``~/.local/bin/flexget``... cron-tastic!
|
|
189
|
+
|
|
190
|
+
.. code:: bash
|
|
191
|
+
|
|
192
|
+
$ flexget -t 111111111111111111111111 -q 111111 > 2018-01_ibkr.xml
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
Resources
|
|
196
|
+
=========
|
|
197
|
+
* Interactive Brokers `Activity Flex Query Reference`_
|
|
198
|
+
* Interactive Brokers `FlexWeb Service Reference`_
|
|
199
|
+
* `capgains`_ - package that uses ibflex (inter alia) to calculate realized gains
|
|
200
|
+
* `ib-flex-analyzer`_ - Analyze your Interactive Brokers Flex XML reports with pandas
|
|
201
|
+
|
|
202
|
+
.. _Pull requests: https://github.com/robcohen/ibflex2/pull/new/master
|
|
203
|
+
.. _requests: https://github.com/requests/requests
|
|
204
|
+
.. _Interactive Brokers account management: https://gdcdyn.interactivebrokers.com/sso/Login
|
|
205
|
+
.. _Activity Flex Query Reference: https://www.interactivebrokers.com/en/software/reportguide/reportguide.htm#reportguide/activity_flex_query_reference.htm
|
|
206
|
+
.. _FlexWeb Service Reference: https://www.interactivebrokers.com/en/software/am/am/reports/flex_web_service_version_3.htm
|
|
207
|
+
.. _capgains: https://github.com/csingley/capgains
|
|
208
|
+
.. _ib-flex-analyzer: https://github.com/wesm/ib-flex-analyzer
|
ibflex2-1.0.0/README.rst
ADDED
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
=========================================================
|
|
2
|
+
Python parser for Interactive Brokers Flex XML statements
|
|
3
|
+
=========================================================
|
|
4
|
+
|
|
5
|
+
.. note::
|
|
6
|
+
|
|
7
|
+
**This is a maintained fork of** `ibflex <https://github.com/csingley/ibflex>`_.
|
|
8
|
+
|
|
9
|
+
The original package on PyPI (v0.15) was last updated in January 2021 and crashes
|
|
10
|
+
on modern Interactive Brokers Flex reports. This fork publishes current updates to PyPI.
|
|
11
|
+
|
|
12
|
+
Install with: ``pip install ibflex2``
|
|
13
|
+
|
|
14
|
+
If the original package is updated on PyPI, this fork will be deprecated.
|
|
15
|
+
|
|
16
|
+
----
|
|
17
|
+
|
|
18
|
+
``ibflex`` is a Python library for converting brokerage statement data in
|
|
19
|
+
Interactive Brokers' Flex XML format into standard Python data structures,
|
|
20
|
+
so it can be conveniently processed and analyzed with Python scripts.
|
|
21
|
+
|
|
22
|
+
*N.B. This module has nothing to do with programmatic trading.
|
|
23
|
+
It's about reading brokerage reports.*
|
|
24
|
+
|
|
25
|
+
``ibflex`` is compatible with Python version 3.7+. The parser has no
|
|
26
|
+
dependencies beyond the Python standard library (although the optional client
|
|
27
|
+
for fetching Flex Statements from Interactive Brokers' server does depend
|
|
28
|
+
on `requests`_ ).
|
|
29
|
+
|
|
30
|
+
**This module is alpha software!** It works and it's useful, but the
|
|
31
|
+
API, data structures, etc. are likely to see major changes. Several XML
|
|
32
|
+
schemata are missing, and a few of the more newly-introduced attributes
|
|
33
|
+
for the existing schemata. There are probably bugs.
|
|
34
|
+
|
|
35
|
+
`Pull requests`_ are welcome. If you're submitting a pull request for an updated
|
|
36
|
+
type, please do me a favor and include a test case based on your real-world data
|
|
37
|
+
(censored to remove any personal information) in `tests.test_types.py`. You should
|
|
38
|
+
easily be able to cut&paste one of the existing `unittest.TestCase` subclasses in
|
|
39
|
+
that file and adapt it to your own data. Thanks very much; my own datastream does
|
|
40
|
+
not have full coverage of the object model!
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
Installation
|
|
44
|
+
============
|
|
45
|
+
::
|
|
46
|
+
|
|
47
|
+
pip install ibflex2
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
Flex Parser
|
|
51
|
+
===========
|
|
52
|
+
The primary facility provided is the ``ibflex.parser`` module, which parses
|
|
53
|
+
Flex-format XML data into a hierarchy of Python objects whose structure
|
|
54
|
+
corresponds to that of the original Flex statements, with the data converted
|
|
55
|
+
into appropriate Python types (datetime.datetime, decimal.Decimal, etc.)
|
|
56
|
+
|
|
57
|
+
Usage example:
|
|
58
|
+
|
|
59
|
+
.. code:: python
|
|
60
|
+
|
|
61
|
+
In [1]: from ibflex import parser
|
|
62
|
+
|
|
63
|
+
In [2]: response = parser.parse("2017-01_ibkr.xml")
|
|
64
|
+
|
|
65
|
+
In [3]: response
|
|
66
|
+
Out[3]: FlexQueryResponse(queryName='SCP Everything', type='AF', len(FlexStatements)=1)
|
|
67
|
+
|
|
68
|
+
In [4]: stmt = response.FlexStatements[0]
|
|
69
|
+
|
|
70
|
+
In [5]: stmt
|
|
71
|
+
Out[5]: FlexStatement(accountId='U770993', fromDate=datetime.date(2017, 1, 2), toDate=datetime.date(2017, 1, 31), period=None, whenGenerated=datetime.datetime(2017, 5, 10, 11, 41, 38), len(CashReport)=3, len(EquitySummaryInBase)=23, len(StmtFunds)=344, len(ChangeInPositionValues)=2, len(OpenPositions)=2140, len(FxPositions)=1, len(Trades)=339, len(CorporateActions)=1, len(CashTransactions)=4, len(InterestAccruals)=1, len(ChangeInDividendAccruals)=5, len(OpenDividendAccruals)=2, len(SecuritiesInfo)=30, len(ConversionRates)=550)
|
|
72
|
+
|
|
73
|
+
In [6]: trade = stmt.Trades[-1]
|
|
74
|
+
|
|
75
|
+
In [7]: trade
|
|
76
|
+
Out[7]: Trade(transactionType=<TradeType.EXCHTRADE: 'ExchTrade'>, openCloseIndicator=<OpenClose.CLOSE: 'C'>, buySell=<BuySell.SELL: 'SELL'>, orderType=<OrderType.LIMIT: 'LMT'>, assetCategory=<AssetClass.STOCK: 'STK'>, accountId='U770993', currency='USD', fxRateToBase=Decimal('1'), symbol='WMIH', description='WMIH CORP', conid='105068604', cusip=None, isin=None, listingExchange=None, multiplier=Decimal('1'), strike=None, expiry=None, putCall=None, tradeID='1742757182', reportDate=datetime.date(2017, 1, 30), tradeDate=datetime.date(2017, 1, 30), tradeTime=datetime.time(15, 39, 36), settleDateTarget=datetime.date(2017, 2, 2), exchange='BYX', quantity=Decimal('-8'), tradePrice=Decimal('1.4'), tradeMoney=Decimal('-11.2'), taxes=Decimal('0'), ibCommission=Decimal('-0.00680792'), ibCommissionCurrency='USD', netCash=Decimal('11.19319208'), netCashInBase=None, closePrice=Decimal('1.4'), notes=(<Code.PARTIAL: 'P'>,), cost=Decimal('-10.853621'), mtmPnl=Decimal('0'), origTradePrice=Decimal('0'), origTradeDate=None, origTradeID=None, origOrderID='0', openDateTime=None, fifoPnlRealized=Decimal('0.339571'), capitalGainsPnl=None, levelOfDetail='EXECUTION', ibOrderID='865480117', orderTime=datetime.datetime(2017, 1, 30, 15, 39, 36), changeInPrice=Decimal('0'), changeInQuantity=Decimal('0'), proceeds=Decimal('11.2'), fxPnl=Decimal('0'), clearingFirmID=None, transactionID='7248583136', holdingPeriodDateTime=None, ibExecID='0001090f.588f449a.01.01', brokerageOrderID=None, orderReference=None, volatilityOrderLink=None, exchOrderId=None, extExecID='S2367553204796', traderID=None, isAPIOrder=False, acctAlias='SCP 0-0', model=None, securityID=None, securityIDType=None, principalAdjustFactor=None, dateTime=None, underlyingConid=None, underlyingSecurityID=None, underlyingSymbol=None, underlyingListingExchange=None, issuer=None, sedol=None, whenRealized=None, whenReopened=None)
|
|
77
|
+
|
|
78
|
+
In [8]: print(f"{trade.tradeDate} {trade.buySell.name} {abs(trade.quantity)} {trade.symbol} @ {trade.tradePrice} {trade.currency}")
|
|
79
|
+
2017-01-30 SELL 8 WMIH @ 1.4 USD
|
|
80
|
+
|
|
81
|
+
In [9]: pos = stmt.OpenPositions[-1]
|
|
82
|
+
|
|
83
|
+
In [10]: pos
|
|
84
|
+
Out[10]: OpenPosition(side=<LongShort.SHORT: 'Short'>, assetCategory=<AssetClass.STOCK: 'STK'>, accountId='U770993', currency='USD', fxRateToBase=Decimal('1'), reportDate=datetime.date(2017, 1, 31), symbol='VXX', description='IPATH S&P 500 VIX S/T FU ETN', conid='242500577', securityID=None, cusip=None, isin=None, multiplier=Decimal('1'), position=Decimal('-75'), markPrice=Decimal('19.42'), positionValue=Decimal('-1456.5'), openPrice=Decimal('109.210703693'), costBasisPrice=Decimal('109.210703693'), costBasisMoney=Decimal('-8190.802777'), fifoPnlUnrealized=Decimal('6734.302777'), levelOfDetail='LOT', openDateTime=datetime.datetime(2015, 8, 24, 9, 28, 9), holdingPeriodDateTime=datetime.datetime(2015, 8, 24, 9, 28, 9), securityIDType=None, issuer=None, underlyingConid=None, underlyingSymbol=None, code=(), originatingOrderID='699501861', originatingTransactionID='5634129129', accruedInt=None, acctAlias='SCP 0-0', model=None, sedol=None, percentOfNAV=None, strike=None, expiry=None, putCall=None, principalAdjustFactor=None, listingExchange=None, underlyingSecurityID=None, underlyingListingExchange=None, positionValueInBase=None, unrealizedCapitalGainsPnl=None, unrealizedlFxPnl=None)
|
|
85
|
+
|
|
86
|
+
In [11]: print(f"{trade.tradeDate} {trade.buySell.name} {abs(trade.quantity)} {trade.symbol} @ {trade.tradePrice} {trade.currency}")
|
|
87
|
+
2017-01-30 SELL 8 WMIH @ 1.4 USD
|
|
88
|
+
|
|
89
|
+
In [12]: [sec for sec in stmt.SecuritiesInfo if sec.conid == trade.conid][0]
|
|
90
|
+
Out[12]: SecurityInfo(assetCategory=<AssetClass.STOCK: 'STK'>, symbol='WMIH', description='WMIH CORP', conid='105068604', securityID=None, cusip=None, isin=None, listingExchange=None, underlyingSecurityID=None, underlyingListingExchange=None, underlyingConid=None, underlyingCategory=None, subCategory=None, multiplier=Decimal('1'), strike=None, expiry=None, maturity=None, issueDate=None, type=None, sedol=None, securityIDType=None, underlyingSymbol=None, issuer=None, putCall=None, principalAdjustFactor=Decimal('1'), code=())
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
Flex Query Report Configuration
|
|
94
|
+
===============================
|
|
95
|
+
Configure Flex statements through `Interactive Brokers account management`_ .
|
|
96
|
+
Reports > Flex Queries > Custom Flex Queries > Configure
|
|
97
|
+
|
|
98
|
+
You can configure whatever you like and ibflex should parse it, with these exceptions:
|
|
99
|
+
|
|
100
|
+
* You can't use European-style date formats (dd/MM/yy or dd/MM/yyyy).
|
|
101
|
+
Just accept the default (yyyyMMdd) or get with the program and use ISO-8601 (yyyy-MM-dd).
|
|
102
|
+
|
|
103
|
+
* You should use some delimiter between dates & times. The default delimiter
|
|
104
|
+
(semicolon) is fastest to process.
|
|
105
|
+
|
|
106
|
+
* For the Trades section of the statement, you can't select the options at the
|
|
107
|
+
top for "Symbol Summary", "Asset Class", or "Orders". These will blow up
|
|
108
|
+
the parser. It's fine to check the box for "Asset Class" down below, along
|
|
109
|
+
with the other selections for XML attributes.
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
Flex Client
|
|
113
|
+
===========
|
|
114
|
+
Once you've defined various Flex queries, you can generate an access token
|
|
115
|
+
that will allow you to generate statements and download them through the web
|
|
116
|
+
API, instead of logging in to get them.
|
|
117
|
+
|
|
118
|
+
Reports > Settings > FlexWeb Service
|
|
119
|
+
|
|
120
|
+
Once you've got that set up - armed with the token, and the ID# of the desired
|
|
121
|
+
Flex query - ``ibflex.client`` contains the facilities necessary to retrieve
|
|
122
|
+
them:
|
|
123
|
+
|
|
124
|
+
.. code:: python
|
|
125
|
+
|
|
126
|
+
In [1]: from ibflex import client
|
|
127
|
+
In [2]: token = '111111111111111111111111'
|
|
128
|
+
In [3]: query_id = '111111'
|
|
129
|
+
In [4]: response = client.download(token, query_id)
|
|
130
|
+
In [5]: response[:215]
|
|
131
|
+
Out[5]: b'<FlexQueryResponse queryName="Get Everything" type="AF">\n<FlexStatements count="1">\n<FlexStatement accountId="U111111" fromDate="2018-01-01" toDate="2018-01-31" period="LastMonth" whenGenerated="2018-02-01;211353">\n'
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
You can also just execute client.main() as a script:
|
|
135
|
+
|
|
136
|
+
.. code:: bash
|
|
137
|
+
|
|
138
|
+
$ python client.py -t 111111111111111111111111 -q 111111 > 2018-01_ibkr.xml
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
Finally, setup.py installs a script at ``~/.local/bin/flexget``... cron-tastic!
|
|
142
|
+
|
|
143
|
+
.. code:: bash
|
|
144
|
+
|
|
145
|
+
$ flexget -t 111111111111111111111111 -q 111111 > 2018-01_ibkr.xml
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
Resources
|
|
149
|
+
=========
|
|
150
|
+
* Interactive Brokers `Activity Flex Query Reference`_
|
|
151
|
+
* Interactive Brokers `FlexWeb Service Reference`_
|
|
152
|
+
* `capgains`_ - package that uses ibflex (inter alia) to calculate realized gains
|
|
153
|
+
* `ib-flex-analyzer`_ - Analyze your Interactive Brokers Flex XML reports with pandas
|
|
154
|
+
|
|
155
|
+
.. _Pull requests: https://github.com/robcohen/ibflex2/pull/new/master
|
|
156
|
+
.. _requests: https://github.com/requests/requests
|
|
157
|
+
.. _Interactive Brokers account management: https://gdcdyn.interactivebrokers.com/sso/Login
|
|
158
|
+
.. _Activity Flex Query Reference: https://www.interactivebrokers.com/en/software/reportguide/reportguide.htm#reportguide/activity_flex_query_reference.htm
|
|
159
|
+
.. _FlexWeb Service Reference: https://www.interactivebrokers.com/en/software/am/am/reports/flex_web_service_version_3.htm
|
|
160
|
+
.. _capgains: https://github.com/csingley/capgains
|
|
161
|
+
.. _ib-flex-analyzer: https://github.com/wesm/ib-flex-analyzer
|