Big refactoring
This commit is contained in:
@@ -0,0 +1,42 @@
|
||||
import type { FetchDataResult, IngestionSourceResult } from '../api/ingestion';
|
||||
|
||||
export type IngestionToastType = 'success' | 'error' | 'info';
|
||||
|
||||
export interface IngestionStatusSummary {
|
||||
toastType: IngestionToastType;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export function summarizeIngestionResult(
|
||||
result: FetchDataResult | null | undefined,
|
||||
fallbackLabel: string,
|
||||
): IngestionStatusSummary {
|
||||
const sources = result?.sources;
|
||||
if (!sources) {
|
||||
return {
|
||||
toastType: 'success',
|
||||
message: `Data fetched for ${fallbackLabel}`,
|
||||
};
|
||||
}
|
||||
|
||||
const entries = Object.entries(sources) as [string, IngestionSourceResult][];
|
||||
const parts = entries.map(([name, info]) => {
|
||||
const label = name.charAt(0).toUpperCase() + name.slice(1);
|
||||
if (info.status === 'ok') {
|
||||
return `${label} ✓`;
|
||||
}
|
||||
if (info.status === 'skipped') {
|
||||
return `${label}: skipped${info.message ? ` (${info.message})` : ''}`;
|
||||
}
|
||||
return `${label} ✗${info.message ? `: ${info.message}` : ''}`;
|
||||
});
|
||||
|
||||
const hasError = entries.some(([, source]) => source.status === 'error');
|
||||
const hasSkip = entries.some(([, source]) => source.status === 'skipped');
|
||||
const toastType: IngestionToastType = hasError ? 'error' : hasSkip ? 'info' : 'success';
|
||||
|
||||
return {
|
||||
toastType,
|
||||
message: parts.join(' · '),
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
import type { TradeSetup } from './types';
|
||||
|
||||
export type RecommendationAction = NonNullable<TradeSetup['recommended_action']>;
|
||||
|
||||
export const RECOMMENDATION_ACTION_LABELS: Record<RecommendationAction, string> = {
|
||||
LONG_HIGH: 'LONG (High Confidence)',
|
||||
LONG_MODERATE: 'LONG (Moderate Confidence)',
|
||||
SHORT_HIGH: 'SHORT (High Confidence)',
|
||||
SHORT_MODERATE: 'SHORT (Moderate Confidence)',
|
||||
NEUTRAL: 'NEUTRAL (Conflicting Signals)',
|
||||
};
|
||||
|
||||
export const RECOMMENDATION_ACTION_GLOSSARY: Array<{ action: RecommendationAction; description: string }> = [
|
||||
{
|
||||
action: 'LONG_HIGH',
|
||||
description: 'Ticker bias favors LONG strongly. LONG confidence is above the high threshold and clearly above SHORT.',
|
||||
},
|
||||
{
|
||||
action: 'LONG_MODERATE',
|
||||
description: 'Ticker bias favors LONG, but with moderate conviction.',
|
||||
},
|
||||
{
|
||||
action: 'SHORT_HIGH',
|
||||
description: 'Ticker bias favors SHORT strongly. SHORT confidence is above the high threshold and clearly above LONG.',
|
||||
},
|
||||
{
|
||||
action: 'SHORT_MODERATE',
|
||||
description: 'Ticker bias favors SHORT, but with moderate conviction.',
|
||||
},
|
||||
{
|
||||
action: 'NEUTRAL',
|
||||
description: 'No strong directional edge. Signals are mixed or confidence gap is too small.',
|
||||
},
|
||||
];
|
||||
|
||||
export function recommendationActionLabel(action: TradeSetup['recommended_action']): string {
|
||||
if (!action) return RECOMMENDATION_ACTION_LABELS.NEUTRAL;
|
||||
return RECOMMENDATION_ACTION_LABELS[action] ?? RECOMMENDATION_ACTION_LABELS.NEUTRAL;
|
||||
}
|
||||
|
||||
export function recommendationActionDirection(action: TradeSetup['recommended_action']): 'long' | 'short' | 'neutral' {
|
||||
if (!action || action === 'NEUTRAL') return 'neutral';
|
||||
if (action.startsWith('LONG')) return 'long';
|
||||
if (action.startsWith('SHORT')) return 'short';
|
||||
return 'neutral';
|
||||
}
|
||||
@@ -121,6 +121,32 @@ export interface TradeSetup {
|
||||
rr_ratio: number;
|
||||
composite_score: number;
|
||||
detected_at: string;
|
||||
confidence_score: number | null;
|
||||
targets: TradeTarget[];
|
||||
conflict_flags: string[];
|
||||
recommended_action: 'LONG_HIGH' | 'LONG_MODERATE' | 'SHORT_HIGH' | 'SHORT_MODERATE' | 'NEUTRAL' | null;
|
||||
reasoning: string | null;
|
||||
risk_level: 'Low' | 'Medium' | 'High' | null;
|
||||
actual_outcome: string | null;
|
||||
recommendation_summary?: RecommendationSummary;
|
||||
}
|
||||
|
||||
export interface TradeTarget {
|
||||
price: number;
|
||||
distance_from_entry: number;
|
||||
distance_atr_multiple: number;
|
||||
rr_ratio: number;
|
||||
probability: number;
|
||||
classification: 'Conservative' | 'Moderate' | 'Aggressive';
|
||||
sr_level_id: number;
|
||||
sr_strength: number;
|
||||
}
|
||||
|
||||
export interface RecommendationSummary {
|
||||
action: string;
|
||||
reasoning: string | null;
|
||||
risk_level: 'Low' | 'Medium' | 'High' | null;
|
||||
composite_score: number;
|
||||
}
|
||||
|
||||
// S/R Levels
|
||||
@@ -214,3 +240,51 @@ export interface SystemSetting {
|
||||
value: string;
|
||||
updated_at: string | null;
|
||||
}
|
||||
|
||||
export interface RecommendationConfig {
|
||||
high_confidence_threshold: number;
|
||||
moderate_confidence_threshold: number;
|
||||
confidence_diff_threshold: number;
|
||||
signal_alignment_weight: number;
|
||||
sr_strength_weight: number;
|
||||
distance_penalty_factor: number;
|
||||
momentum_technical_divergence_threshold: number;
|
||||
fundamental_technical_divergence_threshold: number;
|
||||
}
|
||||
|
||||
export type TickerUniverse = 'sp500' | 'nasdaq100' | 'nasdaq_all';
|
||||
|
||||
export interface TickerUniverseSetting {
|
||||
universe: TickerUniverse;
|
||||
}
|
||||
|
||||
export interface TickerUniverseBootstrapResult {
|
||||
universe: TickerUniverse;
|
||||
total_universe_symbols: number;
|
||||
added: number;
|
||||
already_tracked: number;
|
||||
deleted: number;
|
||||
}
|
||||
|
||||
export interface PipelineReadiness {
|
||||
symbol: string;
|
||||
ohlcv_bars: number;
|
||||
ohlcv_last_date: string | null;
|
||||
dimensions: {
|
||||
technical: number | null;
|
||||
sr_quality: number | null;
|
||||
sentiment: number | null;
|
||||
fundamental: number | null;
|
||||
momentum: number | null;
|
||||
};
|
||||
sentiment_count: number;
|
||||
sentiment_last_at: string | null;
|
||||
has_fundamentals: boolean;
|
||||
fundamentals_fetched_at: string | null;
|
||||
sr_level_count: number;
|
||||
has_composite: boolean;
|
||||
composite_stale: boolean | null;
|
||||
trade_setup_count: number;
|
||||
missing_reasons: string[];
|
||||
ready_for_scanner: boolean;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user