phase-8g: add sqllite.
This commit is contained in:
@@ -70,10 +70,15 @@ server/
|
||||
PortfolioAdvisor.ts ← cross-references holdings with screener signals → hold/sell/add advice
|
||||
index.ts ← barrel re-export (import services from here, not individual files)
|
||||
|
||||
repositories/ ← data persistence only (JSON file read/write)
|
||||
MarketCallRepository.ts ← persists market thesis entries to market-calls.json.
|
||||
CRUD: list/get/create/delete.
|
||||
PortfolioRepository.ts ← read/write portfolio.json. Methods: read, upsert, remove.
|
||||
repositories/ ← data persistence (SQLite via better-sqlite3)
|
||||
MarketCallRepository.ts ← market_calls table. CRUD: list/get/create/delete.
|
||||
Accepts injected Db instance.
|
||||
PortfolioRepository.ts ← holdings table. Methods: exists, read, upsert, remove.
|
||||
Accepts injected Db instance.
|
||||
|
||||
db/
|
||||
index.ts ← createDb(path?) → opens/creates market-screener.db, runs DDL,
|
||||
migrates legacy portfolio.json + market-calls.json on first boot.
|
||||
|
||||
clients/ ← external API connectors, one class per third-party system
|
||||
YahooFinanceClient.ts ← wraps yahoo-finance2 v3, retry + backoff. Methods: fetchSummary,
|
||||
@@ -161,8 +166,9 @@ ui/ ← SvelteKit dashboard (lives inside this repo, not a
|
||||
portfolio/ ← portfolio advice view
|
||||
safe-buys/ ← filtered strong-buy view
|
||||
|
||||
market-calls.json ← persisted market thesis calls (written by MarketCallRepository)
|
||||
portfolio.json ← user's holdings: ticker, shares, costBasis, source, type
|
||||
market-screener.db ← SQLite database (created on first boot). Contains holdings + market_calls tables.
|
||||
Legacy portfolio.json / market-calls.json are auto-migrated on first boot
|
||||
and renamed to *.json.migrated.
|
||||
.env ← SIMPLEFIN_ACCESS_URL or SIMPLEFIN_SETUP_TOKEN, ANTHROPIC_API_KEY, API_KEY (optional — enables Bearer auth on all routes)
|
||||
```
|
||||
|
||||
@@ -434,19 +440,13 @@ new ScreenerEngine({ logger: noopLogger })
|
||||
|
||||
---
|
||||
|
||||
## portfolio.json Format
|
||||
## Holdings Format
|
||||
|
||||
```json
|
||||
{
|
||||
"holdings": [
|
||||
{ "ticker": "AAPL", "shares": 10, "costBasis": 150.00, "source": "Robinhood", "type": "stock" },
|
||||
{ "ticker": "VOO", "shares": 8, "costBasis": 380.00, "source": "Vanguard", "type": "etf" },
|
||||
{ "ticker": "BTC-USD", "shares": 0.25, "costBasis": 45000, "source": "Coinbase", "type": "crypto" }
|
||||
]
|
||||
}
|
||||
```
|
||||
Holdings are stored in the `holdings` table in `market-screener.db`. To seed initial data, add holdings via the Portfolio UI or by inserting into the database directly.
|
||||
|
||||
`type` values: `stock`, `etf`, `crypto`. Crypto is priced via Yahoo (BTC-USD style) but not fundamentally scored.
|
||||
`type` values: `stock`, `etf`, `bond`, `crypto`. Crypto is priced via Yahoo (BTC-USD style) but not fundamentally scored.
|
||||
|
||||
If you have an existing `portfolio.json`, it will be auto-migrated to SQLite on first boot and renamed to `portfolio.json.migrated`.
|
||||
|
||||
---
|
||||
|
||||
@@ -474,7 +474,7 @@ Test output uses the built-in `spec` reporter.
|
||||
**Key unit:** `ytm` in `Bond.metrics` is stored as a percentage (e.g. `6.5` = 6.5%). `BondScorer._sanitize` divides by 100 before spread calculation.
|
||||
|
||||
**Coverage gaps (known):**
|
||||
- `MarketCallRepository.ts` — no tests; CRUD against `market-calls.json` is untested
|
||||
- `MarketCallRepository.ts` — covered by `tests/MarketCallRepository.test.ts` using in-memory SQLite
|
||||
- `LLMAnalyst.test.js` — tests a local copy of the fence-stripping regex rather than importing from source; will silently drift if the regex changes
|
||||
- API controllers (`server/controllers/`) — no integration tests; covered implicitly by manual testing only
|
||||
- Expert scoring features (analyst, DCF, 52W) — not yet covered in `StockScorer.test.js`
|
||||
|
||||
Reference in New Issue
Block a user