ibflex 0.14__tar.gz → 1.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.
ibflex-1.0/LICENSE.txt ADDED
@@ -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.
ibflex-1.0/PKG-INFO ADDED
@@ -0,0 +1,172 @@
1
+ Metadata-Version: 2.4
2
+ Name: ibflex
3
+ Version: 1.0
4
+ Summary: Parse Interactive Brokers Flex XML reports and convert to Python types
5
+ Author-email: Christopher Singley <csingley@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/csingley/ibflex
8
+ Keywords: Interactive Brokers,ibkr,flex,xml
9
+ Classifier: Development Status :: 5 - Production/Stable
10
+ Classifier: Intended Audience :: Developers
11
+ Classifier: Intended Audience :: Financial and Insurance Industry
12
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
13
+ Classifier: Topic :: Utilities
14
+ Classifier: Topic :: Office/Business
15
+ Classifier: Topic :: Office/Business :: Financial
16
+ Classifier: Topic :: Office/Business :: Financial :: Accounting
17
+ Classifier: Topic :: Office/Business :: Financial :: Investment
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Natural Language :: English
20
+ Classifier: Programming Language :: Python
21
+ Classifier: Programming Language :: Python :: 3 :: Only
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Programming Language :: Python :: 3.13
26
+ Requires-Python: >=3.10
27
+ Description-Content-Type: text/x-rst
28
+ License-File: LICENSE.txt
29
+ Provides-Extra: web
30
+ Requires-Dist: requests; extra == "web"
31
+ Dynamic: license-file
32
+
33
+ =========================================================
34
+ Python parser for Interactive Brokers Flex XML statements
35
+ =========================================================
36
+
37
+ ``ibflex`` is a Python library for converting brokerage statement data in
38
+ Interactive Brokers' Flex XML format into standard Python data structures,
39
+ so it can be conveniently processed and analyzed with Python scripts.
40
+
41
+ *N.B. This module has nothing to do with programmatic trading.
42
+ It's about reading brokerage reports.*
43
+
44
+ ``ibflex`` is compatible with Python version 3.10+. The parser has no
45
+ dependencies beyond the Python standard library (although the optional client
46
+ for fetching Flex Statements from Interactive Brokers' server does depend
47
+ on `requests`_ ).
48
+
49
+ The parser is lenient by default: unknown XML attributes and element types
50
+ are skipped with a warning rather than raising an error, so new fields added
51
+ by Interactive Brokers won't break your code.
52
+
53
+ `Pull requests`_ are welcome. If you're submitting a pull request for an updated
54
+ type, please do me a favor and include a test case based on your real-world data
55
+ (censored to remove any personal information) in `tests.test_types.py`. You should
56
+ easily be able to cut&paste one of the existing `unittest.TestCase` subclasses in
57
+ that file and adapt it to your own data. Thanks very much; my own datastream does
58
+ not have full coverage of the object model!
59
+
60
+
61
+ Installation
62
+ ============
63
+ ::
64
+
65
+ pip install ibflex
66
+
67
+
68
+ Flex Parser
69
+ ===========
70
+ The primary facility provided is the ``ibflex.parser`` module, which parses
71
+ Flex-format XML data into a hierarchy of Python objects whose structure
72
+ corresponds to that of the original Flex statements, with the data converted
73
+ into appropriate Python types (datetime.datetime, decimal.Decimal, etc.)
74
+
75
+ Usage example:
76
+
77
+ .. code:: python
78
+
79
+ In [1]: from ibflex import parser
80
+
81
+ In [2]: response = parser.parse("2017-01_ibkr.xml")
82
+
83
+ In [3]: response
84
+ Out[3]: FlexQueryResponse(queryName='SCP Everything', type='AF', len(FlexStatements)=1)
85
+
86
+ In [4]: stmt = response.FlexStatements[0]
87
+
88
+ In [5]: stmt
89
+ 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)
90
+
91
+ In [6]: trade = stmt.Trades[-1]
92
+
93
+ In [7]: trade
94
+ 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)
95
+
96
+ In [8]: print(f"{trade.tradeDate} {trade.buySell.name} {abs(trade.quantity)} {trade.symbol} @ {trade.tradePrice} {trade.currency}")
97
+ 2017-01-30 SELL 8 WMIH @ 1.4 USD
98
+
99
+ In [9]: pos = stmt.OpenPositions[-1]
100
+
101
+ In [10]: pos
102
+ 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)
103
+
104
+ In [11]: print(f"{trade.tradeDate} {trade.buySell.name} {abs(trade.quantity)} {trade.symbol} @ {trade.tradePrice} {trade.currency}")
105
+ 2017-01-30 SELL 8 WMIH @ 1.4 USD
106
+
107
+ In [12]: [sec for sec in stmt.SecuritiesInfo if sec.conid == trade.conid][0]
108
+ 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=())
109
+
110
+
111
+ Flex Query Report Configuration
112
+ ===============================
113
+ Configure Flex statements through `Interactive Brokers account management`_ .
114
+ Reports > Flex Queries > Custom Flex Queries > Configure
115
+
116
+ You can configure whatever you like and ibflex should parse it, with these exceptions:
117
+
118
+ * You can't use European-style date formats (dd/MM/yy or dd/MM/yyyy).
119
+ Just accept the default (yyyyMMdd) or get with the program and use ISO-8601 (yyyy-MM-dd).
120
+
121
+ * You should use some delimiter between dates & times. The default delimiter
122
+ (semicolon) is fastest to process.
123
+
124
+ * For the Trades section of the statement, you can't select the options at the
125
+ top for "Symbol Summary", "Asset Class", or "Orders". These will blow up
126
+ the parser. It's fine to check the box for "Asset Class" down below, along
127
+ with the other selections for XML attributes.
128
+
129
+
130
+ Flex Client
131
+ ===========
132
+ Once you've defined various Flex queries, you can generate an access token
133
+ that will allow you to generate statements and download them through the web
134
+ API, instead of logging in to get them.
135
+
136
+ Reports > Settings > FlexWeb Service
137
+
138
+ Once you've got that set up - armed with the token, and the ID# of the desired
139
+ Flex query - ``ibflex.client`` contains the facilities necessary to retrieve
140
+ them:
141
+
142
+ .. code:: python
143
+
144
+ In [1]: from ibflex import client
145
+ In [2]: token = '111111111111111111111111'
146
+ In [3]: query_id = '111111'
147
+ In [4]: response = client.download(token, query_id)
148
+ In [5]: response[:215]
149
+ 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'
150
+
151
+
152
+ ``pip install ibflex[web]`` also installs a ``flexget`` console script:
153
+
154
+ .. code:: bash
155
+
156
+ $ flexget -t 111111111111111111111111 -q 111111 > 2018-01_ibkr.xml
157
+
158
+
159
+ Resources
160
+ =========
161
+ * Interactive Brokers `Activity Flex Query Reference`_
162
+ * Interactive Brokers `FlexWeb Service Reference`_
163
+ * `capgains`_ - package that uses ibflex (inter alia) to calculate realized gains
164
+ * `ib-flex-analyzer`_ - Analyze your Interactive Brokers Flex XML reports with pandas
165
+
166
+ .. _Pull requests: https://github.com/csingley/ibflex/pull/new/master
167
+ .. _requests: https://github.com/requests/requests
168
+ .. _Interactive Brokers account management: https://www.interactivebrokers.com/sso/Login
169
+ .. _Activity Flex Query Reference: https://www.interactivebrokers.com/en/software/reportguide/reportguide.htm#reportguide/activity_flex_query_reference.htm
170
+ .. _FlexWeb Service Reference: https://www.interactivebrokers.com/en/software/am/am/reports/flex_web_service_version_3.htm
171
+ .. _capgains: https://github.com/csingley/capgains
172
+ .. _ib-flex-analyzer: https://github.com/wesm/ib-flex-analyzer
@@ -9,15 +9,14 @@ so it can be conveniently processed and analyzed with Python scripts.
9
9
  *N.B. This module has nothing to do with programmatic trading.
10
10
  It's about reading brokerage reports.*
11
11
 
12
- ``ibflex`` is compatible with Python version 3.7+. The parser has no
12
+ ``ibflex`` is compatible with Python version 3.10+. The parser has no
13
13
  dependencies beyond the Python standard library (although the optional client
14
14
  for fetching Flex Statements from Interactive Brokers' server does depend
15
15
  on `requests`_ ).
16
16
 
17
- **This module is alpha software!** It works and it's useful, but the
18
- API, data structures, etc. are likely to see major changes. Several XML
19
- schemata are missing, and a few of the more newly-introduced attributes
20
- for the existing schemata. There are probably bugs.
17
+ The parser is lenient by default: unknown XML attributes and element types
18
+ are skipped with a warning rather than raising an error, so new fields added
19
+ by Interactive Brokers won't break your code.
21
20
 
22
21
  `Pull requests`_ are welcome. If you're submitting a pull request for an updated
23
22
  type, please do me a favor and include a test case based on your real-world data
@@ -118,14 +117,7 @@ them:
118
117
  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'
119
118
 
120
119
 
121
- You can also just execute client.main() as a script:
122
-
123
- .. code:: bash
124
-
125
- $ python client.py -t 111111111111111111111111 -q 111111 > 2018-01_ibkr.xml
126
-
127
-
128
- Finally, setup.py installs a script at ``~/.local/bin/flexget``... cron-tastic!
120
+ ``pip install ibflex[web]`` also installs a ``flexget`` console script:
129
121
 
130
122
  .. code:: bash
131
123
 
@@ -141,7 +133,7 @@ Resources
141
133
 
142
134
  .. _Pull requests: https://github.com/csingley/ibflex/pull/new/master
143
135
  .. _requests: https://github.com/requests/requests
144
- .. _Interactive Brokers account management: https://gdcdyn.interactivebrokers.com/sso/Login
136
+ .. _Interactive Brokers account management: https://www.interactivebrokers.com/sso/Login
145
137
  .. _Activity Flex Query Reference: https://www.interactivebrokers.com/en/software/reportguide/reportguide.htm#reportguide/activity_flex_query_reference.htm
146
138
  .. _FlexWeb Service Reference: https://www.interactivebrokers.com/en/software/am/am/reports/flex_web_service_version_3.htm
147
139
  .. _capgains: https://github.com/csingley/capgains