Skip to content

Commit

Permalink
Address #16
Browse files Browse the repository at this point in the history
  • Loading branch information
rlan committed Oct 16, 2024
1 parent 397f4d2 commit 8e8df01
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 33 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ Duplicate transactions:

As far as I can test, PP will detect and skip duplicate transactions. So it is safe to import overlapping transactions in the future.

Dates:

If date is in "date1 as of date2" format, "date1" will be used and "as of date2" will be appended to the resulting "Note" column.

## License

MIT
Expand Down
73 changes: 44 additions & 29 deletions convert.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,14 @@
# Prefix: "Transactions for account..."
# Suffix: "Transactions Total"
# They are ignored.
df = pd.read_csv(args.schwab_csv, skiprows=1, skipfooter=1, engine="python")

# Convert dates to datetime objects
df["Date"] = pd.to_datetime(df["Date"], format="%m/%d/%Y")
dtype = {
"Date" : str,
"Symbol" : str,
"Fees & Comm" : str, # must keep as string, in case of floating-point rounding errors.
"Amount" : str, # must keep as string, in case of floating-point rounding errors.
}
df = pd.read_csv(args.schwab_csv, skiprows=1, skipfooter=1, dtype=dtype, engine="python")
df["Symbol"] = df["Symbol"].fillna("")

# Rename column names
column_new_names = {
Expand All @@ -53,8 +57,8 @@
df.rename(columns=column_new_names, inplace=True)


# Remove US dollar sign from Value column
def remove_currency(text: str):
def remove_currency(text: str) -> str:
"""Removes currency symbol from string. Works for negative values."""
import re
import locale

Expand All @@ -63,20 +67,25 @@ def remove_currency(text: str):
return clean


# Remove US dollar symbol
new_value = df["Value"].apply(remove_currency)
df["Value"] = new_value

# Add a new column with all USD: Transaction Currency
transaction_currency = ["USD" for x in df["Value"]]
df["Transaction Currency"] = transaction_currency
# Hard-coding. Assume all transcations are in USD.
# Add a new column: Transaction Currency
df["Transaction Currency"] = ["USD"] * len(df.index)

# Convert Action to Type
# Convert Action (Schwab) to Type (Portfolio Performance)
"""
"Deposit/Removal (or withdrawal): Depositing or withdrawing funds will
respectively increase or decrease the value of a deposit account."
Ref: https://help.portfolio-performance.info/en/reference/transaction/
So a Schwab "Wire Sent" is a PP "Removal".
Bank Interest as Dividend was introduced in commit
297f429979d4588f8871ad6d23d70f0557de9420 by @sdtom. After review, as Interest
is probably more appropriate.
"""
action_to_type = {
"NRA Tax Adj": "Taxes",
Expand All @@ -92,36 +101,42 @@ def remove_currency(text: str):
"Advisor Fee": "Fees",
"Reinvest Dividend": "Dividend",
"Reinvest Shares": "Buy",
"Bank Interest": "Dividend",
"Bank Interest": "Interest",
"Funds Received": "Deposit",
"MoneyLink Transfer": "Deposit",
}
new_type = [action_to_type[x] for x in df["Note"]]
df["Type"] = new_type

# Delete Price column
# Delete Price column because PP seems not to have this column for a
# transaction.
df.drop(columns=["Price"], inplace=True)

# Add SCHWAB1 INT to Notes
for k, v in df["Security Name"].items():
if v.startswith("SCHWAB1 INT"):
df.at[k, "Note"] = df.at[k, "Note"] + " " + v


# Remove non-security names
def convert_security_name(data: str):
if data.startswith("SCHWAB1 INT"):
return ""
elif data.startswith("WIRED FUNDS RECEIVED"):
return ""
elif data.startswith("WIRED FUNDS DISBURSED"):
return ""
# If "Ticker Symbol" column is not empty, then "Security Name" column
# contains the name of the security. Otherwise it's a description.
# If latter, append to "Note" column.
new_security_name = []
for k, v in df["Ticker Symbol"].items():
if len(v) == 0:
new_security_name.append("")
df.at[k, "Note"] = df.at[k, "Note"] + " " + df.at[k, "Security Name"]
else:
return data
new_security_name.append(df.at[k, "Security Name"])
df["Security Name"] = new_security_name


new_security_name = [convert_security_name(v) for v in df["Security Name"]]
df["Security Name"] = new_security_name
# Convert dates to datetime objects
new_date = []
for k, v in df["Date"].items():
multiple = v.split(" as of ", 1)
new_date.append(multiple[0])
if len(multiple) > 1:
if len(df.at[k, "Note"]):
df.at[k, "Note"] = df.at[k, "Note"] + " as of " + multiple[1]
else:
df.at[k, "Note"] = "as of " + multiple[1]

df["Date"] = pd.to_datetime(new_date, format="%m/%d/%Y")

# Write to CSV file
df.to_csv(args.pp_csv, index=False, date_format="%Y-%m-%d")
Expand Down
2 changes: 1 addition & 1 deletion example.csv
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
"03/04/2021","NRA Tax Adj","BNDX","VANGUARD TOTAL INTERNATIONAL BND ETF","","","","-$1.10"
"03/04/2021","Cash Dividend","BNDX","VANGUARD TOTAL INTERNATIONAL BND ETF","","","","$3.65"
"02/25/2021","NRA Tax Adj","","SCHWAB1 INT 01/28-02/24","","","","-$0.02"
"02/25/2021","Credit Interest","","SCHWAB1 INT 01/28-02/24","","","","$0.09"
"02/25/2021 as of 02/21/2021","Credit Interest","","SCHWAB1 INT 01/28-02/24","","","","$0.09"
"02/09/2021","Buy","BNDX","VANGUARD TOTAL INTERNATIONAL BND ETF","81","$57.9999","","-$4697.99"
"02/02/2021","Wire Received","","WIRED FUNDS RECEIVED","","","","$5000.00"
"Transactions Total","","","","","","","$94.33",
6 changes: 3 additions & 3 deletions example_out.csv
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
Date,Note,Ticker Symbol,Security Name,Shares,Fees,Value,Transaction Currency,Type
2024-01-01,Wire Sent,,,,,-100.00,USD,Removal
2024-01-01,Wire Sent WIRED FUNDS DISBURSED,,,,,-100.00,USD,Removal
2021-12-29,NRA Withholding,BNDX,VANGUARD TOTAL INTERNATIONAL BND ETF,,,-0.14,USD,Taxes
2021-12-29,Short Term Cap Gain,BNDX,VANGUARD TOTAL INTERNATIONAL BND ETF,,,0.48,USD,Dividend
2021-12-29,Long Term Cap Gain,BNDX,VANGUARD TOTAL INTERNATIONAL BND ETF,,,29.21,USD,Dividend
2021-03-04,NRA Tax Adj,BNDX,VANGUARD TOTAL INTERNATIONAL BND ETF,,,-1.10,USD,Taxes
2021-03-04,Cash Dividend,BNDX,VANGUARD TOTAL INTERNATIONAL BND ETF,,,3.65,USD,Dividend
2021-02-25,NRA Tax Adj SCHWAB1 INT 01/28-02/24,,,,,-0.02,USD,Taxes
2021-02-25,Credit Interest SCHWAB1 INT 01/28-02/24,,,,,0.09,USD,Interest
2021-02-25,Credit Interest SCHWAB1 INT 01/28-02/24 as of 02/21/2021,,,,,0.09,USD,Interest
2021-02-09,Buy,BNDX,VANGUARD TOTAL INTERNATIONAL BND ETF,81.0,,-4697.99,USD,Buy
2021-02-02,Wire Received,,,,,5000.00,USD,Deposit
2021-02-02,Wire Received WIRED FUNDS RECEIVED,,,,,5000.00,USD,Deposit

0 comments on commit 8e8df01

Please sign in to comment.