-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapp.py
More file actions
107 lines (77 loc) · 3.79 KB
/
Copy pathapp.py
File metadata and controls
107 lines (77 loc) · 3.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
from flask import Flask, request, jsonify, render_template
import pandas as pd
import yfinance as yf
import sqlite3
import riskfolio as rp
import numpy as np
app = Flask(__name__)
def get_db_connection():
conn = sqlite3.connect('stocks.db')
conn.row_factory = sqlite3.Row
return conn
@app.route('/')
def input_form():
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute("SELECT ticker, name FROM tickers")
stocks = cursor.fetchall()
conn.close()
return render_template('input.html', stocks=stocks)
@app.route('/search', methods=['GET'])
def search():
query = request.args.get('query', '')
conn = get_db_connection()
cursor = conn.cursor()
cursor.execute("SELECT ticker, name FROM tickers WHERE name LIKE ? OR ticker LIKE ?",
('%' + query + '%', '%' + query + '%'))
results = cursor.fetchall()
conn.close()
stock_list = [{"label": f"{row['name']} ({row['ticker']})", "value": row['ticker']} for row in results]
return jsonify(stock_list)
@app.route('/graph', methods=['POST'])
def generate_graph():
assets = request.form.getlist('stocks')
start_date = '2010-01-01'
end_date = pd.Timestamp.today().strftime('%Y-%m-%d')
try:
data = yf.download(assets, start=start_date, end=end_date)['Adj Close']
if data.empty:
return jsonify(error="No data downloaded. Check the stock symbols."), 400
rf_data = yf.download("^IRX", period="1d")
current_rf = rf_data["Adj Close"].iloc[0] / 100 # Convert to decimal (e.g., 0.02 for 2%)
returns = data.pct_change().dropna()
annual_returns = returns.resample('YE').apply(lambda x: (1 + x).prod() - 1)
port = rp.Portfolio(returns=returns)
port.assets_stats(method_mu='hist', method_cov='hist')
model_type = request.form.get('dataInput') # e.g., 'Sharpe' or 'MaxRet'
risk_tolerance = float(request.form.get('riskTolerance', 0))
method_mu = 'hist' # Method to estimate expected returns based on historical data.
method_cov = 'hist' # Method to estimate covariance matrix based on historical data.
port.assets_stats(method_mu=method_mu, method_cov=method_cov)
weights = port.optimization(model='Classic', rm='MV', rf=0, obj=model_type, hist=True)
labels = weights.index.tolist()
sizes = weights.values.flatten().tolist() # Convert to a 1D list
portfolio_return = (returns * sizes).sum(axis=1).mean() # Average daily return
annualized_return = round((portfolio_return * 252),2) # Annualized return
portfolio_std = np.sqrt(np.dot(weights.T, np.dot(returns.cov() * 252, weights)))
portfolio_std_value = round(portfolio_std.item(),2)
sharpe_ratio = (annualized_return - current_rf) / portfolio_std # Risk-free rate adjusted Sharpe
sharpe_ratio = round(sharpe_ratio[0][0],2)
stock_labels = weights.index.tolist()
sizes = weights.values.flatten().tolist()
date_strings = data.index.strftime('%Y-%m-%d').tolist()
price = data.dropna().T.values.tolist()
correlation_matrix = annual_returns.corr()
correlations = correlation_matrix.values.tolist()
return render_template('graph.html', labels=stock_labels, sizes=sizes, correlations=correlations,
stock_labels=stock_labels, prices=price, date_strings=date_strings,
sharpe_ratio=sharpe_ratio, annualized_return=annualized_return,
portfolio_std=portfolio_std_value)
except Exception as e:
return jsonify(error=str(e)), 500
@app.route('/submit', methods=['POST'])
def submit():
data_value = request.form.get('dataInput')
return render_template('graph.html')
if __name__ == '__main__':
app.run(debug=True)