Imported from anthony-liu-unsw/fundview-partb (
AGENTS.md). Install upstream withnpx skills add anthony-liu-unsw/fundview-partb. Copyright stays with the author.
AGENTS.md — Project instructions (z5364313_projectB)
AI assistant
- Uses opencode (big-pickle model)
Project: FundView — Part B
Funds, sentiment & app (Stations 3-4) for FINS3645 FinTech course.
Reuse Part A foundation from fins2026/z5364313_projectA/ (ETL pipeline, cleaned data, headline panel).
Part B code in this folder (fins2026/z5364313_projectB/).
Solution overview
A. Funds (3 families × 4 methods = 12 funds)
| Family | Assets | Methods |
|---|---|---|
| Equity-only | 50 US stocks | Max-Sharpe, Min-Variance, Risk-Parity, Equal-Weight |
| Crypto-only | 10 crypto pairs (-USD) | Max-Sharpe, Min-Variance, Risk-Parity, Equal-Weight |
| Combined | 50 stocks + 10 crypto | Max-Sharpe, Min-Variance, Risk-Parity, Equal-Weight |
B. Backtest design
- Walk-forward, out-of-sample (no look-ahead)
- Estimation window: 252 trading days
- Rebalance: every 63 trading days (~quarterly)
- First OOS date: day 253
- Cov matrix + expected returns from trailing window only
- Risk-free rate: 0 for Sharpe ratio
- Zero transaction costs (state in report)
- Annualise with sqrt(252) for equities, sqrt(365) for crypto
- Fact sheet per fund: growth of $1, annualised return, vol, Sharpe, max drawdown, current weights
C. Sentiment index & fusion
- VADER compound score on headlines (baseline)
- Extended VADER finance lexicon (Innovation 1 — see below)
- Sector index: equal-weight ticker-day mean compound within each sector
- No-headline days: treat as neutral (0) — retail investor hears no news, takes no action
- Lag signal by 1 trading day (Monday headlines → usable for Tuesday's trade)
- Fusion: tilt Equity Max-Sharpe fund — overweight top-3 sentiment sectors by 5%, fund from bottom-3. Compare before/after.
- Fusion result is honestly negative (Sharpe 0.566 → 0.546, growth 1.348 → 1.334): report the null rather than tuning the tilt to win.
D. Innovation 1 — Extended VADER finance lexicon
- Add ~50 finance terms with agent-assigned valences (-4 to +4) to VADER's dictionary
- Terms: downgrade, outperform, beat, miss, bullish, bearish, upgrade, rally, slump, volatile, etc.
- Patch SentimentIntensityAnalyzer to use merged lexicon
- Score all headlines with both baseline and extended VADER
- Evidence: side-by-side sector index chart, % moved from neutral, % sign flips
E. Innovation 2 — Sentiment-quintile event study with historical timeline
Core quintile study:
- Rank all ticker-days by extended VADER score into 5 quintiles each day
- Compute forward 1d/3d/5d mean return per quintile + % negative
- App callout: "Bottom 20% sentiment stocks historically averaged -0.8% over 3 days; 65% had negative returns"
Historical timeline with event annotations (new enhancement):
- Scatter/bar chart of Q1 (most negative sentiment) stock-day forward returns over time (Jan 2020 – Dec 2023)
- Overlay major market events as vertical annotations: COVID crash (Mar 2020), rate-hike selloff (Sep 2022), SVB collapse (Mar 2023), etc.
- Shows that negative forward returns cluster during stress periods — the 65% negative rate is not uniform across time
- Interactive: user hovers over a cluster to see "March 2020 — COVID-19 declared pandemic"
- App feature: user inspects which periods drove the aggregate statistic and decides if current conditions resemble them
period_summarycompares stress windows (COVID early, COVID crash, rate-hike, SVB) vs the rest of the sample: COVID early fwd-3d −5.34% / 73% negative vs +0.28% / 47% elsewhere. Aggregate Q1 fwd-3d is +0.06% (null) — the effect lives in stress periods.
Report exhibits:
- Bar chart of forward 3d returns by quintile with % negative overlay
- Timeline chart: Q1 stock-day returns with annotated market events
- Cumulative spread of hypothetical long-Q5/short-Q1 strategy
F. Streamlit app
- Pages: Dashboard (fund comparison), Fund Detail (fact sheet), Sentiment Analytics (sector index + quintile study), Allocation Tool
- Allocation Tool includes a management-fee slider (bps p.a.) applied to the combined return before growth/drawdown/Sharpe (net-of-fee view)
- Reads precomputed CSVs from
results/data/— NO backtests or VADER at runtime - Custom colour scheme, coherent design
- Deploy from public GitHub repo at hand-in
Required output filenames (exact names)
results/data/fund_returns.csvresults/data/fund_weights.csvresults/data/sector_sentiment_index.csvresults/tables/performance_metrics.csv
Key rules enforced
- Compute returns within each asset panel BEFORE merging (never merge price levels then diff)
- Crypto capped at 2023-12-31 (exclude 10 stray 2024-01-01 rows)
- Dedup news on ticker + date + title (not ticker-date alone)
- Keep genuine outlier returns — flag |z|>4 but do not delete
- Headlines mapped using merge_asof(direction="forward") to next trading day
- Raw headline text kept intact (VADER needs stopwords)
- News dates are UTC tz-aware, price dates are tz-naive — normalise before merge
- Annualise: sqrt(252) for equities, sqrt(365) for crypto
- App reads only precomputed CSVs — never runs backtests or VADER at deployment
- LaTeX not used — Word-first (report/report.docx → report.pdf)
- Every figure/table self-contained (caption, labelled axes, units, sample period) and interpreted in text
- Report writing in student's own words — no verbatim AI prose
Folder structure
src/portfolios.py— backtest engine and portfolio optimisationsrc/sentiment.py— VADER scoring, extended lexicon, sector indexsrc/fusion.py— sentiment tilt fusionsrc/etl.py— reuse Part A ETL (copy or import from projectA)src/features.py— reuse Part A featuressrc/extend_vader.py— extended VADER lexicon (Innovation 1)src/quintile_event_study.py— quintile study (Innovation 2)scripts/run_part_b.py— entry point, runs full pipelinestreamlit_app.py— Streamlit app entrypointresults/figures/— all figuresresults/tables/— CSV tablesresults/data/— app-readable CSVsreport/— Word report sourceai/— prompt logs
Student direct AI
The student first asked the AI to follow the solution overview. After all that was completed, the student asked the AI to run the full verification chain again and again until no error was shown.
Student Feedback on AI
- The AI helped me understand VADER scoring in more detail and explained the steps it follows.
- The pipeline kept regenerating
scratch/cache/, which meant I had to delete it manually every time before zipping. I asked the AI agent to fix this by making the pipeline cache-free instead. Ironically, that change introduced a small new bug while it was finalising the code. - In cache-free mode, every pipeline run has to re-score the headlines from scratch, which takes an extra 1-2 minutes. That trade-off is worth it because the folder stays ready to zip straight after a run.