AI Image and Audio Generation Improvements.
AI Video Generation Pre-Flight Checklist. Cost Estimate Improvements.
This commit is contained in:
@@ -1,190 +0,0 @@
|
||||
# AI Finance Report Generator
|
||||
|
||||
An advanced AI-powered financial analysis and report generation system that combines data collection, technical analysis, visualization, and automated report generation.
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
ai_finance_report_generator/
|
||||
├── ai_financial_dashboard.py # Main dashboard interface
|
||||
├── utils/ # Utility functions
|
||||
│ ├── __init__.py
|
||||
│ └── storage.py # Data persistence
|
||||
├── reports/ # Report generation modules
|
||||
│ ├── technical_analysis/ # Technical analysis reports
|
||||
│ ├── fundamental_analysis/ # Fundamental analysis reports
|
||||
│ ├── options_analysis/ # Options analysis reports
|
||||
│ ├── portfolio_analysis/ # Portfolio analysis reports
|
||||
│ ├── market_research/ # Market research reports
|
||||
│ └── news_analysis/ # News analysis reports
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
### Current Features
|
||||
- Unified dashboard interface for all financial analysis tools
|
||||
- Technical Analysis report generation
|
||||
- Options analysis report generation
|
||||
- User preferences management
|
||||
- Recent reports tracking
|
||||
- Data persistence with JSON storage
|
||||
- Financial data collection from various sources
|
||||
- Integration with LLM for report generation
|
||||
|
||||
### Planned Features
|
||||
|
||||
#### 1. Data Collection Module
|
||||
- Web scraping for financial news and data
|
||||
- API integrations (Yahoo Finance, Alpha Vantage, Financial Modeling Prep)
|
||||
- Real-time market data collection
|
||||
- Historical data retrieval
|
||||
- Company financial statements
|
||||
- Market sentiment data
|
||||
- Economic indicators
|
||||
- Sector analysis data
|
||||
|
||||
#### 2. Technical Analysis Module
|
||||
- Moving averages (SMA, EMA, WMA)
|
||||
- RSI, MACD, Bollinger Bands
|
||||
- Volume analysis
|
||||
- Support/Resistance levels
|
||||
- Trend analysis
|
||||
- Pattern recognition
|
||||
- Fibonacci retracements
|
||||
- Momentum indicators
|
||||
|
||||
#### 3. Fundamental Analysis Module
|
||||
- Financial ratios calculation
|
||||
- Company valuation metrics
|
||||
- Growth analysis
|
||||
- Profitability analysis
|
||||
- Debt analysis
|
||||
- Cash flow analysis
|
||||
- Industry comparison
|
||||
- Peer analysis
|
||||
|
||||
#### 4. Data Visualization Module
|
||||
- Candlestick charts
|
||||
- Technical indicator overlays
|
||||
- Volume charts
|
||||
- Price action patterns
|
||||
- Correlation matrices
|
||||
- Heat maps
|
||||
- Interactive charts
|
||||
- Custom chart templates
|
||||
|
||||
#### 5. Report Generation Module
|
||||
- Technical analysis reports
|
||||
- Fundamental analysis reports
|
||||
- Market research reports
|
||||
- Investment recommendations
|
||||
- Risk assessment reports
|
||||
- Sector analysis reports
|
||||
- News impact analysis
|
||||
- Custom report templates
|
||||
|
||||
#### 6. News and Sentiment Analysis Module
|
||||
- News aggregation
|
||||
- Sentiment scoring
|
||||
- Social media analysis
|
||||
- Market sentiment indicators
|
||||
- News impact analysis
|
||||
- Event correlation
|
||||
- Trend detection
|
||||
- Sentiment visualization
|
||||
|
||||
#### 7. Portfolio Analysis Module
|
||||
- Portfolio performance analysis
|
||||
- Risk assessment
|
||||
- Asset allocation
|
||||
- Correlation analysis
|
||||
- Diversification metrics
|
||||
- Performance attribution
|
||||
- Portfolio optimization
|
||||
- Rebalancing suggestions
|
||||
|
||||
## Usage
|
||||
|
||||
### Basic Usage
|
||||
|
||||
```python
|
||||
from lib.ai_writers.ai_finance_report_generator.ai_financial_dashboard import get_dashboard
|
||||
|
||||
# Get dashboard instance
|
||||
dashboard = get_dashboard()
|
||||
|
||||
# Generate technical analysis report
|
||||
ta_report = dashboard.generate_technical_analysis("AAPL")
|
||||
|
||||
# Generate options analysis report
|
||||
options_report = dashboard.generate_options_analysis("AAPL")
|
||||
|
||||
# Get recent reports
|
||||
recent_reports = dashboard.get_recent_reports()
|
||||
```
|
||||
|
||||
### User Preferences
|
||||
|
||||
```python
|
||||
# Update user preferences
|
||||
dashboard.update_preferences({
|
||||
"report_format": "markdown",
|
||||
"include_charts": True,
|
||||
"chart_style": "dark",
|
||||
"language": "en"
|
||||
})
|
||||
|
||||
# Get current preferences
|
||||
preferences = dashboard.get_preferences()
|
||||
```
|
||||
|
||||
### Portfolio Analysis
|
||||
|
||||
```python
|
||||
# Create portfolio
|
||||
portfolio = [
|
||||
{"symbol": "AAPL", "shares": 100},
|
||||
{"symbol": "GOOGL", "shares": 50}
|
||||
]
|
||||
|
||||
# Generate portfolio report
|
||||
portfolio_report = dashboard.generate_portfolio_analysis(portfolio)
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install -r requirements.txt
|
||||
```
|
||||
|
||||
## Dependencies
|
||||
|
||||
1. **Data Collection**
|
||||
- `finance_data_researcher`
|
||||
- `web_scraping_tools`
|
||||
|
||||
2. **Analysis Tools**
|
||||
- `pandas_ta`
|
||||
- `numpy`
|
||||
- `scipy`
|
||||
|
||||
3. **Visualization**
|
||||
- `matplotlib`
|
||||
- `plotly`
|
||||
|
||||
4. **Text Generation**
|
||||
- `llm_text_gen`
|
||||
- `gpt_providers`
|
||||
|
||||
## Contributing
|
||||
|
||||
1. Fork the repository
|
||||
2. Create your feature branch (`git checkout -b feature/AmazingFeature`)
|
||||
3. Commit your changes (`git commit -m 'Add some AmazingFeature'`)
|
||||
4. Push to the branch (`git push origin feature/AmazingFeature`)
|
||||
5. Open a Pull Request
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the MIT License - see the LICENSE file for details.
|
||||
@@ -1,358 +0,0 @@
|
||||
"""
|
||||
AI Financial Dashboard Module
|
||||
|
||||
This module combines the financial dashboard interface with financial report generation capabilities.
|
||||
It provides a unified interface for managing financial analysis tools and generating reports.
|
||||
"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
from textwrap import dedent
|
||||
from pathlib import Path
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Any, Optional, Union
|
||||
|
||||
from loguru import logger
|
||||
logger.remove()
|
||||
logger.add(sys.stdout,
|
||||
colorize=True,
|
||||
format="<level>{level}</level>|<green>{file}:{line}:{function}</green>| {message}"
|
||||
)
|
||||
|
||||
from ...ai_web_researcher.finance_data_researcher import get_finance_data, get_fin_options_data
|
||||
from ...gpt_providers.text_generation.main_text_generation import llm_text_gen
|
||||
from .utils import get_feature_status
|
||||
from .utils.storage import get_storage_manager
|
||||
|
||||
class UserPreferences:
|
||||
"""Class to manage user preferences and settings."""
|
||||
|
||||
def __init__(self):
|
||||
self.default_settings = {
|
||||
"theme": "light",
|
||||
"currency": "USD",
|
||||
"timezone": "UTC",
|
||||
"date_format": "%Y-%m-%d",
|
||||
"default_symbols": [],
|
||||
"notifications": True,
|
||||
"auto_refresh": False,
|
||||
"refresh_interval": 300, # 5 minutes
|
||||
"report_format": "markdown",
|
||||
"include_charts": True,
|
||||
"chart_style": "default",
|
||||
"language": "en"
|
||||
}
|
||||
self.settings = self.default_settings.copy()
|
||||
self.storage = get_storage_manager()
|
||||
self.load_settings()
|
||||
|
||||
def update_setting(self, key: str, value: Any) -> None:
|
||||
"""Update a specific setting."""
|
||||
if key in self.default_settings:
|
||||
self.settings[key] = value
|
||||
self.save_settings()
|
||||
|
||||
def get_setting(self, key: str) -> Any:
|
||||
"""Get a specific setting value."""
|
||||
return self.settings.get(key, self.default_settings.get(key))
|
||||
|
||||
def reset_settings(self) -> None:
|
||||
"""Reset all settings to default values."""
|
||||
self.settings = self.default_settings.copy()
|
||||
self.save_settings()
|
||||
|
||||
def save_settings(self) -> None:
|
||||
"""Save current settings to storage."""
|
||||
self.storage.save_user_preferences(self.settings)
|
||||
|
||||
def load_settings(self) -> None:
|
||||
"""Load settings from storage."""
|
||||
stored_settings = self.storage.load_user_preferences()
|
||||
if stored_settings:
|
||||
self.settings.update(stored_settings)
|
||||
|
||||
class RecentReport:
|
||||
"""Class to represent a recently generated report."""
|
||||
|
||||
def __init__(self, report_type: str, symbol: Optional[str], timestamp: datetime, content: Optional[str] = None):
|
||||
self.report_type = report_type
|
||||
self.symbol = symbol
|
||||
self.timestamp = timestamp
|
||||
self.content = content
|
||||
self.id = f"{report_type}_{symbol}_{timestamp.strftime('%Y%m%d%H%M%S')}"
|
||||
|
||||
def to_dict(self) -> Dict[str, Any]:
|
||||
"""Convert report to dictionary format."""
|
||||
return {
|
||||
"id": self.id,
|
||||
"type": self.report_type,
|
||||
"symbol": self.symbol,
|
||||
"timestamp": self.timestamp.isoformat(),
|
||||
"content": self.content
|
||||
}
|
||||
|
||||
@classmethod
|
||||
def from_dict(cls, data: Dict[str, Any]) -> 'RecentReport':
|
||||
"""Create report from dictionary format."""
|
||||
return cls(
|
||||
report_type=data["type"],
|
||||
symbol=data["symbol"],
|
||||
timestamp=datetime.fromisoformat(data["timestamp"]),
|
||||
content=data.get("content")
|
||||
)
|
||||
|
||||
class FinancialDashboard:
|
||||
"""Main dashboard class for managing financial analysis tools and generating reports."""
|
||||
|
||||
def __init__(self):
|
||||
self.features = {
|
||||
"technical_analysis": {
|
||||
"name": "Technical Analysis",
|
||||
"description": "Generate technical analysis reports with indicators and patterns",
|
||||
"icon": "📊",
|
||||
"route": "/technical-analysis",
|
||||
"category": "analysis",
|
||||
"dependencies": ["data_collection"],
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"fundamental_analysis": {
|
||||
"name": "Fundamental Analysis",
|
||||
"description": "Analyze company financials and valuation metrics",
|
||||
"icon": "📈",
|
||||
"route": "/fundamental-analysis",
|
||||
"category": "analysis",
|
||||
"dependencies": ["data_collection"],
|
||||
"version": "0.1.0"
|
||||
},
|
||||
"options_analysis": {
|
||||
"name": "Options Analysis",
|
||||
"description": "Analyze options chains and generate trading strategies",
|
||||
"icon": "⚡",
|
||||
"route": "/options-analysis",
|
||||
"category": "analysis",
|
||||
"dependencies": ["data_collection", "options_data"],
|
||||
"version": "1.0.0"
|
||||
},
|
||||
"portfolio_analysis": {
|
||||
"name": "Portfolio Analysis",
|
||||
"description": "Analyze portfolio performance and risk metrics",
|
||||
"icon": "📑",
|
||||
"route": "/portfolio-analysis",
|
||||
"category": "portfolio",
|
||||
"dependencies": ["data_collection", "portfolio_data"],
|
||||
"version": "0.1.0"
|
||||
},
|
||||
"market_research": {
|
||||
"name": "Market Research",
|
||||
"description": "Generate market research reports and sector analysis",
|
||||
"icon": "🔍",
|
||||
"route": "/market-research",
|
||||
"category": "research",
|
||||
"dependencies": ["data_collection", "news_data"],
|
||||
"version": "0.1.0"
|
||||
},
|
||||
"news_analysis": {
|
||||
"name": "News Analysis",
|
||||
"description": "Analyze news impact and market sentiment",
|
||||
"icon": "📰",
|
||||
"route": "/news-analysis",
|
||||
"category": "research",
|
||||
"dependencies": ["data_collection", "news_data"],
|
||||
"version": "0.1.0"
|
||||
}
|
||||
}
|
||||
|
||||
self.user_preferences = UserPreferences()
|
||||
self.storage = get_storage_manager()
|
||||
self.recent_reports: List[RecentReport] = []
|
||||
self.max_recent_reports = 10
|
||||
self.load_recent_reports()
|
||||
|
||||
def get_all_features(self) -> List[Dict[str, Any]]:
|
||||
"""Get all available features with their status."""
|
||||
features_list = []
|
||||
for feature_id, feature_info in self.features.items():
|
||||
status = get_feature_status(feature_id)
|
||||
feature_info.update(status)
|
||||
features_list.append(feature_info)
|
||||
return features_list
|
||||
|
||||
def get_feature(self, feature_id: str) -> Dict[str, Any]:
|
||||
"""Get information about a specific feature."""
|
||||
if feature_id not in self.features:
|
||||
raise ValueError(f"Feature {feature_id} not found")
|
||||
|
||||
feature_info = self.features[feature_id].copy()
|
||||
status = get_feature_status(feature_id)
|
||||
feature_info.update(status)
|
||||
return feature_info
|
||||
|
||||
def get_implemented_features(self) -> List[Dict[str, Any]]:
|
||||
"""Get only the implemented features."""
|
||||
return [f for f in self.get_all_features() if f["implemented"]]
|
||||
|
||||
def get_coming_soon_features(self) -> List[Dict[str, Any]]:
|
||||
"""Get features that are coming soon."""
|
||||
return [f for f in self.get_all_features() if f["coming_soon"]]
|
||||
|
||||
def get_features_by_category(self, category: str) -> List[Dict[str, Any]]:
|
||||
"""Get features filtered by category."""
|
||||
return [f for f in self.get_all_features() if f["category"] == category]
|
||||
|
||||
def add_recent_report(self, report_type: str, symbol: Optional[str] = None, content: Optional[str] = None) -> None:
|
||||
"""Add a report to the recent reports list."""
|
||||
report = RecentReport(report_type, symbol, datetime.now(), content)
|
||||
self.recent_reports.insert(0, report)
|
||||
if len(self.recent_reports) > self.max_recent_reports:
|
||||
self.recent_reports.pop()
|
||||
self.save_recent_reports()
|
||||
|
||||
def get_recent_reports(self, limit: Optional[int] = None) -> List[Dict[str, Any]]:
|
||||
"""Get recent reports."""
|
||||
reports = self.recent_reports[:limit] if limit else self.recent_reports
|
||||
return [{
|
||||
**r.to_dict(),
|
||||
"feature_info": self.get_feature(r.report_type)
|
||||
} for r in reports]
|
||||
|
||||
def save_recent_reports(self) -> None:
|
||||
"""Save recent reports to storage."""
|
||||
reports_data = [r.to_dict() for r in self.recent_reports]
|
||||
self.storage.save_recent_reports(reports_data)
|
||||
|
||||
def load_recent_reports(self) -> None:
|
||||
"""Load recent reports from storage."""
|
||||
reports_data = self.storage.load_recent_reports()
|
||||
self.recent_reports = [RecentReport.from_dict(r) for r in reports_data]
|
||||
|
||||
def get_dashboard_summary(self) -> Dict[str, Any]:
|
||||
"""Get a summary of the dashboard state."""
|
||||
return {
|
||||
"total_features": len(self.features),
|
||||
"implemented_features": len(self.get_implemented_features()),
|
||||
"coming_soon_features": len(self.get_coming_soon_features()),
|
||||
"recent_reports": len(self.recent_reports),
|
||||
"categories": list(set(f["category"] for f in self.features.values())),
|
||||
"user_preferences": self.user_preferences.settings
|
||||
}
|
||||
|
||||
def check_feature_dependencies(self, feature_id: str) -> Dict[str, bool]:
|
||||
"""Check if all dependencies for a feature are met."""
|
||||
if feature_id not in self.features:
|
||||
raise ValueError(f"Feature {feature_id} not found")
|
||||
|
||||
feature = self.features[feature_id]
|
||||
dependencies = feature.get("dependencies", [])
|
||||
|
||||
return {
|
||||
dep: get_feature_status(dep)["implemented"]
|
||||
for dep in dependencies
|
||||
}
|
||||
|
||||
def backup_data(self, backup_dir: Optional[str] = None) -> None:
|
||||
"""Create a backup of all dashboard data."""
|
||||
self.storage.backup_storage(backup_dir)
|
||||
|
||||
def restore_from_backup(self, backup_file: str) -> None:
|
||||
"""Restore dashboard data from a backup file."""
|
||||
self.storage.restore_from_backup(backup_file)
|
||||
self.user_preferences.load_settings()
|
||||
self.load_recent_reports()
|
||||
|
||||
def generate_technical_analysis(self, symbol: str) -> str:
|
||||
"""Generate a technical analysis report for the given symbol."""
|
||||
try:
|
||||
# Get financial data
|
||||
symbol_fin_data = get_finance_data(symbol)
|
||||
|
||||
# Generate report
|
||||
report_content = self._generate_ta_report(symbol_fin_data, symbol)
|
||||
|
||||
# Add to recent reports
|
||||
self.add_recent_report("technical_analysis", symbol, report_content)
|
||||
|
||||
logger.info(f"Done: Final Technical Analysis for {symbol}")
|
||||
return report_content
|
||||
|
||||
except Exception as err:
|
||||
logger.error(f"Error: Failed to generate Technical Analysis report: {err}")
|
||||
raise
|
||||
|
||||
def generate_options_analysis(self, symbol: str) -> str:
|
||||
"""Generate an options analysis report for the given symbol."""
|
||||
try:
|
||||
# Get options data
|
||||
options_data = get_fin_options_data(symbol)
|
||||
|
||||
# Generate report
|
||||
report_content = self._generate_options_report(options_data, symbol)
|
||||
|
||||
# Add to recent reports
|
||||
self.add_recent_report("options_analysis", symbol, report_content)
|
||||
|
||||
logger.info(f"Done: Options Analysis for {symbol}")
|
||||
return report_content
|
||||
|
||||
except Exception as err:
|
||||
logger.error(f"Error: Failed to generate Options Analysis report: {err}")
|
||||
raise
|
||||
|
||||
def _generate_ta_report(self, last_day_summary: str, symbol: str) -> str:
|
||||
"""Generate technical analysis report using LLM."""
|
||||
prompt = f"""
|
||||
You are a seasoned Technical Analysis (TA) expert, rivaling legends like Charles Dow, John Bollinger, and Alan Andrews.
|
||||
Your deep understanding of market dynamics, coupled with mastery of technical indicators,
|
||||
allows you to decipher complex patterns and offer precise predictions.
|
||||
|
||||
Your expertise extends to practical tools like the pandas_ta module, enabling you to extract valuable insights from raw data.
|
||||
|
||||
**Objective:**
|
||||
Analyze the provided technical indicators for {symbol} on its last trading day and predict its price movement over the next few trading sessions.
|
||||
|
||||
**Instructions:**
|
||||
1. **Identify Potential Trading Signals:** Highlight specific indicators suggesting bullish, bearish, or neutral signals. Explain the rationale behind each signal, referencing historical patterns or comparable market scenarios.
|
||||
2. **Detect Patterns and Divergences:** Analyze the interplay between different indicators. Detect patterns like moving average crossovers, candlestick formations, or divergences between price action and indicators. Explain the significance of each pattern.
|
||||
3. **Price Movement Prediction:** Based on your analysis, provide a clear prediction for {symbol}'s price movement in the next few days. State the expected direction (up, down, sideways) and potential price targets if identifiable.
|
||||
4. **Risk Assessment:** Briefly discuss any potential risks or factors that could invalidate your predictions, promoting a balanced and informed perspective.
|
||||
|
||||
**Technical Indicators for {symbol} on the Last Trading Day:**
|
||||
{last_day_summary}
|
||||
|
||||
Remember, your analysis should be detailed, insightful, and actionable for traders seeking to capitalize on market movements.
|
||||
"""
|
||||
|
||||
try:
|
||||
return llm_text_gen(prompt)
|
||||
except Exception as err:
|
||||
logger.error(f"Failed to generate TA report: {err}")
|
||||
raise
|
||||
|
||||
def _generate_options_report(self, results_sentences: List[str], ticker: str) -> str:
|
||||
"""Generate options analysis report using LLM."""
|
||||
prompt = f"""
|
||||
You are a financial expert specializing in options trading and market sentiment analysis.
|
||||
You have been provided with the following technical analysis of options data for the ticker symbol {ticker} with the nearest expiry date:
|
||||
|
||||
{chr(10).join(results_sentences)}
|
||||
|
||||
Based on this data, provide a comprehensive analysis of the options market for {ticker}.
|
||||
|
||||
Your analysis should include:
|
||||
|
||||
1. **Implied Volatility Interpretation:** Discuss the significance of the average implied volatility for both call and put options. What does it suggest about market expectations of future price movements?
|
||||
2. **Volume and Open Interest Insights:** Analyze the volume and open interest for call and put options. What does this data reveal about current market positioning and potential future trading activity?
|
||||
3. **Sentiment Analysis:** Evaluate the put-call ratio, implied volatility skew, and overall market sentiment. What do these indicators suggest about trader sentiment and potential future price direction?
|
||||
4. **Potential Trading Strategies:** Based on your analysis, suggest potential options trading strategies that could be employed for {ticker}, considering the current market conditions and sentiment.
|
||||
|
||||
Please provide your analysis in a clear and concise manner, suitable for someone with a good understanding of options trading.
|
||||
"""
|
||||
|
||||
try:
|
||||
return llm_text_gen(prompt)
|
||||
except Exception as err:
|
||||
logger.error(f"Failed to generate options report: {err}")
|
||||
raise
|
||||
|
||||
def get_dashboard() -> FinancialDashboard:
|
||||
"""Get the financial dashboard instance."""
|
||||
return FinancialDashboard()
|
||||
@@ -1,265 +0,0 @@
|
||||
# Financial Reports Module
|
||||
|
||||
This directory contains the core report generation modules for different types of financial analysis. Each module is designed to handle a specific type of financial report and can be accessed through the main dashboard interface.
|
||||
|
||||
## Directory Structure
|
||||
|
||||
```
|
||||
reports/
|
||||
├── technical_analysis/ # Technical analysis reports
|
||||
├── fundamental_analysis/ # Fundamental analysis reports
|
||||
├── options_analysis/ # Options analysis reports
|
||||
├── portfolio_analysis/ # Portfolio analysis reports
|
||||
├── market_research/ # Market research reports
|
||||
└── news_analysis/ # News analysis reports
|
||||
```
|
||||
|
||||
## Report Types
|
||||
|
||||
### 1. Technical Analysis Reports
|
||||
Location: `technical_analysis/`
|
||||
|
||||
Generates technical analysis reports including:
|
||||
- Moving averages (SMA, EMA, WMA)
|
||||
- RSI, MACD, Bollinger Bands
|
||||
- Volume analysis
|
||||
- Support/Resistance levels
|
||||
- Trend analysis
|
||||
- Pattern recognition
|
||||
|
||||
Usage:
|
||||
```python
|
||||
from lib.ai_writers.ai_finance_report_generator.reports.technical_analysis import generate_ta_report
|
||||
|
||||
report = generate_ta_report("AAPL")
|
||||
```
|
||||
|
||||
### 2. Fundamental Analysis Reports
|
||||
Location: `fundamental_analysis/`
|
||||
|
||||
Generates fundamental analysis reports including:
|
||||
- Financial ratios
|
||||
- Company valuation metrics
|
||||
- Growth analysis
|
||||
- Profitability analysis
|
||||
- Debt analysis
|
||||
- Cash flow analysis
|
||||
|
||||
Usage:
|
||||
```python
|
||||
from lib.ai_writers.ai_finance_report_generator.reports.fundamental_analysis import generate_fa_report
|
||||
|
||||
report = generate_fa_report("AAPL")
|
||||
```
|
||||
|
||||
### 3. Options Analysis Reports
|
||||
Location: `options_analysis/`
|
||||
|
||||
Generates options analysis reports including:
|
||||
- Options chain analysis
|
||||
- Implied volatility analysis
|
||||
- Options strategies
|
||||
- Risk metrics
|
||||
- Greeks analysis
|
||||
|
||||
Usage:
|
||||
```python
|
||||
from lib.ai_writers.ai_finance_report_generator.reports.options_analysis import generate_options_report
|
||||
|
||||
report = generate_options_report("AAPL")
|
||||
```
|
||||
|
||||
### 4. Portfolio Analysis Reports
|
||||
Location: `portfolio_analysis/`
|
||||
|
||||
Generates portfolio analysis reports including:
|
||||
- Portfolio performance analysis
|
||||
- Risk assessment
|
||||
- Asset allocation
|
||||
- Correlation analysis
|
||||
- Diversification metrics
|
||||
- Performance attribution
|
||||
|
||||
Usage:
|
||||
```python
|
||||
from lib.ai_writers.ai_finance_report_generator.reports.portfolio_analysis import generate_portfolio_report
|
||||
|
||||
portfolio = [
|
||||
{"symbol": "AAPL", "shares": 100},
|
||||
{"symbol": "GOOGL", "shares": 50}
|
||||
]
|
||||
report = generate_portfolio_report(portfolio)
|
||||
```
|
||||
|
||||
### 5. Market Research Reports
|
||||
Location: `market_research/`
|
||||
|
||||
Generates market research reports including:
|
||||
- Sector analysis
|
||||
- Industry trends
|
||||
- Market overview
|
||||
- Competitive analysis
|
||||
- Market opportunities
|
||||
- Risk factors
|
||||
|
||||
Usage:
|
||||
```python
|
||||
from lib.ai_writers.ai_finance_report_generator.reports.market_research import generate_market_research_report
|
||||
|
||||
report = generate_market_research_report(sectors=["Technology", "Healthcare"])
|
||||
```
|
||||
|
||||
### 6. News Analysis Reports
|
||||
Location: `news_analysis/`
|
||||
|
||||
Generates news analysis reports including:
|
||||
- News sentiment analysis
|
||||
- Market impact analysis
|
||||
- Event correlation
|
||||
- Trend detection
|
||||
- Social media analysis
|
||||
- News aggregation
|
||||
|
||||
Usage:
|
||||
```python
|
||||
from lib.ai_writers.ai_finance_report_generator.reports.news_analysis import generate_news_analysis_report
|
||||
|
||||
report = generate_news_analysis_report("AAPL")
|
||||
```
|
||||
|
||||
## Common Features
|
||||
|
||||
All report modules share the following features:
|
||||
|
||||
1. **Data Validation**
|
||||
- Input validation for symbols and parameters
|
||||
- Error handling for invalid inputs
|
||||
- Data type checking
|
||||
|
||||
2. **Report Formatting**
|
||||
- Markdown formatting
|
||||
- Chart generation (when applicable)
|
||||
- Customizable templates
|
||||
|
||||
3. **Storage Integration**
|
||||
- Automatic report storage
|
||||
- Recent reports tracking
|
||||
- Report versioning
|
||||
|
||||
4. **User Preferences**
|
||||
- Customizable report formats
|
||||
- Language selection
|
||||
- Chart style preferences
|
||||
|
||||
## Integration with Dashboard
|
||||
|
||||
All report modules are integrated with the main dashboard and can be accessed through the `FinancialDashboard` class:
|
||||
|
||||
```python
|
||||
from lib.ai_writers.ai_finance_report_generator.ai_financial_dashboard import get_dashboard
|
||||
|
||||
dashboard = get_dashboard()
|
||||
|
||||
# Generate reports through dashboard
|
||||
ta_report = dashboard.generate_technical_analysis("AAPL")
|
||||
options_report = dashboard.generate_options_analysis("AAPL")
|
||||
|
||||
# Get recent reports
|
||||
recent_reports = dashboard.get_recent_reports()
|
||||
```
|
||||
|
||||
## Adding New Report Types
|
||||
|
||||
To add a new report type:
|
||||
|
||||
1. Create a new directory in the `reports/` folder
|
||||
2. Create an `__init__.py` file with the report generation function
|
||||
3. Add the report type to the dashboard features
|
||||
4. Implement the report generation logic
|
||||
5. Add appropriate error handling and validation
|
||||
|
||||
Example:
|
||||
```python
|
||||
# reports/new_analysis/__init__.py
|
||||
from typing import Dict, Any
|
||||
from ...utils import validate_symbol
|
||||
|
||||
def generate_new_analysis_report(symbol: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Generate a new type of analysis report.
|
||||
|
||||
Args:
|
||||
symbol (str): Stock symbol to analyze
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Analysis report
|
||||
"""
|
||||
if not validate_symbol(symbol):
|
||||
raise ValueError("Invalid symbol provided")
|
||||
|
||||
# Implement report generation logic
|
||||
return {
|
||||
"symbol": symbol,
|
||||
"analysis": "Report content"
|
||||
}
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
All report modules implement consistent error handling:
|
||||
|
||||
1. **Input Validation**
|
||||
- Symbol validation
|
||||
- Parameter validation
|
||||
- Data type checking
|
||||
|
||||
2. **Data Collection Errors**
|
||||
- API errors
|
||||
- Network errors
|
||||
- Data format errors
|
||||
|
||||
3. **Report Generation Errors**
|
||||
- LLM errors
|
||||
- Template errors
|
||||
- Formatting errors
|
||||
|
||||
4. **Storage Errors**
|
||||
- File system errors
|
||||
- Database errors
|
||||
- Backup errors
|
||||
|
||||
## Contributing
|
||||
|
||||
When contributing to the reports module:
|
||||
|
||||
1. Follow the existing code structure
|
||||
2. Add appropriate type hints
|
||||
3. Include comprehensive docstrings
|
||||
4. Add error handling
|
||||
5. Update the dashboard integration
|
||||
6. Add tests for new functionality
|
||||
|
||||
## Dependencies
|
||||
|
||||
The reports module depends on:
|
||||
|
||||
1. **Data Collection**
|
||||
- `finance_data_researcher`
|
||||
- `web_scraping_tools`
|
||||
|
||||
2. **Analysis Tools**
|
||||
- `pandas_ta`
|
||||
- `numpy`
|
||||
- `scipy`
|
||||
|
||||
3. **Visualization**
|
||||
- `matplotlib`
|
||||
- `plotly`
|
||||
|
||||
4. **Text Generation**
|
||||
- `llm_text_gen`
|
||||
- `gpt_providers`
|
||||
|
||||
## License
|
||||
|
||||
This module is part of the AI Finance Report Generator project and is licensed under the MIT License.
|
||||
@@ -1,34 +0,0 @@
|
||||
"""
|
||||
Fundamental Analysis Reports Module
|
||||
|
||||
This module handles the generation of fundamental analysis reports including:
|
||||
- Financial ratios
|
||||
- Company valuation metrics
|
||||
- Growth analysis
|
||||
- Profitability analysis
|
||||
- Debt analysis
|
||||
- Cash flow analysis
|
||||
"""
|
||||
|
||||
from typing import Dict, Any
|
||||
from ...utils import validate_symbol
|
||||
|
||||
def generate_fa_report(symbol: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Generate a fundamental analysis report for the given symbol.
|
||||
|
||||
Args:
|
||||
symbol (str): Stock symbol to analyze
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Fundamental analysis report
|
||||
"""
|
||||
if not validate_symbol(symbol):
|
||||
raise ValueError("Invalid symbol provided")
|
||||
|
||||
# TODO: Implement fundamental analysis report generation
|
||||
return {
|
||||
"symbol": symbol,
|
||||
"status": "coming_soon",
|
||||
"message": "Fundamental analysis report generation is coming soon"
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
"""
|
||||
Market Research Reports Module
|
||||
|
||||
This module handles the generation of market research reports including:
|
||||
- Sector analysis
|
||||
- Industry trends
|
||||
- Market overview
|
||||
- Competitive analysis
|
||||
- Market opportunities
|
||||
- Risk factors
|
||||
"""
|
||||
|
||||
from typing import Dict, Any, List
|
||||
|
||||
def generate_market_research_report(sectors: List[str] = None) -> Dict[str, Any]:
|
||||
"""
|
||||
Generate a market research report.
|
||||
|
||||
Args:
|
||||
sectors (List[str], optional): List of sectors to analyze
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Market research report
|
||||
"""
|
||||
# TODO: Implement market research report generation
|
||||
return {
|
||||
"status": "coming_soon",
|
||||
"message": "Market research report generation is coming soon"
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
"""
|
||||
News Analysis Reports Module
|
||||
|
||||
This module handles the generation of news analysis reports including:
|
||||
- News sentiment analysis
|
||||
- Market impact analysis
|
||||
- Event correlation
|
||||
- Trend detection
|
||||
- Social media analysis
|
||||
- News aggregation
|
||||
"""
|
||||
|
||||
from typing import Dict, Any, List
|
||||
from ...utils import validate_symbol
|
||||
|
||||
def generate_news_analysis_report(symbol: str = None) -> Dict[str, Any]:
|
||||
"""
|
||||
Generate a news analysis report.
|
||||
|
||||
Args:
|
||||
symbol (str, optional): Stock symbol to analyze news for
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: News analysis report
|
||||
"""
|
||||
if symbol and not validate_symbol(symbol):
|
||||
raise ValueError("Invalid symbol provided")
|
||||
|
||||
# TODO: Implement news analysis report generation
|
||||
return {
|
||||
"status": "coming_soon",
|
||||
"message": "News analysis report generation is coming soon"
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
"""
|
||||
Options Analysis Reports Module
|
||||
|
||||
This module handles the generation of options analysis reports including:
|
||||
- Options chain analysis
|
||||
- Implied volatility analysis
|
||||
- Options strategies
|
||||
- Risk metrics
|
||||
- Greeks analysis
|
||||
"""
|
||||
|
||||
from typing import Dict, Any
|
||||
from ...utils import validate_symbol
|
||||
|
||||
def generate_options_report(symbol: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Generate an options analysis report for the given symbol.
|
||||
|
||||
Args:
|
||||
symbol (str): Stock symbol to analyze
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Options analysis report
|
||||
"""
|
||||
if not validate_symbol(symbol):
|
||||
raise ValueError("Invalid symbol provided")
|
||||
|
||||
# TODO: Implement options analysis report generation
|
||||
return {
|
||||
"symbol": symbol,
|
||||
"status": "coming_soon",
|
||||
"message": "Options analysis report generation is coming soon"
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
"""
|
||||
Portfolio Analysis Reports Module
|
||||
|
||||
This module handles the generation of portfolio analysis reports including:
|
||||
- Portfolio performance analysis
|
||||
- Risk assessment
|
||||
- Asset allocation
|
||||
- Correlation analysis
|
||||
- Diversification metrics
|
||||
- Performance attribution
|
||||
"""
|
||||
|
||||
from typing import Dict, Any, List
|
||||
|
||||
def generate_portfolio_report(portfolio: List[Dict[str, Any]]) -> Dict[str, Any]:
|
||||
"""
|
||||
Generate a portfolio analysis report.
|
||||
|
||||
Args:
|
||||
portfolio (List[Dict[str, Any]]): List of portfolio positions
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Portfolio analysis report
|
||||
"""
|
||||
if not portfolio:
|
||||
raise ValueError("Portfolio cannot be empty")
|
||||
|
||||
# TODO: Implement portfolio analysis report generation
|
||||
return {
|
||||
"status": "coming_soon",
|
||||
"message": "Portfolio analysis report generation is coming soon"
|
||||
}
|
||||
@@ -1,314 +0,0 @@
|
||||
"""
|
||||
Technical Analysis Reports Module
|
||||
|
||||
This module handles the generation of technical analysis reports using yfinance data and pandas_ta for indicators.
|
||||
"""
|
||||
|
||||
from typing import Dict, Any, List, Optional
|
||||
import yfinance as yf
|
||||
import pandas as pd
|
||||
import pandas_ta as ta
|
||||
import plotly.graph_objects as go
|
||||
from datetime import datetime, timedelta
|
||||
from loguru import logger
|
||||
from ...utils import validate_symbol
|
||||
from ...ai_financial_dashboard import get_dashboard
|
||||
|
||||
class TechnicalAnalysis:
|
||||
def __init__(self, symbol: str, timeframe: str = "1d", period: str = "1y"):
|
||||
"""
|
||||
Initialize Technical Analysis.
|
||||
|
||||
Args:
|
||||
symbol (str): Stock symbol to analyze
|
||||
timeframe (str): Data timeframe (1m, 5m, 15m, 30m, 1h, 1d, 1wk, 1mo)
|
||||
period (str): Data period (1d, 5d, 1mo, 3mo, 6mo, 1y, 2y, 5y, 10y, ytd, max)
|
||||
"""
|
||||
logger.info(f"Initializing Technical Analysis for {symbol} with timeframe {timeframe} and period {period}")
|
||||
self.symbol = symbol
|
||||
self.timeframe = timeframe
|
||||
self.period = period
|
||||
self.data = None
|
||||
self.indicators = {}
|
||||
self.stock = yf.Ticker(symbol)
|
||||
|
||||
def fetch_data(self) -> None:
|
||||
"""Fetch historical price data using yfinance"""
|
||||
try:
|
||||
logger.info(f"Fetching historical data for {self.symbol}")
|
||||
# Get historical data
|
||||
self.data = self.stock.history(period=self.period, interval=self.timeframe)
|
||||
logger.debug(f"Retrieved {len(self.data)} data points")
|
||||
|
||||
# Get additional info
|
||||
logger.info("Fetching company information")
|
||||
self.info = self.stock.info
|
||||
|
||||
# Calculate basic metrics
|
||||
logger.debug("Calculating basic metrics")
|
||||
self.data['Returns'] = self.data['Close'].pct_change()
|
||||
self.data['Volatility'] = self.data['Returns'].rolling(window=20).std()
|
||||
|
||||
logger.success(f"Successfully fetched data for {self.symbol}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error fetching data for {self.symbol}: {str(e)}")
|
||||
raise ValueError(f"Error fetching data for {self.symbol}: {str(e)}")
|
||||
|
||||
def calculate_indicators(self) -> None:
|
||||
"""Calculate technical indicators using pandas_ta"""
|
||||
if self.data is None:
|
||||
logger.error("Data not fetched. Call fetch_data() first.")
|
||||
raise ValueError("Data not fetched. Call fetch_data() first.")
|
||||
|
||||
logger.info("Calculating technical indicators")
|
||||
|
||||
# Moving Averages
|
||||
logger.debug("Calculating Moving Averages")
|
||||
self.indicators['sma_20'] = self.data.ta.sma(length=20)
|
||||
self.indicators['sma_50'] = self.data.ta.sma(length=50)
|
||||
self.indicators['sma_200'] = self.data.ta.sma(length=200)
|
||||
self.indicators['ema_20'] = self.data.ta.ema(length=20)
|
||||
|
||||
# RSI
|
||||
logger.debug("Calculating RSI")
|
||||
self.indicators['rsi'] = self.data.ta.rsi()
|
||||
|
||||
# MACD
|
||||
logger.debug("Calculating MACD")
|
||||
macd = self.data.ta.macd()
|
||||
self.indicators['macd'] = macd['MACD_12_26_9']
|
||||
self.indicators['macd_signal'] = macd['MACDs_12_26_9']
|
||||
self.indicators['macd_hist'] = macd['MACDh_12_26_9']
|
||||
|
||||
# Bollinger Bands
|
||||
logger.debug("Calculating Bollinger Bands")
|
||||
bbands = self.data.ta.bbands()
|
||||
self.indicators['bb_upper'] = bbands['BBU_20_2.0']
|
||||
self.indicators['bb_middle'] = bbands['BBM_20_2.0']
|
||||
self.indicators['bb_lower'] = bbands['BBL_20_2.0']
|
||||
|
||||
# Volume Analysis
|
||||
logger.debug("Calculating Volume indicators")
|
||||
self.indicators['volume_sma'] = self.data['Volume'].rolling(window=20).mean()
|
||||
self.indicators['obv'] = self.data.ta.obv()
|
||||
|
||||
# Additional Indicators
|
||||
logger.debug("Calculating additional indicators")
|
||||
self.indicators['stoch'] = self.data.ta.stoch()
|
||||
self.indicators['adx'] = self.data.ta.adx()
|
||||
self.indicators['atr'] = self.data.ta.atr()
|
||||
|
||||
logger.success("Successfully calculated all technical indicators")
|
||||
|
||||
def identify_patterns(self) -> List[Dict[str, Any]]:
|
||||
"""Identify chart patterns"""
|
||||
logger.info("Identifying chart patterns")
|
||||
patterns = []
|
||||
|
||||
# Candlestick Patterns
|
||||
if len(self.data) >= 3:
|
||||
logger.debug("Analyzing candlestick patterns")
|
||||
# Doji
|
||||
doji = self.data.ta.cdl_doji()
|
||||
if doji['CDL_DOJI'].iloc[-1] != 0:
|
||||
logger.debug("Doji pattern detected")
|
||||
patterns.append({
|
||||
'type': 'doji',
|
||||
'date': self.data.index[-1],
|
||||
'significance': 'neutral'
|
||||
})
|
||||
|
||||
# Engulfing
|
||||
engulfing = self.data.ta.cdl_engulfing()
|
||||
if engulfing['CDL_ENGULFING'].iloc[-1] != 0:
|
||||
logger.debug("Engulfing pattern detected")
|
||||
patterns.append({
|
||||
'type': 'engulfing',
|
||||
'date': self.data.index[-1],
|
||||
'significance': 'bullish' if engulfing['CDL_ENGULFING'].iloc[-1] > 0 else 'bearish'
|
||||
})
|
||||
|
||||
logger.info(f"Identified {len(patterns)} patterns")
|
||||
return patterns
|
||||
|
||||
def find_support_resistance(self) -> Dict[str, List[float]]:
|
||||
"""Find support and resistance levels using price action"""
|
||||
logger.info("Finding support and resistance levels")
|
||||
levels = {
|
||||
'support': [],
|
||||
'resistance': []
|
||||
}
|
||||
|
||||
# Use recent price action to identify levels
|
||||
recent_data = self.data.tail(100)
|
||||
logger.debug(f"Analyzing {len(recent_data)} recent data points for S/R levels")
|
||||
|
||||
# Find local minima and maxima
|
||||
for i in range(2, len(recent_data) - 2):
|
||||
# Support level
|
||||
if (recent_data['Low'].iloc[i] < recent_data['Low'].iloc[i-1] and
|
||||
recent_data['Low'].iloc[i] < recent_data['Low'].iloc[i-2] and
|
||||
recent_data['Low'].iloc[i] < recent_data['Low'].iloc[i+1] and
|
||||
recent_data['Low'].iloc[i] < recent_data['Low'].iloc[i+2]):
|
||||
levels['support'].append(recent_data['Low'].iloc[i])
|
||||
|
||||
# Resistance level
|
||||
if (recent_data['High'].iloc[i] > recent_data['High'].iloc[i-1] and
|
||||
recent_data['High'].iloc[i] > recent_data['High'].iloc[i-2] and
|
||||
recent_data['High'].iloc[i] > recent_data['High'].iloc[i+1] and
|
||||
recent_data['High'].iloc[i] > recent_data['High'].iloc[i+2]):
|
||||
levels['resistance'].append(recent_data['High'].iloc[i])
|
||||
|
||||
# Remove duplicates and sort
|
||||
levels['support'] = sorted(list(set(levels['support'])))
|
||||
levels['resistance'] = sorted(list(set(levels['resistance'])))
|
||||
|
||||
logger.info(f"Found {len(levels['support'])} support and {len(levels['resistance'])} resistance levels")
|
||||
return levels
|
||||
|
||||
def generate_chart(self) -> go.Figure:
|
||||
"""Generate interactive chart using plotly"""
|
||||
logger.info("Generating interactive chart")
|
||||
fig = go.Figure()
|
||||
|
||||
# Candlestick chart
|
||||
logger.debug("Adding candlestick chart")
|
||||
fig.add_trace(go.Candlestick(
|
||||
x=self.data.index,
|
||||
open=self.data['Open'],
|
||||
high=self.data['High'],
|
||||
low=self.data['Low'],
|
||||
close=self.data['Close'],
|
||||
name='Price'
|
||||
))
|
||||
|
||||
# Moving Averages
|
||||
logger.debug("Adding moving averages")
|
||||
fig.add_trace(go.Scatter(
|
||||
x=self.data.index,
|
||||
y=self.indicators['sma_20'],
|
||||
name='SMA 20',
|
||||
line=dict(color='blue')
|
||||
))
|
||||
|
||||
fig.add_trace(go.Scatter(
|
||||
x=self.data.index,
|
||||
y=self.indicators['sma_50'],
|
||||
name='SMA 50',
|
||||
line=dict(color='orange')
|
||||
))
|
||||
|
||||
# Bollinger Bands
|
||||
logger.debug("Adding Bollinger Bands")
|
||||
fig.add_trace(go.Scatter(
|
||||
x=self.data.index,
|
||||
y=self.indicators['bb_upper'],
|
||||
name='BB Upper',
|
||||
line=dict(color='gray', dash='dash')
|
||||
))
|
||||
|
||||
fig.add_trace(go.Scatter(
|
||||
x=self.data.index,
|
||||
y=self.indicators['bb_lower'],
|
||||
name='BB Lower',
|
||||
line=dict(color='gray', dash='dash'),
|
||||
fill='tonexty'
|
||||
))
|
||||
|
||||
# Volume
|
||||
logger.debug("Adding volume bars")
|
||||
fig.add_trace(go.Bar(
|
||||
x=self.data.index,
|
||||
y=self.data['Volume'],
|
||||
name='Volume',
|
||||
marker_color='rgba(0,0,255,0.3)'
|
||||
))
|
||||
|
||||
# Layout
|
||||
logger.debug("Setting chart layout")
|
||||
fig.update_layout(
|
||||
title=f'{self.symbol} Technical Analysis',
|
||||
yaxis_title='Price',
|
||||
xaxis_title='Date',
|
||||
template='plotly_dark'
|
||||
)
|
||||
|
||||
logger.success("Successfully generated chart")
|
||||
return fig
|
||||
|
||||
def _generate_summary(self) -> Dict[str, Any]:
|
||||
"""Generate summary of technical analysis"""
|
||||
logger.info("Generating analysis summary")
|
||||
current_price = self.data['Close'].iloc[-1]
|
||||
sma_20 = self.indicators['sma_20'].iloc[-1]
|
||||
sma_50 = self.indicators['sma_50'].iloc[-1]
|
||||
rsi = self.indicators['rsi'].iloc[-1]
|
||||
|
||||
summary = {
|
||||
'current_price': current_price,
|
||||
'price_change': self.data['Returns'].iloc[-1] * 100,
|
||||
'trend': 'bullish' if current_price > sma_20 > sma_50 else 'bearish',
|
||||
'rsi_signal': 'overbought' if rsi > 70 else 'oversold' if rsi < 30 else 'neutral',
|
||||
'volatility': self.data['Volatility'].iloc[-1],
|
||||
'volume_trend': 'increasing' if self.data['Volume'].iloc[-1] > self.indicators['volume_sma'].iloc[-1] else 'decreasing'
|
||||
}
|
||||
|
||||
logger.debug(f"Analysis summary: {summary}")
|
||||
return summary
|
||||
|
||||
def generate_report(self) -> Dict[str, Any]:
|
||||
"""Generate comprehensive technical analysis report"""
|
||||
logger.info(f"Generating comprehensive report for {self.symbol}")
|
||||
|
||||
self.fetch_data()
|
||||
self.calculate_indicators()
|
||||
patterns = self.identify_patterns()
|
||||
levels = self.find_support_resistance()
|
||||
chart = self.generate_chart()
|
||||
summary = self._generate_summary()
|
||||
|
||||
report = {
|
||||
'symbol': self.symbol,
|
||||
'timestamp': datetime.now(),
|
||||
'company_info': self.info,
|
||||
'indicators': self.indicators,
|
||||
'patterns': patterns,
|
||||
'levels': levels,
|
||||
'chart': chart,
|
||||
'summary': summary
|
||||
}
|
||||
|
||||
logger.success(f"Successfully generated report for {self.symbol}")
|
||||
return report
|
||||
|
||||
def generate_ta_report(symbol: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Generate a technical analysis report for the given symbol.
|
||||
|
||||
Args:
|
||||
symbol (str): Stock symbol to analyze
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Technical analysis report
|
||||
"""
|
||||
logger.info(f"Generating technical analysis report for {symbol}")
|
||||
|
||||
if not validate_symbol(symbol):
|
||||
logger.error(f"Invalid symbol provided: {symbol}")
|
||||
raise ValueError("Invalid symbol provided")
|
||||
|
||||
try:
|
||||
analysis = TechnicalAnalysis(symbol)
|
||||
report = analysis.generate_report()
|
||||
|
||||
# Add to dashboard's recent reports
|
||||
dashboard = get_dashboard()
|
||||
dashboard.add_recent_report("technical_analysis", symbol, report)
|
||||
|
||||
logger.success(f"Successfully completed technical analysis for {symbol}")
|
||||
return report
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error generating technical analysis report for {symbol}: {str(e)}")
|
||||
raise
|
||||
@@ -1,62 +0,0 @@
|
||||
"""
|
||||
Utility functions and helpers for the AI Finance Report Generator.
|
||||
"""
|
||||
|
||||
from typing import Dict, List, Any
|
||||
import logging
|
||||
|
||||
# Configure logging
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def validate_symbol(symbol: str) -> bool:
|
||||
"""
|
||||
Validate if the given symbol is in correct format.
|
||||
|
||||
Args:
|
||||
symbol (str): Stock symbol to validate
|
||||
|
||||
Returns:
|
||||
bool: True if valid, False otherwise
|
||||
"""
|
||||
if not isinstance(symbol, str):
|
||||
return False
|
||||
return len(symbol.strip()) > 0
|
||||
|
||||
def format_currency(value: float) -> str:
|
||||
"""
|
||||
Format number as currency.
|
||||
|
||||
Args:
|
||||
value (float): Number to format
|
||||
|
||||
Returns:
|
||||
str: Formatted currency string
|
||||
"""
|
||||
return f"${value:,.2f}"
|
||||
|
||||
def get_feature_status(feature_name: str) -> Dict[str, Any]:
|
||||
"""
|
||||
Get the status of a feature.
|
||||
|
||||
Args:
|
||||
feature_name (str): Name of the feature
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: Feature status information
|
||||
"""
|
||||
# This will be expanded as we implement more features
|
||||
implemented_features = {
|
||||
"technical_analysis": True,
|
||||
"options_analysis": True,
|
||||
}
|
||||
|
||||
return {
|
||||
"name": feature_name,
|
||||
"implemented": implemented_features.get(feature_name, False),
|
||||
"coming_soon": not implemented_features.get(feature_name, False)
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
"""
|
||||
Storage Module for AI Finance Report Generator
|
||||
|
||||
This module handles the persistence of user preferences and recent reports using JSON files.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
from typing import Dict, List, Any, Optional
|
||||
from datetime import datetime
|
||||
from pathlib import Path
|
||||
|
||||
class StorageManager:
|
||||
"""Manages storage operations for user preferences and recent reports."""
|
||||
|
||||
def __init__(self, base_dir: Optional[str] = None):
|
||||
"""
|
||||
Initialize the storage manager.
|
||||
|
||||
Args:
|
||||
base_dir (Optional[str]): Base directory for storage files
|
||||
"""
|
||||
if base_dir is None:
|
||||
# Use user's home directory by default
|
||||
self.base_dir = Path.home() / ".ai_finance"
|
||||
else:
|
||||
self.base_dir = Path(base_dir)
|
||||
|
||||
# Create storage directory if it doesn't exist
|
||||
self.base_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Define file paths
|
||||
self.prefs_file = self.base_dir / "preferences.json"
|
||||
self.reports_file = self.base_dir / "recent_reports.json"
|
||||
|
||||
# Initialize files if they don't exist
|
||||
self._initialize_storage()
|
||||
|
||||
def _initialize_storage(self) -> None:
|
||||
"""Initialize storage files if they don't exist."""
|
||||
if not self.prefs_file.exists():
|
||||
self._save_preferences({})
|
||||
|
||||
if not self.reports_file.exists():
|
||||
self._save_reports([])
|
||||
|
||||
def _save_preferences(self, preferences: Dict[str, Any]) -> None:
|
||||
"""
|
||||
Save user preferences to file.
|
||||
|
||||
Args:
|
||||
preferences (Dict[str, Any]): User preferences to save
|
||||
"""
|
||||
with open(self.prefs_file, 'w') as f:
|
||||
json.dump(preferences, f, indent=4)
|
||||
|
||||
def _load_preferences(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Load user preferences from file.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: User preferences
|
||||
"""
|
||||
try:
|
||||
with open(self.prefs_file, 'r') as f:
|
||||
return json.load(f)
|
||||
except (json.JSONDecodeError, FileNotFoundError):
|
||||
return {}
|
||||
|
||||
def _save_reports(self, reports: List[Dict[str, Any]]) -> None:
|
||||
"""
|
||||
Save recent reports to file.
|
||||
|
||||
Args:
|
||||
reports (List[Dict[str, Any]]): Recent reports to save
|
||||
"""
|
||||
with open(self.reports_file, 'w') as f:
|
||||
json.dump(reports, f, indent=4)
|
||||
|
||||
def _load_reports(self) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Load recent reports from file.
|
||||
|
||||
Returns:
|
||||
List[Dict[str, Any]]: Recent reports
|
||||
"""
|
||||
try:
|
||||
with open(self.reports_file, 'r') as f:
|
||||
return json.load(f)
|
||||
except (json.JSONDecodeError, FileNotFoundError):
|
||||
return []
|
||||
|
||||
def save_user_preferences(self, preferences: Dict[str, Any]) -> None:
|
||||
"""
|
||||
Save user preferences.
|
||||
|
||||
Args:
|
||||
preferences (Dict[str, Any]): User preferences to save
|
||||
"""
|
||||
self._save_preferences(preferences)
|
||||
|
||||
def load_user_preferences(self) -> Dict[str, Any]:
|
||||
"""
|
||||
Load user preferences.
|
||||
|
||||
Returns:
|
||||
Dict[str, Any]: User preferences
|
||||
"""
|
||||
return self._load_preferences()
|
||||
|
||||
def save_recent_reports(self, reports: List[Dict[str, Any]]) -> None:
|
||||
"""
|
||||
Save recent reports.
|
||||
|
||||
Args:
|
||||
reports (List[Dict[str, Any]]): Recent reports to save
|
||||
"""
|
||||
# Convert datetime objects to ISO format strings
|
||||
serialized_reports = []
|
||||
for report in reports:
|
||||
serialized_report = report.copy()
|
||||
if isinstance(report.get('timestamp'), datetime):
|
||||
serialized_report['timestamp'] = report['timestamp'].isoformat()
|
||||
serialized_reports.append(serialized_report)
|
||||
|
||||
self._save_reports(serialized_reports)
|
||||
|
||||
def load_recent_reports(self) -> List[Dict[str, Any]]:
|
||||
"""
|
||||
Load recent reports.
|
||||
|
||||
Returns:
|
||||
List[Dict[str, Any]]: Recent reports with datetime objects
|
||||
"""
|
||||
reports = self._load_reports()
|
||||
|
||||
# Convert ISO format strings back to datetime objects
|
||||
for report in reports:
|
||||
if isinstance(report.get('timestamp'), str):
|
||||
report['timestamp'] = datetime.fromisoformat(report['timestamp'])
|
||||
|
||||
return reports
|
||||
|
||||
def clear_storage(self) -> None:
|
||||
"""Clear all stored data."""
|
||||
self._save_preferences({})
|
||||
self._save_reports([])
|
||||
|
||||
def backup_storage(self, backup_dir: Optional[str] = None) -> None:
|
||||
"""
|
||||
Create a backup of the storage files.
|
||||
|
||||
Args:
|
||||
backup_dir (Optional[str]): Directory to store backup files
|
||||
"""
|
||||
if backup_dir is None:
|
||||
backup_dir = self.base_dir / "backups"
|
||||
else:
|
||||
backup_dir = Path(backup_dir)
|
||||
|
||||
backup_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
|
||||
# Backup preferences
|
||||
if self.prefs_file.exists():
|
||||
backup_prefs = backup_dir / f"preferences_{timestamp}.json"
|
||||
with open(self.prefs_file, 'r') as src, open(backup_prefs, 'w') as dst:
|
||||
dst.write(src.read())
|
||||
|
||||
# Backup reports
|
||||
if self.reports_file.exists():
|
||||
backup_reports = backup_dir / f"recent_reports_{timestamp}.json"
|
||||
with open(self.reports_file, 'r') as src, open(backup_reports, 'w') as dst:
|
||||
dst.write(src.read())
|
||||
|
||||
def restore_from_backup(self, backup_file: str) -> None:
|
||||
"""
|
||||
Restore storage from a backup file.
|
||||
|
||||
Args:
|
||||
backup_file (str): Path to the backup file
|
||||
"""
|
||||
backup_path = Path(backup_file)
|
||||
if not backup_path.exists():
|
||||
raise FileNotFoundError(f"Backup file not found: {backup_file}")
|
||||
|
||||
# Determine which type of backup file it is
|
||||
if "preferences" in backup_path.name:
|
||||
with open(backup_path, 'r') as src, open(self.prefs_file, 'w') as dst:
|
||||
dst.write(src.read())
|
||||
elif "recent_reports" in backup_path.name:
|
||||
with open(backup_path, 'r') as src, open(self.reports_file, 'w') as dst:
|
||||
dst.write(src.read())
|
||||
else:
|
||||
raise ValueError(f"Unknown backup file type: {backup_file}")
|
||||
|
||||
def get_storage_manager(base_dir: Optional[str] = None) -> StorageManager:
|
||||
"""
|
||||
Get a storage manager instance.
|
||||
|
||||
Args:
|
||||
base_dir (Optional[str]): Base directory for storage files
|
||||
|
||||
Returns:
|
||||
StorageManager: Storage manager instance
|
||||
"""
|
||||
return StorageManager(base_dir)
|
||||
Reference in New Issue
Block a user