| import pandas as pd |
| import numpy as np |
| from typing import List, Dict, Optional |
| from utils.quantum_algorithms import QuantumInspiredOptimizer |
| from utils.data_loader import fetch_stock_data |
|
|
| class PortfolioManager: |
| def __init__(self): |
| self.quantum_optimizer = QuantumInspiredOptimizer() |
| self.watchlists = {} |
| self.portfolios = {} |
|
|
| def create_watchlist(self, user_id: str, name: str) -> Dict: |
| """Create a new watchlist for a user""" |
| if user_id not in self.watchlists: |
| self.watchlists[user_id] = {} |
| |
| self.watchlists[user_id][name] = [] |
| return {'status': 'success', 'message': f'Watchlist {name} created'} |
|
|
| def add_to_watchlist(self, user_id: str, watchlist_name: str, symbol: str) -> Dict: |
| """Add a symbol to a watchlist""" |
| if user_id in self.watchlists and watchlist_name in self.watchlists[user_id]: |
| if symbol not in self.watchlists[user_id][watchlist_name]: |
| self.watchlists[user_id][watchlist_name].append(symbol) |
| return {'status': 'success', 'message': f'Added {symbol} to watchlist'} |
| return {'status': 'error', 'message': 'Watchlist not found'} |
|
|
| def get_watchlist(self, user_id: str, watchlist_name: str) -> List[Dict]: |
| """Get watchlist with current prices and analysis""" |
| if user_id not in self.watchlists or watchlist_name not in self.watchlists[user_id]: |
| return [] |
|
|
| watchlist_data = [] |
| for symbol in self.watchlists[user_id][watchlist_name]: |
| data = fetch_stock_data(symbol, period='1d') |
| if data is not None: |
| current_price = data['Close'].iloc[-1] |
| change = ((current_price - data['Open'].iloc[0]) / data['Open'].iloc[0]) * 100 |
| |
| watchlist_data.append({ |
| 'symbol': symbol, |
| 'current_price': current_price, |
| 'change_percent': change, |
| 'last_updated': data.index[-1].strftime('%Y-%m-%d %H:%M:%S') |
| }) |
|
|
| return watchlist_data |
|
|
| def optimize_portfolio(self, symbols: List[str], risk_tolerance: float = 0.5) -> Dict: |
| """Optimize portfolio allocation using quantum-inspired algorithm""" |
| |
| data = {} |
| for symbol in symbols: |
| hist_data = fetch_stock_data(symbol, period='1y') |
| if hist_data is not None: |
| data[symbol] = hist_data['Close'] |
|
|
| if not data: |
| return {'status': 'error', 'message': 'No data available for optimization'} |
|
|
| |
| returns = pd.DataFrame(data).pct_change().dropna() |
|
|
| |
| weights = self.quantum_optimizer.optimize_portfolio(returns, risk_tolerance) |
|
|
| |
| portfolio_return = sum(weights[symbol] * returns[symbol].mean() for symbol in symbols) |
| portfolio_risk = np.sqrt(sum(sum( |
| weights[s1] * weights[s2] * returns[s1].cov(returns[s2]) |
| for s2 in symbols) for s1 in symbols)) |
|
|
| return { |
| 'status': 'success', |
| 'allocation': weights, |
| 'metrics': { |
| 'expected_return': portfolio_return * 100, |
| 'risk': portfolio_risk * 100, |
| 'sharpe_ratio': portfolio_return / portfolio_risk if portfolio_risk > 0 else 0 |
| } |
| } |
|
|
| def analyze_portfolio(self, portfolio: Dict[str, float]) -> Dict: |
| """Analyze current portfolio performance and suggest rebalancing""" |
| symbols = list(portfolio.keys()) |
| current_weights = list(portfolio.values()) |
| |
| |
| optimal_allocation = self.optimize_portfolio(symbols) |
| |
| if optimal_allocation['status'] == 'error': |
| return optimal_allocation |
|
|
| |
| rebalancing_needed = any( |
| abs(portfolio[symbol] - optimal_allocation['allocation'][symbol]) > 0.05 |
| for symbol in symbols |
| ) |
|
|
| return { |
| 'status': 'success', |
| 'current_allocation': portfolio, |
| 'optimal_allocation': optimal_allocation['allocation'], |
| 'metrics': optimal_allocation['metrics'], |
| 'rebalancing_needed': rebalancing_needed, |
| 'rebalancing_suggestions': { |
| symbol: optimal_allocation['allocation'][symbol] - portfolio[symbol] |
| for symbol in symbols |
| } if rebalancing_needed else {} |
| } |
|
|