How to build a low-touch tax-loss harvesting workflow across multiple taxable accounts using free tools

How to build a low-touch tax-loss harvesting workflow across multiple taxable accounts using free tools

I want to share a practical, low-touch workflow I use for tax-loss harvesting across multiple taxable accounts using only free tools. If you're like me — juggling brokerage accounts, ETFs, and a full-time job — it helps to automate the repetitive parts, keep clear records, and only intervene when a real opportunity appears. Below I walk through the process I set up, the tools I rely on, how I avoid wash sales, and a simple logging template you can copy into Google Sheets and adapt to your situation.

Why a low-touch approach?

Tax-loss harvesting works best when it's systematic: you identify losses, realize them at logical thresholds, and maintain documentation. But constantly logging into every broker, checking lots of positions, and manually recording trades is a time sink. My goal was to create a workflow that alerts me only when action is needed and captures the trade history for tax-time without paid software. Free tools like Google Sheets, broker account notifications, and a few lightweight scripts are surprisingly effective.

Overview of the workflow

The workflow has three pillars: monitoring, decision rules, and recordkeeping. Here’s the high-level flow I use:

  • Inventory all taxable accounts and positions into a central Google Sheet.
  • Apply simple, rule-based filters to flag potential harvest candidates (loss threshold, holding period, tax lot info).
  • Receive an email or Slack alert for flagged candidates; review and execute trades in the broker of record.
  • Record realized losses and replacement buys immediately in the sheet and mark potential wash-sale windows.
  • Free tools I use

    Here are the main free pieces I rely on:

  • Google Sheets — central ledger and automation via Google Apps Script.
  • Broker CSV exports — most brokers let you download positions and tax-lot data (Vanguard, Fidelity, Schwab all do).
  • Yahoo Finance or Alpha Vantage (free tier) — for price updates if you want intra-day or daily checks.
  • Gmail filters + Google Apps Script — to detect broker notifications and trigger sheet updates or email alerts.
  • IFTTT / Zapier (free tiers) — to push simple notifications to Slack, Discord, or mobile when criteria are met.
  • All of the above can be used without paying for third-party tax-harvesting platforms.

    Step 1 — Build a central inventory

    I keep a master Google Sheet with one tab per account and a consolidated tab. Minimum columns I track:

    Account Symbol Shares Cost Basis Market Price Unrealized P/L Tax Lot Date Wash Sale Flag Notes
    Broker A VTI 120 $185 $170 -$1,800 2021-06-15 No

    I import CSVs from each broker into the per-account tabs monthly and run a small Apps Script that copies the current price via the GOOGLEFINANCE function or a free API and updates the consolidated tab.

    Step 2 — Simple harvesting rules

    I keep the rules intentionally conservative so I don't trade too often. My typical filters:

  • Unrealized loss ≥ 3% and absolute loss ≥ $500 (for core ETFs I use higher thresholds, e.g., $1,000).
  • Holding period > 30 days (short-term losses can be used but I weigh their impact on my overall tax profile).
  • No replacement or highly correlated holding in any taxable account in the prior 30 days (to avoid wash sale complexities).
  • Liquidity and spread check — avoid harvesting low-volume securities.
  • These are just my defaults — tweak by account size, tax bracket, and portfolio turnover tolerance.

    Step 3 — Replacement security rules

    One of the hardest parts is choosing replacements that avoid wash sales but retain market exposure. I typically use these approaches:

  • Use a broadly similar ETF from a different issuer (e.g., replace Vanguard's VTI with iShares' ITOT or Schwab's SCHB for U.S. total market exposure).
  • Switch from a broad ETF to an equal-weight ETF or a different provider’s fund within the same asset class.
  • For single stocks, consider immediately buying a similar sector ETF or waiting >31 days to re-buy the same name.
  • Document the replacement rationale in the sheet’s Notes column. This is invaluable if the IRS questions the trade or you reconstruct your decisions months later.

    Step 4 — Alerts and low-touch execution

    I aim for alerts only. Here’s how I automate them:

  • Google Apps Script runs nightly to recalc unrealized P/L and apply my thresholds.
  • If a position meets harvest criteria, the script sends a templated email (or Slack message via Zapier) listing the account, symbol, loss amount, and suggested replacement.
  • I review the alert once or twice a week and execute trades in the relevant broker account(s).
  • If you prefer not to run scripts, you can use conditional formatted cells in Sheets and set a filter view — it’s manual but still centralizes the information.

    Step 5 — Record the realized loss and manage wash-sale windows

    After executing a harvest, immediately update the sheet with:

  • Trade date, realized loss amount, replacement security details, and broker trade confirmation number.
  • Mark the original symbol with a 30-day wash-sale window in the "Wash Sale Flag" column (I include both -30 and +30 windows relative to the sale date to track buys that could create a wash sale).
  • If a wash sale occurs (e.g., you bought an identical ETF in another account within 30 days), mark the displaced loss and attribute it to the replacement lot for your own tracking — brokers will handle the formal tax reporting (Form 1099-B), but your internal ledger helps reconcile differences.
  • Reporting and tax prep

    At year-end I use the sheet to cross-check broker 1099-Bs. The key advantages of this system:

  • You have a human-readable audit trail of why and when you harvested.
  • You can reconcile broker-reported disallowed losses (wash sales) quickly because your sheet tracks cross-account buys and sells.
  • It’s easy to hand this sheet to your CPA or upload parts of it to tax software.
  • Common pitfalls and how I avoid them

    Here are practical issues I’ve run into and the fixes I use:

  • Missing tax-lot detail in CSV exports — if a broker omits lots, export a “tax lot” or “realized/unrealized gain” report specifically.
  • Wash sales across IRAs — if you sell a security in a taxable account and buy the same security in an IRA within 30 days, the loss can be permanently disallowed. I use the sheet to flag any trades that cross into retirement accounts.
  • Micro-harvesting — avoiding harvesting tiny losses that cost you time and increase transaction costs; set sensible minimum thresholds.
  • If you want, I can share a starter Google Sheets template with the columns and a simple Apps Script snippet I use to send alerts. It will get you from zero to a low-touch harvesting workflow in a couple of hours.

    One last practical note: I am not a tax professional. Tax rules change and individual situations differ, so use this workflow as a practical system and consult your CPA for specifics on your tax-return reporting and strategy optimization.


    You should also check the following news:

    Portfolio Strategies

    When an airbnb conversion beats long-term leasing: a numbers-first checklist for urban landlords

    21/03/2026

    Converting an urban rental from a long-term lease to short-term (Airbnb-style) can feel like swapping a slow, steady annuity for a high-volatility...

    Read more...
    When an airbnb conversion beats long-term leasing: a numbers-first checklist for urban landlords
    Portfolio Strategies

    How to use a home equity line to buy your next rental without derailing your portfolio

    17/03/2026

    Using a home equity line of credit (HELOC) to acquire a rental property can feel like a clever shortcut: tap into the equity you've built, move...

    Read more...
    How to use a home equity line to buy your next rental without derailing your portfolio