I use Betterment for my taxable brokerage and Wealthfront for my Roth IRA. Trying to track both in Beancount and running into challenges. Looking for advice on automation strategies.
Why Robo-Advisors + Beancount?
The robo-advisor market is exploding - expected to hit $14.29B in 2025 and $54.73B by 2030. I use them because:
- Automatic rebalancing (I’m lazy)
- Tax-loss harvesting in taxable account
- Low fees (0.25% at Betterment)
But I want Beancount for:
- Consolidated view across all accounts
- Custom queries and analysis
- Long-term archival
- Net worth tracking with real estate, crypto, etc.
Current Challenges
1. Transaction Volume
Robo-advisors rebalance frequently. My Betterment account had 47 transactions last month - mostly small rebalancing trades. Manually importing these would be insane.
2. Tax-Loss Harvesting Complexity
Betterment swaps between similar ETFs (e.g., VTI ↔ SCHB) to harvest losses. This creates:
- Wash sale tracking nightmares
- Cost basis that differs from what Beancount calculates
- Lots that I need to track but didn’t explicitly create
3. No Good API
Neither Betterment nor Wealthfront has a public API. I’m stuck with:
- Manual CSV downloads
- Screen scraping (fragile)
- Plaid (expensive for personal use)
What I’ve Tried
OFX Downloads: Betterment supports OFX but the data is incomplete - missing cost basis info.
CSV + Custom Importer: Works but requires manual download and doesn’t handle the tax lot complexity well.
Questions
-
Has anyone automated Betterment/Wealthfront imports? What’s your stack?
-
How do you handle the cost basis discrepancy between robo-advisor’s records and Beancount’s FIFO/LIFO calculations?
-
Is there a plugin for tracking tax-loss harvesting swaps properly?
-
Should I just trust the robo-advisor’s tax docs and only track at the account level (not individual lots)?
Appreciate any guidance from folks who’ve solved this.
Hot take: the complexity you’re describing is a sign you should ditch the robo-advisors entirely.
The Case for Manual Three-Fund Portfolio
I track a simple three-fund portfolio in Beancount:
- VTI (US Total Market)
- VXUS (International)
- BND (Bonds)
Rebalancing: Once per year, maybe 6 transactions total. Takes 30 minutes.
Tax-loss harvesting: I do it manually when markets drop significantly. Maybe 2-3 times per year. I control which lots to sell (specific identification), so Beancount’s tracking is always accurate.
Fees: Vanguard charges nothing. Betterment’s 0.25% on $100K = $250/year. Over 30 years with 7% returns, that’s ~$20K in lost gains.
Why This Works Better
- Simplicity - 6 transactions/year vs 47/month
- Control - I know exactly what I own and why
- Tax efficiency - I choose when to harvest, not an algorithm
- Beancount compatibility - Trivial to track
The whole point of robo-advisors is “set and forget.” But if you’re already tracking in Beancount, you’re not forgetting - you’re adding complexity for marginal benefit.
Just my 2 cents. The robo-advisor market growth you cited is mostly from people who don’t track their finances at all. We’re a different audience.
I’ve dealt with this exact problem. Here’s what worked for me:
The Cost Basis Problem
You’re right that Beancount’s calculated cost basis will diverge from Betterment’s. This happens because:
- Betterment uses specific lot identification for tax optimization
- Beancount defaults to FIFO
- Wash sale adjustments aren’t automatic in Beancount
My Solution: beancount-asset-transfer Plugin
The beancount-asset-transfer plugin is designed for exactly this. It generates in-kind transfer entries between accounts while preserving the original cost basis.
Use case: When Betterment swaps VTI → SCHB for tax-loss harvesting:
2024-03-15 * "Tax-loss harvest swap"
Assets:Betterment:VTI -100 VTI {45.00 USD} @ 42.00 USD
Assets:Betterment:SCHB 100 SCHB {45.00 USD}
Income:Capital:Losses 300.00 USD
The SCHB inherits VTI’s cost basis, which is what happens for tax purposes.
For Wash Sales
You need to manually adjust cost basis when wash sales occur. I add metadata:
2024-03-20 * "Buy SCHB" ^wash-sale-adj
Assets:Betterment:SCHB 50 SCHB {48.50 USD}
wash_sale_adjustment: 3.00 USD
Then I have a custom query that adds these adjustments to cost basis.
My Recommendation
For your question #4: Don’t track at account level only. The whole point of Beancount for investments is accurate cost basis for tax planning. If you give that up, you might as well use a spreadsheet.
Yes, it’s work. But you only need to reconcile with Betterment’s 1099 once per year. The monthly tracking is just data entry.
I use Schwab Intelligent Portfolios (it’s free - no management fee) and track everything in Beancount. Here’s my workflow:
Why Schwab
- No advisory fee (Betterment’s 0.25% adds up)
- Still get automatic rebalancing and TLH
- Good OFX support
- Can call a human if needed
Trade-off: They keep ~6% in cash (that’s how they make money). I’m fine with that for the convenience.
My Import Workflow
Monthly Process (~20 min)
- Download OFX from Schwab
- Run importer using
beancount-reds-importers - I customized the Schwab module
- Review and adjust - The importer handles 90% correctly, I fix edge cases
- Reconcile with Schwab’s month-end statement
Code Snippet
# schwab_importer.py
from beancount_reds_importers import schwab
class SchwabIntelligent(schwab.Importer):
def categorize_transaction(self, row):
if 'REBALANCE' in row['description']:
return 'rebalance'
if 'TAX LOSS' in row['description']:
return 'tlh_swap'
return super().categorize_transaction(row)
On the Cost Basis Question
I gave up on matching Schwab’s cost basis exactly. Instead:
- I use Beancount’s cost basis for planning (estimated tax impact)
- I use Schwab’s 1099-B for filing (actual tax basis)
The discrepancy is usually small (<5%) and I’d rather have slightly imprecise estimates than spend hours reconciling lot-by-lot.
For Betterment/Wealthfront
Your best bet might be Plaid even though it’s not free. The plaid-to-beancount project on GitHub pulls transactions automatically. Costs ~$500/year for personal use, but saves hours of manual work.
Thanks everyone - this is exactly the kind of practical advice I needed.
You’re not wrong about the irony. I chose robo-advisors for simplicity but now I’m spending more time wrestling with imports than I would just doing manual rebalancing.
The fee math is sobering too. $250/year × 30 years compounded… yeah, that’s a new car.
I think the real value prop was behavioral: I started with robo-advisors when I didn’t trust myself not to panic-sell. Now that I’ve been through a few market cycles, maybe I’m ready for the three-fund approach. Something to think about.
The beancount-asset-transfer plugin is the missing piece! I didn’t know it preserved cost basis on swaps. That solves my tax-loss harvesting tracking problem.
Your wash sale metadata approach is clever. I’ll implement something similar:
2024-03-20 * "SCHB purchase" #wash-sale
Assets:Betterment:SCHB 50 SCHB {48.50 USD}
wash_adjustment: 3.00 USD
original_lot: "VTI-2024-01-15"
And you’ve convinced me not to go account-level only. The whole point is accurate tax planning.
@hybrid_inv - Schwab Is Interesting
I hadn’t considered Schwab Intelligent Portfolios. No fee + good OFX is appealing. The 6% cash drag is annoying, but probably less than Betterment’s 0.25% over time.
Your two-tier approach makes sense:
- Beancount for planning (good enough estimates)
- 1099-B for filing (actual basis)
I was trying to match exactly, which is probably overkill.
My Plan
- Short term: Implement beancount-asset-transfer for TLH swaps, stop trying to match cost basis exactly
- Medium term: Evaluate moving Wealthfront IRA to Schwab for better OFX
- Long term: Consider moving taxable to three-fund manual management
Thanks again - this community is invaluable.