Site icon R-bloggers

Labeling Opportunities in Price Series

[This article was first published on R – Quintuitive, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

One approach to trading which has been puzzling me lately, is to sit and wait for opportunities. Sounds simplistic, but it is indeed different than, for instance, the asset allocation strategies. In order to be able to even attempt taking advantage of these opportunities, however, we must be able to identify them. Once the opportunities are identified – we can try to explain (forecast) them using historical data.

The first step is to define what an opportunity is. It could be anything, for instance we can start with a strong directional move, but then we need to define what a strong directional move is. Let’s give it a try.

We can define a strong directional move as a 5% move over 3 days for instance. However, that’s not likely to work for different markets (think futures). 5% move is a lot in treasuries, but not so much in oil. The solution is to normalize the returns using volatility. I will use exponential moving average for that.

Here is a short code snippet:

adjust.returns = function(returns, vola.len=35) {
    vola = sqrt(EMA(returns * returns, n = vola.len))
    return(returns/vola)
}

good.entries = function(ohlc, days.out=15, vola.len=35, days.pos=0.6) {
    stopifnot(days.out > 3)
    
    hi = Hi(ohlc)
    lo = Lo(ohlc)
    cl = Cl(ohlc)
    rets = ROC(cl, type='discrete')
    arets = abs(adjust.returns(rets, vola.len=vola.len))
    res = rep(0, NROW(ohlc))
    days = rep(0, NROW(ohlc))
    for(ii in 3:days.out) {
        hh = lag.xts(runMax(hi, n=ii), -ii)
        ll = lag.xts(runMin(lo, n=ii), -ii)
        hi.ratio = (hh/cl - 1)/arets
        lo.ratio = (ll/cl - 1)/arets
        
        # days required
        dd = ceiling(days.pos*ii)
        
        longs = hi.ratio > dd & -lo.ratio < dd
        longs = ifelse(longs, 1, 0)
        
        shorts = -lo.ratio > dd & hi.ratio < dd
        shorts = ifelse(shorts, -1, 0)
        
        both = ifelse(longs == 1, 1, shorts)
        new.days = ii*as.numeric(res == 0 & both != 0)
        res = ifelse(res != 0, res, both)
        days = ifelse(days != 0, days, new.days)
    }
    return(data.frame(entry=res, days=days))
}

The code basically defines an opportunity as a directional move over X days (X is between 3 and 15). The minimum move we would accept is computed by taking a percentage of the days (60% by default), rounding that number up, and multiplying it by the standard deviation of the normalized returns. We also require that the move in the opposite direction is smaller. Hard to explain, but hopefully you get the idea.

The function returns a label for each day: 0, 1, or -1. The opportunities are the 1 and -1 days of course.

Is this trade-able? Absolutely. When an opportunity arises, we enter in the suggested direction. The exit is a profit target, we can use a stop loss of the same magnitude.

Why all this effort again? Simple – these labels can be used as the response, or the dependent variable in an attempt to explain (forecast) the opportunities using historical data. At this point what’s left is to generate what we think might constitute a good set of predictors, align the two sets appropriately (no data snooping) and the rest is standard machine learning.

That’s for another post though.

The post Labeling Opportunities in Price Series appeared first on Quintuitive.

To leave a comment for the author, please follow the link and comment on their blog: R – Quintuitive.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.