Part I - Writing a function called sharperatio
You have to write a function called sharperatio that will calculate
the Sharpe ratio of any financial instrument. Here are the
specifications: The inputs of this function are: A vector for the stock
returns (in continuously compounded) A value for the risk-free rate The
function has to calculate the Sharpe ratio of the stock using the given
risk-free rate. The function has to return the value of the Sharpe
ratio. As expected return of the stock, use its geometric return (as we
have done it when estimating expected return of a stock in a portfolio).
As expected risk of the stock, use the standard deviation of its
continuously compounded returns. Your function has to validate the
following: If any of the return values of the inputs has NA values, do
not consider these values to do the calculations Your R function has to
be flexible to any stock return. Test your function with one stock using
data from the text file usrets.csv. Download the usrets dataset from the
web using the following code: download.file(“http://www.apradie.com/fz3030/returns.csv”,
“returns.csv”) returns <- read.csv(file=“returns.csv”, header=TRUE,
sep=“,”)
This dataset has already monthly continuously compounded returns for
several US firms. The SECOND column (right after the date) of this
dataset you have the market return ( rGSPC), that is the S&P
returns. The first column has the date. You can use any of the stock
returns. You can test your function with the following code: sharpe1
<- sharperatio(returns$r_AAPL,0.001) cat(“The Sharpe ratio is”,
sharpe1) You MUST DOCUMENT your code. You have to include as comments
the following documentation: - At the beginning of your code, you have
to write your general approach of your program/function including
inputs, steps and output - Document your lines of code inside your
function, so I can read your line of thinking.
Part II Automate Sharpe ratio calculation using a loop
You have to write a program to automatically calculate the Sharpe
ratio for all stocks in the returns dataset, and then select the top 5
stocks with the highest sharpe ratio. You have to use the same dataset
returns.csv that has real monthly returns of several US stocks. Remember
that the stocks start in the third column of this dataset. Your program
has to do the following: a) Calculate and save in a vector or matrix all
the sharpe ratios. Use risk-free rate=0.001 for all stocks. You have to
use a loop for this part. b) Select the top 5 stocks with the highest
Sharpe ratio. c) (extra 10 points) Estimate the optimal (tangent)
portfolio with these stocks (as risk-free rate, use zero) Specifications
of your program: You ONLY have to include the CODE you need for this
program. Extra code will be penalized. Your program MUST RUN according
to the content of the csv file. For example, if you delete, change a
column or add one, your program should run consider this. You MUST
DOCUMENT your code. You have to include as comments the following
documentation: - At the beginning of your code, you have to write your
general approach of your program/function including inputs, steps and
output - Document your lines of code, so I can read your line of
thinking. You have to submit an .html FILE with both problems. Name your
file as YourNameExam2
Part 1 - Solution
AS ALWAYS, THESE TESTS ARE MADE TO CHALLENGE US REGARDING OUR
FINANCIAL PROGRAMMING KNOWLEDGE. WE ARE GIVEN A DATASET SO NATURALLY
WE’LL BE USING THAT FOR OUR FUNCTION. FIRST THINGS FIRST, WE’LL NEED TO
DOWNLOAD SOME PACKAGES IN ORDER TO DOWNLOAD OUR DATA.
library(PerformanceAnalytics)
library(quantmod)
library(dygraphs)
monthly_stock_returns <- function(ticker, start_year)
download.file("http://www.apradie.com/fz3030/returns.csv", "returns.csv")
returns.csv <- read.csv(file="returns.csv", header=TRUE, sep=",")
# Lets choose the starting year for our function
year <- 2018
# And visualize our monthly returns
monthly_stock_returns('AAPL', 2018)
trying URL 'http://www.apradie.com/fz3030/returns.csv'
Content type 'text/csv' length 22812 bytes (22 KB)
==================================================
downloaded 22 KB
monthly_stock_returns('CERN', 2018)
trying URL 'http://www.apradie.com/fz3030/returns.csv'
Content type 'text/csv' length 22812 bytes (22 KB)
==================================================
downloaded 22 KB
monthly_stock_returns('XOM', 2018)
trying URL 'http://www.apradie.com/fz3030/returns.csv'
Content type 'text/csv' length 22812 bytes (22 KB)
==================================================
downloaded 22 KB
# CREATING OBJECTS FOR EACH STOCK RETURN IN 2016
Apple_Returns <- monthly_stock_returns('AAPL', 2018)
trying URL 'http://www.apradie.com/fz3030/returns.csv'
Content type 'text/csv' length 22812 bytes (22 KB)
==================================================
downloaded 22 KB
Cerner_Returns <- monthly_stock_returns('CERN', 2018)
trying URL 'http://www.apradie.com/fz3030/returns.csv'
Content type 'text/csv' length 22812 bytes (22 KB)
==================================================
downloaded 22 KB
ExxonM_Returns <- monthly_stock_returns('XOM', 2018)
trying URL 'http://www.apradie.com/fz3030/returns.csv'
Content type 'text/csv' length 22812 bytes (22 KB)
==================================================
downloaded 22 KB
# Lets merge the returns to assing weights
merged_returns <- merge.default(Apple_Returns, Cerner_Returns, ExxonM_Returns)
# Plotting 2018's returns
plot(merged_returns)

# NOW THAT I HAVE THREE STOCKS MERGED IN ONE OBJECT, LET US ASSING WEIGHTS
w <- c(.25, .25, .50)
# APLYING FUNCTION RETURN PORTFOLIO
portfolio_monthly_returns <- Return.portfolio(merged_returns, weights = w)
Error in checkData(R, method = "xts") :
The data cannot be converted into a time series. If you are trying to pass in names from a data object with one column, you should use the form 'data[rows, columns, drop = FALSE]'. Rownames should have standard date formats, such as '1985-03-15'.
sd(merged_returns)
[1] 0.5773503
SharpeRatio(FUN = StdDev(0.5773503))
Error in checkData(R) : argument "R" is missing, with no default
Part 2 - Solution
For this loop well be using the objects and data created previously
in order to make a loop that calculates the desired information.
returns_equities <- Return.excess(eq_prices)
Error in is.xts(x) : object 'eq_prices' not found
LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKYXV0aG9yOiBTdGVmYW4gU2Nod2VpdHplciAtIEEwMTIwOTc1NQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sKLS0tCgojIFBhcnQgSSAtIFdyaXRpbmcgYSBmdW5jdGlvbiBjYWxsZWQgc2hhcnBlcmF0aW8KCllvdSBoYXZlIHRvIHdyaXRlIGEgZnVuY3Rpb24gY2FsbGVkIHNoYXJwZXJhdGlvIHRoYXQgd2lsbCBjYWxjdWxhdGUgdGhlIFNoYXJwZSByYXRpbyBvZiBhbnkgZmluYW5jaWFsIGluc3RydW1lbnQuIEhlcmUgYXJlIHRoZSBzcGVjaWZpY2F0aW9uczoKVGhlIGlucHV0cyBvZiB0aGlzIGZ1bmN0aW9uIGFyZToKQSB2ZWN0b3IgZm9yIHRoZSBzdG9jayByZXR1cm5zIChpbiBjb250aW51b3VzbHkgY29tcG91bmRlZCkKQSB2YWx1ZSBmb3IgdGhlIHJpc2stZnJlZSByYXRlClRoZSBmdW5jdGlvbiBoYXMgdG8gY2FsY3VsYXRlIHRoZSBTaGFycGUgcmF0aW8gb2YgdGhlIHN0b2NrIHVzaW5nIHRoZSBnaXZlbiByaXNrLWZyZWUgcmF0ZS4gVGhlIGZ1bmN0aW9uIGhhcyB0byByZXR1cm4gdGhlIHZhbHVlIG9mIHRoZSBTaGFycGUgcmF0aW8uCkFzIGV4cGVjdGVkIHJldHVybiBvZiB0aGUgc3RvY2ssIHVzZSBpdHMgZ2VvbWV0cmljIHJldHVybiAoYXMgd2UgaGF2ZSBkb25lIGl0IHdoZW4gZXN0aW1hdGluZyBleHBlY3RlZCByZXR1cm4gb2YgYSBzdG9jayBpbiBhIHBvcnRmb2xpbykuCkFzIGV4cGVjdGVkIHJpc2sgb2YgdGhlIHN0b2NrLCB1c2UgdGhlIHN0YW5kYXJkIGRldmlhdGlvbiBvZiBpdHMgY29udGludW91c2x5IGNvbXBvdW5kZWQgcmV0dXJucy4KWW91ciBmdW5jdGlvbiBoYXMgdG8gdmFsaWRhdGUgdGhlIGZvbGxvd2luZzoKSWYgYW55IG9mIHRoZSByZXR1cm4gdmFsdWVzIG9mIHRoZSBpbnB1dHMgaGFzIE5BIHZhbHVlcywgZG8gbm90IGNvbnNpZGVyIHRoZXNlIHZhbHVlcyB0byBkbyB0aGUgY2FsY3VsYXRpb25zCllvdXIgUiBmdW5jdGlvbiBoYXMgdG8gYmUgZmxleGlibGUgdG8gYW55IHN0b2NrIHJldHVybi4KVGVzdCB5b3VyIGZ1bmN0aW9uIHdpdGggb25lIHN0b2NrIHVzaW5nIGRhdGEgZnJvbSB0aGUgdGV4dCBmaWxlIHVzcmV0cy5jc3YuIERvd25sb2FkIHRoZSB1c3JldHMgZGF0YXNldCBmcm9tIHRoZSB3ZWIgdXNpbmcgdGhlIGZvbGxvd2luZyBjb2RlOgpkb3dubG9hZC5maWxlKCJodHRwOi8vd3d3LmFwcmFkaWUuY29tL2Z6MzAzMC9yZXR1cm5zLmNzdiIsICJyZXR1cm5zLmNzdiIpCnJldHVybnMgPC0gcmVhZC5jc3YoZmlsZT0icmV0dXJucy5jc3YiLCBoZWFkZXI9VFJVRSwgc2VwPSIsIikKClRoaXMgZGF0YXNldCBoYXMgYWxyZWFkeSBtb250aGx5IGNvbnRpbnVvdXNseSBjb21wb3VuZGVkIHJldHVybnMgZm9yIHNldmVyYWwgVVMgZmlybXMuIFRoZSBTRUNPTkQgY29sdW1uIChyaWdodCBhZnRlciB0aGUgZGF0ZSkgb2YgdGhpcyBkYXRhc2V0IHlvdSBoYXZlIHRoZSBtYXJrZXQgcmV0dXJuICggckdTUEMpLCB0aGF0IGlzIHRoZSBTJlAgcmV0dXJucy4gVGhlIGZpcnN0IGNvbHVtbiBoYXMgdGhlIGRhdGUuIFlvdSBjYW4gdXNlIGFueSBvZiB0aGUgc3RvY2sgcmV0dXJucy4KWW91IGNhbiB0ZXN0IHlvdXIgZnVuY3Rpb24gd2l0aCB0aGUgZm9sbG93aW5nIGNvZGU6CnNoYXJwZTEgPC0gc2hhcnBlcmF0aW8ocmV0dXJucyRyX0FBUEwsMC4wMDEpCmNhdCgiVGhlIFNoYXJwZSByYXRpbyBpcyAiLCBzaGFycGUxKQpZb3UgTVVTVCBET0NVTUVOVCB5b3VyIGNvZGUuIFlvdSBoYXZlIHRvIGluY2x1ZGUgYXMgY29tbWVudHMgdGhlIGZvbGxvd2luZyBkb2N1bWVudGF0aW9uOgotIEF0IHRoZSBiZWdpbm5pbmcgb2YgeW91ciBjb2RlLCB5b3UgaGF2ZSB0byB3cml0ZSB5b3VyIGdlbmVyYWwgYXBwcm9hY2ggb2YgeW91ciBwcm9ncmFtL2Z1bmN0aW9uIGluY2x1ZGluZyBpbnB1dHMsIHN0ZXBzIGFuZCBvdXRwdXQKLSBEb2N1bWVudCB5b3VyIGxpbmVzIG9mIGNvZGUgaW5zaWRlIHlvdXIgZnVuY3Rpb24sIHNvIEkgY2FuIHJlYWQgeW91ciBsaW5lIG9mIHRoaW5raW5nLgoKCiMgUGFydCBJSSBBdXRvbWF0ZSBTaGFycGUgcmF0aW8gY2FsY3VsYXRpb24gdXNpbmcgYSBsb29wCgpZb3UgaGF2ZSB0byB3cml0ZSBhIHByb2dyYW0gdG8gYXV0b21hdGljYWxseSBjYWxjdWxhdGUgdGhlIFNoYXJwZSByYXRpbyBmb3IgYWxsIHN0b2NrcyBpbiB0aGUgcmV0dXJucyBkYXRhc2V0LCBhbmQgdGhlbiBzZWxlY3QgdGhlIHRvcCA1IHN0b2NrcyB3aXRoIHRoZSBoaWdoZXN0IHNoYXJwZSByYXRpby4KWW91IGhhdmUgdG8gdXNlIHRoZSBzYW1lIGRhdGFzZXQgcmV0dXJucy5jc3YgdGhhdCBoYXMgcmVhbCBtb250aGx5IHJldHVybnMgb2Ygc2V2ZXJhbCBVUyBzdG9ja3MuIFJlbWVtYmVyIHRoYXQgdGhlIHN0b2NrcyBzdGFydCBpbiB0aGUgdGhpcmQgY29sdW1uIG9mIHRoaXMgZGF0YXNldC4KWW91ciBwcm9ncmFtIGhhcyB0byBkbyB0aGUgZm9sbG93aW5nOgphKSBDYWxjdWxhdGUgYW5kIHNhdmUgaW4gYSB2ZWN0b3Igb3IgbWF0cml4IGFsbCB0aGUgc2hhcnBlIHJhdGlvcy4gVXNlIHJpc2stZnJlZSByYXRlPTAuMDAxIGZvciBhbGwgc3RvY2tzLiBZb3UgaGF2ZSB0byB1c2UgYSBsb29wIGZvciB0aGlzIHBhcnQuCmIpIFNlbGVjdCB0aGUgdG9wIDUgc3RvY2tzIHdpdGggdGhlIGhpZ2hlc3QgU2hhcnBlIHJhdGlvLgpjKSAoZXh0cmEgMTAgcG9pbnRzKSBFc3RpbWF0ZSB0aGUgb3B0aW1hbCAodGFuZ2VudCkgcG9ydGZvbGlvIHdpdGggdGhlc2Ugc3RvY2tzIChhcyByaXNrLWZyZWUgcmF0ZSwgdXNlIHplcm8pClNwZWNpZmljYXRpb25zIG9mIHlvdXIgcHJvZ3JhbToKWW91IE9OTFkgaGF2ZSB0byBpbmNsdWRlIHRoZSBDT0RFIHlvdSBuZWVkIGZvciB0aGlzIHByb2dyYW0uIEV4dHJhIGNvZGUgd2lsbCBiZSBwZW5hbGl6ZWQuCllvdXIgcHJvZ3JhbSBNVVNUIFJVTiBhY2NvcmRpbmcgdG8gdGhlIGNvbnRlbnQgb2YgdGhlIGNzdiBmaWxlLiBGb3IgZXhhbXBsZSwgaWYgeW91IGRlbGV0ZSwgY2hhbmdlIGEgY29sdW1uIG9yIGFkZCBvbmUsIHlvdXIgcHJvZ3JhbSBzaG91bGQgcnVuIGNvbnNpZGVyIHRoaXMuCllvdSBNVVNUIERPQ1VNRU5UIHlvdXIgY29kZS4gWW91IGhhdmUgdG8gaW5jbHVkZSBhcyBjb21tZW50cyB0aGUgZm9sbG93aW5nIGRvY3VtZW50YXRpb246Ci0gQXQgdGhlIGJlZ2lubmluZyBvZiB5b3VyIGNvZGUsIHlvdSBoYXZlIHRvIHdyaXRlIHlvdXIgZ2VuZXJhbCBhcHByb2FjaCBvZiB5b3VyIHByb2dyYW0vZnVuY3Rpb24gaW5jbHVkaW5nIGlucHV0cywgc3RlcHMgYW5kIG91dHB1dAotIERvY3VtZW50IHlvdXIgbGluZXMgb2YgY29kZSwgc28gSSBjYW4gcmVhZCB5b3VyIGxpbmUgb2YgdGhpbmtpbmcuCllvdSBoYXZlIHRvIHN1Ym1pdCBhbiAuaHRtbCBGSUxFIHdpdGggYm90aCBwcm9ibGVtcy4gTmFtZSB5b3VyIGZpbGUgYXMgWW91ck5hbWVFeGFtMgoKCiMgUGFydCAxIC0gU29sdXRpb24KCkFTIEFMV0FZUywgVEhFU0UgVEVTVFMgQVJFIE1BREUgVE8gQ0hBTExFTkdFIFVTIFJFR0FSRElORyBPVVIgRklOQU5DSUFMIFBST0dSQU1NSU5HIEtOT1dMRURHRS4gV0UgQVJFIEdJVkVOIEEgREFUQVNFVCBTTyBOQVRVUkFMTFkgV0UnTEwgQkUgVVNJTkcgVEhBVCBGT1IgT1VSIEZVTkNUSU9OLiBGSVJTVCBUSElOR1MgRklSU1QsIFdFJ0xMIE5FRUQgVE8gRE9XTkxPQUQgU09NRSBQQUNLQUdFUyBJTiBPUkRFUiBUTyBET1dOTE9BRCBPVVIgREFUQS4KCmBgYHtyfQpsaWJyYXJ5KFBlcmZvcm1hbmNlQW5hbHl0aWNzKQpsaWJyYXJ5KHF1YW50bW9kKQpsaWJyYXJ5KGR5Z3JhcGhzKQpgYGAKCmBgYHtyfQptb250aGx5X3N0b2NrX3JldHVybnMgPC0gZnVuY3Rpb24odGlja2VyLCBzdGFydF95ZWFyKQogIGRvd25sb2FkLmZpbGUoImh0dHA6Ly93d3cuYXByYWRpZS5jb20vZnozMDMwL3JldHVybnMuY3N2IiwgInJldHVybnMuY3N2IikKcmV0dXJucy5jc3YgPC0gcmVhZC5jc3YoZmlsZT0icmV0dXJucy5jc3YiLCBoZWFkZXI9VFJVRSwgc2VwPSIsIikKYGBgCgpgYGB7cn0KIyBMZXRzIGNob29zZSB0aGUgc3RhcnRpbmcgeWVhciBmb3Igb3VyIGZ1bmN0aW9uCnllYXIgPC0gMjAxOAojIEFuZCB2aXN1YWxpemUgb3VyIG1vbnRobHkgcmV0dXJucwptb250aGx5X3N0b2NrX3JldHVybnMoJ0FBUEwnLCAyMDE4KQptb250aGx5X3N0b2NrX3JldHVybnMoJ0NFUk4nLCAyMDE4KQptb250aGx5X3N0b2NrX3JldHVybnMoJ1hPTScsIDIwMTgpCmBgYApgYGB7cn0KIyBDUkVBVElORyBPQkpFQ1RTIEZPUiBFQUNIIFNUT0NLIFJFVFVSTiBJTiBKYW51YXJ5IDIwMTgKQXBwbGVfUmV0dXJucyA8LSBtb250aGx5X3N0b2NrX3JldHVybnMoJ0FBUEwnLCAyMDE4KQpDZXJuZXJfUmV0dXJucyA8LSBtb250aGx5X3N0b2NrX3JldHVybnMoJ0NFUk4nLCAyMDE4KQpFeHhvbk1fUmV0dXJucyA8LSBtb250aGx5X3N0b2NrX3JldHVybnMoJ1hPTScsIDIwMTgpCmBgYApgYGB7cn0KIyBMZXRzIG1lcmdlIHRoZSByZXR1cm5zIHRvIGFzc2luZyB3ZWlnaHRzCm1lcmdlZF9yZXR1cm5zIDwtIG1lcmdlLmRlZmF1bHQoQXBwbGVfUmV0dXJucywgQ2VybmVyX1JldHVybnMsIEV4eG9uTV9SZXR1cm5zKQojIFBsb3R0aW5nIDIwMTgncyByZXR1cm5zCnBsb3QobWVyZ2VkX3JldHVybnMpCmBgYAoKYGBge3J9CiMgTk9XIFRIQVQgSSBIQVZFIFRIUkVFIFNUT0NLUyBNRVJHRUQgSU4gT05FIE9CSkVDVCwgTEVUIFVTIEFTU0lORyBXRUlHSFRTCncgPC0gYyguMjUsIC4yNSwgLjUwKQojIEFQTFlJTkcgRlVOQ1RJT04gUkVUVVJOIFBPUlRGT0xJTwpwb3J0Zm9saW9fbW9udGhseV9yZXR1cm5zIDwtIFJldHVybi5wb3J0Zm9saW8obWVyZ2VkX3JldHVybnMsIHdlaWdodHMgPSB3KQpgYGAKCmBgYHtyfQojIE9idGFpbmluZyB0aGUgU3RhbmRhcmQgRGV2aWF0aW9uCnNkKG1lcmdlZF9yZXR1cm5zKQpgYGAKYGBge3J9ClNoYXJwZVJhdGlvKEZVTiA9IFN0ZERldigwLjU3NzM1MDMpKQpgYGAKCgojIFBhcnQgMiAtIFNvbHV0aW9uCgpGb3IgdGhpcyBsb29wIHdlbGwgYmUgdXNpbmcgdGhlIG9iamVjdHMgYW5kIGRhdGEgY3JlYXRlZCBwcmV2aW91c2x5IGluIG9yZGVyIHRvIG1ha2UgYSBsb29wIHRoYXQgY2FsY3VsYXRlcyB0aGUgZGVzaXJlZCBpbmZvcm1hdGlvbi4KCmBgYHtyfQpyZXR1cm5zX2VxdWl0aWVzIDwtIFJldHVybi5leGNlc3MoZXFfcHJpY2VzKQpyZXR1cm5zX2JvbmRzIDwtIFJldHVybi5wb3J0Zm9saW8oYm9uZF9wcmljZXMpCiMgTWFraW5nIGEgZ3JpZApncmlkIDwtIHNlcShmcm9tID0gMCwgdG8gPSAxLCBieSA9IDAuMDEpCgojIEVtcHR5IHZlY3RvciBmb3IgU2hhcnBlIFJhdGlvcwp2c2hhcnBlIDwtIHJlcChOQSwgdGltZXMgPSBsZW5ndGgoZ3JpZCkpCgojIExvb3AgdG8gY2FsY3VsYXRlIHNoYXJwZSByYXRpb3MKZm9yKGkgaW4gMTpsZW5ndGgoZ3JpZCkpIHsKICAgIHdlaWdodCA8LSBncmlkW2ldCiAgICBwcmV0dXJucyA8LSB3ZWlnaHQgKiByZXR1cm5zX2VxdWl0aWVzICsgKDEgLSB3ZWlnaHQpICogcmV0dXJuc19ib25kcwogICAgdnNoYXJwZVtpXSA8LSBTaGFycGVSYXRpby5hbm51YWxpemVkKHByZXR1cm5zKQp9CgojIFBsb3QgdGhlIHdlaWdodHMgYW5kIFNoYXJwZQpwbG90KGdyaWQsIHZzaGFycGUsIHhsYWIgPSAiV2VpZ2h0cyIsIHlsYWI9ICJBbm4uIFNoYXJwZSByYXRpbyIpCmFibGluZSh2ID0gZ3JpZFt2c2hhcnBlID09IG1heCh2c2hhcnBlKV0sIGx0eSA9IDMpCmBgYAoK