我正在运行一个脚本,从雅虎财经下载股票价格,然后计算其价格变化的对数,前20天的标准差,将第i个价格乘以第i个标准差,然后除以当前的价格变化按前一天的价格变动或i-1。
我到处都是循环,这是第一个红旗,因为有更好的方法在R中做事。我很乐意尽可能使用矢量化操作。
我在R中定义一个空数据框以包含我想要的信息。我读到这是一个坏主意。我知道数据框有多大,因为我知道我要下载价格的符号数量。但是,当我初始化数据框时,它只是填充用0指定的行数并添加我想要的数据。通过在事实之后删除行来简单地修复它很容易,但我确信有一种更清洁的方式。
以下代码会产生错误:
1: In `[<-.factor`(`*tmp*`, ri, value = "IBM") :
invalid factor level, NA generated.
如果我在初始化SpikeData时将0更改为1,它将填充正常,但我需要删除在脚本的第3行到最后一行完成的空白第一行。
我遇到的第二个问题是SpikeRank数据框中的列名。我希望第一列标题为“符号”,接下来的5列为日期。但是,我似乎无法混合搭配。如果我将第一个col名称设置为“Symbol”,则日期将转换为序列号。使用此脚本,我将添加其他具有字符的列,因此我希望能够混合和匹配列名称中的日期和字符。
GetVol <- function(Window = 20, end=as.Date(Sys.time()), start = end-37){
library(tseries)
library(zoo)
SpikeRank = data.frame(stringsAsFactors=FALSE, Symbol=character(0),
SDInPriceTerms1=numeric(0), SDInPriceTerms2=numeric(0),
SDInPriceTerms3=numeric(0), SDInPriceTerms4=numeric(0),
SDInPriceTerms5=numeric(0))
SymbolList <- c("AAPL", "IBM")
for (Symbol in SymbolList)
{
ts <- get.hist.quote(instrument=Symbol,
start, end,
quote="Close", provider="yahoo", origin="1970-01-01",
compression="d", retclass="zoo")
df <- data.frame(ts)
df <- data.frame(Date=as.Date(rownames(df)), Close=df$Close)
df$PriorClose <- c(NA, head(df$Close, -1))
df$Return <- log(df$Close/df$PriorClose)
for (i in 1:length(df$Close))
{
if(i < Window+1)
{
df$stddev[i] = NA
df$SDPrice[i] = NA
df$CurrentSpike[i] = NA
}
else
{
df$stddev[i] <- sd(df$Return[(i-Window+1):i], na.rm = TRUE)
df$SDPrice[i] <- df$stddev[i] * df$Close[i]
df$CurrentSpike[i] <- (df$Close[i] - df$PriorClose[i])/df$SDPrice[i-1]
}
}#end for
df <- na.omit(df)
SpikeRank <- rbind(SpikeRank, c(Symbol, df$CurrentSpike))
}#end for loop
SpikeRank <- SpikeRank[-1,]
colnames(SpikeRank) <- c(as.Date(1), df$Date)
print(SpikeRank)
)
SpikeRank的打印假设数据帧初始化为1s而不是0s,如下所示。行中的值都是正确的。我对计算没有任何问题。
1970-01-02 2014-03-03 2014-03-04 2014-03-05 2014-03-06
2 AAPL 0.268505943103897 0.613087867831883 0.195414096323545 -0.289567687725125
3 IBM -0.600147413085885 1.43686920161242 0.592564096496001 0.426680866502713
2014-03-07
2 -0.055981998552076
3 0.0344269384370513
如果有帮助,这是IBM的df:
Date Close PriorClose Return stddev SDPrice CurrentSpike
1 2014-01-30 177.36 NA NA NA NA NA
2 2014-01-31 176.68 177.36 -0.0038413786 NA NA NA
3 2014-02-03 172.90 176.68 -0.0216267940 NA NA NA
4 2014-02-04 172.84 172.90 -0.0003470816 NA NA NA
5 2014-02-05 174.24 172.84 0.0080673481 NA NA NA
6 2014-02-06 174.67 174.24 0.0024648203 NA NA NA
7 2014-02-07 177.25 174.67 0.0146626860 NA NA NA
8 2014-02-10 177.14 177.25 -0.0006207850 NA NA NA
9 2014-02-11 179.70 177.14 0.0143484134 NA NA NA
10 2014-02-12 180.24 179.70 0.0030005023 NA NA NA
11 2014-02-13 181.84 180.24 0.0088378834 NA NA NA
12 2014-02-14 183.69 181.84 0.0101223746 NA NA NA
13 2014-02-18 183.19 183.69 -0.0027256886 NA NA NA
14 2014-02-19 182.95 183.19 -0.0013109741 NA NA NA
15 2014-02-20 184.26 182.95 0.0071349122 NA NA NA
16 2014-02-21 182.79 184.26 -0.0080098508 NA NA NA
17 2014-02-24 183.45 182.79 0.0036041979 NA NA NA
18 2014-02-25 183.23 183.45 -0.0011999565 NA NA NA
19 2014-02-26 184.06 183.23 0.0045195971 NA NA NA
20 2014-02-27 185.27 184.06 0.0065524292 NA NA NA
21 2014-02-28 185.17 185.27 -0.0005398985 0.008188660 1.516294 NA
22 2014-03-03 184.26 185.17 -0.0049265184 0.008233949 1.517188 -0.60014741
23 2014-03-04 186.44 184.26 0.0117616678 0.006336123 1.181307 1.43686920
24 2014-03-05 187.14 186.44 0.0037475283 0.006261815 1.171836 0.59256410
25 2014-03-06 187.64 187.14 0.0026682336 0.006192074 1.161881 0.42668087
26 2014-03-07 187.68 187.64 0.0002131514 0.006236115 1.170394 0.03442694
感谢您的帮助。
答案 0 :(得分:1)
首先,您的代码不会按照提供的方式运行。这是因为您无需定义start
,end
或Window
。所以我不得不从你的df
推断IBM的那些值。 (顺便说一句:这可能就是为什么其他人都不愿意回应。对SO的期望是,如果你需要帮助,你将提供一个工作的例子)。
所以这是制作你所拥有的更短的方式。请注意使用rollapply(...)
和head(...)
来避免内部循环,并使用do.call(rbind,lapply(...))
来避免外部循环和SpikeRank
的预分配。您坚持将日期作为列名创建了许多问题,因为在大多数创建数据框的函数中的默认行为是避免以数字开头的列名。
library(tseries) # for get.hist.quote
library(zoo) # for rollapply
start <- "2014-01-30"
end <- "2014-03-07"
Window <- 20
SymbolList <- c("AAPL","IBM")
get.SpikeRank <- function(Symbol,start, end, Window) {
ts <- get.hist.quote(instrument=Symbol,
start, end,
quote="Close", provider="yahoo", origin="1970-01-01",
compression="d", retclass="zoo")
df <- data.frame(ts)
df <- data.frame(Date=as.Date(rownames(df)), Close=df$Close)
df$PriorClose <- c(NA, head(df$Close, -1))
df$Return <- log(df$Close/df$PriorClose)
df$stdev <- c(rep(NA,Window),rollapply(df$Return[-1],width=Window,sd,na.rm=T))
df$SDPrice <- df$stdev * df$Close
df$CurrentSpike <- (df$Close - df$PriorClose)/c(NA,head(df$SDPrice,-1))
df <- na.omit(df)
row <- df$CurrentSpike
names(row) <- df$Date
return(row)
}
SpikeRank <- do.call(rbind,lapply(SymbolList,get.SpikeRank,start,end,Window))
SpikeRank <- data.frame(Symbol=SymbolList, SpikeRank)
colnames(SpikeRank)[-1] <- substring(colnames(SpikeRank)[-1],2)
print(SpikeRank)
# Symbol 2014.03.03 2014.03.04 2014.03.05 2014.03.06 2014.03.07
# 1 AAPL 0.2685059 0.6130879 0.1954141 -0.2895677 -0.05598200
# 2 IBM -0.6001474 1.4368692 0.5925641 0.4266809 0.03442694