use common williams market structure calcs

This commit is contained in:
Dobromir Popov
2025-10-24 12:30:17 +03:00
parent bd95ff610c
commit 42bf91b735
3 changed files with 260 additions and 162 deletions

View File

@@ -19,16 +19,19 @@ import logging
from datetime import datetime
import json
import pandas as pd
import numpy as np
# Import core components from main system
try:
from core.data_provider import DataProvider
from core.orchestrator import TradingOrchestrator
from core.config import get_config
from core.williams_market_structure import WilliamsMarketStructure
except ImportError as e:
print(f"Warning: Could not import main system components: {e}")
print("Running in standalone mode with limited functionality")
DataProvider = None
WilliamsMarketStructure = None
TradingOrchestrator = None
get_config = lambda: {}
@@ -200,66 +203,90 @@ class AnnotationDashboard:
def _get_pivot_markers_for_timeframe(self, symbol: str, timeframe: str, df: pd.DataFrame) -> dict:
"""
Get pivot markers for a specific timeframe
Returns dict with indices mapping to pivot info for that candle
Get pivot markers for a specific timeframe using WilliamsMarketStructure directly
Returns dict with all pivot points and identifies which are the last high/low per level
"""
try:
if not self.data_provider:
if WilliamsMarketStructure is None:
logger.warning("WilliamsMarketStructure not available")
return {}
# Get Williams pivot levels for this timeframe
pivot_levels = self.data_provider.get_williams_pivot_levels(
symbol=symbol,
base_timeframe=timeframe,
limit=len(df)
if df is None or len(df) < 10:
logger.warning(f"Insufficient data for pivot calculation: {len(df) if df is not None else 0} bars")
return {}
# Convert DataFrame to numpy array format expected by Williams Market Structure
ohlcv_array = df[['open', 'high', 'low', 'close', 'volume']].copy()
# Add timestamp as first column (convert to milliseconds)
timestamps = df.index.astype(np.int64) // 10**6 # pandas index is ns -> convert to ms
ohlcv_array.insert(0, 'timestamp', timestamps)
ohlcv_array = ohlcv_array.to_numpy()
# Initialize Williams Market Structure with default distance
# We'll override it in the calculation call
williams = WilliamsMarketStructure(min_pivot_distance=1)
# Calculate recursive pivot points with min_pivot_distance=2
# This ensures 5 candles per pivot (tip + 2 prev + 2 next)
pivot_levels = williams.calculate_recursive_pivot_points(
ohlcv_array,
min_pivot_distance=2
)
if not pivot_levels:
logger.debug(f"No pivot levels found for {symbol} {timeframe}")
return {}
# Build a map of timestamp -> pivot info
# Also track last high/low per level for drawing horizontal lines
pivot_map = {}
last_pivots = {} # {level: {'high': (ts_str, idx), 'low': (ts_str, idx)}}
# For each level (1-5), find the last high and last low pivot
# For each level (1-5), collect ALL pivot points
for level_num, trend_level in pivot_levels.items():
if not hasattr(trend_level, 'pivot_points') or not trend_level.pivot_points:
continue
# Find last high and last low for this level
last_high = None
last_low = None
last_pivots[level_num] = {'high': None, 'low': None}
# Add ALL pivot points to the map
for pivot in trend_level.pivot_points:
ts_str = pivot.timestamp.strftime('%Y-%m-%d %H:%M:%S')
if ts_str not in pivot_map:
pivot_map[ts_str] = {'highs': [], 'lows': []}
pivot_info = {
'level': level_num,
'price': pivot.price,
'strength': pivot.strength,
'is_last': False # Will be updated below
}
if pivot.pivot_type == 'high':
last_high = pivot
pivot_map[ts_str]['highs'].append(pivot_info)
last_pivots[level_num]['high'] = (ts_str, len(pivot_map[ts_str]['highs']) - 1)
elif pivot.pivot_type == 'low':
last_low = pivot
# Add to pivot map
if last_high:
ts_str = last_high.timestamp.strftime('%Y-%m-%d %H:%M:%S')
if ts_str not in pivot_map:
pivot_map[ts_str] = {'highs': [], 'lows': []}
pivot_map[ts_str]['highs'].append({
'level': level_num,
'price': last_high.price,
'strength': last_high.strength
})
if last_low:
ts_str = last_low.timestamp.strftime('%Y-%m-%d %H:%M:%S')
if ts_str not in pivot_map:
pivot_map[ts_str] = {'highs': [], 'lows': []}
pivot_map[ts_str]['lows'].append({
'level': level_num,
'price': last_low.price,
'strength': last_low.strength
})
pivot_map[ts_str]['lows'].append(pivot_info)
last_pivots[level_num]['low'] = (ts_str, len(pivot_map[ts_str]['lows']) - 1)
# Mark the last high and last low for each level
for level_num, last_info in last_pivots.items():
if last_info['high']:
ts_str, idx = last_info['high']
pivot_map[ts_str]['highs'][idx]['is_last'] = True
if last_info['low']:
ts_str, idx = last_info['low']
pivot_map[ts_str]['lows'][idx]['is_last'] = True
logger.info(f"Found {len(pivot_map)} pivot candles for {symbol} {timeframe} (from {len(df)} candles)")
return pivot_map
except Exception as e:
logger.error(f"Error getting pivot markers for {timeframe}: {e}")
import traceback
logger.error(traceback.format_exc())
return {}
def _setup_routes(self):