/// <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; } } } }
/// <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; } } } }