Tax-Aware Rebalancing: what to buy and sell, and in which account, to get back on target
In one minute: once a month, this tab tells you whether your portfolio has drifted outside the band you set. If it has, it gives you a trade list: which fund to sell or buy, in which account, and how many shares. Sales come from IRAs, Roths and 401(k)s first (no tax), and every account pays for its own buys.
Try it in 60 seconds: Make a copy, then open the Rebalancing w Tiller Example Data tab. It is already set up with sample data, so the dashboard works right away.
Want to look first? (view only)
- Rebalancing w Tiller Example Data: set up for the sample data.
- Rebalancing: minimal setup, to start from with your own data.
The question it answers
How far has my portfolio drifted from my target allocation, do I need to act, and if so, how do I get back on target with the least tax?
If your money is spread across a taxable brokerage, an IRA, a Roth and a 401(k), an allocation chart can tell you that Bonds are 2.8 points light. It can’t tell you which account to sell from, which account to buy in, or what the sale will cost you in tax. This sheet answers all three on a single tab, using the account type, cost basis and value of every position in Holdings, and the daily history in Holdings History.
The dashboard (sample data). Total holdings $130,390. Three of five classes are outside the ±1.0 percentage point band, and the largest drift is 2.80% (Bonds under target).
Why it is useful
It tells you whether to act at all. Each asset class has a target and a band: ±1.0 percentage point in the sample, or a dollar band for a dollar target such as a cash reserve. The status line at the top says how many classes are outside their band, so a monthly check takes a minute. When everything is inside the band, the trade list still shows what a full rebalance would take, but you don’t need to act on it.
It sells in the cheapest place first. A sale inside an IRA, Roth or 401(k) has no tax cost, so the plan sells there first. Taxable sales cover only what those accounts can’t, starting with the holding that has the lowest gain. In the sample data, US Equity is $1,442 overweight and the Roth IRA covers it entirely with IVV. The only taxable sale is $3,361 of Emerging Markets (VWO), because that class exists only in the taxable account.
Every account pays for its own buys. The plan never asks you to move cash from one account to another. The “Cash by account” table shows each account’s sells, buys and net cash, and all three sample accounts read “self-funded”.
Buys land where you would rather hold them. You rank the account types you prefer for each class (for example bonds in tax-deferred first, US equity in taxable first). When a buy would land in the wrong kind of account, the plan swaps: it sells a class inside a tax-advantaged account and buys the other class there instead, so each class ends up where you prefer it without adding a taxable sale. In the sample, bonds go into the 401(k) and US equity into the taxable account. Every swap trade is labeled so you can see why it is on the list.
It checks its own work. The plan-check table compares planned sells and buys to what each class needs and says “closes the gap” for each one (and flags any that don’t). If you want to trade a different amount, type it into the yellow Planned $ column and the check follows your numbers.
It shows what it can’t fix. The asset location table shows how much of each class sits outside its preferred account type. It never sells a taxable holding just to relocate it, because that would create a taxable gain, but it does show you the gap. In the sample, $9,880 (7.58%) of holdings sit outside their preferred account type.
It uses your history to help you choose a band. Holdings History feeds a drift table and a band backtest. Over the sample’s 120 days, a ±0.25 pp band would have triggered 26 rebalances, a ±0.5 pp band 8, and a ±1.0 pp band just 1, which helps you decide how tight to set your own band.
A quick tour
Section 2 of the dashboard: the plan by asset class. For each class it shows the amount to sell or buy, how much of it is held in tax-advantaged versus taxable accounts, and how much of the sale can be covered inside tax-advantaged accounts. Here that is $1,442 with no tax, and $3,361 that has to come from taxable.
The trade list: holding by holding. Seven trades in the sample. Each line names the action, class, holding, account and account type, the holding’s gain, and the amount. The Note column explains the line (for example “No tax — retirement account”, or “Taxable sale · gain 25.9%”), and the Order column converts the amount to shares at the current price. Lines marked Swap are the swap trades described above. The yellow Planned $ column is optional: leave it blank to accept the suggestion. The “Cash by account” table on the right confirms that every account nets to $0.
Plan check. Every class shows “closes the gap”: planned sells minus planned buys equals what the class needs.
Asset location. Where each class is held, by account type, and how much sits outside its preferred type.
Drift history and band backtest. Drift by date from Holdings History, with a trend line per class, and a backtest that starts you at target, lets the market move you, and rebalances whenever any class passes the band. This helps you decide how large to set your acceptable bands.
Install and setup
What you need: a Tiller-powered Google spreadsheet (the Foundation Template is recommended) with the Holdings and Holdings History sheets added from the Tiller Console. Holdings is available for Direct Fills Google Sheets.
You don’t type in your holdings. Once your investment accounts are connected in the Tiller Console and the Holdings sheet is added, Tiller fills it in.
Option A: try it first with sample data
- Click Make a copy in the links at the top of this post and confirm the prompt.
- Open the Rebalancing w Tiller Example Data tab. The copy includes the sample Holdings and Holdings History, so the dashboard works immediately.
Option B: use it on your own Tiller sheet
- In the Tiller Console, connect your investment accounts, add the Holdings and Holdings History sheets to your Tiller spreadsheet, and let the data fill in.
- Use the Make a copy link at the top of this post to get your own copy. In your copy, right-click the tab named Rebalancing (the one without “w Tiller Example Data”) and choose Copy to > Existing spreadsheet, then pick your Tiller spreadsheet.
- In your spreadsheet, rename the new tab (it will be called “Copy of Rebalancing”) to Rebalancing. The name doesn’t matter to the formulas, which read your own Holdings and Holdings History sheets directly.
- Open the setup panel to the right of the dashboard (columns R to Z; the dashboard header says “Open ⊞ Settings at the right”) and work through steps 2 to 6 below (they use the same numbering as the panel’s own “How to set up” list; step 1 is Option B step 1 above). It takes about ten minutes, once. Yellow cells are the only cells you edit.
The setup steps
-
Targets. List your asset classes (up to 12). Each target is either a percentage of the portfolio or a fixed dollar amount, which is handy for a cash reserve. Dollar targets are funded first, and the percentage targets share out the rest and must add to 100%. Type
45for 45%; for a dollar target, choose$in the next column and type the amount (the cell turns blue). A check under the table tells you if your percentages don’t add up. -
Bands, sell order and fractional shares. Set the band for percentage targets (in percentage points) and for dollar targets (in dollars). Choose the sell order inside tax-advantaged accounts: “Consolidate” sells the smallest and non-preferred holdings first, “Fewest trades” sells the largest first. Tick the fractional-shares box if your broker lets you buy part of a share.
-
Securities. Give every ticker an asset class. Holdings with no ticker (common in 401(k)s) use their Description exactly as it appears in Holdings. A red “Needs an asset class” list on the right names anything in Holdings that is still unassigned, and turns into “✓ Every holding has an asset class” when you’re done. Optionally tick Preferred buy beside the fund you want each class to collect in.
-
Accounts. The sheet reads each account’s tax type (Taxable, Tax-deferred, Roth or HSA) from Tiller’s Account Type. Check the list. Only if one is wrong, use the yellow override table to choose the right tax type, or tick Exclude to leave the account out.
-
Preferred location order. For each asset class, rank the account types where you would rather hold it, 1st choice first.
When you’re done, check the result: back on the dashboard, the Status cell should no longer say “
Assign all holdings in ⊞ Settings”, and the “Total of % targets” line under the Targets table should read “✓ % targets add to 100%”.
How to use it each month
- Open the Rebalancing tab and check the “Holdings as of” date in the header. Tiller refreshes Holdings on its own schedule.
- Read the status. If it says a class is outside its band, continue. If everything is
, you’re done. - Read the trade list in section 2. Each line says what to sell or buy, in which account, and how many shares. Lines marked “Swap” put a class in the account type where you prefer it; the note under the class table explains why the list can have more buys and sells than the class-level table above it.
- Place the trades at your broker. Each account should net to $0 in “Cash by account”, so no transfers are needed.
- Optional: change an amount. Type into Planned $ on any line. The plan-check table recalculates and tells you whether every class still closes its gap.
- Glance at asset location to see how much still sits outside its preferred account type.
- Revisit your band now and then using the drift history and backtest, especially if you’re being asked to rebalance more often than you’d like.
Once Tiller’s next refresh picks up your trades, the status clears on its own.
How the plan is built (for the curious)
- Each class’s need is its target minus its current value. A class inside its band can still be given a small buy or sell, because the plan rebalances the whole portfolio back to target, not only the classes that tripped the band. In the sample, Intl Developed is within its band and still gets a $1,157 buy.
- Sells. For each class that needs selling, candidate holdings are ordered with tax-advantaged accounts first and taxable accounts last. Taxable holdings are ordered by lowest gain, using the cost basis in Holdings.
- Buys. Sale proceeds are totaled per account, and each buy class is spread across the accounts that sold, ranked by your preferred location order. The fund bought is the one you ticked as Preferred buy, or otherwise the largest holding of that class in that account. If the account holds none, the line says “(not held yet)”.
- Swaps. Where a buy would land in an account type that isn’t preferred for that class, the plan looks for a swap partner inside a tax-advantaged account: sell one class there, buy the other, so both end up more where you’d prefer them. Swaps never add a taxable sale, must be at least $100, and there can be up to six per plan.
Assumptions, limitations and known issues
- Tax is a rule of thumb, not a tax calculation. The sheet uses each position’s gain (value versus cost basis from Holdings) to order taxable sales. It doesn’t know lot dates, so it can’t tell short-term from long-term gains, and it doesn’t check wash-sale rules or state taxes. It isn’t tax or investment advice, so check the trades against your own situation.
- It follows your inputs. Asset-class mappings, the preferred location order and the tax type of each account are all set by you (the tax type starts from Tiller’s Account Type). Wrong inputs give a wrong plan, and if you clear a class’s target it counts as 0% and the sheet will propose selling that whole class, so watch the “% targets add to…” message under the Targets table.
- Existing misplaced holdings stay put. The plan steers new buys and swaps toward the right accounts, but it never sells a taxable holding just to move it, since that would realize a gain. The asset location table shows what is left over (in the sample, Emerging Markets in the taxable account).
- Missing cost basis. Some institutions don’t send cost basis to Tiller. A taxable holding without it has an unknown gain, so the plan sells it last, after holdings whose gain is known. The Note column says “gain unknown — check the cost basis”, and the line above the trade list counts how many taxable holdings are missing it. A money market fund without cost basis is treated as 0% gain, which is how a money market fund behaves.
- Cash. The sheet sees only what Tiller Holdings reports. In my own data, cash showed up only as a money market fund (which the Cash class picks up), so a plain cash balance may not appear. If one is missing, you can type it into the Holdings sheet as your own row; Tiller keeps rows it didn’t create when it refreshes. Some Holdings rows have shown a money market fund’s Value as $1.00 (the price) instead of quantity × price; the sheet detects that and uses quantity × price.
- Capacity. 12 asset classes, 40 rows in the securities table, about 20 accounts in the override table, and a trade list of about 30 lines.
- Whole shares. If fractional shares are turned off, the Order column rounds down, so the small remainder isn’t reflected in “Cash by account”.
- Errors are quiet. If something unexpected breaks the trade-plan formula, the list shows “No trades needed” rather than an error. If you see that while the status says classes are outside the band, treat it as a bug and tell me.
- Fixed settings. The $100 minimum swap and the six-swap limit are built into the formula rather than exposed as settings. The plan formula is long (about 7,100 characters in cell A43), so edit it only if you’re comfortable in Sheets.
- Sample data. The sample Holdings and Holdings History are fictional, dated September 9, 2026, with 120 days of history.
- Column names. The sheet finds each Holdings and Holdings History column by its header name, so extra columns you add, or a change in column order, don’t break it. It also accepts the older names from the first beta templates (Current Value, Current Price, Account Name).
- Repeated rows in Holdings History. Tiller can write the same holding several times a day. For each day and account the sheet uses only the latest update, and counts each holding once, so repeated rows don’t inflate the drift history or the backtest.
- Old data. The dashboard header shows the “Holdings as of” date, and adds a warning when that date is more than a week old, so you know to refresh your investment accounts in Tiller before you trade.
How it was checked
How it was checked. I compared the sheet with an independent Python model of the plan logic on 80,000 randomly generated multi-account portfolios. The checks were: no negative amounts or duplicate sell lines, no holding oversold, every class closes its gap, and every account nets to $0. There were no violations. Live scenarios in the sheet matched the model. I also ran the sheet against a real Tiller-connected portfolio with taxable, Traditional IRA, Roth IRA, 401(k) and HSA accounts.
FAQ
Do I have to type in my holdings?
No. Once your investment accounts are connected and the Holdings sheet is added from the Tiller Console, Tiller fills it in. The main setup step is giving each ticker an asset class.
The status says “
Assign all holdings in ⊞ Settings”. What do I do?
A holding in Holdings has no asset class yet. The red “Needs an asset class” list in the setup panel names it; add it to the Securities table and pick a class.
Some of my 401(k) funds have no ticker.
Use the fund’s Description exactly as it appears in Holdings in the Securities table.
The trade list says “No trades needed”, but the status says classes are outside the band.
That shouldn’t happen. The plan formula hides its own errors, so this is the one sign that something broke. Please post a reply here and I’ll fix it.
Why does the trade list have more lines than the class table?
Lines marked Swap move a class into an account type where you prefer it (for example bonds into the 401(k)), without adding a taxable sale. The net amount per class is unchanged, and the plan check confirms each class still “closes the gap”.
Why is a holding marked “(not held yet)”?
The plan wants to buy a class in an account that doesn’t hold any fund of that class. Pick a fund of that class to buy in that account at your broker.
Can I trade a different amount than suggested?
Yes. Type it into the yellow Planned $ column. The plan check and the “Cash by account” table update, and tell you if a class no longer closes its gap or an account no longer nets to $0.
Does it know short-term vs long-term gains, or wash sales?
No. Tiller Holdings gives one cost basis per position, not tax lots, so the sheet can’t see lot dates. It uses each position’s overall gain as a guide, and flags when you buy something while selling at a loss. Check the trades against your own tax situation.
How often should I use it?
Once a month is plenty. If everything is green, you’re done.
What’s in the workbook
The workbook has four tabs: Holdings and Holdings History (the Tiller source sheets, with sample data), Rebalancing w Tiller Example Data (already set up for the sample data, so try this first), and Rebalancing (the same dashboard and setup panel with nothing configured, for you to set up with your own data).
Everything is native Google Sheets: formulas (LET, REDUCE, VSTACK/HSTACK, FILTER, SORT and friends), SPARKLINE, data validation, conditional formatting and a built-in chart. No Apps Script, add-ons or third-party tools. Everything recalculates when Holdings or Holdings History change.
Video walkthrough: coming soon.
Permissions
It’s ok for others to copy, use, and modify this workflow, but I ask that you share your modifications back with me if you do that.










