Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Custom Factor - Kaufman's Efficiency Ratio

Here is an attempt to render Kaufman's Efficiency Ratio in Zipline / Quantopian. Any comments, improvements etc gratefully accepted. Quantopian - you may want to incorporate the corrected / improved version in Zipline and Quantopian.

class efficiency_ratio(CustomFactor):  
   inputs = [USEquityPricing.close, USEquityPricing.high, USEquityPricing.low]  
   window_length = 30  
   def compute(self, today, assets, out, close, high, low):  
       lb = self.window_length  
       e_r = np.zeros(len(assets), dtype=np.float64)  
       a=np.array(([high[1:(lb):1]-low[1:(lb):1],abs(high[1:(lb):1]-close[0:(lb-1):1]),abs(low[1:(lb):1]-close[0:(lb-1):1])]))  
       b=a.T.max(axis=1)  
       c=b.sum(axis=1)  
       e_r=abs(close[-1]-close[0]) /c  
       out[:] = e_r  
5 responses

Incidentally of course you can easily adapt the above to achieve the ATR as a Custom Factor. As an aside, I find it pretty difficult de-bugging Custom Factors in Pipeline / USEquityPricing because of the large number of stocks.....but there you go.

Thanks Anthony - glancing at the code, this seems to be an indicator of how much of the daily movement is contributing to net movement, rather than chopping around/mean reverting?

Yep. If the price moved from A to B in a perfectly straight line the result if the indicator would be one. If it meanders around a lot it will be closer to zero. I have found some use for it as a filter in stock trades. EG don't take the trade if efficiency is less than X. Or in a ranking situation, mark down the ranking to -100 if efficiency is too low. Far from perfect (what isn't) but it seems to add value and I have been using it in my own trading.

@Anthony, thanks for the code, I've been working on adapting it to create ATR as a custom factor. I think I discovered a small bug along the way - I think the corrected code should read as follows (the only difference is b=a.T.max(axis=2) )

class Efficiency_Ratio(CustomFactor):  
   inputs = [USEquityPricing.close, USEquityPricing.high, USEquityPricing.low]  
   window_length = 30  
   def compute(self, today, assets, out, close, high, low):  
       lb = self.window_length  
       e_r = np.zeros(len(assets), dtype=np.float64)  
       a=np.array(([high[1:(lb):1]-low[1:(lb):1],abs(high[1:(lb):1]-close[0:(lb-1):1]),abs(low[1:(lb):1]-close[0:(lb-1):1])]))  
       b=a.T.max(axis=2)  
       c=b.sum(axis=1)  
       e_r=abs(close[-1]-close[0]) /c  
       out[:] = e_r  

I reached this conclusion by actually inspecting the log.info outputs after every line of code, so I think it's now correct. Take a look and see if you agree?

No idea Richard. I have not looked at Q for a while. I find the IDE not hugely helpful and this was a nightmare to code given the difficulties I had seeing the full shape, scope, size and so forth of the pipeline. I will revisit this when I have the time. To be frank I find the whole Zipline back tester incomprehensible since it is virtually impossible to install on Window s and I haven't bothered trying it on Linux yet.

I am not finding either Q or Zipline suitable for my purposes. There is no provision for base currency and P&L currency conversion for starters. For another the vast and increasingly incomprehensible list of dependencies drives me mad.

It is a good product no doubt and had the Got a move on with the currency problem and made Zipline Windows friendly I might have pursued it more fervently.

As it stands however my focus has shifted to other Python solutions.

Which is not to say I am abanding Q or Zipline. But it currently lacks some stuff which I need.