`;
document.body.appendChild(modal);
- // Close on overlay click
- modal.addEventListener('click', (e) => {
- if (e.target === modal) {
- modal.remove();
- }
- });
+ // Make it draggable
+ if (window.UI && window.UI.dragElement) {
+ window.UI.dragElement(modal, 'public_strategy_header');
+ }
}
}
diff --git a/src/static/backtesting.js b/src/static/backtesting.js
index 27e29d0..8e6e058 100644
--- a/src/static/backtesting.js
+++ b/src/static/backtesting.js
@@ -470,15 +470,41 @@ class Backtesting {
let html = '';
for (const test of this.tests) {
const statusClass = test.status || 'default'; // Use the status or fallback to 'default'
+ const symbol = this.getBacktestSymbol(statusClass);
+ const statusText = this.getStatusText(statusClass);
html += `
-
-
${test.name}
+
+
+ ${symbol}
+
+
${test.name}
+
${statusText}
`;
}
this.backtestDisplay.innerHTML = html;
}
+ getBacktestSymbol(status) {
+ const symbols = {
+ 'running': '⏳',
+ 'complete': '✅',
+ 'error': '❌',
+ 'default': '🧪'
+ };
+ return symbols[status] || symbols['default'];
+ }
+
+ getStatusText(status) {
+ const texts = {
+ 'running': 'Running',
+ 'complete': 'Complete',
+ 'error': 'Error',
+ 'default': 'Ready'
+ };
+ return texts[status] || texts['default'];
+ }
+
openTestDialog(testName) {
const test = this.tests.find(t => t.name === testName);
if (!test) {
diff --git a/src/static/general.js b/src/static/general.js
index f8f4314..5d62a28 100644
--- a/src/static/general.js
+++ b/src/static/general.js
@@ -35,6 +35,7 @@ class User_Interface {
this.initializeResizablePopup("new_sig_form", null, "signal_draggable_header", "resize-signal");
this.initializeResizablePopup("new_signal_type_form", null, "signal_type_draggable_header", "resize-signal-type");
this.initializeResizablePopup("external_indicator_form", null, "external_indicator_header", "resize-external-indicator");
+ this.initializeResizablePopup("edit_indicator_form", null, "edit_indicator_header", null);
this.initializeResizablePopup("new_trade_form", null, "trade_draggable_header", "resize-trade");
this.initializeResizablePopup("ai_strategy_form", null, "ai_strategy_header", "resize-ai-strategy");
diff --git a/src/static/indicators.js b/src/static/indicators.js
index b18ec14..38f3939 100644
--- a/src/static/indicators.js
+++ b/src/static/indicators.js
@@ -706,6 +706,10 @@ class Indicators {
// Contains instantiated indicators.
this.i_objs = {};
this.comms = comms;
+ // Store indicator configurations for editing
+ this.indicators = {};
+ // Store indicator data (values) for card display
+ this.indicator_data = {};
}
create_indicators(indicators, charts) {
@@ -766,6 +770,16 @@ class Indicators {
// Always set up the visibility form event handler
this._setupIndicatorForm();
+ // Store indicator configurations for card rendering and editing
+ if (idata.indicators) {
+ this.indicators = idata.indicators;
+ }
+
+ // Store indicator data (values) for card display
+ if (idata.indicator_data) {
+ this.indicator_data = idata.indicator_data;
+ }
+
if (idata.indicators && Object.keys(idata.indicators).length > 0) {
this.create_indicators(idata.indicators, charts);
// Initialize each indicator with the data directly
@@ -777,6 +791,9 @@ class Indicators {
} else {
console.log('No indicators defined for this user.');
}
+
+ // Render indicator cards in the UI (after init so values are available)
+ this.renderIndicators();
}
_setupIndicatorForm(){
@@ -807,12 +824,39 @@ class Indicators {
if (window.UI.indicators.i_objs[name]) {
// Use init() to refresh with full data on candle close
window.UI.indicators.i_objs[name].init(updates[name]);
+
+ // Update stored data and card display
+ this.indicator_data[name] = updates[name];
+ this._updateCardValue(name, updates[name]);
} else {
console.warn(`Indicator "${name}" not found in i_objs, skipping update`);
}
}
}
+ /**
+ * Updates a single indicator card's displayed value
+ */
+ _updateCardValue(name, data) {
+ const valueEl = document.getElementById(`indicator_card_value_${name}`);
+ if (!valueEl) return;
+
+ let displayValue = '--';
+ if (data && Array.isArray(data) && data.length > 0) {
+ const lastPoint = data[data.length - 1];
+ if (lastPoint.value !== undefined && lastPoint.value !== null) {
+ displayValue = this._formatValue(lastPoint.value);
+ } else if (lastPoint.macd !== undefined) {
+ displayValue = this._formatValue(lastPoint.macd);
+ } else if (lastPoint.middle !== undefined) {
+ displayValue = this._formatValue(lastPoint.middle);
+ } else if (lastPoint.upper !== undefined) {
+ displayValue = this._formatValue(lastPoint.upper);
+ }
+ }
+ valueEl.textContent = displayValue;
+ }
+
deleteIndicator(indicator, event) {
this.comms.deleteIndicator(indicator).then(response => {
if (response.success) {
@@ -1110,4 +1154,326 @@ class Indicators {
});
}
+ // ==================== Card Display Methods ====================
+
+ /**
+ * Renders all indicators as icon cards in the indicators_list container
+ */
+ renderIndicators() {
+ const container = document.getElementById('indicators_list');
+ if (!container) return;
+
+ container.innerHTML = '';
+
+ for (const [name, indicator] of Object.entries(this.indicators)) {
+ const item = document.createElement('div');
+ const isVisible = indicator.visible !== false;
+ item.className = `indicator-item ${isVisible ? 'visible' : 'hidden'}`;
+ item.setAttribute('data-indicator-name', name);
+
+ // Get indicator type symbol
+ const symbol = this.getIndicatorSymbol(indicator.type);
+
+ // Get current value from indicator_data
+ let displayValue = '--';
+ const data = this.indicator_data[name];
+ if (data && Array.isArray(data) && data.length > 0) {
+ const lastPoint = data[data.length - 1];
+ // Handle different indicator data formats
+ if (lastPoint.value !== undefined && lastPoint.value !== null) {
+ // Simple indicators (RSI, SMA, EMA, etc.)
+ displayValue = this._formatValue(lastPoint.value);
+ } else if (lastPoint.macd !== undefined) {
+ // MACD - show the MACD value
+ displayValue = this._formatValue(lastPoint.macd);
+ } else if (lastPoint.middle !== undefined) {
+ // Bollinger Bands - show middle value
+ displayValue = this._formatValue(lastPoint.middle);
+ } else if (lastPoint.upper !== undefined) {
+ // Other band indicators
+ displayValue = this._formatValue(lastPoint.upper);
+ }
+ }
+
+ const indicatorType = indicator.type || 'Unknown';
+ item.innerHTML = `
+
+
+