wip
This commit is contained in:
@@ -385,7 +385,7 @@ class TradingOrchestrator:
|
||||
logger.info(f"Transformer checkpoint loaded: {metadata.checkpoint_id}")
|
||||
except Exception as e:
|
||||
logger.debug(f"No transformer checkpoint found: {e}")
|
||||
|
||||
|
||||
if not checkpoint_loaded:
|
||||
self.model_states['transformer']['checkpoint_loaded'] = False
|
||||
self.model_states['transformer']['checkpoint_filename'] = 'none (fresh start)'
|
||||
@@ -1182,137 +1182,156 @@ class TradingOrchestrator:
|
||||
logger.debug(f"Error getting current price for {symbol}: {e}")
|
||||
return 0.0
|
||||
|
||||
# Get standard feature matrix for this timeframe
|
||||
feature_matrix = self.data_provider.get_feature_matrix(
|
||||
symbol=symbol,
|
||||
timeframes=[timeframe],
|
||||
window_size=getattr(model, 'window_size', 20)
|
||||
)
|
||||
|
||||
# Enhance with COB feature matrix if available
|
||||
enhanced_features = feature_matrix
|
||||
if feature_matrix is not None and self.cob_integration:
|
||||
try:
|
||||
# Get COB feature matrix (5-minute history)
|
||||
cob_feature_matrix = self.get_cob_feature_matrix(symbol, sequence_length=60)
|
||||
|
||||
if cob_feature_matrix is not None:
|
||||
# Take the latest COB features to augment the standard features
|
||||
latest_cob_features = cob_feature_matrix[-1:, :] # Shape: (1, 400)
|
||||
|
||||
# Resize to match the feature matrix timeframe dimension
|
||||
timeframe_count = feature_matrix.shape[0]
|
||||
cob_features_expanded = np.repeat(latest_cob_features, timeframe_count, axis=0)
|
||||
|
||||
# Concatenate COB features with standard features
|
||||
# Standard features shape: (timeframes, window_size, features)
|
||||
# COB features shape: (timeframes, 400)
|
||||
# We'll add COB as additional features to each timeframe
|
||||
window_size = feature_matrix.shape[1]
|
||||
cob_features_reshaped = cob_features_expanded.reshape(timeframe_count, 1, 400)
|
||||
cob_features_tiled = np.tile(cob_features_reshaped, (1, window_size, 1))
|
||||
|
||||
# Concatenate along feature dimension
|
||||
enhanced_features = np.concatenate([feature_matrix, cob_features_tiled], axis=2)
|
||||
|
||||
logger.debug(f"Enhanced CNN features with COB data for {symbol}: "
|
||||
f"{feature_matrix.shape} + COB -> {enhanced_features.shape}")
|
||||
|
||||
except Exception as cob_error:
|
||||
logger.debug(f"Could not enhance CNN features with COB data: {cob_error}")
|
||||
enhanced_features = feature_matrix
|
||||
|
||||
# Add extrema features if available
|
||||
if self.extrema_trainer:
|
||||
try:
|
||||
extrema_features = self.extrema_trainer.get_context_features_for_model(symbol)
|
||||
if extrema_features is not None:
|
||||
# Reshape and tile to match the enhanced_features shape
|
||||
extrema_features = extrema_features.flatten()
|
||||
tiled_extrema = np.tile(extrema_features, (enhanced_features.shape[0], enhanced_features.shape[1], 1))
|
||||
enhanced_features = np.concatenate([enhanced_features, tiled_extrema], axis=2)
|
||||
logger.debug(f"Enhanced CNN features with Extrema data for {symbol}")
|
||||
except Exception as extrema_error:
|
||||
logger.debug(f"Could not enhance CNN features with Extrema data: {extrema_error}")
|
||||
|
||||
if enhanced_features is not None:
|
||||
# Get CNN prediction - use the actual underlying model
|
||||
try:
|
||||
# Ensure features are properly shaped and limited
|
||||
if isinstance(enhanced_features, np.ndarray):
|
||||
# Flatten and limit features to prevent shape mismatches
|
||||
enhanced_features = enhanced_features.flatten()
|
||||
if len(enhanced_features) > 100: # Limit to 100 features
|
||||
enhanced_features = enhanced_features[:100]
|
||||
elif len(enhanced_features) < 100: # Pad with zeros
|
||||
padded = np.zeros(100)
|
||||
padded[:len(enhanced_features)] = enhanced_features
|
||||
enhanced_features = padded
|
||||
|
||||
if hasattr(model.model, 'act'):
|
||||
# Use the CNN's act method
|
||||
action_result = model.model.act(enhanced_features, explore=False)
|
||||
if isinstance(action_result, tuple):
|
||||
action_idx, confidence = action_result
|
||||
else:
|
||||
action_idx = action_result
|
||||
confidence = 0.7 # Default confidence
|
||||
|
||||
# Convert to action probabilities
|
||||
action_probs = [0.1, 0.1, 0.8] # Default distribution
|
||||
action_probs[action_idx] = confidence
|
||||
else:
|
||||
# Fallback to generic predict method
|
||||
action_probs, confidence = model.predict(enhanced_features)
|
||||
except Exception as e:
|
||||
logger.warning(f"CNN prediction failed: {e}")
|
||||
action_probs, confidence = None, None
|
||||
|
||||
if action_probs is not None:
|
||||
# Convert to prediction object
|
||||
action_names = ['SELL', 'HOLD', 'BUY']
|
||||
best_action_idx = np.argmax(action_probs)
|
||||
best_action = action_names[best_action_idx]
|
||||
|
||||
prediction = Prediction(
|
||||
action=best_action,
|
||||
confidence=float(confidence) if confidence is not None else float(action_probs[best_action_idx]),
|
||||
probabilities={name: float(prob) for name, prob in zip(action_names, action_probs)},
|
||||
timeframe=timeframe,
|
||||
timestamp=datetime.now(),
|
||||
model_name=model.name,
|
||||
metadata={
|
||||
'timeframe_specific': True,
|
||||
'cob_enhanced': enhanced_features is not feature_matrix,
|
||||
'feature_shape': str(enhanced_features.shape)
|
||||
}
|
||||
)
|
||||
|
||||
predictions.append(prediction)
|
||||
|
||||
# Capture CNN prediction for dashboard visualization
|
||||
current_price = self._get_current_price(symbol)
|
||||
if current_price:
|
||||
direction = best_action_idx # 0=SELL, 1=HOLD, 2=BUY
|
||||
pred_confidence = float(confidence) if confidence is not None else float(action_probs[best_action_idx])
|
||||
predicted_price = current_price * (1 + (pred_confidence * 0.01 if best_action == 'BUY' else -pred_confidence * 0.01 if best_action == 'SELL' else 0))
|
||||
self.capture_cnn_prediction(symbol, int(direction), pred_confidence, current_price, predicted_price)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting CNN predictions: {e}")
|
||||
|
||||
return predictions
|
||||
|
||||
async def _get_rl_prediction(self, model: RLAgentInterface, symbol: str) -> Optional[Prediction]:
|
||||
"""Get prediction from RL agent"""
|
||||
async def _get_cob_rl_prediction(self, model: COBRLModelInterface, symbol: str) -> Optional[Prediction]:
|
||||
"""Get prediction from COB RL model"""
|
||||
try:
|
||||
# Get current state for RL agent
|
||||
state = self._get_rl_state(symbol)
|
||||
if state is None:
|
||||
# Get COB state from current market data
|
||||
cob_state = self._get_cob_state(symbol)
|
||||
if cob_state is None:
|
||||
return None
|
||||
|
||||
# Get RL agent's action, confidence, and q_values from the underlying model
|
||||
# Get prediction from COB RL model
|
||||
if hasattr(model.model, 'act_with_confidence'):
|
||||
result = model.model.act_with_confidence(cob_state)
|
||||
if len(result) == 2:
|
||||
action_idx, confidence = result
|
||||
else:
|
||||
action_idx = result[0] if isinstance(result, (list, tuple)) else result
|
||||
confidence = 0.6
|
||||
else:
|
||||
action_idx = model.model.act(cob_state)
|
||||
confidence = 0.6
|
||||
|
||||
# Convert to action name
|
||||
action_names = ['BUY', 'SELL', 'HOLD']
|
||||
if 0 <= action_idx < len(action_names):
|
||||
action = action_names[action_idx]
|
||||
else:
|
||||
return None
|
||||
|
||||
# Store prediction in database for tracking
|
||||
if (hasattr(self, 'enhanced_training_system') and
|
||||
self.enhanced_training_system and
|
||||
hasattr(self.enhanced_training_system, 'store_model_prediction')):
|
||||
|
||||
current_price = self._get_current_price_safe(symbol)
|
||||
if current_price > 0:
|
||||
prediction_id = self.enhanced_training_system.store_model_prediction(
|
||||
model_name=f"COB_RL_{model.model_name}" if hasattr(model, 'model_name') else "COB_RL",
|
||||
symbol=symbol,
|
||||
prediction_type=action,
|
||||
confidence=confidence,
|
||||
current_price=current_price
|
||||
)
|
||||
logger.debug(f"Stored COB RL prediction {prediction_id} for {symbol}")
|
||||
|
||||
# Create prediction object
|
||||
prediction = Prediction(
|
||||
model_name=f"COB_RL_{model.model_name}" if hasattr(model, 'model_name') else "COB_RL",
|
||||
symbol=symbol,
|
||||
signal=action,
|
||||
confidence=confidence,
|
||||
reasoning=f"COB RL model prediction based on order book imbalance",
|
||||
features=cob_state.tolist() if isinstance(cob_state, np.ndarray) else [],
|
||||
metadata={
|
||||
'action_idx': action_idx,
|
||||
'cob_state_size': len(cob_state) if cob_state is not None else 0
|
||||
}
|
||||
)
|
||||
|
||||
return prediction
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting COB RL prediction for {symbol}: {e}")
|
||||
return None
|
||||
|
||||
async def _get_generic_prediction(self, model, symbol: str) -> Optional[Prediction]:
|
||||
"""Get prediction from generic model interface"""
|
||||
try:
|
||||
# Placeholder for generic model prediction
|
||||
logger.debug(f"Getting generic prediction from {model} for {symbol}")
|
||||
return None
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting generic prediction for {symbol}: {e}")
|
||||
return None
|
||||
|
||||
def _get_rl_state(self, symbol: str) -> Optional[np.ndarray]:
|
||||
"""Build RL state vector for DQN agent"""
|
||||
try:
|
||||
# Use data provider to get comprehensive RL state
|
||||
if hasattr(self.data_provider, 'get_dqn_state_for_inference'):
|
||||
symbols_timeframes = [(symbol, '1m'), (symbol, '5m'), (symbol, '1h')]
|
||||
state = self.data_provider.get_dqn_state_for_inference(symbols_timeframes, target_size=100)
|
||||
if state is not None:
|
||||
return state
|
||||
|
||||
# Fallback: build basic state from market data
|
||||
market_features = []
|
||||
|
||||
# Get latest price data
|
||||
latest_data = self.data_provider.get_latest_data(symbol)
|
||||
if latest_data and 'close' in latest_data:
|
||||
current_price = float(latest_data['close'])
|
||||
market_features.extend([
|
||||
current_price,
|
||||
latest_data.get('volume', 0.0),
|
||||
latest_data.get('high', current_price) - latest_data.get('low', current_price), # Range
|
||||
latest_data.get('open', current_price)
|
||||
])
|
||||
else:
|
||||
market_features.extend([4300.0, 100.0, 10.0, 4295.0]) # Default values
|
||||
|
||||
# Pad to standard size
|
||||
while len(market_features) < 100:
|
||||
market_features.append(0.0)
|
||||
|
||||
return np.array(market_features[:100], dtype=np.float32)
|
||||
|
||||
except Exception as e:
|
||||
logger.debug(f"Error building RL state for {symbol}: {e}")
|
||||
return None
|
||||
|
||||
def _get_cob_state(self, symbol: str) -> Optional[np.ndarray]:
|
||||
"""Build COB state vector for COB RL agent"""
|
||||
try:
|
||||
# Get COB data from integration
|
||||
if hasattr(self, 'cob_integration') and self.cob_integration:
|
||||
cob_snapshot = self.cob_integration.get_cob_snapshot(symbol)
|
||||
if cob_snapshot:
|
||||
# Extract features from COB snapshot
|
||||
features = []
|
||||
|
||||
# Add bid/ask imbalance
|
||||
bid_volume = sum([level['volume'] for level in cob_snapshot.get('bids', [])])
|
||||
ask_volume = sum([level['volume'] for level in cob_snapshot.get('asks', [])])
|
||||
if bid_volume + ask_volume > 0:
|
||||
imbalance = (bid_volume - ask_volume) / (bid_volume + ask_volume)
|
||||
else:
|
||||
imbalance = 0.0
|
||||
features.append(imbalance)
|
||||
|
||||
# Add spread
|
||||
if cob_snapshot.get('bids') and cob_snapshot.get('asks'):
|
||||
spread = cob_snapshot['asks'][0]['price'] - cob_snapshot['bids'][0]['price']
|
||||
features.append(spread)
|
||||
else:
|
||||
features.append(0.0)
|
||||
|
||||
# Pad to standard size
|
||||
while len(features) < 50:
|
||||
features.append(0.0)
|
||||
|
||||
return np.array(features[:50], dtype=np.float32)
|
||||
|
||||
# Fallback state
|
||||
return np.zeros(50, dtype=np.float32)
|
||||
|
||||
except Exception as e:
|
||||
logger.debug(f"Error building COB state for {symbol}: {e}")
|
||||
return None
|
||||
|
||||
def _combine_predictions(self, symbol: str, price: float, predictions: List[Prediction],
|
||||
timestamp: datetime) -> TradingDecision:
|
||||
# Call act_with_confidence and handle different return formats
|
||||
result = model.model.act_with_confidence(state)
|
||||
|
||||
@@ -1728,7 +1747,7 @@ class TradingOrchestrator:
|
||||
)
|
||||
|
||||
if needs_refresh:
|
||||
result = load_best_checkpoint(model_name)
|
||||
result = load_best_checkpoint(model_name)
|
||||
self._checkpoint_cache[model_name] = result
|
||||
self._checkpoint_cache_time[model_name] = current_time
|
||||
|
||||
@@ -1869,14 +1888,14 @@ class TradingOrchestrator:
|
||||
logger.warning("EnhancedRealtimeTrainingSystem not available - training disabled")
|
||||
self.training_enabled = False
|
||||
return
|
||||
|
||||
|
||||
# Initialize enhanced training system directly (no external training_integration module needed)
|
||||
try:
|
||||
from NN.training.enhanced_realtime_training import EnhancedRealtimeTrainingSystem
|
||||
|
||||
self.enhanced_training_system = EnhancedRealtimeTrainingSystem(
|
||||
orchestrator=self,
|
||||
data_provider=self.data_provider,
|
||||
self.enhanced_training_system = EnhancedRealtimeTrainingSystem(
|
||||
orchestrator=self,
|
||||
data_provider=self.data_provider,
|
||||
dashboard=None
|
||||
)
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import logging
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Any, Optional
|
||||
import numpy as np
|
||||
from utils.reward_calculator import RewardCalculator
|
||||
from core.reward_calculator import RewardCalculator
|
||||
import threading
|
||||
import time
|
||||
|
||||
|
||||
Reference in New Issue
Block a user