liveBook · Manning

Tax lot

As explained in Build a Robo-Advisor with Python (From Scratch)

A tax lot is a distinct group of investment shares acquired in a particular transaction and tracked with its acquisition details for tax purposes.

A tax lot is a group of shares bought at the same time at one purchase price. Lots of the same asset are not equivalent when sold: their gain or loss and holding period can produce different current tax effects. Tracking lots turns a share-level sale into a choice among specific acquisition records. section 13.2.3

Choose lots for a sale

With a current price of $110, four lots bought at $80, $85, $105, and $115 have different gains and holding periods. Applying 40% to short-term gains and 20% to long-term gains yields effective rates of 7.5%, 11.8%, 1.9%, and -1.7%. To sell 35 shares, sell the 10-share loss lot, all 20 shares of the 1.9% lot, and 5 shares of the 7.5% lot. section 13.2.3

Listing 13.3 Calculating tax exposure
import datetime as dt

lt_gains_rate = 0.20
income_rate = .40
current_price = 110
current_date = dt.date(2022, 5, 11)

lots = pd.DataFrame({'price': [80, 85, 105, 115],
                     'quantity': [25, 30, 20, 10],
                     'purchase_date': ['2021-02-10', '2021-07-21',
                                       '2021-11-23', '2022-03-25']})

tax_info = {}
for i in lots.index:
    lot_info = lots.iloc[i]
    purchase_date = dt.date.fromisoformat(lot_info['purchase_date'])
    holding_period = (current_date - purchase_date).days
    if holding_period <= 365:
        lot_rate = income_rate
    else:
        lot_rate = lt_gains_rate

    purchase_price = lot_info['price']
    gain = (current_price / purchase_price - 1)
    effective_rate = gain * lot_rate

    tax_info[i] = pd.Series({'holding_period': holding_period,
                             'applicable_rate': lot_rate,
                             'pct_gain': gain,
                             'effective_rate': effective_rate})

tax_info = pd.DataFrame(tax_info).T

This calculation derives each lot’s holding period, applicable rate, percentage gain, and effective tax rate from its purchase date, purchase price, quantity, and the current price. section 13.2.3

A practical lot-selection rule works incrementally:

  • Calculate each lot’s holding period and gain or loss at the current price. section 13.2.3
  • Sort lots by effective tax rate, from lowest to highest. section 13.2.3
  • Sell from the best-ranked lot until it is exhausted or the requested share count is met, then continue to the next lot. section 13.2.3

For portfolio rebalancing, represent each current lot separately rather than using one sell variable per asset. Buy variables can be keyed by ticker, while sell variables use ticker and purchase date; positions aggregate starting holdings with selected trades. This lets an optimizer weigh tax effects alongside target-portfolio constraints and objectives. section 13.3.1 section 13.3.2

Lot records also support ongoing accounting. A backtest marks every lot to market, calculates tax for each selected sale, and retains lot-level holdings when computing portfolio weights. Tax-loss harvesting additionally needs closed-lot sale dates and prices so potential wash-sale restrictions and cost-basis adjustments can be evaluated. section 13.4.2 section 14.2.2

When harvesting losses, first identify sellable lots and lots that block purchases, then consider only eligible losses. Candidate lots can be ordered by tax benefit, while trade costs and opportunity costs determine whether a proposed replacement trade is worthwhile. section 14.2.2 section 14.3.3

How Build a Robo-Advisor with Python (From Scratch) covers it

How deep it goes
Defines lot records, computes tax exposure, implements selection, and models lots in optimization and wash-sale accounting.
Examples
Uses VTI and AGG lot DataFrames, four priced lots at $110, and exchangeable ETF harvesting trades.
What you can do after
Apply it via Python and pandas to select sales, maintain holdings, and evaluate lot-level tax-aware trades.
How it connects
Connects tax lots with portfolio rebalancing, optimization, tax-loss harvesting, wash sales, and tracking error.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of Build a Robo-Advisor with Python (From Scratch). The section links point to the parts of the book it draws on.