2015-11-11 50 views
2

这是我在编程方面的第一篇文章,所以我很抱歉如果我没有使用正确的术语或发布在正确的位置。我对使用r非常陌生,并且一般来说对编程不熟悉(除了一点VBA)。我写了一个基本函数,用于计算从最新价格到最旧价格列出的股票价格列表的每日价格回报。我认为我的代码有点sl and,我可以用一些帮助清理它。我创建“returnarray”的目的是让我可以将循环结果存储到一个变量中,而不仅仅是打印。有人可以帮我清理我的r功能吗?

我真的很想在这里做的一件事是消除对“returnarray”的需求,而是希望将结果保存到用户输入的任何内容中。例如,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 
    } 

} 
+0

@ G.Grothendieck,作为回答发布......? –

回答

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. 最主要的是使用()返回到在的端返回一个值函数 - 这会阻止你需要创建returnarray()。
  2. 我不认为你需要初始化你的变量,尽管肯定没有伤害,并且这可能是一个好习惯。
+0

这工作就像一个魅力!谢谢! – purealpha

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是0.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,PerformanceAna lytics和quantmod软件包。更多详情请参阅Empirical Finance Task View

0

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

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

好,欢迎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-loops通常是你想要使用的最后一件事。随着数据集越来越大,您的代码将呈指数级下降。

相关问题