Private family income portfolio management system.
Thai retail investor focus Β· USD income assets Β· KAsset THB mutual fund Β· Multi-account Β· AI-assisted
A multi-page Streamlit application that tracks, analyses, and optimises a generational income portfolio across three brokerage accounts. It is not a general-purpose tool β it is built around the specific needs of a Thai investor holding USD income assets (BKLN, ARCC, PDI) and a Thai fixed-income mutual fund (K-FIXED-A), with a 30-year wealth-building mandate.
| ID | Account | Currency | Contents |
|---|---|---|---|
397543-7 |
K CYBER TRADE (Kasikorn Securities) | USD | BKLN 192sh Β· ARCC 133sh Β· PDI 105sh |
722379-7 |
K CYBER TRADE (Kasikorn Securities) | THB | Cash only β Thai domestic account |
005-8-95518-3 |
KAsset Wisdom (Finnomena) | THB | K-FIXED-A ΰΈΏ1,396,284.70 |
PortfolioOptimizer/
βββ app.py Entry point β 85 lines of pure routing
βββ core.py Shared runtime: accounts, YAML I/O, cache, sidebar
βββ requirements.txt
β
βββ pages/
β βββ p1_dashboard.py Dashboard: overview, prices, dividend calendar, WHT, transactions
β βββ p2_intelligence.py Intelligence Hub: macro, SEC EDGAR, FX timing
β βββ p3_analytics.py Analytics: risk, backtest, Monte Carlo, generational plan, charts
β βββ p4_sandbox.py Sandbox: What-If, 3D frontier (Plotly + Three.js), exit simulator
β βββ p5_accounts.py Account manager: consolidated view, settings, cash transfers
β βββ p6_research.py AI research agent (Groq streaming)
β βββ p7_family.py Family overview (shown when 2+ accounts)
β
βββ engine/
β βββ julia_engine.jl Julia worker: LW covariance, MC, gen plan, max-Sharpe, HRP
β βββ julia_bridge.py PythonβJulia bridge (juliacall, Python fallback)
β βββ charts.py Advanced charts via pandas_ta (SMA/EMA/BB/RSI/MACD)
β βββ exit_simulator.py Exit position impact: P&L, tax, income loss, 30yr generational
β βββ scenario_analyzer.py What-If multi-asset optimizer
β βββ wht_reconciliation.py WHT reconciliation with treaty band 12β22%
β βββ edgar_monitor.py SEC EDGAR: ARCC 8-K, XBRL NAV/NII, BDC screener
β βββ analytics.py Portfolio risk metrics
β βββ backtest.py Walk-forward backtest
β βββ black_litterman.py Black-Litterman model
β βββ dividend_calendar.py Upcoming dividend event builder
β βββ fx_timing.py USD/THB z-score signal
β βββ generational_planner.py 30-year generational plan
β βββ macro_monitor.py VIX, yield curve, oil, FX macro indicators
β βββ report_builder.py (Legacy β kept for reference, Excel export removed)
β
βββ utils/
β βββ i18n.py EN/TH language switching β t() helper
β βββ finnomena.py KAsset/Finnomena NAV fetcher + YAML fallback
β βββ research_agent.py Groq llama-3.3-70b-versatile streaming agent
β βββ llm_summarizer.py Post-analysis AI summaries with session-state cache
β βββ github_commit.py GitHub PAT auto-commit after data mutations
β
βββ config/
βββ accounts.yaml Account registry (IDs, colours, YAML filenames)
βββ portfolio_397543-7.yaml USD income account (BKLN/ARCC/PDI)
βββ portfolio_722379-7.yaml THB cash account
βββ portfolio_005895518-3.yaml KAsset Wisdom mutual fund account
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txtCopy .streamlit/secrets.toml.template β .streamlit/secrets.toml and fill in:
[github]
pat = "ghp_..." # GitHub Personal Access Token (for auto-commit)
repo_url = "https://github.com/Blackl1stV35/PortfolioOptimizer"
[groq]
api_key = "gsk_..." # From console.groq.com β free tier
[account_pins]
# Not required β PIN gate removed. Accounts switch by button click.Never commit
secrets.toml. It is already in.gitignore.
streamlit run app.pyJulia provides sub-3-second Monte Carlo (5,000 Γ 360 months), Ledoit-Wolf covariance, Max-Sharpe, Min-CVaR, and HRP optimisation. Without Julia, Python/NumPy fallbacks are used automatically.
# Install Julia (https://julialang.org/downloads/)
# Then:
pip install juliacall
# On first run, Julia initialises once via @st.cache_resourceJulia is not required for the app to function.
- Overview β live market values in USD and THB, unrealised P&L per holding (live prices via yfinance)
- Price & History β 6-timeframe interactive price chart (1M β MAX) with monthly return bars
- Dividend Calendar β smart checklist for upcoming dividends with β confirm flow; auto-updates portfolio YAML; ICS export for Google/Apple/Outlook Calendar
- Tax & Reconciliation β WHT implied rate back-calculation; treaty band 12β22% (W-8BEN validated); auto-detects 15% treaty vs 30% default
- Transactions β editable
st.data_editorledger + step-by-step add-transaction wizard with live price autofill, impact preview, and optional GitHub push
- Macro Pulse β Thai policy rate, US Fed rate, VIX, oil, yield curve, recession probability, macro regime (Aggressive / Neutral / Defensive) with cash deployment recommendation
- SEC EDGAR β ARCC 8-K dividend declarations, XBRL NAV/NII fundamentals, insider Form 4 trades, BDC candidate screener
- FX Timing β USD/THB 90-day z-score signal with deployment recommendation
- Risk & Optimisation β per-asset risk metrics (Sharpe, CVaR, Max Drawdown) via Julia; Max-Sharpe, Min-Variance, Min-CVaR weight tables; Groq AI summary
- Backtest β walk-forward backtest across multiple strategies; Groq AI summary
- Monte Carlo β 1,000β10,000 path simulation (Julia-accelerated); p10/p50/p90 fan chart; target income probability; Groq AI summary
- Generational Plan β 30-year, 5,000-path plan; milestone table (Year 5/10/15/20/25/30); median time-to-target; Groq AI summary
- Advanced Charts β pandas_ta technical indicators: SMA20/50, EMA20, Bollinger Bands, RSI(14), MACD(12,26,9); multi-asset overlay with benchmark comparison; 8 timeframes
- What-If Simulator β add up to 3 tickers simultaneously; Β±5% entry price sensitivity sub-scenarios; ΞSharpe / ΞCVaR / Ξincome KPIs; before/after weight table; 5-year MC fan chart; sandbox checkbox (never writes to YAML until explicitly confirmed)
- 3D Frontier β Plotly WebGL 3D scatter: X=volatility, Y=return, Z=monthly income; coloured by Sharpe ratio; 2,000 random portfolios
- Three.js Bubble Chart β interactive WebGL asset bubbles; drag to rotate, scroll to zoom, hover for details; size=weight, colour=yield
- Exit Simulator β full exit impact: capital gain/loss, Thai CGT exemption note, lost monthly income, 30-year compounded income loss, portfolio concentration after exit
- Consolidated NAV, income, and cash across all 3 accounts
- Income bar chart by account
- Per-account settings editor (FX rate, WHT rate, risk-free rate, income target)
- Cash transfer recorder (bookkeeping only β no broker API)
- Groq
llama-3.3-70b-versatilestreaming agent - Full portfolio context injected into system prompt (holdings, WHT, FX, strategy)
- Responds in English or Thai based on language setting
- 7 curated starter questions in both languages
The Finnomena API is Cloudflare-blocked from server environments. NAV is managed manually:
- Open Dashboard β KAsset Wisdom account β Overview
- Expand "Update NAV manually"
- Enter NAV per unit + total market value β Update NAV
- The app stores the entry in
portfolio_005895518-3.yaml β nav_history - A
β οΈ stale warning appears if data is more than 3 days old
Click the π ΰΈ ΰΈ²ΰΈ©ΰΈ²ΰΉΰΈΰΈ’ / English button at the bottom of the sidebar. All UI labels, navigation items, and metric names switch. AI Research responses also switch language based on this setting.
YAML files (primary) βββ core.load_cfg()
β
βββ render_sidebar() (once per re-run)
β
βββ pages/pN.render() (only active page re-runs)
β
βββ yfinance (prices, FX β cached 5 min)
βββ Julia (heavy compute β cached resource)
βββ Groq (summaries β session-state cache)
βββ Finnomena (NAV β YAML fallback)
β
save_cfg()
β
βββ YAML write
βββ Supabase dual-write (Phase 2 hook, optional)
βββ GitHub auto-commit (if PAT configured)
| Implied WHT | Verdict | Meaning |
|---|---|---|
| < 5% | no_data | KS data missing or zero |
| 12β22% | treaty_15 β | W-8BEN applied (18% band accounts for KS FX rounding) |
| 27β33% | default_30 |
Standard US withholding β file W-8BEN with KS |
| > 35% | overpaid β | Contact KS |
| Other | partial | Unusual β verify KS statement |
W-8BEN treaty rate (15%) validated on account 397543-7 as of 2026-04-14.
| Ticker | Ex-date | Pay-date | Eligible shares | Est. gross | Est. net (15% WHT) |
|---|---|---|---|---|---|
| PDI | 2026-04-13 | 2026-05-01 | 105 | $23.15 | $19.68 |
| BKLN | 2026-04-23 | 2026-04-27 | 192 | $19.20 | $16.32 |
| PDI | 2026-05-11 | 2026-06-01 | 105 | $23.15 | $19.68 |
| BKLN | 2026-05-28 | 2026-06-01 | 192 | $19.20 | $16.32 |
| ARCC | 2026-06-12 | 2026-06-30 | 133 | $63.84 | $54.26 |
| BKLN | 2026-06-25 | 2026-06-27 | 192 | $19.20 | $16.32 |
| PDI | 2026-06-12 | 2026-07-01 | 105 | $23.15 | $19.68 |
β οΈ ARCC Q1 2026 dividend missed β shares purchased 2026-03-25, ex-date was 2026-03-12.
Free, 1 app, ~1 GB RAM. Julia not available (Python fallback active). Suitable for current portfolio size.
Free, always-on, 16 GB RAM, Julia installable via Dockerfile. Zero cold starts.
FROM python:3.11-slim
RUN apt-get update && apt-get install -y curl
RUN curl -fsSL https://install.julialang.org | sh
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
RUN echo 'juliacall>=0.9.0' >> requirements.txt && pip install juliacall
CMD ["streamlit", "run", "app.py", "--server.port=7860"]Auto-commits are triggered after: dividend confirmation, trade logging, What-If apply, NAV update.
feat: multi-account + Groq LLM + Julia + 3D sandbox
fix: WHT treaty band 12-22%, snapshot key resolver, PyArrow KS THB
data: portfolio_397543-7 β WHT 15% validated, mkt value $8,201.80
data: KAsset Wisdom account 005-8-95518-3 β K-FIXED-A ΰΈΏ1,396,284.70
MIT