Project Aletheia: Claude as a Financial Advisor to Manage my Factor-Weighted Equity Portfolio.
- Joseph Liu @ Bayesian Capital Management
- Venture , Finance
- April 18, 2026
Table Of Contents
Disclaimer: Not investment advice., personal research project. Past performance is not indicative of future results.
- The $7,000 problem It was the fortnight of April 15th, the dreaded day of paying taxes. I was crunching through every transaction in my CSV file with my tax person when I realized I could drop up to $7,000 into a Roth IRA and get it locked up until I was 60 or 65.
Now, I know finance, I know math, and I know the markets are stupidly efficient. I’m not smarter than them. For most people, for most of history, buying a basket of the top 500 stocks and going outside has been the smartest thing you can do with your money. The market prices in information with a speed that would make the oracles at Delphi cower in shame. I believe this.
But here’s the thing I kept turning over while staring at the Roth IRA paperwork: the argument for passive investing depends on an assumption that’s quietly breaking. And if it’s breaking, what I’m really doing when I buy SPY isn’t “trusting the market,” it’s trusting a specific basket that a specific mechanism produced, under conditions that no longer hold. Which made me wonder whether the same research project I did for myself could scale into something weirder: a $0 financial advisor for everyone who was never going to get one.
More on that at the end. First let’s talk about why I don’t trust the SPY anymore.
- The assumption that’s breaking The argument for passive investing isn’t really Markowitz. Markowitz’s paper just tells you that if you know the covariance structure of returns, you can sit on an efficient frontier. It doesn’t tell you who picks the stocks.
That’s the Efficient Market Hypothesis (Fama), and more precisely the Grossman-Stiglitz paradox: markets are efficient because there’s a sufficiently large class of sophisticated investors who gather information, trade on it, and push prices toward fundamentals. Index funds ride on their backs. Bogle’s whole argument, that most financial advisors are net-negative and you should just dump everything into SPY, only works if that class of smart money is big enough to actually price things.
And that’s the part that’s changing. The passive share of equity AUM keeps climbing. At some point (we may already be there), the cap-weighted index doesn’t reflect “where smart money concentrates its conviction.” It reflects where retirement account auto-contributions flow. Those flows then determine cap-weights, which then determine the index composition, which then pull in more flows. This is roughly the Mike Green argument, and you should read him directly if you want the full case.
[Add Mike Green’s passive-flows-vs-price-discovery graph here, with credit. Alternative: side-by-side finviz-style treemap of S&P 500 in 2018 vs. 2026 showing the visible concentration shift.]
The numbers are not subtle. As of April 14, 2026, the Mag 7 is 33.7% of the S&P 500. In 2025, roughly 42% of the S&P’s total return came from those seven names. When that happens, the S&P 500 stops behaving like a list of “the best companies smart investors collectively picked” and starts behaving like a list of companies that were already big, being made bigger by the fact that being big makes you bigger. Which is definitionally dumb money. It’s literally a one-line algorithm.
- What that actually means for my basket Two concrete consequences.
First: the diversification math breaks. Markowitz’s efficient frontier assumes you can add uncorrelated return streams and shed variance without sacrificing mean. The 2018 SPY had that property reasonably well. The 2025 SPY does not. Even within sectors, we’re seeing increasingly large concentrations inside sectors, to the point where “I own 500 stocks” and “I own the same handful of trades dressed 500 different ways” are starting to describe the same portfolio.
Second: the weightings are a hidden bet I didn’t place. The S&P is currently wildly overweight tech and growth. If I buy SPY today, I’m making a specific factor bet (long tech, long growth, long momentum, short value) whether I like it or not. It’s like a CPI index that decides to overweight TVs and electronics. Viktor Orbán would be jealous of how efficiently we skewed what was supposed to be a neutral distribution into a narrow bet on a few founders younger than the median senator.
So when the monkey paw curled and offered a “well-diversified” basket, with the quotation marks doing all the work, I said no. I still want diversification. I just want to pick the flavor myself.
If the money is going to be locked up until 2072 (a year so distant it sounds like a Pixar title) and the underlying assumptions are already visibly wobbling, I want to be the one deciding the tilts.
- The research question Can I hold a diversified basket where I choose the factor tilts, instead of letting cap-weighting choose them for me?
Because macro conditions will shift across the 40+ years this money is locked up (dovish rates reward momentum, hawkish rates reward balance-sheet strength, uncertainty rewards low dispersion), I want the tilts themselves to be a lever I can pull, not a fixed commitment I lock in at age 30 and pray about.
- The methodology I’ll assume you have undergrad stats: regression, time series, basic linear algebra. If you don’t know what orthogonality or “cross-sectional z-score” means, skip to Section 7 - that’s the part about what this system might mean for financial advice, and it doesn’t require any math. Come back to this section if you get curious.
The conceptual frame is the standard linear factor model from Giuseppe Paleologo’s The Elements of Quantitative Investing, Ch. 4:
$R_t = \alpha + \beta F_t + \epsilon_t$
Excess returns are driven by a small number of pervasive factors $F_t$, loadings $\beta$ that say how each stock reacts to them, alpha $\alpha$ that is idiosyncratic expected return, and $\epsilon_t$ that is the leftover.
Here’s the honest part, because I don’t want anyone at-me-ing with a Ch. 4 critique I already know: Paleologo’s book sets up the full machinery. Estimate loadings, estimate factor returns, compute the factor covariance matrix, optimize the portfolio against it. That is what a real quant shop does, with a risk team and ten analysts.
My implementation is the lightweight version. I skip the estimation entirely. I use z-scored factor metrics (for example, the cross-sectional z-score of P/FCF across the S&P 500) as a direct proxy for factor loadings, and I select and weight stocks to control aggregate factor exposure. I am borrowing Paleologo’s conceptual scaffolding (factor exposures are the thing that matters, control them directly) without doing the full covariance-based portfolio optimization. If you are running a five-digit book like mine, it works. If you are running real money, please do not use this.
The pipeline Z-score each factor cross-sectionally across the 500 stocks: $Z_i = (X_i - \mu)/\sigma$. Direction-adjust. Low P/FCF is good (direction = -1), high momentum is good (direction = +1). Applied as $Z^{adj}_i = d \cdot Z^{raw}_i$. Weighted composite across factors. Weights live in config.yaml. This is the lever I actually turn when I want to re-tilt. Missing factors contribute 0 (neutral). Top 50 by composite score. Score-weighted. A stock with composite 2 gets roughly twice the weight of composite 1. If anything in the top 50 is negative (rare but possible), shift everything up by $|\min| + \epsilon$ first so weights stay positive. Clip to 5% max per stock, 25% max per sector. The two caps can fight each other (sector clipping redistributes into stocks that then breach the single-stock cap), so the code iterates both until weights stop moving. Converges in 2-3 passes. Everything that matters lives in one YAML file The whole system is parameterized in config.yaml. This is the entire control surface. If you wanted to run this yourself with different tilts, this is all you would touch:
factors: price_to_fcf: weight: 0.17 direction: -1 # lower P/FCF = better value momentum_12m: weight: 0.17 direction: 1 # higher return = better momentum share_repurchase: weight: 0.16 direction: 1 low_volatility: weight: 0.17 direction: -1 # BAB anomaly earnings_momentum: weight: 0.17 direction: 1 eps_dispersion: weight: 0.16 direction: -1
portfolio: num_holdings: 50 max_single_weight: 0.05 # 5% max_sector_weight: 0.25 # 25% weighting: score_weighted Want a value tilt? Raise price_to_fcf weight and drop momentum. Worried about concentration? Drop max_single_weight to 3%. Think the Mag 7 is in trouble? Raise eps_dispersion and low_volatility. That is the entire user interface.
The six factors Factor Metric Direction Value Price-to-Free-Cash-Flow Low is good Momentum 12-month return, excluding most recent month High is good Capital allocation Buyback yield High is good Low volatility 252-day realized vol Low is good (Betting Against Beta) Earnings momentum 3-month EPS estimate revision High is good EPS dispersion Analyst estimate spread / |mean| Low is good (uncertainty proxy) Full disclosure on factor selection: I chose these by scrolling through what FMP offered as a data provider and picking what was cheaply implementable. This is a proof of concept. The interesting claim is not “these are the right six factors.” The interesting claim is that whatever six factors you want, the same architecture works and the YAML does all the work.
The diagnostics that matter Two numbers tell you whether the thing worked.
Effective N: $N_{eff} = 1/\sum w_i^2$. Equal weights across 50 stocks gives $N_{eff} = 50$. If one name dominates, it drops. This is how concentrated the portfolio actually is, regardless of how many tickers you hold. For reference, the S&P 500 itself currently runs around $N_{eff} \approx 45$ despite the 500 in the name. That is how bad the concentration got. [TODO: verify against sp500_factor_exposure.py output.]
Factor exposure: $\text{exposure}k = \sum_i w_i \cdot Z^{adj}{k,i}$. The weighted average z-score of the portfolio against each factor. A value of +0.8σ for momentum means the portfolio is tilted 0.8 standard deviations toward high-momentum stocks relative to the universe. This is the number that makes the whole exercise worth it. It is the thing you cannot see when you hold SPY.
- The daily loop Running the composite once gives me a portfolio. Running it every day gives me a monitor.
Each morning, a GitHub Action pulls fresh data, recomputes today’s factor exposures, effective N, top positions, and sector weights, and compares them against yesterday’s. All of that gets handed to Claude. Claude reads both reports and writes up what is notable. If value exposure dropped 0.3σ overnight because something in Consumer Staples rallied, it says so. The writeup gets pushed to a Jekyll site.
You can see the live dashboard at ensyllis.github.io/project_aletheia. [TODO: screenshot or pasted excerpt from a recent daily report.]
What this already gives me is a tripwire. I do not need to rerun the full construction every day. I need to know when the portfolio has drifted far enough from my intended tilts that rebalancing is worth the tax cost, and this tells me.
- Where this gets interesting What I have built so far is the minimum viable version. The more interesting picture is what happens when you keep going.
The next version is not hard to imagine. You add a Financial_Goals.md file where you write, in plain English, what you want your money to do for you: retirement timeline, risk tolerance, specific goals like a down payment or a kid’s college fund. You give Claude an MCP server that lets it edit config.yaml and rerun the pipeline. Now the YAML stops being something you edit by hand and starts being a live object that Claude adjusts on your behalf when your goals or the market regime changes.
Next you layer in a trading thesis file. Something like: “during dovish interest rate regimes, increase weight on momentum and high-beta names; during hawkish regimes, increase weight on balance-sheet strength and low volatility.” Claude reads the morning news, decides what regime we are in, and tilts. Next you give it email. Every morning you get a note from your portfolio: here is what I did, here is why, here are two new factors I think you should consider adding to your model. The responsible production version of this probably has a company in the middle managing the beta model and vetting the factor definitions, rather than letting a single LLM go fully autonomous. But the architecture works the same.
Now sit with what that actually is. A human financial advisor’s job is roughly:
Understand your goals and constraints. Recommend an asset mix. Monitor it for drift. Talk you off the ledge when markets drop 20% and you want to panic-sell. Jobs 1 through 3 are what the system I just described does. Job 4 is the one that is still meaningfully human, because it is about trust and a phone call at the worst possible moment.
And here is the part that actually matters to me. The people who need financial management most (the ones saving for a down payment, a college fund, a retirement on a $50k income) are exactly the people no human advisor will take on, because they do not clear the minimum-assets threshold. The advisor industry’s unit economics have always required ignoring them. The architecture I just sketched does not. It runs for the cost of an API call.
I have not built that full thing. I built the piece for myself. But the piece for myself already works, and the gap between “my Roth IRA” and “a product that could serve anyone with a brokerage account” is smaller than I expected when I started. I would not trust it to handle the phone call part yet. But for everything else, the unit economics of financial advice just fell through the floor, and most people have not noticed.
Thanks to Giuseppe Paleologo for writing the book that made the math legible, and to Mike Green for the passive-vs-active flows framework. Code and daily dashboard live at ensyllis.github.io/project_aletheia.