Last active
February 15, 2023 17:55
-
-
Save ross/1ffc2a81c12cce68e262891cd358c58b to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# https://github.com/simonmichael/hledger/blob/master/examples/TXF-spec-v042.org | |
# https://github.com/andreasg123/stock-gain-tax-import/blob/main/create-txf-2018.py | |
from collections import defaultdict | |
from datetime import date | |
from io import StringIO | |
from pprint import pprint | |
from sys import argv | |
symbols = defaultdict(list) | |
with open(argv[1]) as fh: | |
# skip pass the header | |
lines = fh.read().split('\n') | |
for i, line in enumerate(lines): | |
if line.startswith('Symbol'): | |
break | |
# parse the symbols | |
for i in range(i+1, len(lines)): | |
line = lines[i] | |
if line[0] != ' ': | |
# new symbol | |
symbol = line.split(',', 1)[0] | |
continue | |
( | |
_, | |
quantity, | |
acquired, | |
cost_per_share, | |
cost, | |
disposed, | |
price_per_share, | |
proceeds, | |
gain, | |
deferred_loss, | |
term, | |
lot_selection, | |
_ | |
) = line.strip().split(',') | |
if deferred_loss in ('--', '.00'): | |
deferred_loss = None | |
symbols[symbol].append({ | |
'quantity': quantity, | |
'acquired': acquired, | |
'cost_per_share': cost_per_share, | |
'cost': cost, | |
'disposed': disposed, | |
'price_per_share': price_per_share, | |
'proceeds': proceeds, | |
'gain': gain, | |
'deferred_loss': deferred_loss, | |
'term': term, | |
'lot_selection': lot_selection | |
}) | |
print('V042') | |
print('Aextrade-to-txf.py') | |
print('D', date.today().strftime('%m/%d/%y')) | |
print('^') | |
# WARNING: e*Trade doesn't provide enough information to know what was reported | |
# to the IRS and what wasn't in their CSVs. If you hav box B, E, or X stuff. | |
# You'll have to grab the pdf version and manually change the boxes for those | |
# :-( | |
codes = { | |
# A | |
'Short': 321, | |
# D | |
'Long': 323, | |
} | |
wash_codes = { | |
# A | |
'Short': 682, | |
# D | |
'Long': 323, | |
} | |
for symbol, lots in sorted(symbols.items()): | |
for lot in lots: | |
print('TD') | |
if lot['deferred_loss']: | |
code = wash_codes[lot['term']] | |
else: | |
code = codes[lot['term']] | |
print(f'N{code}') | |
print(f'P {lot["quantity"]} sh {symbol}') | |
print(f'D{lot["acquired"]}') | |
print(f'D{lot["disposed"]}') | |
print(f'${lot["cost"]}') | |
print(f'${lot["proceeds"]}') | |
if lot['deferred_loss']: | |
print(f'${-lot["deferred_loss"]}') | |
print('^') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment