Update OKX configuration and aggregation logic for enhanced multi-timeframe support

- Increased health check interval from 30s to 120s in `okx_config.json`.
- Added support for additional timeframes (1s, 5s, 10s, 15s, 30s) in the aggregation logic across multiple components.
- Updated `CandleProcessingConfig` and `RealTimeCandleProcessor` to handle new timeframes.
- Enhanced validation and parsing functions to include new second-based timeframes.
- Updated database schema to support new timeframes in `schema_clean.sql`.
- Improved documentation to reflect changes in multi-timeframe aggregation capabilities.
This commit is contained in:
Vasily.onl
2025-06-02 12:35:19 +08:00
parent cecb5fd411
commit 02a51521a0
9 changed files with 964 additions and 374 deletions

View File

@@ -133,7 +133,17 @@ class TimeframeBucket:
def _calculate_end_time(self, start_time: datetime, timeframe: str) -> datetime:
"""Calculate end time for this timeframe (right-aligned timestamp)."""
if timeframe == '1m':
if timeframe == '1s':
return start_time + timedelta(seconds=1)
elif timeframe == '5s':
return start_time + timedelta(seconds=5)
elif timeframe == '10s':
return start_time + timedelta(seconds=10)
elif timeframe == '15s':
return start_time + timedelta(seconds=15)
elif timeframe == '30s':
return start_time + timedelta(seconds=30)
elif timeframe == '1m':
return start_time + timedelta(minutes=1)
elif timeframe == '5m':
return start_time + timedelta(minutes=5)
@@ -314,6 +324,10 @@ class RealTimeCandleProcessor:
The start time is the LEFT boundary of the interval.
EXAMPLES:
- Trade at 09:03:45.123 for 1s timeframe -> bucket start = 09:03:45.000
- Trade at 09:03:47.456 for 5s timeframe -> bucket start = 09:03:45.000 (45-50s bucket)
- Trade at 09:03:52.789 for 10s timeframe -> bucket start = 09:03:50.000 (50-60s bucket)
- Trade at 09:03:23.456 for 15s timeframe -> bucket start = 09:03:15.000 (15-30s bucket)
- Trade at 09:03:45 for 5m timeframe -> bucket start = 09:00:00
- Trade at 09:07:23 for 5m timeframe -> bucket start = 09:05:00
- Trade at 14:00:00 for 1h timeframe -> bucket start = 14:00:00
@@ -325,6 +339,26 @@ class RealTimeCandleProcessor:
Returns:
Bucket start time (left boundary)
"""
if timeframe == '1s':
# 1-second buckets align to second boundaries (remove microseconds)
return timestamp.replace(microsecond=0)
elif timeframe == '5s':
# 5-second buckets: 00:00, 00:05, 00:10, 00:15, etc.
dt = timestamp.replace(microsecond=0)
return dt.replace(second=(dt.second // 5) * 5)
elif timeframe == '10s':
# 10-second buckets: 00:00, 00:10, 00:20, 00:30, 00:40, 00:50
dt = timestamp.replace(microsecond=0)
return dt.replace(second=(dt.second // 10) * 10)
elif timeframe == '15s':
# 15-second buckets: 00:00, 00:15, 00:30, 00:45
dt = timestamp.replace(microsecond=0)
return dt.replace(second=(dt.second // 15) * 15)
elif timeframe == '30s':
# 30-second buckets: 00:00, 00:30
dt = timestamp.replace(microsecond=0)
return dt.replace(second=(dt.second // 30) * 30)
# Normalize to UTC and remove microseconds for clean boundaries
dt = timestamp.replace(second=0, microsecond=0)
@@ -519,12 +553,12 @@ def validate_timeframe(timeframe: str) -> bool:
Validate if timeframe is supported.
Args:
timeframe: Timeframe string (e.g., '1m', '5m', '1h')
timeframe: Timeframe string (e.g., '1s', '5s', '10s', '1m', '5m', '1h')
Returns:
True if supported, False otherwise
"""
supported = ['1m', '5m', '15m', '30m', '1h', '4h', '1d']
supported = ['1s', '5s', '10s', '15s', '30s', '1m', '5m', '15m', '30m', '1h', '4h', '1d']
return timeframe in supported
@@ -533,18 +567,19 @@ def parse_timeframe(timeframe: str) -> tuple[int, str]:
Parse timeframe string into number and unit.
Args:
timeframe: Timeframe string (e.g., '5m', '1h')
timeframe: Timeframe string (e.g., '1s', '5m', '1h')
Returns:
Tuple of (number, unit)
Examples:
'1s' -> (1, 's')
'5m' -> (5, 'm')
'1h' -> (1, 'h')
'1d' -> (1, 'd')
"""
import re
match = re.match(r'^(\d+)([mhd])$', timeframe.lower())
match = re.match(r'^(\d+)([smhd])$', timeframe.lower())
if not match:
raise ValueError(f"Invalid timeframe format: {timeframe}")

View File

@@ -118,14 +118,14 @@ class OHLCVCandle:
@dataclass
class CandleProcessingConfig:
"""Configuration for candle processing - shared across exchanges."""
timeframes: List[str] = field(default_factory=lambda: ['1m', '5m', '15m', '1h'])
timeframes: List[str] = field(default_factory=lambda: ['1s', '5s', '1m', '5m', '15m', '1h'])
auto_save_candles: bool = True
emit_incomplete_candles: bool = False
max_trades_per_candle: int = 100000 # Safety limit
def __post_init__(self):
"""Validate configuration after initialization."""
supported_timeframes = ['1m', '5m', '15m', '30m', '1h', '4h', '1d']
supported_timeframes = ['1s', '5s', '10s', '15s', '30s', '1m', '5m', '15m', '30m', '1h', '4h', '1d']
for tf in self.timeframes:
if tf not in supported_timeframes:
raise ValueError(f"Unsupported timeframe: {tf}")
@@ -139,6 +139,7 @@ class TradeSide(Enum):
class TimeframeUnit(Enum):
"""Time units for candle timeframes."""
SECOND = "s"
MINUTE = "m"
HOUR = "h"
DAY = "d"