【发布时间】:2017-10-17 18:39:48
【问题描述】:
好的,我有一个循环来计算股票价格系列的年化/累积回报。
我希望对许多文件做同样的事情。所以做了一个循环来这样做。
首先是一些虚拟数据:
# Create dummy data
# Use lubridate to change timestamp to date format
# Use dplyr to arrange by ascending order
# Use fread from data.table to read .csv to data frame
require(lubridate)
require(data.table)
require(dplyr)
MSFT <- fread("https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=MSFT&outputsize=full&apikey=6RSYX9BPXKZVXUS9&datatype=csv")
MSFT$timestamp <- ymd(MSFT$timestamp)
MSFT <- arrange(MSFT,timestamp)
AAPL <- fread("https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=AAPL&outputsize=full&apikey=6RSYX9BPXKZVXUS9&datatype=csv")
AAPL$timestamp <- ymd(AAPL$timestamp)
AAPL <- arrange(AAPL,timestamp)
NFLX <- fread("https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=NFLX&outputsize=full&apikey=6RSYX9BPXKZVXUS9&datatype=csv")
NFLX$timestamp <- ymd(NFLX$timestamp)
NFLX <- arrange(NFLX,timestamp)
TSLA <- fread("https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=TSLA&outputsize=full&apikey=6RSYX9BPXKZVXUS9&datatype=csv")
TSLA$timestamp <- ymd(TSLA$timestamp)
TSLA <- arrange(TSLA,timestamp)
# Place data frames in a list
df.list <- list(MSFT,AAPL,NFLX,TSLA)
# Specify file names
file.names <- c("MSFT","AAPL","NFLX","TSLA")
现在准备数据。
接下来我要计算每个系列的累计和年化回报。我将它放在一个函数中,然后用循环调用该函数:
# Create function for performing commands.
genAnnualized = function(x){
next.file <- data.frame(df.list[[1]],stringsAsFactors=FALSE)
next.name <- paste0(file.names[i])
new.df <- data.frame(next.file)
# Calculate annualized return
# Make prices vector
prices <- new.df[, "close", drop = FALSE]
# Denote n the number of time periods:
n <- nrow(prices)
# Calculate close to close returns
# lead in with rep,NA,1 to maintain length of vector comparible to data frame
close_ret <- c(rep(NA, 1),(prices[2:n, 1] - prices[1:(n-1), 1])/prices[1:(n-1), 1])
close_ret[1] <- 0
# Compute continuously returns (log returns)
close_ccret <- log(prices[2:n, 1]) - log(prices[1:(n-1), 1])
# Compute gross returns
close_gret <- 1 + close_ret # use close to close ret
# Compute future values
close_fv <- cumprod(close_gret)
# Obtain first and last values
ret.last <- tail(close_fv, n=1)
ret.first <- head(close_fv, n=1)
cum.ret <- (ret.last-ret.first)/ret.first
# Get First And Last row to calculate time between
ret.first.row <- head(new.df$timestamp, n=1)
ret.last.row <- tail(new.df$timestamp, n=1)
# Time diff
#trading.years.between <- as.numeric(difftime(as.Date(ret.last.row), as.Date(ret.first.row), unit="weeks"))/52.25
# Find time diff
ret.time <- ret.last.row - ret.first.row
ret.trading.years.between <- ret.time/365 #252 trading days or 365
ret.trading.years.between <- as.numeric(ret.trading.years.between, units="days") # Extract numerical value from time difference 'Time difference of 2837.208 days'
# Annualized return
# (1 + % diff of final) / (last balance to the power of 1/time first and last balance) -1
ret.annual.return <- (1+cum.ret) ^ (1/ret.trading.years.between) -1
########## Store annualized and cumulative return in data frame for each iteration #########
# Store file name as a row name :: next.name variable
# Store final annualized return :: cret.annual.return
# Store final cumulative return :: cum.ret
output.df <- cbind(cum.ret,ret.annual.return)
rownames(output.df) <- next.name
##################################################################
# Sanity check, use PerformanceAnalytics for annualized return
# TTR for returns
# Calculate Close-to-Close returns
require(TTR)
require(PerformanceAnalytics)
new.df$clret <- ROC(new.df$close, type = c("discrete"))
new.df$clret[1] <- 0
# Make time series object of returns and date
require(xts)
xts1 = xts(new.df$clret, order.by=as.Date(new.df$timestamp, format="%m/%d/%Y"))
Return.annualized(xts1)
Return.cumulative(xts1, geometric=TRUE)
}
并调用函数循环遍历数据框列表中的每个数据框:
for (i in 1:length(df.list)){
tryCatch({
genAnnualized(df.list[[i]])
}, error = function(e) { print(paste("i =", i, "failed:")) })
}
这应该是一个可重现的例子。
在每次迭代中,我希望将每个系列的累积和年化收益与数据集的名称一起存储(以便以后识别)。 我在我的函数中尝试使用以下内容:
output.df <- cbind(cum.ret,ret.annual.return)
rownames(output.df) <- next.name
我正在指定名称:
file.names <- c("MSFT","AAPL","NFLX","TSLA")
然后在调用它的函数中:
next.name <- paste0(file.names[i])
我希望粘贴文件名,以便在数据框中标记我的最终输出。
我认为在命名每行或列名时可能需要重复两次。这样它就可以标记累积回报和年化回报。
我认为有一个大致的想法,但已经为此苦苦挣扎了几个星期,因此寻求一些帮助。
基本上使用输出数据框,然后我可以将其组织成四分位数等以进行进一步分析
【问题讨论】:
-
我总是通过将值分配给循环内的数据框或列表来处理这些情况,即 alist[]
-
您在函数的第一行有一个硬编码的
df.list[[1]]- 这似乎不正确。此外,您的函数应该return()一些东西 - 现在它正在返回Return.cumulative(xts1, geometric=TRUE),但Return.annualized(xts1)已计算但未使用或返回。 -
我建议编写你的函数,这样它就需要一个数据框和一个名称作为参数,并在没有“意识到”它在循环内的情况下对它们进行操作 - 没有对
i的引用或函数内的df.list。然后你可以,正如 CCurtis 建议的那样,做类似results = list(); for (i in seq_along(df_list)) results[[i]] = genAnnualized(dat = df.list[[i]], name = file.names[i]) -
是的,我改成了 df.list[[i]] 来完成这项工作。阅读 return() 并看看它现在是如何工作的!