Reputation:
This is my first ever post in regards to programming, so I apologize if am not using the proper terminology or posting in the right spot. I am extremely new to using r, and new to programming in general(except for a little VBA). I wrote a basic function that calculates the daily price return of a list of stock prices that are listed from newest price to oldest price. I think my code is a little sloppy and I could use some help cleaning it up. My purpose of creating "returnarray" was so that I could have the loop results stored to a variable instead of just printing.
One thing I would really like to do here is eliminate the need for "returnarray" and would instead like to have the results saved to whatever the user inputs. For example myreturns <- price.return(mydata)
would yield a variable named myreturns, containing all of the returns, instead of creating returnarray. Find my code below, and thank you in advance.
price.return <- function(mydata)
{
returnarray <- c()
tmp <- c()
for (i in 1:length(mydata)-1)
{
tmp <- (((mydata[i]/mydata[i+1])-1))
returnarray <- c(returnarray,tmp)
returnarray <<- returnarray
}
}
Upvotes: 2
Views: 109
Reputation: 269774
Transferred from comments.
1) The function shown in the question does this:
price.return1 <- function(x) x[-length(x)] / x[-1] - 1 # similar to question
2) Index increasing in time It seems that the question is assuming that x[1]
is the most recent point and x[length(x)]
is the oldest point whereas the normal convention is that x[1]
is the oldest point and x[length(n)]
is the most recent, i.e. normally it is assumed that the index is increasing in time, so using this more usual convention it would be written like this:
price.return2 <- function(x) x[-1] / x[-length(x)] - 1 # assume index increasing in time
Example: To illustrate price.return2
with an example, suppose the prices are increasing 1, 2, 3, 4, 5 over time. Then we can write:
price.return2(1:5)
## [1] 1.0000000 0.5000000 0.3333333 0.2500000
so the return from 1 to 2 is 1 or 100%, the return from 2 to 3 is .5 or 50% and so on.
3) Same An alternate way to write it that is equivalent to price.return2
is:
price.return3 <- function(x) exp(diff(log(x))) - 1 # similar to price.return2
We can verify that price.return2
and price.return3
give similar answers for the input 1:5
like this:
all.equal(price.return2(1:5), price.return3(1:5))
## [1] TRUE
Note: that you might be interested in some of the functions in the zoo, xts, PerformanceAnalytics and quantmod packages. For even more see the Empirical Finance Task View .
Upvotes: 6
Reputation: 1361
One thing you should start getting used to is vectorization. The essence of R programming is using already built functions that are vectorized to help you out. For-looping in R isn't always the best choice especially if you can use vectors.
Also, you generally should provide data that can be easily replicated so that others can compare their results with you.
Well, welcome to R and here is a more efficient solution:
### always have replicable data at the beginning of your question
### this allows answers to verify that they are indeed doing what you want them to do
data <- data.frame(c(120.663499,122.047573,121.480003,
120.919998,121.059998,120.57,116.769997))
rownames(data) <- rev(seq(as.Date("2015/11/05"),as.Date("2015/11/11"),"days"))
colnames(data) <- "AAPL"
> data
AAPL
2015-11-11 120.6635
2015-11-10 122.0476
2015-11-09 121.4800
2015-11-08 120.9200
2015-11-07 121.0600
2015-11-06 120.5700
2015-11-05 116.7700
### since your data is from newest to oldest, I have to switch them to oldest to newest
### this is the common convention used in finance. Also, packages like quantmod do this
### you can collect price data very quickly using quantmod
### its important to use rownames(data) that way the associated date stays with the price
data <- data[rev(rownames(data)),,drop=F]
> data
AAPL
2015-11-05 116.7700
2015-11-06 120.5700
2015-11-07 121.0600
2015-11-08 120.9200
2015-11-09 121.4800
2015-11-10 122.0476
2015-11-11 120.6635
### we use the vectorized diff() function to calculate the difference between
### each consecutive price (Pt - Pt-1)
### we then divide that difference by the previous period's price
### in notation: (Pt-Pt-1)/Pt-1
res <- diff(data$AAPL)/data$AAPL[-length(data$AAPL)]
### Now I am just putting this in the data frame to show you how it might look
### in something in excel
res <- data.frame(data,"Returns"=c(NA,res))
I hope this helps. And if you are looking to continue to do this kind of work in R with financial prices, I strongly suggest learning to code in a fashion similar to this. Vectorization is super important. For-loops are generally the last thing you want to use. As data sets get bigger, your code gets exponentially slower.
Upvotes: 0
Reputation: 624
Someone may provide a cleaner solution, but hopefully this is at least a bit useful:
price.return <- function(mydata) {
for (i in 1:length(mydata)-1) {
mydata[i] <- mydata[i] / mydata[i+1] - 1
}
return(mydata[1:(length(mydata) - 1)])
}
Upvotes: 1