Implement multi-timeframe support for indicators

- Enhanced the `UserIndicator` class to include an optional `timeframe` attribute for custom indicator timeframes.
- Updated the `get_indicator_data` method in `MarketDataIntegrator` to fetch and calculate indicators based on the specified timeframe, ensuring proper data alignment and handling.
- Modified the `ChartBuilder` to pass the correct DataFrame for plotting indicators with different timeframes.
- Added UI elements in the indicator modal for selecting timeframes, improving user experience.
- Updated relevant JSON templates to include the new `timeframe` field for all indicators.
- Refactored the `prepare_chart_data` function to ensure it returns a DataFrame with a `DatetimeIndex` for consistent calculations.

This commit enhances the flexibility and usability of the indicator system, allowing users to analyze data across various timeframes.
This commit is contained in:
Vasily.onl
2025-06-06 15:06:17 +08:00
parent 58a754414a
commit b49e39dcb4
19 changed files with 417 additions and 247 deletions

View File

@@ -562,21 +562,28 @@ def get_market_statistics(df: pd.DataFrame, symbol: str, timeframe: str) -> html
"""
Generate a comprehensive market statistics component from a DataFrame.
"""
if df.empty:
return html.Div("No data available for statistics.", className="text-center text-muted")
try:
volume_analyzer = VolumeAnalyzer()
# Get statistics
price_analyzer = PriceMovementAnalyzer()
volume_analyzer = VolumeAnalyzer()
volume_stats = volume_analyzer.get_volume_statistics(df)
price_stats = price_analyzer.get_price_movement_statistics(df)
volume_stats = volume_analyzer.get_volume_statistics(df)
if 'error' in volume_stats or 'error' in price_stats:
error_msg = volume_stats.get('error') or price_stats.get('error')
# Format key statistics for display
start_date = df.index.min().strftime('%Y-%m-%d %H:%M')
end_date = df.index.max().strftime('%Y-%m-%d %H:%M')
# Check for errors from analyzers
if 'error' in price_stats or 'error' in volume_stats:
error_msg = price_stats.get('error') or volume_stats.get('error')
return html.Div(f"Error generating statistics: {error_msg}", style={'color': 'red'})
# Time range for display
start_date = df['timestamp'].min().strftime('%Y-%m-%d %H:%M')
end_date = df['timestamp'].max().strftime('%Y-%m-%d %H:%M')
days_back = (df['timestamp'].max() - df['timestamp'].min()).days
days_back = (df.index.max() - df.index.min()).days
time_status = f"📅 Analysis Range: {start_date} to {end_date} (~{days_back} days)"
return html.Div([

View File

@@ -33,6 +33,27 @@ def create_indicator_modal():
placeholder='Select indicator type',
), width=12)
], className="mb-3"),
dbc.Row([
dbc.Col(dbc.Label("Timeframe (Optional):"), width=12),
dbc.Col(dcc.Dropdown(
id='indicator-timeframe-dropdown',
options=[
{'label': 'Chart Timeframe', 'value': ''},
{'label': "1 Second", 'value': '1s'},
{'label': "5 Seconds", 'value': '5s'},
{'label': "15 Seconds", 'value': '15s'},
{'label': "30 Seconds", 'value': '30s'},
{'label': '1 Minute', 'value': '1m'},
{'label': '5 Minutes', 'value': '5m'},
{'label': '15 Minutes', 'value': '15m'},
{'label': '1 Hour', 'value': '1h'},
{'label': '4 Hours', 'value': '4h'},
{'label': '1 Day', 'value': '1d'},
],
value='',
placeholder='Defaults to chart timeframe'
), width=12),
], className="mb-3"),
dbc.Row([
dbc.Col(dbc.Label("Description (Optional):"), width=12),
dbc.Col(dcc.Textarea(