Jur*_*ura 0 if-statement r function
我正在尝试创建一个创建索引的函数(从100开始),然后根据投资结果调整此索引.因此,简而言之,如果第一笔投资的利润为5%,那么指数将为105,如果第二个结果是-7%,则指数为97.65.在这个问题中,当我使用"索引"这个词时,我并不是指包的index功能zoo.
除了创建这个索引之外,我的目标还是创建一个可以应用于我的完整数据集的各种子集的函数(即使用sapply它和它的朋友).
这是我到目前为止的功能(此问题末尾的数据):
CalculateIndex <- function(x){
totalAccount <- accountValueStart
if(x$TradeResult.Currency == head(x$TradeResult.Currency., n = 1)){
indexedValues <- 100 + ( 100 *((((x$Size.Units. * x$EntryPrice) / totalAccount) * x$TradeResult.Percent.) / 100))
# Update the accountvalue
totalAccount <- totalAccount + x$TradeResult.Currency.
}
else{ # the value is not the first
indexedValues <- c(indexedValues,
indexedValues[-1] + (indexedValues[-1] *(((x$Size.Units. * x$EntryPrice) / totalAccount) * x$TradeResult.Percent.) / 100)
)
# Update the accountvalue
totalAccount <- totalAccount + x$TradeResult.Currency.
}
return(indexedValues)
}
Run Code Online (Sandbox Code Playgroud)
在函数中,函数执行(读取:用于执行)以下操作:
如果值是第一个,则100用作索引的起点.如果该值不是第一个,则使用先前计算的索引值作为计算新索引值的起点.除此之外,该功能还考虑了个体结果的权重(与totalAccount值相比).
问题:CalculateIndex在theData数据框上
使用此功能会产生以下错误输出:
> CalculateIndex(theData)
[1] 99.97901 99.94180 99.65632 101.88689 100.89309 98.92878 102.02911 100.49159 98.52955 102.02243 98.43655 100.76502 99.34869 100.76401 101.18014 99.75136 97.90130
[18] 100.39935 99.81311 101.34961
Warning message:
In if (x$TradeResult.Currency == head(x$TradeResult.Currency., n = 1)) { :
the condition has length > 1 and only the first element will be used
Run Code Online (Sandbox Code Playgroud)
编辑: 哇,我已经投了票,但我认为我的问题已经太长了.对不起,我认为/我认为这个问题存在于我的循环中,所以我不想让你厌烦细节,我认为这只会给出较少的答案.对不起,我的错误判断.
问题是,从上面的输出CalculateIndex结果来看,结果与Excel有很大的不同.即使这可能是由于舍入误差造成的(正如Joris在下面提到的那样),我对此表示怀疑.与Excel结果相比,R结果差异很大:
R output Excel calculate values
99,9790085700 99,97900857
99,9418035700 99,92081189
99,6563228600 99,57713687
101,8868850000 101,4639947
100,8930864300 102,3570786
98,9287771400 101,2858564
102,0291071400 103,3149664
100,4915864300 103,806556
98,5295542900 102,3361186
102,0224285700 104,3585552
98,4365550000 102,795089
100,7650171400 103,5601228
99,3486857100 102,9087897
100,7640057100 103,6728077
101,1801400000 104,8529634
99,7513600000 104,6043164
97,9013000000 102,5055298
100,3993485700 102,9048999
99,8131085700 102,7179995
101,3496071400 104,0676555
Run Code Online (Sandbox Code Playgroud)
我认为可以公平地说,输出的差异不是R与Excel问题的结果,而是我的函数中的错误.所以,让我们关注这个功能.
手动计算函数 函数使用不同的变量:
Size.Units.; 这是购买的单位数量EntryPrice.EntryPrice:股票买入的价格,TradeResult.Percent.:投资产生的收益或损失百分比,TradeResult.Currency.:投资产生的收益或损失的货币价值($),这些变量用于函数的以下部分:
100 + ( 100 *((((x$Size.Units. * x$EntryPrice) / totalAccount) * x$TradeResult.Percent.) / 100))
Run Code Online (Sandbox Code Playgroud)
和
indexedValues[-1] + (indexedValues[-1] *(((x$Size.Units. * x$EntryPrice) / totalAccount) * x$TradeResult.Percent.) / 100)
Run Code Online (Sandbox Code Playgroud)
这两个公式基本相同,区别在于第一个公式从100第二个开始,第二个使用previous value计算新索引值.
公式可以分为不同的步骤:
首先,x$Size.Units. * x$EntryPrice确定所采取的总头寸,即以48.98的价格买入100股的位置为4898美元.
然后将得到的总位置除以总账户大小(即totalAccount).这需要纠正一个职位相对于整个投资组合的影响.例如,如果我们的100股以48.98的价格下跌10%,则计算的指数(即CalculateIndex函数)不必下跌10%,因为当然并非所有资金totalAccount都投入到一只股票中.因此,通过将总持仓由totalAccount我们得到它告诉我们多少钱是投资的比例.例如,如果股票下跌10%,那么大小为4898美元(总账户数为14000)的头寸会导致总账户损失 3.49%.(即4898 / 14000 = 0.349857. 0.349857 * 10% = 3.49857%)
然后将该比率(投资金额与总金额)乘以公式乘以x$TradeResult.Percent.,以获得对总账户的百分比影响(参见前一段中的计算示例).
最后一步,总帐户的百分比损失将应用于索引值(从以下开始100).在这种情况下,以48.89美元买入100股的第一笔投资让指数从100点开始下跌至99.97901,反映了交易对总账户的影响.
编辑结束
剥离函数清理然后一次添加公式的一部分,以便发现错误,我来到以下错误似乎驻留的步骤:
CalculateIndex <- function(x){
totalAccount <- accountValueStart
if(x$TradeResult.Currency == head(x$TradeResult.Currency., n = 1)){
indexedValues <- totalAccount
# Update the accountvalue
totalAccount <- totalAccount + x$TradeResult.Currency.
}
else{ # the value is not the first
indexedValues <- c(indexedValues, totalAccount)
# Update the accountvalue
totalAccount <- totalAccount + x$TradeResult.Currency.
}
return(indexedValues)
}
> CalculateIndex(theData)
[1] 14000
Warning message:
In if (x$TradeResult.Currency == head(x$TradeResult.Currency., n = 1)) { :
the condition has length > 1 and only the first element will be used
Run Code Online (Sandbox Code Playgroud)
所以,似乎如果我只使用totalAccount变量,该函数不会正确更新.这似乎表明if else语句的基础有一些错误,因为它只输出第一个值.
如果我else从函数中删除语句,我会得到每个行的值theData.然而,这些都是错误计算的.所以,在我看来,这个函数如何更新totalAccount变量有一些错误.我没有看到我在哪里犯了错误,所以任何建议都会受到高度赞赏.我究竟做错了什么?
数据
这是我的数据:
> theData
Size.Units. EntryPrice TradeResult.Percent. TradeResult.Currency.
1 100 48.98 -0.06 -3
11 100 32.59 -0.25 -8
12 100 32.51 -1.48 -48
2 100 49.01 5.39 264
13 100 32.99 3.79 125
14 100 34.24 -4.38 -150
3 100 51.65 5.50 284
4 100 48.81 1.41 69
15 100 35.74 -5.76 -206
5 100 49.50 5.72 283
6 100 46.67 -4.69 -219
16 100 33.68 3.18 107
7 100 44.48 -2.05 -91
17 100 32.61 3.28 107
8 100 45.39 3.64 165
9 100 47.04 -0.74 -35
10 100 47.39 -6.20 -294
18 100 33.68 1.66 56
19 100 33.12 -0.79 -26
20 100 32.86 5.75 189
theData <- structure(list(X = c(1L, 11L, 12L, 2L, 13L, 14L, 3L, 4L, 15L,
5L, 6L, 16L, 7L, 17L, 8L, 9L, 10L, 18L, 19L, 20L), Size.Units. = c(100L,
100L, 100L, 100L, 100L, 100L, 100L, 100L, 100L, 100L, 100L, 100L,
100L, 100L, 100L, 100L, 100L, 100L, 100L, 100L), EntryPrice = c(48.98,
32.59, 32.51, 49.01, 32.99, 34.24, 51.65, 48.81, 35.74, 49.5,
46.67, 33.68, 44.48, 32.61, 45.39, 47.04, 47.39, 33.68, 33.12,
32.86), TradeResult.Percent. = c(-0.06, -0.25, -1.48, 5.39, 3.79,
-4.38, 5.5, 1.41, -5.76, 5.72, -4.69, 3.18, -2.05, 3.28, 3.64,
-0.74, -6.2, 1.66, -0.79, 5.75), TradeResult.Currency. = c(-3L,
-8L, -48L, 264L, 125L, -150L, 284L, 69L, -206L, 283L, -219L,
107L, -91L, 107L, 165L, -35L, -294L, 56L, -26L, 189L)), .Names = c("X",
"Size.Units.", "EntryPrice", "TradeResult.Percent.", "TradeResult.Currency."
), class = "data.frame", row.names = c(NA, -20L))
# Set the account start @ 14000
> accountValueStart <- 14000
Run Code Online (Sandbox Code Playgroud)
你的代码看起来很奇怪,似乎你对R来自另一种编程语言有很多误解.Gavin和Gillespie已经指出了为什么你得到了warniong.让我为更优化的编码添加一些提示:
[-1]并不意味着:删除最后一个.它意味着"保留除了第一个值之外的所有东西",这也解释了为什么你会得到错误的结果.
在开始时计算常见的东西,以整理你的代码.
head(x$TradeResult.Currency., n = 1)是一样的x$TradeResult.Currency.[1].
留意你的向量.代码中的大多数错误都来自忘记你正在使用向量.
如果你需要一个值作为向量中的第一个,把你使用的任何循环的OUTSIDE放在那里,永远不要在函数中添加if子句.
尽可能预定义您的矢量/矩阵,在处理大数据时速度更快,内存更少.
矢量化,矢量化,矢量化.我提到了矢量化吗?
学习使用debug(),debugonce()并browser()检查你的功能,在做什么.您可以通过在函数内操作时检查对象来解决许多问题.
这说并考虑到,你的功能变成:
CalculateIndex <- function(x,accountValueStart){
# predifine your vector
indexedValues <- vector("numeric",nrow(x))
# get your totalAccount calculated FAST. This is a VECTOR!!!
totalAccount <- cumsum(c(accountValueStart,x$TradeResult.Currency.))
#adjust length:
totalAccount <- totalAccount[-(nrow(x)+1)]
# only once this calculation. This is a VECTOR!!!!
totRatio <- 1+(((x$Size.Units. * x$EntryPrice)/totalAccount) *
x$TradeResult.Percent.)/100
# and now the calculations
indexedValues[1] <- 100 * totRatio[1]
for(i in 2:nrow(x)){
indexedValues[i] <- indexedValues[i-1]*totRatio[i]
}
return(indexedValues)
}
Run Code Online (Sandbox Code Playgroud)
并返回
> CalculateIndex(theData,14000)
[1] 99.97901 99.92081 99.57714 101.46399 102.35708 101.28586 103.31497
103.80656 102.33612 104.35856 102.79509 103.56012
[13] 102.90879 103.67281 104.85296 104.60432 102.50553 102.90490 102.71800
104.06766
Run Code Online (Sandbox Code Playgroud)
所以现在你做:
invisible(replicate(10,print("I will never forget about vectorization any more!")))
Run Code Online (Sandbox Code Playgroud)