0

Getting started on backtesting some trading data, in particular a very basic mean reversion idea and can't get my head around how to approach this concept.

How would I go about having a running 'posy' increase by 1 once DifFromFv (the deviation from fair value) reaches -10 and subsequently 'posy' increases by 1 as DifFromFv extends by multiples of -3 (-13,-16,-19, etc.) whilst having 'posy' decrease by 1 every time DifFromFv reverts back +5 from last changed 'posy'? Simply put, I am buying once the DifFromFv reaches 10 points and averaging every 3 points, whilst taking each individual average out for 5 points profit.

E.g:

  DifFromFv posy
     0.00    0
   -10.00    1   #initial clip (target profit -5.00)
   -11.50    1
   -13.00    2   #avg #1 (target profit -8.00)
   -16.60    3   #avg #2 (target profit -11.00)
   -12.30    3    
   -11.00    2   #taking profit on avg #2
   -14.10    2   
    -8.00    1   #taking profit on avg #1
    -7.00    1
    -5.00    0   #taking profit on initial clip

It should be noted that the take profit for every clip is consistently set at -5,-8,-11,etc. increments regardless of where the averages are filled as seen by the target profit for avg #2 being at -11.00 rather than -11.60. This is both to reduce margin of error in real-life fills vs data fills and also I'm pretty sure should make the approach to this concept a lot easier to think about.

Thanks in advance!

Kevin Chen
  • 23
  • 3
  • Why doesn't the posy increase again when DifFromFv reaches -14.1 (from -11) ? – Vincent K Sep 29 '17 at 10:03
  • Hey Vincent, thanks very much for your response - I'll definitely provide code next time. The posy should not increase from -11.00 to -14.10 because avg #1 (which was put on at -13.00) has yet to be taken out and thus we only will add to the posy once it reaches -16.00 as to put back on avg #2 (which was taken out at -11.00). Otherwise, we wait until DifFromFv reaches -8.00 and profit is taken on avg #1, and then the next time -13.00 is reached we may add back avg #1. Hope that makes sense. I will take some time to run your code and see if it runs as intended. Thanks again! – Kevin Chen Sep 30 '17 at 14:06

1 Answers1

0

Next time please provide some code, even though your explanation is quite clear. However, you didn't mention how you want to deal with large jumps in DifFromFv (for instance, if it goes from -3 to -18), so I leave it up to you.

Here is the code with comments:

library(plyr)

firstPosy = FALSE

DiffFair <- c(0, -10, -11.5, -13, -16.6, -12.3, -11, -14.1, -8, -7, -5) # Your data here
posy <- c(0)

buyPrices <- c(0) # Stores the prices at which you by your asset
targetProfit <- c(0) # Stores the target profit alongside with the vector above

steps <- c(0) # Stores your multiples of -3 after -10 (-10, -13, -16...)
PNL = 0

for (i in 2:length(DiffFair)) {

  # Case where posy increments for the first time by one

  if (DiffFair[i] <= -10 & DiffFair[i] > -13 & firstPosy == FALSE) {
    firstPosy = TRUE
    posy <- c(posy, 1)
    steps <- c(steps, round_any(DiffFair[i], 10, f = ceiling))
    lastChangePosy = DiffFair[i]
    buyPrices <- c(buyPrices, DiffFair[i])
    targetProfit <- c(targetProfit, -5)
  } 

else if (DiffFair[i] <= -13 & firstPosy == FALSE) {
    firstPosy = TRUE
    lastChangePosy = DiffFair[i]
    steps <- c(steps, round_any(DiffFair[i] + 10, 3, f = ceiling) - 10)
    buyPrices <- c(buyPrices, DiffFair[i])
    targetProfit <- c(targetProfit, -5)
    posy <- c(posy, tail(posy, n=1) + (-round_any(DiffFair[i] + 10, 3, f = ceiling) / 3) + 1)
  }

  # Posy increase

  else if (tail(steps, n=1) > round_any(DiffFair[i] + 10, 3, f = ceiling) - 10 & DiffFair[i] <= -10) {
    posy <- c(posy, posy[i-1] + 1)
    steps <- c(steps, round_any(DiffFair[i] + 10, 3, f = ceiling) -10)
    lastChangePosy = DiffFair[i]

    buyPrices <- c(buyPrices, DiffFair[i])
    targetProfit <- c(targetProfit, tail(targetProfit, n=1) - 3)
  }

  # Posy decrease

 else if (DiffFair[i] >= tail(targetProfit, n=1) & tail(posy, n=1) > 0) {
    if (tail(targetProfit, n=1) == -5) {
      posy <- c(posy, 0)
    }
    else {
      posy <- c(posy, posy[i-1] - 1)
    }
    lastChangePosy = DiffFair[i]

    # Compute PNL and delete the target profit and buy price from the vectors
    PNL = PNL + (DiffFair[i] - tail(buyPrices, n=1))
    buyPrices <- buyPrices[-length(buyPrices)]
    targetProfit <- targetProfit[-length(targetProfit)]
    steps <- steps[-length(steps)]

    if (DiffFair[i] > -10) {
      firstPosy = FALSE
    }

  }

  # Posy doesn't change

  else {
    posy <- c(posy, posy[i-1])
  }

}

print(PNL)
Vincent K
  • 568
  • 5
  • 9
  • Hey Vincent, awesome code and seems to work perfectly as intended; however, I've been playing around with the DiffFair vector and as an example when I change it to DiffFair <- c(0, -5, -6.9, -13.4, -16.6, -12.3, -10.2, -14.1, -7.9, -7, -5), the code faces: Error in if (DiffFair[i] >= tail(targetProfit, n = 1)) { : argument is of length zero. Not too sure why this happens? Cheers! – Kevin Chen Sep 30 '17 at 17:53
  • I updated the code, initializing the buyPrices and targetProfit vectors and adding more conditions to make the execution safer. – Vincent K Oct 01 '17 at 14:50
  • Works perfect now Vincent. Thanks again, was exactly what I was looking for. Cheers! – Kevin Chen Oct 01 '17 at 20:42
  • Hey @Vincent , how would you approach the situation you previously mentioned, whereby there would be big jumps from -3 to -18 and wanted the position to increase from 0 to 3 rather than just by 1 (and same goes for profit taking)? – Kevin Chen Oct 02 '17 at 23:28
  • Check my update. It takes into account the jump from a DiffFromFv > -10 to a DiffFromFv < -13. You can use this example to code another "else if" statement for jumps like -18.3 -> -33.5 – Vincent K Oct 03 '17 at 09:30
  • Cheers Vincent ! – Kevin Chen Oct 04 '17 at 07:58