UNPKG

behemoth-cli

Version:

šŸŒ BEHEMOTH CLIv3.760.4 - Level 50+ POST-SINGULARITY Intelligence Trading AI

310 lines (307 loc) • 12.7 kB
/** * Chart Command - Interactive ASCII charts for crypto data */ import { BaseCommand } from '../base.js'; import InteractiveChartManager, { MultiSymbolDashboard } from '../../ui/components/display/InteractiveChartManager.js'; import { render } from 'ink'; import React from 'react'; export class ChartCommand extends BaseCommand { command = 'chart'; description = 'Display interactive ASCII charts for crypto analysis'; examples = [ '/chart --symbol=BTCUSDT --type=price', '/chart --symbol=ETHUSDT --type=all', '/chart --dashboard', '/chart --symbol=BTCUSDT --interactive' ]; handler(context) { // This handler is for the CommandDefinition interface // The actual chart functionality is in the execute method console.log('Chart command handler called'); } async execute(args, agent) { const { symbol = 'BTCUSDT', type = 'price', timeframe = '1h', interactive = true, dashboard = false } = args; try { if (dashboard) { return this.showDashboard(agent); } if (interactive) { return this.showInteractiveCharts(symbol, type, timeframe, agent); } // Static chart fallback return this.generateStaticChart(symbol, type, timeframe, agent); } catch (error) { return `āŒ Failed to generate chart: ${error instanceof Error ? error.message : 'Unknown error'}`; } } async showDashboard(agent) { const popularSymbols = [ 'BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'ADAUSDT', 'XRPUSDT', 'SOLUSDT', 'DOTUSDT', 'DOGEUSDT', 'AVAXUSDT', 'MATICUSDT' ]; return new Promise((resolve) => { const DashboardApp = () => { return React.createElement(MultiSymbolDashboard, { symbols: popularSymbols, onSymbolSelect: async (selectedSymbol) => { // Close dashboard and show charts for selected symbol const result = await this.showInteractiveCharts(selectedSymbol, 'all', '1h', agent); resolve(result); }, onClose: () => { resolve('šŸ“Š Chart dashboard closed'); } }); }; // Render the dashboard const { unmount } = render(React.createElement(DashboardApp)); // Auto-cleanup after 60 seconds setTimeout(() => { unmount(); resolve('šŸ“Š Chart dashboard timed out'); }, 60000); }); } async showInteractiveCharts(symbol, type, timeframe, agent) { // Fetch real data using BEHEMOTH tools const chartConfigs = await this.generateChartConfigs(symbol, type, timeframe, agent); return new Promise((resolve) => { const ChartApp = () => { return React.createElement(InteractiveChartManager, { charts: chartConfigs, onRefresh: async (chartId) => { // Refresh specific chart data await this.refreshChartData(chartId, symbol, agent); }, onClose: () => { resolve(`šŸ“Š Interactive charts for ${symbol} closed`); } }); }; // Render the interactive charts const { unmount } = render(React.createElement(ChartApp)); // Auto-cleanup after 5 minutes setTimeout(() => { unmount(); resolve(`šŸ“Š Interactive charts for ${symbol} timed out`); }, 300000); }); } async generateChartConfigs(symbol, type, timeframe, agent) { const configs = []; try { if (type === 'price' || type === 'all') { // Get price data const priceResult = await agent.executeTool('mcp__behemoth__binance_spot_ticker', { symbol }); const klineResult = await agent.executeTool('mcp__behemoth__bitget_klines', { symbol, interval: timeframe, limit: 20 }); if (klineResult?.success && klineResult.data?.length) { const prices = klineResult.data.map((candle) => parseFloat(candle.close)); const timestamps = klineResult.data.map((candle) => new Date(candle.timestamp).toLocaleTimeString()); configs.push({ id: `price_${symbol}`, title: `${symbol} Price`, type: 'price', symbol, data: prices, timestamps, autoRefresh: true, refreshInterval: 30 }); } } if (type === 'rsi' || type === 'all') { // Get RSI data const rsiResult = await agent.executeTool('mcp__behemoth__rsi_analysis', { symbol }); if (rsiResult?.success && rsiResult.data?.rsi_values) { configs.push({ id: `rsi_${symbol}`, title: `${symbol} RSI`, type: 'rsi', symbol, data: rsiResult.data.rsi_values, timestamps: rsiResult.data.timestamps, autoRefresh: true, refreshInterval: 30 }); } } if (type === 'volume' || type === 'all') { // Get volume data from klines const klineResult = await agent.executeTool('mcp__behemoth__bitget_klines', { symbol, interval: timeframe, limit: 20 }); if (klineResult?.success && klineResult.data?.length) { const volumes = klineResult.data.map((candle) => parseFloat(candle.volume)); const timestamps = klineResult.data.map((candle) => new Date(candle.timestamp).toLocaleTimeString()); configs.push({ id: `volume_${symbol}`, title: `${symbol} Volume`, type: 'volume', symbol, data: volumes, timestamps, autoRefresh: true, refreshInterval: 30 }); } } // If no real data, generate mock data for demo if (configs.length === 0) { configs.push(...this.generateMockChartConfigs(symbol, type)); } } catch (error) { console.error('Error generating chart configs:', error); // Fallback to mock data configs.push(...this.generateMockChartConfigs(symbol, type)); } return configs; } generateMockChartConfigs(symbol, type) { const configs = []; const timestamps = Array.from({ length: 20 }, (_, i) => { const time = new Date(Date.now() - (19 - i) * 60000); return time.toLocaleTimeString(); }); if (type === 'price' || type === 'all') { const basePrice = 45000 + Math.random() * 10000; const prices = Array.from({ length: 20 }, (_, i) => { return basePrice + (Math.random() - 0.5) * 2000 + Math.sin(i * 0.5) * 1000; }); configs.push({ id: `price_${symbol}`, title: `${symbol} Price (Demo)`, type: 'price', symbol, data: prices, timestamps, autoRefresh: true, refreshInterval: 30 }); } if (type === 'rsi' || type === 'all') { const rsiValues = Array.from({ length: 20 }, (_, i) => { return 30 + Math.random() * 40 + Math.sin(i * 0.3) * 10; }); configs.push({ id: `rsi_${symbol}`, title: `${symbol} RSI (Demo)`, type: 'rsi', symbol, data: rsiValues, timestamps, autoRefresh: true, refreshInterval: 30 }); } if (type === 'volume' || type === 'all') { const volumes = Array.from({ length: 20 }, (_, i) => { return 1000000 + Math.random() * 5000000; }); configs.push({ id: `volume_${symbol}`, title: `${symbol} Volume (Demo)`, type: 'volume', symbol, data: volumes, timestamps, autoRefresh: true, refreshInterval: 30 }); } return configs; } async refreshChartData(chartId, symbol, agent) { try { // Refresh data based on chart type if (chartId.includes('price')) { await agent.executeTool('mcp__behemoth__bitget_klines', { symbol, limit: 20 }); } else if (chartId.includes('rsi')) { await agent.executeTool('mcp__behemoth__rsi_analysis', { symbol }); } else if (chartId.includes('volume')) { await agent.executeTool('mcp__behemoth__bitget_klines', { symbol, limit: 20 }); } } catch (error) { console.error(`Failed to refresh chart ${chartId}:`, error); } } async generateStaticChart(symbol, type, timeframe, agent) { try { // Generate a simple text-based chart for non-interactive mode const result = await agent.executeTool('mcp__behemoth__binance_spot_ticker', { symbol }); if (result?.success) { const price = parseFloat(result.data.price); const change = parseFloat(result.data.priceChangePercent); // Simple sparkline const sparkline = this.generateSparkline(price, change); return `šŸ“Š ${symbol} ${type.toUpperCase()} Chart (${timeframe}) Current Price: $${price.toLocaleString()} 24h Change: ${change >= 0 ? '+' : ''}${change.toFixed(2)}% ${sparkline} šŸ’” Use --interactive flag for full interactive charts Example: /chart --symbol=${symbol} --interactive`; } } catch (error) { console.error('Error generating static chart:', error); } return `šŸ“Š Unable to generate chart for ${symbol}. Try /chart --dashboard for available symbols.`; } generateSparkline(price, change) { // Generate a simple sparkline based on price and change const chars = ['▁', 'ā–‚', 'ā–ƒ', 'ā–„', 'ā–…', 'ā–†', 'ā–‡', 'ā–ˆ']; let line = ''; for (let i = 0; i < 20; i++) { const variation = Math.sin(i * 0.5) * 0.1 + (change / 100); const normalized = Math.max(0, Math.min(1, 0.5 + variation)); const charIndex = Math.floor(normalized * (chars.length - 1)); line += chars[charIndex]; } return line; } getSchema() { return { type: 'object', properties: { symbol: { type: 'string', description: 'Trading pair symbol (e.g., BTCUSDT)', default: 'BTCUSDT' }, type: { type: 'string', enum: ['price', 'rsi', 'volume', 'all'], description: 'Chart type to display', default: 'price' }, timeframe: { type: 'string', enum: ['1m', '5m', '15m', '1h', '4h', '1d'], description: 'Chart timeframe', default: '1h' }, interactive: { type: 'boolean', description: 'Enable interactive chart mode', default: true }, dashboard: { type: 'boolean', description: 'Show multi-symbol dashboard', default: false } } }; } } //# sourceMappingURL=chart.js.map