Cost Basis Methods: FIFO vs Specific ID
Cost basis methods decide which shares you sell first: FIFO, LIFO, HIFO, and specific ID. See how each one changes the realized gain on the same sale.
Cost basis methods decide which of your shares leave the account when you sell part of a position, and a US broker will usually let you elect one of four: FIFO, LIFO, highest in first out, or specific identification. The method changes the size and the character of the gain reported on that one sale. It does not change what the position costs you over its lifetime, since basis you do not use today stays on the books for the next sale.
What is a cost basis method?
A lot is one purchase: a quantity of shares bought at a price, stamped with a trade date. Buy the same stock four times and you hold four lots, each carrying its own basis and its own holding-period clock. Sell fewer shares than you own and something has to decide which lots left the account. That decision is the cost basis method.
- FIFO, first in first out, sells the oldest lot first. It is the default at nearly every US broker and applies whenever you make no election.
- LIFO, last in first out, sells the newest lot first.
- HIFO, highest in first out, sells the highest-cost lot first, wherever it sits on the calendar.
- Specific identification lets you name the exact lots and quantities yourself, in any combination.
Two things follow from those definitions. FIFO retires the shares most likely to have passed the one-year mark, so its gains skew long-term. HIFO retires the shares carrying the most basis, so it reports the smallest gain available on that sale, and the character of that gain depends on when the expensive lot happened to be bought.
Does the method change how much tax you pay?
Over the life of the position, no. Basis is conserved: every dollar assigned to today's sale is a dollar unavailable to a future one, and the sum of realized gains from first purchase to last share out is identical under all four methods. What moves is timing, meaning which tax year the gain lands in, and character, meaning short-term or long-term. A lot held one year or less produces a short-term gain taxed at ordinary income rates. A lot held more than a year produces a long-term gain at the lower long-term rates.
The arithmetic is small enough to run in front of you. The scenario below holds four hypothetical lots and one sale of 150 shares, then prints the realized result under each method, split into short-term and long-term. It uses nothing outside the Python standard library.
python3 <<'PY'
from datetime import date
# Four hypothetical purchase lots, oldest first, then one sale of 150 shares.
lots = [
{'bought': date(2023, 3, 15), 'qty': 100, 'price': 20.00},
{'bought': date(2024, 2, 20), 'qty': 100, 'price': 45.00},
{'bought': date(2024, 11, 1), 'qty': 100, 'price': 60.00},
{'bought': date(2025, 1, 15), 'qty': 100, 'price': 35.00},
]
sale_date = date(2025, 6, 2)
sale_qty = 150
sale_price = 50.00
def realize(order):
left, short, long_, basis_used = sale_qty, 0.0, 0.0, 0.0
for lot in order:
if left <= 0:
break
take = min(left, lot['qty'])
gain = take * (sale_price - lot['price'])
if (sale_date - lot['bought']).days > 365:
long_ += gain
else:
short += gain
basis_used += take * lot['price']
left -= take
return short, long_, basis_used
methods = {
'FIFO': sorted(lots, key=lambda l: l['bought']),
'LIFO': sorted(lots, key=lambda l: l['bought'], reverse=True),
'HIFO': sorted(lots, key=lambda l: l['price'], reverse=True),
'SpecID': [lots[2], lots[3], lots[0], lots[1]],
}
total_basis = sum(l['qty'] * l['price'] for l in lots)
print('%-8s %11s %10s %9s %11s' % ('method', 'short-term', 'long-term', 'realized', 'basis left'))
for name, order in methods.items():
short, long_, basis_used = realize(order)
print('%-8s %11.2f %10.2f %9.2f %11.2f' % (name, short, long_, short + long_, total_basis - basis_used))
PY
In that made-up ledger the four rows disagree by a wide margin. FIFO consumes the two oldest lots and reports 3,250.00 of gain, all of it long-term. LIFO takes the two newest and reports 1,000.00, all short-term. HIFO starts with the 60.00 lot and reports a loss of 750.00. The hand-picked specific identification order lands at a loss of 250.00. Now read the last column, the basis left behind on the 250 unsold shares: the method reporting the smallest gain today also leaves the least basis for tomorrow. That is conservation made visible.
How far apart are lots in real prices?
The election only matters to the extent the lots differ. Buy at nearly the same price every time and every method returns nearly the same number. The panel below pins a real price history, the first regular session of each month of 2024 in AAPL, as a stand-in for the monthly buying program an automatic investment plan produces.
The exact SQL behind every number
SELECT
formatDateTime(toStartOfMonth(date), '%Y-%m') AS month,
formatDateTime(min(date), '%b %e, %Y') AS lot_label,
round(toFloat64(argMin(close, date)), 2) AS lot_price
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'AAPL'
AND date >= '2024-01-01'
AND date < '2025-01-01'
GROUP BY toStartOfMonth(date)
ORDER BY toStartOfMonth(date)That is 12 lots, from $185.64 on Jan 2, 2024 to $239.59 on Dec 2, 2024. The distance between the cheapest and the dearest of them is the whole room a lot-selection method has to work in on this position.
Which lot does FIFO sell, and which one does HIFO sell?
Fix a sale and the per-lot difference becomes a curve you can read at a glance. The panel below holds the sale price constant at the AAPL close on the first session of June 2025, then reports what each 2024 lot would realize per share on that day, alongside whether the lot had passed its one-year mark by then.
The exact SQL behind every number
WITH
(
SELECT toFloat64(argMin(close, date))
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'AAPL'
AND date >= '2025-06-02'
AND date < '2025-06-07'
) AS sale_price,
toDate('2025-06-02') AS sale_date
SELECT
formatDateTime(toStartOfMonth(date), '%Y-%m') AS month,
round(sale_price - toFloat64(argMin(close, date)), 2) AS gain_per_share,
if(dateDiff('day', min(date), sale_date) > 365, 'long-term', 'short-term') AS holding_term
FROM global_markets.stocks_daily_aggs
WHERE ticker = 'AAPL'
AND date >= '2024-01-01'
AND date < '2025-01-01'
GROUP BY toStartOfMonth(date)
ORDER BY toStartOfMonth(date)FIFO reaches for the leftmost point: the Jan 2, 2024 lot, $16.06 per share, marked long-term at that sale date. The December lot at the other end of the curve prints -37.89 per share against the very same sale price, and the panel marks it short-term. One stock, one sale, one day. The row the method selects is the number that reaches the tax return, and the holding-term column shows where the one-year line cuts across the year.
Does the choice matter on every position?
Not equally. The gap between the cheapest and the dearest lot bounds everything the election can do, and it varies by name. This panel runs the same monthly buying program across 5 household tickers over 2024.
The exact SQL behind every number
SELECT
ticker AS symbol,
concat('$', toString(round(min(lot_price), 2)),
' to $', toString(round(max(lot_price), 2))) AS lot_price_band,
round(100 * (max(lot_price) / min(lot_price) - 1), 1) AS spread_pct
FROM
(
SELECT
ticker,
toStartOfMonth(date) AS month,
toFloat64(argMin(close, date)) AS lot_price
FROM global_markets.stocks_daily_aggs
WHERE ticker IN ('AAPL', 'MSFT', 'SPY', 'KO', 'JNJ')
AND date >= '2024-01-01'
AND date < '2025-01-01'
GROUP BY ticker, month
)
GROUP BY ticker
ORDER BY spread_pct DESCThe widest band belongs to AAPL, whose monthly lots span $169.3 to $239.59, a spread of 41.5% from bottom to top. The narrowest, JNJ, spans 14.1%. Where every lot sits within a few percent of the others, the election is close to bookkeeping. Where the band is 41.5% wide, the same sale can be a gain or a loss depending on which lot the system consumed.
When do you elect a method, and who reports it?
The election has to be in place at or before settlement of the sale. US equities settle one business day after the trade date under T+1, which leaves a narrow window to identify lots after the order fills. Most brokers make it easier to choose at the ticket, and most also let you set a standing account default that applies to every sale until you change it.
After settlement the identification is locked for that sale. Your broker reports the basis of covered securities to the IRS on Form 1099-B under the method in force, and those figures are what gets matched against the return. A covered security is one acquired after the reporting rules took effect: from 2011 for most corporate stock and from 2012 for mutual fund shares and dividend reinvestment plans, with simpler options and debt instruments following in 2014. Basis on anything older is noncovered and travels on your own records.
HIFO deserves a footnote of its own. It is seldom a separate regulatory category. Brokers implement it as automated specific identification: the system selects the highest-cost lot and records a specific-lot instruction, and the 1099-B looks the same as if you had named the lots by hand. That is also why a broker offering specific ID can usually offer HIFO, while one offering neither leaves you with FIFO. Fund shares carry a further option that stocks do not, average cost, which pools every share of a fund into a single per-share basis. Our note on selling mutual funds at a loss covers the wrinkles pooling creates.
Two rules that sit next to the election
The wash sale rule disallows a loss when substantially identical shares are bought within the 30 days before or the 30 days after the sale that produced it. The disallowed loss carries: it is added to the basis of the replacement shares, creating a new lot with an inflated basis and an adjusted holding period. Harvesting losses by HIFO inside a position you are still buying every month runs into this directly.
The qualified dividend holding period is a second clock on the same shares, counted inside a 121-day window around the ex-dividend date rather than from the trade date alone. Selling one specific lot can break that clock for the shares sold while leaving it running for the shares kept, and the counting rules live in the qualified dividend holding period guide.
Split arithmetic sits outside all of this. A split multiplies the share count of every existing lot and divides its per-share basis, leaving each lot's total basis unchanged and its trade date untouched. No lot selection is involved at all. See split-adjusted price history for what a split does to a price series. Index options sit further out still, carrying 60/40 tax treatment set by statute rather than by holding period.
FAQ
What is the default cost basis method?
FIFO, at nearly every US broker, for individual stocks. Absent an election on the account or at the ticket, the oldest lot is sold first and Form 1099-B reports it that way. Mutual fund positions may default to average cost instead, depending on the fund and the broker.
Can I change my cost basis method after I sell?
For that sale, only up to settlement, which under T+1 is the business day after the trade. Once it settles, the lots identified are the lots sold. A standing account default can be changed at any time for future sales.
Is HIFO allowed?
Yes, as a form of specific identification rather than as a separate named method. The broker automates the pick of the highest-cost lot and records it as a specific-lot instruction, which is the same reporting path as naming lots by hand.
Does the cost basis method change my total tax bill?
Not over the life of a position. It moves gain between tax years and between short-term and long-term treatment. Basis unused on one sale stays with the remaining shares, which the last column of the scenario above prints directly.
What is a covered security on Form 1099-B?
A security whose basis your broker must report to the IRS, decided by when it was acquired: from 2011 for most corporate stock and from 2012 for mutual fund and dividend reinvestment shares, with simpler options and debt following in 2014. Noncovered lots leave the basis box blank, and the figure comes from your own records.
How these panels are pinned
All three panels use fixed 2024 and 2025 date ranges, so the numbers do not move on a later run. Each monthly lot is the close of the first regular session of that month, the closest match to a program that funds on the first business day. None of the five tickers had a stock split inside the window, so no split adjustment is mixed into the price series. The sale price in the second panel is the close of the first session of June 2025, held constant across all 12 lots.
This is a mechanics explainer, not tax advice, and it describes US federal treatment in a taxable account. Inside a tax-deferred account there is nothing to elect, since the sale is not a taxable event.
Every panel above carries the exact SQL that produced it, expand one to see how a lot price was pulled. To line up your own buy dates against a later sale price, ask the question in plain English on the Strasmore terminal.