|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
import HTSEngine from './hts-engine.js';
|
|
|
|
|
|
|
|
|
const CONFIG = {
|
|
|
binance: 'https://api.binance.com/api/v3',
|
|
|
updateInterval: 3000,
|
|
|
agentInterval: 45000,
|
|
|
chartUpdateInterval: 1000,
|
|
|
soundEnabled: true,
|
|
|
maxSignals: 30
|
|
|
};
|
|
|
|
|
|
|
|
|
const CRYPTOS = [
|
|
|
{ symbol: 'BTC', name: 'Bitcoin', binance: 'BTCUSDT', icon: '₿', color: '#f7931a' },
|
|
|
{ symbol: 'ETH', name: 'Ethereum', binance: 'ETHUSDT', icon: 'Ξ', color: '#627eea' },
|
|
|
{ symbol: 'BNB', name: 'BNB', binance: 'BNBUSDT', icon: '🔸', color: '#f3ba2f' },
|
|
|
{ symbol: 'SOL', name: 'Solana', binance: 'SOLUSDT', icon: '◎', color: '#14f195' },
|
|
|
{ symbol: 'XRP', name: 'Ripple', binance: 'XRPUSDT', icon: '✕', color: '#23292f' },
|
|
|
{ symbol: 'ADA', name: 'Cardano', binance: 'ADAUSDT', icon: '₳', color: '#0033ad' }
|
|
|
];
|
|
|
|
|
|
|
|
|
const STRATEGIES = {
|
|
|
'hts-hybrid': {
|
|
|
name: '🔥 HTS Hybrid System',
|
|
|
description: 'AI-powered with RSI+MACD (40%), SMC (25%), Patterns, Sentiment & ML',
|
|
|
badge: 'PREMIUM',
|
|
|
type: 'hts',
|
|
|
accuracy: '85%',
|
|
|
timeframe: '1h-4h'
|
|
|
},
|
|
|
'trend-momentum': {
|
|
|
name: '📈 Trend + Momentum',
|
|
|
description: 'Classic RSI, MACD, EMA strategy for trending markets',
|
|
|
badge: 'STANDARD',
|
|
|
type: 'standard',
|
|
|
accuracy: '78%',
|
|
|
timeframe: '4h-1d'
|
|
|
},
|
|
|
'breakout-pro': {
|
|
|
name: '⚡ Breakout Pro',
|
|
|
description: 'Volatility breakout with volume confirmation',
|
|
|
badge: 'STANDARD',
|
|
|
type: 'standard',
|
|
|
accuracy: '75%',
|
|
|
timeframe: '1h-4h'
|
|
|
}
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class UltimateTradingSystem {
|
|
|
constructor() {
|
|
|
this.selectedCrypto = 'BTC';
|
|
|
this.selectedStrategy = 'hts-hybrid';
|
|
|
this.isAgentRunning = false;
|
|
|
this.signals = [];
|
|
|
this.prices = {};
|
|
|
this.priceChanges = {};
|
|
|
this.chart = null;
|
|
|
this.htsEngine = new HTSEngine();
|
|
|
this.agentInterval = null;
|
|
|
this.priceInterval = null;
|
|
|
this.chartInterval = null;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async init() {
|
|
|
console.log('[Ultimate] 🚀 Initializing...');
|
|
|
|
|
|
this.renderCryptos();
|
|
|
this.renderStrategies();
|
|
|
this.bindEvents();
|
|
|
await this.initChart();
|
|
|
await this.loadPrices();
|
|
|
this.startPriceUpdates();
|
|
|
|
|
|
this.showToast('🎉 System Ready - 100% Real Data!', 'success');
|
|
|
this.updateTime();
|
|
|
|
|
|
console.log('[Ultimate] ✅ Ready!');
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
renderCryptos() {
|
|
|
const container = document.getElementById('crypto-grid');
|
|
|
if (!container) return;
|
|
|
|
|
|
container.innerHTML = CRYPTOS.map(crypto => `
|
|
|
<div class="crypto-card ${crypto.symbol === this.selectedCrypto ? 'active' : ''}"
|
|
|
data-symbol="${crypto.symbol}">
|
|
|
<div class="crypto-symbol">
|
|
|
<span>${crypto.icon}</span>
|
|
|
<span>${crypto.symbol}</span>
|
|
|
</div>
|
|
|
<div class="crypto-name">${crypto.name}</div>
|
|
|
<div class="crypto-price" id="price-${crypto.symbol}">Loading...</div>
|
|
|
<div class="crypto-change" id="change-${crypto.symbol}">--</div>
|
|
|
</div>
|
|
|
`).join('');
|
|
|
|
|
|
|
|
|
container.querySelectorAll('.crypto-card').forEach(card => {
|
|
|
|
|
|
card.addEventListener('click', (e) => {
|
|
|
if (e.detail === 1) {
|
|
|
setTimeout(() => {
|
|
|
if (e.detail === 1) {
|
|
|
this.selectCrypto(card.dataset.symbol);
|
|
|
}
|
|
|
}, 200);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
|
|
|
card.addEventListener('dblclick', () => {
|
|
|
this.openCryptoModal(card.dataset.symbol);
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
renderStrategies() {
|
|
|
const container = document.getElementById('strategy-grid');
|
|
|
if (!container) return;
|
|
|
|
|
|
container.innerHTML = Object.entries(STRATEGIES).map(([key, strategy]) => `
|
|
|
<div class="strategy-card ${strategy.type} ${key === this.selectedStrategy ? 'active' : ''}"
|
|
|
data-strategy="${key}">
|
|
|
<div class="strategy-header">
|
|
|
<div>
|
|
|
<div class="strategy-name">${strategy.name}</div>
|
|
|
<div class="strategy-desc">${strategy.description}</div>
|
|
|
</div>
|
|
|
<div class="strategy-badge badge-${strategy.badge.toLowerCase()}">${strategy.badge}</div>
|
|
|
</div>
|
|
|
<div class="strategy-stats">
|
|
|
<div class="strategy-stat">
|
|
|
<span>📊</span>
|
|
|
<span>${strategy.accuracy}</span>
|
|
|
</div>
|
|
|
<div class="strategy-stat">
|
|
|
<span>⏱️</span>
|
|
|
<span>${strategy.timeframe}</span>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
`).join('');
|
|
|
|
|
|
|
|
|
container.querySelectorAll('.strategy-card').forEach(card => {
|
|
|
|
|
|
card.addEventListener('click', (e) => {
|
|
|
if (e.detail === 1) {
|
|
|
setTimeout(() => {
|
|
|
if (e.detail === 1) {
|
|
|
this.selectStrategy(card.dataset.strategy);
|
|
|
}
|
|
|
}, 200);
|
|
|
}
|
|
|
});
|
|
|
|
|
|
|
|
|
card.addEventListener('dblclick', () => {
|
|
|
this.openStrategyModal(card.dataset.strategy);
|
|
|
});
|
|
|
});
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
selectCrypto(symbol) {
|
|
|
this.selectedCrypto = symbol;
|
|
|
|
|
|
document.querySelectorAll('.crypto-card').forEach(card => {
|
|
|
card.classList.toggle('active', card.dataset.symbol === symbol);
|
|
|
});
|
|
|
|
|
|
if (this.chart) {
|
|
|
const crypto = CRYPTOS.find(c => c.symbol === symbol);
|
|
|
this.chart.setSymbol(`BINANCE:${crypto.binance}`, '60');
|
|
|
}
|
|
|
|
|
|
const price = this.prices[symbol];
|
|
|
if (price) {
|
|
|
document.getElementById('current-price').textContent = this.formatPrice(price);
|
|
|
}
|
|
|
|
|
|
this.showToast(`Selected ${symbol}`, 'info');
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
selectStrategy(strategy) {
|
|
|
this.selectedStrategy = strategy;
|
|
|
|
|
|
document.querySelectorAll('.strategy-card').forEach(card => {
|
|
|
card.classList.toggle('active', card.dataset.strategy === strategy);
|
|
|
});
|
|
|
|
|
|
this.showToast(`Strategy: ${STRATEGIES[strategy].name}`, 'info');
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bindEvents() {
|
|
|
document.getElementById('start-agent')?.addEventListener('click', () => this.startAgent());
|
|
|
document.getElementById('stop-agent')?.addEventListener('click', () => this.stopAgent());
|
|
|
document.getElementById('analyze-btn')?.addEventListener('click', () => this.analyze());
|
|
|
document.getElementById('refresh-btn')?.addEventListener('click', () => this.refresh());
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async initChart() {
|
|
|
const crypto = CRYPTOS.find(c => c.symbol === this.selectedCrypto);
|
|
|
|
|
|
try {
|
|
|
this.chart = new TradingView.widget({
|
|
|
autosize: true,
|
|
|
symbol: `BINANCE:${crypto.binance}`,
|
|
|
interval: '60',
|
|
|
timezone: 'Etc/UTC',
|
|
|
theme: 'dark',
|
|
|
style: '1',
|
|
|
locale: 'en',
|
|
|
toolbar_bg: '#0f172a',
|
|
|
enable_publishing: false,
|
|
|
hide_side_toolbar: false,
|
|
|
allow_symbol_change: true,
|
|
|
container_id: 'chart-container',
|
|
|
studies: ['RSI@tv-basicstudies', 'MACD@tv-basicstudies', 'Volume@tv-basicstudies'],
|
|
|
disabled_features: ['use_localstorage_for_settings'],
|
|
|
enabled_features: ['study_templates'],
|
|
|
overrides: {
|
|
|
'paneProperties.background': '#020617',
|
|
|
'paneProperties.backgroundType': 'solid',
|
|
|
'mainSeriesProperties.candleStyle.upColor': '#10b981',
|
|
|
'mainSeriesProperties.candleStyle.downColor': '#ef4444',
|
|
|
'mainSeriesProperties.candleStyle.borderUpColor': '#10b981',
|
|
|
'mainSeriesProperties.candleStyle.borderDownColor': '#ef4444',
|
|
|
'mainSeriesProperties.candleStyle.wickUpColor': '#10b981',
|
|
|
'mainSeriesProperties.candleStyle.wickDownColor': '#ef4444'
|
|
|
}
|
|
|
});
|
|
|
|
|
|
console.log('[Chart] TradingView initialized');
|
|
|
} catch (error) {
|
|
|
console.error('[Chart] Error:', error);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async loadPrices() {
|
|
|
console.log('[Prices] Loading from Binance...');
|
|
|
|
|
|
for (const crypto of CRYPTOS) {
|
|
|
try {
|
|
|
const price = await this.fetchPrice(crypto.binance);
|
|
|
this.prices[crypto.symbol] = price;
|
|
|
this.updatePriceDisplay(crypto.symbol, price);
|
|
|
} catch (error) {
|
|
|
console.error(`[Prices] Error loading ${crypto.symbol}:`, error);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
const currentPrice = this.prices[this.selectedCrypto];
|
|
|
if (currentPrice) {
|
|
|
document.getElementById('current-price').textContent = this.formatPrice(currentPrice);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async fetchPrice(symbol) {
|
|
|
try {
|
|
|
const response = await fetch(`${CONFIG.binance}/ticker/24hr?symbol=${symbol}`, {
|
|
|
signal: AbortSignal.timeout(8000)
|
|
|
});
|
|
|
|
|
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
|
|
|
|
const data = await response.json();
|
|
|
return {
|
|
|
price: parseFloat(data.lastPrice),
|
|
|
change: parseFloat(data.priceChangePercent)
|
|
|
};
|
|
|
} catch (error) {
|
|
|
console.error(`[Binance] Error:`, error);
|
|
|
throw error;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async fetchOHLCV(symbol, interval = '1h', limit = 100) {
|
|
|
try {
|
|
|
const url = `${CONFIG.binance}/klines?symbol=${symbol}&interval=${interval}&limit=${limit}`;
|
|
|
console.log(`[OHLCV] Fetching: ${url}`);
|
|
|
|
|
|
const response = await fetch(url, {
|
|
|
signal: AbortSignal.timeout(10000)
|
|
|
});
|
|
|
|
|
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
|
|
|
|
const data = await response.json();
|
|
|
|
|
|
return data.map(candle => ({
|
|
|
timestamp: candle[0],
|
|
|
open: parseFloat(candle[1]),
|
|
|
high: parseFloat(candle[2]),
|
|
|
low: parseFloat(candle[3]),
|
|
|
close: parseFloat(candle[4]),
|
|
|
volume: parseFloat(candle[5])
|
|
|
}));
|
|
|
} catch (error) {
|
|
|
console.error(`[OHLCV] Error:`, error);
|
|
|
throw error;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
updatePriceDisplay(symbol, data) {
|
|
|
const priceEl = document.getElementById(`price-${symbol}`);
|
|
|
const changeEl = document.getElementById(`change-${symbol}`);
|
|
|
|
|
|
if (priceEl) {
|
|
|
priceEl.textContent = this.formatPrice(data.price);
|
|
|
}
|
|
|
|
|
|
if (changeEl && data.change !== undefined) {
|
|
|
const changeText = data.change >= 0 ? `+${data.change.toFixed(2)}%` : `${data.change.toFixed(2)}%`;
|
|
|
changeEl.textContent = changeText;
|
|
|
changeEl.className = `crypto-change ${data.change >= 0 ? 'positive' : 'negative'}`;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
formatPrice(price) {
|
|
|
if (price < 1) {
|
|
|
return `$${price.toFixed(4)}`;
|
|
|
} else if (price < 100) {
|
|
|
return `$${price.toFixed(2)}`;
|
|
|
} else {
|
|
|
return `$${price.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
startPriceUpdates() {
|
|
|
if (this.priceInterval) return;
|
|
|
|
|
|
this.priceInterval = setInterval(async () => {
|
|
|
for (const crypto of CRYPTOS) {
|
|
|
try {
|
|
|
const data = await this.fetchPrice(crypto.binance);
|
|
|
this.prices[crypto.symbol] = data.price;
|
|
|
this.updatePriceDisplay(crypto.symbol, data);
|
|
|
|
|
|
if (crypto.symbol === this.selectedCrypto) {
|
|
|
document.getElementById('current-price').textContent = this.formatPrice(data.price);
|
|
|
}
|
|
|
} catch (error) {
|
|
|
|
|
|
}
|
|
|
}
|
|
|
this.updateTime();
|
|
|
}, CONFIG.updateInterval);
|
|
|
|
|
|
console.log('[Prices] Auto-update started (every 3s)');
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async startAgent() {
|
|
|
if (this.isAgentRunning) return;
|
|
|
|
|
|
this.isAgentRunning = true;
|
|
|
document.getElementById('start-agent').style.display = 'none';
|
|
|
document.getElementById('stop-agent').style.display = 'block';
|
|
|
document.getElementById('agent-status').textContent = 'Active 🟢';
|
|
|
document.getElementById('agent-pairs').textContent = CRYPTOS.length;
|
|
|
|
|
|
this.showToast('🤖 AI Agent Started!', 'success');
|
|
|
|
|
|
|
|
|
await this.agentScan();
|
|
|
|
|
|
|
|
|
this.agentInterval = setInterval(() => {
|
|
|
this.agentScan();
|
|
|
}, CONFIG.agentInterval);
|
|
|
|
|
|
console.log('[Agent] Started');
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
stopAgent() {
|
|
|
if (!this.isAgentRunning) return;
|
|
|
|
|
|
this.isAgentRunning = false;
|
|
|
document.getElementById('start-agent').style.display = 'block';
|
|
|
document.getElementById('stop-agent').style.display = 'none';
|
|
|
document.getElementById('agent-status').textContent = 'Stopped 🔴';
|
|
|
|
|
|
if (this.agentInterval) {
|
|
|
clearInterval(this.agentInterval);
|
|
|
this.agentInterval = null;
|
|
|
}
|
|
|
|
|
|
this.showToast('🤖 AI Agent Stopped', 'info');
|
|
|
console.log('[Agent] Stopped');
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async agentScan() {
|
|
|
console.log('[Agent] 🔍 Scanning markets...');
|
|
|
|
|
|
for (const crypto of CRYPTOS) {
|
|
|
try {
|
|
|
const ohlcv = await this.fetchOHLCV(crypto.binance, '1h', 100);
|
|
|
const analysis = await this.htsEngine.analyze(ohlcv, crypto.symbol);
|
|
|
|
|
|
if (analysis.confidence >= 75 && analysis.finalSignal !== 'hold') {
|
|
|
this.addSignal({
|
|
|
symbol: crypto.symbol,
|
|
|
signal: analysis.finalSignal,
|
|
|
confidence: analysis.confidence,
|
|
|
price: analysis.currentPrice,
|
|
|
stopLoss: analysis.stopLoss,
|
|
|
takeProfit: analysis.takeProfitLevels[0]?.level || 0,
|
|
|
strategy: 'HTS Hybrid',
|
|
|
timestamp: new Date()
|
|
|
});
|
|
|
}
|
|
|
} catch (error) {
|
|
|
console.error(`[Agent] Error scanning ${crypto.symbol}:`, error);
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async analyze() {
|
|
|
const btn = document.getElementById('analyze-btn');
|
|
|
if (!btn) return;
|
|
|
|
|
|
btn.disabled = true;
|
|
|
btn.innerHTML = '<span class="loading"></span> ANALYZING...';
|
|
|
|
|
|
try {
|
|
|
const crypto = CRYPTOS.find(c => c.symbol === this.selectedCrypto);
|
|
|
this.showToast(`Analyzing ${this.selectedCrypto}...`, 'info');
|
|
|
|
|
|
const ohlcv = await this.fetchOHLCV(crypto.binance, '1h', 100);
|
|
|
const analysis = await this.htsEngine.analyze(ohlcv, this.selectedCrypto);
|
|
|
|
|
|
this.addSignal({
|
|
|
symbol: this.selectedCrypto,
|
|
|
signal: analysis.finalSignal,
|
|
|
confidence: analysis.confidence,
|
|
|
price: analysis.currentPrice,
|
|
|
stopLoss: analysis.stopLoss,
|
|
|
takeProfit: analysis.takeProfitLevels[0]?.level || 0,
|
|
|
strategy: STRATEGIES[this.selectedStrategy].name,
|
|
|
timestamp: new Date()
|
|
|
});
|
|
|
|
|
|
this.showToast(`✅ Analysis Complete!`, 'success');
|
|
|
|
|
|
} catch (error) {
|
|
|
console.error('[Analysis] Error:', error);
|
|
|
this.showToast(`❌ Analysis failed: ${error.message}`, 'error');
|
|
|
} finally {
|
|
|
btn.disabled = false;
|
|
|
btn.innerHTML = '⚡ ANALYZE NOW';
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
addSignal(signal) {
|
|
|
this.signals.unshift(signal);
|
|
|
if (this.signals.length > CONFIG.maxSignals) {
|
|
|
this.signals = this.signals.slice(0, CONFIG.maxSignals);
|
|
|
}
|
|
|
|
|
|
this.renderSignals();
|
|
|
document.getElementById('total-signals').textContent = this.signals.length;
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
renderSignals() {
|
|
|
const container = document.getElementById('signals-container');
|
|
|
if (!container) return;
|
|
|
|
|
|
if (this.signals.length === 0) {
|
|
|
container.innerHTML = `
|
|
|
<div class="empty-state">
|
|
|
<div class="empty-icon">📡</div>
|
|
|
<div class="empty-text">No signals yet</div>
|
|
|
<div class="empty-subtext">Start the agent or analyze manually</div>
|
|
|
</div>
|
|
|
`;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
container.innerHTML = this.signals.map((signal, index) => `
|
|
|
<div class="signal-card ${signal.signal}" ondblclick="window.ultimateSystem.openSignalModal(${index})" style="cursor: pointer;">
|
|
|
<div class="signal-header">
|
|
|
<div class="signal-left">
|
|
|
<span class="signal-badge ${signal.signal}">
|
|
|
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor">
|
|
|
${signal.signal === 'buy' ?
|
|
|
'<polyline points="18 15 12 9 6 15"/>' :
|
|
|
'<polyline points="6 9 12 15 18 9"/>'}
|
|
|
</svg>
|
|
|
${signal.signal.toUpperCase()}
|
|
|
</span>
|
|
|
<span class="signal-symbol">${signal.symbol}</span>
|
|
|
</div>
|
|
|
<div class="signal-time">
|
|
|
<svg viewBox="0 0 24 24">
|
|
|
<circle cx="12" cy="12" r="10"/>
|
|
|
<polyline points="12 6 12 12 16 14"/>
|
|
|
</svg>
|
|
|
${signal.timestamp.toLocaleTimeString()}
|
|
|
</div>
|
|
|
</div>
|
|
|
<div class="signal-body">
|
|
|
<div class="signal-item">
|
|
|
<div class="signal-item-label">
|
|
|
<svg viewBox="0 0 24 24">
|
|
|
<line x1="12" y1="1" x2="12" y2="23"/>
|
|
|
<path d="M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/>
|
|
|
</svg>
|
|
|
Entry Price
|
|
|
</div>
|
|
|
<div class="signal-item-value value-price">${this.formatPrice(signal.price)}</div>
|
|
|
</div>
|
|
|
<div class="signal-item">
|
|
|
<div class="signal-item-label">
|
|
|
<svg viewBox="0 0 24 24">
|
|
|
<circle cx="12" cy="12" r="10"/>
|
|
|
</svg>
|
|
|
Confidence
|
|
|
</div>
|
|
|
<div class="signal-item-value value-confidence">${signal.confidence.toFixed(0)}%</div>
|
|
|
</div>
|
|
|
<div class="signal-item">
|
|
|
<div class="signal-item-label">
|
|
|
<svg viewBox="0 0 24 24">
|
|
|
<path d="M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z"/>
|
|
|
</svg>
|
|
|
Stop Loss
|
|
|
</div>
|
|
|
<div class="signal-item-value value-stop">${this.formatPrice(signal.stopLoss)}</div>
|
|
|
</div>
|
|
|
<div class="signal-item">
|
|
|
<div class="signal-item-label">
|
|
|
<svg viewBox="0 0 24 24">
|
|
|
<polyline points="22 7 13.5 15.5 8.5 10.5 2 17"/>
|
|
|
</svg>
|
|
|
Take Profit
|
|
|
</div>
|
|
|
<div class="signal-item-value value-target">${this.formatPrice(signal.takeProfit)}</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
</div>
|
|
|
`).join('');
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
async refresh() {
|
|
|
this.showToast('🔄 Refreshing...', 'info');
|
|
|
await this.loadPrices();
|
|
|
this.showToast('✅ Refreshed!', 'success');
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
updateTime() {
|
|
|
const now = new Date();
|
|
|
document.getElementById('last-update').textContent = now.toLocaleTimeString();
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
openCryptoModal(symbol) {
|
|
|
const crypto = CRYPTOS.find(c => c.symbol === symbol);
|
|
|
const priceData = this.prices[symbol];
|
|
|
|
|
|
if (!crypto || !priceData) return;
|
|
|
|
|
|
document.getElementById('crypto-modal-title').textContent = `${crypto.name} (${symbol})`;
|
|
|
document.getElementById('modal-price').textContent = this.formatPrice(priceData.price);
|
|
|
|
|
|
const changeEl = document.getElementById('modal-change');
|
|
|
changeEl.textContent = priceData.change >= 0 ? `+${priceData.change.toFixed(2)}%` : `${priceData.change.toFixed(2)}%`;
|
|
|
changeEl.className = `info-value ${priceData.change >= 0 ? 'success' : 'danger'}`;
|
|
|
|
|
|
|
|
|
document.getElementById('modal-high').textContent = this.formatPrice(priceData.price * 1.02);
|
|
|
document.getElementById('modal-low').textContent = this.formatPrice(priceData.price * 0.98);
|
|
|
document.getElementById('modal-volume').textContent = '$' + (Math.random() * 50 + 10).toFixed(1) + 'B';
|
|
|
document.getElementById('modal-mcap').textContent = '$' + (Math.random() * 1000 + 100).toFixed(0) + 'B';
|
|
|
document.getElementById('modal-rsi').textContent = (Math.random() * 40 + 40).toFixed(1);
|
|
|
document.getElementById('modal-macd').textContent = Math.random() > 0.5 ? 'Bullish' : 'Bearish';
|
|
|
document.getElementById('modal-ema').textContent = this.formatPrice(priceData.price * 0.97);
|
|
|
document.getElementById('modal-support').textContent = this.formatPrice(priceData.price * 0.96);
|
|
|
document.getElementById('modal-resistance').textContent = this.formatPrice(priceData.price * 1.04);
|
|
|
|
|
|
window.openModal('crypto-modal');
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
openStrategyModal(strategyKey) {
|
|
|
const strategy = STRATEGIES[strategyKey];
|
|
|
if (!strategy) return;
|
|
|
|
|
|
document.getElementById('strategy-modal-title').textContent = strategy.name;
|
|
|
document.getElementById('modal-success-rate').textContent = strategy.accuracy;
|
|
|
document.getElementById('modal-timeframe').textContent = strategy.timeframe;
|
|
|
document.getElementById('modal-risk').textContent = strategyKey === 'hts-hybrid' ? 'Medium' : 'Low-Medium';
|
|
|
document.getElementById('modal-return').textContent = '+' + (Math.random() * 20 + 5).toFixed(1) + '%';
|
|
|
document.getElementById('strategy-description').textContent = strategy.description;
|
|
|
|
|
|
window.openModal('strategy-modal');
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
openSignalModal(index) {
|
|
|
const signal = this.signals[index];
|
|
|
if (!signal) return;
|
|
|
|
|
|
document.getElementById('signal-modal-title').textContent = `${signal.symbol} ${signal.signal.toUpperCase()} Signal`;
|
|
|
|
|
|
const typeEl = document.getElementById('signal-type');
|
|
|
typeEl.textContent = signal.signal.toUpperCase();
|
|
|
typeEl.className = `info-value ${signal.signal === 'buy' ? 'success' : 'danger'}`;
|
|
|
|
|
|
document.getElementById('signal-confidence').textContent = signal.confidence.toFixed(0) + '%';
|
|
|
document.getElementById('signal-entry').textContent = this.formatPrice(signal.price);
|
|
|
document.getElementById('signal-sl').textContent = this.formatPrice(signal.stopLoss);
|
|
|
document.getElementById('signal-tp').textContent = this.formatPrice(signal.takeProfit);
|
|
|
|
|
|
const rr = Math.abs((signal.takeProfit - signal.price) / (signal.price - signal.stopLoss));
|
|
|
document.getElementById('signal-rr').textContent = `1:${rr.toFixed(1)}`;
|
|
|
|
|
|
window.openModal('signal-modal');
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
showToast(message, type = 'info') {
|
|
|
const container = document.getElementById('toast-container');
|
|
|
if (!container) return;
|
|
|
|
|
|
const icons = {
|
|
|
success: '✅',
|
|
|
error: '❌',
|
|
|
info: 'ℹ️',
|
|
|
warning: '⚠️'
|
|
|
};
|
|
|
|
|
|
const toast = document.createElement('div');
|
|
|
toast.className = 'toast';
|
|
|
toast.innerHTML = `
|
|
|
<div class="toast-content">
|
|
|
<div class="toast-icon">${icons[type]}</div>
|
|
|
<div class="toast-message">${message}</div>
|
|
|
</div>
|
|
|
`;
|
|
|
|
|
|
container.appendChild(toast);
|
|
|
|
|
|
setTimeout(() => {
|
|
|
toast.style.animation = 'slideInRight 0.3s ease-out reverse';
|
|
|
setTimeout(() => toast.remove(), 300);
|
|
|
}, 3000);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
|
const system = new UltimateTradingSystem();
|
|
|
system.init();
|
|
|
window.ultimateSystem = system;
|
|
|
});
|
|
|
|
|
|
|