Create app.py
Browse files
app.py
ADDED
@@ -0,0 +1,523 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import sqlite3
|
3 |
+
import pandas as pd
|
4 |
+
import numpy as np
|
5 |
+
import gradio as gr
|
6 |
+
import yfinance as yf
|
7 |
+
import tensorflow as tf
|
8 |
+
from sklearn.model_selection import train_test_split
|
9 |
+
from sklearn.preprocessing import StandardScaler, MinMaxScaler
|
10 |
+
from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier
|
11 |
+
from sklearn.metrics import mean_squared_error, accuracy_score
|
12 |
+
import joblib
|
13 |
+
from datetime import datetime, timedelta
|
14 |
+
|
15 |
+
class AdvancedHedgeFundManagementSystem:
|
16 |
+
def __init__(self, db_path='data/advanced_hedge_fund_database.sqlite'): # path to database corrected
|
17 |
+
"""
|
18 |
+
Initialize the Advanced Hedge Fund Management System
|
19 |
+
|
20 |
+
Args:
|
21 |
+
db_path (str): Path to the SQLite database
|
22 |
+
"""
|
23 |
+
self.db_path = db_path
|
24 |
+
self.conn = None
|
25 |
+
self.cursor = None
|
26 |
+
|
27 |
+
# Investment Types
|
28 |
+
self.investment_types = [
|
29 |
+
'Stocks', 'Bonds', 'ETFs', 'Mutual Funds',
|
30 |
+
'Real Estate', 'Cryptocurrencies', 'Commodities',
|
31 |
+
'Private Equity', 'Hedge Funds', 'Derivatives'
|
32 |
+
]
|
33 |
+
|
34 |
+
# Market Indices for Benchmarking
|
35 |
+
self.market_indices = [
|
36 |
+
'^GSPC', # S&P 500
|
37 |
+
'^DJI', # Dow Jones Industrial Average
|
38 |
+
'^IXIC', # NASDAQ Composite
|
39 |
+
'^RUT', # Russell 2000
|
40 |
+
]
|
41 |
+
|
42 |
+
# Initialize database and create tables
|
43 |
+
self.initialize_database()
|
44 |
+
|
45 |
+
# Load or train predictive models
|
46 |
+
self.load_or_train_models()
|
47 |
+
|
48 |
+
# Define some common Equity and Bond ETF
|
49 |
+
self.equity_etfs = ['SPY', 'QQQ', 'IWM', 'VOO', 'IVV'] # US equities
|
50 |
+
self.bond_etfs = ['BND', 'AGG', 'LQD', 'TLT', 'SHY'] # US bonds
|
51 |
+
|
52 |
+
|
53 |
+
def initialize_database(self):
|
54 |
+
"""
|
55 |
+
Create database connection and initialize tables
|
56 |
+
"""
|
57 |
+
try:
|
58 |
+
self.conn = sqlite3.connect(self.db_path)
|
59 |
+
self.cursor = self.conn.cursor()
|
60 |
+
|
61 |
+
# Enhanced clients table
|
62 |
+
self.cursor.execute('''
|
63 |
+
CREATE TABLE IF NOT EXISTS clients (
|
64 |
+
id INTEGER PRIMARY KEY,
|
65 |
+
name TEXT NOT NULL,
|
66 |
+
email TEXT UNIQUE,
|
67 |
+
age INTEGER,
|
68 |
+
income REAL,
|
69 |
+
risk_tolerance INTEGER,
|
70 |
+
total_investment REAL,
|
71 |
+
investment_goals TEXT,
|
72 |
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
73 |
+
)
|
74 |
+
''')
|
75 |
+
|
76 |
+
# Enhanced portfolios table
|
77 |
+
self.cursor.execute('''
|
78 |
+
CREATE TABLE IF NOT EXISTS portfolios (
|
79 |
+
id INTEGER PRIMARY KEY,
|
80 |
+
client_id INTEGER,
|
81 |
+
investment_type TEXT,
|
82 |
+
asset_symbol TEXT,
|
83 |
+
investment_amount REAL,
|
84 |
+
purchase_price REAL,
|
85 |
+
current_price REAL,
|
86 |
+
performance REAL,
|
87 |
+
risk_score REAL,
|
88 |
+
allocation_percentage REAL,
|
89 |
+
last_updated DATETIME DEFAULT CURRENT_TIMESTAMP,
|
90 |
+
FOREIGN KEY (client_id) REFERENCES clients (id)
|
91 |
+
)
|
92 |
+
''')
|
93 |
+
|
94 |
+
# Transactions table with more details
|
95 |
+
self.cursor.execute('''
|
96 |
+
CREATE TABLE IF NOT EXISTS transactions (
|
97 |
+
id INTEGER PRIMARY KEY,
|
98 |
+
portfolio_id INTEGER,
|
99 |
+
transaction_type TEXT,
|
100 |
+
asset_symbol TEXT,
|
101 |
+
amount REAL,
|
102 |
+
quantity REAL,
|
103 |
+
price REAL,
|
104 |
+
date DATETIME DEFAULT CURRENT_TIMESTAMP,
|
105 |
+
FOREIGN KEY (portfolio_id) REFERENCES portfolios (id)
|
106 |
+
)
|
107 |
+
''')
|
108 |
+
|
109 |
+
# Performance tracking table
|
110 |
+
self.cursor.execute('''
|
111 |
+
CREATE TABLE IF NOT EXISTS performance_tracking (
|
112 |
+
id INTEGER PRIMARY KEY,
|
113 |
+
client_id INTEGER,
|
114 |
+
total_investment REAL,
|
115 |
+
current_value REAL,
|
116 |
+
total_return REAL,
|
117 |
+
annual_return REAL,
|
118 |
+
last_updated DATETIME DEFAULT CURRENT_TIMESTAMP,
|
119 |
+
FOREIGN KEY (client_id) REFERENCES clients (id)
|
120 |
+
)
|
121 |
+
''')
|
122 |
+
|
123 |
+
self.conn.commit()
|
124 |
+
except sqlite3.Error as e:
|
125 |
+
print(f"Database initialization error: {e}")
|
126 |
+
|
127 |
+
def get_real_time_market_data(self, symbols):
|
128 |
+
"""
|
129 |
+
Fetch real-time market data using Yahoo Finance
|
130 |
+
|
131 |
+
Args:
|
132 |
+
symbols (list): List of stock/asset symbols
|
133 |
+
|
134 |
+
Returns:
|
135 |
+
dict: Real-time market data
|
136 |
+
"""
|
137 |
+
market_data = {}
|
138 |
+
for symbol in symbols:
|
139 |
+
try:
|
140 |
+
ticker = yf.Ticker(symbol)
|
141 |
+
# Fetch historical data and current info
|
142 |
+
hist = ticker.history(period="1mo")
|
143 |
+
market_data[symbol] = {
|
144 |
+
'current_price': ticker.info.get('regularMarketPrice', 0),
|
145 |
+
'previous_close': ticker.info.get('previousClose', 0),
|
146 |
+
'volume': ticker.info.get('volume', 0),
|
147 |
+
'market_cap': ticker.info.get('marketCap', 0),
|
148 |
+
'beta': ticker.info.get('beta', 1.0),
|
149 |
+
'volatility': hist['Close'].std() if not hist.empty else 0,
|
150 |
+
'returns_1m': (hist['Close'][-1] / hist['Close'][0] - 1) * 100 if len(hist) > 1 else 0
|
151 |
+
}
|
152 |
+
except Exception as e:
|
153 |
+
print(f"Error fetching data for {symbol}: {e}")
|
154 |
+
return market_data
|
155 |
+
|
156 |
+
def generate_advanced_training_data(self, n_samples=5000):
|
157 |
+
"""
|
158 |
+
Generate advanced synthetic training data with more features
|
159 |
+
|
160 |
+
Returns:
|
161 |
+
tuple: Features and target variables
|
162 |
+
"""
|
163 |
+
np.random.seed(42)
|
164 |
+
|
165 |
+
# More comprehensive feature generation
|
166 |
+
age = np.random.randint(25, 65, n_samples)
|
167 |
+
income = np.random.uniform(30000, 1000000, n_samples)
|
168 |
+
investment_experience = np.random.randint(0, 30, n_samples)
|
169 |
+
current_investments = np.random.uniform(0, 5000000, n_samples)
|
170 |
+
|
171 |
+
# Additional features
|
172 |
+
education_level = np.random.randint(1, 5, n_samples) # 1-4 education levels
|
173 |
+
family_size = np.random.randint(1, 6, n_samples)
|
174 |
+
debt_to_income = np.random.uniform(0, 0.5, n_samples)
|
175 |
+
|
176 |
+
# Combine features
|
177 |
+
X = np.column_stack([
|
178 |
+
age, income, investment_experience, current_investments,
|
179 |
+
education_level, family_size, debt_to_income
|
180 |
+
])
|
181 |
+
|
182 |
+
# Advanced risk scoring with more nuanced calculation
|
183 |
+
y_risk = (
|
184 |
+
(income / 50000) +
|
185 |
+
(investment_experience / 10) -
|
186 |
+
(debt_to_income * 10) +
|
187 |
+
(education_level * 0.5) -
|
188 |
+
(current_investments / 500000)
|
189 |
+
)
|
190 |
+
y_risk = np.clip(y_risk, 1, 10) # Risk score between 1-10
|
191 |
+
|
192 |
+
# Portfolio performance with more complex calculation
|
193 |
+
y_portfolio_performance = (
|
194 |
+
(income / 25000) +
|
195 |
+
(investment_experience / 5) +
|
196 |
+
(current_investments / 250000) -
|
197 |
+
(debt_to_income * 20)
|
198 |
+
)
|
199 |
+
y_portfolio_performance = np.clip(y_portfolio_performance, 0, 100)
|
200 |
+
|
201 |
+
return X, y_risk, y_portfolio_performance
|
202 |
+
|
203 |
+
def train_advanced_models(self):
|
204 |
+
"""
|
205 |
+
Train advanced machine learning models for risk and portfolio prediction
|
206 |
+
"""
|
207 |
+
# Generate training data
|
208 |
+
X, y_risk, y_portfolio_performance = self.generate_advanced_training_data()
|
209 |
+
|
210 |
+
# Split the data
|
211 |
+
X_train, X_test, y_risk_train, y_risk_test, y_perf_train, y_perf_test = train_test_split(
|
212 |
+
X, y_risk, y_portfolio_performance, test_size=0.2, random_state=42
|
213 |
+
)
|
214 |
+
|
215 |
+
# Scale features
|
216 |
+
scaler = StandardScaler()
|
217 |
+
X_train_scaled = scaler.fit_transform(X_train)
|
218 |
+
X_test_scaled = scaler.transform(X_test)
|
219 |
+
|
220 |
+
# Risk Prediction Model (Regression)
|
221 |
+
risk_model = RandomForestRegressor(n_estimators=200, random_state=42)
|
222 |
+
risk_model.fit(X_train_scaled, y_risk_train)
|
223 |
+
y_risk_pred = risk_model.predict(X_test_scaled)
|
224 |
+
risk_mse = mean_squared_error(y_risk_test, y_risk_pred)
|
225 |
+
|
226 |
+
# Portfolio Performance Model (Regression)
|
227 |
+
portfolio_model = RandomForestRegressor(n_estimators=200, random_state=42)
|
228 |
+
portfolio_model.fit(X_train_scaled, y_perf_train)
|
229 |
+
y_perf_pred = portfolio_model.predict(X_test_scaled)
|
230 |
+
perf_mse = mean_squared_error(y_perf_test, y_perf_pred)
|
231 |
+
|
232 |
+
# Investment Type Recommendation Model (Classification)
|
233 |
+
# Create synthetic labels for investment type recommendation
|
234 |
+
y_investment_type = np.random.choice(len(self.investment_types), len(X))
|
235 |
+
X_type_train, X_type_test, y_type_train, y_type_test = train_test_split(
|
236 |
+
X, y_investment_type, test_size=0.2, random_state=42
|
237 |
+
)
|
238 |
+
X_type_train_scaled = scaler.transform(X_type_train)
|
239 |
+
X_type_test_scaled = scaler.transform(X_type_test)
|
240 |
+
|
241 |
+
investment_type_model = RandomForestClassifier(n_estimators=200, random_state=42)
|
242 |
+
investment_type_model.fit(X_type_train_scaled, y_type_train)
|
243 |
+
y_type_pred = investment_type_model.predict(X_type_test_scaled)
|
244 |
+
type_accuracy = accuracy_score(y_type_test, y_type_pred)
|
245 |
+
|
246 |
+
# Save models and scaler
|
247 |
+
joblib.dump({
|
248 |
+
'risk_model': risk_model,
|
249 |
+
'portfolio_model': portfolio_model,
|
250 |
+
'investment_type_model': investment_type_model,
|
251 |
+
'scaler': scaler
|
252 |
+
}, 'advanced_hedge_fund_models.joblib')
|
253 |
+
|
254 |
+
# Print model performance
|
255 |
+
print(f"Risk Prediction MSE: {risk_mse}")
|
256 |
+
print(f"Portfolio Performance MSE: {perf_mse}")
|
257 |
+
print(f"Investment Type Recommendation Accuracy: {type_accuracy}")
|
258 |
+
|
259 |
+
return risk_model, portfolio_model, investment_type_model, scaler
|
260 |
+
|
261 |
+
def load_or_train_models(self):
|
262 |
+
"""
|
263 |
+
Load existing models or train new predictive models
|
264 |
+
"""
|
265 |
+
try:
|
266 |
+
# Try to load pre-trained models
|
267 |
+
models = joblib.load('advanced_hedge_fund_models.joblib')
|
268 |
+
self.risk_model = models['risk_model']
|
269 |
+
self.portfolio_model = models['portfolio_model']
|
270 |
+
self.investment_type_model = models['investment_type_model']
|
271 |
+
self.scaler = models['scaler']
|
272 |
+
except (FileNotFoundError, KeyError):
|
273 |
+
# Train new models if not found
|
274 |
+
(self.risk_model,
|
275 |
+
self.portfolio_model,
|
276 |
+
self.investment_type_model,
|
277 |
+
self.scaler) = self.train_advanced_models()
|
278 |
+
|
279 |
+
def recommend_portfolio_allocation(self, client_features, target_return=0.15):
|
280 |
+
"""
|
281 |
+
Recommend portfolio allocation with 15% target return
|
282 |
+
|
283 |
+
Args:
|
284 |
+
client_features (numpy.ndarray): Client features
|
285 |
+
target_return (float): Target annual return percentage
|
286 |
+
|
287 |
+
Returns:
|
288 |
+
dict: Recommended portfolio allocation
|
289 |
+
"""
|
290 |
+
# Scale client features
|
291 |
+
scaled_features = self.scaler.transform(client_features.reshape(1, -1))
|
292 |
+
|
293 |
+
# Predict risk and investment type
|
294 |
+
risk_score = float(self.risk_model.predict(scaled_features)[0])
|
295 |
+
investment_type_index = int(self.investment_type_model.predict(scaled_features)[0])
|
296 |
+
recommended_investment_type = self.investment_types[investment_type_index]
|
297 |
+
|
298 |
+
# Fetch real-time market data for market indices
|
299 |
+
market_data = self.get_real_time_market_data(self.market_indices)
|
300 |
+
|
301 |
+
# Calculate portfolio allocation
|
302 |
+
base_allocation = {
|
303 |
+
'Stocks': 0.4,
|
304 |
+
'Bonds': 0.3,
|
305 |
+
'ETFs': 0.15,
|
306 |
+
'Real Estate': 0.1,
|
307 |
+
'Other Alternatives': 0.05
|
308 |
+
}
|
309 |
+
|
310 |
+
# Adjust allocation based on risk tolerance
|
311 |
+
if risk_score <= 3: # Conservative
|
312 |
+
base_allocation = {
|
313 |
+
'Bonds': 0.6,
|
314 |
+
'Stocks': 0.2,
|
315 |
+
'ETFs': 0.1,
|
316 |
+
'Real Estate': 0.05,
|
317 |
+
'Other Alternatives': 0.05
|
318 |
+
}
|
319 |
+
elif risk_score >= 8: # Aggressive
|
320 |
+
base_allocation = {
|
321 |
+
'Stocks': 0.5,
|
322 |
+
'ETFs': 0.2,
|
323 |
+
'Real Estate': 0.1,
|
324 |
+
'Cryptocurrencies': 0.1,
|
325 |
+
'Other Alternatives': 0.1
|
326 |
+
}
|
327 |
+
|
328 |
+
# Recommended portfolio details
|
329 |
+
portfolio_recommendation = {
|
330 |
+
'risk_score': risk_score,
|
331 |
+
'recommended_investment_type': recommended_investment_type,
|
332 |
+
'allocation': base_allocation,
|
333 |
+
'target_return': target_return,
|
334 |
+
'market_indices': market_data
|
335 |
+
}
|
336 |
+
|
337 |
+
return portfolio_recommendation
|
338 |
+
|
339 |
+
def analyze_equity_bonds(self, risk_tolerance, investment_amount, investment_timeframe, sector_preference = None):
|
340 |
+
"""Analyze Equities and Bonds and recommend investments
|
341 |
+
Args:
|
342 |
+
risk_tolerance: (str) "Low", "Medium", "High"
|
343 |
+
investment_amount: (float) total investment amount
|
344 |
+
investment_timeframe: (str) "Short term", "Medium term", "Long term"
|
345 |
+
sector_preference: (str) for equities, can be "Tech", "Healthcare", "Finance", etc.
|
346 |
+
"""
|
347 |
+
|
348 |
+
# Step 1: Data Retrieval for equities
|
349 |
+
equity_data = self.get_real_time_market_data(self.equity_etfs)
|
350 |
+
equity_df = pd.DataFrame.from_dict(equity_data, orient='index')
|
351 |
+
|
352 |
+
# Step 2: Data Retrieval for bonds
|
353 |
+
bond_data = self.get_real_time_market_data(self.bond_etfs)
|
354 |
+
bond_df = pd.DataFrame.from_dict(bond_data, orient='index')
|
355 |
+
|
356 |
+
# Additional data retrieval
|
357 |
+
for symbol in self.equity_etfs + self.bond_etfs:
|
358 |
+
ticker = yf.Ticker(symbol)
|
359 |
+
hist = ticker.history(period="1y")
|
360 |
+
if not hist.empty:
|
361 |
+
returns = hist['Close'].pct_change().dropna() # Daily returns, remove the first NAN value
|
362 |
+
equity_df.loc[symbol, 'annual_return'] = returns.mean() * 252 # Annualize returns
|
363 |
+
else:
|
364 |
+
equity_df.loc[symbol, 'annual_return'] = 0
|
365 |
+
|
366 |
+
# Equity Analysis
|
367 |
+
equity_df['risk_adjusted_return'] = equity_df['annual_return'] / equity_df['volatility'] if equity_df['volatility'].any() > 0 else 0
|
368 |
+
if sector_preference:
|
369 |
+
# Fetch and match to sector specific ETFs
|
370 |
+
sector_etfs_dict = {
|
371 |
+
"Technology": ["XLK","VGT"],
|
372 |
+
"Healthcare":["XLV","VHT"],
|
373 |
+
"Finance": ["XLF", "VFH"]
|
374 |
+
}
|
375 |
+
sector_etfs = sector_etfs_dict.get(sector_preference, None)
|
376 |
+
if sector_etfs:
|
377 |
+
sector_data = self.get_real_time_market_data(sector_etfs)
|
378 |
+
sector_df = pd.DataFrame.from_dict(sector_data, orient='index')
|
379 |
+
|
380 |
+
# additional data retrieve for sector
|
381 |
+
for symbol in sector_etfs:
|
382 |
+
ticker = yf.Ticker(symbol)
|
383 |
+
hist = ticker.history(period="1y")
|
384 |
+
if not hist.empty:
|
385 |
+
returns = hist['Close'].pct_change().dropna() # Daily returns, remove the first NAN value
|
386 |
+
sector_df.loc[symbol, 'annual_return'] = returns.mean() * 252 # Annualize returns
|
387 |
+
else:
|
388 |
+
sector_df.loc[symbol, 'annual_return'] = 0
|
389 |
+
|
390 |
+
sector_df['risk_adjusted_return'] = sector_df['annual_return'] / sector_df['volatility'] if sector_df['volatility'].any() > 0 else 0
|
391 |
+
|
392 |
+
# Concatenate the dataframes of the Sector data with the equity data
|
393 |
+
equity_df = pd.concat([equity_df, sector_df])
|
394 |
+
# Bond analysis
|
395 |
+
bond_df['risk_adjusted_return'] = bond_df['returns_1m'] / bond_df['volatility'] if bond_df['volatility'].any() > 0 else 0
|
396 |
+
|
397 |
+
# Step 3: Asset selection based on risk tolerance
|
398 |
+
|
399 |
+
if risk_tolerance == "Low":
|
400 |
+
equity_recommendations = equity_df.sort_values(by=['volatility']).head(3).index.tolist() # Lower vol
|
401 |
+
bond_recommendations = bond_df.sort_values(by=['risk_adjusted_return'], ascending=False).head(2).index.tolist() # Higher returns for low risk
|
402 |
+
elif risk_tolerance == "Medium":
|
403 |
+
equity_recommendations = equity_df.sort_values(by=['risk_adjusted_return'], ascending=False).head(3).index.tolist()
|
404 |
+
bond_recommendations = bond_df.sort_values(by=['risk_adjusted_return'], ascending=False).head(2).index.tolist()
|
405 |
+
else: # High Risk
|
406 |
+
equity_recommendations = equity_df.sort_values(by=['risk_adjusted_return'], ascending=False).head(3).index.tolist()
|
407 |
+
bond_recommendations = bond_df.sort_values(by=['volatility'], ascending=False).head(2).index.tolist() # higher yield, volatile bonds
|
408 |
+
|
409 |
+
# Step 4: Recommended Investment with allocation
|
410 |
+
|
411 |
+
if investment_timeframe == 'Short term':
|
412 |
+
allocation = {'Bonds':0.6, 'Equities':0.4}
|
413 |
+
elif investment_timeframe == 'Medium term':
|
414 |
+
allocation = {'Bonds': 0.4, 'Equities':0.6}
|
415 |
+
else: # Long Term
|
416 |
+
allocation = {'Bonds':0.3, 'Equities':0.7}
|
417 |
+
|
418 |
+
formatted_output = f"Recommended allocation: Bonds {allocation['Bonds'] * 100:.2f}%, Equities: {allocation['Equities'] * 100:.2f}% \n"
|
419 |
+
formatted_output += f"Equity Recommendations: \n"
|
420 |
+
for rec in equity_recommendations:
|
421 |
+
formatted_output += f" - {rec}\n"
|
422 |
+
formatted_output += f"Bond Recommendations: \n"
|
423 |
+
for rec in bond_recommendations:
|
424 |
+
formatted_output += f" - {rec}\n"
|
425 |
+
|
426 |
+
return formatted_output
|
427 |
+
|
428 |
+
|
429 |
+
def create_gradio_interface(self):
|
430 |
+
"""
|
431 |
+
Create Gradio interface for the Advanced Hedge Fund Management System
|
432 |
+
|
433 |
+
Returns:
|
434 |
+
gr.Interface: Gradio web interface
|
435 |
+
"""
|
436 |
+
def analyze_investment_profile(age, income, investment_experience,
|
437 |
+
current_investments, education_level,
|
438 |
+
family_size, debt_to_income):
|
439 |
+
"""
|
440 |
+
Comprehensive investment profile analysis
|
441 |
+
"""
|
442 |
+
# Prepare client features
|
443 |
+
client_features = np.array([
|
444 |
+
age, income, investment_experience, current_investments,
|
445 |
+
education_level, family_size, debt_to_income
|
446 |
+
])
|
447 |
+
|
448 |
+
# Get portfolio recommendation
|
449 |
+
recommendation = self.recommend_portfolio_allocation(client_features)
|
450 |
+
|
451 |
+
# Format output
|
452 |
+
allocation_str = "\n".join([
|
453 |
+
f"{k}: {v*100:.2f}%" for k, v in recommendation['allocation'].items()
|
454 |
+
])
|
455 |
+
|
456 |
+
output = (
|
457 |
+
f"Risk Score: {recommendation['risk_score']:.2f}/10\n"
|
458 |
+
f"Recommended Investment Type: {recommendation['recommended_investment_type']}\n"
|
459 |
+
f"Target Annual Return: {recommendation['target_return']*100:.2f}%\n\n"
|
460 |
+
"Portfolio Allocation:\n" + allocation_str + "\n\n"
|
461 |
+
"Market Indices Performance:\n" +
|
462 |
+
"\n".join([
|
463 |
+
f"{symbol}: {data['returns_1m']:.2f}% (1M Return)"
|
464 |
+
for symbol, data in recommendation['market_indices'].items()
|
465 |
+
])
|
466 |
+
)
|
467 |
+
|
468 |
+
return output
|
469 |
+
|
470 |
+
def analyze_equity_bond_investments(risk_tolerance, investment_amount, investment_timeframe, sector_preference):
|
471 |
+
"""
|
472 |
+
Analyze equity and bond investments based on users preferences
|
473 |
+
"""
|
474 |
+
|
475 |
+
return self.analyze_equity_bonds(risk_tolerance, investment_amount, investment_timeframe, sector_preference)
|
476 |
+
# Gradio interface with more comprehensive inputs
|
477 |
+
interface = gr.TabbedInterface(
|
478 |
+
[
|
479 |
+
gr.Interface(
|
480 |
+
fn=analyze_investment_profile,
|
481 |
+
inputs=[
|
482 |
+
gr.Number(label="Age"),
|
483 |
+
gr.Number(label="Annual Income"),
|
484 |
+
gr.Number(label="Investment Experience (Years)"),
|
485 |
+
gr.Number(label="Current Investments"),
|
486 |
+
gr.Dropdown(label="Education Level", choices=[1, 2, 3, 4]),
|
487 |
+
gr.Number(label="Family Size"),
|
488 |
+
gr.Number(label="Debt-to-Income Ratio")
|
489 |
+
],
|
490 |
+
outputs=gr.Textbox(label="Investment Profile Analysis"),
|
491 |
+
title="Investment Profile Analysis",
|
492 |
+
description="Get personalized recommendations based on your profile"
|
493 |
+
),
|
494 |
+
gr.Interface(
|
495 |
+
fn=analyze_equity_bond_investments,
|
496 |
+
inputs=[
|
497 |
+
gr.Dropdown(label="Risk Tolerance", choices=["Low", "Medium", "High"]),
|
498 |
+
gr.Number(label="Investment Amount"),
|
499 |
+
gr.Dropdown(label="Investment Timeframe", choices=["Short term", "Medium term", "Long term"]),
|
500 |
+
gr.Dropdown(label="Sector Preference", choices = ["Technology","Healthcare", "Finance", None] )
|
501 |
+
],
|
502 |
+
outputs=gr.Textbox(label="Equity and Bond Analysis"),
|
503 |
+
title="Equity and Bond Analysis",
|
504 |
+
description="Analyze and get recommended Equities and Bonds based on your parameters"
|
505 |
+
)
|
506 |
+
],
|
507 |
+
tab_names=["Investment Profile","Equity and Bond Analyzer"],
|
508 |
+
title="Advanced Hedge Fund Management System",
|
509 |
+
# description="Enter your details to get personalized investment recommendations." # Removed description here
|
510 |
+
)
|
511 |
+
|
512 |
+
return interface
|
513 |
+
|
514 |
+
def run_gradio_app(self):
|
515 |
+
"""
|
516 |
+
Run the Gradio web application
|
517 |
+
"""
|
518 |
+
interface = self.create_gradio_interface()
|
519 |
+
interface.launch()
|
520 |
+
|
521 |
+
if __name__ == "__main__":
|
522 |
+
hedge_fund_system = AdvancedHedgeFundManagementSystem()
|
523 |
+
hedge_fund_system.run_gradio_app()
|