/// <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); }
public bool Equals(PriceLevel other) { return(other != null && other.Level == Level); }