improved data structure
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user