How to repeat a cunk of code up to when a condition is matched

Viewed 30

I have a specific code which I want R to loop over a precise dataframe, in particular the code is actually considering the column returns and does something iff it is higher than 0.5 or lower than -0.33 The code does the correction and recomputes the column returns. The idea is to loop this code until in all the dataset I end up with no returns > 0.5 | returns < -0.33

How can I do this? I'm an r beginner and got lost in the process!

I paste my code here and a str of the dataset

 str(mktprice)
tibble [2,588,434 x 13] (S3: tbl_df/tbl/data.frame)
 $ datetime   : Date[1:2588434], format: "2015-03-18" "2015-03-19" "2015-03-20" ...
 $ investor   : chr [1:2588434] "Q1762" "Q1762" "Q1762" "Q1762" ...
 $ asset      : chr [1:2588434] "004125" "004125" "004125" "004125" ...
 $ marketprice: num [1:2588434] 163 165 165 165 165 165 165 165 165 165 ...
 $ operation  : num [1:2588434] 1000 7000 NA NA NA NA NA NA NA NA ...
 $ returns    : num [1:2588434] 0 0.0123 0 0 0 ...
 $ ret_no4days: num [1:2588434] NA 0.0123 0 0 0 ...
 $ ab_check   : logi [1:2588434] FALSE FALSE FALSE FALSE FALSE FALSE ...
 $ adjustm    : num [1:2588434] 1 1 1 1 1 1 1 1 1 1 ...
 $ fixprice   : num [1:2588434] 163 165 165 165 165 165 165 165 165 165 ...
 $ fixquant   : num [1:2588434] 1000 7000 NA NA NA NA NA NA NA NA ...
 $ rows_to_mod: num [1:2588434] NA NA NA NA NA NA NA NA NA NA ...
 $ new_adj    : num [1:2588434] 1 1 1 1 1 1 1 1 1 1 ...






mktprice <- mktprice %>% 
  group_by(investor, asset, datetime) %>% 
  slice(1) %>%  # remove repeated dates
  group_by(investor, asset) %>% 
  arrange(datetime) %>% 
  mutate(returns = (fixprice-lag(fixprice))/lag(fixprice)) %>%
  mutate(returns = ifelse(is.na(returns), 0 , returns)) %>% # ifelse check the differences of days
  arrange(asset,datetime) %>%  # show by assets and dates
  ungroup()


mktprice <- mktprice %>% mutate(ab_check = ifelse((returns > 0.5 | returns < -0.33), TRUE, FALSE))
mktprice <- mktprice %>% 
  group_by(asset) %>% 
  mutate(adjustm = ifelse((returns > 0.5 | returns < -0.33), fixprice/dplyr::lag(fixprice), 1)) %>% 
  ungroup


mktprice <- mktprice %>% mutate(ab_check= ifelse(is.na(ab_check), FALSE, ab_check))




mktprice <- mktprice %>% 
  arrange(asset, datetime) %>%  
  replace_na(list(ab_check = FALSE)) %>% 
  group_by(asset) %>%  
  mutate(rows_to_mod = max(ab_check),
         rows_to_mod = if_else(lag(ab_check) == TRUE, 1, NA_real_),
         new_adj = if_else(lag(ab_check) == TRUE, lag(adjustm), NA_real_)
  ) %>% 
  fill(rows_to_mod, new_adj) %>%  
  replace_na(list(new_adj = 1)) %>%  
  mutate(fixprice = fixprice / new_adj) %>% 
  mutate(fixquant = operation*new_adj) %>% 
  ungroup


mktprice <- mktprice %>% 
  group_by(asset) %>% 
  mutate(fixprice = ifelse((returns > 0.5 | returns < -0.33), fixprice/adjustm, fixprice)) %>%
  mutate(fixquant = ifelse((returns > 0.5 | returns < -0.33), operation*adjustm, operation)) %>% 
  ungroup

mktprice$fixquant <- round(mktprice$fixquant)
1 Answers

You probably want a while loop rather than a for loop. I think this should do what you're after.

while(max(mktprice$returns) > 0.05   | min(mktprice$returns) < -0.33) {
  mktprice <- mktprice %>% 
    group_by(asset) %>% 
    mutate(fixprice = ifelse((returns > 0.5 | returns < -0.33), fixprice/adjustm, fixprice)) %>%
    mutate(fixquant = ifelse((returns > 0.5 | returns < -0.33), operation*adjustm, operation)) %>% 
    ungroup()
}
Related