vibe-stocks
Version:
Terminal-based stock market viewer with real-time data streaming
70 lines (57 loc) • 2.21 kB
JavaScript
const axios = require('axios');
const asciichart = require('asciichart');
const chalk = require('chalk');
const ora = require('ora');
const config = require('./config');
module.exports = {
run: async (symbol, options) => {
const spinner = ora(`Loading chart data for ${symbol}...`).start();
try {
const response = await axios.get(`${config.MCP_SERVER_URL}${config.endpoints.historical(symbol)}`);
const data = response.data?.historical || [];
if (data.length < 2) {
spinner.fail('Not enough data for chart');
return;
}
spinner.stop();
// Filter data based on period
const periodDays = {
'1d': 1,
'5d': 5,
'1m': 30,
'3m': 90,
'6m': 180,
'1y': 365
};
const days = periodDays[options.period] || 30;
const recentData = data.slice(0, days).reverse();
const prices = recentData.map(d => d.close);
console.clear();
console.log(chalk.cyan.bold(`${symbol} Price Chart - ${options.period || '1m'}`));
console.log(chalk.gray(`Last Update: ${new Date().toLocaleTimeString()}\n`));
const chartConfig = {
offset: 3,
padding: ' ',
height: parseInt(options.height) || 15,
colors: [asciichart.green, asciichart.red]
};
console.log(asciichart.plot(prices, chartConfig));
const minPrice = Math.min(...prices);
const maxPrice = Math.max(...prices);
const currentPrice = prices[prices.length - 1];
const startPrice = prices[0];
const change = ((currentPrice - startPrice) / startPrice) * 100;
console.log(`\nRange: ${formatCurrency(minPrice)} - ${formatCurrency(maxPrice)}`);
console.log(`Period Change: ${change >= 0 ? chalk.green : chalk.red}${change >= 0 ? '+' : ''}${change.toFixed(2)}%${chalk.reset}`);
} catch (error) {
spinner.fail(`Failed to load chart for ${symbol}`);
console.error(chalk.red('Error:'), error.message);
}
}
};
function formatCurrency(num) {
return new Intl.NumberFormat('en-US', {
style: 'currency',
currency: 'USD'
}).format(num);
}