- Enhanced 24/7 automation with sentiment-based threshold adjustments - Multi-asset global trader supporting BTC, ETH, SOL, ADA - Comprehensive sentiment indicators guide with 8 categories - Global sentiment API providing real-time market regime detection - Fear & Greed Index integration with fallback estimation - Sentiment-adjusted confidence thresholds and position sizing - Successfully executed first sentiment-aware trade (GREED regime) - Market regime classification: EXTREME_FEAR to EXTREME_GREED - Trading threshold adjustments based on market psychology
265 lines
8.4 KiB
JavaScript
265 lines
8.4 KiB
JavaScript
/**
|
|
* 🌍 Global Market Sentiment Dashboard API
|
|
* Provides comprehensive sentiment data for frontend display
|
|
*/
|
|
|
|
import { NextRequest, NextResponse } from 'next/server';
|
|
import https from 'https';
|
|
|
|
// Utility function for external API calls
|
|
function makeRequest(url, options = {}) {
|
|
return new Promise((resolve, reject) => {
|
|
const req = https.request(url, options, (res) => {
|
|
let data = '';
|
|
res.on('data', chunk => data += chunk);
|
|
res.on('end', () => {
|
|
try {
|
|
resolve(res.statusCode === 200 ? JSON.parse(data) : null);
|
|
} catch (e) {
|
|
resolve(null);
|
|
}
|
|
});
|
|
});
|
|
req.on('error', reject);
|
|
req.end();
|
|
});
|
|
}
|
|
|
|
async function getFearGreedIndex() {
|
|
try {
|
|
const response = await makeRequest('https://api.alternative.me/fng/');
|
|
if (response?.data?.[0]) {
|
|
const data = response.data[0];
|
|
return {
|
|
value: parseInt(data.value),
|
|
classification: data.value_classification,
|
|
timestamp: data.timestamp,
|
|
source: 'alternative.me'
|
|
};
|
|
}
|
|
} catch (error) {
|
|
console.log('Fear & Greed API unavailable, using estimation');
|
|
}
|
|
|
|
// Fallback estimation
|
|
const now = Date.now();
|
|
const baseValue = 50 + Math.sin(now / (1000 * 60 * 60 * 24)) * 25;
|
|
return {
|
|
value: Math.round(Math.max(0, Math.min(100, baseValue))),
|
|
classification: 'estimated',
|
|
timestamp: Math.floor(now / 1000),
|
|
source: 'estimated'
|
|
};
|
|
}
|
|
|
|
async function getAssetPrice(coinId) {
|
|
try {
|
|
const url = `https://api.coingecko.com/api/v3/simple/price?ids=${coinId}&vs_currencies=usd&include_24hr_change=true`;
|
|
const response = await makeRequest(url);
|
|
return response?.[coinId];
|
|
} catch (error) {
|
|
console.log(`Price fetch failed for ${coinId}`);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
async function getBitcoinDominance() {
|
|
try {
|
|
const url = 'https://api.coingecko.com/api/v3/global';
|
|
const response = await makeRequest(url);
|
|
return response?.data?.market_cap_percentage?.btc || 50;
|
|
} catch (error) {
|
|
return 50; // Default assumption
|
|
}
|
|
}
|
|
|
|
function calculateVolatilityIndex(prices) {
|
|
if (!prices || prices.length < 2) return 50;
|
|
|
|
// Calculate simple volatility based on price changes
|
|
const changes = [];
|
|
for (let i = 1; i < prices.length; i++) {
|
|
changes.push(Math.abs((prices[i] - prices[i-1]) / prices[i-1]));
|
|
}
|
|
|
|
const avgChange = changes.reduce((a, b) => a + b, 0) / changes.length;
|
|
return Math.min(100, avgChange * 1000); // Scale to 0-100
|
|
}
|
|
|
|
function getMarketRegime(fearGreed, btcDom, volatility) {
|
|
if (fearGreed <= 25) return 'EXTREME_FEAR';
|
|
if (fearGreed <= 45) return 'FEAR';
|
|
if (fearGreed >= 75) return 'EXTREME_GREED';
|
|
if (fearGreed >= 55) return 'GREED';
|
|
return 'NEUTRAL';
|
|
}
|
|
|
|
function getRiskLevel(regime, volatility) {
|
|
switch (regime) {
|
|
case 'EXTREME_FEAR': return volatility > 60 ? 'HIGH_OPPORTUNITY' : 'MODERATE_OPPORTUNITY';
|
|
case 'FEAR': return 'MODERATE_OPPORTUNITY';
|
|
case 'EXTREME_GREED': return volatility > 60 ? 'EXTREME_RISK' : 'HIGH_RISK';
|
|
case 'GREED': return 'MODERATE_RISK';
|
|
default: return volatility > 60 ? 'ELEVATED' : 'BALANCED';
|
|
}
|
|
}
|
|
|
|
function getTradingThresholds(regime) {
|
|
const thresholds = {
|
|
EXTREME_FEAR: { buy: 55, sell: 75, maxPosition: 1.5 },
|
|
FEAR: { buy: 60, sell: 70, maxPosition: 1.2 },
|
|
NEUTRAL: { buy: 65, sell: 65, maxPosition: 1.0 },
|
|
GREED: { buy: 70, sell: 60, maxPosition: 0.8 },
|
|
EXTREME_GREED: { buy: 80, sell: 55, maxPosition: 0.5 }
|
|
};
|
|
|
|
return thresholds[regime] || thresholds.NEUTRAL;
|
|
}
|
|
|
|
export async function GET() {
|
|
try {
|
|
console.log('🌍 Fetching global market sentiment data...');
|
|
|
|
// Fetch all sentiment data in parallel
|
|
const [fearGreed, btcPrice, ethPrice, solPrice, btcDominance] = await Promise.all([
|
|
getFearGreedIndex(),
|
|
getAssetPrice('bitcoin'),
|
|
getAssetPrice('ethereum'),
|
|
getAssetPrice('solana'),
|
|
getBitcoinDominance()
|
|
]);
|
|
|
|
// Calculate derived metrics
|
|
const priceChanges = [
|
|
btcPrice?.usd_24h_change || 0,
|
|
ethPrice?.usd_24h_change || 0,
|
|
solPrice?.usd_24h_change || 0
|
|
];
|
|
|
|
const volatilityIndex = calculateVolatilityIndex(priceChanges);
|
|
const marketRegime = getMarketRegime(fearGreed.value, btcDominance, volatilityIndex);
|
|
const riskLevel = getRiskLevel(marketRegime, volatilityIndex);
|
|
const thresholds = getTradingThresholds(marketRegime);
|
|
|
|
// Calculate correlations (simplified)
|
|
const avgChange = priceChanges.reduce((a, b) => a + b, 0) / priceChanges.length;
|
|
const correlationLevel = Math.abs(avgChange) > 5 ? 'HIGH' : 'NORMAL';
|
|
|
|
const sentimentData = {
|
|
timestamp: new Date().toISOString(),
|
|
|
|
// Core sentiment indicators
|
|
fearAndGreed: {
|
|
value: fearGreed.value,
|
|
classification: fearGreed.classification,
|
|
interpretation: getInterpretation(fearGreed.value),
|
|
source: fearGreed.source
|
|
},
|
|
|
|
// Crypto-specific metrics
|
|
bitcoinDominance: {
|
|
value: btcDominance,
|
|
interpretation: btcDominance > 60 ? 'BTC_STRENGTH' : btcDominance < 40 ? 'ALT_STRENGTH' : 'BALANCED'
|
|
},
|
|
|
|
// Volatility measures
|
|
volatility: {
|
|
index: volatilityIndex,
|
|
level: volatilityIndex > 60 ? 'HIGH' : volatilityIndex < 30 ? 'LOW' : 'MODERATE'
|
|
},
|
|
|
|
// Market classification
|
|
marketRegime: {
|
|
current: marketRegime,
|
|
riskLevel: riskLevel,
|
|
correlationLevel: correlationLevel
|
|
},
|
|
|
|
// Trading parameters
|
|
tradingThresholds: thresholds,
|
|
|
|
// Asset prices
|
|
assetPrices: {
|
|
bitcoin: btcPrice,
|
|
ethereum: ethPrice,
|
|
solana: solPrice
|
|
},
|
|
|
|
// Market summary
|
|
summary: {
|
|
sentiment: `${marketRegime.replace('_', ' ')} market with ${riskLevel.replace('_', ' ')} risk level`,
|
|
recommendation: getMarketRecommendation(marketRegime, volatilityIndex),
|
|
keyFactors: getKeyFactors(fearGreed.value, btcDominance, volatilityIndex)
|
|
}
|
|
};
|
|
|
|
console.log(`📊 Sentiment: ${marketRegime} | F&G: ${fearGreed.value} | BTC Dom: ${btcDominance.toFixed(1)}%`);
|
|
|
|
return NextResponse.json({
|
|
success: true,
|
|
data: sentimentData
|
|
});
|
|
|
|
} catch (error) {
|
|
console.error('❌ Global sentiment fetch error:', error);
|
|
|
|
return NextResponse.json({
|
|
success: false,
|
|
error: error.message,
|
|
data: getDefaultSentimentData()
|
|
});
|
|
}
|
|
}
|
|
|
|
function getInterpretation(fearGreedValue) {
|
|
if (fearGreedValue <= 25) return 'Strong contrarian buy signal - market oversold';
|
|
if (fearGreedValue <= 45) return 'Cautious buy opportunity - fear dominates';
|
|
if (fearGreedValue >= 75) return 'Strong sell signal - market euphoric';
|
|
if (fearGreedValue >= 55) return 'Consider profit taking - greed increasing';
|
|
return 'Neutral sentiment - technical analysis primary';
|
|
}
|
|
|
|
function getMarketRecommendation(regime, volatility) {
|
|
switch (regime) {
|
|
case 'EXTREME_FEAR':
|
|
return volatility > 60 ? 'AGGRESSIVE_BUY' : 'MODERATE_BUY';
|
|
case 'FEAR':
|
|
return 'CAUTIOUS_BUY';
|
|
case 'EXTREME_GREED':
|
|
return volatility > 60 ? 'AGGRESSIVE_SELL' : 'MODERATE_SELL';
|
|
case 'GREED':
|
|
return 'CAUTIOUS_SELL';
|
|
default:
|
|
return 'TECHNICAL_ANALYSIS';
|
|
}
|
|
}
|
|
|
|
function getKeyFactors(fearGreed, btcDom, volatility) {
|
|
const factors = [];
|
|
|
|
if (fearGreed <= 25) factors.push('Extreme fear presents opportunity');
|
|
if (fearGreed >= 75) factors.push('Extreme greed suggests caution');
|
|
if (btcDom > 60) factors.push('Bitcoin dominance affecting altcoins');
|
|
if (btcDom < 40) factors.push('Altcoin season conditions');
|
|
if (volatility > 60) factors.push('High volatility increases risk/reward');
|
|
if (volatility < 30) factors.push('Low volatility suggests consolidation');
|
|
|
|
return factors;
|
|
}
|
|
|
|
function getDefaultSentimentData() {
|
|
return {
|
|
timestamp: new Date().toISOString(),
|
|
fearAndGreed: { value: 50, classification: 'neutral', interpretation: 'Default neutral sentiment', source: 'default' },
|
|
bitcoinDominance: { value: 50, interpretation: 'BALANCED' },
|
|
volatility: { index: 50, level: 'MODERATE' },
|
|
marketRegime: { current: 'NEUTRAL', riskLevel: 'BALANCED', correlationLevel: 'NORMAL' },
|
|
tradingThresholds: { buy: 65, sell: 65, maxPosition: 1.0 },
|
|
summary: {
|
|
sentiment: 'Neutral market with balanced risk level',
|
|
recommendation: 'TECHNICAL_ANALYSIS',
|
|
keyFactors: ['Default sentiment data - external APIs unavailable']
|
|
}
|
|
};
|
|
}
|