feat: strategy builder

This commit is contained in:
OpenSquared
2026-07-21 10:18:15 +02:00
parent 52890f4d1d
commit 6c22b3f552
11 changed files with 129 additions and 16 deletions

View File

@@ -0,0 +1,26 @@
/**
* Shared price/rate formatter. Raw quotes (spot, strike, bid/ask) always show a
* meaningful number of decimals — 4 for FX-scale instruments (<10), 2 above that
* (equities/indices), matching standard quoting convention for each magnitude.
* NOT for post-nominal dollar amounts (P&L, entry cost) — those stay at 2 decimals
* via each page's own fmtMoney.
*/
export function fmtPrice(v: number | null | undefined, decimals?: number): string {
if (v == null || Number.isNaN(v)) return '—'
const d = decimals ?? (Math.abs(v) < 10 ? 4 : 2)
return v.toFixed(d)
}
/**
* Formats a backend UTC timestamp as a compact local "as of" label, e.g. "18/07 14:32".
* Backend timestamps come in two shapes, both naive UTC: Python's `datetime.isoformat()`
* ("2026-07-18T14:32:01.123") and sqlite's `datetime('now')` ("2026-07-18 14:32:01").
*/
export function fmtAsOf(raw: string | null | undefined): string | null {
if (!raw) return null
let iso = raw.includes('T') ? raw : raw.replace(' ', 'T')
if (!/[zZ]|[+-]\d{2}:?\d{2}$/.test(iso)) iso += 'Z'
const d = new Date(iso)
if (Number.isNaN(d.getTime())) return null
return d.toLocaleString('fr-FR', { day: '2-digit', month: '2-digit', hour: '2-digit', minute: '2-digit' })
}