/// <summary> /// Copy parameters. /// </summary> /// <param name="copy">Copy.</param> /// <returns>Copy.</returns> protected CandleMessage CopyTo(CandleMessage copy) { if (copy == null) { throw new ArgumentNullException(nameof(copy)); } copy.LocalTime = LocalTime; copy.OpenPrice = OpenPrice; copy.OpenTime = OpenTime; copy.OpenVolume = OpenVolume; copy.ClosePrice = ClosePrice; copy.CloseTime = CloseTime; copy.CloseVolume = CloseVolume; copy.HighPrice = HighPrice; copy.HighVolume = HighVolume; copy.HighTime = HighTime; copy.LowPrice = LowPrice; copy.LowVolume = LowVolume; copy.LowTime = LowTime; copy.OpenInterest = OpenInterest; copy.SecurityId = SecurityId; copy.TotalVolume = TotalVolume; copy.RelativeVolume = RelativeVolume; copy.OriginalTransactionId = OriginalTransactionId; copy.DownTicks = DownTicks; copy.UpTicks = UpTicks; copy.TotalTicks = TotalTicks; copy.IsFinished = IsFinished; copy.PriceLevels = PriceLevels?.Select(l => l.Clone()).ToArray(); copy.State = State; return(copy); }
/// <summary> /// Copy the message into the <paramref name="destination" />. /// </summary> /// <typeparam name="TCandle">The candle type.</typeparam> /// <param name="destination">The object, which copied information.</param> /// <returns>The object, which copied information.</returns> protected TCandle CopyTo <TCandle>(TCandle destination) where TCandle : Candle { destination.Arg = Arg; destination.ClosePrice = ClosePrice; destination.CloseTime = CloseTime; destination.CloseVolume = CloseVolume; destination.DownTicks = DownTicks; destination.HighPrice = HighPrice; destination.HighTime = HighTime; destination.HighVolume = HighVolume; destination.LowPrice = LowPrice; destination.LowTime = LowTime; destination.LowVolume = LowVolume; destination.OpenInterest = OpenInterest; destination.OpenPrice = OpenPrice; destination.OpenTime = OpenTime; destination.OpenVolume = OpenVolume; destination.RelativeVolume = RelativeVolume; destination.Security = Security; //destination.Series = Series; //destination.Source = Source; //destination.State = State; destination.TotalPrice = TotalPrice; destination.TotalTicks = TotalTicks; destination.TotalVolume = TotalVolume; //destination.VolumeProfileInfo = VolumeProfileInfo; destination.PriceLevels = PriceLevels?.Select(l => l.Clone()).ToArray(); return(destination); }
/// <summary> /// To calculate the value area. /// </summary> public void Calculate() { // Основная суть: // Есть POC Vol от него выше и ниже берется по два значения(объемы) // Суммируются и сравниваются, те что в сумме больше, складываются в общий объем, в котором изначально лежит POC Vol. // На следующей итерации берутся следующие два объема суммируются и сравниваются, и опять большая сумма ложится в общий объем // И так до тех пор пока общий объем не превысит порог, который устанавливается в процентном отношении к всему объему. // После превышения порога, самый верхний и самый нижний объем, из которых складывался общий объем будут VAH и VAL. // Возможные траблы: // Если POC Vol находится на границе ценового диапазона, то сверху/снизу брать нечего, то "набор" объемов только в одну сторону. // Если POC Vol находится на один шаг ниже/выше ценового диапазона, то сверху/снизу можно взять только одно значение для сравнения с двумя другими значениями. // Теоретически в ценовом диапазоне может быть несколько POC Vol, если будет несколько ценовых уровней с одинаковыми объемом, // в таком случае должен браться POC Vol который ближе к центру. Теоретически они могут быть равно удалены от центра.))) // Если сумма сравниваемых объемов равна, х.з. какие брать. var maxVolume = Math.Round(PriceLevels.Sum(p => p.BuyVolume + p.SellVolume) * VolumePercent / 100, 0); var currVolume = PriceLevels.Select(p => (p.BuyVolume + p.SellVolume)).Max(); POC = PriceLevels.FirstOrDefault(p => p.BuyVolume + p.SellVolume == currVolume); var abovePoc = Combine(PriceLevels.Where(p => p.Price > POC.Price).OrderBy(p => p.Price)); var belowePoc = Combine(PriceLevels.Where(p => p.Price < POC.Price).OrderByDescending(p => p.Price)); if (abovePoc.Count == 0) { LinkedListNode <PriceLevel> node; for (node = belowePoc.First; node != null; node = node.Next) { var vol = node.Value.BuyVolume + node.Value.SellVolume; if (currVolume + vol > maxVolume) { VAH = POC; VAL = node.Value; } else { currVolume += vol; } } } else if (belowePoc.Count == 0) { LinkedListNode <PriceLevel> node; for (node = abovePoc.First; node != null; node = node.Next) { var vol = node.Value.BuyVolume + node.Value.SellVolume; if (currVolume + vol > maxVolume) { VAH = node.Value; VAL = POC; } else { currVolume += vol; } } } else { var abovePocNode = abovePoc.First; var belowPocNode = belowePoc.First; while (true) { var aboveVol = abovePocNode.Value.BuyVolume + abovePocNode.Value.SellVolume; var belowVol = belowPocNode.Value.BuyVolume + belowPocNode.Value.SellVolume; if (aboveVol > belowVol) { if (currVolume + aboveVol > maxVolume) { VAH = abovePocNode.Value; VAL = belowPocNode.Value; break; } currVolume += aboveVol; abovePocNode = abovePocNode.Next; } else { if (currVolume + belowVol > maxVolume) { VAH = abovePocNode.Value; VAL = belowPocNode.Value; break; } currVolume += belowVol; belowPocNode = belowPocNode.Next; } } } }