/// <summary> /// Calculate return over maximum drawdown. /// </summary> /// <param name="series">input time series</param> /// <param name="n">length of observation window</param> /// <param name="parentId">caller cache id, optional</param> /// <param name="memberName">caller's member name, optional</param> /// <param name="lineNumber">caller line number, optional</param> /// <returns>RoMaD</returns> public static ITimeSeries <double> ReturnOnMaxDrawdown(this ITimeSeries <double> series, int n, CacheId parentId = null, [CallerMemberName] string memberName = "", [CallerLineNumber] int lineNumber = 0) { var cacheId = new CacheId(parentId, memberName, lineNumber, series.GetHashCode(), n); return(IndicatorsBasic.BufferedLambda( (p) => { double ret = series[0] / series[n] - 1.0; double dd = series.MaxDrawdown(n)[0]; return ret / Math.Max(1e-3, dd); }, 0.0, cacheId)); }