wash-sale-tracker

Software that calculates wash sale adjustments for US taxes.

Note that the author is not a CPA or tax expert. This program most certainly contains bugs.

This script is inspired by adlr/wash-sale-calculator, but rewritten so that the author could reason about how the replacement lots were being chosen. It also includes keeps track of some additional fields, like the original basis and buy date, to make it easy to correlate the output with a 1099-B.

Installing

  • Install pipenv. This is usually either sudo apt install pipenv or pip install --user pipenv.
  • cd into project directory
  • pipenv shell to enter the virtual environment
  • pipenv sync to download all the dependencies

Running

After running pipenv shell, inside the virtual environment shell run:

./wash.py -w dummy_example.csv -o out.csv --output-dollars

The --output-dollars argument makes the final outputs for money columns in dollars instead of cents.

The CSV file must have one buy or buy-sell trade per row. Each row must have all of the following columns, but the optional ones can remain blank.

The parse_morgan_stanley.py file can help in parsing 1099-Bs from Morgan Stanley and in producing the right CSV file that wash.py needs.

Column Header Type Description
Num Shares Integer The number of shares in this lot.
Symbol String Stock symbol. This is unused by the script, as all lots fed into the script are considered substantially identical.
Description String An arbitrary description of this lot.
Buy Date Date (mm/dd/yyyy) The date that this lot was actually bought.
Adjusted Buy Date Date (mm/dd/yyyy) Optional. The adjusted buy date of a loss. Provided by the output. See IRS Publication 550, Wash Sales section for why this matters. Specifically this sentence: "Your holding period for the new stock or securities includes the holding period of the stock or securities sold."
Basis Integer The number of cents for the cost basis of this lot.
Adjusted Basis Integer Optional. The number of cents of the adjusted cost basis of this lot. Provided by the output.
Sell Date Date (mm/dd/yyyy) Optional. The date that this lot was sold.
Proceeds Integer Optional. The number of cents that this lot was sold for.
Adjustment Code String Optional. Will be W if the lot is adjusted for a wash sale.
Adjustment Integer Optional. The number of cents of this lot's disallowed loss.
Form Position String Optional. This field is used as a tertiary sorting value, but is primarily used to associate lots before and after the script is run.
Buy Lot String Optional. Generally can be left blank. If two lots were acquired as part of the same buy order, put the same value here. This may occur if you bought a lot of stock, then sold off the lot in pieces (each piece would get a new line on the 1099b); if the broker automatically divided your buy order into pieces to execute; or if other factors caused the broker to split one buy lot into multiple lines on the 1099b. (This field is used because shares from a given buy lot can't replace shares from the same buy lot in a wash sale).
Replacement For String Optional. A list of strings, separated by a | character, of buy lots that this lot is a replacement for. Populated by the script.
Is Replacement Boolean (the strings true/false) Optional. True if the lot was used as a replacement lot.
Loss Processed Boolean (the strings true/false) Optional. True if the lot is a loss and has been processed.

Notes

It could be possible for a wash sale to cause losses to travel backwards in time, potentially for multiple years, if a replacement lot is sold before the loss is sold. This software does not account for this, and allows the loss to travel backwards in time.

If multiple lots are bought on the same day and sold on the same day (though the buy and sell dates may be different), this software will not use a lot as a replacement lot if the loss replaced that same lot. Specifically, say there are 2 lots of size 10 and 6 shares, named A and B. The 10 A shares would be split into 6 and 4 shares, and the 6 A shares would be replaced with the 6 B shares. The 6 B shares will not then be split into 4 shares and 2 shares with the 4 B shares replaced with the 4 A shares.

Contributing

If you commit changes to this software, make sure all tests are passing. To verify that all the tests pass, just run ./run_tests.py from within the virtual environment shell.