improved data structure

This commit is contained in:
Dobromir Popov
2025-10-31 00:44:08 +02:00
parent b8f54e61fa
commit 7ddf98bf18
16 changed files with 5892 additions and 35 deletions

View File

@@ -10651,16 +10651,118 @@ class CleanTradingDashboard:
price_change = (next_price - current_price) / current_price if current_price > 0 else 0
cumulative_imbalance = current_data.get('cumulative_imbalance', {})
# TODO(Guideline: no synthetic data) Replace random feature vectors with real market-derived inputs.
features = np.random.randn(32) # Decision fusion expects 32 features
features[0] = current_price / 10000
# Build real feature vector from market data (128 features as per config)
# Decision fusion network expects 128 features (configurable in models.yml)
features = np.zeros(128, dtype=np.float32)
# Price features (0-9)
features[0] = current_price / 10000.0 if current_price > 0 else 0.0
features[1] = price_change
features[2] = current_data.get('volume', 0) / 1000000
# Add cumulative imbalance features
features[3] = cumulative_imbalance.get('1s', 0.0)
features[4] = cumulative_imbalance.get('5s', 0.0)
features[5] = cumulative_imbalance.get('15s', 0.0)
features[6] = cumulative_imbalance.get('60s', 0.0)
features[2] = current_data.get('volume', 0) / 1000000.0 if current_data.get('volume', 0) > 0 else 0.0
features[3] = (next_price - current_price) / current_price if current_price > 0 else 0.0
features[4] = current_data.get('high', current_price) / 10000.0 if current_data.get('high', 0) > 0 else 0.0
features[5] = current_data.get('low', current_price) / 10000.0 if current_data.get('low', 0) > 0 else 0.0
features[6] = current_data.get('open', current_price) / 10000.0 if current_data.get('open', 0) > 0 else 0.0
features[7] = current_data.get('close', current_price) / 10000.0 if current_data.get('close', 0) > 0 else 0.0
features[8] = abs(price_change) if price_change != 0 else 0.0 # Absolute price change
features[9] = (current_data.get('high', current_price) - current_data.get('low', current_price)) / current_price if current_price > 0 else 0.0 # Price range
# Cumulative imbalance features (10-13)
features[10] = cumulative_imbalance.get('1s', 0.0)
features[11] = cumulative_imbalance.get('5s', 0.0)
features[12] = cumulative_imbalance.get('15s', 0.0)
features[13] = cumulative_imbalance.get('60s', 0.0)
# Technical indicators from market data (14-30)
if 'indicators' in current_data:
indicators = current_data['indicators']
feature_idx = 14
for key in ['rsi', 'macd', 'ema', 'sma', 'bb_upper', 'bb_lower', 'atr', 'adx', 'stoch', 'williams_r', 'cci', 'roc', 'momentum', 'ad', 'obv', 'vwap']:
if feature_idx < 30 and key in indicators:
features[feature_idx] = float(indicators[key]) if indicators[key] is not None else 0.0
feature_idx += 1
# Model prediction features (if available from orchestrator) (31-50)
if self.orchestrator:
if hasattr(self.orchestrator, 'recent_cnn_predictions') and self.symbol in self.orchestrator.recent_cnn_predictions:
cnn_preds = self.orchestrator.recent_cnn_predictions[self.symbol]
if cnn_preds:
last_cnn = cnn_preds[-1]
feature_idx = 31
if feature_idx < 50:
features[feature_idx] = last_cnn.get('confidence', 0.0)
feature_idx += 1
features[feature_idx] = last_cnn.get('buy_probability', 0.0)
feature_idx += 1
features[feature_idx] = last_cnn.get('sell_probability', 0.0)
feature_idx += 1
features[feature_idx] = last_cnn.get('hold_probability', 0.0)
feature_idx += 1
if hasattr(self.orchestrator, 'recent_dqn_predictions') and self.symbol in self.orchestrator.recent_dqn_predictions:
dqn_preds = self.orchestrator.recent_dqn_predictions[self.symbol]
if dqn_preds:
last_dqn = dqn_preds[-1]
feature_idx = 36
if feature_idx < 50:
features[feature_idx] = last_dqn.get('confidence', 0.0)
feature_idx += 1
features[feature_idx] = last_dqn.get('q_values', {}).get('BUY', 0.0) if isinstance(last_dqn.get('q_values'), dict) else 0.0
feature_idx += 1
features[feature_idx] = last_dqn.get('q_values', {}).get('SELL', 0.0) if isinstance(last_dqn.get('q_values'), dict) else 0.0
feature_idx += 1
# Market microstructure features (51-80)
feature_idx = 51
if 'market_microstructure' in current_data:
micro = current_data['market_microstructure']
for key in ['spread', 'bid_volume', 'ask_volume', 'imbalance_ratio', 'order_flow', 'liquidity', 'volatility', 'tick_size', 'depth_imbalance', 'momentum', 'acceleration', 'volume_profile', 'price_velocity', 'volume_velocity', 'order_book_pressure', 'trade_intensity', 'spread_ratio', 'depth_ratio', 'imbalance_momentum', 'liquidity_imbalance']:
if feature_idx < 80 and key in micro:
val = micro[key]
features[feature_idx] = float(val) if val is not None and not np.isnan(val) else 0.0
feature_idx += 1
# Historical price features (81-100)
if len(market_data) > 1:
feature_idx = 81
# Price momentum (last 5 periods)
for i in range(min(5, len(market_data) - 1)):
if i + 1 < len(market_data):
prev_data = market_data[len(market_data) - 2 - i]
prev_price = prev_data.get('price', 0)
if prev_price > 0 and feature_idx < 100:
features[feature_idx] = (current_price - prev_price) / prev_price
feature_idx += 1
# Volume features (101-110)
feature_idx = 101
if len(market_data) > 1:
volumes = [d.get('volume', 0) for d in market_data[-10:] if d.get('volume', 0) > 0]
if volumes:
avg_volume = sum(volumes) / len(volumes)
current_vol = current_data.get('volume', 0)
if avg_volume > 0 and feature_idx < 110:
features[feature_idx] = current_vol / avg_volume # Volume ratio
feature_idx += 1
features[feature_idx] = max(volumes) / avg_volume if max(volumes) > 0 else 0.0 # Max volume ratio
feature_idx += 1
# Position features (if available) (111-115)
if self.orchestrator and hasattr(self.orchestrator, 'positions') and self.symbol in self.orchestrator.positions:
position = self.orchestrator.positions[self.symbol]
feature_idx = 111
if feature_idx < 115:
features[feature_idx] = 1.0 if position.get('size', 0) != 0 else 0.0
feature_idx += 1
features[feature_idx] = position.get('pnl', 0.0) / 1000.0 # Normalized PnL
feature_idx += 1
features[feature_idx] = abs(position.get('size', 0.0)) / 100.0 # Normalized size
feature_idx += 1
features[feature_idx] = position.get('entry_price', 0.0) / 10000.0 if position.get('entry_price', 0) > 0 else 0.0
feature_idx += 1
# Fill remaining features with zeros (116-127) - padding for future features
# Features 116-127 are reserved for future expansion
# Determine action target based on price change
if price_change > 0.001: action_target = 0 # BUY