Conditional results?

Hi,

I've spent sometime on this, but being an R newbie, and despite reading furiously, I am stuck. All guidance would be appreciated.

I have created simplified exchange prices, and based on various ifelse consitions, should print the start of a trade as '1' and the exit as '0', and also record the entry and exit.price. I have got this to work to some extent, but ideally I would like the exit.price and trade.off columns to only be recorded in the first instance of the conditions becoming true - i.e. only on rows 7 and 14, when this part becomes true ifelse (prices$High >= lag(prices$High), 0, NA)

# A tibble: 14 × 8
    Low  High up_day p_type entry.price exit.price trade.on trade.off
  <dbl> <dbl> <chr>  <chr>        <dbl>      <dbl>    <dbl>     <dbl>
1   100   110 NA     NA              NA         NA       NA        NA
2   110   130 NA     NA              NA        110       NA         0
3   100   120 Up     P.High         100         NA        1        NA
4    90   110 NA     NA              NA         NA       NA        NA
5    80   100 NA     NA              NA         NA       NA        NA
6    70    90 NA     NA              NA         NA       NA        NA
7    80    95 NA     NA              NA         90       NA         0
8    90   105 NA     NA              NA         95       NA         0
9   100   110 NA     NA              NA        105       NA         0
10   105   120 Up     P.High         105        110        1         0
11   108   110 NA     NA              NA         NA       NA        NA
12   108   109 NA     NA              NA         NA       NA        NA
13    90   100 NA     NA              NA         NA       NA        NA
14    95   110 NA     NA              NA        100       NA         0

So far my code looks like this:
note: using Dplyr

for (i in 1:nrow(prices)) {
  print("Start")
  prices$entry.price <- ifelse (prices$p_type == "P.High" & prices$up_day == "Up", prices$Low, NA)
  prices$trade.on <- ifelse (prices$p_type == "P.High" & prices$up_day == "Up", 1, NA)
  i <- 1
  if (i <= 1) {
    prices$exit.price <- ifelse (prices$High >= lag(prices$High), lag(prices$High), NA)
    prices$trade.off <- ifelse (prices$High >= lag(prices$High), 0, NA)
    i <- i - 1
  } else {
    NA
  }
  print("End")
}

I tried to use an if else argument to limit the nested ifelse conditions to only run after trade.on becomes 1, but that doesn't seem to work at all. I'm very much out of my depth!

can you explain how the start and end of a trade are to be identified from the initial columns ?

FWIW, in my contrived and simplified data example, there are only selling trades.

In the 1st case, on row 3, where a p.high is marked, the entry occurs when the next low price of row 4 exceeds the low of the p.high row3. I.e. 100, well probably 99, but hopefully you see my point. The exit is identified when a High exceeds a previous High, i.e. row7 High exceeds row6 High.

In the 2nd case, largely as above, row 10 Low is exceeded at row 13, commecing a trade. Row 14's High exceeds row13s High, ending the trade.

I hope that makes sense?

I would approach it in this way

library(tidyverse)

(start_df <- tibble::tribble(
  ~Low, ~High, ~up_day, ~p_type,
  100, 110, NA, NA,
  110, 130, NA, NA,
  100, 120, "Up", "P.High",
  90, 110, NA, NA,
  80, 100, NA, NA,
  70, 90, NA, NA,
  80, 95, NA, NA,
  90, 105, NA, NA,
  100, 110, NA, NA,
  105, 120, "Up", "P.High",
  108, 110, NA, NA,
  108, 109, NA, NA,
  90, 100, NA, NA,
  95, 110, NA, NA
))


# break the data into consecutive up/Phigh groups,
# I assume that these always go together ...
# here there are 3, with even though the first one is a dud
(step_1 <- start_df |>
  mutate(
    build_group_ = as.integer(!is.na(up_day)),
    build_group_2 = cumsum(build_group_)
  # ) |> filter(
  #   build_group_2 > 0
  )
)

(step_2 <- step_1 |> group_by(build_group_2) |>
  mutate(
    rn = row_number(),
    low_to_beat = ifelse(build_group_, Low, NA_real_)
  ) |>
  fill(low_to_beat) |>
  mutate(
    beats_low = cumsum(as.integer(Low < low_to_beat & rn != 1)),
    first_beats_low = as.integer(beats_low == 1),
    all_exit = as.integer(High > lag(High, default = Inf)),
    exit_nums = cumsum(all_exit),
    first_exit = as.integer(exit_nums==1)
  ))
1 Like

Thank you very much for taking the time to code all that, I really appreciate it.

I understand the concept of what you've created, though it will take me a little while to understand the code, but it definitely does the trick. In my world, it's ingenious! :+1:

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.