csingley / ibflex

Python parser for Interactive Brokers Flex XML statements
MIT License
85 stars 42 forks source link

ibflex.parser.FlexParserError: CashReportCurrency has no attribute 'endingCashIBUKL' #52

Closed Dr-Nuke closed 1 year ago

Dr-Nuke commented 2 years ago

Since very recently, my flexqueries do not parse anymore. one month ago, it still worked fine. Python 3.7.10 ibflex 0.15 (same with 0.14) WSL Ubuntu 18.04.4 LTS

sample code:

import yaml
credsfile="../ibkr.yaml"
with open(credsfile, 'r') as f:
                config = yaml.safe_load(f)
                token = config['token']
                queryId = config['queryId']

from ibflex import client, parser, Types
response = client.download(token, queryId)

print('received valid FlexQuery information:\n' + str(response[:270]))
print('failing parsing of the response:')
parser.parse(response)
received valid FlexQuery information:
b'<FlexQueryResponse queryName="my monthly flexquery" type="AF">\n<FlexStatements count="1">\n<FlexStatement accountId="U*******" fromDate="2022-06-01" toDate="2022-06-30" period="LastMonth" whenGenerated="2022-07-02;10:12:05">\n<CashReport>\n<CashReportCurrency currency="BASE_S'...
failing parsing of the response:
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
~/miniconda3/envs/IBenv/lib/python3.7/site-packages/ibflex/parser.py in parse_data_element(elem)
    116             parse_element_attr(Class, k, v)
--> 117             for k, v in elem.attrib.items()
    118         )

~/miniconda3/envs/IBenv/lib/python3.7/site-packages/ibflex/parser.py in <genexpr>(.0)
    116             parse_element_attr(Class, k, v)
--> 117             for k, v in elem.attrib.items()
    118         )

~/miniconda3/envs/IBenv/lib/python3.7/site-packages/ibflex/parser.py in parse_element_attr(Class, name, value)
    155     #  in parse_data_element(), instead accepting it as a function arg here.
--> 156     Type = Class.__annotations__[name]
    157 

KeyError: 'endingCashIBUKL'

During handling of the above exception, another exception occurred:

FlexParserError                           Traceback (most recent call last)
<ipython-input-4-4e26de39b5b6> in <module>
     11 print('received valid FlexQuery information:\n' + str(response[:270]))
     12 print('failing parsing of the response:')
---> 13 parser.parse(response)

~/miniconda3/envs/IBenv/lib/python3.7/site-packages/ibflex/parser.py in parse(source)
     51     if root.tag != "FlexQueryResponse":
     52         raise FlexParserError("Not a FlexQueryResponse")
---> 53     parsed = parse_element(root)
     54     assert isinstance(parsed, Types.FlexQueryResponse)
     55     return parsed

~/miniconda3/envs/IBenv/lib/python3.7/site-packages/ibflex/parser.py in parse_element(elem)
     83         return parse_element_container(elem)
     84 
---> 85     return parse_data_element(elem)
     86 
     87 

~/miniconda3/envs/IBenv/lib/python3.7/site-packages/ibflex/parser.py in parse_data_element(elem)
    123     #  FlexQueryResponse & FlexStatement are the only data elements
    124     #  that contain other data elements.
--> 125     contained_elements = {child.tag: parse_element(child) for child in elem}
    126     if contained_elements:
    127         assert elem.tag in ("FlexQueryResponse", "FlexStatement")

~/miniconda3/envs/IBenv/lib/python3.7/site-packages/ibflex/parser.py in <dictcomp>(.0)
    123     #  FlexQueryResponse & FlexStatement are the only data elements
    124     #  that contain other data elements.
--> 125     contained_elements = {child.tag: parse_element(child) for child in elem}
    126     if contained_elements:
    127         assert elem.tag in ("FlexQueryResponse", "FlexStatement")

~/miniconda3/envs/IBenv/lib/python3.7/site-packages/ibflex/parser.py in parse_element(elem)
     78             raise FlexParserError(msg)
     79 
---> 80         return parse_element_container(elem)
     81 
     82     if not elem.attrib:

~/miniconda3/envs/IBenv/lib/python3.7/site-packages/ibflex/parser.py in parse_element_container(elem)
     99         return tuple(itertools.chain.from_iterable(fxlots))
    100 
--> 101     instances = tuple(parse_data_element(child) for child in elem)
    102     return instances
    103 

~/miniconda3/envs/IBenv/lib/python3.7/site-packages/ibflex/parser.py in <genexpr>(.0)
     99         return tuple(itertools.chain.from_iterable(fxlots))
    100 
--> 101     instances = tuple(parse_data_element(child) for child in elem)
    102     return instances
    103 

~/miniconda3/envs/IBenv/lib/python3.7/site-packages/ibflex/parser.py in parse_data_element(elem)
    123     #  FlexQueryResponse & FlexStatement are the only data elements
    124     #  that contain other data elements.
--> 125     contained_elements = {child.tag: parse_element(child) for child in elem}
    126     if contained_elements:
    127         assert elem.tag in ("FlexQueryResponse", "FlexStatement")

~/miniconda3/envs/IBenv/lib/python3.7/site-packages/ibflex/parser.py in <dictcomp>(.0)
    123     #  FlexQueryResponse & FlexStatement are the only data elements
    124     #  that contain other data elements.
--> 125     contained_elements = {child.tag: parse_element(child) for child in elem}
    126     if contained_elements:
    127         assert elem.tag in ("FlexQueryResponse", "FlexStatement")

~/miniconda3/envs/IBenv/lib/python3.7/site-packages/ibflex/parser.py in parse_element(elem)
     81 
     82     if not elem.attrib:
---> 83         return parse_element_container(elem)
     84 
     85     return parse_data_element(elem)

~/miniconda3/envs/IBenv/lib/python3.7/site-packages/ibflex/parser.py in parse_element_container(elem)
     99         return tuple(itertools.chain.from_iterable(fxlots))
    100 
--> 101     instances = tuple(parse_data_element(child) for child in elem)
    102     return instances
    103 

~/miniconda3/envs/IBenv/lib/python3.7/site-packages/ibflex/parser.py in <genexpr>(.0)
     99         return tuple(itertools.chain.from_iterable(fxlots))
    100 
--> 101     instances = tuple(parse_data_element(child) for child in elem)
    102     return instances
    103 

~/miniconda3/envs/IBenv/lib/python3.7/site-packages/ibflex/parser.py in parse_data_element(elem)
    119     except KeyError as exc:
    120         msg = f"{Class.__name__} has no attribute " + str(exc)
--> 121         raise FlexParserError(msg)
    122 
    123     #  FlexQueryResponse & FlexStatement are the only data elements

FlexParserError: CashReportCurrency has no attribute 'endingCashIBUKL'
csingley commented 2 years ago

So add the endingCashIBUKL? IB does this stuff all the time, that's why I made it so easy to work with ibflex.Types. CashReportCurrency is on line 502, and you appear to be holding valid data in your hands. Let me know if you can't figure it out