Factor exposures with Newey–West inference and an implied-vs-direct reconciliation
Regress ETF and household excess returns on FF5 + momentum with Newey–West standard errors, and reconcile weight-implied versus directly-estimated household exposures.
instruction.md
What the agent sees (CONVENTIONS.md is appended automatically)
Factor exposures with HAC inference
Using /app/data/factors.csv (daily decimals: mkt_rf, smb, hml, rmw, cma, mom, rf), regress daily excess returns of each held ETF on the six factors with an intercept over the trailing 5 years (1260 observations, or the ETF's available subset if shorter). Report in /app/output/factors.json: betas, alpha annualised (x252), R-squared, and t-statistics using Newey–West HAC covariance with Bartlett kernel and lag 5, no small-sample correction.
Also regress the household (current weights, daily rebalanced) over the common window where every held ETF has data, and report household_implied_betas = sum of w_i x beta_i where each beta_i is re-estimated on that same common window, plus max_abs_diff between implied and direct household betas. State in why_differ whether the two should agree and why.
Verification
reward.json metrics · weights sum to 1.00
| Metric | Weight | Check |
|---|---|---|
| betas | 0.35 | abs 1e-6 per ETF. |
| alpha_r2 | 0.1 | abs 1e-6. |
| nw_tstats | 0.35 | abs 1e-4. |
| implied_consistency | 0.2 | max_abs_diff < 1e-8 and why_differ states they agree by linearity on a common window. |
Harbor scaffold
Generated from this record — task.toml, Dockerfile, verifier, oracle stub
schema_version = "1.4" [task] name = "portfolio-agent-evals/pf-analyze-factor-regression" version = "1.0.0" description = "Regress ETF and household excess returns on FF5 + momentum with Newey–West standard errors, and reconcile weight-implied versus directly-estimated household exposures." keywords = ["etf", "portfolio", "analyze", "portfolio-analytics", "econometrics", "hac-inference", "self-checking"] [metadata] author_name = "portfolio-agent-evals" difficulty = "hard" category = "quant-finance" tags = ["portfolio-analytics", "tier-3", "analyze", "multi-metric"] theme = "Portfolio Analytics & Exposure" tier = 3 reward_type = "multi-metric" [agent] timeout_sec = 1800.0 [verifier] timeout_sec = 180.0 [environment] # Offline by design: all data is synthetic and generated at build time. network_mode = "none" cpus = 2 memory_mb = 4096 storage_mb = 10240 build_timeout_sec = 900.0
Traps
Each must carry signal: a trap-blind solution must lose credit
- One ETF launched inside the window: full-window betas use its subset, but the reconciliation must use the common window.
- Factors are already excess; only ETF returns need rf subtracted.
- Newey–West lag-5 Bartlett weights 1 - l/(L+1); no (T/(T-k)) correction.
- Cash weight scales implied betas (cash has zero loadings).
Inputs
Fixtures mounted in the environment
- /app/data/factors.csv
- /app/data/prices/One held ETF launched inside the 5-year window.
- /app/portfolio/holdings.csv, /app/portfolio/accounts.csv
- /app/data/dividends.csv
Outputs
What the verifier reads from /app/output
- /app/output/factors.jsonJSONLoadings, alphas, HAC t-stats and reconciliation.
Anti-gaming
Loadings are seed-generated with known truth; the verifier recomputes from data, not from truth.
Oracle notes
solution/solve.sh must score 1.0 on five seeds
numpy lstsq plus explicit HAC sandwich; statsmodels cov_type HAC with use_correction=False matches.
Reviews (0)
Design review before a task is marked ready