[英]How to generalize this algorithm (sign pattern match counter)?
我在R中有以下代码:
corr = function(x, y) {
sx = sign(x)
sy = sign(y)
cond_a = sx == sy && sx > 0 && sy >0
cond_b = sx < sy && sx < 0 && sy >0
cond_c = sx > sy && sx > 0 && sy <0
cond_d = sx == sy && sx < 0 && sy < 0
cond_e = sx == 0 || sy == 0
if(cond_a) return('a')
else if(cond_b) return('b')
else if(cond_c) return('c')
else if(cond_d) return('d')
else if(cond_e) return('e')
}
它的作用是与R中的mapply
函数结合使用,以便计算时间序列中存在的所有可能的符号模式。 在这种情况下,模式的长度为2,所有可能的元组为: (+,+)(+,-)(-,+)(-,-)
我以这种方式使用corr
函数:
> with(dt['AAPL'], table(mapply(corr, Return[-1], Return[-length(Return)])) /length(Return)*100)
a b c d e
24.6129416 25.4466058 25.4863041 24.0174672 0.3969829
> dt["AAPL",list(date, Return)]
symbol date Return
1: AAPL 2014-08-29 -0.3499903
2: AAPL 2014-08-28 0.6496702
3: AAPL 2014-08-27 1.0987923
4: AAPL 2014-08-26 -0.5235654
5: AAPL 2014-08-25 -0.2456037
我想将corr
函数概括为n
参数。 这意味着对于每个n
我将必须写下与所有可能的n元组相对应的所有条件。 目前,我能想到的最好的方法是使python脚本使用循环来编写代码字符串,但是必须有一种正确执行此操作的方法。 您是否对如何概括条件性条件编写有一个想法,也许我可以尝试使用expand.grid
但是如何进行匹配呢?
这是一种稍微不同的方法,但是它可以为您提供所需的内容,并允许您使用任意大小的n元组。 基本方法是为每个连续的n个返回集找到相邻变化的符号,将n长度的符号变化转换为1和0的n个元组,其中0 =负返回而1 =正返回。 然后计算每个n元组的十进制值作为二进制数。 对于每个不同的n元组,这些数字将明显不同。 使用Zoo时间序列进行这些计算可提供几个有用的函数,包括get.hist.quote()检索股票价格,diff()计算收益,以及rollapply()函数用于计算n元组及其和。下面的代码进行这些计算,将符号变化的总和转换回二进制n位元组,并将结果收集到一个数据帧中。
library(zoo)
library(tseries)
n <- 3 # set size of n-tuple
#
# get stock prices and compute % returns
#
dtz <- get.hist.quote("AAPL","2014-01-01","2014-10-01", quote="Close")
dtz <- merge(dtz, (diff(dtz, arithmetic=FALSE ) - 1)*100)
names(dtz) <- c("prices","returns")
#
# calculate the sum of the sign changes
#
dtz <- merge(dtz, rollapply( data=(sign(dtz$returns)+1)/2, width=n,
FUN=function(x, y) sum(x*y), y = 2^(0:(n-1)), align="right" ))
dtz <- fortify.zoo(dtz)
names(dtz) <- c("date","prices","returns", "sum_sgn_chg")
#
# convert the sum of the sign changes back to an n-tuple of binary digits
#
for( i in 1:nrow(dtz) )
dtz$sign_chg[i] <- paste(((as.numeric(dtz$sum_sgn_chg[i]) %/%(2^(0:2))) %%2), collapse="")
#
# report first part of result
#
head(dtz, 10)
#
# report count of changes by month and type
#
table(format(dtz$date,"%Y %m"), dtz$sign_chg)
可能的输出示例是一个表格,该表格显示了每个月按类型进行的更改计数。
000 001 010 011 100 101 110 111 NANANA
2014 01 1 3 3 2 3 2 2 2 3
2014 02 1 2 4 2 2 3 2 3 0
2014 03 2 3 0 4 4 1 4 3 0
2014 04 2 3 2 3 3 2 3 3 0
2014 05 2 2 1 3 1 2 3 7 0
2014 06 3 4 3 2 4 1 1 3 0
2014 07 2 1 2 4 2 5 5 1 0
2014 08 2 2 1 3 1 2 2 8 0
2014 09 0 4 2 3 4 2 4 2 0
2014 10 0 0 1 0 0 0 0 0 0
因此,这表明在2014年1月1日中,存在一组三天,其中000表示3个下降收益,3天001的变化表示两个下降收益,然后是一个正收益,依此类推。 大多数月份似乎都具有相当随机的分布,但是5月和8月显示了3天正回报的7套和8套,这反映了AAPL的强劲月份。
我认为您最好在zoo
软件包中使用rollapply(...)
。 由于您似乎quantmod
使用quantmod
(加载xts
和zoo
),因此这里的解决方案不使用所有嵌套的if(...)
语句。
library(quantmod)
AAPL <- getSymbols("AAPL",auto.assign=FALSE)
AAPL <- AAPL["2007-08::2009-03"] # AAPL during the crash...
Returns <- dailyReturn(AAPL)
get.patterns <- function(ret,n) {
f <- function(x) { # identifies which row of `patterns` matches sign(x)
which(apply(patterns,1,function(row)all(row==sign(x))))
}
returns <- na.omit(ret)
patterns <- expand.grid(rep(list(c(-1,1)),n))
labels <- apply(patterns,1,function(row) paste0("(",paste(row,collapse=","),")"))
result <- rollapply(returns,width=n,f,align="left")
data.frame(100*table(labels[result])/(length(returns)-(n-1)))
}
get.patterns(Returns,n=2)
# Var1 Freq
# 1 (-1,-1) 22.67303
# 2 (-1,1) 26.49165
# 3 (1,-1) 26.73031
# 4 (1,1) 23.15036
get.patterns(Returns,n=3)
# Var1 Freq
# 1 (-1,-1,-1) 9.090909
# 2 (-1,-1,1) 13.397129
# 3 (-1,1,-1) 14.593301
# 4 (-1,1,1) 11.722488
# 5 (1,-1,-1) 13.636364
# 6 (1,-1,1) 13.157895
# 7 (1,1,-1) 12.200957
# 8 (1,1,1) 10.765550
基本思想是创建具有2^n
行和n列的patterns
矩阵,其中每一行代表一种可能的模式(例如,(1,1),(-1,1)等)。 然后使用rollapply(...)
将每日收益率n传递给该函数,并确定patterns
中的哪一行与sign(x)
完全匹配。 然后使用该行号向量和一个labels
索引,该索引包含模式的字符表示,然后像您一样使用table(...)
。
这是n天模式的常规设置,但它忽略了任何收益恰好为零的情况,因此$Freq
列的$Freq
不$Freq
100。如您所见,这种情况很少发生。
有趣的是,即使在坠机事故中,连续两个工作日(而不是两个休息日)的可能性(非常小)。 如果在此期间查看plot(Cl(AAPL))
,您会发现这是一个非常疯狂的旅程。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.