1883 lines
54 KiB
Plaintext
1883 lines
54 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 1,
|
|
"id": "0aab70ec",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import json\n",
|
|
"import plotly.graph_objects as go\n",
|
|
"import plotly.express as px\n",
|
|
"from plotly.subplots import make_subplots\n",
|
|
"import pandas as pd\n",
|
|
"import re\n",
|
|
"from datetime import datetime\n",
|
|
"from textstat import flesch_reading_ease\n",
|
|
"import numpy as np"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"id": "47f14ad4",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class InvestmentDashboard:\n",
|
|
" def __init__(self, json_data=None, json_file_path=None):\n",
|
|
" \"\"\"\n",
|
|
" Initialize the dashboard with JSON data\n",
|
|
" Args:\n",
|
|
" json_data: Dictionary containing investment data\n",
|
|
" json_file_path: Path to JSON file containing investment data\n",
|
|
" \"\"\"\n",
|
|
" if json_file_path:\n",
|
|
" with open(json_file_path, 'r') as f:\n",
|
|
" self.data = json.load(f)\n",
|
|
" elif json_data:\n",
|
|
" self.data = json_data\n",
|
|
" else:\n",
|
|
" raise ValueError(\"Either json_data or json_file_path must be provided\")\n",
|
|
" \n",
|
|
" self.analysis = self._analyze_data()\n",
|
|
" \n",
|
|
" def _analyze_data(self):\n",
|
|
" \"\"\"Analyze the JSON data to extract key metrics and insights\"\"\"\n",
|
|
" analysis = {}\n",
|
|
" \n",
|
|
" for date, data in self.data.items():\n",
|
|
" company = data.get('company_of_interest', 'Unknown')\n",
|
|
" \n",
|
|
" # Extract technical indicators from market report\n",
|
|
" analysis[date] = {\n",
|
|
" 'company': company,\n",
|
|
" 'trade_date': data.get('trade_date'),\n",
|
|
" 'technical_indicators': self._extract_technical_indicators(data.get('market_report', '')),\n",
|
|
" 'sentiment_metrics': self._extract_sentiment_metrics(data.get('sentiment_report', '')),\n",
|
|
" 'fundamental_metrics': self._extract_fundamental_metrics(data.get('fundamentals_report', '')),\n",
|
|
" 'final_decisions': self._extract_decisions(data),\n",
|
|
" 'risk_assessment': self._analyze_risk_debate(data.get('risk_debate_state', {})),\n",
|
|
" 'news_sentiment': self._analyze_news_sentiment(data.get('news_report', ''))\n",
|
|
" }\n",
|
|
" \n",
|
|
" return analysis\n",
|
|
" \n",
|
|
" def _extract_technical_indicators(self, market_report):\n",
|
|
" \"\"\"Extract technical indicators from market report\"\"\"\n",
|
|
" indicators = {}\n",
|
|
" \n",
|
|
" # Price information\n",
|
|
" price_match = re.search(r'closing price.*?\\$?([\\d,]+\\.?\\d*)', market_report, re.IGNORECASE)\n",
|
|
" if price_match:\n",
|
|
" indicators['closing_price'] = float(price_match.group(1).replace(',', ''))\n",
|
|
" \n",
|
|
" # Moving averages\n",
|
|
" sma_50_match = re.search(r'50-SMA.*?\\$?([\\d,]+\\.?\\d*)', market_report, re.IGNORECASE)\n",
|
|
" if sma_50_match:\n",
|
|
" indicators['sma_50'] = float(sma_50_match.group(1).replace(',', ''))\n",
|
|
" \n",
|
|
" sma_200_match = re.search(r'200-SMA.*?\\$?([\\d,]+\\.?\\d*)', market_report, re.IGNORECASE)\n",
|
|
" if sma_200_match:\n",
|
|
" indicators['sma_200'] = float(sma_200_match.group(1).replace(',', ''))\n",
|
|
" \n",
|
|
" ema_10_match = re.search(r'10-EMA.*?\\$?([\\d,]+\\.?\\d*)', market_report, re.IGNORECASE)\n",
|
|
" if ema_10_match:\n",
|
|
" indicators['ema_10'] = float(ema_10_match.group(1).replace(',', ''))\n",
|
|
" \n",
|
|
" # MACD\n",
|
|
" macd_match = re.search(r'MACD.*?([\\d.]+)', market_report, re.IGNORECASE)\n",
|
|
" if macd_match:\n",
|
|
" indicators['macd'] = float(macd_match.group(1))\n",
|
|
" \n",
|
|
" # RSI\n",
|
|
" rsi_match = re.search(r'RSI.*?([\\d.]+)', market_report, re.IGNORECASE)\n",
|
|
" if rsi_match:\n",
|
|
" indicators['rsi'] = float(rsi_match.group(1))\n",
|
|
" \n",
|
|
" # ATR\n",
|
|
" atr_match = re.search(r'ATR.*?([\\d.]+)', market_report, re.IGNORECASE)\n",
|
|
" if atr_match:\n",
|
|
" indicators['atr'] = float(atr_match.group(1))\n",
|
|
" \n",
|
|
" return indicators\n",
|
|
" \n",
|
|
" def _extract_sentiment_metrics(self, sentiment_report):\n",
|
|
" \"\"\"Extract sentiment metrics from sentiment report\"\"\"\n",
|
|
" metrics = {}\n",
|
|
" \n",
|
|
" # Reddit mentions\n",
|
|
" mentions_match = re.search(r'(\\d+)\\s+mentions', sentiment_report, re.IGNORECASE)\n",
|
|
" if mentions_match:\n",
|
|
" metrics['reddit_mentions'] = int(mentions_match.group(1))\n",
|
|
" \n",
|
|
" # Sentiment score\n",
|
|
" sentiment_match = re.search(r'sentiment score.*?(\\d+\\.?\\d*)%?', sentiment_report, re.IGNORECASE)\n",
|
|
" if sentiment_match:\n",
|
|
" metrics['sentiment_score'] = float(sentiment_match.group(1))\n",
|
|
" \n",
|
|
" # Rule of 40 score\n",
|
|
" rule40_match = re.search(r'Rule of 40.*?(\\d+)%', sentiment_report, re.IGNORECASE)\n",
|
|
" if rule40_match:\n",
|
|
" metrics['rule_of_40'] = int(rule40_match.group(1))\n",
|
|
" \n",
|
|
" # Stock price from sentiment\n",
|
|
" price_match = re.search(r'current price.*?\\$?([\\d,]+\\.?\\d*)', sentiment_report, re.IGNORECASE)\n",
|
|
" if price_match:\n",
|
|
" metrics['current_price'] = float(price_match.group(1).replace(',', ''))\n",
|
|
" \n",
|
|
" return metrics\n",
|
|
" \n",
|
|
" def _extract_fundamental_metrics(self, fundamentals_report):\n",
|
|
" \"\"\"Extract fundamental metrics from fundamentals report\"\"\"\n",
|
|
" metrics = {}\n",
|
|
" \n",
|
|
" # Revenue\n",
|
|
" revenue_match = re.search(r'revenue.*?\\$?([\\d,]+\\.?\\d*)\\s*(billion|million)', fundamentals_report, re.IGNORECASE)\n",
|
|
" if revenue_match:\n",
|
|
" value = float(revenue_match.group(1).replace(',', ''))\n",
|
|
" unit = revenue_match.group(2).lower()\n",
|
|
" if unit == 'billion':\n",
|
|
" value *= 1000\n",
|
|
" metrics['revenue_millions'] = value\n",
|
|
" \n",
|
|
" # Revenue growth\n",
|
|
" revenue_growth_match = re.search(r'(\\d+)%.*?year-over-year', fundamentals_report, re.IGNORECASE)\n",
|
|
" if revenue_growth_match:\n",
|
|
" metrics['revenue_growth'] = int(revenue_growth_match.group(1))\n",
|
|
" \n",
|
|
" # Net income\n",
|
|
" net_income_match = re.search(r'net income.*?\\$?([\\d,]+\\.?\\d*)\\s*million', fundamentals_report, re.IGNORECASE)\n",
|
|
" if net_income_match:\n",
|
|
" metrics['net_income_millions'] = float(net_income_match.group(1).replace(',', ''))\n",
|
|
" \n",
|
|
" # Market cap\n",
|
|
" market_cap_match = re.search(r'market capitalization.*?\\$?([\\d,]+\\.?\\d*)\\s*(billion|trillion)', fundamentals_report, re.IGNORECASE)\n",
|
|
" if market_cap_match:\n",
|
|
" value = float(market_cap_match.group(1).replace(',', ''))\n",
|
|
" unit = market_cap_match.group(2).lower()\n",
|
|
" if unit == 'trillion':\n",
|
|
" value *= 1000\n",
|
|
" metrics['market_cap_billions'] = value\n",
|
|
" \n",
|
|
" return metrics\n",
|
|
" \n",
|
|
" def _extract_decisions(self, data):\n",
|
|
" \"\"\"Extract investment decisions from various reports\"\"\"\n",
|
|
" decisions = {}\n",
|
|
" \n",
|
|
" # Extract final decisions from each report\n",
|
|
" for report_type in ['market_report', 'sentiment_report', 'fundamentals_report']:\n",
|
|
" report = data.get(report_type, '')\n",
|
|
" decision_match = re.search(r'FINAL TRANSACTION PROPOSAL:\\s*\\*?\\*?([A-Z]+)', report, re.IGNORECASE)\n",
|
|
" if decision_match:\n",
|
|
" decisions[report_type] = decision_match.group(1).upper()\n",
|
|
" \n",
|
|
" # Final trade decision\n",
|
|
" final_decision = data.get('final_trade_decision', '')\n",
|
|
" if 'BUY' in final_decision.upper():\n",
|
|
" decisions['final_decision'] = 'BUY'\n",
|
|
" elif 'SELL' in final_decision.upper():\n",
|
|
" decisions['final_decision'] = 'SELL'\n",
|
|
" elif 'HOLD' in final_decision.upper():\n",
|
|
" decisions['final_decision'] = 'HOLD'\n",
|
|
" \n",
|
|
" return decisions\n",
|
|
" \n",
|
|
" def _analyze_risk_debate(self, risk_debate):\n",
|
|
" \"\"\"Analyze risk debate to extract risk assessment\"\"\"\n",
|
|
" if not risk_debate:\n",
|
|
" return {}\n",
|
|
" \n",
|
|
" risk_analysis = {}\n",
|
|
" \n",
|
|
" # Analyze judge decision\n",
|
|
" judge_decision = risk_debate.get('judge_decision', '')\n",
|
|
" if 'BUY' in judge_decision.upper():\n",
|
|
" risk_analysis['risk_adjusted_decision'] = 'BUY'\n",
|
|
" elif 'SELL' in judge_decision.upper():\n",
|
|
" risk_analysis['risk_adjusted_decision'] = 'SELL'\n",
|
|
" elif 'HOLD' in judge_decision.upper():\n",
|
|
" risk_analysis['risk_adjusted_decision'] = 'HOLD'\n",
|
|
" \n",
|
|
" # Extract position sizing\n",
|
|
" position_match = re.search(r'(\\d+\\.?\\d*)%.*?portfolio', judge_decision, re.IGNORECASE)\n",
|
|
" if position_match:\n",
|
|
" risk_analysis['recommended_position_size'] = float(position_match.group(1))\n",
|
|
" \n",
|
|
" # Extract stop loss\n",
|
|
" stop_loss_match = re.search(r'(\\d+)%.*?stop', judge_decision, re.IGNORECASE)\n",
|
|
" if stop_loss_match:\n",
|
|
" risk_analysis['stop_loss_percent'] = int(stop_loss_match.group(1))\n",
|
|
" \n",
|
|
" return risk_analysis\n",
|
|
" \n",
|
|
" def _analyze_news_sentiment(self, news_report):\n",
|
|
" \"\"\"Analyze news report for sentiment indicators\"\"\"\n",
|
|
" sentiment = {}\n",
|
|
" \n",
|
|
" # Count positive/negative words\n",
|
|
" positive_words = ['growth', 'increase', 'strong', 'positive', 'bullish', 'surge', 'rise', 'improvement']\n",
|
|
" negative_words = ['decline', 'fall', 'weak', 'negative', 'bearish', 'drop', 'concern', 'risk']\n",
|
|
" \n",
|
|
" news_lower = news_report.lower()\n",
|
|
" positive_count = sum(news_lower.count(word) for word in positive_words)\n",
|
|
" negative_count = sum(news_lower.count(word) for word in negative_words)\n",
|
|
" \n",
|
|
" if positive_count + negative_count > 0:\n",
|
|
" sentiment['news_sentiment_score'] = (positive_count - negative_count) / (positive_count + negative_count) * 100\n",
|
|
" else:\n",
|
|
" sentiment['news_sentiment_score'] = 0\n",
|
|
" \n",
|
|
" return sentiment\n",
|
|
" \n",
|
|
" def create_dashboard(self):\n",
|
|
" \"\"\"Create the main dashboard with multiple visualizations\"\"\"\n",
|
|
" fig = make_subplots(\n",
|
|
" rows=4, cols=2,\n",
|
|
" subplot_titles=(\n",
|
|
" 'Technical Indicators Overview', 'Investment Decisions Summary',\n",
|
|
" 'Sentiment Analysis', 'Fundamental Metrics',\n",
|
|
" 'Risk Assessment', 'Price vs Moving Averages',\n",
|
|
" 'Decision Consensus', 'Key Performance Metrics'\n",
|
|
" ),\n",
|
|
" specs=[[{\"secondary_y\": True}, {\"type\": \"pie\"}],\n",
|
|
" [{\"type\": \"bar\"}, {\"type\": \"bar\"}],\n",
|
|
" [{\"type\": \"indicator\"}, {\"type\": \"scatter\"}],\n",
|
|
" [{\"type\": \"bar\"}, {\"type\": \"table\"}]],\n",
|
|
" vertical_spacing=0.12,\n",
|
|
" horizontal_spacing=0.1\n",
|
|
" )\n",
|
|
" \n",
|
|
" # Extract data for visualizations\n",
|
|
" dates = list(self.analysis.keys())\n",
|
|
" latest_date = dates[0] if dates else None\n",
|
|
" \n",
|
|
" if not latest_date:\n",
|
|
" return fig\n",
|
|
" \n",
|
|
" latest_data = self.analysis[latest_date]\n",
|
|
" \n",
|
|
" # 1. Technical Indicators Radar Chart (converted to bar for simplicity)\n",
|
|
" tech_indicators = latest_data['technical_indicators']\n",
|
|
" if tech_indicators:\n",
|
|
" # RSI and normalized values for comparison\n",
|
|
" indicators = []\n",
|
|
" values = []\n",
|
|
" \n",
|
|
" if 'rsi' in tech_indicators:\n",
|
|
" indicators.append('RSI')\n",
|
|
" values.append(tech_indicators['rsi'])\n",
|
|
" \n",
|
|
" if 'macd' in tech_indicators:\n",
|
|
" indicators.append('MACD')\n",
|
|
" values.append(tech_indicators['macd'] * 10) # Scale for visibility\n",
|
|
" \n",
|
|
" if 'atr' in tech_indicators:\n",
|
|
" indicators.append('ATR')\n",
|
|
" values.append(tech_indicators['atr'] * 10) # Scale for visibility\n",
|
|
" \n",
|
|
" if indicators:\n",
|
|
" fig.add_trace(\n",
|
|
" go.Bar(x=indicators, y=values, name=\"Technical Indicators\", \n",
|
|
" marker_color=['#FF6B6B', '#4ECDC4', '#45B7D1']),\n",
|
|
" row=1, col=1\n",
|
|
" )\n",
|
|
" \n",
|
|
" # 2. Investment Decisions Pie Chart\n",
|
|
" decisions = latest_data['final_decisions']\n",
|
|
" decision_counts = {}\n",
|
|
" for decision in decisions.values():\n",
|
|
" decision_counts[decision] = decision_counts.get(decision, 0) + 1\n",
|
|
" \n",
|
|
" if decision_counts:\n",
|
|
" fig.add_trace(\n",
|
|
" go.Pie(labels=list(decision_counts.keys()), \n",
|
|
" values=list(decision_counts.values()),\n",
|
|
" hole=0.4,\n",
|
|
" marker_colors=['#FF6B6B', '#4ECDC4', '#45B7D1']),\n",
|
|
" row=1, col=2\n",
|
|
" )\n",
|
|
" \n",
|
|
" # 3. Sentiment Analysis\n",
|
|
" sentiment_data = latest_data['sentiment_metrics']\n",
|
|
" if sentiment_data:\n",
|
|
" sentiment_labels = []\n",
|
|
" sentiment_values = []\n",
|
|
" \n",
|
|
" if 'reddit_mentions' in sentiment_data:\n",
|
|
" sentiment_labels.append('Reddit Mentions')\n",
|
|
" sentiment_values.append(sentiment_data['reddit_mentions'])\n",
|
|
" \n",
|
|
" if 'sentiment_score' in sentiment_data:\n",
|
|
" sentiment_labels.append('Sentiment Score')\n",
|
|
" sentiment_values.append(sentiment_data['sentiment_score'])\n",
|
|
" \n",
|
|
" if sentiment_labels:\n",
|
|
" fig.add_trace(\n",
|
|
" go.Bar(x=sentiment_labels, y=sentiment_values, \n",
|
|
" name=\"Sentiment Metrics\",\n",
|
|
" marker_color='#FFA726'),\n",
|
|
" row=2, col=1\n",
|
|
" )\n",
|
|
" \n",
|
|
" # 4. Fundamental Metrics\n",
|
|
" fundamental_data = latest_data['fundamental_metrics']\n",
|
|
" if fundamental_data:\n",
|
|
" fund_labels = []\n",
|
|
" fund_values = []\n",
|
|
" \n",
|
|
" if 'revenue_growth' in fundamental_data:\n",
|
|
" fund_labels.append('Revenue Growth %')\n",
|
|
" fund_values.append(fundamental_data['revenue_growth'])\n",
|
|
" \n",
|
|
" if 'revenue_millions' in fundamental_data:\n",
|
|
" fund_labels.append('Revenue (M)')\n",
|
|
" fund_values.append(fundamental_data['revenue_millions'])\n",
|
|
" \n",
|
|
" if fund_labels:\n",
|
|
" fig.add_trace(\n",
|
|
" go.Bar(x=fund_labels, y=fund_values, \n",
|
|
" name=\"Fundamental Metrics\",\n",
|
|
" marker_color='#66BB6A'),\n",
|
|
" row=2, col=2\n",
|
|
" )\n",
|
|
" \n",
|
|
" # 5. Risk Assessment Gauge\n",
|
|
" risk_data = latest_data['risk_assessment']\n",
|
|
" risk_score = 50 # Default neutral\n",
|
|
" \n",
|
|
" if 'recommended_position_size' in risk_data:\n",
|
|
" # Convert position size to risk score (higher position = higher confidence = lower risk)\n",
|
|
" position_size = risk_data['recommended_position_size']\n",
|
|
" risk_score = max(0, min(100, 100 - (position_size * 10)))\n",
|
|
" \n",
|
|
" fig.add_trace(\n",
|
|
" go.Indicator(\n",
|
|
" mode=\"gauge+number+delta\",\n",
|
|
" value=risk_score,\n",
|
|
" title={'text': \"Risk Level\"},\n",
|
|
" gauge={\n",
|
|
" 'axis': {'range': [0, 100]},\n",
|
|
" 'bar': {'color': \"#FF6B6B\"},\n",
|
|
" 'steps': [\n",
|
|
" {'range': [0, 30], 'color': \"#4ECDC4\"},\n",
|
|
" {'range': [30, 70], 'color': \"#FFA726\"},\n",
|
|
" {'range': [70, 100], 'color': \"#FF6B6B\"}\n",
|
|
" ],\n",
|
|
" 'threshold': {\n",
|
|
" 'line': {'color': \"red\", 'width': 4},\n",
|
|
" 'thickness': 0.75,\n",
|
|
" 'value': 80\n",
|
|
" }\n",
|
|
" }\n",
|
|
" ),\n",
|
|
" row=3, col=1\n",
|
|
" )\n",
|
|
" \n",
|
|
" # 6. Price vs Moving Averages\n",
|
|
" if 'closing_price' in tech_indicators:\n",
|
|
" price_data = {\n",
|
|
" 'Current Price': tech_indicators.get('closing_price', 0),\n",
|
|
" '50-SMA': tech_indicators.get('sma_50', 0),\n",
|
|
" '200-SMA': tech_indicators.get('sma_200', 0),\n",
|
|
" '10-EMA': tech_indicators.get('ema_10', 0)\n",
|
|
" }\n",
|
|
" \n",
|
|
" # Filter out zero values\n",
|
|
" price_data = {k: v for k, v in price_data.items() if v > 0}\n",
|
|
" \n",
|
|
" if price_data:\n",
|
|
" fig.add_trace(\n",
|
|
" go.Scatter(x=list(price_data.keys()), \n",
|
|
" y=list(price_data.values()),\n",
|
|
" mode='lines+markers',\n",
|
|
" name=\"Price vs MA\",\n",
|
|
" line=dict(color='#9C27B0', width=3),\n",
|
|
" marker=dict(size=8)),\n",
|
|
" row=3, col=2\n",
|
|
" )\n",
|
|
" \n",
|
|
" # 7. Decision Consensus\n",
|
|
" all_decisions = list(decisions.values())\n",
|
|
" buy_count = all_decisions.count('BUY')\n",
|
|
" hold_count = all_decisions.count('HOLD')\n",
|
|
" sell_count = all_decisions.count('SELL')\n",
|
|
" \n",
|
|
" fig.add_trace(\n",
|
|
" go.Bar(x=['BUY', 'HOLD', 'SELL'], \n",
|
|
" y=[buy_count, hold_count, sell_count],\n",
|
|
" name=\"Decision Consensus\",\n",
|
|
" marker_color=['#4ECDC4', '#FFA726', '#FF6B6B']),\n",
|
|
" row=4, col=1\n",
|
|
" )\n",
|
|
" \n",
|
|
" # 8. Key Performance Metrics Table\n",
|
|
" kpi_data = []\n",
|
|
" \n",
|
|
" # Compile KPI data\n",
|
|
" if 'closing_price' in tech_indicators:\n",
|
|
" kpi_data.append(['Current Price', f\"${tech_indicators['closing_price']:.2f}\"])\n",
|
|
" if 'revenue_growth' in fundamental_data:\n",
|
|
" kpi_data.append(['Revenue Growth', f\"{fundamental_data['revenue_growth']}%\"])\n",
|
|
" if 'rule_of_40' in sentiment_data:\n",
|
|
" kpi_data.append(['Rule of 40', f\"{sentiment_data['rule_of_40']}%\"])\n",
|
|
" if 'rsi' in tech_indicators:\n",
|
|
" kpi_data.append(['RSI', f\"{tech_indicators['rsi']:.2f}\"])\n",
|
|
" \n",
|
|
" if kpi_data:\n",
|
|
" fig.add_trace(\n",
|
|
" go.Table(\n",
|
|
" header=dict(values=['Metric', 'Value'],\n",
|
|
" fill_color='#E3F2FD',\n",
|
|
" align='left',\n",
|
|
" font=dict(size=12, color='#1976D2')),\n",
|
|
" cells=dict(values=[[row[0] for row in kpi_data], \n",
|
|
" [row[1] for row in kpi_data]],\n",
|
|
" fill_color='#F8F9FA',\n",
|
|
" align='left',\n",
|
|
" font=dict(size=11))\n",
|
|
" ),\n",
|
|
" row=4, col=2\n",
|
|
" )\n",
|
|
" \n",
|
|
" # Update layout\n",
|
|
" fig.update_layout(\n",
|
|
" title=f\"Investment Analysis Dashboard - {latest_data['company']} ({latest_date})\",\n",
|
|
" title_font_size=24,\n",
|
|
" title_x=0.5,\n",
|
|
" height=1200,\n",
|
|
" showlegend=False,\n",
|
|
" plot_bgcolor='white',\n",
|
|
" paper_bgcolor='#F8F9FA',\n",
|
|
" font=dict(family=\"Arial, sans-serif\", size=10)\n",
|
|
" )\n",
|
|
" \n",
|
|
" # Update all axes\n",
|
|
" fig.update_xaxes(showgrid=True, gridwidth=1, gridcolor='#E0E0E0')\n",
|
|
" fig.update_yaxes(showgrid=True, gridwidth=1, gridcolor='#E0E0E0')\n",
|
|
" \n",
|
|
" return fig\n",
|
|
" \n",
|
|
" def create_summary_report(self):\n",
|
|
" \"\"\"Create a summary report of the analysis\"\"\"\n",
|
|
" report = {}\n",
|
|
" \n",
|
|
" for date, analysis in self.analysis.items():\n",
|
|
" company = analysis['company']\n",
|
|
" decisions = analysis['final_decisions']\n",
|
|
" \n",
|
|
" # Get most common decision\n",
|
|
" decision_list = list(decisions.values())\n",
|
|
" final_recommendation = max(set(decision_list), key=decision_list.count) if decision_list else \"UNKNOWN\"\n",
|
|
" \n",
|
|
" # Risk assessment\n",
|
|
" risk_data = analysis['risk_assessment']\n",
|
|
" position_size = risk_data.get('recommended_position_size', 'Not specified')\n",
|
|
" stop_loss = risk_data.get('stop_loss_percent', 'Not specified')\n",
|
|
" \n",
|
|
" # Key metrics\n",
|
|
" tech_indicators = analysis['technical_indicators']\n",
|
|
" fundamental_metrics = analysis['fundamental_metrics']\n",
|
|
" \n",
|
|
" report[date] = {\n",
|
|
" 'company': company,\n",
|
|
" 'final_recommendation': final_recommendation,\n",
|
|
" 'current_price': tech_indicators.get('closing_price', 'N/A'),\n",
|
|
" 'rsi': tech_indicators.get('rsi', 'N/A'),\n",
|
|
" 'revenue_growth': fundamental_metrics.get('revenue_growth', 'N/A'),\n",
|
|
" 'position_size': position_size,\n",
|
|
" 'stop_loss': stop_loss\n",
|
|
" }\n",
|
|
" \n",
|
|
" return report"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"id": "ff0c9dd5",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"\n",
|
|
"# Example usage and demo\n",
|
|
"def demo_dashboard():\n",
|
|
" \"\"\"Demo function to show how to use the dashboard\"\"\"\n",
|
|
" \n",
|
|
" # Sample JSON data structure (you can replace this with actual data)\n",
|
|
" sample_data = {\n",
|
|
" \"2025-08-01\": {\n",
|
|
" \"company_of_interest\": \"PLTR\",\n",
|
|
" \"trade_date\": \"2025-08-01\",\n",
|
|
" \"market_report\": \"The closing price on August 1, 2025, is $158.35. 50-SMA: $139.85, 200-SMA: $96.60, 10-EMA: $155.04, MACD: 5.46, RSI: 58.63, ATR: 5.41 FINAL TRANSACTION PROPOSAL: BUY\",\n",
|
|
" \"sentiment_report\": \"PLTR received 70 mentions on Reddit with a sentiment score of 58%. Rule of 40 score of 81%. Current price $160.66. FINAL TRANSACTION PROPOSAL: BUY\",\n",
|
|
" \"fundamentals_report\": \"Q2 2025 Revenue: $1 billion, 48% year-over-year growth. Net Income: $327 million, 144% increase. Market Capitalization: $360 billion. FINAL TRANSACTION PROPOSAL: HOLD\",\n",
|
|
" \"final_trade_decision\": \"BUY with 2.5% starter position, 12% stop-loss\",\n",
|
|
" \"risk_debate_state\": {\n",
|
|
" \"judge_decision\": \"BUY with 2.5% of portfolio at ~$160. Stop-loss at 12% below entry.\"\n",
|
|
" },\n",
|
|
" \"news_report\": \"Global M&A activity shows strong growth. Palantir wins $10 billion U.S. Army contract showing positive momentum.\"\n",
|
|
" }\n",
|
|
" }\n",
|
|
" \n",
|
|
" # Create dashboard\n",
|
|
" dashboard = InvestmentDashboard(json_data=sample_data)\n",
|
|
" \n",
|
|
" # Generate the dashboard\n",
|
|
" fig = dashboard.create_dashboard()\n",
|
|
" fig.show()\n",
|
|
" \n",
|
|
" # Get summary report\n",
|
|
" summary = dashboard.create_summary_report()\n",
|
|
" print(\"Summary Report:\")\n",
|
|
" print(json.dumps(summary, indent=2))\n",
|
|
" \n",
|
|
" return dashboard"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"id": "f540c44b",
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"application/vnd.plotly.v1+json": {
|
|
"config": {
|
|
"plotlyServerURL": "https://plot.ly"
|
|
},
|
|
"data": [
|
|
{
|
|
"marker": {
|
|
"color": [
|
|
"#FF6B6B",
|
|
"#4ECDC4",
|
|
"#45B7D1"
|
|
]
|
|
},
|
|
"name": "Technical Indicators",
|
|
"type": "bar",
|
|
"x": [
|
|
"RSI",
|
|
"MACD",
|
|
"ATR"
|
|
],
|
|
"xaxis": "x",
|
|
"y": [
|
|
58.63,
|
|
54.6,
|
|
54.1
|
|
],
|
|
"yaxis": "y"
|
|
},
|
|
{
|
|
"domain": {
|
|
"x": [
|
|
0.52,
|
|
0.94
|
|
],
|
|
"y": [
|
|
0.84,
|
|
1
|
|
]
|
|
},
|
|
"hole": 0.4,
|
|
"labels": [
|
|
"BUY",
|
|
"HOLD"
|
|
],
|
|
"marker": {
|
|
"colors": [
|
|
"#FF6B6B",
|
|
"#4ECDC4",
|
|
"#45B7D1"
|
|
]
|
|
},
|
|
"type": "pie",
|
|
"values": [
|
|
3,
|
|
1
|
|
]
|
|
},
|
|
{
|
|
"marker": {
|
|
"color": "#FFA726"
|
|
},
|
|
"name": "Sentiment Metrics",
|
|
"type": "bar",
|
|
"x": [
|
|
"Reddit Mentions",
|
|
"Sentiment Score"
|
|
],
|
|
"xaxis": "x2",
|
|
"y": [
|
|
70,
|
|
58
|
|
],
|
|
"yaxis": "y3"
|
|
},
|
|
{
|
|
"marker": {
|
|
"color": "#66BB6A"
|
|
},
|
|
"name": "Fundamental Metrics",
|
|
"type": "bar",
|
|
"x": [
|
|
"Revenue Growth %",
|
|
"Revenue (M)"
|
|
],
|
|
"xaxis": "x3",
|
|
"y": [
|
|
48,
|
|
1000
|
|
],
|
|
"yaxis": "y4"
|
|
},
|
|
{
|
|
"domain": {
|
|
"x": [
|
|
0,
|
|
0.42
|
|
],
|
|
"y": [
|
|
0.28,
|
|
0.44000000000000006
|
|
]
|
|
},
|
|
"gauge": {
|
|
"axis": {
|
|
"range": [
|
|
0,
|
|
100
|
|
]
|
|
},
|
|
"bar": {
|
|
"color": "#FF6B6B"
|
|
},
|
|
"steps": [
|
|
{
|
|
"color": "#4ECDC4",
|
|
"range": [
|
|
0,
|
|
30
|
|
]
|
|
},
|
|
{
|
|
"color": "#FFA726",
|
|
"range": [
|
|
30,
|
|
70
|
|
]
|
|
},
|
|
{
|
|
"color": "#FF6B6B",
|
|
"range": [
|
|
70,
|
|
100
|
|
]
|
|
}
|
|
],
|
|
"threshold": {
|
|
"line": {
|
|
"color": "red",
|
|
"width": 4
|
|
},
|
|
"thickness": 0.75,
|
|
"value": 80
|
|
}
|
|
},
|
|
"mode": "gauge+number+delta",
|
|
"title": {
|
|
"text": "Risk Level"
|
|
},
|
|
"type": "indicator",
|
|
"value": 75
|
|
},
|
|
{
|
|
"line": {
|
|
"color": "#9C27B0",
|
|
"width": 3
|
|
},
|
|
"marker": {
|
|
"size": 8
|
|
},
|
|
"mode": "lines+markers",
|
|
"name": "Price vs MA",
|
|
"type": "scatter",
|
|
"x": [
|
|
"Current Price",
|
|
"50-SMA",
|
|
"200-SMA",
|
|
"10-EMA"
|
|
],
|
|
"xaxis": "x4",
|
|
"y": [
|
|
1,
|
|
139.85,
|
|
96.6,
|
|
155.04
|
|
],
|
|
"yaxis": "y5"
|
|
},
|
|
{
|
|
"marker": {
|
|
"color": [
|
|
"#4ECDC4",
|
|
"#FFA726",
|
|
"#FF6B6B"
|
|
]
|
|
},
|
|
"name": "Decision Consensus",
|
|
"type": "bar",
|
|
"x": [
|
|
"BUY",
|
|
"HOLD",
|
|
"SELL"
|
|
],
|
|
"xaxis": "x5",
|
|
"y": [
|
|
3,
|
|
1,
|
|
0
|
|
],
|
|
"yaxis": "y6"
|
|
},
|
|
{
|
|
"cells": {
|
|
"align": "left",
|
|
"fill": {
|
|
"color": "#F8F9FA"
|
|
},
|
|
"font": {
|
|
"size": 11
|
|
},
|
|
"values": [
|
|
[
|
|
"Current Price",
|
|
"Revenue Growth",
|
|
"Rule of 40",
|
|
"RSI"
|
|
],
|
|
[
|
|
"$1.00",
|
|
"48%",
|
|
"81%",
|
|
"58.63"
|
|
]
|
|
]
|
|
},
|
|
"domain": {
|
|
"x": [
|
|
0.52,
|
|
0.94
|
|
],
|
|
"y": [
|
|
0,
|
|
0.16
|
|
]
|
|
},
|
|
"header": {
|
|
"align": "left",
|
|
"fill": {
|
|
"color": "#E3F2FD"
|
|
},
|
|
"font": {
|
|
"color": "#1976D2",
|
|
"size": 12
|
|
},
|
|
"values": [
|
|
"Metric",
|
|
"Value"
|
|
]
|
|
},
|
|
"type": "table"
|
|
}
|
|
],
|
|
"layout": {
|
|
"annotations": [
|
|
{
|
|
"font": {
|
|
"size": 16
|
|
},
|
|
"showarrow": false,
|
|
"text": "Technical Indicators Overview",
|
|
"x": 0.21,
|
|
"xanchor": "center",
|
|
"xref": "paper",
|
|
"y": 1,
|
|
"yanchor": "bottom",
|
|
"yref": "paper"
|
|
},
|
|
{
|
|
"font": {
|
|
"size": 16
|
|
},
|
|
"showarrow": false,
|
|
"text": "Investment Decisions Summary",
|
|
"x": 0.73,
|
|
"xanchor": "center",
|
|
"xref": "paper",
|
|
"y": 1,
|
|
"yanchor": "bottom",
|
|
"yref": "paper"
|
|
},
|
|
{
|
|
"font": {
|
|
"size": 16
|
|
},
|
|
"showarrow": false,
|
|
"text": "Sentiment Analysis",
|
|
"x": 0.21,
|
|
"xanchor": "center",
|
|
"xref": "paper",
|
|
"y": 0.7200000000000001,
|
|
"yanchor": "bottom",
|
|
"yref": "paper"
|
|
},
|
|
{
|
|
"font": {
|
|
"size": 16
|
|
},
|
|
"showarrow": false,
|
|
"text": "Fundamental Metrics",
|
|
"x": 0.73,
|
|
"xanchor": "center",
|
|
"xref": "paper",
|
|
"y": 0.7200000000000001,
|
|
"yanchor": "bottom",
|
|
"yref": "paper"
|
|
},
|
|
{
|
|
"font": {
|
|
"size": 16
|
|
},
|
|
"showarrow": false,
|
|
"text": "Risk Assessment",
|
|
"x": 0.21,
|
|
"xanchor": "center",
|
|
"xref": "paper",
|
|
"y": 0.44000000000000006,
|
|
"yanchor": "bottom",
|
|
"yref": "paper"
|
|
},
|
|
{
|
|
"font": {
|
|
"size": 16
|
|
},
|
|
"showarrow": false,
|
|
"text": "Price vs Moving Averages",
|
|
"x": 0.73,
|
|
"xanchor": "center",
|
|
"xref": "paper",
|
|
"y": 0.44000000000000006,
|
|
"yanchor": "bottom",
|
|
"yref": "paper"
|
|
},
|
|
{
|
|
"font": {
|
|
"size": 16
|
|
},
|
|
"showarrow": false,
|
|
"text": "Decision Consensus",
|
|
"x": 0.21,
|
|
"xanchor": "center",
|
|
"xref": "paper",
|
|
"y": 0.16,
|
|
"yanchor": "bottom",
|
|
"yref": "paper"
|
|
},
|
|
{
|
|
"font": {
|
|
"size": 16
|
|
},
|
|
"showarrow": false,
|
|
"text": "Key Performance Metrics",
|
|
"x": 0.73,
|
|
"xanchor": "center",
|
|
"xref": "paper",
|
|
"y": 0.16,
|
|
"yanchor": "bottom",
|
|
"yref": "paper"
|
|
}
|
|
],
|
|
"font": {
|
|
"family": "Arial, sans-serif",
|
|
"size": 10
|
|
},
|
|
"height": 1200,
|
|
"paper_bgcolor": "#F8F9FA",
|
|
"plot_bgcolor": "white",
|
|
"showlegend": false,
|
|
"template": {
|
|
"data": {
|
|
"bar": [
|
|
{
|
|
"error_x": {
|
|
"color": "#2a3f5f"
|
|
},
|
|
"error_y": {
|
|
"color": "#2a3f5f"
|
|
},
|
|
"marker": {
|
|
"line": {
|
|
"color": "#E5ECF6",
|
|
"width": 0.5
|
|
},
|
|
"pattern": {
|
|
"fillmode": "overlay",
|
|
"size": 10,
|
|
"solidity": 0.2
|
|
}
|
|
},
|
|
"type": "bar"
|
|
}
|
|
],
|
|
"barpolar": [
|
|
{
|
|
"marker": {
|
|
"line": {
|
|
"color": "#E5ECF6",
|
|
"width": 0.5
|
|
},
|
|
"pattern": {
|
|
"fillmode": "overlay",
|
|
"size": 10,
|
|
"solidity": 0.2
|
|
}
|
|
},
|
|
"type": "barpolar"
|
|
}
|
|
],
|
|
"carpet": [
|
|
{
|
|
"aaxis": {
|
|
"endlinecolor": "#2a3f5f",
|
|
"gridcolor": "white",
|
|
"linecolor": "white",
|
|
"minorgridcolor": "white",
|
|
"startlinecolor": "#2a3f5f"
|
|
},
|
|
"baxis": {
|
|
"endlinecolor": "#2a3f5f",
|
|
"gridcolor": "white",
|
|
"linecolor": "white",
|
|
"minorgridcolor": "white",
|
|
"startlinecolor": "#2a3f5f"
|
|
},
|
|
"type": "carpet"
|
|
}
|
|
],
|
|
"choropleth": [
|
|
{
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
},
|
|
"type": "choropleth"
|
|
}
|
|
],
|
|
"contour": [
|
|
{
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
},
|
|
"colorscale": [
|
|
[
|
|
0,
|
|
"#0d0887"
|
|
],
|
|
[
|
|
0.1111111111111111,
|
|
"#46039f"
|
|
],
|
|
[
|
|
0.2222222222222222,
|
|
"#7201a8"
|
|
],
|
|
[
|
|
0.3333333333333333,
|
|
"#9c179e"
|
|
],
|
|
[
|
|
0.4444444444444444,
|
|
"#bd3786"
|
|
],
|
|
[
|
|
0.5555555555555556,
|
|
"#d8576b"
|
|
],
|
|
[
|
|
0.6666666666666666,
|
|
"#ed7953"
|
|
],
|
|
[
|
|
0.7777777777777778,
|
|
"#fb9f3a"
|
|
],
|
|
[
|
|
0.8888888888888888,
|
|
"#fdca26"
|
|
],
|
|
[
|
|
1,
|
|
"#f0f921"
|
|
]
|
|
],
|
|
"type": "contour"
|
|
}
|
|
],
|
|
"contourcarpet": [
|
|
{
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
},
|
|
"type": "contourcarpet"
|
|
}
|
|
],
|
|
"heatmap": [
|
|
{
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
},
|
|
"colorscale": [
|
|
[
|
|
0,
|
|
"#0d0887"
|
|
],
|
|
[
|
|
0.1111111111111111,
|
|
"#46039f"
|
|
],
|
|
[
|
|
0.2222222222222222,
|
|
"#7201a8"
|
|
],
|
|
[
|
|
0.3333333333333333,
|
|
"#9c179e"
|
|
],
|
|
[
|
|
0.4444444444444444,
|
|
"#bd3786"
|
|
],
|
|
[
|
|
0.5555555555555556,
|
|
"#d8576b"
|
|
],
|
|
[
|
|
0.6666666666666666,
|
|
"#ed7953"
|
|
],
|
|
[
|
|
0.7777777777777778,
|
|
"#fb9f3a"
|
|
],
|
|
[
|
|
0.8888888888888888,
|
|
"#fdca26"
|
|
],
|
|
[
|
|
1,
|
|
"#f0f921"
|
|
]
|
|
],
|
|
"type": "heatmap"
|
|
}
|
|
],
|
|
"histogram": [
|
|
{
|
|
"marker": {
|
|
"pattern": {
|
|
"fillmode": "overlay",
|
|
"size": 10,
|
|
"solidity": 0.2
|
|
}
|
|
},
|
|
"type": "histogram"
|
|
}
|
|
],
|
|
"histogram2d": [
|
|
{
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
},
|
|
"colorscale": [
|
|
[
|
|
0,
|
|
"#0d0887"
|
|
],
|
|
[
|
|
0.1111111111111111,
|
|
"#46039f"
|
|
],
|
|
[
|
|
0.2222222222222222,
|
|
"#7201a8"
|
|
],
|
|
[
|
|
0.3333333333333333,
|
|
"#9c179e"
|
|
],
|
|
[
|
|
0.4444444444444444,
|
|
"#bd3786"
|
|
],
|
|
[
|
|
0.5555555555555556,
|
|
"#d8576b"
|
|
],
|
|
[
|
|
0.6666666666666666,
|
|
"#ed7953"
|
|
],
|
|
[
|
|
0.7777777777777778,
|
|
"#fb9f3a"
|
|
],
|
|
[
|
|
0.8888888888888888,
|
|
"#fdca26"
|
|
],
|
|
[
|
|
1,
|
|
"#f0f921"
|
|
]
|
|
],
|
|
"type": "histogram2d"
|
|
}
|
|
],
|
|
"histogram2dcontour": [
|
|
{
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
},
|
|
"colorscale": [
|
|
[
|
|
0,
|
|
"#0d0887"
|
|
],
|
|
[
|
|
0.1111111111111111,
|
|
"#46039f"
|
|
],
|
|
[
|
|
0.2222222222222222,
|
|
"#7201a8"
|
|
],
|
|
[
|
|
0.3333333333333333,
|
|
"#9c179e"
|
|
],
|
|
[
|
|
0.4444444444444444,
|
|
"#bd3786"
|
|
],
|
|
[
|
|
0.5555555555555556,
|
|
"#d8576b"
|
|
],
|
|
[
|
|
0.6666666666666666,
|
|
"#ed7953"
|
|
],
|
|
[
|
|
0.7777777777777778,
|
|
"#fb9f3a"
|
|
],
|
|
[
|
|
0.8888888888888888,
|
|
"#fdca26"
|
|
],
|
|
[
|
|
1,
|
|
"#f0f921"
|
|
]
|
|
],
|
|
"type": "histogram2dcontour"
|
|
}
|
|
],
|
|
"mesh3d": [
|
|
{
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
},
|
|
"type": "mesh3d"
|
|
}
|
|
],
|
|
"parcoords": [
|
|
{
|
|
"line": {
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
}
|
|
},
|
|
"type": "parcoords"
|
|
}
|
|
],
|
|
"pie": [
|
|
{
|
|
"automargin": true,
|
|
"type": "pie"
|
|
}
|
|
],
|
|
"scatter": [
|
|
{
|
|
"fillpattern": {
|
|
"fillmode": "overlay",
|
|
"size": 10,
|
|
"solidity": 0.2
|
|
},
|
|
"type": "scatter"
|
|
}
|
|
],
|
|
"scatter3d": [
|
|
{
|
|
"line": {
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
}
|
|
},
|
|
"marker": {
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
}
|
|
},
|
|
"type": "scatter3d"
|
|
}
|
|
],
|
|
"scattercarpet": [
|
|
{
|
|
"marker": {
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
}
|
|
},
|
|
"type": "scattercarpet"
|
|
}
|
|
],
|
|
"scattergeo": [
|
|
{
|
|
"marker": {
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
}
|
|
},
|
|
"type": "scattergeo"
|
|
}
|
|
],
|
|
"scattergl": [
|
|
{
|
|
"marker": {
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
}
|
|
},
|
|
"type": "scattergl"
|
|
}
|
|
],
|
|
"scattermap": [
|
|
{
|
|
"marker": {
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
}
|
|
},
|
|
"type": "scattermap"
|
|
}
|
|
],
|
|
"scattermapbox": [
|
|
{
|
|
"marker": {
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
}
|
|
},
|
|
"type": "scattermapbox"
|
|
}
|
|
],
|
|
"scatterpolar": [
|
|
{
|
|
"marker": {
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
}
|
|
},
|
|
"type": "scatterpolar"
|
|
}
|
|
],
|
|
"scatterpolargl": [
|
|
{
|
|
"marker": {
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
}
|
|
},
|
|
"type": "scatterpolargl"
|
|
}
|
|
],
|
|
"scatterternary": [
|
|
{
|
|
"marker": {
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
}
|
|
},
|
|
"type": "scatterternary"
|
|
}
|
|
],
|
|
"surface": [
|
|
{
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
},
|
|
"colorscale": [
|
|
[
|
|
0,
|
|
"#0d0887"
|
|
],
|
|
[
|
|
0.1111111111111111,
|
|
"#46039f"
|
|
],
|
|
[
|
|
0.2222222222222222,
|
|
"#7201a8"
|
|
],
|
|
[
|
|
0.3333333333333333,
|
|
"#9c179e"
|
|
],
|
|
[
|
|
0.4444444444444444,
|
|
"#bd3786"
|
|
],
|
|
[
|
|
0.5555555555555556,
|
|
"#d8576b"
|
|
],
|
|
[
|
|
0.6666666666666666,
|
|
"#ed7953"
|
|
],
|
|
[
|
|
0.7777777777777778,
|
|
"#fb9f3a"
|
|
],
|
|
[
|
|
0.8888888888888888,
|
|
"#fdca26"
|
|
],
|
|
[
|
|
1,
|
|
"#f0f921"
|
|
]
|
|
],
|
|
"type": "surface"
|
|
}
|
|
],
|
|
"table": [
|
|
{
|
|
"cells": {
|
|
"fill": {
|
|
"color": "#EBF0F8"
|
|
},
|
|
"line": {
|
|
"color": "white"
|
|
}
|
|
},
|
|
"header": {
|
|
"fill": {
|
|
"color": "#C8D4E3"
|
|
},
|
|
"line": {
|
|
"color": "white"
|
|
}
|
|
},
|
|
"type": "table"
|
|
}
|
|
]
|
|
},
|
|
"layout": {
|
|
"annotationdefaults": {
|
|
"arrowcolor": "#2a3f5f",
|
|
"arrowhead": 0,
|
|
"arrowwidth": 1
|
|
},
|
|
"autotypenumbers": "strict",
|
|
"coloraxis": {
|
|
"colorbar": {
|
|
"outlinewidth": 0,
|
|
"ticks": ""
|
|
}
|
|
},
|
|
"colorscale": {
|
|
"diverging": [
|
|
[
|
|
0,
|
|
"#8e0152"
|
|
],
|
|
[
|
|
0.1,
|
|
"#c51b7d"
|
|
],
|
|
[
|
|
0.2,
|
|
"#de77ae"
|
|
],
|
|
[
|
|
0.3,
|
|
"#f1b6da"
|
|
],
|
|
[
|
|
0.4,
|
|
"#fde0ef"
|
|
],
|
|
[
|
|
0.5,
|
|
"#f7f7f7"
|
|
],
|
|
[
|
|
0.6,
|
|
"#e6f5d0"
|
|
],
|
|
[
|
|
0.7,
|
|
"#b8e186"
|
|
],
|
|
[
|
|
0.8,
|
|
"#7fbc41"
|
|
],
|
|
[
|
|
0.9,
|
|
"#4d9221"
|
|
],
|
|
[
|
|
1,
|
|
"#276419"
|
|
]
|
|
],
|
|
"sequential": [
|
|
[
|
|
0,
|
|
"#0d0887"
|
|
],
|
|
[
|
|
0.1111111111111111,
|
|
"#46039f"
|
|
],
|
|
[
|
|
0.2222222222222222,
|
|
"#7201a8"
|
|
],
|
|
[
|
|
0.3333333333333333,
|
|
"#9c179e"
|
|
],
|
|
[
|
|
0.4444444444444444,
|
|
"#bd3786"
|
|
],
|
|
[
|
|
0.5555555555555556,
|
|
"#d8576b"
|
|
],
|
|
[
|
|
0.6666666666666666,
|
|
"#ed7953"
|
|
],
|
|
[
|
|
0.7777777777777778,
|
|
"#fb9f3a"
|
|
],
|
|
[
|
|
0.8888888888888888,
|
|
"#fdca26"
|
|
],
|
|
[
|
|
1,
|
|
"#f0f921"
|
|
]
|
|
],
|
|
"sequentialminus": [
|
|
[
|
|
0,
|
|
"#0d0887"
|
|
],
|
|
[
|
|
0.1111111111111111,
|
|
"#46039f"
|
|
],
|
|
[
|
|
0.2222222222222222,
|
|
"#7201a8"
|
|
],
|
|
[
|
|
0.3333333333333333,
|
|
"#9c179e"
|
|
],
|
|
[
|
|
0.4444444444444444,
|
|
"#bd3786"
|
|
],
|
|
[
|
|
0.5555555555555556,
|
|
"#d8576b"
|
|
],
|
|
[
|
|
0.6666666666666666,
|
|
"#ed7953"
|
|
],
|
|
[
|
|
0.7777777777777778,
|
|
"#fb9f3a"
|
|
],
|
|
[
|
|
0.8888888888888888,
|
|
"#fdca26"
|
|
],
|
|
[
|
|
1,
|
|
"#f0f921"
|
|
]
|
|
]
|
|
},
|
|
"colorway": [
|
|
"#636efa",
|
|
"#EF553B",
|
|
"#00cc96",
|
|
"#ab63fa",
|
|
"#FFA15A",
|
|
"#19d3f3",
|
|
"#FF6692",
|
|
"#B6E880",
|
|
"#FF97FF",
|
|
"#FECB52"
|
|
],
|
|
"font": {
|
|
"color": "#2a3f5f"
|
|
},
|
|
"geo": {
|
|
"bgcolor": "white",
|
|
"lakecolor": "white",
|
|
"landcolor": "#E5ECF6",
|
|
"showlakes": true,
|
|
"showland": true,
|
|
"subunitcolor": "white"
|
|
},
|
|
"hoverlabel": {
|
|
"align": "left"
|
|
},
|
|
"hovermode": "closest",
|
|
"mapbox": {
|
|
"style": "light"
|
|
},
|
|
"paper_bgcolor": "white",
|
|
"plot_bgcolor": "#E5ECF6",
|
|
"polar": {
|
|
"angularaxis": {
|
|
"gridcolor": "white",
|
|
"linecolor": "white",
|
|
"ticks": ""
|
|
},
|
|
"bgcolor": "#E5ECF6",
|
|
"radialaxis": {
|
|
"gridcolor": "white",
|
|
"linecolor": "white",
|
|
"ticks": ""
|
|
}
|
|
},
|
|
"scene": {
|
|
"xaxis": {
|
|
"backgroundcolor": "#E5ECF6",
|
|
"gridcolor": "white",
|
|
"gridwidth": 2,
|
|
"linecolor": "white",
|
|
"showbackground": true,
|
|
"ticks": "",
|
|
"zerolinecolor": "white"
|
|
},
|
|
"yaxis": {
|
|
"backgroundcolor": "#E5ECF6",
|
|
"gridcolor": "white",
|
|
"gridwidth": 2,
|
|
"linecolor": "white",
|
|
"showbackground": true,
|
|
"ticks": "",
|
|
"zerolinecolor": "white"
|
|
},
|
|
"zaxis": {
|
|
"backgroundcolor": "#E5ECF6",
|
|
"gridcolor": "white",
|
|
"gridwidth": 2,
|
|
"linecolor": "white",
|
|
"showbackground": true,
|
|
"ticks": "",
|
|
"zerolinecolor": "white"
|
|
}
|
|
},
|
|
"shapedefaults": {
|
|
"line": {
|
|
"color": "#2a3f5f"
|
|
}
|
|
},
|
|
"ternary": {
|
|
"aaxis": {
|
|
"gridcolor": "white",
|
|
"linecolor": "white",
|
|
"ticks": ""
|
|
},
|
|
"baxis": {
|
|
"gridcolor": "white",
|
|
"linecolor": "white",
|
|
"ticks": ""
|
|
},
|
|
"bgcolor": "#E5ECF6",
|
|
"caxis": {
|
|
"gridcolor": "white",
|
|
"linecolor": "white",
|
|
"ticks": ""
|
|
}
|
|
},
|
|
"title": {
|
|
"x": 0.05
|
|
},
|
|
"xaxis": {
|
|
"automargin": true,
|
|
"gridcolor": "white",
|
|
"linecolor": "white",
|
|
"ticks": "",
|
|
"title": {
|
|
"standoff": 15
|
|
},
|
|
"zerolinecolor": "white",
|
|
"zerolinewidth": 2
|
|
},
|
|
"yaxis": {
|
|
"automargin": true,
|
|
"gridcolor": "white",
|
|
"linecolor": "white",
|
|
"ticks": "",
|
|
"title": {
|
|
"standoff": 15
|
|
},
|
|
"zerolinecolor": "white",
|
|
"zerolinewidth": 2
|
|
}
|
|
}
|
|
},
|
|
"title": {
|
|
"font": {
|
|
"size": 24
|
|
},
|
|
"text": "Investment Analysis Dashboard - PLTR (2025-08-01)",
|
|
"x": 0.5
|
|
},
|
|
"xaxis": {
|
|
"anchor": "y",
|
|
"domain": [
|
|
0,
|
|
0.42
|
|
],
|
|
"gridcolor": "#E0E0E0",
|
|
"gridwidth": 1,
|
|
"showgrid": true
|
|
},
|
|
"xaxis2": {
|
|
"anchor": "y3",
|
|
"domain": [
|
|
0,
|
|
0.42
|
|
],
|
|
"gridcolor": "#E0E0E0",
|
|
"gridwidth": 1,
|
|
"showgrid": true
|
|
},
|
|
"xaxis3": {
|
|
"anchor": "y4",
|
|
"domain": [
|
|
0.52,
|
|
0.94
|
|
],
|
|
"gridcolor": "#E0E0E0",
|
|
"gridwidth": 1,
|
|
"showgrid": true
|
|
},
|
|
"xaxis4": {
|
|
"anchor": "y5",
|
|
"domain": [
|
|
0.52,
|
|
0.94
|
|
],
|
|
"gridcolor": "#E0E0E0",
|
|
"gridwidth": 1,
|
|
"showgrid": true
|
|
},
|
|
"xaxis5": {
|
|
"anchor": "y6",
|
|
"domain": [
|
|
0,
|
|
0.42
|
|
],
|
|
"gridcolor": "#E0E0E0",
|
|
"gridwidth": 1,
|
|
"showgrid": true
|
|
},
|
|
"yaxis": {
|
|
"anchor": "x",
|
|
"domain": [
|
|
0.84,
|
|
1
|
|
],
|
|
"gridcolor": "#E0E0E0",
|
|
"gridwidth": 1,
|
|
"showgrid": true
|
|
},
|
|
"yaxis2": {
|
|
"anchor": "x",
|
|
"gridcolor": "#E0E0E0",
|
|
"gridwidth": 1,
|
|
"overlaying": "y",
|
|
"showgrid": true,
|
|
"side": "right"
|
|
},
|
|
"yaxis3": {
|
|
"anchor": "x2",
|
|
"domain": [
|
|
0.56,
|
|
0.7200000000000001
|
|
],
|
|
"gridcolor": "#E0E0E0",
|
|
"gridwidth": 1,
|
|
"showgrid": true
|
|
},
|
|
"yaxis4": {
|
|
"anchor": "x3",
|
|
"domain": [
|
|
0.56,
|
|
0.7200000000000001
|
|
],
|
|
"gridcolor": "#E0E0E0",
|
|
"gridwidth": 1,
|
|
"showgrid": true
|
|
},
|
|
"yaxis5": {
|
|
"anchor": "x4",
|
|
"domain": [
|
|
0.28,
|
|
0.44000000000000006
|
|
],
|
|
"gridcolor": "#E0E0E0",
|
|
"gridwidth": 1,
|
|
"showgrid": true
|
|
},
|
|
"yaxis6": {
|
|
"anchor": "x5",
|
|
"domain": [
|
|
0,
|
|
0.16
|
|
],
|
|
"gridcolor": "#E0E0E0",
|
|
"gridwidth": 1,
|
|
"showgrid": true
|
|
}
|
|
}
|
|
}
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
},
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"Summary Report:\n",
|
|
"{\n",
|
|
" \"2025-08-01\": {\n",
|
|
" \"company\": \"PLTR\",\n",
|
|
" \"final_recommendation\": \"BUY\",\n",
|
|
" \"current_price\": 1.0,\n",
|
|
" \"rsi\": 58.63,\n",
|
|
" \"revenue_growth\": 48,\n",
|
|
" \"position_size\": 2.5,\n",
|
|
" \"stop_loss\": 5\n",
|
|
" }\n",
|
|
"}\n"
|
|
]
|
|
},
|
|
{
|
|
"data": {
|
|
"text/plain": [
|
|
"<__main__.InvestmentDashboard at 0x7f5fd4fac920>"
|
|
]
|
|
},
|
|
"execution_count": 4,
|
|
"metadata": {},
|
|
"output_type": "execute_result"
|
|
}
|
|
],
|
|
"source": [
|
|
"# Run demo\n",
|
|
"demo_dashboard()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "35f59ac0",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"dashboard = InvestmentDashboard(json_file_path=\"path/to/your/file.json\")\n",
|
|
"fig = dashboard.create_dashboard()\n",
|
|
"fig.show()\n",
|
|
"summary = dashboard.create_summary_report()\n",
|
|
"\n",
|
|
"\n"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "Trading Agents",
|
|
"language": "python",
|
|
"name": "trading_agents"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.12.3"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|