Eliminates XSS token theft by storing JWT in httpOnly Secure cookie
instead of localStorage. Backend sets cookie on login and clears on
logout. Token extraction uses cookie-first with Authorization header
fallback for backward compatibility with existing tests.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add "거래 추가" button to the transactions tab with a modal dialog for
manually entering buy/sell transactions (ticker, type, quantity, price, memo).
Refreshes portfolio and transaction list after successful submission.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Portfolio value chart now uses actual snapshot API data instead of
generated simulation. Shows empty state message when no snapshots exist.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add hover-visible edit (rename) and delete buttons to portfolio cards
on the list page, with modal dialogs for name editing and delete
confirmation. Uses existing PUT/DELETE API endpoints.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add class-based ErrorBoundary component that catches rendering errors
and shows a user-friendly fallback with retry/reload buttons. Wrap in
root layout to protect against full-page crashes.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace silent console.error-only handling with user-visible toast notifications
using sonner, while keeping console.error for debugging.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add 10 indexes across prices, etf_prices, financials, valuations,
holdings, transactions, signals, portfolio_snapshots, and etfs tables.
Fix N+1 query in list_backtests by eager-loading backtest results
with joinedload.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add dc_only parameter to all strategy endpoints. When true, filters
results to include only tickers present in the ETF table, supporting
DC pension investment constraints where only ETFs are allowed.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add min_trade_amount parameter (default 10,000 KRW) to rebalance/calculate
endpoint. Trades below this threshold are converted to hold actions to avoid
inefficient micro-trades during rebalancing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add a compare page at /strategy/compare that runs MultiFactor, Quality,
and ValueMomentum strategies simultaneously and displays results side-by-side
with common ticker highlighting and factor score comparison table.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add realized_pnl column to transactions table with alembic migration
- Calculate realized PnL on sell transactions: (sell_price - avg_price) * quantity
- Show total realized/unrealized PnL in portfolio detail summary cards
- Show per-transaction realized PnL in transaction history table
- Add position sizing API endpoint (GET /portfolios/{id}/position-size)
- Show position sizing guide in signal execution modal for buy signals
- 8 new E2E tests, all 88 tests passing
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Phase 1 (Critical):
- Add bulk rebalance apply API + UI with confirmation modal
- Add strategy results to portfolio targets flow (shared component)
Phase 2 (Important):
- Show current holdings in signal execute modal with auto-fill
- Add DC pension risk asset ratio warning (70% limit)
- Add KOSPI benchmark comparison to portfolio returns
- Track signal execution details (price, quantity, timestamp)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Expert team identified 12 gaps across 6 scenarios. Prioritized into
3 phases: Critical (rebalance apply, strategy-to-portfolio link),
Important (signal holdings, DC limits, benchmark, signal PnL),
and Nice-to-have (comparison UI, walk-forward, undo).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Define 6 core usage scenarios and expert team composition for
evaluating feature completeness of the quant portfolio management system.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Allow users to execute active KJB signals by selecting a portfolio,
entering quantity and price, then creating the corresponding transaction
and updating holdings. Signal status changes to 'executed' after completion.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Full system: signal generator, daily backtest engine, trading portfolio,
signal API, scheduler job, and frontend dashboard.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Validates trading day count, benchmark coverage, per-date ticker
density, and date gaps before running simulation. Logs warnings for
holdings with missing prices during execution.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Port make-quant-py's FnGuide scraping logic into galaxy-po's
BaseCollector pattern. Collects annual and quarterly financial
statements (revenue, net income, total assets, etc.) and maps
Korean account names to English keys for FactorCalculator.
Scheduled weekly on Monday 19:00 KST since data updates quarterly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The seed script was incorrectly using the latest snapshot's market price
as avg_price, resulting in inflated average costs. Now computes avg_price
from actual total invested amounts per ticker.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
For holdings with quantity > 0, the input now accepts the total
valuation amount and derives the current price by dividing by quantity.
Holdings with quantity 0 (target-only) still accept price directly.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
CronTrigger had no explicit timezone, defaulting to system timezone
(UTC in Docker containers), causing jobs to run at KST 03:00/03:30
instead of the intended 18:00/18:30.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add "데이터 탐색" menu item to sidebar with Search icon
- Add "수집 데이터 조회" link button on data management page
- Fix sidebar active state to correctly distinguish /admin/data
from /admin/data/explorer
- Add page title mapping for data explorer in header
- Fix .gitignore: add negation for frontend/src/app/admin/data/
so admin data pages are tracked without needing git add -f
- Fix dashboard loading state (return null → skeleton with layout)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Two issues caused DB reset on every deploy:
1. docker-compose.prod.yml used bind mount (./data/postgres) with
PostgreSQL 18's incompatible /var/lib/postgresql/data path.
2. The Gitea CI runner shares Docker socket with the host, but
./data/postgres resolves to a temp path inside the runner container.
Each deploy creates a fresh workspace, so the bind mount always
points to an empty directory on the host.
Fix: Use a named Docker volume (same as docker-compose.yml dev config).
Named volumes are managed by Docker daemon directly, survive container
recreation, and don't depend on working directory resolution.
Also fix deploy.yml: remove unnecessary mkdir for data dirs, write
backup to /tmp instead of relative path.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>