8 Commits

Author SHA1 Message Date
tiennm99 99cd8449ec feat(db,trading): phase 03 — MongoTradesStore + trading refactor + SqlStore shim
Replaces the originally-planned SQL-pattern dispatcher with a direct refactor:
trading/history.js + retention.js call MongoTradesStore methods explicitly
instead of routing strings through a regex dispatcher. Cleaner abstraction;
eliminates the "7th SQL statement silently breaks" risk flagged in code-review.

- src/db/mongo-trades-store.js: 6 explicit methods (insert, byUser,
  distinctUsers, oldRowsForUser, oldRows, deleteByIds). Lazy index init
  for (user_id, ts desc), (ts desc), and sparse (legacy_id).
- src/db/mongo-sql-store.js: thin SqlStore shim returning {changes:1,
  last_row_id:0} (number, NOT hex) to satisfy the existing
  tests/db/create-sql-store.test.js:48-52 contract. Exists purely for
  factory branching; trading code calls MongoTradesStore directly.
  Unsupported SQL throws loud.
- trading/history.js + retention.js + index.js: accept optional
  tradesStore in init args. Falls back to existing D1 sql path when
  tradesStore absent — keeps trading working on D1 until Phase 04
  wires dual-write.
- legacy_id: null on runtime inserts. Sparse index + field reserved
  for backfill (Phase 05) to preserve original D1 integer IDs for
  historical join-ability.

Pre-refactor grep gates (all PASS):
- exactly 6 SQL statements in src/modules/trading/
- zero arithmetic on .id (.id [+-*/<>])
- last_row_id consumed by zero callers in trading

Tests: 529 → 577 (+48). Lint clean.
2026-04-26 08:48:18 +07:00
tiennm99 7f47799733 fix(trading): swap dead TCBS endpoint for KBS data_day
The TCBS `apipubaws.tcbs.com.vn` host returns HTTP 404/500 for every
request, so every ticker resolved as "Unknown stock ticker" and /trade_buy
was unusable. Switch price + symbol resolution to the KBS public endpoint
that vnstock currently defaults to (`kbbuddywts.kbsec.com.vn/iis-server/
investment/stocks/{TICKER}/data_day`). KBS needs no auth, returns JSON,
and is Worker-compatible.

- `prices.fetchStockPrice` now queries KBS with a 14-day lookback window
  (covers weekends/holidays) and drops the TCBS-specific ×1000 scaling;
  KBS returns real VND.
- `symbols.resolveSymbol` delegates to `fetchStockPrice` for existence
  checks — empty `data_day` means unknown ticker.
- Update test fetch stubs to match the `kbsec` host and KBS response
  shape (`{ symbol, data_day: [{ c }] }`).
2026-04-21 14:39:05 +07:00
tiennm99 d040ce4161 feat(trading): add trade history and daily FIFO retention cron
- trading_trades table (migration 0001) persists every buy/sell via optional onTrade callback
- /history [n] command shows caller's last N trades (default 10, max 50), HTML-escaped
- daily cron at 0 17 * * * trims to 1000/user + 10000/global via FIFO delete
- persistence failure logs but does not fail the trade reply
2026-04-15 13:29:15 +07:00
tiennm99 a34c1cf85f refactor: move totalvnd into meta.invested for extensibility
Portfolio schema now uses meta object: { currency, assets, meta: { invested } }.
Migrates old totalvnd field automatically on load. The meta object provides
a clean place for future per-user metadata without polluting the top level.
2026-04-14 17:33:11 +07:00
tiennm99 0d4feb9ef8 refactor: dynamic symbol resolution, flat portfolio, VN stocks only
Replace hardcoded 9-symbol registry with dynamic TCBS-based resolution.
Any VN stock ticker is now resolved on first use and cached in KV
permanently. Portfolio flattened from 4 category maps to single assets
map with automatic migration of old format. Crypto, gold, and currency
exchange disabled with "coming soon" message.
2026-04-14 17:22:05 +07:00
tiennm99 86268341d1 feat: use real BIDV bid/ask rates for forex conversion
Replace hardcoded 0.5% spread with live buy/sell rates from BIDV bank
API. Buying USD uses bank's sell rate (higher), selling USD uses bank's
buy rate (lower). Reply shows both rates and actual spread percentage.
2026-04-14 16:53:07 +07:00
tiennm99 f3aaf16d6a feat: simplify topup to VND-only, add bid/ask spread to convert
Topup now only accepts VND — users must convert to get other currencies.
Convert uses a 0.5% bid/ask spread: buying USD costs more VND (ask),
selling USD back gives less VND (bid). Simulates real forex behavior.
2026-04-14 16:06:36 +07:00
tiennm99 c9270764f2 feat: add fake trading module with crypto, stocks, forex and gold
Paper trading system with 5 commands (trade_topup, trade_buy,
trade_sell, trade_convert, trade_stats). Supports VN stocks via TCBS,
crypto via CoinGecko, forex via ER-API, and gold via PAX Gold proxy.
Per-user portfolio stored in KV with 60s price caching. 54 new tests.
2026-04-14 15:16:53 +07:00