Apr-02-2020, 10:56 PM
Thanks by advance for your help. I know it is a complex request. I did my best to do it on my own, but I am stuck… I am using Python 3 on Anaconda, Jupyter.
-----
Hi, I am a noob on Python and more generally in programming, but I am doing my best to learn thanks to online tutorials.
I would like to code a small downloadable program allowing anyone to obtain the optimal stock weights to include in a portfolio in order to maximise expected return. Even if you know nothing about finance, you can still help me because my computations are already working. I just need a “Tkinter expert” ?
Based on a code I found online and some personal adjustments, the code is operational and gives me the outcomes (text and graphs) that I want already. However, I would like to make the code "responsive" to inputs entered in a user interface. For this, I know I have to use Tkinter. I have made several attemps, but I cannot succeed to connect my python code and the user interface thanks to Tkinter. I just miss that "link" to make everything go smoothly.
Could you please help me?
I would like to add a picture of the final result I am looking for but I don't know how to dit on this forum. So here is a quick description.
-----
I would like to have a downloadable program with an icon, which opens a window when we click on it. Just like any program.
Once the window opens it would be organised as follow:
Top section: Logo + Welcome + Instructions
Next to it, two buttons one "Export the document as PDF" and another "Clear inputs"
Inputs section: 3 labels with 3 entry boxes and one button "Go"
Label 1: How many stocks are there in your portfolio?
Entry box 1: horizontal slider widget ranging from 3 to 30
Label 2: Enter the related stock tickers (yahoo finance)
Entry box 2: text box - important to type stocks as follow 'AAPL', 'GOOGL', 'FB' ......
Label 3: Precise time interval for historic performance and volatility
Entry box 3: radio button - 1 year or 3 years or 5 years from today (last closing price when the user opens the program)
A button "Go" to run the program
Outputs section: 2 graphs and 2 texts
Graph 1: Efficient frontier
Text 1: Max Sharpe Ratio Portfolio and Min Variance Portfolio descriptions
Graph 2: Pie chart with related weights
Graph 2: Stocks' historical return and volatility
-----
Here is the code (with no Tkinter attempt)
I will post my unworking Tkinter attempt afterwards.
This is my failed attempt at tkinter. Since it was not working for entry boxes, I did not try to do more.
As, said before, all my computations and graphs are displaying correctly in Python. However, I need your help to make the connection between my code and a simple user interface via Tkinter. I watched several tutorials but I am stuck.
First of all, I would like to have a basic, ugly version working from inputs to outputs. Afterwards, and if you are still kind enough to help me, we can have a look at the “export”, “clear” buttons and the layout :D
If this is not clear please tell me and I will be happy to give more information!
PS: I had to retype all this TWICE because the forum does not allow to edit a message 10 minutes after starting to type. This was, VERY, annoying.
-----
Hi, I am a noob on Python and more generally in programming, but I am doing my best to learn thanks to online tutorials.
I would like to code a small downloadable program allowing anyone to obtain the optimal stock weights to include in a portfolio in order to maximise expected return. Even if you know nothing about finance, you can still help me because my computations are already working. I just need a “Tkinter expert” ?
Based on a code I found online and some personal adjustments, the code is operational and gives me the outcomes (text and graphs) that I want already. However, I would like to make the code "responsive" to inputs entered in a user interface. For this, I know I have to use Tkinter. I have made several attemps, but I cannot succeed to connect my python code and the user interface thanks to Tkinter. I just miss that "link" to make everything go smoothly.
Could you please help me?
I would like to add a picture of the final result I am looking for but I don't know how to dit on this forum. So here is a quick description.
-----
I would like to have a downloadable program with an icon, which opens a window when we click on it. Just like any program.
Once the window opens it would be organised as follow:
Top section: Logo + Welcome + Instructions
Next to it, two buttons one "Export the document as PDF" and another "Clear inputs"
Inputs section: 3 labels with 3 entry boxes and one button "Go"
Label 1: How many stocks are there in your portfolio?
Entry box 1: horizontal slider widget ranging from 3 to 30
Label 2: Enter the related stock tickers (yahoo finance)
Entry box 2: text box - important to type stocks as follow 'AAPL', 'GOOGL', 'FB' ......
Label 3: Precise time interval for historic performance and volatility
Entry box 3: radio button - 1 year or 3 years or 5 years from today (last closing price when the user opens the program)
A button "Go" to run the program
Outputs section: 2 graphs and 2 texts
Graph 1: Efficient frontier
Text 1: Max Sharpe Ratio Portfolio and Min Variance Portfolio descriptions
Graph 2: Pie chart with related weights
Graph 2: Stocks' historical return and volatility
-----
Here is the code (with no Tkinter attempt)
I will post my unworking Tkinter attempt afterwards.
import numpy as np import pandas as pd from pandas_datareader import data as wb import matplotlib.pyplot as plt import seaborn as sns import quandl import scipy.optimize as sco %matplotlib inline %config InlineBackend.figure_format = 'retina' plt.style.use('fivethirtyeight') np.random.seed(777) #I think this is a CRITICAL part from which many inputs should be collected from the user interface’s entry boxes, but I do not know how to connect them (eg: replace 'AAPL', 'AMZN', 'FB', 'GOOGL' by what is written in entry box 2). tickers = ['AAPL', 'AMZN', 'FB', 'GOOGL'] stocks = pd.DataFrame() for t in tickers: stocks[t] = wb.DataReader(t, data_source='yahoo', start='2019-3-31', end='2020-3-31')['Adj Close'] def pfolio_ann_perf(weights, mean_returns, cov_matrix): returns = np.sum(mean_returns * weights ) * 250 std = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights))) * np.sqrt(250) return std, returns #Here as well, I need to make sure that the value of rf-rate changes according to what the user wrote in entry box 4, but don’t know how. returns = stocks.pct_change() mean_returns = returns.mean() cov_matrix = returns.cov() num_pfolio = 25000 rf_rate = 0.01 def neg_sharpe_ratio(weights, mean_returns, cov_matrix, rf_rate): p_var, p_ret = pfolio_ann_perf(weights, mean_returns, cov_matrix) return -(p_ret - rf_rate) / p_var def max_sharpe_ratio(mean_returns, cov_matrix, rf_rate): num_assets = len(mean_returns) args = (mean_returns, cov_matrix, rf_rate) constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1}) bound = (0.0,1.0) bounds = tuple(bound for asset in range(num_assets)) result = sco.minimize(neg_sharpe_ratio, num_assets*[1./num_assets,], args=args, method='SLSQP', bounds=bounds, constraints=constraints) return result def pfolio_volatility(weights, mean_returns, cov_matrix): return pfolio_ann_perf(weights, mean_returns, cov_matrix)[0] def min_variance(mean_returns, cov_matrix): num_assets = len(mean_returns) args = (mean_returns, cov_matrix) constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1}) bound = (0.0,1.0) bounds = tuple(bound for asset in range(num_assets)) result = sco.minimize(pfolio_volatility, num_assets*[1./num_assets,], args=args, method='SLSQP', bounds=bounds, constraints=constraints) return result def efficient_return(mean_returns, cov_matrix, target): num_assets = len(mean_returns) args = (mean_returns, cov_matrix) def pfolio_return(weights): return pfolio_ann_perf(weights, mean_returns, cov_matrix)[1] constraints = ({'type': 'eq', 'fun': lambda x: pfolio_return(x) - target}, {'type': 'eq', 'fun': lambda x: np.sum(x) - 1}) bounds = tuple((0,1) for asset in range(num_assets)) result = sco.minimize(pfolio_volatility, num_assets*[1./num_assets,], args=args, method='SLSQP', bounds=bounds, constraints=constraints) return result def efficient_frontier(mean_returns, cov_matrix, returns_range): efficients = [] for ret in returns_range: efficients.append(efficient_return(mean_returns, cov_matrix, ret)) return efficients def display_ef_with_selected(mean_returns, cov_matrix, rf_rate): max_sharpe = max_sharpe_ratio(mean_returns, cov_matrix, rf_rate) sdp, rp = pfolio_ann_perf(max_sharpe['x'], mean_returns, cov_matrix) max_sharpe_allocation = pd.DataFrame(max_sharpe.x,index=stocks.columns,columns=['allocation']) max_sharpe_allocation.allocation = [round(i*100,2)for i in max_sharpe_allocation.allocation] max_sharpe_allocation = max_sharpe_allocation.T max_sharpe_allocation min_vol = min_variance(mean_returns, cov_matrix) sdp_min, rp_min = pfolio_ann_perf(min_vol['x'], mean_returns, cov_matrix) min_vol_allocation = pd.DataFrame(min_vol.x,index=stocks.columns,columns=['allocation']) min_vol_allocation.allocation = [round(i*100,2)for i in min_vol_allocation.allocation] min_vol_allocation = min_vol_allocation.T an_vol = np.std(returns) * np.sqrt(252) an_rt = mean_returns * 252 print ("-"*80) print ("Maximum Sharpe Ratio Portfolio Allocation\n") print ("Annualised Return:", round(rp,2)) print ("Annualised Volatility:", round(sdp,2)) print ("\n") print (max_sharpe_allocation) print ("-"*80) print ("Minimum Volatility Portfolio Allocation\n") print ("Annualised Return:", round(rp_min,2)) print ("Annualised Volatility:", round(sdp_min,2)) print ("\n") print (min_vol_allocation) print ("-"*80) print ("Individual Stock Returns and Volatility\n") for i, txt in enumerate(stocks.columns): print (txt,":","annualised return",round(an_rt[i],2),", annualised volatility:",round(an_vol[i],2)) print ("-"*80) fig, ax = plt.subplots(figsize=(10, 7)) ax.scatter(an_vol,an_rt,marker='o',s=200) for i, txt in enumerate(stocks.columns): ax.annotate(txt, (an_vol[i],an_rt[i]), xytext=(10,0), textcoords='offset points') ax.scatter(sdp,rp,marker='*',color='r',s=500, label='Maximum Sharpe ratio') ax.scatter(sdp_min,rp_min,marker='*',color='g',s=500, label='Minimum volatility') target = np.linspace(rp_min, 0.34, 50) efficient_pfolio = efficient_frontier(mean_returns, cov_matrix, target) ax.plot([p['fun'] for p in efficient_pfolio], target, linestyle=':', color='black', label='Efficient frontier') ax.set_title('Portfolio Optimization with Individual Stocks') ax.set_xlabel('Annualised Volatility') ax.set_ylabel('Annualised Returns') ax.legend(labelspacing=0.8) display_ef_with_selected(mean_returns, cov_matrix, rf_rate)-----
This is my failed attempt at tkinter. Since it was not working for entry boxes, I did not try to do more.
from tkinter import * from PIL import ImageTk, Image root = Tk() root.title('MT Finance') root.iconbitmap(r'D:/Coding/Portfolio_Optimisation/Logo.ico') mylabel1 = Label(root, text='Please type stock tickers (eg: "AAPL")') mylabel1.grid(row=2, column=0) e1 = Entry(root, width=35, borderwidth=5) e1.grid(row=3, column=0, columnspan=3, padx=10, pady=10) mylabel2 = Label(root, text='Please type start date (eg: 1-1-2019)') mylabel2.grid(row=4, column=0) e2 = Entry(root, width=35, borderwidth=5) e2.grid(row=5, column=0, columnspan=3, padx=10, pady=10) mylabel3 = Label(root, text='Please type end date (eg: 1-1-2020)') mylabel3.grid(row=6, column=0) e3 = Entry(root, width=35, borderwidth=5) e3.grid(row=7, column=0, columnspan=3, padx=10, pady=10) #def mystocks(): #selected_stocks = Label(root, text=e1.get()) #selected_stocks.grid(row=9, column=0) #e1.delete(0, END) # Display the button triggering the function #mybutton = Button(root, text='Write stocks', padx=10, pady=10, command=mystocks, fg='red') #mybutton.grid(row=8, column=0) tickers = [e1.get()] start_date = [e2.get()] end_date = [e3.get()] stocks = pd.DataFrame() for t in tickers: stocks[t] = wb.DataReader(t, data_source='yahoo', start_date, end_date)['Adj Close'] def price_graph(): (stocks / stocks.iloc[0] * 100).plot(figsize=(15, 6)) plt.legend(loc='upper left', fontsize=10) plt.ylabel('price in $') plt.show() price_graph_button = Button(root, text='Price Graph', padx=10, pady=10, command=price_graph, fg='red') price_graph_button.grid(row=8, column=0) root.mainloop()-----
As, said before, all my computations and graphs are displaying correctly in Python. However, I need your help to make the connection between my code and a simple user interface via Tkinter. I watched several tutorials but I am stuck.
First of all, I would like to have a basic, ugly version working from inputs to outputs. Afterwards, and if you are still kind enough to help me, we can have a look at the “export”, “clear” buttons and the layout :D
If this is not clear please tell me and I will be happy to give more information!
PS: I had to retype all this TWICE because the forum does not allow to edit a message 10 minutes after starting to type. This was, VERY, annoying.