/// <summary> /// Returns True if the index bar is a doji bar /// </summary> /// <param name="bars"></param> /// <param name="index">The bar index number in a market series</param> /// <returns>bool</returns> public static bool IsDojiBar(this Bars bars, int index) { double barBodyRange = bars.GetBarRange(index, true); double barRange = bars.GetBarRange(index); double meanBarRange = bars.GetAverageBarRange(index - 1, 50); return(barRange < meanBarRange / 3 && barBodyRange / barRange < 0.5); }
/// <summary> /// Returns True if the index bar is an engulfing bar /// </summary> /// <param name="bars"></param> /// <param name="index">The bar index number in a market series</param> /// <returns>bool</returns> public static bool IsEngulfingBar(this Bars bars, int index) { double barBodyRange = bars.GetBarRange(index, true); double previousBarRange = bars.GetBarRange(index - 1); BarType barType = bars.GetBarType(index); BarType previousBarType = bars.GetBarType(index - 1); return(barBodyRange > previousBarRange && barType != previousBarType); }
/// <summary> /// Returns the minimum bar range in a market series /// </summary> /// <param name="bars"></param> /// <param name="index">The start bar index</param> /// <param name="periods">The number of previous bars</param> /// <param name="useBarBody">Use bar open and close price instead of high and low?</param> /// <returns>double</returns> public static double GetMinBarRange(this Bars bars, int index, int periods, bool useBarBody = false) { var minRange = double.MaxValue; for (var i = index; i >= index - periods; i--) { minRange = Math.Min(minRange, bars.GetBarRange(i, useBarBody: useBarBody)); } return(minRange); }
/// <summary> /// Returns the median bar range of x previous bars on a market series /// </summary> /// <param name="bars"></param> /// <param name="index">Bar index in market series, the calculation will begin from this bar</param> /// <param name="periods">The number of x previous bars or look back bars</param> /// <param name="useBarBody">Use bar open and close price instead of high and low?</param> /// <returns>double</returns> public static double GetMedianBarRange(this Bars bars, int index, int periods, bool useBarBody = false) { var barRanges = new List <double>(); for (var iBarIndex = index; iBarIndex >= index - periods; iBarIndex--) { double iBarRange = bars.GetBarRange(iBarIndex, useBarBody); barRanges.Add(iBarRange); } return(barRanges.Median()); }
/// <summary> /// Returns the volume profile of x latest bars in a market series /// </summary> /// <param name="bars"></param> /// <param name="index">Last Bar Index</param> /// <param name="periods">Number of previous bars before provided index</param> /// <param name="symbol">The market series symbol</param> /// <returns>List<PriceVolume></returns> public static List <PriceLevel> GetVolumeProfile(this Bars bars, int index, int periods, Symbol symbol) { var result = new List <PriceLevel>(); for (var i = index; i > index - periods; i--) { var barRange = bars.GetBarRange(i); var barVolume = bars.TickVolumes[i]; if (barRange <= 0 || barVolume <= 0) { continue; } var percentageAboveBarClose = (bars.HighPrices[i] - bars.ClosePrices[i]) / barRange; var percentageBelowBarClose = (bars.ClosePrices[i] - bars.LowPrices[i]) / barRange; var bullishVolume = barVolume * percentageBelowBarClose; var bearishVolume = barVolume * percentageAboveBarClose; var barRangeInPips = symbol.ToPips(barRange); var bullishVolumePerPips = bullishVolume / barRangeInPips; var bearishVolumePerPips = bearishVolume / barRangeInPips; for (var level = bars.LowPrices[i]; level <= bars.HighPrices[i]; level += symbol.PipSize) { level = Math.Round(level, symbol.Digits); var priceLevel = result.FirstOrDefault(pLevel => pLevel.Level == level); if (priceLevel == null) { priceLevel = new PriceLevel { Level = level }; result.Add(priceLevel); } priceLevel.BullishVolume += bullishVolumePerPips; priceLevel.BearishVolume += bearishVolumePerPips; } } return(result); }
/// <summary> /// Returns True if the index bar is a rejection bar /// </summary> /// <param name="bars"></param> /// <param name="index">The bar index number in a market series</param> /// <returns>bool</returns> public static bool IsRejectionBar(this Bars bars, int index) { double barBodyRange = bars.GetBarRange(index, true); double barRange = bars.GetBarRange(index); BarType barType = bars.GetBarType(index); double meanBarRange = bars.GetAverageBarRange(index - 1, 50); if (barBodyRange / barRange < 0.3 && barRange > meanBarRange) { var barMiddle = barRange * 0.5 + bars.LowPrices[index]; var barFirstQuartile = barRange * 0.25 + bars.LowPrices[index]; var barThirdQuartile = barRange * 0.75 + bars.LowPrices[index]; if (bars.OpenPrices[index] > barMiddle && bars.ClosePrices[index] > barThirdQuartile && barType == BarType.Bullish || bars.OpenPrices[index] < barMiddle && bars.ClosePrices[index] < barFirstQuartile && barType == BarType.Bearish) { return(true); } } return(false); }
/// <summary> /// Returns the maximum bar range in a market series /// </summary> /// <param name="bars"></param> /// <param name="index">The start bar index</param> /// <param name="periods">The number of previous bars</param> /// <param name="barType">The type of bars</param> /// <param name="useBarBody">Use bar open and close price instead of high and low?</param> /// <returns>double</returns> public static double GetMaxBarRange(this Bars bars, int index, int periods, BarType barType, bool useBarBody = false) { var maxRange = double.MinValue; for (var i = index; i >= index - periods; i--) { if (bars.GetBarType(i) != barType) { continue; } maxRange = Math.Max(maxRange, bars.GetBarRange(i, useBarBody: useBarBody)); } return(maxRange); }
/// <summary> /// Returns the average bar range of x previous bars on a market series /// </summary> /// <param name="bars"></param> /// <param name="index">Bar index in market series, the calculation will begin from this bar</param> /// <param name="periods">The number of x previous bars or look back bars</param> /// <param name="barType">The type of bars</param> /// <param name="useBarBody">Use bar open and close price instead of high and low?</param> /// <returns>double</returns> public static double GetAverageBarRange(this Bars bars, int index, int periods, BarType barType, bool useBarBody = false) { var barRanges = new List <double>(); for (var iBarIndex = index; iBarIndex >= index - periods; iBarIndex--) { if (bars.GetBarType(iBarIndex) != barType) { continue; } double iBarRange = bars.GetBarRange(iBarIndex, useBarBody); barRanges.Add(iBarRange); } return(barRanges.Average()); }
/// <summary> /// Returns a bar volume strength /// </summary> /// <param name="bars"></param> /// <param name="index">Bar index</param> /// <returns>double</returns> public static double GetBarVolumeStrength(this Bars bars, int index) { return(bars.GetBarRange(index) / bars.TickVolumes[index]);; }
/// <summary> /// Returns the range of a bar in a market series /// </summary> /// <param name="bars"></param> /// <param name="index">Bar index in market series</param> /// <param name="symbol">The market series symbol</param> /// <param name="returnType">The return type</param> /// <param name="useBarBody">Use bar open and close price instead of high and low?</param> /// <returns>double</returns> public static double GetBarRange(this Bars bars, int index, Symbol symbol, PriceValueType returnType, bool useBarBody = false) { double range = bars.GetBarRange(index, useBarBody); return(symbol.ChangePriceValueType(range, returnType)); }