Skip to content

Commit

Permalink
Additional reworking of the history importers to reduce the number of…
Browse files Browse the repository at this point in the history
… rejected rows (#15)

Update the Fido (Fidelity) history importer to support security transfers where no share price is specified.
  • Loading branch information
reedes authored Jan 9, 2022
1 parent 6018f25 commit ab21868
Show file tree
Hide file tree
Showing 4 changed files with 28 additions and 32 deletions.
17 changes: 8 additions & 9 deletions Sources/Importers/ChuckHistory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,11 @@ class ChuckHistory: FINporter {

delimitedRows.reduce(into: []) { decodedRows, delimitedRow in

// ignore totals row
let rawDate = delimitedRow["Date"]
guard rawDate != "Transactions Total" else { return }

guard let rawAction = MTransaction.parseString(delimitedRow["Action"]),
let rawDate = delimitedRow["Date"],
let transactedAt = parseChuckMMDDYYYY(rawDate, defTimeOfDay: defTimeOfDay, timeZone: timeZone)
else {
rejectedRows.append(delimitedRow)
Expand Down Expand Up @@ -176,6 +179,7 @@ class ChuckHistory: FINporter {
switch netAction {
case .buysell:
guard let symbol = rawSymbol,
symbol.count > 0,
let sharePrice = rawSharePrice,
let quantity = rawQuantity
else {
Expand All @@ -198,7 +202,7 @@ class ChuckHistory: FINporter {
}

if rawSymbol == "NO NUMBER" {
// assume that it's a cash transfer, where amount is required
// assume that it's a cash transfer (where amount is required)
guard let amount = rawAmount else { return nil }
decodedRow[MTransaction.CodingKeys.shareCount.rawValue] = amount
decodedRow[MTransaction.CodingKeys.sharePrice.rawValue] = 1.0
Expand All @@ -217,20 +221,15 @@ class ChuckHistory: FINporter {
}
}

case .income:
default:
guard let amount = rawAmount else { return nil }
decodedRow[MTransaction.CodingKeys.shareCount.rawValue] = amount
decodedRow[MTransaction.CodingKeys.sharePrice.rawValue] = 1.0

// accept the income even if no symbol specified
// accept the income/miscflow even if no symbol specified
if let symbol = rawSymbol {
decodedRow[MTransaction.CodingKeys.securityID.rawValue] = symbol
}

default:
guard let amount = rawAmount else { return nil }
decodedRow[MTransaction.CodingKeys.shareCount.rawValue] = amount
decodedRow[MTransaction.CodingKeys.sharePrice.rawValue] = 1.0
}

return decodedRow
Expand Down
14 changes: 7 additions & 7 deletions Sources/Importers/FidoHistory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -173,17 +173,17 @@ class FidoHistory: FINporter {

case .transfer:
if let symbol = rawSymbol {
guard let quantity = rawShareCount,
let sharePrice = rawSharePrice
else {
return nil
}
guard let quantity = rawShareCount else { return nil }

decodedRow[MTransaction.CodingKeys.shareCount.rawValue] = quantity
decodedRow[MTransaction.CodingKeys.sharePrice.rawValue] = sharePrice
decodedRow[MTransaction.CodingKeys.securityID.rawValue] = symbol

// if transfer of a stock/etf, there may be no share price
if let sharePrice = rawSharePrice {
decodedRow[MTransaction.CodingKeys.sharePrice.rawValue] = sharePrice
}
} else {
// no symbol, so it's probably cash
// no symbol, so it's probably cash (where amount is required)
guard let amount = rawAmount else { return nil }

decodedRow[MTransaction.CodingKeys.shareCount.rawValue] = amount
Expand Down
21 changes: 7 additions & 14 deletions Tests/Importers/ChuckHistoryTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -114,22 +114,15 @@ final class ChuckHistoryTests: XCTestCase {
timeZone: tzNewYork)

let expected: [AllocRowed.DecodedRow] = [
["txnAccountID": "XXXX-1234", "txnShareCount": 100.0, "txnSharePrice": 1.0, "txnTransactedAt": timestamp3, "txnAction": MTransaction.Action.miscflow],
["txnAction": MTransaction.Action.buysell, "txnShareCount": 961.0, "txnSharePrice": 105.0736, "txnAccountID": "XXXX-1234", "txnTransactedAt": timestamp1, "txnSecurityID": "SCHB"],
["txnTransactedAt": timestamp4, "txnSharePrice": 1.0, "txnAccountID": "XXXX-1234", "txnAction": MTransaction.Action.transfer, "txnShareCount": 101000.0],
["txnTransactedAt": timestamp2, "txnAccountID": "XXXX-5678", "txnSecurityID": "VOO", "txnAction": MTransaction.Action.buysell, "txnShareCount": -10.0, "txnSharePrice": 137.1222],
["txnAccountID": "XXXX-5678", "txnShareCount": 0.55, "txnSharePrice": 1.0, "txnAction": MTransaction.Action.income, "txnTransactedAt": timestamp4],
["txnAction": MTransaction.Action.miscflow, "txnTransactedAt": timestamp3, "txnAccountID": "XXXX-1234", "txnShareCount": 100.0, "txnSharePrice": 1.0],
["txnAction": MTransaction.Action.buysell, "txnTransactedAt": timestamp1, "txnAccountID": "XXXX-1234", "txnShareCount": 961.0, "txnSharePrice": 105.0736, "txnSecurityID": "SCHB"],
["txnAction": MTransaction.Action.transfer, "txnTransactedAt": timestamp4, "txnAccountID": "XXXX-1234", "txnShareCount": 101000.0, "txnSharePrice": 1.0],
["txnAction": MTransaction.Action.buysell, "txnTransactedAt": timestamp2, "txnAccountID": "XXXX-5678", "txnShareCount": -10.0, "txnSharePrice": 137.1222, "txnSecurityID": "VOO"],
["txnAction": MTransaction.Action.income, "txnTransactedAt": timestamp4, "txnAccountID": "XXXX-5678", "txnShareCount": 0.55, "txnSharePrice": 1.0],

]
XCTAssertEqual(expected, actual)

let rejected: [AllocRowed.RawRow] = [
["Action": "", "Quantity": "", "Symbol": "", "Date": "Transactions Total", "Amount": "$524.82", "Price": "", "Fees & Comm": "", "Description": "", "": ""],
["Description": "", "Action": "", "Fees & Comm": "", "Quantity": "", "Date": "Transactions Total", "Price": "", "Amount": "$524.82", "": "", "Symbol": ""]
]
XCTAssertEqual(rejected, rr)

XCTAssertEqual(2, rr.count)
XCTAssertEqual(expected, actual)
XCTAssertEqual(0, rr.count)
}

func testParseAccountTitleID() throws {
Expand Down
8 changes: 6 additions & 2 deletions Tests/Importers/FidoHistoryActionTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -176,10 +176,10 @@ final class FidoHistoryActionTests: XCTestCase {

("03/01/2021,PASSIVE X0000000A, YOU BOUGHT VANGUARD INDEX FDS VANGUARD VALUE ETF F (VTV) (Cash), VTV, VANGUARD INDEX FDS VANGUARD VALUE ETF F,Cash,7.0,100.0,,,,-700.0,03/05/2021",
[["txnTransactedAt": YYYYMMDDts, "txnSharePrice": 100.0, "txnShareCount": 7.0, "txnAction": buysell, "txnAccountID": accountID, "txnSecurityID": "VTV"]]),

("03/01/2021,PASSIVE X0000000A, REDEMPTION FROM CORE ACCOUNT FIDELITY GOVERNMENT MONEY MARKET (SPAXX) MORNING TRADE (Cash), SPAXX, FIDELITY GOVERNMENT MONEY MARKET,Cash,-17.00,1,,,,17.00,",
[["txnTransactedAt": YYYYMMDDts, "txnSharePrice": 1.0, "txnShareCount": -17.0, "txnAction": buysell, "txnAccountID": accountID, "txnSecurityID": "SPAXX"]]),

("03/01/2021,PASSIVE X0000000A, REINVESTMENT FIDELITY GOVERNMENT MONEY MARKET (SPAXX) (Cash), SPAXX, FIDELITY GOVERNMENT MONEY MARKET,Cash,-17.00,1,,,,-17.00,",
[["txnTransactedAt": YYYYMMDDts, "txnSharePrice": 1.0, "txnShareCount": -17.0, "txnAction": buysell, "txnAccountID": accountID, "txnSecurityID": "SPAXX"]]),

Expand All @@ -193,6 +193,10 @@ final class FidoHistoryActionTests: XCTestCase {

("03/01/2021,BROKERAGE X0000000A, TRANSFER OF ASSETS ACAT DELIVER, TLT, ISHARES TR 20 YR TR BD ETF,Cash,-86,144.41,,0.07,,12418.76,08/02/2021",
[["txnTransactedAt": YYYYMMDDts, "txnSharePrice": 144.41, "txnShareCount": -86.0, "txnAction": transfer, "txnAccountID": accountID, "txnSecurityID":"TLT"]]),

// no share price on this stock transfer
("03/01/2021,BROKERAGE X0000000A, TRANSFER OF ASSETS EST SETTLE 02-04-21 ALPHABET INC (ABCD) (Cash), ABCD, ALPHA INC,Cash,-200,,,,,,",
[["txnTransactedAt": YYYYMMDDts, "txnShareCount": -200.0, "txnAction": transfer, "txnAccountID": accountID, "txnSecurityID":"ABCD"]]),

// income

Expand Down

0 comments on commit ab21868

Please sign in to comment.