Add signal markers on main chart with configurable shapes and colors

- Create signal-markers.js module to calculate crossover markers for indicators
- Add marker configuration options to indicator config panel:
  - Show/hide markers toggle
  - Buy/sell shape selection (built-in or custom Unicode)
  - Buy/sell color pickers
- Integrate markers with lightweight-charts using createSeriesMarkers API
- Markers recalculate when indicators change or historical data loads
This commit is contained in:
DiTus
2026-03-02 12:49:49 +01:00
parent d332748411
commit 9d7647fde5
3 changed files with 349 additions and 2 deletions

View File

@ -322,6 +322,61 @@ function renderIndicatorConfig(indicator, meta) {
</div>
` : ''}
<div class="config-section">
<div class="section-subtitle">Signals</div>
<div class="config-row">
<label>Show Markers</label>
<input type="checkbox" ${indicator.params.showMarkers !== false ? 'checked' : ''}
onchange="window.updateIndicatorSetting && window.updateIndicatorSetting('${indicator.id}', 'showMarkers', this.checked)">
</div>
<div class="config-row">
<label>Buy Shape</label>
<select onchange="window.updateIndicatorSetting && window.updateIndicatorSetting('${indicator.id}', 'markerBuyShape', this.value)">
<option value="arrowUp" ${indicator.params.markerBuyShape === 'arrowUp' || !indicator.params.markerBuyShape ? 'selected' : ''}>Arrow Up</option>
<option value="arrowDown" ${indicator.params.markerBuyShape === 'arrowDown' ? 'selected' : ''}>Arrow Down</option>
<option value="circle" ${indicator.params.markerBuyShape === 'circle' ? 'selected' : ''}>Circle</option>
<option value="square" ${indicator.params.markerBuyShape === 'square' ? 'selected' : ''}>Square</option>
<option value="triangleUp" ${indicator.params.markerBuyShape === 'triangleUp' ? 'selected' : ''}>Triangle Up</option>
<option value="triangleDown" ${indicator.params.markerBuyShape === 'triangleDown' ? 'selected' : ''}>Triangle Down</option>
<option value="custom" ${indicator.params.markerBuyShape === 'custom' ? 'selected' : ''}>Custom</option>
</select>
<input type="text" style="width: 60px; margin-left: 5px;" value="${indicator.params.markerBuyShape === 'custom' ? (indicator.params.markerBuyCustom || '') : ''}"
placeholder="◭"
onchange="window.updateIndicatorSetting && window.updateIndicatorSetting('${indicator.id}', 'markerBuyCustom', this.value)">
</div>
<div class="config-row">
<label>Buy Color</label>
<div class="color-picker">
<input type="color" id="markerBuyColor_${indicator.id}" value="${indicator.params.markerBuyColor || '#26a69a'}"
onchange="window.updateIndicatorSetting && window.updateIndicatorSetting('${indicator.id}', 'markerBuyColor', this.value)">
<span class="color-preview" style="background: ${indicator.params.markerBuyColor || '#26a69a'};"></span>
</div>
</div>
<div class="config-row">
<label>Sell Shape</label>
<select onchange="window.updateIndicatorSetting && window.updateIndicatorSetting('${indicator.id}', 'markerSellShape', this.value)">
<option value="arrowDown" ${indicator.params.markerSellShape === 'arrowDown' || !indicator.params.markerSellShape ? 'selected' : ''}>Arrow Down</option>
<option value="arrowUp" ${indicator.params.markerSellShape === 'arrowUp' ? 'selected' : ''}>Arrow Up</option>
<option value="circle" ${indicator.params.markerSellShape === 'circle' ? 'selected' : ''}>Circle</option>
<option value="square" ${indicator.params.markerSellShape === 'square' ? 'selected' : ''}>Square</option>
<option value="triangleUp" ${indicator.params.markerSellShape === 'triangleUp' ? 'selected' : ''}>Triangle Up</option>
<option value="triangleDown" ${indicator.params.markerSellShape === 'triangleDown' ? 'selected' : ''}>Triangle Down</option>
<option value="custom" ${indicator.params.markerSellShape === 'custom' ? 'selected' : ''}>Custom</option>
</select>
<input type="text" style="width: 60px; margin-left: 5px;" value="${indicator.params.markerSellShape === 'custom' ? (indicator.params.markerSellCustom || '') : ''}"
placeholder="▼"
onchange="window.updateIndicatorSetting && window.updateIndicatorSetting('${indicator.id}', 'markerSellCustom', this.value)">
</div>
<div class="config-row">
<label>Sell Color</label>
<div class="color-picker">
<input type="color" id="markerSellColor_${indicator.id}" value="${indicator.params.markerSellColor || '#ef5350'}"
onchange="window.updateIndicatorSetting && window.updateIndicatorSetting('${indicator.id}', 'markerSellColor', this.value)">
<span class="color-preview" style="background: ${indicator.params.markerSellColor || '#ef5350'};"></span>
</div>
</div>
</div>
<div class="config-section">
<div class="section-subtitle">
Presets
@ -633,7 +688,14 @@ function addIndicator(type) {
const params = {
_lineType: 'solid',
_lineWidth: 2
_lineWidth: 2,
showMarkers: true,
markerBuyShape: 'arrowUp',
markerBuyColor: '#26a69a',
markerBuyCustom: '◭',
markerSellShape: 'arrowDown',
markerSellColor: '#ef5350',
markerSellCustom: '▼'
};
metadata.plots.forEach((plot, idx) => {
params[`_color_${idx}`] = plot.color || getDefaultColor(activeIndicators.length + idx);
@ -966,6 +1028,11 @@ export function drawIndicatorsOnChart() {
} catch (error) {
console.error('[Indicators] Error drawing indicators:', error);
}
// Update signal markers after indicators are drawn
if (window.dashboard && typeof window.dashboard.updateSignalMarkers === 'function') {
window.dashboard.updateSignalMarkers();
}
}
function resetIndicator(id) {