- 
                Notifications
    You must be signed in to change notification settings 
- Fork 708
Remove most currency conversions from IBFlex importer #5094
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Remove most currency conversions from IBFlex importer #5094
Conversation
c70543f    to
    90ae088      
    Compare
  
    | 
 This is not correct assumption, taken literally. A security hosted on a particular exchange (and "listed" in currency of that exchange) can still pay dividends in another currency. | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There're multiple unrelated whitespace changes. Please assume that your changes introduce regressions, so someone later will need to investigate which actual changed code hunk introduce a particular regressions. And having unrelated changes complicate that process grossly.
        
          
                ...uchen.portfolio/src/name/abuchen/portfolio/datatransfer/ibflex/IBFlexStatementExtractor.java
          
            Show resolved
            Hide resolved
        
              
          
                ...uchen.portfolio/src/name/abuchen/portfolio/datatransfer/ibflex/IBFlexStatementExtractor.java
          
            Show resolved
            Hide resolved
        
      | */ | ||
| private LocalDateTime extractDate(Element element) | ||
| { | ||
| if (!element.hasAttribute("tradeDate")) | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another example of unrelated changes, and less benign than the whitespace ones: the commit description talks about currency conversion, but actually changes way transaction timestamp is parsed behind the scene. Again, please assume that leads to regressions, and someone who reads the description wouldn't even know this patch introduced it.
(Otherwise I certainly agree that getting transaction timestamp in IBFlexStatementExtractor leaves much to be desired, but these changes flip-flop one tangled way for another - that's clear, because the correct way to get transaction timestamp in modern IBKR XML is from "dateTime" attribute alone. And getting proper, second-resolution timestamp is imperative to properly group transactions into trades.)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I reverse the order then? (Broken out into a separate commit) start with date time and fall back to trade date etc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried to improve this by centralising it all in a single function.
| Thanks for taking a first pass! I squashed all of my changes into a single commit because I wasn’t sure what the policy re multiple commits in a single PR was. Happy to split things out again. 
 I think we are trying to say the same thing, but I lack the correct vocabulary. I mean the currency that a fund is denominated in I guess? I also don’t think this has an effect on the code itself. | 
0c5a8d7    to
    6024b33      
    Compare
  
    Use a single method to extract a LocalDateTime from a transaction element. This improves the result of some imports by adding LocalTime when there previously wasn't one.
The existing exchange rate calculations are spread all over the place and are not entirely consistent. For example, fxRateToBase can only safely be used if the accountCurrency is known. Improve this by using fxRateToBase correctly and by parsing ConversionRate elements contained in the IB XML. This allows doing cross currency conversions even if the accountCurrency is not known.
The IBFlex importer currently has a set of historically grown heuristics around currency conversions: 1. DIVIDEND and TAX transactions are converted to account base currency in buildAccountTransaction() 2. BUY and SELL transactions are converted to account base currency in buildPortfolioTransaction() As far as I can tell, Interactive Brokers doesn't actually work the way that these heuristics assume. - There are no automatic currency conversions, the platform creates forex balances on the fly. - Performing a trade in a foreign currency requires a balance in that currency. - Dividends are distributed in the "base" currency of a security. - fxRateToBase attributes give the exchange rate to the base currency of the account. It is possible to get into a situation where the internal currency of a security doesn't match the listed currency. For example by buying a security denominated in USD on a German exchange and then transferring this to Interactive Brokers. The current heuristics make it impossible to import transactions in this case. Fix this by removing most currency conversions outright. Users will have to maintain additional deposit accounts in the correct currency and then manually track forex conversions. We still create GROSS_VALUE units with forex amounts for securities where the internal currency doesn't match the listed currency. Closes portfolio-performance#4978
6024b33    to
    4d4b293      
    Compare
  
    | // Calculate the FX rate to the base currency | ||
| BigDecimal fxRateToBase = element.getAttribute("fxRateToBase").isEmpty() ? BigDecimal.ONE | ||
| : asExchangeRate(element.getAttribute("fxRateToBase")); | ||
| BigDecimal exchangeRate = getExchangeRate(element, amount.getCurrencyCode(), accountCurrency); | 
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe getExchangeRate can return null.
As I understand it, getExchangeRate is also checking for fxRateToBase and it now attempts to calculate the cross rate using the account currency, to probably it is not a change. But maybe a check for null could make sense
| Hi @lmb, thanks for the contribution. About cbf4f78: The changes to the date parsing make sense. As I plan to a make a new release, I might cherry pick those two commits to be included in the release. | 
| About removing currency conversions: I believe there is value in cleaning up the code. In the past, it was only possible to import to one deposit account at a time (and a deposit account has exactly one currency). That is now much more flexible - one can pick a deposit account per transaction currency that is imported. So I guess some of the conversions can be removed. However, PP makes the assumption that a dividend transactions contains a currency conversion between the transaction currency and the instrument currency. That can be different. Once can configure an instrument with EUR as currency (traded on a European exchange) but still receive dividends in a foreign currency on the deposit account. Then PP needs the exchange rate to properly import the entry. I believe that was the reason for the code in the #buildAccountTransaction method to check for the instrument. | 
| Ok, thinking about it some more I see that the currency conversion to the instrument currency is included. The change imports transactions always in the currency as denoted in the IBFlex XML file. It is an incompatible change. Users trading in multiple currencies have to create deposit accounts in the additional currencies. In general, the change looks good to me. The change make sense - it is closer to what a user would see in IBFlex. You write: 
 Can the forex conversions also be part of the IBFlex XML file? Then they would also be imported. | 
| 
 It does look like it: As usual it's hard to know what the codes mean. 
 Please let me know how you want to proceed here. Should I make changes to this branch, or wait for you to cherry-pick and then rebase? | 
IBFlex: Refactor extractDate to work on all transaction types
IBFlex: Improve handling of currency conversions
IBFlex: Remove most currency conversions
Closes #4978