first commit
Deploy / lint (push) Failing after 7s
Deploy / test (push) Has been skipped
Deploy / deploy (push) Has been skipped

This commit is contained in:
Dennis Thiessen
2026-02-20 17:31:01 +01:00
commit 61ab24490d
160 changed files with 17034 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
/**
* Format a number as a price string with 2 decimal places and thousands separators.
* e.g. 1234.5 → "1,234.50"
*/
export function formatPrice(n: number): string {
return n.toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
}
/**
* Format a number as a percentage string with 2 decimal places.
* e.g. 12.345 → "12.35%"
*/
export function formatPercent(n: number): string {
return `${n.toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
})}%`;
}
/**
* Format a large number with K/M/B suffix.
* Values >= 1_000_000_000 → "1.23B"
* Values >= 1_000_000 → "456.7M"
* Values >= 1_000 → "12.3K"
* Values < 1_000 → plain number, no suffix
*/
export function formatLargeNumber(n: number): string {
const abs = Math.abs(n);
const sign = n < 0 ? '-' : '';
if (abs >= 1_000_000_000) {
return `${sign}${(abs / 1_000_000_000).toFixed(2).replace(/\.?0+$/, '')}B`;
}
if (abs >= 1_000_000) {
return `${sign}${(abs / 1_000_000).toFixed(1).replace(/\.?0+$/, '')}M`;
}
if (abs >= 1_000) {
return `${sign}${(abs / 1_000).toFixed(1).replace(/\.?0+$/, '')}K`;
}
return n.toString();
}
/**
* Format an ISO date string as a short date.
* e.g. "2025-01-15T14:30:00Z" → "Jan 15, 2025"
*/
export function formatDate(d: string): string {
const date = new Date(d);
return date.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
});
}
/**
* Format an ISO date string as a date with time.
* e.g. "2025-01-15T14:30:00Z" → "Jan 15, 2025 2:30 PM"
*/
export function formatDateTime(d: string): string {
const date = new Date(d);
return `${date.toLocaleDateString('en-US', {
month: 'short',
day: 'numeric',
year: 'numeric',
})} ${date.toLocaleTimeString('en-US', {
hour: 'numeric',
minute: '2-digit',
hour12: true,
})}`;
}
+172
View File
@@ -0,0 +1,172 @@
// API envelope (before unwrapping)
export interface APIEnvelope<T = unknown> {
status: 'success' | 'error';
data: T | null;
error: string | null;
}
// Auth
export interface TokenResponse {
access_token: string;
token_type: string;
}
// Watchlist
export interface WatchlistEntry {
symbol: string;
entry_type: 'auto' | 'manual';
composite_score: number | null;
dimensions: DimensionScore[];
rr_ratio: number | null;
rr_direction: string | null;
sr_levels: SRLevelSummary[];
added_at: string;
}
export interface DimensionScore {
dimension: string;
score: number;
}
export interface SRLevelSummary {
price_level: number;
type: 'support' | 'resistance';
strength: number;
}
// OHLCV
export interface OHLCVBar {
id: number;
ticker_id: number;
date: string;
open: number;
high: number;
low: number;
close: number;
volume: number;
created_at: string;
}
// Scores
export interface ScoreResponse {
symbol: string;
composite_score: number | null;
composite_stale: boolean;
weights: Record<string, number>;
dimensions: DimensionScoreDetail[];
missing_dimensions: string[];
computed_at: string | null;
}
export interface DimensionScoreDetail {
dimension: string;
score: number;
is_stale: boolean;
computed_at: string | null;
}
export interface RankingEntry {
symbol: string;
composite_score: number;
dimensions: DimensionScoreDetail[];
}
export interface RankingsResponse {
rankings: RankingEntry[];
weights: Record<string, number>;
}
// Trade Setups
export interface TradeSetup {
id: number;
symbol: string;
direction: string;
entry_price: number;
stop_loss: number;
target: number;
rr_ratio: number;
composite_score: number;
detected_at: string;
}
// S/R Levels
export interface SRLevel {
id: number;
price_level: number;
type: 'support' | 'resistance';
strength: number;
detection_method: string;
created_at: string;
}
export interface SRLevelResponse {
symbol: string;
levels: SRLevel[];
count: number;
}
// Sentiment
export interface SentimentScore {
id: number;
classification: 'bullish' | 'bearish' | 'neutral';
confidence: number;
source: string;
timestamp: string;
}
export interface SentimentResponse {
symbol: string;
scores: SentimentScore[];
count: number;
dimension_score: number | null;
lookback_hours: number;
}
// Fundamentals
export interface FundamentalResponse {
symbol: string;
pe_ratio: number | null;
revenue_growth: number | null;
earnings_surprise: number | null;
market_cap: number | null;
fetched_at: string | null;
}
// Indicators
export interface IndicatorResult {
indicator_type: string;
values: Record<string, unknown>;
score: number;
bars_used: number;
}
export interface EMACrossResult {
short_ema: number;
long_ema: number;
short_period: number;
long_period: number;
signal: 'bullish' | 'bearish' | 'neutral';
}
// Tickers
export interface Ticker {
id: number;
symbol: string;
created_at: string;
}
// Admin
export interface AdminUser {
id: number;
username: string;
role: string;
has_access: boolean;
created_at: string | null;
updated_at: string | null;
}
export interface SystemSetting {
key: string;
value: string;
updated_at: string | null;
}