Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -3679,4 +3679,112 @@ public void testIBFlexStatementFile28() throws IOException
BigDecimal eqqqTolerance = new BigDecimal("0.0000001"); // Same tolerance as HIDR test
assertThat(eqqqUnit.getExchangeRate().subtract(eqqqExpectedRate).abs().compareTo(eqqqTolerance) < 0, is(true));
}

@Test
public void testIBFlexStatementFile29() throws IOException
{
IBFlexStatementExtractor extractor = new IBFlexStatementExtractor(new Client());

InputStream activityStatement = getClass().getResourceAsStream("testIBFlexStatementFile29.xml");
Extractor.InputFile tempFile = createTempFile(activityStatement);

List<Exception> errors = new ArrayList<>();

List<Item> results = extractor.extract(Collections.singletonList(tempFile), errors);

assertThat(errors, empty());

List<Item> securityItems = results.stream().filter(SecurityItem.class::isInstance) //
.collect(Collectors.toList());

// Should have 6 securities total:
// 1. GCM CAD (CA38501D2041) - Case 1 base trade
// 2. GCM EUR (CA38501D2041) - Case 1 trade (same ISIN, different currency - NEW security)
// 3. GCM CAD (CA38501D2042) - Case 2 trade (same symbol, different ISIN - NEW security)
// 4. GCM EUR (CA38501D2043) - Case 2 dividend (different ISIN from Case 2 trade - NEW security)
// 5. UUU CAD (no ISIN) - Case 3 base trade
// 6. UUU EUR (no ISIN) - Case 3 trade (same symbol, different currency - NEW security)
assertThat("Should create 6 distinct securities", securityItems.size(), is(6));

// Verify Case 1: Same ISIN, different currency creates separate securities
Security gcmCad = securityItems.stream() //
.map(item -> ((SecurityItem) item).getSecurity()) //
.filter(s -> "CA38501D2041".equals(s.getIsin()) && "CAD".equals(s.getCurrencyCode())) //
.findFirst() //
.orElseThrow(() -> new AssertionError("GCM CAD security not found"));
assertThat(gcmCad.getTickerSymbol(), is("GCM.TO"));

Security gcmEur = securityItems.stream() //
.map(item -> ((SecurityItem) item).getSecurity()) //
.filter(s -> "CA38501D2041".equals(s.getIsin()) && "EUR".equals(s.getCurrencyCode())) //
.findFirst() //
.orElseThrow(() -> new AssertionError("GCM EUR security not found"));
assertThat(gcmEur.getTickerSymbol(), is("GCM.TO"));
assertThat("Same ISIN but different currencies should be separate securities", gcmCad.getUUID(), not(is(gcmEur.getUUID())));

// Verify Case 2: Same symbol, different ISIN creates separate securities
Security gcmCad2042 = securityItems.stream() //
.map(item -> ((SecurityItem) item).getSecurity()) //
.filter(s -> "CA38501D2042".equals(s.getIsin())) //
.findFirst() //
.orElseThrow(() -> new AssertionError("GCM CA38501D2042 security not found"));
assertThat(gcmCad2042.getTickerSymbol(), is("GCM.TO"));

Security gcmEur2043 = securityItems.stream() //
.map(item -> ((SecurityItem) item).getSecurity()) //
.filter(s -> "CA38501D2043".equals(s.getIsin())) //
.findFirst() //
.orElseThrow(() -> new AssertionError("GCM CA38501D2043 security not found"));
assertThat(gcmEur2043.getTickerSymbol(), is("GCM.TO"));
assertThat("Same symbol but different ISINs should be separate securities", gcmCad2042.getUUID(), not(is(gcmEur2043.getUUID())));

// Verify Case 3: Same symbol, no ISIN, different currency creates separate securities
Security uuuCad = securityItems.stream() //
.map(item -> ((SecurityItem) item).getSecurity()) //
.filter(s -> (s.getIsin() == null || s.getIsin().isEmpty()) && "UUU.TO".equals(s.getTickerSymbol()) && "CAD".equals(s.getCurrencyCode())) //
.findFirst() //
.orElseThrow(() -> new AssertionError("UUU CAD security not found"));
assertThat(uuuCad.getTickerSymbol(), is("UUU.TO"));

Security uuuEur = securityItems.stream() //
.map(item -> ((SecurityItem) item).getSecurity()) //
.filter(s -> (s.getIsin() == null || s.getIsin().isEmpty()) && "UUU.TO".equals(s.getTickerSymbol()) && "EUR".equals(s.getCurrencyCode())) //
.findFirst() //
.orElseThrow(() -> new AssertionError("UUU EUR security not found"));
assertThat(uuuEur.getTickerSymbol(), is("UUU.TO"));
assertThat("Same symbol but different currencies should be separate securities", uuuCad.getUUID(), not(is(uuuEur.getUUID())));

// Verify dividends are associated with correct securities
List<AccountTransaction> dividends = results.stream() //
.filter(TransactionItem.class::isInstance) //
.map(item -> (AccountTransaction) ((TransactionItem) item).getSubject()) //
.filter(t -> t.getType() == AccountTransaction.Type.DIVIDENDS) //
.collect(Collectors.toList());

assertThat("Should have 3 dividend transactions", dividends.size(), is(3));

// Verify Case 1 dividend: ISIN match with non-strict currency (should match one of the Case 1 securities)
AccountTransaction case1Dividend = dividends.stream() //
.filter(t -> "CA38501D2041".equals(t.getSecurity().getIsin()) && "USD".equals(t.getCurrencyCode())) //
.findFirst() //
.orElseThrow(() -> new AssertionError("Case 1 USD dividend not found"));
assertThat("Case 1 dividend should match one of the Case 1 securities", case1Dividend.getSecurity().getIsin(), is("CA38501D2041"));

// Verify Case 2 dividend: Creates new security (different ISIN)
AccountTransaction case2Dividend = dividends.stream() //
.filter(t -> "CA38501D2043".equals(t.getSecurity().getIsin())) //
.findFirst() //
.orElseThrow(() -> new AssertionError("Case 2 EUR dividend not found"));
assertThat(case2Dividend.getCurrencyCode(), is("EUR"));
assertThat(case2Dividend.getSecurity().getTickerSymbol(), is("GCM.TO"));

// Verify Case 3 dividend: Ticker match with no ISIN (should match one of the Case 3 securities)
AccountTransaction case3Dividend = dividends.stream() //
.filter(t -> (t.getSecurity().getIsin() == null || t.getSecurity().getIsin().isEmpty())
&& "UUU.TO".equals(t.getSecurity().getTickerSymbol())
&& "AUD".equals(t.getCurrencyCode())) //
.findFirst() //
.orElseThrow(() -> new AssertionError("Case 3 AUD dividend not found"));
assertThat("Case 3 dividend should match one of the Case 3 securities", case3Dividend.getSecurity().getTickerSymbol(), is("UUU.TO"));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@
<CashTransaction accountId="U123456" acctAlias="" currency="CHF" assetCategory="" fxRateToBase="1" symbol="" description="BALANCE OF MONTHLY MINIMUM FEE FOR MAR 2013" conid="" securityID="" securityIDType="" cusip="" isin="" underlyingConid="" underlyingSymbol="" issuer="" multiplier="0" strike="" expiry="" putCall="" dateTime="2013-04-03" amount="-9.49" type="Other Fees" tradeID="" code="" />
<CashTransaction accountId="U123456" acctAlias="" currency="CAD" assetCategory="" fxRateToBase="0.91249" symbol="" description="CAD DEBIT INT FOR JAN-2013" conid="" securityID="" securityIDType="" cusip="" isin="" underlyingConid="" underlyingSymbol="" issuer="" multiplier="0" strike="" expiry="" putCall="" dateTime="2013-02-05" amount="1.23" type="Broker Interest Received" tradeID="" code="" />
<CashTransaction accountId="U123456" acctAlias="" currency="CAD" assetCategory="" fxRateToBase="0.91249" symbol="" description="CAD DEBIT INT FOR JAN-2013" conid="" securityID="" securityIDType="" cusip="" isin="" underlyingConid="" underlyingSymbol="" issuer="" multiplier="0" strike="" expiry="" putCall="" dateTime="2013-02-05" amount="-15.17" type="Broker Interest Paid" tradeID="" code="" />
<CashTransaction accountId="U123456" acctAlias="" currency="USD" assetCategory="" fxRateToBase="0.83701" symbol="GCM.TO" description="GCM.TO CASH DIVIDEND USD 0.6900000000 - US TAX" conid="6691" securityID="" securityIDType="" cusip="" isin="" underlyingConid="" underlyingSymbol="" issuer="" multiplier="0" strike="" expiry="" putCall="" dateTime="2017-09-15" amount="-2.07" type="Withholding Tax" tradeID="" code="" />
<CashTransaction accountId="U123456" acctAlias="" currency="USD" assetCategory="" fxRateToBase="0.83701" symbol="GCM.TO" description="GCM.TO CASH DIVIDEND USD 0.6900000000 - US TAX" conid="80845553" securityID="" securityIDType="" cusip="" isin="" underlyingConid="" underlyingSymbol="" issuer="" multiplier="0" strike="" expiry="" putCall="" dateTime="2017-09-15" amount="-2.07" type="Withholding Tax" tradeID="" code="" />
<CashTransaction accountId="U123456" acctAlias="" currency="USD" assetCategory="" fxRateToBase="1" symbol="" description="NP SECURITIES AND FUTURES VALUE BUNDLE FOR APR 2017" conid="" securityID="" securityIDType="" cusip="" isin="" underlyingConid="" underlyingSymbol="" issuer="" multiplier="0" strike="" expiry="" putCall="" dateTime="2017-05-03" amount="-9.18" type="Other Fees" tradeID="" code="" />
<CashTransaction accountId="U123456" acctAlias="" currency="USD" assetCategory="" fxRateToBase="1" symbol="" description="NP SECURITIES AND FUTURES VALUE BUNDLE FOR APR 2017" conid="" securityID="" securityIDType="" cusip="" isin="" underlyingConid="" underlyingSymbol="" issuer="" multiplier="0" strike="" expiry="" putCall="" dateTime="2017-05-03" amount="9.18" type="Other Fees" tradeID="" code="" />
</CashTransactions>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<FlexQueryResponse queryName="AccountActivities" type="AF">
<FlexStatements count="1">
<FlexStatement accountId="U123456" fromDate="20240101" toDate="20241231" period="" whenGenerated="20240101 12:00:00">
<Trades>
<!-- Base security 1 with ISIN -->
<Trade accountId="U123456" acctAlias="" currency="CAD" assetCategory="STK" fxRateToBase="0.93099" symbol="GCM" description="GRAN COLOMBIA GOLD CORP" conid="" securityID="CA38501D2041" securityIDType="ISIN" cusip="" isin="CA38501D2041" underlyingConid="" underlyingSymbol="" issuer="" multiplier="1" strike="" expiry="" putCall="" tradeID="855937427" reportDate="20130401" tradeDate="20130401" tradeTime="093406" settleDateTarget="20130404" transactionType="ExchTrade" exchange="TSE" quantity="5000" tradePrice="0.27" tradeMoney="1350" proceeds="-1350" taxes="0" ibCommission="-6.75" ibCommissionCurrency="CAD" closePrice="0.275" openCloseIndicator="O" notes="P;" cost="1356.75" fifoPnlRealized="0" mtmPnl="25" origTradePrice="0" origTradeDate="" origTradeID="" origOrderID="0" clearingFirmID="" transactionID="3452745495" buySell="BUY" ibOrderID="437137993" ibExecID="0000d514.5159662d.01.01" brokerageOrderID="" orderReference="" volatilityOrderLink="" orderPlacementTime="" exchOrderId="N/A" extExecID="14.GCM.B" orderTime="20130401;070007" openDateTime="--" holdingPeriodDateTime="--" whenRealized="--" whenReopened="--" levelOfDetail="EXECUTION" changeInPrice="0" changeInQuantity="0" netCash="-1356.75" orderType="LMT" traderID="" />
<!-- Base security 2 without ISIN -->
<Trade accountId="U123456" acctAlias="" currency="CAD" assetCategory="STK" fxRateToBase="0.93194" symbol="UUU" description="URANIUM ONE INC." conid="" securityID="CA91701P1053" securityIDType="ISIN" cusip="" isin="" underlyingConid="" underlyingSymbol="" issuer="" multiplier="1" strike="" expiry="" putCall="" tradeID="813598116" reportDate="20130102" tradeDate="20130102" tradeTime="151236" settleDateTarget="20130107" transactionType="ExchTrade" exchange="TSE" quantity="100" tradePrice="2.31" tradeMoney="231" proceeds="-231" taxes="0" ibCommission="-1" ibCommissionCurrency="CAD" closePrice="2.36" openCloseIndicator="O" notes="P;" cost="232" fifoPnlRealized="0" mtmPnl="5" origTradePrice="0" origTradeDate="" origTradeID="" origOrderID="0" clearingFirmID="" transactionID="3277427053" buySell="BUY" ibOrderID="415875524" ibExecID="0000d514.50e42ded.01.01" brokerageOrderID="" orderReference="" volatilityOrderLink="" orderPlacementTime="" exchOrderId="N/A" extExecID="5173.UUU.B" orderTime="20130102;115456" openDateTime="--" holdingPeriodDateTime="--" whenRealized="--" whenReopened="--" levelOfDetail="EXECUTION" changeInPrice="0" changeInQuantity="0" netCash="-232" orderType="LMT" traderID="" />

<!-- Case 1: Same ISIN, different currency - Should create new security -->
<Trade accountId="U123456" acctAlias="" currency="EUR" assetCategory="STK" fxRateToBase="0.93099" symbol="GCM" description="GRAN COLOMBIA GOLD CORP" conid="" securityID="CA38501D2041" securityIDType="ISIN" cusip="" isin="CA38501D2041" underlyingConid="" underlyingSymbol="" issuer="" multiplier="1" strike="" expiry="" putCall="" tradeID="855937427" reportDate="20130401" tradeDate="20130401" tradeTime="093406" settleDateTarget="20130404" transactionType="ExchTrade" exchange="TSE" quantity="5000" tradePrice="0.27" tradeMoney="1350" proceeds="-1350" taxes="0" ibCommission="-6.75" ibCommissionCurrency="EUR" closePrice="0.275" openCloseIndicator="O" notes="P;" cost="1356.75" fifoPnlRealized="0" mtmPnl="25" origTradePrice="0" origTradeDate="" origTradeID="" origOrderID="0" clearingFirmID="" transactionID="3452745495" buySell="BUY" ibOrderID="437137993" ibExecID="0000d514.5159662d.01.01" brokerageOrderID="" orderReference="" volatilityOrderLink="" orderPlacementTime="" exchOrderId="N/A" extExecID="14.GCM.B" orderTime="20130401;070007" openDateTime="--" holdingPeriodDateTime="--" whenRealized="--" whenReopened="--" levelOfDetail="EXECUTION" changeInPrice="0" changeInQuantity="0" netCash="-1356.75" orderType="LMT" traderID="" />
<!-- Case 2: Same symbol, different ISIN - Should create new security -->
<Trade accountId="U123456" acctAlias="" currency="CAD" assetCategory="STK" fxRateToBase="0.93099" symbol="GCM" description="GARBAGE COLLECTION CORP" conid="" securityID="CA38501D2042" securityIDType="ISIN" cusip="" isin="CA38501D2042" underlyingConid="" underlyingSymbol="" issuer="" multiplier="1" strike="" expiry="" putCall="" tradeID="855937427" reportDate="20130401" tradeDate="20130401" tradeTime="093406" settleDateTarget="20130404" transactionType="ExchTrade" exchange="TSE" quantity="5000" tradePrice="0.27" tradeMoney="1350" proceeds="-1350" taxes="0" ibCommission="-6.75" ibCommissionCurrency="CAD" closePrice="0.275" openCloseIndicator="O" notes="P;" cost="1356.75" fifoPnlRealized="0" mtmPnl="25" origTradePrice="0" origTradeDate="" origTradeID="" origOrderID="0" clearingFirmID="" transactionID="3452745495" buySell="BUY" ibOrderID="437137993" ibExecID="0000d514.5159662d.01.01" brokerageOrderID="" orderReference="" volatilityOrderLink="" orderPlacementTime="" exchOrderId="N/A" extExecID="14.GCM.B" orderTime="20130401;070007" openDateTime="--" holdingPeriodDateTime="--" whenRealized="--" whenReopened="--" levelOfDetail="EXECUTION" changeInPrice="0" changeInQuantity="0" netCash="-1356.75" orderType="LMT" traderID="" />
<!-- Case 3: No ISIN, same symbol, different currency - Should create new security -->
<Trade accountId="U123456" acctAlias="" currency="EUR" assetCategory="STK" fxRateToBase="0.93194" symbol="UUU" description="URANIUM ONE INC." conid="" securityID="CA91701P1053" securityIDType="ISIN" cusip="" isin="" underlyingConid="" underlyingSymbol="" issuer="" multiplier="1" strike="" expiry="" putCall="" tradeID="813598116" reportDate="20130102" tradeDate="20130102" tradeTime="151236" settleDateTarget="20130107" transactionType="ExchTrade" exchange="TSE" quantity="100" tradePrice="2.31" tradeMoney="231" proceeds="-231" taxes="0" ibCommission="-1" ibCommissionCurrency="EUR" closePrice="2.36" openCloseIndicator="O" notes="P;" cost="232" fifoPnlRealized="0" mtmPnl="5" origTradePrice="0" origTradeDate="" origTradeID="" origOrderID="0" clearingFirmID="" transactionID="3277427053" buySell="BUY" ibOrderID="415875524" ibExecID="0000d514.50e42ded.01.01" brokerageOrderID="" orderReference="" volatilityOrderLink="" orderPlacementTime="" exchOrderId="N/A" extExecID="5173.UUU.B" orderTime="20130102;115456" openDateTime="--" holdingPeriodDateTime="--" whenRealized="--" whenReopened="--" levelOfDetail="EXECUTION" changeInPrice="0" changeInQuantity="0" netCash="-232" orderType="LMT" traderID="" />
</Trades>
<CashTransactions>
<!-- Case 1: Same ISIN, different currency - Should match base security 1 -->
<CashTransaction accountId="U123456" acctAlias="" currency="USD" assetCategory="STK" fxRateToBase="0.93194" symbol="GCM" description="GRAN COLOMBIA GOLD CORP" conid="" securityID="CA38501D2041" securityIDType="ISIN" cusip="" isin="CA38501D2041" exchange="TSE" amount="10" type="Dividends" dateTime="20130401" reportDate="20130401" />
<!-- Case 2: Same symbol, different ISIN - Should create new security -->
<CashTransaction accountId="U123456" acctAlias="" currency="EUR" assetCategory="STK" fxRateToBase="0.93194" symbol="GCM" description="GARBAGE COLLECTION CORP" conid="" securityID="CA38501D2043" securityIDType="ISIN" cusip="" isin="CA38501D2043" exchange="TSE" amount="10" type="Dividends" dateTime="20130401" reportDate="20130401" />
<!-- Case 3: No ISIN, same symbol, different currency - Should match base security 2 -->
<CashTransaction accountId="U123456" acctAlias="" currency="AUD" assetCategory="STK" fxRateToBase="0.93194" symbol="UUU" description="URANIUM ONE INC." conid="" securityID="CA91701P1053" securityIDType="ISIN" cusip="" isin="" exchange="TSE" amount="10" type="Dividends" dateTime="20130401" reportDate="20130401" />
</CashTransactions>
</FlexStatement>
</FlexStatements>
</FlexQueryResponse>
Loading