mattorb Stay curiousTighten Feedback LoopsIterate, Measure, LearnFan of Science, Design, and Systems Thinking

Personal Software: Rebalancing Your Portfolio Across Account Types and Providers

If you are a diligent saver or investor, and find yourself needing to pursue a portfolio asset allocation strategy that is not fully managed by a third party, you will at some point hit a complexity wall where each financial services provider has optimized for encouraging you to hold as much of your money as possible with them so they can help you manage it and orchestrate investments through a single view, regardless of what that might cost you.

Maintaining a whole portfolio across multiple providers with an overall target asset allocation while accounting for yearly drift and tax strategy is often complex enough for a non-financial-professional that many people just don’t do it unless they have an independent financial advisor separate from the provider that is holding their assets. This is why glide path funds are so popular, why a lot of people end up saving everything in one place and why many short-sighted financial plans end up locking people into enormous tax consequences or lost growth opportunities.

Rebalancing a whole portfolio often requires making unique adjustments within each account in a weighted manner to ensure the whole portfolio lands on the desired target percentages overall. Some assets are penalty gated before retirement (401k) or need to be set aside like emergency funds, college savings, and working capital. There are various risks, tax consequences, constraints, and goals to consider.

Up until this last year, access to financial software that enables planning, tax strategy, asset allocation, and investing was hard to come by, with most of the very best reserved for financial advisors.

Enter the era of Personal Software.

Some things we used to build in spreadsheets are now easy to build in totally custom, personal software with a level of capability they could not have before.

Now, if you can think of it, and effectively describe the goals and constraints and how to test that it is working, with some AI help you can build it! and quickly!

So I built an engine, a Rust rebalancing allocation model compiled to WebAssembly, running entirely in a browser tab with no server involved. This allows for running (lots of) automated tests at the speed of Rust, keeping data entirely local, and being able to launch the application entirely through the web browser locally.

I say it’s personal software because I built it primarily for myself, with a lot of constraints and assumptions in mind. Those assumptions aren’t buried in the code. They’re editable rules, with my reasoning written down next to them.

A Role Account Buy/Sell Order editor with eight rows. Each row pairs a role such as SmallCap Buy or Bond Sell with an ordered list of account types: Roth, TaxDeferred, Plan529, TaxableNew. A panel beside it explains that buy rows are fill order and sell rows are trim order, and gives the reasoning for placing small cap in a Roth first.
Figure 1: Placement policy as editable data, showing which account fills first for each sleeve, and which gets trimmed first.

Domain Context: Example Rebalancing

Let’s consider a single-earner young household that has been diligently saving in a few accounts and wants to rebalance their portfolio to 60% large-cap stocks, 18% small-cap, 10% international, 10% bonds, and 2% cash.

They are nowhere near that today. Saving diligently into whatever each provider offered (a target-date fund in the 401(k), a growth fund in the Roth, an international ETF picked up early in a brokerage account) left them with this, measured against the $102,000 that is actually in play after setting aside a $15,000 emergency reserve:

SleeveCurrentTarget
Large cap33.78%60%
Small cap12.63%18%
International34.14%10%
Bonds3.76%10%
Cash15.69%2%

Figure 2: Where the portfolio actually sits against its target, measured on the $102,000 modeled base.

Not one sleeve is within five points of its target, and the two biggest are off by roughly a quarter of the portfolio in opposite directions. That is miscalibrated risk, and in this case, lost growth opportunity for that cash. That is what a few years of saving into single blended funds at three different providers actually looks like. Nobody made a bad decision here; the allocation just was never anybody’s job.

Here’s an example of how they could shift assets to get as close to the target allocation as their constraints allow.

A post-rebalance shift table with seven holdings. The 401(k) and the Roth IRA each show a change in amount of exactly $0.00 while their asset composition percentages shift substantially. Two cash accounts show negative changes of $9,000 and $5,000, a taxable brokerage line shows a positive change of $14,000, and a Starter International ETF shows 0% change in every column.
Figure 3: The necessary money movements to get as close to the target allocation as possible, while minimizing tax consequences.

Rolled up, that is the difference between where they were and where those trades leave them.

Two donut charts side by side labeled Initial and Modeled, with a legend showing large cap up 25.04%, small cap up 5.02%, international down 22.37%, bonds up 6.04%, and cash down 13.73%.
Figure 4: Before and after, with the achievable change in each sleeve.

They don’t quite land on the target. International comes in at 11.76% against a 10% goal, because the $12,000 international ETF sits in a taxable account and selling it would realize gains. The engine holds it at that floor and scales the other four sleeves down proportionally to fit, so large cap lands at 58.82% instead of 60%, small cap at 17.65% instead of 18%, and so on.

Holding that ETF instead of selling it has a payoff, though. Moving a portfolio this far out of alignment back into shape usually means realizing gains somewhere. Here it doesn’t.

A tax consequences table titled Potential taxable sales from taxable holdings, brokerage. The table has no rows and the total potential taxable sales reads $0.00. A reminder underneath says to calculate your tax based on basis, gains, and tax bracket.
Figure 5: An empty table is the good outcome. The whole rebalance runs without a single taxable sale.

This better be well tested! Involves money!

Yes, and the reason I’ll act on what it produces is that every rule I care about is written down as a test, and the names read like a policy document:

locked_529_holding_is_preserved_and_not_traded
inflow_only_mode_avoids_non_cash_sells
minimum_balances_count_toward_reserved_target
bond_target_below_fixed_exposure_returns_closest_feasible_with_advisory
shared_retired_scenario_errors_when_bond_mapping_removed

That is the whole trick to building personal software this way. A constraint you can describe becomes a test, and the test is what stops the next change from quietly undoing it. Every build runs all the regression tests, then builds the WebAssembly binary and runs a browser smoke test that checks the UI and the engine still agree on function names and output keys. One command tells me the rules still hold.

None of this is exotic, and that is rather the point. A tool that only has to satisfy one household can make choices a product never could: no accounts, no server, no dependencies, no telemetry, and a test suite encoding one person’s actual rules. What would you build if the only user you had to satisfy was you?

Related Posts