Dashboard Parallel Lists
by smith6jt-cop
Dashboard symbol_signals uses parallel lists (symbols[], signal_values[], gate_statuses[]) not dict keyed by symbol. Trigger when: (1) 'list' object has no attribute 'get', (2) .items() on symbol_signals fails.
Skill Details
Repository Files
1 file in this skill directory
name: dashboard-parallel-lists description: "Dashboard symbol_signals uses parallel lists (symbols[], signal_values[], gate_statuses[]) not dict keyed by symbol. Trigger when: (1) 'list' object has no attribute 'get', (2) .items() on symbol_signals fails." author: Claude Code date: 2024-12-26
Dashboard Parallel Lists Pattern
Experiment Overview
| Item | Details |
|---|---|
| Date | 2024-12-26 |
| Goal | Fix dashboard error when processing symbol signals |
| Environment | scripts/monitor_dashboard.py, scripts/live_trader.py |
| Status | Success |
Context
The dashboard crashed with:
[ERROR] __main__: Dashboard error: 'list' object has no attribute 'get'
Root Cause: Code assumed symbol_signals was a dict keyed by symbol:
# WRONG assumption
for symbol, data in symbol_signals.items():
signal = data.get('signal', 0)
gate_status = data.get('gate_status', {})
Actual Structure: get_symbol_signals() returns parallel lists:
{
'symbols': ['AAPL', 'MSFT', 'GOOGL'],
'signal_values': [1, -1, 0],
'confidences': [0.72, 0.65, 0.45],
'gate_statuses': [
{'final_status': 'READY', ...},
{'final_status': 'BLOCKED', 'blocking_gate': 'crypto_short'},
{'final_status': 'HOLD', ...}
]
}
Verified Workflow
Correct Pattern: Iterate by Index
def get_model_metrics(symbol_signals: Dict) -> dict:
"""Process symbol signals using parallel list structure."""
metrics = {
'total_symbols': 0,
'ready_count': 0,
'blocked_count': 0,
'hold_count': 0,
'avg_confidence': 0.0,
'signals': {'buy': 0, 'sell': 0, 'hold': 0}
}
if not symbol_signals:
return metrics
# Extract parallel lists
symbols = symbol_signals.get('symbols', [])
signal_values = symbol_signals.get('signal_values', [])
confidences = symbol_signals.get('confidences', [])
gate_statuses = symbol_signals.get('gate_statuses', [])
if not symbols:
return metrics
metrics['total_symbols'] = len(symbols)
valid_confidences = []
# Iterate by index across parallel lists
for i, sym in enumerate(symbols):
# Safe access with bounds checking
gate_status = gate_statuses[i] if i < len(gate_statuses) else {}
signal = signal_values[i] if i < len(signal_values) else 0
conf = confidences[i] if i < len(confidences) else 0
status = gate_status.get('final_status', 'HOLD')
if status == 'READY':
metrics['ready_count'] += 1
elif status == 'BLOCKED':
metrics['blocked_count'] += 1
else:
metrics['hold_count'] += 1
if signal > 0:
metrics['signals']['buy'] += 1
elif signal < 0:
metrics['signals']['sell'] += 1
else:
metrics['signals']['hold'] += 1
if conf > 0:
valid_confidences.append(conf)
if valid_confidences:
metrics['avg_confidence'] = sum(valid_confidences) / len(valid_confidences)
return metrics
Why Parallel Lists?
The get_symbol_signals() function returns parallel lists because:
- Performance: Lists are faster to append during signal generation loop
- Order preservation: Maintains processing order for display
- Flexible lengths: Different lists can have different lengths if some data missing
- JSON serialization: Easy to serialize for dashboard communication
Accessing Individual Symbol Data
# Get data for a specific symbol by finding its index
def get_symbol_data(symbol_signals: Dict, target_symbol: str) -> dict:
symbols = symbol_signals.get('symbols', [])
try:
idx = symbols.index(target_symbol)
return {
'symbol': target_symbol,
'signal': symbol_signals.get('signal_values', [])[idx],
'confidence': symbol_signals.get('confidences', [])[idx],
'gate_status': symbol_signals.get('gate_statuses', [])[idx],
}
except (ValueError, IndexError):
return None
Failed Attempts (Critical)
| Attempt | Why it Failed | Lesson Learned |
|---|---|---|
for sym, data in symbol_signals.items() |
symbol_signals is not keyed by symbol | Use parallel list iteration |
symbol_signals[symbol]['signal'] |
Lists don't support dict-style access | Find index first, then access |
| Assuming all lists same length | Some fields may be missing | Always use bounds checking |
| Converting to dict-by-symbol | Expensive for large symbol counts | Keep parallel structure |
Key Insights
Signal Structure from get_symbol_signals()
# In live_trader.py get_symbol_signals() returns:
{
'symbols': List[str], # Symbol names
'signal_values': List[int], # -1 (sell), 0 (hold), 1 (buy)
'confidences': List[float], # Model confidence [0, 1]
'gate_statuses': List[Dict], # Gate check results
'prices': List[float], # Current prices
'regime_contexts': List[Dict], # Markov regime info
}
Gate Status Structure
# Each gate_status dict contains:
{
'final_status': 'READY' | 'BLOCKED' | 'HOLD',
'blocking_gate': str | None, # Which gate blocked (if any)
'confidence_gate': bool,
'crypto_short_gate': bool,
'portfolio_limit_gate': bool,
'capital_manager_gate': bool,
'portfolio_risk_gate': bool,
}
Common Error Patterns
| Error | Cause | Fix |
|---|---|---|
'list' object has no attribute 'get' |
Called .get() on a list |
Use index access |
'list' object has no attribute 'items' |
Called .items() on symbol_signals |
Iterate by index |
KeyError: 'AAPL' |
Tried symbol_signals['AAPL'] |
Find index in symbols list |
IndexError: list index out of range |
Lists have different lengths | Add bounds checking |
Files Modified
scripts/monitor_dashboard.py:
- Lines 536-577: get_model_metrics() rewritten for parallel lists
- Pattern: Extract lists first, iterate by index with bounds checking
References
scripts/live_trader.py:get_symbol_signals()function (lines ~800-900)scripts/monitor_dashboard.py:get_model_metrics()function (lines ~536-577)alpaca_trading/visualization/dashboard.py: Dashboard display logic
Related Skills
Attack Tree Construction
Build comprehensive attack trees to visualize threat paths. Use when mapping attack scenarios, identifying defense gaps, or communicating security risks to stakeholders.
Grafana Dashboards
Create and manage production Grafana dashboards for real-time visualization of system and application metrics. Use when building monitoring dashboards, visualizing metrics, or creating operational observability interfaces.
Matplotlib
Foundational plotting library. Create line plots, scatter, bar, histograms, heatmaps, 3D, subplots, export PNG/PDF/SVG, for scientific visualization and publication figures.
Scientific Visualization
Create publication figures with matplotlib/seaborn/plotly. Multi-panel layouts, error bars, significance markers, colorblind-safe, export PDF/EPS/TIFF, for journal-ready scientific plots.
Seaborn
Statistical visualization. Scatter, box, violin, heatmaps, pair plots, regression, correlation matrices, KDE, faceted plots, for exploratory analysis and publication figures.
Shap
Model interpretability and explainability using SHAP (SHapley Additive exPlanations). Use this skill when explaining machine learning model predictions, computing feature importance, generating SHAP plots (waterfall, beeswarm, bar, scatter, force, heatmap), debugging models, analyzing model bias or fairness, comparing models, or implementing explainable AI. Works with tree-based models (XGBoost, LightGBM, Random Forest), deep learning (TensorFlow, PyTorch), linear models, and any black-box model
Pydeseq2
Differential gene expression analysis (Python DESeq2). Identify DE genes from bulk RNA-seq counts, Wald tests, FDR correction, volcano/MA plots, for RNA-seq analysis.
Query Writing
For writing and executing SQL queries - from simple single-table queries to complex multi-table JOINs and aggregations
Pydeseq2
Differential gene expression analysis (Python DESeq2). Identify DE genes from bulk RNA-seq counts, Wald tests, FDR correction, volcano/MA plots, for RNA-seq analysis.
Scientific Visualization
Meta-skill for publication-ready figures. Use when creating journal submission figures requiring multi-panel layouts, significance annotations, error bars, colorblind-safe palettes, and specific journal formatting (Nature, Science, Cell). Orchestrates matplotlib/seaborn/plotly with publication styles. For quick exploration use seaborn or plotly directly.
