// cluster calculation // расчёт кластеров /// <summary> /// compute the clusters /// просчитать кластеры /// </summary> public void Process(List <Candle> candles) { if (candles == null) { return; } if (_myCandles != null && candles.Count < _myCandles.Count) { Clear(); } if (candles.Count == 1 && candles[0].Trades.Count == 0) { return; } _myCandles = candles; int index = _lastCandlesCount - 2; if (index < 0) { index = 0; } for (int i = index; i < candles.Count; i++) { if (candles[i].Trades.Count == 0) { continue; } // take the cluster from the storage, if not, then create a new // берём кластер из хранилища, если нет, то создаём новый if (candles[i].Trades == null || candles[i].Trades.Count == 0) { continue; } HorizontalVolumeCluster cluster = VolumeClusters.Find(c => c.Time == candles[i].TimeStart); if (cluster == null) { cluster = new HorizontalVolumeCluster(_lineStep, Security); VolumeClusters.Add(cluster); cluster.NumCluster = VolumeClusters.Count - 1; cluster.Time = candles[i].TimeStart; cluster.LogMessageEvent += SendNewLogMessage; cluster.MaxSummLineChangeEvent += delegate(HorizontalVolumeLine line) { MaxSummLineChangeEvent?.Invoke(line); }; cluster.MaxBuyLineChangeEvent += delegate(HorizontalVolumeLine line) { MaxBuyLineChangeEvent?.Invoke(line); }; cluster.MaxSellLineChangeEvent += delegate(HorizontalVolumeLine line) { MaxSellLineChangeEvent?.Invoke(line); }; cluster.MaxDeltaLineChangeEvent += delegate(HorizontalVolumeLine line) { MaxDeltaLineChangeEvent?.Invoke(line); }; cluster.MinSummLineChangeEvent += delegate(HorizontalVolumeLine line) { MinSummLineChangeEvent?.Invoke(line); }; cluster.MinBuyLineChangeEvent += delegate(HorizontalVolumeLine line) { MinBuyLineChangeEvent?.Invoke(line); }; cluster.MinSellLineChangeEvent += delegate(HorizontalVolumeLine line) { MinSellLineChangeEvent?.Invoke(line); }; cluster.MinDeltaLineChangeEvent += delegate(HorizontalVolumeLine line) { MinDeltaLineChangeEvent?.Invoke(line); }; cluster.NewLineCreateEvent += delegate(HorizontalVolumeLine line) { VolumeClusterLines.Add(line); }; } // upload the cluster with data // прогружаем кластер данными cluster.Process(candles[i].Trades); // calculate the maximum / minimum clusters // рассчитываем максимальные / минимальные кластеры if (MaxSummVolumeCluster == null || cluster.MaxSummVolumeLine.VolumeSumm > MaxSummVolumeCluster.MaxSummVolumeLine.VolumeSumm) { MaxSummVolumeCluster = cluster; MaxSummClusterChangeEvent?.Invoke(cluster); } if (MinSummVolumeCluster == null || cluster.MinSummVolumeLine.VolumeSumm < MinSummVolumeCluster.MinSummVolumeLine.VolumeSumm) { MinSummVolumeCluster = cluster; MinSummClusterChangeEvent?.Invoke(cluster); } // if (MaxBuyVolumeCluster == null || cluster.MaxBuyVolumeLine.VolumeBuy > MaxBuyVolumeCluster.MaxBuyVolumeLine.VolumeBuy) { MaxBuyVolumeCluster = cluster; MaxBuyClusterChangeEvent?.Invoke(cluster); } if (MinBuyVolumeCluster == null || cluster.MinBuyVolumeLine.VolumeBuy < MinBuyVolumeCluster.MinBuyVolumeLine.VolumeBuy) { MinBuyVolumeCluster = cluster; MinBuyClusterChangeEvent?.Invoke(cluster); } // if (MaxSellVolumeCluster == null || cluster.MaxSellVolumeLine.VolumeSell > MaxSellVolumeCluster.MaxSellVolumeLine.VolumeSell) { MaxSellVolumeCluster = cluster; MaxSellClusterChangeEvent?.Invoke(cluster); } if (MinSellVolumeCluster == null || cluster.MinSellVolumeLine.VolumeSell < MinSellVolumeCluster.MinSellVolumeLine.VolumeSell) { MinSellVolumeCluster = cluster; MinSellClusterChangeEvent?.Invoke(cluster); } // if (MaxDeltaVolumeCluster == null || cluster.MaxDeltaVolumeLine.VolumeDelta > MaxDeltaVolumeCluster.MaxDeltaVolumeLine.VolumeDelta) { MaxDeltaVolumeCluster = cluster; MaxDeltaClusterChangeEvent?.Invoke(cluster); } if (MinDeltaVolumeCluster == null || cluster.MinDeltaVolumeLine.VolumeDelta < MinDeltaVolumeCluster.MinDeltaVolumeLine.VolumeDelta) { MinDeltaVolumeCluster = cluster; MinDeltaClusterChangeEvent?.Invoke(cluster); } // if (MaxPriceCluster == null || cluster.MaxPriceLine.Price > MaxPriceCluster.MaxPriceLine.Price) { MaxPriceCluster = cluster; } if (MinPriceCluster == null || cluster.MinPriceLine.Price < MinPriceCluster.MinPriceLine.Price) { MinPriceCluster = cluster; } } _lastCandlesCount = candles.Count; }
/// <summary> /// constructor / /// конструктор /// </summary> /// <param name="name">bot name / имя робота</param> /// <param name="startProgram">class creating program / программа создающая класс</param> public BotTabCluster(string name, StartProgram startProgram) { TabName = name; _startProgram = startProgram; CandleConnector = new ConnectorCandles(name, _startProgram); CandleConnector.LastCandlesChangeEvent += Tab_LastCandlesChangeEvent; CandleConnector.SecuritySubscribeEvent += CandleConnector_SecuritySubscribeEvent; CandleConnector.LogMessageEvent += SendNewLogMessage; _horizontalVolume = new HorizontalVolume(name); _horizontalVolume.MaxSummClusterChangeEvent += delegate(HorizontalVolumeCluster line) { MaxSummClusterChangeEvent?.Invoke(line); }; _horizontalVolume.MaxBuyClusterChangeEvent += delegate(HorizontalVolumeCluster line) { MaxBuyClusterChangeEvent?.Invoke(line); }; _horizontalVolume.MaxSellClusterChangeEvent += delegate(HorizontalVolumeCluster line) { MaxSellClusterChangeEvent?.Invoke(line); }; _horizontalVolume.MaxDeltaClusterChangeEvent += delegate(HorizontalVolumeCluster line) { MaxDeltaClusterChangeEvent?.Invoke(line); }; _horizontalVolume.MinSummClusterChangeEvent += delegate(HorizontalVolumeCluster line) { MinSummClusterChangeEvent?.Invoke(line); }; _horizontalVolume.MinBuyClusterChangeEvent += delegate(HorizontalVolumeCluster line) { MinBuyClusterChangeEvent?.Invoke(line); }; _horizontalVolume.MinSellClusterChangeEvent += delegate(HorizontalVolumeCluster line) { MinSellClusterChangeEvent?.Invoke(line); }; _horizontalVolume.MinDeltaClusterChangeEvent += delegate(HorizontalVolumeCluster line) { MinDeltaClusterChangeEvent?.Invoke(line); }; _horizontalVolume.MaxSummLineChangeEvent += delegate(HorizontalVolumeLine line) { MaxSummLineChangeEvent?.Invoke(line); }; _horizontalVolume.MaxBuyLineChangeEvent += delegate(HorizontalVolumeLine line) { MaxBuyLineChangeEvent?.Invoke(line); }; _horizontalVolume.MaxSellLineChangeEvent += delegate(HorizontalVolumeLine line) { MaxSellLineChangeEvent?.Invoke(line); }; _horizontalVolume.MaxDeltaLineChangeEvent += delegate(HorizontalVolumeLine line) { MaxDeltaLineChangeEvent?.Invoke(line); }; _horizontalVolume.MinSummLineChangeEvent += delegate(HorizontalVolumeLine line) { MinSummLineChangeEvent?.Invoke(line); }; _horizontalVolume.MinBuyLineChangeEvent += delegate(HorizontalVolumeLine line) { MinBuyLineChangeEvent?.Invoke(line); }; _horizontalVolume.MinSellLineChangeEvent += delegate(HorizontalVolumeLine line) { MinSellLineChangeEvent?.Invoke(line); }; _horizontalVolume.MinDeltaLineChangeEvent += delegate(HorizontalVolumeLine line) { MinDeltaLineChangeEvent?.Invoke(line); }; _chartMaster = new ChartClusterMaster(name, startProgram, _horizontalVolume); _chartMaster.LogMessageEvent += SendNewLogMessage; }
/// <summary> /// volume updating method not considered trades /// метод обновляющий объёмы не учтёными трейдами /// </summary> private void ReloadLines() { _neadToRebuidVolume = false; lock (_tradesArrayLocker) { try { for (int i = 0; i < _tradesNew.Count; i++) { HorizontalVolumeLine curLine = null; decimal linePrice = Round(_tradesNew[i].Price); curLine = _lines.Find(l => l.Price == linePrice); if (curLine == null) { curLine = new HorizontalVolumeLine(); curLine.TimeFirstTrade = _tradesNew[i].Time; curLine.Price = linePrice; curLine.TimeCandle = Time; curLine.NumCluster = NumCluster; for (int i2 = 0; i2 < _lines.Count; i2++) { if (curLine.Price < _lines[i2].Price) { _lines.Insert(i2, curLine); break; } if (i2 + 1 == _lines.Count) { _lines.Add(curLine); break; } } if (_lines.Count == 0) { _lines.Add(curLine); } if (NewLineCreateEvent != null) { NewLineCreateEvent(curLine); } } curLine.TimeLastTrade = _tradesNew[i].Time; curLine.Trades.Add(_tradesNew[i]); curLine.VolumeSumm += _tradesNew[i].Volume; _lastUpdateLine = curLine; if (_tradesNew[i].Side == Side.Buy) { curLine.VolumeBuy += _tradesNew[i].Volume; curLine.VolumeDelta += _tradesNew[i].Volume; } else if (_tradesNew[i].Side == Side.Sell) { curLine.VolumeSell += _tradesNew[i].Volume; curLine.VolumeDelta -= _tradesNew[i].Volume; } // if (_maxVolumeSummLine == null || curLine.VolumeSumm > _maxVolumeSummLine.VolumeSumm) { _maxVolumeSummLine = curLine; MaxSummLineChangeEvent?.Invoke(_maxVolumeSummLine); } if (_minVolumeSummLine == null || curLine.VolumeSumm < _minVolumeSummLine.VolumeSumm) { _minVolumeSummLine = curLine; MinSummLineChangeEvent?.Invoke(_minVolumeSummLine); } // if (_maxVolumeBuyLine == null || curLine.VolumeBuy > _maxVolumeBuyLine.VolumeBuy) { _maxVolumeBuyLine = curLine; MaxBuyLineChangeEvent?.Invoke(_maxVolumeBuyLine); } if (_minVolumeBuyLine == null || curLine.VolumeBuy < _minVolumeBuyLine.VolumeBuy) { _minVolumeBuyLine = curLine; MinBuyLineChangeEvent?.Invoke(_minVolumeBuyLine); } // if (_maxVolumeSellLine == null || curLine.VolumeSell > _maxVolumeSellLine.VolumeSell) { _maxVolumeSellLine = curLine; MaxSellLineChangeEvent?.Invoke(_maxVolumeSellLine); } if (_minVolumeSellLine == null || curLine.VolumeSell < _minVolumeSellLine.VolumeSell) { _minVolumeSellLine = curLine; MinSellLineChangeEvent?.Invoke(_minVolumeSellLine); } // if (_maxVolumeDeltaLine == null || curLine.VolumeDelta > _maxVolumeDeltaLine.VolumeDelta) { _maxVolumeDeltaLine = curLine; MaxDeltaLineChangeEvent?.Invoke(_maxVolumeDeltaLine); } if (_minVolumeDeltaLine == null || curLine.VolumeDelta < _minVolumeDeltaLine.VolumeDelta) { _minVolumeDeltaLine = curLine; MinDeltaLineChangeEvent?.Invoke(_minVolumeDeltaLine); } // if (_maxPriceLine == null || curLine.Price > _maxPriceLine.Price) { _maxPriceLine = curLine; } if (_minPriceLine == null || curLine.Price < _minPriceLine.Price) { _minPriceLine = curLine; } } _tradesNew.Clear(); } catch (Exception e) { SendNewLogMessage(e.ToString(), LogMessageType.Error); } } }