有人可以帮我清理我的功能吗?

时间:2015-11-11 23:21:28

标签: r

这是我关于编程的第一篇文章,所以如果我没有使用正确的术语或在正确的位置发布,我会道歉。我对使用r非常陌生,而且对编程很新(除了一点点VBA)。我写了一个基本函数,用于计算从最新价格到最早价格列出的股票价格列表的每日价格回报。我认为我的代码有点草率,我可以使用一些帮助来清理它。我的目的是创造" returnarray"是这样我可以将循环结果存储到变量而不是仅仅打印。

我真的想在这里做的一件事就是不再需要&#34; returnarray&#34;并希望将结果保存到用户输入的任何内容中。例如,myreturns <- price.return(mydata)将生成一个名为myreturns的变量,其中包含所有返回值,而不是创建returnarray。在下面找到我的代码,并提前感谢您。

    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
  }

}

3 个答案:

答案 0 :(得分:6)

从评论中转移。

1)问题中显示的功能是:

price.return1 <- function(x) x[-length(x)] / x[-1] - 1  # similar to question

2)索引在时间上增加似乎问题是假设x[1]是最近的点而x[length(x)]是最旧的点,而正常的约定是x[1]是最旧的点,x[length(n)]是最新的,即通常假设索引在时间上增加,所以使用这个更常见的约定,它将被写成:

price.return2 <- function(x) x[-1] / x[-length(x)] - 1 # assume index increasing in time

示例:为了举例说明price.return2,假设价格随时间增加1,2,3,4,5。然后我们可以写:

price.return2(1:5)
## [1] 1.0000000 0.5000000 0.3333333 0.2500000

所以从1到2的回报是1或100%,从2到3的回报是.5或50%,依此类推。

3)相同写一个等同于price.return2的替代方法是:

price.return3 <- function(x) exp(diff(log(x))) - 1  # similar to price.return2

我们可以验证price.return2price.return3是否为输入1:5提供了类似的答案:

all.equal(price.return2(1:5), price.return3(1:5))
## [1] TRUE

注意:您可能对动物园,xts,PerformanceAnalytics和quantmod包中的某些功能感兴趣。有关更多信息,请参阅Empirical Finance Task View

答案 1 :(得分:1)

有人可能提供更清洁的解决方案,但希望这至少有点用处:

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)])
}
  1. 主要是使用return()在函数末尾返回一个值 - 这将阻止你需要创建returnarray()。
  2. 我认为你不需要初始化你的变量,虽然它确实没有坏处,这可能是一种很好的做法。

答案 2 :(得分:0)

你应该开始习惯的一件事是矢量化。 R编程的本质是使用已经构建的函数来进行矢量化以帮助您。 R中的for循环并不总是最佳选择,特别是如果你可以使用向量。

此外,您通常应该提供可以轻松复制的数据,以便其他人可以将您的结果与您进行比较。

好的,欢迎来到R,这是一个更有效的解决方案:

### 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))

我希望这会有所帮助。如果你想继续在R中用金融价格做这种工作,我强烈建议你学习以类似的方式编写代码。矢量化非常重要。 For循环通常是您想要使用的最后一件事。随着数据集越来越大,代码的速度会呈指数级增长。

相关问题