Elvis
Elvis

Reputation: 425

How to include the counting process in for loop in R Studio?

I want to count how many positive and negative returns for each month in 10 years time and include them in the dtf. This is because I want to calculate the probability of getting positive and negative returns. I'm not sure how to include the counting process in my for loop.

For example: The average monthly returns for July in 10 years is 2.18%, and the number of positive returns are 8 out of 10 which is 80% and so the probability of obtaining negative returns will be 20%. Since the 10 years average monthly return for July is in positive, 2.18%, I would like the probability of positive return (80%) to be shown in dtf instead of negative one (20%).

Another example: Same thing goes to May. Since the average monthly return in 10 years time for May is negative (-1.23%), and the probability of getting positive returns in 10 years is 60% (6 out of 10) while for the negative one is 40% (4 out of 10), I would like the negative probability (40%) to be shown in dtf instead of the positive 60%.

Same thing goes to each and every month, and therefore, there will be a 3rd column in dtf showing the probability of getting positive/negative returns.

I tried to include if loop in my for loop but it doesn't work. I attached my code below with the dtf with only 2 column (Month and AverageMonthlyRet).

library(quantmod)

#obtian the historical stock price
prices <- getSymbols("^GSPC", src = 'yahoo', from = "2009-07-01", to = "2019-08-01", 
                     periodicity = "monthly", auto.assign = FALSE, warnings = FALSE)[,4]

#calculate the log return and convert back to simple return
return <- diff(log(prices))
r <- na.omit(exp(return)-1)

monthlyRet <- as.numeric(r[,1])

#loop through all the months in 10 years
AverageMonthlyRet <- c()
for (j in 1:12){
  Group <- c()
  for (i in seq(j,length(monthlyRet),12)){
    Group[i] <- monthlyRet[i]
  }
  AverageMonthlyRet[j] <- mean(Group, na.rm=TRUE)
}
AverageMonthlyRet <- round(AverageMonthlyRet,4)

#create a data frame to store the result
Month <- c("Aug","Sep","Oct","Nov","Dec","Jan","Feb","Mar","Apr","May","Jun","Jul")
dtf <- data.frame(Month, AverageMonthlyRet)

Upvotes: 2

Views: 531

Answers (2)

Ronak Shah
Ronak Shah

Reputation: 388982

Using base R, we can count the proportion of sign for each month, merge by "Month" with dtf and select the appropriate value based on sign of AverageMonthlyRet.

tmp <- as.data.frame(do.call(rbind, tapply(sign(r), format(index(r), "%b"),
                     function(x) c(table(x)))))
tmp$Month <- rownames(tmp)
df1 <- merge(dtf, tmp)
df1$selected <- ifelse(sign(df1$AverageMonthlyRet) == 1, df1$`1`, df1$`-1`)

df1
#   Month AverageMonthlyRet -1 1 selected
#1    Apr            0.0122  1 9        9
#2    Aug           -0.0078  5 5        5
#3    Dec            0.0061  3 7        7
#4    Feb            0.0234  2 8        8
#5    Jan            0.0115  4 6        6
#6    Jul            0.0218  2 8        8
#7    Jun            0.0030  4 6        6
#8    Mar            0.0171  4 6        6
#9    May           -0.0123  4 6        4
#10   Nov            0.0162  2 8        8
#11   Oct            0.0189  4 6        6
#12   Sep            0.0086  4 6        6

Upvotes: 1

Chelmy88
Chelmy88

Reputation: 1116

Here is a proposed solution, based on my understanding of your question. Comments are given in the code.

The main idea is to add some counter variables that you increment in the loop depending on the results of some if/else tests. They store the probability of negative or positive income. Then with an additional test you determine of you want to keep the positive or negative income probability.

There are ways to write it more concisely, but this longer version show all the details and ideas. If you know that the income is never null, you can just compute one counter because you know that one probability, e.g. positive, will always be 100 - other probability. In my version, null income is possible and thus you might have positive probability + negative probability being smaller than 100.

library(quantmod)

#obtian the historical stock price
prices <- getSymbols("^GSPC", src = 'yahoo', from = "2009-07-01", to = "2019-08-01", 
                     periodicity = "monthly", auto.assign = FALSE, warnings = FALSE)[,4]

#calculate the log return and convert back to simple return
return <- diff(log(prices))
r <- na.omit(exp(return)-1)

monthlyRet <- as.numeric(r[,1])

#loop through all the months in 10 years
AverageMonthlyRet <- c()
#Added: Array to store the probability for each month
Probability <- c()
for (j in 1:12){
  Group <- c()
  #Added: Counter, for each month, of positive or negative income
  connt_pos=0
  count_neg=0
  for (i in seq(j,length(monthlyRet),12)){
    Group[i] <- monthlyRet[i]
    #Added: Increment the counters based on the sign of monthlyRet[i]
    if(monthlyRet[i]>0){
      connt_pos <- connt_pos+1
    }
    else  if(monthlyRet[i]<0){
      count_neg <- count_neg+1
    }
  }
  AverageMonthlyRet[j] <- mean(Group, na.rm=TRUE)
  #Added: Depending if the average monthly retrn is positive or negative
  #compute the probability of positive or negative income (in %)
  prob=0
  if(AverageMonthlyRet[j]>0)
  {
    prob=connt_pos/(length(monthlyRet)/12)*100
  }
  else if (AverageMonthlyRet[j]<0){
    prob=count_neg/(length(monthlyRet)/12)*100
  }
  #Added: Store the result
  Probability[j] <- prob

}
AverageMonthlyRet <- round(AverageMonthlyRet,4)

#create a data frame to store the result
Month <- c("Aug","Sep","Oct","Nov","Dec","Jan","Feb","Mar","Apr","May","Jun","Jul")
#Added: Add the new probability column to the final data frame
dtf <- data.frame(Month, AverageMonthlyRet,Probability)

Upvotes: 1

Related Questions