fix template again

This commit is contained in:
Dobromir Popov
2025-10-24 23:26:59 +03:00
parent e9edf2c5f2
commit 86a579bea9
3 changed files with 238 additions and 5 deletions

View File

@@ -480,6 +480,51 @@ class AnnotationDashboard:
</html>
"""
@self.server.route('/api/recalculate-pivots', methods=['POST'])
def recalculate_pivots():
"""Recalculate pivot points for merged data"""
try:
data = request.get_json()
symbol = data.get('symbol', 'ETH/USDT')
timeframe = data.get('timeframe')
timestamps = data.get('timestamps', [])
ohlcv_data = data.get('ohlcv', {})
if not timeframe or not timestamps:
return jsonify({
'success': False,
'error': {'code': 'INVALID_REQUEST', 'message': 'Missing timeframe or timestamps'}
})
logger.info(f"🔄 Recalculating pivots for {symbol} {timeframe} with {len(timestamps)} candles")
# Convert to DataFrame
df = pd.DataFrame({
'open': ohlcv_data.get('open', []),
'high': ohlcv_data.get('high', []),
'low': ohlcv_data.get('low', []),
'close': ohlcv_data.get('close', []),
'volume': ohlcv_data.get('volume', [])
})
df.index = pd.to_datetime(timestamps)
# Recalculate pivot markers
pivot_markers = self._get_pivot_markers_for_timeframe(symbol, timeframe, df)
logger.info(f" ✅ Recalculated {len(pivot_markers)} pivot candles")
return jsonify({
'success': True,
'pivot_markers': pivot_markers
})
except Exception as e:
logger.error(f"Error recalculating pivots: {e}")
return jsonify({
'success': False,
'error': {'code': 'RECALC_ERROR', 'message': str(e)}
})
@self.server.route('/api/chart-data', methods=['POST'])
def get_chart_data():
"""Get chart data for specified symbol and timeframes with infinite scroll support"""
@@ -489,9 +534,15 @@ class AnnotationDashboard:
timeframes = data.get('timeframes', ['1s', '1m', '1h', '1d'])
start_time_str = data.get('start_time')
end_time_str = data.get('end_time')
limit = data.get('limit', 500) # Allow client to request more data
limit = data.get('limit', 2000) # Default 2000 candles for training
direction = data.get('direction', 'latest') # 'latest', 'before', or 'after'
logger.info(f"📊 Chart data request: {symbol} {timeframes} direction={direction} limit={limit}")
if start_time_str:
logger.info(f" start_time: {start_time_str}")
if end_time_str:
logger.info(f" end_time: {end_time_str}")
if not self.data_loader:
return jsonify({
'success': False,
@@ -522,6 +573,8 @@ class AnnotationDashboard:
)
if df is not None and not df.empty:
logger.info(f"{timeframe}: {len(df)} candles ({df.index[0]} to {df.index[-1]})")
# Get pivot points for this timeframe
pivot_markers = self._get_pivot_markers_for_timeframe(symbol, timeframe, df)
@@ -535,6 +588,8 @@ class AnnotationDashboard:
'volume': df['volume'].tolist(),
'pivot_markers': pivot_markers # Optional: only present if pivots exist
}
else:
logger.warning(f"{timeframe}: No data returned")
# Get pivot bounds for the symbol
pivot_bounds = None

View File

@@ -1190,6 +1190,14 @@ class ChartManager {
const result = await response.json();
console.log(`📊 API Response for ${timeframe} ${direction}:`, {
success: result.success,
hasChartData: !!result.chart_data,
hasTimeframeData: result.chart_data ? !!result.chart_data[timeframe] : false,
dataLength: result.chart_data && result.chart_data[timeframe] ? result.chart_data[timeframe].timestamps.length : 0,
error: result.error
});
if (result.success && result.chart_data && result.chart_data[timeframe]) {
const newData = result.chart_data[timeframe];
@@ -1200,13 +1208,18 @@ class ChartManager {
return;
}
// Log data ranges for debugging
console.log(`📥 New data: ${newData.timestamps[0]} to ${newData.timestamps[newData.timestamps.length - 1]}`);
console.log(`📦 Existing: ${chart.data.timestamps[0]} to ${chart.data.timestamps[chart.data.timestamps.length - 1]}`);
// Merge with existing data
this.mergeChartData(timeframe, newData, direction);
console.log(`Loaded ${newData.timestamps.length} new candles for ${timeframe}`);
console.log(`Loaded ${newData.timestamps.length} new candles for ${timeframe}`);
window.showSuccess(`Loaded ${newData.timestamps.length} more candles`);
} else {
console.warn(`No more data available for ${timeframe} ${direction}`);
console.warn(`No more data available for ${timeframe} ${direction}`);
console.warn('Full result:', result);
window.showWarning('No more historical data available');
}
@@ -1287,10 +1300,173 @@ class ChartManager {
// Update stored data
chart.data = mergedData;
// Recalculate pivot points for the merged data
this.recalculatePivots(timeframe, mergedData);
// Update the chart with merged data
this.updateSingleChart(timeframe, mergedData);
}
/**
* Recalculate pivot points for merged data
*/
async recalculatePivots(timeframe, data) {
try {
console.log(`🔄 Recalculating pivots for ${timeframe} with ${data.timestamps.length} candles...`);
const response = await fetch('/api/recalculate-pivots', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
symbol: window.appState?.currentSymbol || 'ETH/USDT',
timeframe: timeframe,
timestamps: data.timestamps,
ohlcv: {
open: data.open,
high: data.high,
low: data.low,
close: data.close,
volume: data.volume
}
})
});
const result = await response.json();
if (result.success && result.pivot_markers) {
// Update pivot markers in chart data
const chart = this.charts[timeframe];
if (chart && chart.data) {
chart.data.pivot_markers = result.pivot_markers;
console.log(`✅ Pivots recalculated: ${Object.keys(result.pivot_markers).length} pivot candles`);
// Redraw the chart with updated pivots
this.redrawChartWithPivots(timeframe, chart.data);
}
} else {
console.warn('Failed to recalculate pivots:', result.error);
}
} catch (error) {
console.error(`Error recalculating pivots for ${timeframe}:`, error);
}
}
/**
* Redraw chart with updated pivot markers
*/
redrawChartWithPivots(timeframe, data) {
const chart = this.charts[timeframe];
if (!chart) return;
// Build pivot shapes and annotations
const shapes = [];
const annotations = [];
const pivotDots = {
x: [], y: [], text: [],
marker: { color: [], size: [], symbol: [] },
mode: 'markers',
hoverinfo: 'text',
showlegend: false
};
if (data.pivot_markers && Object.keys(data.pivot_markers).length > 0) {
const xMin = data.timestamps[0];
const xMax = data.timestamps[data.timestamps.length - 1];
// Process each timestamp that has pivot markers
Object.entries(data.pivot_markers).forEach(([timestamp, pivots]) => {
// Process high pivots
if (pivots.highs && pivots.highs.length > 0) {
pivots.highs.forEach(pivot => {
const color = this._getPivotColor(pivot.level, 'high');
pivotDots.x.push(timestamp);
pivotDots.y.push(pivot.price);
pivotDots.text.push(`L${pivot.level} High Pivot<br>Price: ${pivot.price.toFixed(2)}<br>Strength: ${(pivot.strength * 100).toFixed(0)}%`);
pivotDots.marker.color.push(color);
pivotDots.marker.size.push(this._getPivotMarkerSize(pivot.level));
pivotDots.marker.symbol.push('triangle-down');
if (pivot.is_last) {
shapes.push({
type: 'line',
x0: xMin, y0: pivot.price,
x1: xMax, y1: pivot.price,
line: { color: color, width: 1, dash: 'dash' },
layer: 'below'
});
annotations.push({
x: xMax, y: pivot.price,
text: `L${pivot.level}H`,
showarrow: false,
xanchor: 'left',
font: { size: 9, color: color },
bgcolor: '#1f2937',
borderpad: 2
});
}
});
}
// Process low pivots
if (pivots.lows && pivots.lows.length > 0) {
pivots.lows.forEach(pivot => {
const color = this._getPivotColor(pivot.level, 'low');
pivotDots.x.push(timestamp);
pivotDots.y.push(pivot.price);
pivotDots.text.push(`L${pivot.level} Low Pivot<br>Price: ${pivot.price.toFixed(2)}<br>Strength: ${(pivot.strength * 100).toFixed(0)}%`);
pivotDots.marker.color.push(color);
pivotDots.marker.size.push(this._getPivotMarkerSize(pivot.level));
pivotDots.marker.symbol.push('triangle-up');
if (pivot.is_last) {
shapes.push({
type: 'line',
x0: xMin, y0: pivot.price,
x1: xMax, y1: pivot.price,
line: { color: color, width: 1, dash: 'dash' },
layer: 'below'
});
annotations.push({
x: xMax, y: pivot.price,
text: `L${pivot.level}L`,
showarrow: false,
xanchor: 'left',
font: { size: 9, color: color },
bgcolor: '#1f2937',
borderpad: 2
});
}
});
}
});
}
// Update chart layout with new pivots
Plotly.relayout(chart.plotId, {
shapes: shapes,
annotations: annotations
});
// Update pivot dots trace
if (pivotDots.x.length > 0) {
Plotly.restyle(chart.plotId, {
x: [pivotDots.x],
y: [pivotDots.y],
text: [pivotDots.text],
'marker.color': [pivotDots.marker.color],
'marker.size': [pivotDots.marker.size],
'marker.symbol': [pivotDots.marker.symbol]
}, [2]); // Trace index 2 is pivot dots
}
console.log(`🎨 Redrawn ${timeframe} chart with updated pivots`);
}
/**
* Update a single chart with new data
*/

View File

@@ -59,6 +59,7 @@
{% block extra_js %}
<script>
// Initialize application state
// IMPORTANT!!! DO NOT CHANGE {{ x }} to { { x } }
window.appState = {
currentSymbol: '{{ current_symbol }}',
currentTimeframes: {{ timeframes | tojson }},
@@ -97,7 +98,7 @@
function loadInitialData() {
console.log('Loading initial chart data...');
// Fetch initial chart data
// Fetch initial chart data with 2000 candles for training
fetch('/api/chart-data', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
@@ -105,7 +106,8 @@
symbol: appState.currentSymbol,
timeframes: appState.currentTimeframes,
start_time: null,
end_time: null
end_time: null,
limit: 2000 // Load 2000 candles initially for training
})
})
.then(response => {