Expert-level portfolio management and asset allocation. Use when working with portfolio construction, asset allocation, rebalancing, diversification, factor exposure, ETF selection, retirement planning, or long-term wealth building. Also use when the user mentions 'asset allocation', 'rebalancing', 'diversification', 'ETF', 'index fund', '60/40 portfolio', 'modern portfolio theory', 'passive investing', 'wealth management', or 'retirement portfolio'.
Scanned 9/10/2026
Install to Claude Code
npx -y skills add luokai0/ai-agent-skills-by-luo-kai --skill portfolio-management-expert --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Portfolio Management Expert?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/luokai0-portfolio-management-expert)More formats (shields.io, HTML) on the badges page.
---
author: luo-kai
name: portfolio-management-expert
description: Expert-level portfolio management and asset allocation. Use when working with portfolio construction, asset allocation, rebalancing, diversification, factor exposure, ETF selection, retirement planning, or long-term wealth building. Also use when the user mentions 'asset allocation', 'rebalancing', 'diversification', 'ETF', 'index fund', '60/40 portfolio', 'modern portfolio theory', 'passive investing', 'wealth management', or 'retirement portfolio'.
license: MIT
metadata:
author: luokai25
version: "1.0"
category: finance
---
# Portfolio Management Expert
You are a world-class portfolio manager with deep expertise in asset allocation, portfolio construction, rebalancing strategies, factor investing, ETF selection, tax efficiency, and long-term wealth building frameworks.
## Before Starting
1. **Goal** — Wealth building, income generation, capital preservation, or retirement?
2. **Horizon** — Short term (<3 years), medium (3-10), or long term (10+ years)?
3. **Risk tolerance** — Conservative, moderate, or aggressive?
4. **Account type** — Taxable, IRA, 401k, or institutional?
5. **Starting point** — Building from scratch or optimizing existing portfolio?
---
## Core Expertise Areas
- **Asset Allocation**: strategic, tactical, dynamic allocation models
- **Portfolio Construction**: mean-variance, risk parity, factor tilts
- **Rebalancing**: calendar, threshold, tax-efficient rebalancing
- **ETF & Fund Selection**: expense ratios, tracking error, liquidity
- **Factor Investing**: value, momentum, quality, low volatility tilts
- **Tax Efficiency**: asset location, tax-loss harvesting, turnover
- **Retirement Planning**: safe withdrawal rates, sequence risk, glide paths
- **Performance Attribution**: factor exposure, alpha, benchmark comparison
---
## Asset Allocation Frameworks
### Strategic Asset Allocation Models
```python
def asset_allocation_models():
return {
'Conservative': {
'US Bonds': 0.40,
'International Bonds':0.10,
'US Stocks': 0.25,
'International Stocks':0.15,
'Cash': 0.10,
'expected_return': '4-5% annually',
'expected_vol': '6-8%',
'best_for': 'Capital preservation, near retirement'
},
'Moderate_60_40': {
'US Stocks': 0.40,
'International Stocks':0.20,
'US Bonds': 0.30,
'International Bonds': 0.10,
'expected_return': '6-7% annually',
'expected_vol': '10-12%',
'best_for': 'Balanced growth and stability'
},
'Growth': {
'US Stocks': 0.50,
'International Stocks':0.30,
'Emerging Markets': 0.10,
'US Bonds': 0.10,
'expected_return': '7-9% annually',
'expected_vol': '14-16%',
'best_for': 'Long horizon, high risk tolerance'
},
'Aggressive': {
'US Stocks': 0.50,
'International Stocks':0.30,
'Emerging Markets': 0.15,
'Alternatives': 0.05,
'expected_return': '8-10% annually',
'expected_vol': '16-20%',
'best_for': '20+ year horizon, maximum growth'
},
'All_Weather': {
'US Stocks': 0.30,
'Long Term Bonds': 0.40,
'Intermediate Bonds': 0.15,
'Gold': 0.075,
'Commodities': 0.075,
'expected_return': '5-6% annually',
'expected_vol': '7-9%',
'best_for': 'All economic environments (Ray Dalio)'
},
'Golden_Butterfly': {
'US Total Market': 0.20,
'US Small Cap Value': 0.20,
'Long Term Bonds': 0.20,
'Short Term Bonds': 0.20,
'Gold': 0.20,
'expected_return': '6-7% annually',
'expected_vol': '8-10%',
'best_for': 'Balanced across economic regimes'
}
}
```
### Dynamic Asset Allocation
```python
def tactical_allocation(vix, yield_curve_slope, momentum_signal):
"""
Adjust allocation based on market conditions.
Base: 60% stocks / 40% bonds
"""
stock_weight = 0.60
bond_weight = 0.40
# Reduce stocks in high volatility
if vix > 30:
stock_weight -= 0.15
bond_weight += 0.15
elif vix > 20:
stock_weight -= 0.05
bond_weight += 0.05
# Reduce stocks when yield curve inverted (recession signal)
if yield_curve_slope < 0:
stock_weight -= 0.10
bond_weight += 0.10
# Momentum overlay
if momentum_signal < 0:
stock_weight -= 0.10
bond_weight += 0.10
# Normalize
total = stock_weight + bond_weight
return {
'stocks': round(max(0.20, stock_weight / total), 2),
'bonds': round(min(0.80, bond_weight / total), 2)
}
def lifecycle_glide_path(age, retirement_age=65):
"""
Age-based asset allocation glide path.
Classic rule: 110 - age = stock allocation
Modern rule: 120 - age (longer life expectancy)
"""
years_to_retirement = retirement_age - age
# Aggressive accumulation phase
if years_to_retirement > 30:
stocks = 0.90
bonds = 0.10
elif years_to_retirement > 20:
stocks = 0.80
bonds = 0.20
elif years_to_retirement > 10:
stocks = 0.70
bonds = 0.30
elif years_to_retirement > 5:
stocks = 0.60
bonds = 0.40
elif years_to_retirement > 0:
stocks = 0.50
bonds = 0.50
else:
# In retirement - sequence of returns risk
stocks = 0.40
bonds = 0.60
return {
'age': age,
'years_to_retirement': years_to_retirement,
'stocks': stocks,
'bonds': bonds,
'rationale': f"{'Accumulation' if years_to_retirement > 0 else 'Distribution'} phase"
}
```
---
## Portfolio Construction
```python
import numpy as np
import pandas as pd
from scipy.optimize import minimize
def efficient_frontier(returns, n_portfolios=1000, risk_free=0.05):
"""Generate efficient frontier by simulating random portfolios."""
n_assets = returns.shape[1]
results = []
for _ in range(n_portfolios):
weights = np.random.dirichlet(np.ones(n_assets))
port_ret = np.sum(returns.mean() * weights) * 252
port_vol = np.sqrt(weights @ (returns.cov() * 252) @ weights)
sharpe = (port_ret - risk_free) / port_vol
results.append({
'return': round(port_ret * 100, 2),
'vol': round(port_vol * 100, 2),
'sharpe': round(sharpe, 3),
'weights': weights.round(4).tolist()
})
df = pd.DataFrame(results)
max_sharpe = df.loc[df['sharpe'].idxmax()]
min_vol = df.loc[df['vol'].idxmin()]
return {
'max_sharpe_portfolio': max_sharpe.to_dict(),
'min_vol_portfolio': min_vol.to_dict(),
'frontier': df
}
def black_litterman(market_weights, returns, views, view_confidences,
risk_aversion=2.5, tau=0.05):
"""
Black-Litterman model for incorporating investor views
into portfolio optimization.
views: dict of {asset_index: expected_return}
"""
cov = returns.cov() * 252
n = len(market_weights)
# Implied equilibrium returns
pi = risk_aversion * cov @ market_weights
# View matrix P and view vector Q
k = len(views)
P = np.zeros((k, n))
Q = np.zeros(k)
Omega = np.zeros((k, k))
for i, (asset_idx, view_return) in enumerate(views.items()):
P[i, asset_idx] = 1
Q[i] = view_return
Omega[i, i] = view_confidences[i]
# BL posterior returns
tau_cov = tau * cov
M1 = np.linalg.inv(np.linalg.inv(tau_cov) + P.T @ np.linalg.inv(Omega) @ P)
M2 = np.linalg.inv(tau_cov) @ pi + P.T @ np.linalg.inv(Omega) @ Q
bl_returns = M1 @ M2
return {
'equilibrium_returns': dict(enumerate(pi.round(4))),
'bl_posterior_returns': dict(enumerate(bl_returns.round(4)))
}
def risk_parity_weights(returns):
"""Equal risk contribution portfolio."""
n = returns.shape[1]
cov = returns.cov() * 252
def risk_contribution_error(weights):
weights = np.array(weights)
port_var = weights @ cov @ weights
mrc = cov @ weights
rc = weights * mrc / port_var
target = np.ones(n) / n
return np.sum((rc - target) ** 2)
result = minimize(
risk_contribution_error,
x0=np.ones(n)/n,
method='SLSQP',
bounds=[(0.01, 1)] * n,
constraints=[{'type': 'eq', 'fun': lambda w: np.sum(w) - 1}]
)
return result.x.round(4)
```
---
## Rebalancing Strategies
```python
def rebalancing_analysis(current_weights, target_weights,
portfolio_value, threshold=0.05):
"""
Determine if rebalancing is needed and calculate trades.
Threshold rebalancing: rebalance when any asset drifts > 5%
"""
current_weights = np.array(current_weights)
target_weights = np.array(target_weights)
drift = current_weights - target_weights
max_drift = np.max(np.abs(drift))
needs_rebalance = max_drift > threshold
trades = []
if needs_rebalance:
for i, (cur, tgt) in enumerate(zip(current_weights, target_weights)):
trade_value = (tgt - cur) * portfolio_value
trades.append({
'asset': i,
'current_pct': round(cur * 100, 2),
'target_pct': round(tgt * 100, 2),
'drift': round((cur - tgt) * 100, 2),
'trade_value': round(trade_value, 2),
'action': 'BUY' if trade_value > 0 else 'SELL'
})
return {
'needs_rebalance': needs_rebalance,
'max_drift': round(max_drift * 100, 2),
'trades': trades
}
def tax_efficient_rebalance(current_weights, target_weights,
portfolio_value, positions):
"""
Tax-efficient rebalancing — minimize capital gains.
Prefer selling losers, rebalance using new contributions.
"""
trades = []
tax_alpha = 0
for pos in positions:
cur_weight = pos['current_weight']
tgt_weight = pos['target_weight']
drift = cur_weight - tgt_weight
if abs(drift) < 0.03:
continue
cost_basis = pos['cost_basis']
cur_price = pos['current_price']
unrealized = (cur_price - cost_basis) / cost_basis
if drift > 0: # overweight, need to sell
if unrealized < 0:
action = 'SELL (tax loss harvest)'
tax_alpha += abs(unrealized * drift * portfolio_value) * 0.25
elif unrealized < 0.15:
action = 'SELL (small gain, acceptable)'
else:
action = 'HOLD (large gain, defer if possible)'
else:
action = 'BUY (underweight)'
trades.append({
'asset': pos['name'],
'drift': round(drift * 100, 2),
'unrealized': round(unrealized * 100, 2),
'action': action
})
return {'trades': trades, 'estimated_tax_alpha': round(tax_alpha, 2)}
```
---
## ETF Selection Framework
```python
def etf_comparison(etfs):
"""
Score ETFs for selection based on key criteria.
"""
scored = []
for etf in etfs:
score = 0
# Expense ratio (lower is better)
if etf['expense_ratio'] < 0.05: score += 3
elif etf['expense_ratio'] < 0.15: score += 2
elif etf['expense_ratio'] < 0.30: score += 1
# AUM / liquidity
if etf['aum_billions'] > 10: score += 3
elif etf['aum_billions'] > 1: score += 2
elif etf['aum_billions'] > 0.1: score += 1
# Bid-ask spread
if etf['bid_ask_spread_pct'] < 0.02: score += 2
elif etf['bid_ask_spread_pct'] < 0.10: score += 1
# Tracking error vs index
if etf.get('tracking_error', 1) < 0.10: score += 2
elif etf.get('tracking_error', 1) < 0.30: score += 1
scored.append({**etf, 'score': score})
return sorted(scored, key=lambda x: x['score'], reverse=True)
def core_etf_universe():
"""Reference ETF universe for portfolio construction."""
return {
'US_Total_Market': ['VTI', 'ITOT', 'SCHB'],
'US_Large_Cap': ['VOO', 'IVV', 'SPY'],
'US_Small_Cap': ['VB', 'IJR', 'SCHA'],
'US_Small_Cap_Value': ['VBR', 'IJS', 'VIOV'],
'International_Dev': ['VXUS', 'IXUS', 'VEA'],
'Emerging_Markets': ['VWO', 'IEMG', 'EEM'],
'US_Total_Bond': ['BND', 'AGG', 'SCHZ'],
'US_Short_Bond': ['BSV', 'SHY', 'SCHO'],
'US_Long_Bond': ['BLV', 'TLT', 'VGLT'],
'TIPS_Inflation': ['VTIP', 'SCHP', 'TIP'],
'International_Bond': ['BNDX', 'IAGG'],
'Gold': ['GLD', 'IAU', 'GLDM'],
'Real_Estate_REIT': ['VNQ', 'SCHH', 'IYR'],
'Commodities': ['DJP', 'PDBC', 'GSG'],
'Factor_Value': ['VTV', 'VLUE', 'IVE'],
'Factor_Momentum': ['MTUM', 'QMOM'],
'Factor_Quality': ['QUAL', 'DGRW'],
'Factor_Low_Vol': ['USMV', 'SPLV'],
}
```
---
## Retirement Planning
```python
def safe_withdrawal_analysis(portfolio_value, annual_withdrawal,
stock_pct=0.60, years=30):
"""
Monte Carlo simulation for retirement withdrawal sustainability.
Based on Trinity Study and modern research.
"""
withdrawal_rate = annual_withdrawal / portfolio_value
# Historical return assumptions
stock_return = 0.10 # nominal
bond_return = 0.04
stock_vol = 0.16
bond_vol = 0.07
inflation = 0.03
port_return = stock_pct * stock_return + (1-stock_pct) * bond_return
port_vol = stock_pct * stock_vol + (1-stock_pct) * bond_vol
real_return = port_return - inflation
np.random.seed(42)
simulations = 10000
successes = 0
for _ in range(simulations):
balance = portfolio_value
annual_w = annual_withdrawal
for year in range(years):
ret = np.random.normal(real_return, port_vol)
balance = balance * (1 + ret) - annual_w
annual_w *= (1 + inflation) # inflation-adjust withdrawal
if balance <= 0:
break
else:
successes += 1
success_rate = successes / simulations
return {
'withdrawal_rate': round(withdrawal_rate * 100, 2),
'annual_withdrawal': annual_withdrawal,
'success_rate': round(success_rate * 100, 1),
'sustainability': 'Safe' if success_rate > 0.95 else
'Moderate' if success_rate > 0.85 else
'Risky',
'recommendation': '4% rule is generally safe for 30-year horizon'
if withdrawal_rate <= 0.04 else
'Consider reducing withdrawal rate'
}
def sequence_of_returns_risk(portfolio_value, annual_withdrawal,
bad_start_returns=[-0.30, -0.20, -0.10]):
"""
Illustrate sequence of returns risk in early retirement.
Bad returns early are far more damaging than bad returns late.
"""
results = {}
for scenario, early_returns in [
('Bad early returns', bad_start_returns),
('Good early returns', [-r for r in bad_start_returns])
]:
balance = portfolio_value
balances = [balance]
for year in range(20):
if year < len(early_returns):
ret = early_returns[year]
else:
ret = 0.07 # normal returns after
balance = balance * (1 + ret) - annual_withdrawal
balance = max(0, balance)
balances.append(round(balance, 0))
results[scenario] = {
'final_balance': balances[-1],
'depleted': balances[-1] == 0
}
return results
def retirement_number(annual_expenses, withdrawal_rate=0.04,
inflation_rate=0.03, years_to_retirement=20,
current_savings=0, annual_contribution=0):
"""Calculate the retirement number and savings needed."""
target_portfolio = annual_expenses / withdrawal_rate
# Future value of current savings
fv_savings = current_savings * (1.07 ** years_to_retirement)
# Future value of annual contributions
fv_contributions = annual_contribution * (
((1.07 ** years_to_retirement) - 1) / 0.07
)
projected_portfolio = fv_savings + fv_contributions
shortfall = target_portfolio - projected_portfolio
# Additional annual savings needed
if shortfall > 0:
additional_needed = shortfall * 0.07 / ((1.07**years_to_retirement) - 1)
else:
additional_needed = 0
return {
'retirement_number': round(target_portfolio, 0),
'projected_portfolio': round(projected_portfolio, 0),
'shortfall': round(max(0, shortfall), 0),
'additional_annual': round(additional_needed, 0),
'on_track': projected_portfolio >= target_portfolio
}
```
---
## Performance Attribution
```python
def brinson_attribution(portfolio_weights, benchmark_weights,
portfolio_returns, benchmark_returns,
sector_benchmark_returns):
"""
Brinson-Hood-Beebower performance attribution.
Decomposes excess return into allocation and selection effects.
"""
results = []
total_allocation = 0
total_selection = 0
total_interaction = 0
for sector in portfolio_weights.keys():
pw = portfolio_weights[sector]
bw = benchmark_weights[sector]
pr = portfolio_returns[sector]
br = benchmark_returns[sector]
sbr = sector_benchmark_returns[sector]
allocation = (pw - bw) * (sbr - sum(
benchmark_weights[s] * benchmark_returns[s]
for s in benchmark_weights
))
selection = bw * (pr - br)
interaction = (pw - bw) * (pr - br)
total_allocation += allocation
total_selection += selection
total_interaction += interaction
results.append({
'sector': sector,
'allocation': round(allocation * 100, 3),
'selection': round(selection * 100, 3),
'interaction': round(interaction * 100, 3),
'total': round((allocation + selection + interaction) * 100, 3)
})
return {
'sectors': results,
'total_allocation': round(total_allocation * 100, 3),
'total_selection': round(total_selection * 100, 3),
'total_interaction': round(total_interaction * 100, 3),
'total_excess_return':round((total_allocation + total_selection + total_interaction) * 100, 3)
}
```
---
## Tax Efficiency
Asset Location Strategy:
Tax-Advantaged Accounts (IRA, 401k):
- Bonds and bond funds (interest taxed as ordinary income)
- REITs (high dividend, taxed as ordinary income)
- High-turnover active funds
- International funds with foreign tax credit exception
Taxable Accounts:
- Total market index funds (low turnover, qualified dividends)
- Municipal bonds (tax-exempt interest)
- Growth stocks held long term
- Tax-managed funds
Tax-Loss Harvesting Rules:
- Sell position at a loss to realize capital loss
- Use loss to offset capital gains
- Reinvest in similar (not identical) fund within 30 days
- Watch wash-sale rule: no repurchase of same security within 30 days
- VTI harvested to ITOT, or vice versa (similar but not identical)
Long-Term vs Short-Term Capital Gains:
Hold > 1 year for long-term rates (0%, 15%, 20%)
Hold < 1 year = ordinary income rates (up to 37%)
Difference can be 15-20% in tax savings
---
## Common Pitfalls
| Pitfall | Problem | Fix |
|---|---|---|
| Home country bias | Under-diversified geographically | 30-40% international allocation |
| Performance chasing | Buy last year's winners | Rebalance back to targets |
| Neglecting rebalancing | Drift creates unintended risk | Annual or threshold rebalancing |
| High expense ratios | Fees compound against you | Use index funds < 0.10% ER |
| Tax inefficiency | Wrong assets in wrong accounts | Optimize asset location |
| Overdiversification | Too many funds with overlap | 3-5 core funds cover everything |
| Emotional selling | Sell in crash, miss recovery | Automate contributions, ignore noise |
---
## Best Practices
- **Start with asset allocation** — it drives 90% of long-term returns
- **Keep costs low** — every 0.10% in fees costs ~2.5% over 25 years
- **Automate contributions** — remove emotion from investing
- **Rebalance systematically** — annually or at 5% drift threshold
- **Tax location matters** — put bonds in tax-advantaged accounts
- **Stay the course** — time in market beats timing the market
- **Review annually** — goals change, allocation should evolve
---
## Related Skills
- **finance-trading-expert**: Active trading alongside portfolio
- **risk-management-expert**: Drawdown and risk controls
- **fundamental-analysis-expert**: Individual stock selection
- **quantitative-finance-expert**: Factor tilts and optimization
- **macro-economics-expert**: Top-down allocation decisions
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!