@@ -94,25 +94,31 @@ demonstrating how easy it is to find the long-only portfolio
9494that maximises the Sharpe ratio (a measure of risk-adjusted returns).
9595
9696``` python
97- import pandas as pd
98- from pypfopt import EfficientFrontier
99- from pypfopt import risk_models
100- from pypfopt import expected_returns
97+ >> > import pandas as pd
98+ >> > from pypfopt import EfficientFrontier
99+ >> > from pypfopt import risk_models
100+ >> > from pypfopt import expected_returns
101101
102102# Read in price data
103- df = pd.read_csv(" tests/resources/stock_prices.csv" , parse_dates = True , index_col = " date" )
103+ >> > df = pd.read_csv(" tests/resources/stock_prices.csv" , parse_dates = True , index_col = " date" )
104104
105105# Calculate expected returns and sample covariance
106- mu = expected_returns.mean_historical_return(df)
107- S = risk_models.sample_cov(df)
106+ >> > mu = expected_returns.mean_historical_return(df)
107+ >> > S = risk_models.sample_cov(df)
108108
109109# Optimize for maximal Sharpe ratio
110- ef = EfficientFrontier(mu, S)
111- raw_weights = ef.max_sharpe()
112- cleaned_weights = ef.clean_weights()
113- ef.save_weights_to_file(" weights.csv" ) # saves to file
114- print (cleaned_weights)
115- ef.portfolio_performance(verbose = True )
110+ >> > ef = EfficientFrontier(mu, S)
111+ >> > raw_weights = ef.max_sharpe()
112+ >> > cleaned_weights = ef.clean_weights()
113+ >> > ef.save_weights_to_file(" weights.csv" ) # saves to file
114+ >> > cleaned_weights
115+ OrderedDict({' GOOG' : 0.0458 , ' AAPL' : 0.06743 , ' FB' : 0.2008 , ' BABA' : 0.08494 , ' AMZN' : 0.03525 , ' GE' : 0.0 , ' AMD' : 0.0 , ' WMT' : 0.0 , ' BAC' : 0.0 , ' GM' : 0.0 , ' T' : 0.0 , ' UAA' : 0.0 , ' SHLD' : 0.0 , ' XOM' : 0.0 , ' RRC' : 0.0 , ' BBY' : 0.01587 , ' MA' : 0.3287 , ' PFE' : 0.20394 , ' JPM' : 0.0 , ' SBUX' : 0.01726 })
116+ >> > ef.portfolio_performance(verbose = True )
117+ Expected annual return : 29.9 %
118+ Annual volatility: 21.8 %
119+ Sharpe Ratio: 1.38
120+ (0.29944709161230304 , 0.21764331681393406 , 1.375861643701672 )
121+
116122```
117123
118124This outputs the following weights:
@@ -150,22 +156,17 @@ convert the above continuous weights to an actual allocation
150156that you could buy. Just enter the most recent prices, and the desired portfolio size ($10,000 in this example):
151157
152158``` python
153- from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices
159+ >> > from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices
154160
161+ >> > latest_prices = get_latest_prices(df)
155162
156- latest_prices = get_latest_prices(df)
163+ >> > da = DiscreteAllocation(cleaned_weights, latest_prices, total_portfolio_value = 10000 )
164+ >> > allocation, leftover = da.greedy_portfolio()
165+ >> > print (" Discrete allocation:" , allocation)
166+ Discrete allocation: {' MA' : 19 , ' PFE' : 57 , ' FB' : 12 , ' BABA' : 4 , ' AAPL' : 4 , ' GOOG' : 1 , ' SBUX' : 2 , ' BBY' : 2 }
167+ >> > print (" Funds remaining: ${:.2f } " .format(leftover))
168+ Funds remaining: $ 17.46
157169
158- da = DiscreteAllocation(weights, latest_prices, total_portfolio_value = 10000 )
159- allocation, leftover = da.greedy_portfolio()
160- print (" Discrete allocation:" , allocation)
161- print (" Funds remaining: ${:.2f } " .format(leftover))
162- ```
163-
164- ``` txt
165- 12 out of 20 tickers were removed
166- Discrete allocation: {'GOOG': 1, 'AAPL': 4, 'FB': 12, 'BABA': 4, 'BBY': 2,
167- 'MA': 20, 'PFE': 54, 'SBUX': 1}
168- Funds remaining: $11.89
169170```
170171
171172_ Disclaimer: nothing about this project constitues investment advice,
0 commit comments