This commit is contained in:
Dobromir Popov
2025-11-22 19:46:28 +02:00
parent afc55b5208
commit cb0d307775
4 changed files with 87 additions and 51 deletions

View File

@@ -116,23 +116,46 @@
} }
}, },
{ {
"annotation_id": "bbafc50c-f885-4dbc-b0cb-fdfb48223b5c", "annotation_id": "cdf32bb9-8f0f-467d-abc2-d409a7c22bcc",
"symbol": "ETH/USDT", "symbol": "ETH/USDT",
"timeframe": "1m", "timeframe": "1m",
"entry": { "entry": {
"timestamp": "2025-11-12 07:58", "timestamp": "2025-11-22 06:41",
"price": 3424.58, "price": 2759.12,
"index": 284 "index": 250
}, },
"exit": { "exit": {
"timestamp": "2025-11-12 11:08", "timestamp": "2025-11-22 10:42",
"price": 3546.35, "price": 2709.14,
"index": 329 "index": 335
}, },
"direction": "LONG", "direction": "SHORT",
"profit_loss_pct": 3.5557645025083366, "profit_loss_pct": 1.8114471280698201,
"notes": "", "notes": "",
"created_at": "2025-11-12T13:11:31.267142", "created_at": "2025-11-22T13:09:16.675137",
"market_context": {
"entry_state": {},
"exit_state": {}
}
},
{
"annotation_id": "5cf94e70-e8f7-4c29-a860-4c2bc516bd8c",
"symbol": "ETH/USDT",
"timeframe": "1s",
"entry": {
"timestamp": "2025-11-22 11:00:30",
"price": 2714.28,
"index": 63
},
"exit": {
"timestamp": "2025-11-22 11:05:19",
"price": 2705.95,
"index": 90
},
"direction": "SHORT",
"profit_loss_pct": 0.30689538293766233,
"notes": "",
"created_at": "2025-11-22T13:09:40.711052",
"market_context": { "market_context": {
"entry_state": {}, "entry_state": {},
"exit_state": {} "exit_state": {}
@@ -140,7 +163,7 @@
} }
], ],
"metadata": { "metadata": {
"total_annotations": 6, "total_annotations": 7,
"last_updated": "2025-11-12T13:11:31.267456" "last_updated": "2025-11-22T13:09:40.712602"
} }
} }

View File

@@ -462,7 +462,7 @@ class ChartManager {
font: { color: '#f8f9fa', size: 11 }, font: { color: '#f8f9fa', size: 11 },
margin: { l: 60, r: 20, t: 10, b: 40 }, margin: { l: 60, r: 20, t: 10, b: 40 },
hovermode: 'x unified', hovermode: 'x unified',
dragmode: 'pan', dragmode: 'zoom', // Use zoom mode for better scroll behavior
// Performance optimizations // Performance optimizations
autosize: true, autosize: true,
staticPlot: false staticPlot: false
@@ -473,22 +473,22 @@ class ChartManager {
displayModeBar: true, displayModeBar: true,
modeBarButtonsToRemove: ['lasso2d', 'select2d'], // Allow autoScale2d modeBarButtonsToRemove: ['lasso2d', 'select2d'], // Allow autoScale2d
displaylogo: false, displaylogo: false,
scrollZoom: true, scrollZoom: true, // Enable mouse wheel zoom
// Enable vertical scaling by dragging Y-axis // Enable vertical scaling by dragging Y-axis
doubleClick: 'reset', // Double-click to reset zoom doubleClick: 'reset', // Double-click to reset zoom
showAxisDragHandles: true, // Show drag handles on axes showAxisDragHandles: true, // Show drag handles on axes
showAxisRangeEntryBoxes: true, // Allow manual range entry showAxisRangeEntryBoxes: true, // Allow manual range entry
// Axis drag behavior // Make pivot lines and annotations read-only
editable: true, // Make axes editable editable: false, // Disable editing to prevent dragging shapes
edits: { edits: {
axisTitleText: false, axisTitleText: false,
colorbarPosition: false, colorbarPosition: false,
colorbarTitleText: false, colorbarTitleText: false,
legendPosition: false, legendPosition: false,
legendText: false, legendText: false,
shapePosition: true, shapePosition: false, // Prevent dragging pivot lines
annotationPosition: true, annotationPosition: false, // Prevent dragging annotations
annotationTail: true, annotationTail: false,
annotationText: false annotationText: false
} }
}; };

View File

@@ -99,6 +99,12 @@
function renderAnnotationsList(annotations) { function renderAnnotationsList(annotations) {
const listContainer = document.getElementById('annotations-list'); const listContainer = document.getElementById('annotations-list');
const noAnnotationsMsg = document.getElementById('no-annotations-msg'); const noAnnotationsMsg = document.getElementById('no-annotations-msg');
const annotationCountEl = document.getElementById('annotation-count');
// Update count immediately
if (annotationCountEl) {
annotationCountEl.textContent = annotations.length;
}
if (annotations.length === 0) { if (annotations.length === 0) {
noAnnotationsMsg.style.display = 'block'; noAnnotationsMsg.style.display = 'block';
@@ -196,9 +202,6 @@
listContainer.appendChild(item); listContainer.appendChild(item);
}); });
// Update annotation count
document.getElementById('annotation-count').textContent = annotations.length;
} }
function viewAnnotation(annotation) { function viewAnnotation(annotation) {

View File

@@ -78,18 +78,20 @@
</select> </select>
</div> </div>
<button class="btn btn-success btn-sm w-100" id="start-inference-btn"> <div id="inference-buttons-container">
<i class="fas fa-play"></i> <button class="btn btn-success btn-sm w-100" id="start-inference-btn">
Start Live Inference (No Training) <i class="fas fa-play"></i>
</button> Start Live Inference (No Training)
<button class="btn btn-info btn-sm w-100 mt-1" id="start-inference-pivot-btn"> </button>
<i class="fas fa-chart-line"></i> <button class="btn btn-info btn-sm w-100 mt-1" id="start-inference-pivot-btn">
Live Inference + Pivot Training <i class="fas fa-chart-line"></i>
</button> Live Inference + Pivot Training
<button class="btn btn-primary btn-sm w-100 mt-1" id="start-inference-candle-btn"> </button>
<i class="fas fa-graduation-cap"></i> <button class="btn btn-primary btn-sm w-100 mt-1" id="start-inference-candle-btn">
Live Inference + Per-Candle Training <i class="fas fa-graduation-cap"></i>
</button> Live Inference + Per-Candle Training
</button>
</div>
<button class="btn btn-danger btn-sm w-100 mt-1" id="stop-inference-btn" style="display: none;"> <button class="btn btn-danger btn-sm w-100 mt-1" id="stop-inference-btn" style="display: none;">
<i class="fas fa-stop"></i> <i class="fas fa-stop"></i>
Stop Inference Stop Inference
@@ -294,18 +296,26 @@
} }
function updateButtonState() { function updateButtonState() {
const modelSelect = document.getElementById('model-select'); // Get UI elements
const trainBtn = document.getElementById('train-model-btn'); const ui = {
const loadBtn = document.getElementById('load-model-btn'); modelSelect: document.getElementById('model-select'),
const inferenceBtn = document.getElementById('start-inference-btn'); trainBtn: document.getElementById('train-model-btn'),
loadBtn: document.getElementById('load-model-btn'),
inferenceContainer: document.getElementById('inference-buttons-container')
};
selectedModel = modelSelect.value; selectedModel = ui.modelSelect.value;
// Helper to set all buttons in container
const setInferenceButtonsState = (disabled) => {
ui.inferenceContainer.querySelectorAll('button').forEach(btn => btn.disabled = disabled);
};
if (!selectedModel) { if (!selectedModel) {
// No model selected // No model selected - disable all inference buttons
trainBtn.style.display = 'none'; ui.trainBtn.style.display = 'none';
loadBtn.style.display = 'none'; ui.loadBtn.style.display = 'none';
inferenceBtn.disabled = true; setInferenceButtonsState(true);
return; return;
} }
@@ -313,15 +323,15 @@
const modelState = modelStates.find(m => m.name === selectedModel); const modelState = modelStates.find(m => m.name === selectedModel);
if (modelState && modelState.loaded) { if (modelState && modelState.loaded) {
// Model is loaded - show train/inference buttons // Model is loaded - enable all buttons
trainBtn.style.display = 'block'; ui.trainBtn.style.display = 'block';
loadBtn.style.display = 'none'; ui.loadBtn.style.display = 'none';
inferenceBtn.disabled = false; setInferenceButtonsState(false);
} else { } else {
// Model not loaded - show load button // Model not loaded - disable all inference buttons
trainBtn.style.display = 'none'; ui.trainBtn.style.display = 'none';
loadBtn.style.display = 'block'; ui.loadBtn.style.display = 'block';
inferenceBtn.disabled = true; setInferenceButtonsState(true);
} }
} }