fed-policy-cli
Version:
Macro trading intelligence from Fed policy analysis. Transform economic data into actionable trading insights by analyzing historical Fed policy analogues.
217 lines (180 loc) • 8.01 kB
text/typescript
// /src/utils/displayUtils.ts
import { Text } from 'ink';
import React from 'react';
export const FED_ANALYZER_ASCII = `
███████╗███████╗██████╗ ██████╗ ██████╗ ██╗ ██╗ ██████╗██╗ ██╗
██╔════╝██╔════╝██╔══██╗ ██╔══██╗██╔═══██╗██║ ██║██╔════╝╚██╗ ██╔╝
█████╗ █████╗ ██║ ██║ ██████╔╝██║ ██║██║ ██║██║ ╚████╔╝
██╔══╝ ██╔══╝ ██║ ██║ ██╔═══╝ ██║ ██║██║ ██║██║ ╚██╔╝
██║ ███████╗██████╔╝ ██║ ╚██████╔╝███████╗██║╚██████╗ ██║
╚═╝ ╚══════╝╚═════╝ ╚═╝ ╚═════╝ ╚══════╝╚═╝ ╚═════╝ ╚═╝
████████╗██████╗ █████╗ ██████╗ ███████╗██████╗
╚══██╔══╝██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔══██╗
██║ ██████╔╝███████║██║ ██║█████╗ ██████╔╝
██║ ██╔══██╗██╔══██║██║ ██║██╔══╝ ██╔══██╗
██║ ██║ ██║██║ ██║██████╔╝███████╗██║ ██║
╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═════╝ ╚══════╝╚═╝ ╚═╝ v5.1
`;
export const QUICK_START_TIPS = [
{
icon: '📊',
title: 'Analyze Current Conditions',
command: 'analyze --template balanced-economic',
description: 'Find historical Fed policy analogues'
},
{
icon: '💹',
title: 'Market vs Fed Expectations',
command: 'market-expectations',
description: 'Yield curve & divergence analysis'
},
{
icon: '🌍',
title: 'Cross-Asset Playbook',
command: 'cross-asset-analysis',
description: 'Multi-asset Fed cycle positioning'
},
{
icon: '🎮',
title: 'Policy Simulator',
command: 'simulate',
description: 'What-if Fed scenario modeling'
}
];
export const formatSectionHeader = (title: string, width: number = 60): string => {
const padding = Math.max(0, width - title.length - 2);
const leftPad = Math.floor(padding / 2);
const rightPad = padding - leftPad;
return `${'═'.repeat(leftPad)} ${title} ${'═'.repeat(rightPad)}`;
};
export const formatSubheader = (title: string): string => {
return `──── ${title} ────`;
};
export const formatPercentage = (value: number, decimals: number = 1): string => {
const formatted = value.toFixed(decimals);
return value >= 0 ? `+${formatted}%` : `${formatted}%`;
};
export const formatBasisPoints = (value: number): string => {
return value >= 0 ? `+${value}bp` : `${value}bp`;
};
export const formatConfidenceBar = (confidence: number, width: number = 10): string => {
const filled = Math.round((confidence / 100) * width);
const empty = width - filled;
return '█'.repeat(filled) + '░'.repeat(empty);
};
export const getSignalEmoji = (type: 'BUY' | 'SELL' | 'HOLD'): string => {
switch (type) {
case 'BUY': return '🟢';
case 'SELL': return '🔴';
case 'HOLD': return '🟡';
}
};
export const getConfidenceLevel = (confidence: number): string => {
if (confidence >= 80) return 'HIGH';
if (confidence >= 60) return 'MEDIUM';
return 'LOW';
};
export const truncateText = (text: string, maxLength: number): string => {
if (text.length <= maxLength) return text;
return text.substring(0, maxLength - 3) + '...';
};
// Executive summary formatter
export interface ExecutiveSummary {
mainInsight: string;
keyTakeaways: string[];
timeframe: string;
confidence: number;
}
export const formatExecutiveSummary = (summary: ExecutiveSummary): string => {
const lines = [
formatSectionHeader('EXECUTIVE SUMMARY'),
'',
`🎯 ${summary.mainInsight}`,
'',
'Key Takeaways:',
...summary.keyTakeaways.map(t => ` • ${t}`),
'',
`Timeframe: ${summary.timeframe}`,
`Confidence: ${formatConfidenceBar(summary.confidence)} ${summary.confidence}%`,
'═'.repeat(60)
];
return lines.join('\n');
};
// Asset class performance formatter
export interface AssetClassSummary {
name: string;
performance: number;
signal: 'positive' | 'negative' | 'neutral';
confidence: number;
}
export const formatAssetClassSummary = (assets: AssetClassSummary[]): string => {
const lines = [formatSubheader('Asset Class Performance')];
const sorted = [...assets].sort((a, b) => b.performance - a.performance);
sorted.forEach(asset => {
const emoji = asset.signal === 'positive' ? '🟢' :
asset.signal === 'negative' ? '🔴' : '🟡';
const perf = formatPercentage(asset.performance);
const conf = formatConfidenceBar(asset.confidence, 5);
lines.push(`${emoji} ${asset.name.padEnd(15)} ${perf.padStart(8)} ${conf}`);
});
return lines.join('\n');
};
// Trading signal formatter
export interface TradingSignalSummary {
action: 'BUY' | 'SELL' | 'HOLD';
asset: string;
expectedReturn: number;
confidence: number;
reasoning: string;
}
export const formatTradingSignals = (signals: TradingSignalSummary[], maxSignals: number = 3): string => {
const lines = [formatSubheader('Top Trading Signals')];
const topSignals = signals
.sort((a, b) => b.confidence - a.confidence)
.slice(0, maxSignals);
topSignals.forEach((signal, i) => {
const emoji = getSignalEmoji(signal.action);
const ret = formatPercentage(signal.expectedReturn);
lines.push('');
lines.push(`${i + 1}. ${emoji} ${signal.action} ${signal.asset}`);
lines.push(` Expected: ${ret} | Confidence: ${signal.confidence}%`);
lines.push(` ${truncateText(signal.reasoning, 60)}`);
});
return lines.join('\n');
};
// Historical context formatter
export interface HistoricalContext {
period: string;
description: string;
similarity: number;
}
export const formatHistoricalContext = (contexts: HistoricalContext[]): string => {
const lines = [formatSubheader('Historical Analogues')];
contexts.forEach((ctx, i) => {
lines.push(`${i + 1}. ${ctx.period} - ${ctx.description}`);
lines.push(` Similarity: ${formatConfidenceBar(ctx.similarity, 8)} ${ctx.similarity}%`);
});
return lines.join('\n');
};
// Risk warning formatter
export interface RiskWarning {
level: 'high' | 'medium' | 'low';
message: string;
}
export const formatRiskWarnings = (warnings: RiskWarning[]): string => {
if (warnings.length === 0) return '';
const lines = ['', formatSubheader('Risk Warnings')];
warnings.forEach(warning => {
const emoji = warning.level === 'high' ? '🚨' :
warning.level === 'medium' ? '⚠️' : 'ℹ️';
lines.push(`${emoji} ${warning.message}`);
});
return lines.join('\n');
};
// Progress indicator for loading states
export const getProgressIndicator = (progress: number): string => {
const width = 30;
const filled = Math.round((progress / 100) * width);
const empty = width - filled;
return `[${'█'.repeat(filled)}${'░'.repeat(empty)}] ${progress}%`;
};