✦ VT split math: VT is treated as 60% US + 40% Int'l and folded into those rows. VT's value is counted once toward your portfolio total.
Drift Analysis
Rebalancing Action Plan
Tax-Location Cheat Sheet
Where each asset sits most tax-efficiently. Used to suggest the destination account when you have new cash to invest.
Asset
Best account
Why
Bonds FXNAX/VGIT
Trad IRA
Bond interest is taxed as ordinary income. Sheltering in tax-deferred avoids the highest tax bracket.
VTI US Stocks
Any IRA → Taxable
Tax-efficient anywhere. Low yield + mostly qualified dividends + low turnover make it ideal for taxable too.
VXUS Int'l Stocks
Roth IRA → Trad → Taxable
Higher-growth, higher-dividend asset benefits most from Roth's tax-free compounding. When Roth is locked, Trad IRA is the simple fallback. Taxable would let you claim the foreign tax credit (~0.3%/yr) but is offset by VXUS's higher non-qualified dividends in high tax brackets.
Cash SGOV/FDLXX
CMA
Liquidity matters more than tax efficiency for short-term cash.
VT Total World
Hold in Taxable
VT does not pass through the foreign tax credit (under the 50% foreign threshold). Don't add new — selling triggers capital gains.
⚡ Rule of thumb: Always max your IRA contribution space first before adding to Taxable.
📊 Connect Google Sheets
One-time setup. After this, click Sync Now to pull your latest balances from any device — Mac, iPhone, or anywhere with a browser.
1
In your Google Sheet, create a new tab named exactly:
Dashboard_Sync
Fill it in like this (starting at cell A1):
A B C D E
1 Asset Roth Trad IRA Taxable CMA
2 VTI 725.24 57625.93 0 0
3 VXUS 23395.26 14762.81 0 0
4 BONDS 0 0 0 0
5 CASH 0 0 0 0
6 VT 0 0 571.21 0
7
8 IRA Contributed: 5024.99
Replace the numbers with your actual current balances. Update this tab whenever your balances change, then Sync to pull them in.
2
In your Google Sheet, go to Extensions → Apps Script
Delete any existing code, paste this entire script, then click Save (💾):
function doGet(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getSheetByName('Dashboard_Sync');
if (!sh) {
var err = JSON.stringify({error:'Sheet "Dashboard_Sync" not found'});
var cb = e && e.parameter && e.parameter.callback;
return ContentService.createTextOutput(cb ? cb+'('+err+')' : err)
.setMimeType(cb ? ContentService.MimeType.JAVASCRIPT
: ContentService.MimeType.JSON);
}
var assets = ['VTI','VXUS','BONDS','CASH','VT'];
var accounts = ['roth','trad','taxable','cma'];
var values = {};
assets.forEach(function(a, i) {
values[a] = {};
accounts.forEach(function(acct, j) {
var v = sh.getRange(i+2, j+2).getValue();
values[a][acct] = (typeof v === 'number') ? v : 0;
});
});
var iraRow = sh.getRange(8, 2).getValue();
var result = {
values: values,
iraContrib: (typeof iraRow === 'number') ? iraRow : 0,
syncedAt: new Date().toISOString()
};
var json = JSON.stringify(result);
var callback = e && e.parameter && e.parameter.callback;
if (callback) {
return ContentService.createTextOutput(callback+'('+json+')')
.setMimeType(ContentService.MimeType.JAVASCRIPT);
}
return ContentService.createTextOutput(json)
.setMimeType(ContentService.MimeType.JSON);
}
3
Deploy the script as a Web App
Click Deploy → New deployment → select type Web app
Set Execute as:Me · Set Who has access:Anyone
Click Deploy → authorize if prompted → copy the Web app URL