Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
b41f90d
Add a bunch of fields that appear in my flex queries on new types
vroonhof May 26, 2025
e4c4913
All types from enabling everything
vroonhof May 26, 2025
7ade81b
More attributes (now enabled all fields)
vroonhof May 26, 2025
330e690
The new summary fields have MULTI as the date values
vroonhof May 26, 2025
ae82e52
Merge in fields form ibflex2
robcohen Dec 16, 2025
97cd84a
Add a few more missing fields for CorporateAction
vroonhof Jan 25, 2026
37cf197
Merge pull request #1 from vroonhof/pullfromibflex2
vroonhof Jan 25, 2026
d48d7b9
Initial plan
Copilot Jan 29, 2026
c70b47f
Fix Trade.initialInvestment type and add liteSurchargeAccruals field
Copilot Jan 29, 2026
3b4062c
Merge pull request #2 from vroonhof/copilot/fix-issue-106-library-error
vroonhof Jan 29, 2026
653b22f
Add unknown attribute tolerance for IB Flex XML parsing
cursoragent Feb 5, 2026
18926db
Initial plan
Copilot Feb 5, 2026
0e62635
Mark package as vendored with version suffix and README notice
Copilot Feb 5, 2026
3b8e761
Keep assertion that only FlexQueryResponse and FlexStatement contain …
cursoragent Feb 5, 2026
9bad47c
Merge pull request #4 from vroonhof/cursor/ib-export-attribute-tolera…
vroonhof Feb 5, 2026
7395223
Revise README for vendored ibflex library details
vroonhof Feb 5, 2026
3992906
Merge pull request #5 from vroonhof/copilot/vendor-package-version-up…
vroonhof Feb 5, 2026
3df5d45
Add missing fields to EquitySummaryByReportDateInBase
google-labs-jules[bot] Feb 5, 2026
ce25064
Merge pull request #6 from vroonhof/fix-issue-132-missing-fields-9228…
vroonhof Feb 5, 2026
3e771f4
Initial plan
Copilot Feb 12, 2026
ed5660b
Add OTC transfer type support for crypto transfers
Copilot Feb 12, 2026
86cd6e8
Merge pull request #7 from vroonhof/copilot/fix-issue-162
vroonhof Feb 12, 2026
17ed932
Initial plan
Copilot Feb 18, 2026
709fe30
Add FIFO (LF) code to Code enum with test
Copilot Feb 18, 2026
7a36e4b
Fix LF enum naming: LIQUIDATION_FORCED not FIFO
Copilot Feb 18, 2026
4e223da
Add docstring to TradeLiquidationForcedTestCase
Copilot Feb 18, 2026
7a4d3e0
Merge pull request #8 from vroonhof/copilot/fix-missing-lf-enum-value
vroonhof Feb 18, 2026
e4eeeae
Add support for StockGrantActivity
hygt Feb 20, 2026
7abdc0e
Initial plan
Copilot Mar 5, 2026
4e899b2
Add LIT (Limit If Touched) to OrderType enum
Copilot Mar 5, 2026
bffd943
Initial plan
Copilot Mar 5, 2026
32844c8
Fix CI: update Python versions, switch to pytest, fix mypy errors
Copilot Mar 5, 2026
76259a5
Merge pull request #11 from vroonhof/copilot/fix-github-action-python…
vroonhof Mar 5, 2026
f7d7ff0
Merge pull request #10 from vroonhof/copilot/fix-issue-264
vroonhof Mar 5, 2026
c50c628
Merge pull request #9 from hygt/master
vroonhof Mar 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/commit-ibflex.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.7, 3.8]
python-version: ["3.11", "3.12"]

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v5
with:
python-version: ${{ matrix.python-version }}
# - name: Cache pip
# uses: actions/cache@v2
# uses: actions/cache@v4
# with:
# path: ~/.cache/pip # This path is specific to Ubuntu
# # Look to see if there is a cache hit for the corresponding requirements file
Expand All @@ -29,5 +29,5 @@ jobs:
run: pip install -r requirements-development.txt
- name: Static analysis with mypy
run: mypy ibflex tests
- name: Test with nose
run: nosetests -dsv --with-coverage --cover-package ibflex tests/*.py
- name: Test with pytest
run: pytest -v --cov=ibflex tests/
17 changes: 17 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,23 @@
Python parser for Interactive Brokers Flex XML statements
=========================================================

**VENDORED PACKAGE NOTICE**
---------------------------

This is a vendored and enhanced version of the original ibflex library by Christopher Singley
(https://github.com/csingley/ibflex).

This fork
* includes additional data fields beyond the upstream version
* incorporates similar improvements from robcohen/ibflex2
* includes an opt-in mechanism to be tolerant against IBKR adding new but unimportant attributes on a regular basis.

The version number
includes a "+vroonhof.vendored" suffix to distinguish it from the original package.

**ORGINAL README**
------------------

``ibflex`` is a Python library for converting brokerage statement data in
Interactive Brokers' Flex XML format into standard Python data structures,
so it can be conveniently processed and analyzed with Python scripts.
Expand Down
118 changes: 109 additions & 9 deletions ibflex/Types.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class decorator. Class attributes are annotated with PEP 484 type hints.
"SymbolSummary",
"AssetSummary",
"Order",
"StockGrantActivity",
]

import datetime
Expand Down Expand Up @@ -187,7 +188,7 @@ class FlexStatement(FlexElement):
ConversionRates: Tuple["ConversionRate", ...] = ()
HKIPOOpenSubscriptions: Tuple = () # TODO
CommissionCredits: Tuple = () # TODO
StockGrantActivities: Tuple = () # TODO
StockGrantActivities: Tuple["StockGrantActivity", ...] = ()
SLBCollaterals: Tuple = () # TODO
IncentiveCouponAccrualDetails: Tuple = () # TODO
DepositsOnHold: Tuple = () # TODO
Expand Down Expand Up @@ -468,7 +469,6 @@ class EquitySummaryByReportDateInBase(FlexElement):
physDel: Optional[decimal.Decimal] = None
physDelLong: Optional[decimal.Decimal] = None
physDelShort: Optional[decimal.Decimal] = None
currency: Optional[str] = None
insuredBankDepositRedemptionCashComponentLong: Optional[decimal.Decimal] = None
insuredBankDepositRedemptionCashComponentShort: Optional[decimal.Decimal] = None
incentiveCouponAccrualsLong: Optional[decimal.Decimal] = None
Expand All @@ -479,6 +479,12 @@ class EquitySummaryByReportDateInBase(FlexElement):
marginFinancingChargeAccrualsShort: Optional[decimal.Decimal] = None
cryptoLong: Optional[decimal.Decimal] = None
cryptoShort: Optional[decimal.Decimal] = None
liteSurchargeAccruals: Optional[decimal.Decimal] = None
liteSurchargeAccrualsLong: Optional[decimal.Decimal] = None
liteSurchargeAccrualsShort: Optional[decimal.Decimal] = None
cgtWithholdingAccruals: Optional[decimal.Decimal] = None
cgtWithholdingAccrualsLong: Optional[decimal.Decimal] = None
cgtWithholdingAccrualsShort: Optional[decimal.Decimal] = None


@dataclass(frozen=True)
Expand Down Expand Up @@ -709,6 +715,8 @@ class CashReportCurrency(FlexElement):
salesTaxYTD: Optional[decimal.Decimal] = None
salesTaxPaxos: Optional[decimal.Decimal] = None
otherIncome: Optional[decimal.Decimal] = None
otherIncomeMTD: Optional[decimal.Decimal] = None
otherIncomeYTD: Optional[decimal.Decimal] = None
otherIncomeSec: Optional[decimal.Decimal] = None
otherIncomeCom: Optional[decimal.Decimal] = None
otherFeesMTD: Optional[decimal.Decimal] = None
Expand Down Expand Up @@ -1144,7 +1152,8 @@ class Trade(FlexElement):
subCategory: Optional[str] = None
issuerCountryCode: Optional[str] = None
rtn: Optional[str] = None
initialInvestment: Optional[decimal.Decimal] = None
initialInvestment: Optional[bool] = None
positionActionID: Optional[str] = None


@dataclass(frozen=True)
Expand Down Expand Up @@ -1296,7 +1305,8 @@ class Lot(FlexElement):
issuerCountryCode: Optional[str] = None
relatedTradeID: Optional[str] = None
rtn: Optional[str] = None
initialInvestment: Optional[decimal.Decimal] = None
initialInvestment: Optional[bool] = None
positionActionID: Optional[str] = None


@dataclass(frozen=True)
Expand Down Expand Up @@ -1385,19 +1395,29 @@ class SymbolSummary(FlexElement):
tradeID: Optional[str] = None
orderID: Optional[decimal.Decimal] = None
execID: Optional[str] = None
ibExecID: Optional[str] = None
extExecID: Optional[str] = None
exchOrderId: Optional[str] = None
brokerageOrderID: Optional[str] = None
orderReference: Optional[str] = None
volatilityOrderLink: Optional[str] = None
clearingFirmID: Optional[str] = None
origTradePrice: Optional[decimal.Decimal] = None
origTradeDate: Optional[datetime.date] = None
origTradeID: Optional[str] = None
transactionID: Optional[str] = None
# Despite the name, `orderTime` actually contains date/time data.
orderTime: Optional[datetime.datetime] = None
openDateTime: Optional[datetime.datetime] = None
holdingPeriodDateTime: Optional[datetime.datetime] = None
dateTime: Optional[datetime.datetime] = None
reportDate: Optional[datetime.date] = None
settleDate: Optional[datetime.date] = None
settleDateTarget: Optional[datetime.date] = None # expected date of ownership transfer
taxes: Optional[decimal.Decimal] = None
tradeDate: Optional[datetime.date] = None
tradePrice: Optional[decimal.Decimal] = None
tradeMoney: Optional[decimal.Decimal] = None # TradeMoney = Proceeds + Fees + Commissions
exchange: Optional[str] = None
buySell: Optional[enums.BuySell] = None
quantity: Optional[decimal.Decimal] = None
Expand Down Expand Up @@ -1427,6 +1447,30 @@ class SymbolSummary(FlexElement):
relatedTradeID: Optional[str] = None
origTransactionID: Optional[str] = None
relatedTransactionID: Optional[str] = None
positionActionID: Optional[str] = None
changeInPrice: Optional[decimal.Decimal] = None
changeInQuantity: Optional[decimal.Decimal] = None
closePrice: Optional[decimal.Decimal] = None
commodityType: Optional[str] = None
cost: Optional[decimal.Decimal] = None
deliveryType: Optional[str] = None
fifoPnlRealized: Optional[decimal.Decimal] = None
fineness: Optional[decimal.Decimal] = None
ibCommission: Optional[decimal.Decimal] = None
ibCommissionCurrency: Optional[str] = None
ibOrderID: Optional[str] = None
initialInvestment: Optional[bool] = None
mtmPnl: Optional[decimal.Decimal] = None
netCash: Optional[decimal.Decimal] = None
netCashInBase: Optional[decimal.Decimal] = None
notes: Optional[str] = None
openCloseIndicator: Optional[enums.OpenClose] = None
origOrderID: Optional[str] = None
rtn: Optional[str] = None
serialNumber: Optional[str] = None
weight: Optional[str] = None
whenRealized: Optional[datetime.datetime] = None
whenReopened: Optional[datetime.datetime] = None


@dataclass(frozen=True)
Expand Down Expand Up @@ -1535,7 +1579,8 @@ class AssetSummary(FlexElement):
origTransactionID: Optional[str] = None
relatedTransactionID: Optional[str] = None
rtn: Optional[str] = None
initialInvestment: Optional[decimal.Decimal] = None
initialInvestment: Optional[bool] = None
positionActionID: Optional[str] = None


@dataclass(frozen=True)
Expand Down Expand Up @@ -1638,12 +1683,13 @@ class Order(FlexElement):
origTransactionID: Optional[str] = None
relatedTransactionID: Optional[str] = None
rtn: Optional[str] = None
initialInvestment: Optional[decimal.Decimal] = None
initialInvestment: Optional[bool] = None
serialNumber: Optional[str] = None
deliveryType: Optional[str] = None
commodityType: Optional[str] = None
fineness: Optional[decimal.Decimal] = None
weight: Optional[str] = None
positionActionID: Optional[str] = None


@dataclass(frozen=True)
Expand Down Expand Up @@ -1796,7 +1842,7 @@ class OptionEAE(FlexElement):
origTransactionID: Optional[str] = None
relatedTransactionID: Optional[str] = None
rtn: Optional[str] = None
initialInvestment: Optional[decimal.Decimal] = None
initialInvestment: Optional[bool] = None
serialNumber: Optional[str] = None
deliveryType: Optional[str] = None
commodityType: Optional[str] = None
Expand Down Expand Up @@ -2122,7 +2168,12 @@ class Transfer(FlexElement):
commodityType: Optional[str] = None
fineness: Optional[decimal.Decimal] = None
weight: Optional[str] = None

figi: Optional[str] = None
settleDate: Optional[datetime.date] = None
issuerCountryCode: Optional[str] = None
levelOfDetail: Optional[str] = None
positionInstructionID: Optional[str] = None
positionInstructionSetID: Optional[str] = None

@dataclass(frozen=True)
class UnsettledTransfer(FlexElement):
Expand Down Expand Up @@ -2245,6 +2296,11 @@ class CorporateAction(FlexElement):
commodityType: Optional[str] = None
fineness: Optional[decimal.Decimal] = None
weight: Optional[str] = None
figi: Optional[str] = None
issuerCountryCode: Optional[str] = None
costBasis: Optional[decimal.Decimal] = None




@dataclass(frozen=True)
Expand Down Expand Up @@ -2480,7 +2536,7 @@ class SecurityInfo(FlexElement):
origTransactionID: Optional[str] = None
relatedTransactionID: Optional[str] = None
rtn: Optional[str] = None
initialInvestment: Optional[decimal.Decimal] = None
initialInvestment: Optional[bool] = None
serialNumber: Optional[str] = None
deliveryType: Optional[str] = None
commodityType: Optional[str] = None
Expand Down Expand Up @@ -2819,5 +2875,49 @@ class SLBOpenContract(FlexElement):
fineness: Optional[decimal.Decimal] = None
weight: Optional[decimal.Decimal] = None


@dataclass(frozen=True)
class StockGrantActivity(FlexElement):
accountId: Optional[str] = None
acctAlias: Optional[str] = None
model: Optional[str] = None
currency: Optional[str] = None
fxRateToBase: Optional[decimal.Decimal] = None
assetCategory: Optional[enums.AssetClass] = None
subCategory: Optional[str] = None
symbol: Optional[str] = None
description: Optional[str] = None
conid: Optional[str] = None
securityID: Optional[str] = None
securityIDType: Optional[str] = None
cusip: Optional[str] = None
isin: Optional[str] = None
figi: Optional[str] = None
listingExchange: Optional[str] = None
underlyingConid: Optional[str] = None
underlyingSymbol: Optional[str] = None
underlyingSecurityID: Optional[str] = None
underlyingListingExchange: Optional[str] = None
issuer: Optional[str] = None
issuerCountryCode: Optional[str] = None
multiplier: Optional[decimal.Decimal] = None
strike: Optional[decimal.Decimal] = None
expiry: Optional[datetime.date] = None
putCall: Optional[enums.PutCall] = None
principalAdjustFactor: Optional[decimal.Decimal] = None
reportDate: Optional[datetime.date] = None
activityDescription: Optional[str] = None
awardDate: Optional[datetime.date] = None
vestingDate: Optional[datetime.date] = None
quantity: Optional[decimal.Decimal] = None
price: Optional[decimal.Decimal] = None
value: Optional[decimal.Decimal] = None
serialNumber: Optional[str] = None
deliveryType: Optional[str] = None
commodityType: Optional[str] = None
fineness: Optional[decimal.Decimal] = None
weight: Optional[decimal.Decimal] = None


# Type alias to work around https://github.com/python/mypy/issues/1775
_ClientFeesDetail = ClientFeesDetail
2 changes: 2 additions & 0 deletions ibflex/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
from .Types import *
from . import parser
from .parser import parse
from .parser import enable_unknown_attribute_tolerance
from .parser import disable_unknown_attribute_tolerance
from . import utils
from . import client

Expand Down
4 changes: 2 additions & 2 deletions ibflex/__version__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
__description__ = (
"Parse Interactive Brokers Flex XML reports and convert to Python types"
),
__url__ = "https://github.com/csingley/ibflex"
__version__ = "0.16"
__url__ = "https://github.com/vroonhof/ibflex"
__version__ = "0.16+vroonhof.vendored"
__author__ = "Christopher Singley"
__author_email__ = "csingley@gmail.com"
__license__ = "MIT"
Expand Down
2 changes: 0 additions & 2 deletions ibflex/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,6 @@ def request_statement(
"""First part of the 2-step download process.
"""
url = url or REQUEST_URL
### AKE FIX
url = 'https://ndcdyn.interactivebrokers.com/portal.flexweb/api/v1/flexQuery'
response = submit_request(url, token, query=query_id)
stmt_access = parse_stmt_response(response)
if isinstance(stmt_access, StatementError):
Expand Down
3 changes: 3 additions & 0 deletions ibflex/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ class Code(str, enum.Enum):
INVESTOR = "INV" # Investment Transfer from Investor
MARGINLOW = "L" # Ordered by IB (Margin Violation)
WASHSALE = "LD" # Adjusted by Loss Disallowed from Wash Sale
LIQUIDATION_FORCED = "LF" # Forced Liquidation
LIFO = "LI" # Last In, First Out (LIFO) tax lot-matching method
LTCG = "LT" # Long-term P/L
LOAN = "Lo" # Direct Loan
Expand Down Expand Up @@ -170,6 +171,7 @@ class OrderType(str, enum.Enum):
TRAIL = "TRAIL"
REL = "REL"
MIT = "MIT"
LIT = "LIT"

@enum.unique
class Reorg(str, enum.Enum):
Expand Down Expand Up @@ -236,6 +238,7 @@ class TransferType(str, enum.Enum):
ACATS = "ACATS"
ATON = "ATON"
FOP = "FOP"
OTC = "OTC"


@enum.unique
Expand Down
Loading