@@ -92,8 +92,12 @@ func Merge(
9292 importedTxns , err := protoio .ReadMessagesJSON (seedTxnPath , func () * datav1.ImportedTransaction { return & datav1.ImportedTransaction {} })
9393 if err == nil {
9494 for _ , txn := range importedTxns {
95+ // Only security transactions (buys, sells, splits, etc.) become trades.
96+ // Non-security transactions (dividends, interest, fees) return nil.
9597 trade := importedTransactionToTrade (txn )
96- allTrades = append (allTrades , trade )
98+ if trade != nil {
99+ allTrades = append (allTrades , trade )
100+ }
97101 }
98102 }
99103 }
@@ -238,30 +242,43 @@ func generateTradeID(symbol string, dateTime time.Time, quantity string, price s
238242}
239243
240244// importedTransactionToTrade converts an ImportedTransaction (from the previous broker)
241- // to a Trade proto for FIFO processing. Uses the ibkr_symbol field for the symbol
242- // so it matches IBKR's naming convention.
245+ // to a Trade proto for FIFO processing. Returns nil for non-security transactions
246+ // (dividends, interest, fees, transfers, deposits, withdrawals) that don't affect
247+ // FIFO lot computation.
243248func importedTransactionToTrade (txn * datav1.ImportedTransaction ) * datav1.Trade {
244249 // Map imported transaction type to trade side.
250+ // Non-security transactions return nil — they're stored for audit/income tracking
251+ // but don't participate in FIFO.
245252 var side datav1.TradeSide
246253 switch txn .GetType () {
247254 case datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_BUY ,
248255 datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_STOCK_DIVIDEND :
249256 // Buys and stock dividends add to position.
250257 side = datav1 .TradeSide_TRADE_SIDE_BUY
251258 case datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_SELL ,
252- datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_EXPIRY :
253- // Sells and expiries reduce position.
259+ datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_EXPIRY ,
260+ datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_REDEMPTION :
261+ // Sells, expiries, and redemptions reduce position.
254262 side = datav1 .TradeSide_TRADE_SIDE_SELL
255263 case datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_SPLIT :
256- // Splits are handled as buys with zero price (quantity adjustment).
264+ // Splits are handled as buys or sells with zero price (quantity adjustment).
257265 if txn .GetQuantity () >= 0 {
258266 side = datav1 .TradeSide_TRADE_SIDE_BUY
259267 } else {
260268 side = datav1 .TradeSide_TRADE_SIDE_SELL
261269 }
262- case datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_UNSPECIFIED :
263- // Skip unspecified transactions.
264- side = datav1 .TradeSide_TRADE_SIDE_UNSPECIFIED
270+ case datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_DIVIDEND ,
271+ datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_INTEREST ,
272+ datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_FEE ,
273+ datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_WITHHOLDING_TAX ,
274+ datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_TRANSFER_IN ,
275+ datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_TRANSFER_OUT ,
276+ datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_DEPOSIT ,
277+ datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_WITHDRAWAL ,
278+ datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_OTHER ,
279+ datav1 .ImportedTransactionType_IMPORTED_TRANSACTION_TYPE_UNSPECIFIED :
280+ // Non-security transactions don't affect FIFO.
281+ return nil
265282 }
266283 // Use ibkr_symbol for FIFO matching.
267284 symbol := txn .GetIbkrSymbol ()
0 commit comments