def test_custom_upper_bound(): ef = EfficientFrontier( *setup_efficient_frontier(data_only=True), weight_bounds=(0, 0.10) ) ef.max_sharpe() ef.portfolio_performance() assert ef.weights.max() <= 0.1 np.testing.assert_almost_equal(ef.weights.sum(), 1)
def test_efficient_return_short(): ef = EfficientFrontier( *setup_efficient_frontier(data_only=True), weight_bounds=(None, None) ) w = ef.efficient_return(0.25) assert isinstance(w, dict) assert set(w.keys()) == set(ef.tickers) assert set(w.keys()) == set(ef.expected_returns.index) np.testing.assert_almost_equal(ef.weights.sum(), 1) np.testing.assert_allclose( ef.portfolio_performance(), (0.25, 0.168264744226909, 1.3640929002973508) ) sharpe = ef.portfolio_performance()[2] ef_long_only = setup_efficient_frontier() ef_long_only.efficient_return(0.25) long_only_sharpe = ef_long_only.portfolio_performance()[2] assert sharpe > long_only_sharpe
def test_max_sharpe_short(): ef = EfficientFrontier( *setup_efficient_frontier(data_only=True), weight_bounds=(None, None) ) w = ef.max_sharpe() assert isinstance(w, dict) assert set(w.keys()) == set(ef.tickers) assert set(w.keys()) == set(ef.expected_returns.index) np.testing.assert_almost_equal(ef.weights.sum(), 1) np.testing.assert_allclose( ef.portfolio_performance(), (0.40723757138191374, 0.24823079451957306, 1.5524922427959371), ) sharpe = ef.portfolio_performance()[2] ef_long_only = setup_efficient_frontier() ef_long_only.max_sharpe() long_only_sharpe = ef_long_only.portfolio_performance()[2] assert sharpe > long_only_sharpe
def test_min_volatility_short(): ef = EfficientFrontier( *setup_efficient_frontier(data_only=True), weight_bounds=(None, None) ) w = ef.min_volatility() assert isinstance(w, dict) assert set(w.keys()) == set(ef.tickers) assert set(w.keys()) == set(ef.expected_returns.index) np.testing.assert_almost_equal(ef.weights.sum(), 1) np.testing.assert_allclose( ef.portfolio_performance(), (0.1719799158957379, 0.15559547854162945, 0.9734986722620801), ) # Shorting should reduce volatility volatility = ef.portfolio_performance()[1] ef_long_only = setup_efficient_frontier() ef_long_only.min_volatility() long_only_volatility = ef_long_only.portfolio_performance()[1] assert volatility < long_only_volatility
def test_efficient_risk_market_neutral(): ef = EfficientFrontier( *setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1) ) w = ef.efficient_risk(0.19, market_neutral=True) assert isinstance(w, dict) assert set(w.keys()) == set(ef.tickers) assert set(w.keys()) == set(ef.expected_returns.index) np.testing.assert_almost_equal(ef.weights.sum(), 0) assert (ef.weights < 1).all() and (ef.weights > -1).all() np.testing.assert_almost_equal( ef.portfolio_performance(), (0.2309497469661495, 0.19000021138101422, 1.1021245569881066) ) sharpe = ef.portfolio_performance()[2] ef_long_only = setup_efficient_frontier() ef_long_only.efficient_return(0.25) long_only_sharpe = ef_long_only.portfolio_performance()[2] assert long_only_sharpe > sharpe
def test_efficient_return_market_neutral(): ef = EfficientFrontier( *setup_efficient_frontier(data_only=True), weight_bounds=(-1, 1) ) w = ef.efficient_return(0.25, market_neutral=True) assert isinstance(w, dict) assert set(w.keys()) == set(ef.tickers) assert set(w.keys()) == set(ef.expected_returns.index) np.testing.assert_almost_equal(ef.weights.sum(), 0) assert (ef.weights < 1).all() and (ef.weights > -1).all() np.testing.assert_almost_equal( ef.portfolio_performance(), (0.25, 0.20567621957041887, 1.1087335497769277) ) sharpe = ef.portfolio_performance()[2] ef_long_only = setup_efficient_frontier() ef_long_only.efficient_return(0.25) long_only_sharpe = ef_long_only.portfolio_performance()[2] assert long_only_sharpe > sharpe
def test_efficient_risk_short(): ef = EfficientFrontier( *setup_efficient_frontier(data_only=True), weight_bounds=(None, None) ) w = ef.efficient_risk(0.19) assert isinstance(w, dict) assert set(w.keys()) == set(ef.tickers) assert set(w.keys()) == set(ef.expected_returns.index) np.testing.assert_almost_equal(ef.weights.sum(), 1) np.testing.assert_allclose( ef.portfolio_performance(), (0.30468522897560224, 0.19, 1.4947624032507056), atol=1e6, ) sharpe = ef.portfolio_performance()[2] ef_long_only = setup_efficient_frontier() ef_long_only.efficient_return(0.25) long_only_sharpe = ef_long_only.portfolio_performance()[2] assert sharpe > long_only_sharpe
def test_max_sharpe_L2_reg_with_shorts(): ef_no_reg = setup_efficient_frontier() ef_no_reg.max_sharpe() initial_number = sum(ef_no_reg.weights > 0.01) ef = EfficientFrontier( *setup_efficient_frontier(data_only=True), weight_bounds=(None, None) ) ef.gamma = 1 w = ef.max_sharpe() assert isinstance(w, dict) assert set(w.keys()) == set(ef.tickers) assert set(w.keys()) == set(ef.expected_returns.index) np.testing.assert_almost_equal(ef.weights.sum(), 1) np.testing.assert_allclose( ef.portfolio_performance(), (0.3236047844566581, 0.20241509723550233, 1.4969817524033966), ) new_number = sum(ef.weights > 0.01) assert new_number >= initial_number
def main(): print("Starting...") # Get the stock symbols/ tickers in the protfolio # FAANG (Facebook, Amazon, Apple, Netflix, Google assets = ['FB', 'AMZN', 'AAPL', 'NFLX', 'GOOG'] # Assign weights to the stocks. weights = np.array([0.2, 0.2, 0.2, 0.2, 0.2]) # Get the stock/ portfolio starting date stock_start_date = '2013-01-01' # Get the stocks ending data (today) today = datetime.today().strftime('%Y-%m-%d') # Create a data frame to store the adjusted close price of the stocks df = pd.DataFrame() # Store the adjusted close price of the stock into the df for stock in assets: df[stock] = web.DataReader(stock, data_source='yahoo', start=stock_start_date, end=today)['Adj Close'] # Visually show the stock / portfolio title = 'Portfolio adj. close price history' # Get the stocks my_stocks = df # Create and plot the graph for c in my_stocks.columns.values: plt.plot(my_stocks[c], label=c) plt.title = title plt.xlabel('Date', fontsize=18) plt.ylabel('Adj. Price USD', fontsize=18) plt.legend(my_stocks.columns.values, loc='upper left') plt.show() # Show the daily simple return returns = df.pct_change() # Create the annualized covariance matrix cov_matrix_annual = returns.cov() * 252 # Calculate the portfolio variance port_variance = np.dot(weights.T, np.dot(cov_matrix_annual, weights)) # Calculate the portfolio volatility aka standard deviation port_volatility = np.sqrt(port_variance) # Calculate annual portfolio return portfolio_simple_annual_return = np.sum(returns.mean() * weights) * 252 # Show the expected annual return, volatility (risk) and variance percent_variance = str(round(port_variance, 2) * 100) + '%' percent_volatility = str(round(port_volatility, 2) * 100) + '%' percent_return = str(round(portfolio_simple_annual_return, 2) * 100) + '%' print('Expected annual return: ' + percent_return) print('Annual volatility / risk: ' + percent_volatility) print('Annual variance: ' + percent_variance) # Portfolio optimization # Calculate the expected returns and the annualised sample covariance matrix of asset returns mu = expected_returns.mean_historical_return(df) s = risk_models.sample_cov(df) # Optimize for maximum sharpe (William Sharpe) ratio ef = EfficientFrontier(mu, s) cleaned_weights = ef.clean_weights() print(cleaned_weights) print(ef.portfolio_performance(verbose=True)) # Get the discrete allocation of each share per stock latest_prices = get_latest_prices(df) weights = cleaned_weights da = DiscreteAllocation(weights, latest_prices, total_portfolio_value=500) allocation, leftover = da.lp_portfolio() print('Discrete allocation: ' + str(allocation)) print('Funds remaining: ${:.2f}'.format(leftover))
# In[107]: mu = expected_returns.mean_historical_return(df) #returns.mean() * 252 S = risk_models.sample_cov(df) #Get the sample covariance matrix # Optimize for maximal Sharpe ration . # In[108]: ef = EfficientFrontier(mu, S) weights = ef.max_sharpe() #Maximize the Sharpe ratio, and get the raw weights cleaned_weights = ef.clean_weights() print(cleaned_weights) #Note the weights may have some rounding error, meaning they may not add up exactly to 1 but should be close ef.portfolio_performance(verbose=True) # Now we see that we can optimize this portfolio by having about 44.29% of the portfolio in Tesla , 55.71% in Amazon. # Also I can see that the expected annual volatility has increased to 34.5% but the annual expected rate also to 50.7% is . This optimized portfolio has a Sharpe ratio of 1.41 which is good. # I want to get the discrete allocation of each share of the stock, meaning I want to know exactly how many of each stock I should buy given some amount that I am willing to put into this portfolio. # In[111]: from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices latest_prices = get_latest_prices(df) weights = cleaned_weights da = DiscreteAllocation(weights, latest_prices, total_portfolio_value=10000) allocation, leftover = da.lp_portfolio() print("Discrete allocation:", allocation)
def main(): dashboard = st.sidebar.selectbox('Which Dashboard to open?', ('All Stocks', 'Strategies', 'Analysis', 'Portfolio', 'Pattern', 'Update Stocks')) cursor = connection.cursor() if dashboard == 'All Stocks': st.title(dashboard) print(f'Inside dashboard : {dashboard}') cursor.execute('''select symbol from stock''') stocks_symbols = cursor.fetchall() stocks = [item for t in stocks_symbols for item in t] symbol_search = st.sidebar.text_input("Stock name ") symbol = st.sidebar.selectbox("Select the Stock", stocks) if symbol_search != "": symbol = symbol_search result = get_quote(symbol) #data = json.loads(result['data'][0]) #df = pd.json_normalize(data['data']) st.dataframe(pd.DataFrame(result['data'])) # elif dashboard == 'Pattern': # stocks= {} # print(f'Inside dashboard : {dashboard}') # st.title(dashboard) # cursor.execute('''select symbol from stock''') # stocks_symbols = cursor.fetchall() # stocks = [item for t in stocks_symbols for item in t] # symbol = st.sidebar.selectbox("Select the Stock",stocks) # df = pd.read_sql("select open,high,low,close,symbol from stock_price where symbol ='"+symbol+"'", connection) # cursor.execute('''select key,name from patterns''') # patterns = cursor.fetchall() # # patterns = [item for t in patterns for item in t] # for pattern in patterns: # pattern_function = getattr(tb,pattern[0]) # result = pattern_function(df['Open'],df['High'],df['Low'],df['Close']) # last = result.tail(1).values[0] # if last>0: # st.write("Patter name : "+pattern[1]) # st.write("BULLISH") # elif last<0: # st.write("Patter name : "+pattern[1]) # st.write("BEARISH") elif dashboard == 'Strategies': print(f'Inside dashboard : {dashboard}') st.title(dashboard) cursor.execute('''select name from strategy''') strategies = cursor.fetchall() strategies = [item for t in strategies for item in t] strategy = st.sidebar.selectbox("Select the Strategy", strategies) cursor.execute('''select name from sectors''') sectors = cursor.fetchall() sectors = [item for t in sectors for item in t] sector = st.sidebar.selectbox("Select the Sector", sectors) if sector == 'All': cursor.execute('''select symbol from stock''') stocks = cursor.fetchall() stock_in_sector = [item for t in stocks for item in t] else: df = pd.read_csv("nifty Sectors/" + sector + ".csv") stock_in_sector = pd.Series(df['Symbol']) st.header("Strategy selected: " + strategy) if strategy == 'TTM Squeeze': if sector != "": my_bar = st.progress(0) percent_complete = 1 i = 1 for stock in stock_in_sector: percent_complete = int((i / len(stock_in_sector)) * 100) i = i + 1 df = pd.read_sql( "select * from stock_price where symbol= '" + stock + "'", connection) if df.empty: continue # st.dataframe(df) #if len(df.squeeze_on.tail()) > 3: if df.iloc[-3]['squeeze_on'] and not df.iloc[-1][ 'squeeze_on'] and (df.iloc[-1]['OBV'] * 2) > df.iloc[-1]['OBV_EMA']: mess = "{} is coming out of squeezer".format(stock) st.subheader(mess) st.dataframe( df.sort_values(by=['Date'], ascending=False)) newdf = df candlestick = go.Candlestick(x=newdf['Date'], open=newdf['Open'], high=newdf['High'], low=newdf['Low'], close=newdf['Close']) upper_band = go.Scatter(x=newdf['Date'], y=newdf['upper_band'], name='Upper Bollinger Band', line={'color': 'red'}) lower_band = go.Scatter(x=newdf['Date'], y=newdf['lower_band'], name='Lower Bollinger Band', line={'color': 'red'}) upper_keltner = go.Scatter( x=newdf['Date'], y=newdf['upper_keltner'], name='Upper Keltner Channel', line={'color': 'blue'}) lower_keltner = go.Scatter( x=newdf['Date'], y=newdf['lower_keltner'], name='Lower Keltner Channel', line={'color': 'blue'}) OBV = go.Scatter(x=newdf['Date'], y=newdf['OBV'], name='On Balace Volume', line={'color': 'black'}) OBV_EMA = go.Scatter(x=newdf['Date'], y=newdf['OBV_EMA'], name='On Balace Volume EMA', line={'color': 'green'}) fig_vol = go.Figure(data=[OBV, OBV_EMA]) fig = go.Figure(data=[ candlestick, upper_band, lower_band, upper_keltner, lower_keltner ]) fig.layout.xaxis.type = 'category' fig.layout.xaxis.rangeslider.visible = False first, last = st.beta_columns(2) first.plotly_chart(fig) last.plotly_chart(fig_vol) my_bar.progress(percent_complete) if percent_complete == 100: st.balloons() elif strategy == 'On Balance Volume(OBV)': if sector != "": my_bar = st.progress(0) percent_complete = 1 i = 1 for stock in stock_in_sector: percent_complete = int((i / len(stock_in_sector)) * 100) i = i + 1 df = pd.read_sql( "select * from stock_price where symbol= '" + stock + "'", connection) if df.empty: continue newdf = df if newdf.iloc[-1]['OBV'] > newdf.iloc[-1][ 'OBV_EMA'] and newdf.iloc[-1]['Close'] > newdf.iloc[ -1]['21ema'] and newdf.iloc[-1][ 'Close'] > newdf.iloc[-1]['VWAP']: mess = "{} is above OBV, 20EMA and VWAP ".format( stock) st.subheader(mess) candlestick = go.Candlestick(x=newdf['Date'], open=newdf['Open'], high=newdf['High'], low=newdf['Low'], close=newdf['Close']) OBV = go.Scatter(x=newdf['Date'], y=newdf['OBV'], name='Volume', line={'color': 'yellow'}) OBV_EMA = go.Scatter(x=newdf['Date'], y=newdf['OBV_EMA'], name='Volume EMA', line={'color': 'green'}) fig = go.Figure(data=[OBV, OBV_EMA]) fig.layout.xaxis.type = 'category' fig.layout.xaxis.rangeslider.visible = False figPrice = go.Figure(data=[candlestick]) figPrice.layout.xaxis.type = 'category' figPrice.layout.xaxis.rangeslider.visible = False first, last = st.beta_columns(2) first.plotly_chart(fig) last.plotly_chart(figPrice) my_bar.progress(percent_complete) if percent_complete == 100: st.balloons() elif strategy == 'SuperTrend': if sector != "": my_bar = st.progress(0) percent_complete = 1 i = 1 for stock in stock_in_sector[:3]: st.subheader(stock) percent_complete = int((i / len(stock_in_sector)) * 100) i = i + 1 df = pd.read_sql( "select * from stock_price where symbol= '" + stock + "'", connection) if df.empty: continue df = supertrend.run_supertrend(df, 10, 3) df['in_uptrend'] = True for current in range(1, len(df.Close)): previous = current - 1 if df['Close'][current] > df['upperband'][previous]: df['in_uptrend'][current] = True elif df['Close'][current] < df['Lowerband'][previous]: df['in_uptrend'][current] = False else: df['in_uptrend'][current] = df['in_uptrend'][ previous] if df['in_uptrend'][current] and df['Lowerband'][ current] < df['Lowerband'][previous]: df['Lowerband'][current] = df['Lowerband'][ previous] if not df['in_uptrend'][ current] and df['upperband'][current] > df[ 'upperband'][previous]: df['upperband'][current] = df['upperband'][ previous] candlestick = go.Candlestick(x=df['Date'], open=df['Open'], high=df['High'], low=df['Low'], close=df['Close']) upper_band = go.Scatter(x=df['Date'], y=df['upperband'], name='Upper Band', line={'color': 'red'}) lower_band = go.Scatter(x=df['Date'], y=df['Lowerband'], name='Lower Band', line={'color': 'red'}) fig = go.Figure(data=[candlestick, upper_band, lower_band]) fig.layout.xaxis.type = 'category' fig.layout.xaxis.rangeslider.visible = False st.plotly_chart(fig) my_bar.progress(percent_complete) if percent_complete == 100: st.balloons() elif strategy == 'Support & Resistence': if sector != "": my_bar = st.progress(0) percent_complete = 1 i = 1 for stock in stock_in_sector: percent_complete = int((i / len(stock_in_sector)) * 100) i = i + 1 df = pd.read_sql( "select * from stock_price where symbol= '" + stock + "'", connection) if df.empty: continue s = np.mean(df['High'] - df['Low']) df['Date'] = pd.to_datetime(df.index) df['Date'] = df['Date'].apply(mpl_dates.date2num) df = df.loc[:, ['Date', 'Open', 'High', 'Low', 'Close']] def isFarFromLevel(l): return np.sum([abs(l - x) < s for x in levels]) == 0 levels = [] def isSupport(df, i): support = df['Low'][i] < df['Low'][ i - 1] and df['Low'][i] < df['Low'][ i + 1] and df['Low'][i + 1] < df['Low'][ i + 2] and df['Low'][i - 1] < df['Low'][i - 2] return support def isResistance(df, i): resistance = df['High'][i] > df['High'][i - 1] and df[ 'High'][i] > df['High'][i + 1] and df['High'][ i + 1] > df['High'][i + 2] and df['High'][ i - 1] > df['High'][i - 2] return resistance for i in range(2, df.shape[0] - 2): if isSupport(df, i): l = df['Low'][i] if isFarFromLevel(l): levels.append((i, l)) elif isResistance(df, i): l = df['High'][i] if isFarFromLevel(l): levels.append((i, l)) elif strategy == 'Breakout': if sector != "": my_bar = st.progress(0) percent_complete = 1 i = 1 def is_consolidating(df, percentage=2): recent_candlesticks = df[-15:] max_close = recent_candlesticks['Close'].max() min_close = recent_candlesticks['Close'].min() threshold = 1 - (percentage / 100) if min_close > (max_close * threshold): return True return False def is_breaking_out(df, percentage=2.5): last_close = df[-1:]['Close'].values[0] if is_consolidating(df[:-1], percentage=percentage): recent_closes = df[-16:-1] if last_close > recent_closes['Close'].max(): return True return False percentage = st.slider('Slide me to select percentage', min_value=1, max_value=10) for stock in stock_in_sector: percent_complete = int((i / len(stock_in_sector)) * 100) i = i + 1 df = pd.read_sql( "select * from stock_price where symbol= '" + stock + "'", connection) if df.empty: continue if is_breaking_out(df, percentage): newdf = df st.subheader(f'{stock} is breaking out...') candlestick = go.Candlestick(x=newdf['Date'], open=newdf['Open'], high=newdf['High'], low=newdf['Low'], close=newdf['Close']) OBV = go.Scatter(x=newdf['Date'], y=newdf['OBV'], name='On Balace Volume', line={'color': 'black'}) OBV_EMA = go.Scatter(x=newdf['Date'], y=newdf['OBV_EMA'], name='On Balace Volume EMA', line={'color': 'green'}) fig_vol = go.Figure(data=[OBV, OBV_EMA]) fig = go.Figure(data=[candlestick]) fig.layout.xaxis.type = 'category' fig.layout.xaxis.rangeslider.visible = False first, last = st.beta_columns(2) first.plotly_chart(fig) last.plotly_chart(fig_vol) my_bar.progress(percent_complete) if percent_complete == 100: st.balloons() elif dashboard == 'Portfolio': print(f'Inside dashboard : {dashboard}') st.title(dashboard) cursor.execute('''select name from sectors''') sectors = cursor.fetchall() sectors = [item for t in sectors for item in t] sector = st.sidebar.selectbox("Select the Sector", sectors) alldf = pd.read_sql("select * from stock_price", connection) if sector == 'All': cursor.execute('''select symbol from stock''') stocks = cursor.fetchall() stock_in_sector = [item for t in stocks for item in t] alldf = alldf.loc[alldf['Symbol'].isin(stock_in_sector)] else: df = pd.read_csv("nifty Sectors/" + sector + ".csv") alldf = alldf.loc[alldf['Symbol'].isin(df['Symbol'])] #alldf = alldf.set_index(pd.DatetimeIndex(df['Date'].values)) #alldf.drop(columns = ['Date'], axis =1, inplace=True) assets = alldf.Symbol.unique() alldf = alldf.set_index('Date') alldf = alldf.pivot_table(index='Date', columns=['Symbol'], values='Close') alldf = alldf.set_index(pd.DatetimeIndex(alldf.index.values)) alldf = alldf.dropna(axis=1) #medals.reindex_axis(['Gold', 'Silver', 'Bronze'], axis=1) st.subheader("Stocks") st.write(alldf) #mu = expected_returns.mean_historical_return(alldf) #s = risk_models.sample_cov(alldf) span = st.slider('Slide me to select span', min_value=1, max_value=500) mu = expected_returns.ema_historical_return(alldf, span=span) st.subheader("Returns") st.write(mu) s = CovarianceShrinkage(alldf).shrunk_covariance() ef = EfficientFrontier(mu, s) weight = ef.max_sharpe() clean_weight = ef.clean_weights() expectedreturn, volatility, Sharperatio = ef.portfolio_performance( verbose=False) st.subheader("Expected annual return: " + str(round(expectedreturn, 2) * 100) + '%') st.subheader("Annual volatility: " + str(round(volatility, 2) * 100) + '%') st.subheader("Sharpe Ratio: " + str(round(Sharperatio, 2))) funds = st.slider('PortFolio Value:', min_value=50000, max_value=500000) latest_prices = get_latest_prices(alldf) weights = clean_weight da = DiscreteAllocation(weights, latest_prices, total_portfolio_value=funds) allocation, leftover = da.lp_portfolio() st.subheader("Weight") st.write(pd.DataFrame(weights, columns=weights.keys(), index=[0])) st.subheader("Discreate Allocation") st.write(pd.DataFrame(allocation, columns=allocation.keys(), index=[0])) st.subheader("Funds Reamaning:" + str(round(leftover, 2))) elif dashboard == 'Update Stocks': print(f'Inside dashboard : {dashboard}') st.title(dashboard) icon('update') if st.button('Update Tables'): status = nse.updateTableList(connection) if status == 'Success': st.balloons() if st.button('Update Stocks Price'): status = update_stock.updateStockPrice(st, connection) if status == 'Success': st.balloons() if st.button('Create Stocks Tables'): status = update_stock.updateTables(connection) if status == 'Success': st.balloons()
def portfolio_optimizer(): etfs_meta = { 'SPY': 'SPDR S&P 500 ETF Trust' , 'XLF': 'Financial Select Sector SPDR Fund' , 'QQQ': 'Invesco QQQ Trust' , 'XLE': 'Energy Select Sector SPDR Fund' , 'IAU': 'iShares Gold Trust' , 'KRE': 'SPDR S&P Regional Banking ETF' , 'XLI': 'Industrial Select Sector SPDR Fund' , 'IYR': 'iShares U.S. Real Estate ETF' , 'IEFA': 'iShares Core MSCI EAFE ETF' , 'XLP': 'Consumer Staples Select Sector SPDR Fund'} etfs_options = list(etfs_meta.keys()) start_date = "2015-01-01" # t-1 yesterday = (date.today() - timedelta(days=1)).strftime("%Y-%m-%d") end_date = yesterday @st.cache def load_data(etfs, start, end): df = yf.download(" ".join(etfs), start=start, end=end)['Adj Close'] return df df = load_data(etfs_options, start_date, end_date) returns = df.pct_change().dropna() st.markdown("---") st.subheader("ETF list") # Show ETF metadata etfs_metadata_df = pd.DataFrame.from_dict(etfs_meta, orient='index').reset_index().rename(columns={"index": "Ticker", 0: "Short description"}) st.table(etfs_metadata_df) st.markdown("---") st.subheader("Historical prices") # Visualize historical prices # title = 'Historical Adj. Close Price of available ETFs' df_temp = df.copy() df_temp['Date'] = df_temp.index df_plot = pd.melt(df_temp, id_vars='Date', value_vars=df_temp.columns[:-1]).rename(columns={'variable': 'Asset', 'value': 'Price ($)'}) fig = px.line(df_plot, x='Date', y='Price ($)', color='Asset') st.plotly_chart(fig) st.subheader("Parameters") etfs_chosen = st.multiselect( 'Which ETFs would you like to potentially add into your portfolio? (recommended to include all)', etfs_options, default=etfs_options) investment_amount = st.number_input('Investment amount (between 1000 and 10000)', min_value=1000, max_value=10000) st.write('Your chosen amount is ', investment_amount) if st.checkbox("All set, let's run the optimization model!"): df = df[etfs_chosen] # calculate expected returns mu = expected_returns.mean_historical_return(df) mu_df = pd.DataFrame(mu).reset_index().rename(columns={"index": "Ticker", 0: "Expected Return (%)"}).sort_values(by="Expected Return (%)", ascending=False) mu_df['Expected Return (%)'] = round(mu_df['Expected Return (%)']*100,2) st.subheader("Expected returns") st.markdown("Showing returns that we could expect when taking into account historical data.") fig = px.bar(mu_df, x='Ticker', y='Expected Return (%)', width=300, height=200) st.plotly_chart(fig) # calculate estimated covariance matrix (risk model) using Ledoit-Wolf shrinkage # reduces the extreme values in the covariance matrix S = risk_models.CovarianceShrinkage(df).ledoit_wolf() st.subheader("Covariance matrix") st.markdown("Showing relationship in price movement between different ETFs.") sns.heatmap(S.corr()) st.pyplot() # Optimize the portfolio performance # Sharpe ratio: portfolio's return less risk-free rate, per unit of risk (volatility) ef = EfficientFrontier(mu, S, weight_bounds=(0.01, 1)) weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() portfolio_performance = ef.portfolio_performance() st.markdown("---") st.subheader("Portfolio performance") st.markdown('Summary metrics:') st.markdown('Expected annual return: {:.2f}%'.format(portfolio_performance[0]*100)) st.markdown('Annual volatility: {:.2f}%'.format(portfolio_performance[1]*100)) st.markdown('Sharpe Ratio: {:.2f}'.format(portfolio_performance[2])) latest_prices = get_latest_prices(df) da = DiscreteAllocation(weights, latest_prices, total_portfolio_value=investment_amount) latest_prices_column = pd.DataFrame(latest_prices).columns[0] latest_prices_df = pd.DataFrame(latest_prices).reset_index().rename(columns={"index": "Ticker", latest_prices_column: "Latest Price"}).sort_values(by='Ticker') allocation, leftover = da.lp_portfolio() st.subheader("Portfolio allocation") allocation_df = pd.DataFrame.from_dict(allocation, orient='index').reset_index().rename(columns={"index": "Ticker", 0: "Shares"}).sort_values(by='Ticker') allocation_df = pd.merge(allocation_df, latest_prices_df, on='Ticker', how='left') allocation_df['Amount'] = allocation_df['Shares'] * allocation_df['Latest Price'] allocation_df.sort_values(by='Amount', inplace=True, ascending=False) allocation_df['Allocation percentage'] = ((allocation_df['Amount'] / allocation_df['Amount'].sum())*100).round(2) allocation_df['Amount'] = ['$' + str(round(item,2)) for item in allocation_df['Amount']] allocation_df['Latest Price'] = ['$' + str(round(item,2)) for item in allocation_df['Latest Price']] allocation_df.reset_index(inplace=True, drop=True) st.table(allocation_df) title = "Allocation visualization (# of shares)" fig = px.bar(allocation_df, x='Ticker', y='Shares', width=600, height=400,title=title) st.plotly_chart(fig) title = "Allocation visualization (% invested)" fig = px.bar(allocation_df, x='Ticker', y='Allocation percentage', width=600, height=400,title=title) st.plotly_chart(fig) invested_amount = investment_amount - leftover st.markdown('Funds invested: ${:.2f}'.format(invested_amount)) st.markdown('Funds remaining: ${:.2f}'.format(leftover))
def _sharpe_on_holdings(holdings): ''' holdings: api.rh.build_holdings() ''' df = pd.DataFrame(index=None) equities = {} with ShadyBar('%32s' % 'Pulling Historic Quote Prices', max=len(holdings)) as bar: for ticker, datum in holdings.items(): df[ticker] = slurp.stock_historic_prices(ticker)['Adj Close'] equities[ticker] = F(datum['equity']) bar.next() # Calculate the current weight of each stock in the portfolio equity = sum(equities.values()) weights = np.array( [equities[ticker] / equity for ticker in equities.keys()], dtype=np.float) # Calculate historic returns (percentage change close-to-close) returns = df.pct_change() # Number of Trading Days per Year (roughly) annual_trading_days = int(365 * 5 / 7 - 6 - 3 * 5 / 7) # Calculate the Annual Covariance # - The diagonal of this matrix is the variance (sqrt of the variance is volatility) # - Every other cell is the covariance (between the two non-identical tickes) annual_covariance = returns.cov() * annual_trading_days # Calculate the Portfolio Variance annual_variance = np.dot(weights.T, np.dot(annual_covariance, weights)) # Calculate the Portfolio Volatility annual_volatility = np.sqrt(annual_variance) # Calculate the Simple Annual Return simple_annual_return = np.sum(returns.mean() * weights * annual_trading_days) # Measure the Portfolio response = dict(status_quo=dict( expected_annual_return=simple_annual_return, annual_volatility=annual_volatility, annual_variance=annual_variance, ), efficient_frontier=dict()) # Improve the Portfolio # Calculate expected returns and annualized sample covariance matrix of asset returns mu = ppo.expected_returns.mean_historical_return(df) S = ppo.risk_models.sample_cov(df) # Optimize for max sharpe ratio (k) - measures the performance of the porfolio compared # to risk-free investments like bonds or treasuries ef = EfficientFrontier(mu, S) reweighted = ef.max_sharpe() cleanweighted = ef.clean_weights() response['efficient_frontier']['portfolio'] = { ticker: pct for ticker, pct in cleanweighted.items() if pct > 0 } expected_annual_return, annual_volatility, sharpe_ratio = ef.portfolio_performance( ) risk_free_ror = expected_annual_return - sharpe_ratio * annual_volatility response['efficient_frontier']['expectation'] = dict( expected_annual_return=expected_annual_return, annual_volatility=annual_volatility, sharpe_ratio=sharpe_ratio, risk_free_ror=risk_free_ror, ) response['status_quo']['risk_free_rate'] = risk_free_ror response['status_quo']['sharpe_ratio'] = ( simple_annual_return - risk_free_ror) / annual_volatility return response
def main(): """ Runs the main descriptive stadistict about stocks and also get optimal portafolio """ t0 = dt.datetime.now() args = utils.get_args() all_config = yaml.safe_load(open(args.config_file_path, "r")) DATA = all_config['output']['data_folder'] input_data_path = all_config['stocks']['data'] logger = logger_utils.log_creator(all_config['output']['log_folder'], log_name='get_stats') start_date, end_date = utils.get_start_end(all_config) df_ticks_path = os.path.join('./src/data', input_data_path) logger.info("Reading tick and weights from %s" % df_ticks_path) weights = utils.get_ticks_data(df_ticks_path) data_path = utils.filename_maker('stocks_', DATA, start_date, end_date) data_sp_path = utils.filename_maker('sp500_', DATA, start_date, end_date) df = pd.read_csv(data_path) sp = pd.read_csv(data_sp_path) df['Date'] = pd.to_datetime(df['Date']) df.set_index('Date', inplace=True) df_pc = df.pct_change().dropna() sp['Date'] = pd.to_datetime(sp['Date']) sp.set_index('Date', inplace=True) sp_pc = sp.pct_change().dropna() weights_np = weights['WEIGHT'].to_numpy() anual_cov_matrix = df_pc.cov()*252 volatilidad_por_anual = np.sqrt(np.dot(weights_np.T, np.dot(anual_cov_matrix, weights_np))) logger.info("Anual portafolio volatility is %.2f" % volatilidad_por_anual) portafolio_anual_return = np.sum(df_pc.mean()*weights_np)*252 logger.info("Anual portafolio return is %.2f" % portafolio_anual_return) logger.info("Mean historical return for each stock %s" % round((df_pc.mean()*252),2)) logger.info("Anual volatility for each stock %s" % round(np.std(df_pc)*np.sqrt(252),2)) # np.sum(df_pc.mean()*weights['WEIGHT'].to_numpy())*252 ticks = weights['TICK'].to_list() skew_list = [] kurtosis_list = [] shapiro_list = [] annual_vol = [] annual_returns = [] for tk in ticks: skewness = np.round(df_pc[tk].skew(), 3) kurt = np.round(df_pc[tk].kurtosis() + 3, 3) shap = np.round(shapiro(df_pc[tk])[1], 3) vol = np.round(df_pc[tk].std()*np.sqrt(252), 3) rtn = np.round((df_pc[tk].mean()*252), 3) skew_list.append(skewness) kurtosis_list.append(kurt) shapiro_list.append(shap) annual_vol.append(vol) annual_returns.append(rtn) logger.info("This is the summary of the stocks regarding the anual return, anual volatility, kurtosis, shapiro and skew.") stocks_summary = pd.DataFrame({'STOCK': ticks, 'SKEW': skew_list, 'KURTOSIS': kurtosis_list, 'SHAPIRO': shapiro_list, 'ANNUAL_VOL': annual_vol, 'ANNUAL_RETURN': annual_returns}) stocks_summary.set_index('STOCK', inplace=True) logger.info(stocks_summary) logger.info("Lets now calculate the anual covariance between stoks") cov_matriz = df_pc.cov()*252 logger.info(cov_matriz) logger.info("Using Python Portafolio") mu = expected_returns.mean_historical_return(df) sigma = risk_models.sample_cov(df) ef = EfficientFrontier(mu, sigma) logger.info("Showing portafolio with max sharpe rate") raw_weights_maxsharpe = ef.max_sharpe() cleaned_weights_maxsharpe = ef.clean_weights() logger.info(cleaned_weights_maxsharpe) # Show portfolio performance logger.info(ef.portfolio_performance(verbose=True)) desire_return = 0.20 ef.efficient_return(desire_return) logger.info("Calculating portafolio which should bring a return of %s" % desire_return) logger.info(ef.clean_weights()) logger.info("Showing portafolio with lowest risk for a return of %s" % desire_return) raw_weights_minvol = ef.min_volatility() cleaned_weights_minvol = ef.clean_weights() logger.info(cleaned_weights_minvol) logger.info(ef.portfolio_performance(verbose=True)) t1 = dt.datetime.now()
[cluster_data_lists[i][asset_name].fillna(cluster_data_lists[i][asset_name].mean()) * w for asset_name, w in weight_list[i].items()]) for i in range(len(cluster_data_lists))], axis=1) new_cov = risk_models.CovarianceShrinkage(new_data).ledoit_wolf() # print(new_mu) # print(new_cov) total_ef = EfficientFrontier(new_mu, new_cov) if args.volatility < 0: cluster_weight = total_ef.max_sharpe(args.risk_free_rate) else: cluster_weight = total_ef.efficient_risk(args.volatility, args.risk_free_rate) total_weight = {} for cluster_id, weights in enumerate(weight_list): for asset_id, w in weights.items(): total_weight[asset_id] = cluster_weight[cluster_id] * w print(len(total_weight)) final_ef = EfficientFrontier(mu, cov) final_ef.weights = total_weight print(total_weight) final_ef.portfolio_performance(True) print(str(time() - start) + " s")
import time import pypfopt from pypfopt.efficient_frontier import EfficientFrontier from pypfopt import expected_returns from pypfopt import risk_models import settings start_time = time.time() start_date = datetime.datetime(settings.start_date[0], settings.start_date[1], settings.start_date[2]) end_date = datetime.datetime(settings.end_date[0], settings.end_date[1], settings.end_date[2]) price_data = web.DataReader(settings.portfolio, 'yahoo', start_date, end_date)['Adj Close'] price_data.index.rename('date', True) returns = expected_returns.mean_historical_return(price_data) cov = risk_models.sample_cov(price_data) ef = EfficientFrontier(returns, cov, weight_bounds=(.1, .4)) sharpe = ef.max_sharpe() min_vol = ef.min_volatility() performance = ef.portfolio_performance() # returns expected returns, volatility, sharpe ratio elapsed = round(time.time() - start_time, 2) print("Portfolio optimized..") print("Completed in {} seconds..".format(elapsed))
elif 'daily_profit' in tdata.columns and not np.isnan( tdata['daily_profit']).all(): # 日结 data_list.append( (tdata[['daily_profit']] / 10000 + 1).cumprod(axis=1).rename(columns={ 'daily_profit': filename[0:6] }, index=str).astype('float')) else: print("BAD file: " + filename) data = pd.concat(data_list, axis=1) print(data.info()) # efficient frontier mu = expected_returns.ema_historical_return(data) print(np.isnan(mu).any()) S = risk_models.CovarianceShrinkage(data).ledoit_wolf() print(np.isnan(S).any().any()) ef = EfficientFrontier(mu, S) if args.volatility < 0: print(ef.max_sharpe(args.risk_free_rate)) else: print(ef.efficient_risk(args.volatility, args.risk_free_rate)) ef.portfolio_performance(True) print(str(time() - start) + " s")
def mo_portfolio(budget, yesterday, end_period): # debug print(f'Hello from mo_portfolio') print(f'- budget:\t\t {budget}') print(f'- yesterday:\t {yesterday}') print(f'- end_period:\t {end_period}') if end_period is None: return 'False' global g_budget g_budget = budget global g_date g_date = [yesterday, end_period] # yesterday: day before the creation of the portfolio # end_period: end of investment chart = pd.DataFrame() # chart: adj closes fino a yesterday for s in stocks: chart = pd.concat( [chart, dataframes[s]['Adj Close'].loc[:yesterday, ]], axis=1) chart.columns = stocks # compute montly (default value = 'Y') cc return chart_rt = {} for s in chart: tmp = chart[s].groupby(pd.Grouper(freq="Y")) tmp2 = tmp.mean() chart_rt[s] = np.log(tmp2 / tmp2.shift(1)) chart_rt = pd.DataFrame.from_dict(chart_rt) chart_rt = chart_rt.dropna() chart_rt.columns = [ "AAPL CC returns", "NVDA CC returns", "KO CC returns", "UL CC returns", "BAC CC returns", "AXP CC returns" ] # adding transition costs (1,5% fee per share) chart = chart.apply(lambda x: x + (x * 0.015)) # Optimal portfolio # computes CC return on year granularity avg_returns = expected_returns.mean_historical_return(chart) # sample covariance matrix S = risk_models.sample_cov(chart) ef = EfficientFrontier(avg_returns, S) # Minimize the volatily of the portfolio (Markowitz) weights = ef.min_volatility() # rounding weights values, meaning they may not add up exactly to 1 but should be close weights = ef.clean_weights() Mop_pw = weights opt_return, opt_risk, _ = ef.portfolio_performance(verbose=False) global g_expected_return_volat g_expected_return_volat = [opt_return, opt_risk] recap = {} for s in weights: # print(f'{s} budget {budget}, {type(budget)}') # debug # print(f'{s} weights[s]/chart[s].iloc[-1] {weights[s]/chart[s].iloc[-1]}, {type(weights[s]/chart[s].iloc[-1])}') # debug recap[s] = [int(np.floor(budget * weights[s] / chart[s].iloc[-1])) ] # number of shares price_no_fee = np.round(chart[s].iloc[-1] - (chart[s].iloc[-1] * 1.5 / 101.5), decimals=2) recap[s].append(price_no_fee) # price for each shares recap[s].append(np.round(price_no_fee * 0.015, 2)) # transaction costs 1,5% tot_cost = np.around(recap[s][0] * (recap[s][1] + recap[s][2]), decimals=2) recap[s].append( tot_cost ) # total cost of the investment in s (shares * (price for each s + transaction costs)) recap = pd.DataFrame.from_dict(recap, orient='index') recap.columns = [ 'Num of shares', 'Price for each share $', 'Transaction costs $', 'Purchase cost $' ] global g_recap g_recap = recap total = 0 for _, row in recap.iterrows(): total += row['Purchase cost $'] total = np.around(total, decimals=2) global g_spent g_spent = total global g_left g_left = str(np.around(budget - total, decimals=2)) price_end = {} tot_port = 0 for s in dataframes: price_end[s] = dataframes[s]['Adj Close'].loc[end_period] act_return = 0 for index, row in recap.iterrows(): tot_port += np.around(row['Num of shares'] * (price_end[index] + row['Transaction costs $']), decimals=2) rtn = (price_end[index] + row['Transaction costs $'] ) / recap.loc[index, 'Price for each share $'] - 1 act_return += weights[index] * rtn global g_returns g_returns = str(np.around(tot_port, decimals=2)) + ' [' + str( np.round(100 * act_return, decimals=2)) + '%]' print(g_returns) return "True"
def load_portfolio_dash(RANDOM_NUMBER_SELECTED_IN, PORTFOLIO_VALUE_IN): START_DATE_FOR_STOCK_PRICES = '2015-1-1' # When you want your Stocks to go back to STOCK_TICKERS_CSV = 'stock_ticker_list.csv' PERCENTAGE_TO_USE = 10 # The % in which the amount a column must have otherwise it will be deleted # MAX 400 Tickers at this moment in time RANDOM_NUMBER_SELECTED = RANDOM_NUMBER_SELECTED_IN # The number used to select the number of element from a larger list PORTFOLIO_VALUE = PORTFOLIO_VALUE_IN # The amount in $ you wish to invest # Load the tickers list from the csv file of tickers names with open(STOCK_TICKERS_CSV, newline='') as f: reader = csv.reader(f) data = list(reader) tickers_list_imported = [] for d in data: ticker = str(d).replace("'", "").replace("[", "").replace("]", "").replace(" ", "") tickers_list_imported.append(ticker) # 2 tickers just to start the dataframe in the correct format tickers_list_start = ['AAPL', 'TSLA'] # Fetching the data from the list of tickers data = yf.download(tickers_list_start, START_DATE_FOR_STOCK_PRICES)['Adj Close'] df = pd.DataFrame(data) ticker_count = 0 LIST_TO_USE = random.sample(tickers_list_imported, RANDOM_NUMBER_SELECTED) #LIST_TO_USE = tickers_list_imported progress_count = 0 my_progress_bar = st.progress(progress_count) val_to_progress_up = (100 / len(LIST_TO_USE)) / 100 for i in range(len(LIST_TO_USE)): if ticker_count > 0 and ticker_count % 300 == 0: #df.to_csv ('stock_dataframe.csv', index=True, header=True) st.write('\nSleeping for 2 Minutes\n') time.sleep(120) ticker_count = ticker_count + 1 data_new_col_name = str(LIST_TO_USE[i]) #st.write('\n' + str(ticker_count) + '/' + str(len(LIST_TO_USE)) + ' - Downloading: ' + data_new_col_name) try: data_new = yf.download(LIST_TO_USE[i], START_DATE_FOR_STOCK_PRICES)['Adj Close'] df[data_new_col_name] = data_new except: continue progress_count = progress_count + val_to_progress_up if progress_count <= 1: my_progress_bar.progress(progress_count) else: my_progress_bar.progress(100) #Drooping stock values no_data_for_ticker_list = [] row_count_based_on_percentage = int(len(df) * (PERCENTAGE_TO_USE / 100)) for (columnName, columnData) in df.iteritems(): if df[columnName].isnull().all(): #st.write('Dropping : ' + str(columnName) + ' - it is all NAN') no_data_for_ticker_list.append(df.columns.get_loc(columnName)) #elif df[columnName].count() < row_count_based_on_percentage: # st.write('Dropping : ' + str(columnName) + ' - < than ' + str(PERCENTAGE_TO_USE) + '% of then number of rows') # no_data_for_ticker_list.append(df.columns.get_loc(columnName)) df = df.drop(df.columns[no_data_for_ticker_list], axis=1) # Creating a csv file #df.to_csv ('stock_dataframe.csv', index=True, header=True) # Calculate the expected annualised returns and the annualised sample covariance matrix of the daily asset returns mu = expected_returns.mean_historical_return(df) S = risk_models.sample_cov(df) # Optimise for the maximal Sharpe ratio - describes how much excess return you recieve from the extra volitility you endure for holding a riskier asset ef = EfficientFrontier(mu, S) # Create the Efficient Frontier object raw_weights = ef.max_sharpe( ) # maximise the Sharpe Ratio and get the raw weights # Helper method to clean the raw weights setting any weights whos absolute values are below the cut off point to zero and rounding the rest # can cause some rounding errors - should not be off by a lot just good to know cleaned_weights = ef.clean_weights() # Get the discret allocations of each share per stock and the leftover money from investment latest_price = get_latest_prices(df) weights = cleaned_weights da = DiscreteAllocation(weights, latest_price, total_portfolio_value=PORTFOLIO_VALUE) allocation, leftover = da.lp_portfolio() # Store the company name into a list & Get descrete allocation values company_name = [] discrete_allocation_list = [] for symbol in allocation: company_name.append(get_company_name(symbol)) discrete_allocation_list.append(allocation.get(symbol)) # Create the portfolio # Create DF for portfolio portfolio_df = pd.DataFrame(columns=[ 'Company_Name', 'Company_Ticker', 'Discrete_val_' + str(PORTFOLIO_VALUE) ]) # Add data to portfolio df portfolio_df['Company_Name'] = company_name portfolio_df['Company_Ticker'] = allocation portfolio_df['Discrete_val_' + str(PORTFOLIO_VALUE)] = discrete_allocation_list # How the portfolio would expect to return perf = ef.portfolio_performance(verbose=True) st.write() st.write( 'Any Sharpe ratio over 1.0 is considered acceptable to good buy investment:' ) st.write('Expected annual return:', round(perf[0], 2), '%') st.write('Annual volatility:', round(perf[1], 2), '%') st.write('Sharpe Ratio:', round(perf[0], 2)) st.write() st.write('Funds Remaining: $', round(leftover, 2)) # Show the portfolio st.write(portfolio_df)
def performance(request): current_user = request.user user = Profile.objects.get(user = current_user) all_portfolios_of_current_users = Portfolio.objects.filter(user = user) stock_and_prices = {} stocks_held = {} all_stocks = [] total_assets_worth = 0 for indv in all_portfolios_of_current_users: all_stocks.append(indv.stock) for stock in all_stocks: price = si.get_live_price(stock) stock_and_prices[stock] = {'price': price} print(stock_and_prices) for indv in all_portfolios_of_current_users: total_assets_worth += stock_and_prices[indv.stock]['price'] * indv.number for indv in all_portfolios_of_current_users: stock = indv.stock number = indv.number worth = stock_and_prices[indv.stock]['price'] * indv.number # total_assets_worth += worth percentage = stock_and_prices[indv.stock]['price'] * indv.number/ total_assets_worth stocks_held[stock] = percentage assets = [] weights = [] for stock, percentage in stocks_held.items(): assets.append(stock) weights.append(percentage) if request.method == "POST": assets = assets weights = np.array(weights) #Get the stock starting date stockStartDate = '2017-01-01' # Get the stocks ending date aka todays date and format it in the form YYYY-MM-DD today = datetime.today().strftime('%Y-%m-%d') #Create a dataframe to store the adjusted close price of the stocks df = pd.DataFrame() #Store the adjusted close price of stock into the data frame for stock in assets: df[stock] = web.DataReader(stock,data_source='yahoo',start=stockStartDate , end=today)['Adj Close'] # Create the title 'Portfolio Adj Close Price History title = 'Portfolio Adj. Close Price History ' #Get the stocks my_stocks = df #Create and plot the graph plt.figure(figsize=(12.2,4.5)) #width = 12.2in, height = 4.5 # Loop through each stock and plot the Adj Close for each day for c in my_stocks.columns.values: plt.plot( my_stocks[c], label=c)#plt.plot( X-Axis , Y-Axis, line_width, alpha_for_blending, label) plt.title(title) plt.xlabel('Date',fontsize=18) plt.ylabel('Adj. Price USD ($)',fontsize=18) plt.legend(my_stocks.columns.values, loc='upper left') returns = df.pct_change() cov_matrix_annual = returns.cov() * 252 port_variance = np.dot(weights.T, np.dot(cov_matrix_annual, weights)) port_volatility = np.sqrt(port_variance) portfolioSimpleAnnualReturn = np.sum(returns.mean()*weights) * 252 percent_var = str(round(port_variance, 2) * 100) + '%' percent_vols = str(round(port_volatility, 2) * 100) + '%' percent_ret = str(round(portfolioSimpleAnnualReturn, 2)*100)+'%' mu = expected_returns.mean_historical_return(df)#returns.mean() * 252 S = risk_models.sample_cov(df) #Get the sample covariance matrix ef = EfficientFrontier(mu, S) weights = ef.max_sharpe() #Maximize the Sharpe ratio, and get the raw weights cleaned_weights = ef.clean_weights() weight_list = list(cleaned_weights.values()) #return the dictionary #print(cleaned_weights) #Note the weights may have some rounding error, meaning they may not add up exactly to 1 but should be close #print out the porfolio performance #ef.portfolio_performance(verbose=True) tuple_elements = ef.portfolio_performance(verbose=False) ef_return = tuple_elements[0] ef_volatility = tuple_elements[1] ef_ratio =tuple_elements[2] stock_dict = {} for i in range(len(weight_list)): percentage = "{:.2%}".format(weight_list[i]) stock_dict[assets[i]] = percentage name_list = ['return','volatility','ratio'] optimized_dict = {} for i in range(len(name_list)): percentage = "{:.2%}".format(tuple_elements[i]) optimized_dict[name_list[i]] = percentage return render(request, 'performance.html',{'weight_list':weight_list,'assets':assets, 'ef_return':ef_return,'ef_volatility':ef_volatility,'ef_ratio':ef_ratio,'percent_var':percent_var, 'percent_vols':percent_vols, 'percent_ret':percent_ret,'stock_dict':stock_dict,'optimized_dict':optimized_dict}) else: assets = assets weights = np.array(weights) #Get the stock starting date stockStartDate = '2017-01-01' # Get the stocks ending date aka todays date and format it in the form YYYY-MM-DD today = datetime.today().strftime('%Y-%m-%d') #Create a dataframe to store the adjusted close price of the stocks df = pd.DataFrame() #Store the adjusted close price of stock into the data frame for stock in assets: df[stock] = web.DataReader(stock,data_source='yahoo',start=stockStartDate , end=today)['Adj Close'] # Create the title 'Portfolio Adj Close Price History title = 'Portfolio Adj. Close Price History ' #Get the stocks my_stocks = df #Create and plot the graph plt.figure(figsize=(12.2,4.5)) #width = 12.2in, height = 4.5 # Loop through each stock and plot the Adj Close for each day for c in my_stocks.columns.values: plt.plot( my_stocks[c], label=c)#plt.plot( X-Axis , Y-Axis, line_width, alpha_for_blending, label) plt.title(title) plt.xlabel('Date',fontsize=18) plt.ylabel('Adj. Price USD ($)',fontsize=18) plt.legend(my_stocks.columns.values, loc='upper left') returns = df.pct_change() cov_matrix_annual = returns.cov() * 252 port_variance = np.dot(weights.T, np.dot(cov_matrix_annual, weights)) port_volatility = np.sqrt(port_variance) portfolioSimpleAnnualReturn = np.sum(returns.mean()*weights) * 252 percent_var = str(round(port_variance, 2) * 100) + '%' percent_vols = str(round(port_volatility, 2) * 100) + '%' percent_ret = str(round(portfolioSimpleAnnualReturn, 2)*100)+'%' return render(request, 'performance.html',{'percent_var':percent_var, 'percent_vols':percent_vols, 'percent_ret':percent_ret,'assets':assets})
def portfolio_all(df): coins = ['ripple','bitcoin','ethereum','litecoin','iota','bitcoin_cash'] #coins = ['bitcoin'] stocks = df.dropna()[coins] log_ret = np.log(stocks/stocks.shift(1)) np.random.seed(42) num_ports = 6000 all_weights = np.zeros((num_ports, len(stocks.columns))) ret_arr = np.zeros(num_ports) vol_arr = np.zeros(num_ports) sharpe_arr = np.zeros(num_ports) for x in range(num_ports): # Weights weights = np.array(np.random.random(len(stocks.columns))) weights = weights/np.sum(weights) # Save weights all_weights[x,:] = weights # Expected return ret_arr[x] = np.sum( (log_ret.mean() * weights * int(252))) # Expected volatility vol_arr[x] = np.sqrt(np.dot(weights.T, np.dot(log_ret.cov()*int(252), weights))) # Sharpe Ratio sharpe_arr[x] = ret_arr[x]/vol_arr[x] max_sr_ret = ret_arr[sharpe_arr.argmax()] max_sr_vol = vol_arr[sharpe_arr.argmax()] logging.info(vol_arr) logging.info(ret_arr) fig = go.Figure(data=go.Scatter(x=vol_arr, y=ret_arr, mode='markers', marker=dict( size=8, color=sharpe_arr, #set color equal to a variable colorscale='Viridis', # one of plotly colorscales showscale=True ) )) fig.add_trace( go.Scatter( mode='markers', x=[max_sr_vol], y=[max_sr_ret], marker=dict( color='Red', size=10 ), showlegend=False ) ) logging.info("Saving portfolio graph...") plio.write_html(fig,'/appdata/portgraphstatic.html', include_plotlyjs=True) logging.info("Getting portfolio info") mu = mean_historical_return(stocks,frequency=int(252)) S = CovarianceShrinkage(stocks).ledoit_wolf() ef = EfficientFrontier(mu, S) weights = ef.max_sharpe() logging.info(weights) perf = ef.portfolio_performance(verbose=True) portinfo={'weights':weights, 'performance':{'Return':perf[0],'Volatility':perf[1],'Sharpe Ratio':perf[2]}} logging.info(type(portinfo)) with open('/appdata/portinfo.json', 'w') as f: json.dump(portinfo, f)
c1, c2, c3, c4 = st.beta_columns((1, 1, 1, 1)) #-----Χαρτοφυλάκιο Νο1 γενικό #Calculate portofolio mu and S mu = expected_returns.mean_historical_return(df_t) if riskmo: S = CovarianceShrinkage(df_t).ledoit_wolf() else: S = risk_models.sample_cov(df_t) # Optimise the portfolio ef = EfficientFrontier(mu, S, gamma=2) # Use regularization (gamma=1) if weightsmo: weights = ef.max_sharpe() else: weights = ef.min_volatility() cleaned_weights = ef.clean_weights(cutoff=cutoff, rounding=3) ef.portfolio_performance() c1.subheader('Χαρτοφυλάκιο Νο1') c1.write( 'Το προτινόμενο χαρτοφυλάκιο από τις ιστορικές τιμές των επιλεγμένων μετοχών έχει τα παρακάτω χαρακτηριστικά' ) c1.write('Αρχική Αξία Χαρτοφυλακίου : ' + str(port_value) + '€') c1.write('Sharpe Ratio: ' + str(round(ef.portfolio_performance()[2], 2))) c1.write('Απόδοση Χαρτοφυλακίο: ' + str(round(ef.portfolio_performance()[0] * 100, 2)) + '%') c1.write('Μεταβλητότητα Χαρτοφυλακίου: ' + str(round(ef.portfolio_performance()[1] * 100, 2)) + '%') # Allocate latest_prices = get_latest_prices(df_t) da = DiscreteAllocation(cleaned_weights, latest_prices,
end='2020-06-06', data_source='yahoo') price_data.append(prices.assign(ticker=ticker)[['Adj Close']]) df_stocks = pd.concat(price_data, axis=1) df_stocks.columns = tickers df_stocks.head() #Annualized Return mu = expected_returns.mean_historical_return(df_stocks) #Sample Variance of Portfolio Sigma = risk_models.sample_cov(df_stocks) #Max Sharpe Ratio - Tangent to the EF ef = EfficientFrontier(mu, Sigma, weight_bounds=(0, 1)) fig, ax = plt.subplots() plotting.plot_efficient_frontier(ef) ef.max_sharpe() ret_tangent, std_tangent, _ = ef.portfolio_performance() ax.scatter(std_tangent, ret_tangent, marker="*", s=100, c="r", label="Max Sharpe") ax.set_title("Efficient Frontier") ax.legend() plt.tight_layout() plt.show()
from pypfopt import risk_models from pypfopt import expected_returns from pypfopt.efficient_frontier import EfficientFrontier from pypfopt.black_litterman import BlackLittermanModel prbr = pd.read_excel(r'C:\Users\Jhona\OneDrive\Área de Trabalho\PRBR11.xlsx', index_col='Data', parse_dates=['Data']) ###Expectativa de retornos de mu mu = expected_returns.mean_historical_return(prbr) ###Matrix de covariancia sigma = risk_models.sample_cov(prbr) ###Fronteira eficiente Max sharpe ef = EfficientFrontier(mu, sigma) weights = ef.max_sharpe() ef.efficient_risk(2.0) ef.efficient_return(1.5) cleaned_weights = ef.clean_weights() print(weights, cleaned_weights) ef.portfolio_performance(verbose=True, risk_free_rate=0.0225) ###Fronteira eficiente Min Vol ef = EfficientFrontier(mu, sigma) raw_weights = ef.min_volatility() cleaned_weights = ef.clean_weights() print(cleaned_weights) ef.portfolio_performance(verbose=True, risk_free_rate=0.02)
from pypfopt import expected_returns from pypfopt.hierarchical_risk_parity import hrp_portfolio from pypfopt.value_at_risk import CVAROpt from pypfopt import discrete_allocation # Reading in the data; preparing expected returns and a risk model df = pd.read_csv("tests/stock_prices.csv", parse_dates=True, index_col="date") returns = df.pct_change().dropna(how="all") mu = expected_returns.mean_historical_return(df) S = risk_models.sample_cov(df) # Long-only Maximum Sharpe portfolio, with discretised weights ef = EfficientFrontier(mu, S) weights = ef.max_sharpe() ef.portfolio_performance(verbose=True) latest_prices = discrete_allocation.get_latest_prices(df) allocation, leftover = discrete_allocation.portfolio(weights, latest_prices) print("Discrete allocation:", allocation) print("Funds remaining: ${:.2f}".format(leftover)) """ Expected annual return: 33.0% Annual volatility: 21.7% Sharpe Ratio: 1.43 Discrete allocation: {'MA': 14, 'FB': 12, 'PFE': 51, 'BABA': 5, 'AAPL': 5, 'AMZN': 0, 'BBY': 9, 'SBUX': 6, 'GOOG': 1} Funds remaining: $12.15 """
df_m = df_m[(df_m['momentum'] > minimum_momentum - 0.5 * dev) & ( df_m['momentum'] < minimum_momentum + 1.9 * dev)].head(portfolio_size) # Set the universe to the top momentum stocks for the period universe = df_m['stock'].tolist() # Create a df with just the stocks from the universe df_t = select_columns(df_tr, universe) # -----Χαρτοφυλάκιο Νο1 γενικό # Calculate portofolio mu and S mu = capm_returns(df_t) S = CovarianceShrinkage(df_t).ledoit_wolf() # Optimise the portfolio for maximal Sharpe ratio ef = EfficientFrontier(mu, S) # Use regularization (gamma=1) weights = ef.min_volatility() cleaned_weights = ef.clean_weights(cutoff=cutoff, rounding=3) ef.portfolio_performance() st.subheader('Βελτιστοποιημένο Χαρτοφυλάκιο') st.write( 'Το προτεινόμενο χαρτοφυλάκιο από τις ιστορικές τιμές των επιλεγμένων μετοχών έχει τα παρακάτω χαρακτηριστικά' ) st.write('Αρχική Αξία Χαρτοφυλακίου : ' + str(port_value) + '€') st.write('Sharpe Ratio: ' + str(round(ef.portfolio_performance()[2], 2))) st.write('Απόδοση Χαρτοφυλακίου: ' + str(round(ef.portfolio_performance()[0] * 100, 2)) + '%') st.write('Μεταβλητότητα Χαρτοφυλακίου: ' + str(round(ef.portfolio_performance()[1] * 100, 2)) + '%') # Allocate latest_prices = get_latest_prices(df_t) da = DiscreteAllocation(cleaned_weights, latest_prices,
def rebalnce_portfolios(): p = abspath(getsourcefile(lambda: 0)) p = p.rsplit('/', 1)[0] os.chdir(p) print('Working Directory is: %s' % os.getcwd()) file_path = p + '/results_2015-2019/' # !!! Editable Folder with files with weights start_time = '2015-01-01' # !!! start date, editable end_time = (datetime.today() - timedelta(days=1)).strftime( '%Y-%m-%d') # last day = day before today # Lists of files with portfolio weights files = [f for f in listdir(file_path) if isfile(join(file_path, f))] files = [f for f in files if f.startswith('portfolio_investment')] files = [file_path + f for f in files] files = sorted(files) weight_bounds_tuple = ( (0.0, 0.1), (0.0, 0.1), (0.0, 0.15), (0.0, 0.05), (0.0, 0.05), (0.01, 0.1) ) # !!! Weights to be adjusted for every iteration by arbitrary value gamma = 0.05 total_portfolio_value = 20000 for i in range(0, len(files)): portfolio = pd.read_csv(files[i], index_col=0).iloc[:, 0:6] tickers = portfolio.iloc[:, 2].tolist( ) # tickers inside portfolio (they will be updated) # Getting stock data (maybe re-do to for loop, if there be problems with memory) temp = pdr.DataReader(tickers, 'yahoo', start_time, end_time)['Close'] current_weights = portfolio['allocation_weight'].to_list() risk_free_rate = 0.0085 # !!! Risk-free rate, 10Y US treasury bond, could be adjusted weight_bounds = weight_bounds_tuple[ i] # taken from the tuple each iteration, defined at the beginning # !!! Different approaches could be taken from here mu = mean_historical_return(temp) # Getting returns S = CovarianceShrinkage(temp).ledoit_wolf() # Getting cov matrix # Main function to find optimal portfolio, determining optimal weights ef = EfficientFrontier(mu, S, weight_bounds=weight_bounds) ef.add_objective(objective_functions.transaction_cost, w_prev=current_weights, k=0.005) ef.add_objective(objective_functions.L2_reg, gamma=gamma) weights = ef.max_sharpe( risk_free_rate=risk_free_rate) # using max sharpe optimization cleaned_weights = ef.clean_weights() # weights with pretty formatting print(cleaned_weights) # Printing info on returns, variance & sharpe ef.portfolio_performance(verbose=True) ### This function would change the weights to a number of shares based on the last price in the observable interval latest_prices = get_latest_prices(temp) da = DiscreteAllocation(weights, latest_prices, total_portfolio_value=total_portfolio_value) allocation, leftover = da.lp_portfolio() print(allocation) print("Money left: " + str(leftover)) print(da._allocation_rmse_error()) allocation = pd.DataFrame.from_dict(allocation, orient='index') allocation.columns = ['allocation_discrete'] weights = pd.DataFrame.from_dict(weights, orient='index') weights.columns = ['allocation_weight'] latest_prices = pd.DataFrame(latest_prices) latest_prices.columns = ['buy_price'] tickers = pd.DataFrame(tickers) tickers.columns = ['ticker'] tickers.index = tickers['ticker'] result = pd.concat([weights, allocation, tickers, latest_prices], axis=1) result['buy_investment'] = result['allocation_discrete'] * result[ 'buy_price'] result['actual_allocation'] = result['buy_investment'] / result[ 'buy_investment'].sum() # Get paths & filenames for saving with replacing old csv files n = files[i].split('_')[-1] s = file_path + 'portfolio_ticker_' + n result.to_csv(s)
response = table.scan(ExclusiveStartKey=response['LastEvaluatedKey']) items.extend(response['Items']) dfitems = pd.DataFrame(items, columns=['code', 'date', 'price']) f = dfitems.drop_duplicates(subset=['date', 'code'], keep='last') filtered = dfitems.pivot(index='date', columns='code', values='price') cols = filtered.columns filtered[cols] = filtered[cols].apply(pd.to_numeric, errors='coerce') filtered = filtered.dropna() print(filtered) mu = mean_historical_return(filtered) S = CovarianceShrinkage(filtered).ledoit_wolf() ef = EfficientFrontier(mu, S) max_sharpe = ef.max_sharpe() max_sharpe_performance = ef.portfolio_performance() minVolFrontier = EfficientFrontier(mu, S) min_volatility = minVolFrontier.min_volatility() min_vol_performance = minVolFrontier.portfolio_performance() print(max_sharpe_performance, "MAX SHARPE PERFORMANCE") print(min_vol_performance, "MIN VOL PERFORMANCE") addModelPrediction("max_sharpe_ratio", max_sharpe_performance[2], max_sharpe_performance[0], max_sharpe_performance[1], max_sharpe) addModelPrediction("min_volatility", min_vol_performance[2], min_vol_performance[0], min_vol_performance[1], min_volatility)
def create_portfolio(self): if len(self.all_tickers) == 0: return self.ui.progressBar.setVisible(True) self.ui.progressBar.setValue(0) df = pd.DataFrame() all_tickers = list(self.all_tickers) num_all_tickers = len(all_tickers) part_each_ticker_progressBar = 90 / num_all_tickers for idx, symbol in enumerate(all_tickers): try: df[symbol] = pdr.get_data_yahoo( symbol, start=datetime.datetime(2006, 1, 1), end=datetime.datetime.now())["Adj Close"] except Exception as e: print(e) continue self.ui.progressBar.setValue( (idx + 1) * part_each_ticker_progressBar) mu = expected_returns.mean_historical_return(df) S = risk_models.sample_cov(df) ef = EfficientFrontier(mu, S) ef.max_sharpe() cleaned_weights = ef.clean_weights() mu, sigma, sharpe = ef.portfolio_performance(verbose=False) portfolio_val = self.ui.spinBox.value() latest_prices = get_latest_prices(df) self.weights = cleaned_weights da = DiscreteAllocation(self.weights, latest_prices, total_portfolio_value=portfolio_val) allocation, leftover = da.greedy_portfolio() self.ui.progressBar.setValue(100) ##-- Page 2 <Parameters> from Pick_up_portfolio_class import pandasModel self.ui.stackedWidget.setCurrentWidget(self.ui.page_2) self.btn_page_2_visible() self.ui.progressBar.setVisible(False) self.ui.label_2.setText("Ожидаемая годовая доходность: {:.1f}%\n" "Годовая волатильность: {:.1f}%\n" "Коэффициент Шарпа: {:.2f}\n" "Остаток средств: {:.2f}$".format( 100 * mu, 100 * sigma, sharpe, leftover)) company_name = [] for symbol in allocation: company_name.append(get_company_name(symbol)) discrete_allocation_list = [] for symbol in allocation: discrete_allocation_list.append(allocation.get(symbol)) portfolio_df = pd.DataFrame(columns=[ 'Название компании', 'Тикер компании', 'Количество', 'Последняя цена, $', 'Сумма в портфеле, $' ]) portfolio_df['Название компании'] = company_name portfolio_df['Тикер компании'] = allocation portfolio_df['Количество'] = discrete_allocation_list portfolio_df['Последняя цена, $'] = np.round( get_latest_prices(df)[allocation].values, 2) portfolio_df['Сумма в портфеле, $'] = np.round( portfolio_df['Последняя цена, $'] * portfolio_df['Количество'], 2) portfolio_df = portfolio_df.sort_values(by='Количество', ascending=False) model = pandasModel(portfolio_df) self.ui.tableView.verticalHeader().setSectionResizeMode( QHeaderView.Stretch) self.ui.tableView.horizontalHeader().setSectionResizeMode( QHeaderView.Stretch) self.ui.tableView.setModel(model)