candles wip

This commit is contained in:
Dobromir Popov
2025-11-22 18:46:44 +02:00
parent 4b93b6fd42
commit 44379ae2e4
2 changed files with 337 additions and 36 deletions

View File

@@ -141,12 +141,42 @@
<!-- Inference Status -->
<div id="inference-status" style="display: none;">
<div class="alert alert-success py-2 px-2 mb-2">
<div class="d-flex align-items-center mb-1">
<div class="spinner-border spinner-border-sm me-2" role="status">
<span class="visually-hidden">Running...</span>
<div class="d-flex align-items-center justify-content-between mb-1">
<div class="d-flex align-items-center">
<div class="spinner-border spinner-border-sm me-2" role="status">
<span class="visually-hidden">Running...</span>
</div>
<strong class="small">🔴 LIVE</strong>
</div>
<!-- Model Performance -->
<div class="small text-end">
<div style="font-size: 0.65rem;">Acc: <span id="live-accuracy" class="fw-bold text-success">--</span></div>
<div style="font-size: 0.65rem;">Loss: <span id="live-loss" class="fw-bold text-warning">--</span></div>
</div>
<strong class="small">🔴 LIVE</strong>
</div>
<!-- Position & PnL Status -->
<div class="mb-2 p-2" style="background-color: rgba(0,0,0,0.1); border-radius: 4px;">
<div class="small">
<div class="d-flex justify-content-between">
<span>Position:</span>
<span id="position-status" class="fw-bold text-info">NO POSITION</span>
</div>
<div class="d-flex justify-content-between" id="floating-pnl-row" style="display: none !important;">
<span>Floating PnL:</span>
<span id="floating-pnl" class="fw-bold">--</span>
</div>
<div class="d-flex justify-content-between">
<span>Session PnL:</span>
<span id="session-pnl" class="fw-bold text-success">+$0.00</span>
</div>
<div class="d-flex justify-content-between" style="font-size: 0.7rem; color: #9ca3af;">
<span>Win Rate:</span>
<span id="win-rate">0% (0/0)</span>
</div>
</div>
</div>
<div class="small">
<div>Timeframe: <span id="active-timeframe" class="fw-bold text-primary">--</span></div>
<div>Signal: <span id="latest-signal" class="fw-bold">--</span></div>
@@ -285,6 +315,36 @@
console.log(`✓ Models available: ${data.available_count}, loaded: ${data.loaded_count}`);
// Auto-select Transformer (or any loaded model) if available
let modelToSelect = null;
// First try to find Transformer
const transformerModel = data.models.find(m => {
const modelName = (m && typeof m === 'object' && m.name) ? m.name : String(m);
const isLoaded = (m && typeof m === 'object' && 'loaded' in m) ? m.loaded : false;
return modelName === 'Transformer' && isLoaded;
});
if (transformerModel) {
modelToSelect = 'Transformer';
} else {
// If Transformer not loaded, find any loaded model
const loadedModel = data.models.find(m => {
const isLoaded = (m && typeof m === 'object' && 'loaded' in m) ? m.loaded : false;
return isLoaded;
});
if (loadedModel) {
const modelName = (loadedModel && typeof loadedModel === 'object' && loadedModel.name) ? loadedModel.name : String(loadedModel);
modelToSelect = modelName;
}
}
// Auto-select if found
if (modelToSelect) {
modelSelect.value = modelToSelect;
selectedModel = modelToSelect;
console.log(`✓ Auto-selected loaded model: ${modelToSelect}`);
}
// Update button state for currently selected model
updateButtonState();
} else {
@@ -988,6 +1048,70 @@
}
}
function updatePositionStateDisplay(positionState, sessionMetrics) {
/**
* Update live trading panel with current position and PnL info
*/
try {
// Update position status
const positionStatusEl = document.getElementById('position-status');
const floatingPnlRow = document.getElementById('floating-pnl-row');
const floatingPnlEl = document.getElementById('floating-pnl');
if (positionState.has_position) {
const posType = positionState.position_type.toUpperCase();
const entryPrice = positionState.entry_price.toFixed(2);
positionStatusEl.textContent = `${posType} @ $${entryPrice}`;
positionStatusEl.className = posType === 'LONG' ? 'fw-bold text-success' : 'fw-bold text-danger';
// Show floating PnL
if (floatingPnlRow) {
floatingPnlRow.style.display = 'flex !important';
floatingPnlRow.classList.remove('d-none');
}
const unrealizedPnl = positionState.unrealized_pnl || 0;
const pnlColor = unrealizedPnl >= 0 ? 'text-success' : 'text-danger';
const pnlSign = unrealizedPnl >= 0 ? '+' : '';
floatingPnlEl.textContent = `${pnlSign}${unrealizedPnl.toFixed(2)}%`;
floatingPnlEl.className = `fw-bold ${pnlColor}`;
} else {
positionStatusEl.textContent = 'NO POSITION';
positionStatusEl.className = 'fw-bold text-secondary';
// Hide floating PnL row
if (floatingPnlRow) {
floatingPnlRow.style.display = 'none !important';
floatingPnlRow.classList.add('d-none');
}
}
// Update session PnL
const sessionPnlEl = document.getElementById('session-pnl');
if (sessionPnlEl && sessionMetrics) {
const totalPnl = sessionMetrics.total_pnl || 0;
const pnlColor = totalPnl >= 0 ? 'text-success' : 'text-danger';
const pnlSign = totalPnl >= 0 ? '+' : '';
sessionPnlEl.textContent = `${pnlSign}$${totalPnl.toFixed(2)}`;
sessionPnlEl.className = `fw-bold ${pnlColor}`;
// Update win rate
const winRateEl = document.getElementById('win-rate');
if (winRateEl) {
const winRate = sessionMetrics.win_rate || 0;
const winCount = sessionMetrics.win_count || 0;
const totalTrades = sessionMetrics.total_trades || 0;
winRateEl.textContent = `${winRate.toFixed(1)}% (${winCount}/${totalTrades})`;
}
}
} catch (error) {
console.error('Error updating position state display:', error);
}
}
// Make function globally accessible for WebSocket handler
window.updatePositionStateDisplay = updatePositionStateDisplay;
function updatePredictionHistory() {
const historyDiv = document.getElementById('prediction-history');
if (predictionHistory.length === 0) {