Difference between revisions of "MC1-Project-2"

From Quantitative Analysis Software Courses
Jump to navigation Jump to search
m (Minor edits)
(Refactored instructions to match project template)
Line 3: Line 3:
 
In this project you will use what you learned about optimizers to optimize a portfolio.  That means that you will find how much of a portfolio's funds should be allocated to each stock so as to optimize it's performance.  In this case we define "optimal" as maximum Sharpe ratio.
 
In this project you will use what you learned about optimizers to optimize a portfolio.  That means that you will find how much of a portfolio's funds should be allocated to each stock so as to optimize it's performance.  In this case we define "optimal" as maximum Sharpe ratio.
  
You will leverage the function you created in the last project that assessed the value of a portfolio with a given set of allocations.
+
You will leverage the functions you created in the last project that assessed the value of a portfolio with a given set of allocations.
  
 
==Task==
 
==Task==
  
Write a Python function named <TT>optimize_portfolio()</TT> that can find the optimal allocations for a given stock portfolio. You should optimize for Sharpe ratio.
+
Implement a Python function named <tt>find_optimal_allocations()</tt> that can find the optimal allocations for a given stock portfolio. You should optimize for Sharpe ratio.
  
Inputs to the function include:
+
The function should accept as input historical stock prices (supplied as a pandas dataframe, with each column representing one equity), and return a list of floats (as a one-dimensional numpy array) that represents the allocations to each of the equities. Use functions developed in the portfolio analysis project to compute daily portfolio value and statistics.
* Start date
 
* End date
 
* Symbols for equities (e.g., GOOG, AAPL, GLD, XOM)
 
  
The function should return:
+
To get started, download and unzip the template code (<tt>01-P2.zip</tt>).
* A list of floats that represents the allocations to each of the equities.
 
  
An example of how the function would be called:
+
A helper function has been included in the template code (see <tt>01-P2/portfolio/optimization.py</tt>), which is called with the desired date range and symbols (see <tt>test_run()</tt>):
 +
start_date = '2010-01-01'
 +
end_date = '2010-12-31'
 +
symbols = ['GOOG', 'AAPL', 'GLD', 'XOM']
 +
'''optimize_portfolio'''(start_date, end_date, symbols)
  
  allocations = optimize_portfolio(startdate, enddate, ['GOOG','AAPL','GLD','XOM'])
+
This in turn reads stock price data, and calls the function to find optimal allocations (you need to implement this):
 +
  allocs = '''find_optimal_allocations'''(prices)
  
Also, create a chart that illustrates the value of your portfolio over the year and compares it to SPY. The portfolio and SPY should be normalized to 1.0 at the beginning of the period.
+
The helper function (<tt>optimize_portfolio()</tt>) prints out the optimal allocations, and some statistics. It also plots a chart comparing the daily value of your portfolio over the year and compares it to SPY. The portfolio and SPY are normalized to 1.0 at the beginning of the period.
  
TODO: include example chart here
+
Make sure the output and plot look like the examples shown below.
  
 
==Suggestions==
 
==Suggestions==
  
None yet.
+
Refer to comments in <tt>find_optimal_allocations()</tt> for pointers regarding how to implement it. In order to specify bounds and constraints when using the <tt>scipy.optmize</tt> module, you'll need to use a special syntax explained here:
 +
http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html
  
Make sure your <tt>optimize_portfolio()</tt> function gives correct output. Check it against the examples below.
+
For bounds, you simply need to pass in a sequence of 2-tuples <tt>(&lt;low&gt;, &lt;high&gt;)</tt>. Just remember that you need to supply as many tuples as the number of stocks in your portfolio.
 +
 
 +
For constraints, it's a little tricky. You need to pass in a sequence of dicts (dictionaries), one dictionary per constraint. Each dictionary must specify the type of constraint (<tt>'eq'</tt> for equality, or <tt>'ineq'</tt> for inequality), and a function that ''returns 0 only when the input satisfies the constraint'' (this is the same input that is supplied to your evaluation function). E.g. to constrain the sum of all values in the input array to be less than 50, you could pass in the following (lambdas are just anonymous functions defined on-the-spot):
 +
constraints = ({'type': 'eq', 'fun': lambda inputs: 50.0 - np.sum(inputs) })
  
 
==Example output==
 
==Example output==
  
Here's an example output for your function. These are actual correct examples that you can use to check your work.
+
Here's an example output for your function. These are actual correct values that you can use to check your work.
  
todo:example 1
+
<pre>Start Date: 2010-01-01
 +
End Date: 2010-12-31
 +
Symbols: ['GOOG', 'AAPL', 'GLD', 'XOM']
 +
Optimal allocations: [  5.38105153e-16  3.96661695e-01  6.03338305e-01  -5.42000166e-17]
 +
Sharpe Ratio: 2.00401501102
 +
Volatility (stdev of daily returns): 0.0101163831312
 +
Average Daily Return: 0.00127710312803
 +
Cumulative Return: 0.360090826885</pre>
  
todo:example 2
+
Corresponding comparison plot:
 +
TODO
  
 
Minor differences in float values may arise due to different implementations.
 
Minor differences in float values may arise due to different implementations.
Line 43: Line 56:
 
==What to turn in==
 
==What to turn in==
  
Via t-square turn in attachments only:
+
Via T-Square, submit as attachments:
  
* Your code as <tt>submission.py</tt>
+
* Your code as <tt>portfolio.py</tt> (only find_optimal_allocations() will be tested)
* Your chart as <tt>chart.pdf</tt>
+
* Plot comparing the optimal portfolio with SPY as <tt>comparison_optimal.png</tt> (save from plot window)

Revision as of 21:25, 19 June 2015

Overview

In this project you will use what you learned about optimizers to optimize a portfolio. That means that you will find how much of a portfolio's funds should be allocated to each stock so as to optimize it's performance. In this case we define "optimal" as maximum Sharpe ratio.

You will leverage the functions you created in the last project that assessed the value of a portfolio with a given set of allocations.

Task

Implement a Python function named find_optimal_allocations() that can find the optimal allocations for a given stock portfolio. You should optimize for Sharpe ratio.

The function should accept as input historical stock prices (supplied as a pandas dataframe, with each column representing one equity), and return a list of floats (as a one-dimensional numpy array) that represents the allocations to each of the equities. Use functions developed in the portfolio analysis project to compute daily portfolio value and statistics.

To get started, download and unzip the template code (01-P2.zip).

A helper function has been included in the template code (see 01-P2/portfolio/optimization.py), which is called with the desired date range and symbols (see test_run()):

start_date = '2010-01-01'
end_date = '2010-12-31'
symbols = ['GOOG', 'AAPL', 'GLD', 'XOM']
optimize_portfolio(start_date, end_date, symbols)

This in turn reads stock price data, and calls the function to find optimal allocations (you need to implement this):

allocs = find_optimal_allocations(prices)

The helper function (optimize_portfolio()) prints out the optimal allocations, and some statistics. It also plots a chart comparing the daily value of your portfolio over the year and compares it to SPY. The portfolio and SPY are normalized to 1.0 at the beginning of the period.

Make sure the output and plot look like the examples shown below.

Suggestions

Refer to comments in find_optimal_allocations() for pointers regarding how to implement it. In order to specify bounds and constraints when using the scipy.optmize module, you'll need to use a special syntax explained here: http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html

For bounds, you simply need to pass in a sequence of 2-tuples (<low>, <high>). Just remember that you need to supply as many tuples as the number of stocks in your portfolio.

For constraints, it's a little tricky. You need to pass in a sequence of dicts (dictionaries), one dictionary per constraint. Each dictionary must specify the type of constraint ('eq' for equality, or 'ineq' for inequality), and a function that returns 0 only when the input satisfies the constraint (this is the same input that is supplied to your evaluation function). E.g. to constrain the sum of all values in the input array to be less than 50, you could pass in the following (lambdas are just anonymous functions defined on-the-spot):

constraints = ({'type': 'eq', 'fun': lambda inputs: 50.0 - np.sum(inputs) })

Example output

Here's an example output for your function. These are actual correct values that you can use to check your work.

Start Date: 2010-01-01
End Date: 2010-12-31
Symbols: ['GOOG', 'AAPL', 'GLD', 'XOM']
Optimal allocations: [  5.38105153e-16   3.96661695e-01   6.03338305e-01  -5.42000166e-17]
Sharpe Ratio: 2.00401501102
Volatility (stdev of daily returns): 0.0101163831312
Average Daily Return: 0.00127710312803
Cumulative Return: 0.360090826885

Corresponding comparison plot: TODO

Minor differences in float values may arise due to different implementations.

What to turn in

Via T-Square, submit as attachments:

  • Your code as portfolio.py (only find_optimal_allocations() will be tested)
  • Plot comparing the optimal portfolio with SPY as comparison_optimal.png (save from plot window)