|
|
|
@ -419,7 +419,7 @@ class EnhancedTradingOrchestrator(TradingOrchestrator):
|
|
|
|
|
symbol_predictions = {}
|
|
|
|
|
for symbol in self.symbols:
|
|
|
|
|
if symbol in market_states:
|
|
|
|
|
predictions = await self._get_enhanced_predictions_universal(
|
|
|
|
|
predictions = await self._get_enhanced_predictions_for_symbol(
|
|
|
|
|
symbol, market_states[symbol], universal_stream
|
|
|
|
|
)
|
|
|
|
|
symbol_predictions[symbol] = predictions
|
|
|
|
@ -444,6 +444,77 @@ class EnhancedTradingOrchestrator(TradingOrchestrator):
|
|
|
|
|
|
|
|
|
|
return decisions
|
|
|
|
|
|
|
|
|
|
async def _get_enhanced_predictions_for_symbol(self, symbol: str, market_state: MarketState,
|
|
|
|
|
universal_stream: UniversalDataStream) -> List[EnhancedPrediction]:
|
|
|
|
|
"""Get enhanced predictions for a symbol using universal data format"""
|
|
|
|
|
predictions = []
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
# Get predictions from all registered models using the parent class method
|
|
|
|
|
base_predictions = await self._get_all_predictions(symbol)
|
|
|
|
|
|
|
|
|
|
if not base_predictions:
|
|
|
|
|
logger.warning(f"No base predictions available for {symbol}")
|
|
|
|
|
return predictions
|
|
|
|
|
|
|
|
|
|
# Group predictions by model and create enhanced predictions
|
|
|
|
|
model_predictions = {}
|
|
|
|
|
for pred in base_predictions:
|
|
|
|
|
if pred.model_name not in model_predictions:
|
|
|
|
|
model_predictions[pred.model_name] = []
|
|
|
|
|
model_predictions[pred.model_name].append(pred)
|
|
|
|
|
|
|
|
|
|
# Create enhanced predictions for each model
|
|
|
|
|
for model_name, model_preds in model_predictions.items():
|
|
|
|
|
# Convert base predictions to timeframe predictions
|
|
|
|
|
timeframe_predictions = []
|
|
|
|
|
for pred in model_preds:
|
|
|
|
|
tf_pred = TimeframePrediction(
|
|
|
|
|
timeframe=pred.timeframe,
|
|
|
|
|
action=pred.action,
|
|
|
|
|
confidence=pred.confidence,
|
|
|
|
|
probabilities=pred.probabilities,
|
|
|
|
|
timestamp=pred.timestamp,
|
|
|
|
|
market_features=pred.metadata or {}
|
|
|
|
|
)
|
|
|
|
|
timeframe_predictions.append(tf_pred)
|
|
|
|
|
|
|
|
|
|
# Combine timeframe predictions into overall action
|
|
|
|
|
if timeframe_predictions:
|
|
|
|
|
overall_action, overall_confidence = self._combine_timeframe_predictions(
|
|
|
|
|
timeframe_predictions, symbol
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Enhance confidence with universal context
|
|
|
|
|
enhanced_confidence = self._enhance_confidence_with_universal_context(
|
|
|
|
|
overall_confidence, 'mixed', market_state, universal_stream
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
# Create enhanced prediction
|
|
|
|
|
enhanced_pred = EnhancedPrediction(
|
|
|
|
|
symbol=symbol,
|
|
|
|
|
timeframe_predictions=timeframe_predictions,
|
|
|
|
|
overall_action=overall_action,
|
|
|
|
|
overall_confidence=enhanced_confidence,
|
|
|
|
|
model_name=model_name,
|
|
|
|
|
timestamp=datetime.now(),
|
|
|
|
|
metadata={
|
|
|
|
|
'universal_data_used': True,
|
|
|
|
|
'market_regime': market_state.market_regime,
|
|
|
|
|
'volatility': market_state.volatility,
|
|
|
|
|
'volume': market_state.volume
|
|
|
|
|
}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
predictions.append(enhanced_pred)
|
|
|
|
|
logger.debug(f"Created enhanced prediction for {symbol} from {model_name}: "
|
|
|
|
|
f"{overall_action} (confidence: {enhanced_confidence:.3f})")
|
|
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.error(f"Error getting enhanced predictions for {symbol}: {e}")
|
|
|
|
|
|
|
|
|
|
return predictions
|
|
|
|
|
|
|
|
|
|
async def _get_all_market_states_universal(self, universal_stream: UniversalDataStream) -> Dict[str, MarketState]:
|
|
|
|
|
"""Get market states for all symbols with comprehensive data for RL"""
|
|
|
|
|
market_states = {}
|
|
|
|
@ -1395,13 +1466,14 @@ class EnhancedTradingOrchestrator(TradingOrchestrator):
|
|
|
|
|
predictions = prediction_result.get('probabilities', [0.33, 0.33, 0.34])
|
|
|
|
|
confidence = prediction_result.get('confidence', 0.7)
|
|
|
|
|
|
|
|
|
|
# Convert predictions to numpy array first
|
|
|
|
|
# Convert predictions to numpy array first using safe conversion
|
|
|
|
|
if isinstance(predictions, np.ndarray):
|
|
|
|
|
predictions_array = predictions.flatten()
|
|
|
|
|
elif isinstance(predictions, (list, tuple)):
|
|
|
|
|
predictions_array = np.array(predictions, dtype=np.float32).flatten()
|
|
|
|
|
else:
|
|
|
|
|
predictions_array = np.array([float(predictions)], dtype=np.float32)
|
|
|
|
|
# Use safe tensor conversion for single values
|
|
|
|
|
predictions_array = np.array([self._safe_tensor_to_scalar(predictions, 0.5)], dtype=np.float32)
|
|
|
|
|
|
|
|
|
|
# Create final predictions array with confidence
|
|
|
|
|
# Use safe tensor conversion to avoid scalar conversion errors
|
|
|
|
@ -1416,7 +1488,7 @@ class EnhancedTradingOrchestrator(TradingOrchestrator):
|
|
|
|
|
# Handle (pred_class, pred_proba) tuple from CNN models
|
|
|
|
|
pred_class, pred_proba = prediction_result
|
|
|
|
|
|
|
|
|
|
# Flatten and process the probability array
|
|
|
|
|
# Flatten and process the probability array using safe conversion
|
|
|
|
|
if isinstance(pred_proba, np.ndarray):
|
|
|
|
|
if pred_proba.ndim > 1:
|
|
|
|
|
# Handle 2D arrays like [[0.1, 0.2, 0.7]]
|
|
|
|
@ -1428,16 +1500,17 @@ class EnhancedTradingOrchestrator(TradingOrchestrator):
|
|
|
|
|
# Use the probability values as the predictions array
|
|
|
|
|
predictions = pred_proba_flat.astype(np.float32)
|
|
|
|
|
else:
|
|
|
|
|
# Fallback: use class prediction only
|
|
|
|
|
predictions = np.array([float(pred_class)], dtype=np.float32)
|
|
|
|
|
# Fallback: use class prediction with safe conversion
|
|
|
|
|
predictions = np.array([self._safe_tensor_to_scalar(pred_class, 0.5)], dtype=np.float32)
|
|
|
|
|
else:
|
|
|
|
|
# Handle direct prediction result
|
|
|
|
|
# Handle direct prediction result using safe conversion
|
|
|
|
|
if isinstance(prediction_result, np.ndarray):
|
|
|
|
|
predictions = prediction_result.flatten()
|
|
|
|
|
elif isinstance(prediction_result, (list, tuple)):
|
|
|
|
|
predictions = np.array(prediction_result, dtype=np.float32).flatten()
|
|
|
|
|
else:
|
|
|
|
|
predictions = np.array([float(prediction_result)], dtype=np.float32)
|
|
|
|
|
# Use safe tensor conversion for single tensor/scalar values
|
|
|
|
|
predictions = np.array([self._safe_tensor_to_scalar(prediction_result, 0.5)], dtype=np.float32)
|
|
|
|
|
|
|
|
|
|
# Extract hidden features if model supports it
|
|
|
|
|
hidden_features = None
|
|
|
|
@ -4740,7 +4813,8 @@ class EnhancedTradingOrchestrator(TradingOrchestrator):
|
|
|
|
|
Python float scalar value
|
|
|
|
|
"""
|
|
|
|
|
try:
|
|
|
|
|
if hasattr(tensor_value, 'item'):
|
|
|
|
|
# Handle PyTorch tensors first
|
|
|
|
|
if hasattr(tensor_value, 'numel') and hasattr(tensor_value, 'item'):
|
|
|
|
|
# PyTorch tensor - handle different shapes
|
|
|
|
|
if tensor_value.numel() == 1:
|
|
|
|
|
return float(tensor_value.item())
|
|
|
|
@ -4754,9 +4828,12 @@ class EnhancedTradingOrchestrator(TradingOrchestrator):
|
|
|
|
|
return float(tensor_value.flatten()[0])
|
|
|
|
|
else:
|
|
|
|
|
return float(tensor_value.flat[0])
|
|
|
|
|
elif hasattr(tensor_value, 'item') and not isinstance(tensor_value, np.ndarray):
|
|
|
|
|
# Other tensor types that have .item() method
|
|
|
|
|
return float(tensor_value.item())
|
|
|
|
|
else:
|
|
|
|
|
# Already a scalar value
|
|
|
|
|
return float(tensor_value)
|
|
|
|
|
except Exception as e:
|
|
|
|
|
logger.warning(f"Error converting tensor to scalar, using default {default_value}: {e}")
|
|
|
|
|
logger.debug(f"Error converting tensor to scalar, using default {default_value}: {e}")
|
|
|
|
|
return default_value
|