PERSONAL TOOL · IN PRODUCTION · 2026

Investment Assistant

A production dashboard for my multi-market portfolio — built for me, and for my agent.

USE
Personal · in production
STACK
Flask · SQLite · Alpine.js
HOSTING
Railway
DATA
Private · single user
Investment Assistant — poster
WHAT IT DOES

One screen for six markets.

My holdings are scattered across US stocks, A-share ETFs, Hong Kong, mainland funds, the ASX and physical gold — in four currencies. This is the one place they all add up.

01

Cross-market holdings + FX

Six market types, four currencies (CNY · AUD · USD · HKD), converted via direct, inverted or cross-via-CNY FX rates — one total that actually means something.

02

Ledger-driven day P&L

The transactions ledger is the single source of trade entry: buys update weighted-average cost, sells accrue realized P&L, and day P&L stays correct even when I trade the same day — measured against my fill, not yesterday's close.

03

P&L calendar

A cron job computes each day's P&L 15 minutes after the US close and paints it green or red on a calendar — the shape of a month at a glance, with win/loss day counts.

04

Buckets (资金池)

Per-currency deposit and withdrawal logs track how much principal actually lives in each market — so returns are measured against real money in, not guesses.

05

Multi-source quotes that degrade, not die

Tencent qt for A-shares and HK in one batched call, yfinance for US/ASX/FX, akshare for fund NAVs and Shanghai gold. Every source is wrapped: a dead feed marks its rows 'no price' — it never breaks the refresh.

06

An API my agent reads every morning

Every weekday at 09:20 Beijing time — ten minutes before the A-share open — a scheduled Claude agent reads four API endpoints and writes me a pre-market briefing. The dashboard was designed to be consumed by an agent as well as a person.

DEMO

Try it — synthetic data, real interactions.

The dashboard below mirrors the real app's interactions. Holdings, prices and P&L are all fabricated for this demo — but the currency switcher, ledger, calendar and live updates work like the original.

invest.aidenyang.me · demo

Investment Assistant demo

Prices updated just now · 1 AUD = 4.72 CNY

Total value
¥ 0
—
Today · CNY assets
+¥ 0
+0.00%
Today · AUD assets
A$ 0
0.00%
Holdings
Auto-refresh every 4s here · every 5 min in the real app
Name Qty Price Day Value
P&L calendar · this month
computed 15 min after US close

Transactions
Add a trade below
    THE ARCHITECTURE

    One container, two clocks, two consumers.

    Everything runs in one Railway container — Flask, the scheduler, and SQLite on a persistent volume. Two things read it: me on my phone, and a scheduled Claude agent every weekday morning. Tap a node to see why each choice was made.

    RAILWAY CONTAINER · /data VOLUME via Cloudflare DNS ME PHONE · BROWSER Tencent qt · yfinance · akshare QUOTES · READ-ONLY PULL Flask GUNICORN · 8 BLUEPRINTS /api/* · one SPA view portfolio.db SQLITE · WAL APScheduler × 2 IN-PROCESS CRON Scheduled Claude agent COWORK + CHROME PLUGIN · GET /api/* RAILWAY BOUNDARY EXTERNAL PULL
    TIP

    Tap a node

    Click on any block in the diagram to see what it does and why I picked it.

    TRADE-OFFS

    Honest edges.

    01

    Reads are open, writes are gated

    Every mutating route requires a bearer token; GETs stay public so the morning agent can read without credentials. A deliberate trade for a single-user tool — the next step would be a signed agent identity.

    02

    I deleted my own equity curve

    An earlier version had a snapshot subsystem and an equity-curve chart. When I simplified the app, the chart ended up with zero callers — so I retired the whole subsystem instead of keeping dead weight. The calendar answers the real question: what kind of month was it.

    03

    What I'd do next

    Runtime failover for HK quotes (Tencent → Yahoo is supported but not wired), and surfacing the two-clock model in the UI — the ET trading day vs Sydney display logic is the app's subtlest code and deserves to be visible.

    ← Back to all works