pivots
This commit is contained in:
@ -34,6 +34,7 @@ from collections import deque
|
||||
from .config import get_config
|
||||
from .tick_aggregator import RealTimeTickAggregator, RawTick, OHLCVBar
|
||||
from .cnn_monitor import log_cnn_prediction
|
||||
from .williams_market_structure import WilliamsMarketStructure, PivotPoint, TrendLevel
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -182,6 +183,16 @@ class DataProvider:
|
||||
'1h': 3600, '4h': 14400, '1d': 86400
|
||||
}
|
||||
|
||||
# Williams Market Structure integration
|
||||
self.williams_structure: Dict[str, WilliamsMarketStructure] = {}
|
||||
for symbol in self.symbols:
|
||||
self.williams_structure[symbol] = WilliamsMarketStructure(min_pivot_distance=3)
|
||||
|
||||
# Pivot point caching
|
||||
self.pivot_points_cache: Dict[str, Dict[int, TrendLevel]] = {} # {symbol: {level: TrendLevel}}
|
||||
self.last_pivot_calculation: Dict[str, datetime] = {}
|
||||
self.pivot_calculation_interval = timedelta(minutes=5) # Recalculate every 5 minutes
|
||||
|
||||
# Load existing pivot bounds from cache
|
||||
self._load_all_pivot_bounds()
|
||||
|
||||
@ -189,6 +200,7 @@ class DataProvider:
|
||||
logger.info(f"Timeframes: {self.timeframes}")
|
||||
logger.info("Centralized data distribution enabled")
|
||||
logger.info("Pivot-based normalization system enabled")
|
||||
logger.info("Williams Market Structure integration enabled")
|
||||
|
||||
# Rate limiting
|
||||
self.last_request_time = {}
|
||||
@ -1613,6 +1625,151 @@ class DataProvider:
|
||||
logger.error(f"Error getting current price for {symbol}: {e}")
|
||||
return None
|
||||
|
||||
def calculate_williams_pivot_points(self, symbol: str, force_recalculate: bool = False) -> Dict[int, TrendLevel]:
|
||||
"""
|
||||
Calculate Williams Market Structure pivot points for a symbol
|
||||
|
||||
Args:
|
||||
symbol: Trading symbol (e.g., 'ETH/USDT')
|
||||
force_recalculate: Force recalculation even if cache is fresh
|
||||
|
||||
Returns:
|
||||
Dictionary of trend levels with pivot points
|
||||
"""
|
||||
try:
|
||||
# Check if we need to recalculate
|
||||
now = datetime.now()
|
||||
if (not force_recalculate and
|
||||
symbol in self.last_pivot_calculation and
|
||||
now - self.last_pivot_calculation[symbol] < self.pivot_calculation_interval):
|
||||
# Return cached results
|
||||
return self.pivot_points_cache.get(symbol, {})
|
||||
|
||||
# Get 1s OHLCV data for Williams Market Structure calculation
|
||||
df_1s = self.get_historical_data(symbol, '1s', limit=1000)
|
||||
if df_1s is None or len(df_1s) < 50:
|
||||
logger.warning(f"Insufficient 1s data for Williams pivot calculation: {symbol}")
|
||||
return {}
|
||||
|
||||
# Convert DataFrame to numpy array for Williams calculation
|
||||
# Format: [timestamp_ms, open, high, low, close, volume]
|
||||
ohlcv_array = np.column_stack([
|
||||
df_1s.index.astype(np.int64) // 10**6, # Convert to milliseconds
|
||||
df_1s['open'].values,
|
||||
df_1s['high'].values,
|
||||
df_1s['low'].values,
|
||||
df_1s['close'].values,
|
||||
df_1s['volume'].values
|
||||
])
|
||||
|
||||
# Calculate recursive pivot points using Williams Market Structure
|
||||
williams = self.williams_structure[symbol]
|
||||
pivot_levels = williams.calculate_recursive_pivot_points(ohlcv_array)
|
||||
|
||||
# Cache the results
|
||||
self.pivot_points_cache[symbol] = pivot_levels
|
||||
self.last_pivot_calculation[symbol] = now
|
||||
|
||||
logger.debug(f"Calculated Williams pivot points for {symbol}: {len(pivot_levels)} levels")
|
||||
return pivot_levels
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error calculating Williams pivot points for {symbol}: {e}")
|
||||
return {}
|
||||
|
||||
def get_pivot_features_for_ml(self, symbol: str) -> np.ndarray:
|
||||
"""
|
||||
Get pivot point features for machine learning models
|
||||
|
||||
Returns a 250-element feature vector containing:
|
||||
- Recent pivot points (price, strength, type) for each level
|
||||
- Trend direction and strength for each level
|
||||
- Time since last pivot for each level
|
||||
"""
|
||||
try:
|
||||
# Ensure we have fresh pivot points
|
||||
pivot_levels = self.calculate_williams_pivot_points(symbol)
|
||||
|
||||
if not pivot_levels:
|
||||
logger.warning(f"No pivot points available for {symbol}")
|
||||
return np.zeros(250, dtype=np.float32)
|
||||
|
||||
# Use Williams Market Structure to extract ML features
|
||||
williams = self.williams_structure[symbol]
|
||||
features = williams.get_pivot_features_for_ml(symbol)
|
||||
|
||||
return features
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting pivot features for ML: {e}")
|
||||
return np.zeros(250, dtype=np.float32)
|
||||
|
||||
def get_market_structure_summary(self, symbol: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Get current market structure summary for dashboard display
|
||||
|
||||
Returns:
|
||||
Dictionary containing market structure information
|
||||
"""
|
||||
try:
|
||||
# Ensure we have fresh pivot points
|
||||
pivot_levels = self.calculate_williams_pivot_points(symbol)
|
||||
|
||||
if not pivot_levels:
|
||||
return {
|
||||
'symbol': symbol,
|
||||
'levels': {},
|
||||
'overall_trend': 'sideways',
|
||||
'overall_strength': 0.0,
|
||||
'last_update': datetime.now().isoformat(),
|
||||
'error': 'No pivot points available'
|
||||
}
|
||||
|
||||
# Use Williams Market Structure to get summary
|
||||
williams = self.williams_structure[symbol]
|
||||
structure = williams.get_current_market_structure()
|
||||
structure['symbol'] = symbol
|
||||
|
||||
return structure
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting market structure summary for {symbol}: {e}")
|
||||
return {
|
||||
'symbol': symbol,
|
||||
'levels': {},
|
||||
'overall_trend': 'sideways',
|
||||
'overall_strength': 0.0,
|
||||
'last_update': datetime.now().isoformat(),
|
||||
'error': str(e)
|
||||
}
|
||||
|
||||
def get_recent_pivot_points(self, symbol: str, level: int = 1, count: int = 10) -> List[PivotPoint]:
|
||||
"""
|
||||
Get recent pivot points for a specific level
|
||||
|
||||
Args:
|
||||
symbol: Trading symbol
|
||||
level: Pivot level (1-5)
|
||||
count: Number of recent pivots to return
|
||||
|
||||
Returns:
|
||||
List of recent pivot points
|
||||
"""
|
||||
try:
|
||||
pivot_levels = self.calculate_williams_pivot_points(symbol)
|
||||
|
||||
if level not in pivot_levels:
|
||||
return []
|
||||
|
||||
trend_level = pivot_levels[level]
|
||||
recent_pivots = trend_level.pivot_points[-count:] if len(trend_level.pivot_points) >= count else trend_level.pivot_points
|
||||
|
||||
return recent_pivots
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting recent pivot points for {symbol} level {level}: {e}")
|
||||
return []
|
||||
|
||||
def get_price_at_index(self, symbol: str, index: int, timeframe: str = '1m') -> Optional[float]:
|
||||
"""Get price at specific index for backtesting"""
|
||||
try:
|
||||
|
Reference in New Issue
Block a user