private List <TradeSignal> Calculate(Dictionary <Selection, IEnumerable <Bar> > marketData)
        {
            var signals = new List <TradeSignal>();

            if (State == SignalState.Backtesting)
            {
                foreach (var data in marketData)
                {
                    if (_dataStorage.TryGetValue(data.Key, out var neededValue))
                    {
                        _dataStorage[data.Key] = neededValue.Concat(data.Value);
                    }
                    else
                    {
                        _dataStorage.Add(data.Key, data.Value);
                    }
                }
            }
            else
            {
                _dataStorage = marketData;
            }

            //calculate for each selection
            foreach (var data in _dataStorage)
            {
                if (data.Value.Count() < RequiredBarsCount)
                {
                    continue;
                }

                //MQL Compatibility Methods
                decimal GetCurrentBid() => data.Value.Last()?.CloseBid ?? 0m;
                decimal GetCurrentAsk() => data.Value.Last()?.CloseAsk ?? 0m;
                DateTime GetCurrentDate() => data.Value.Last()?.Date ?? DateTime.Now;

                Bar RatesArray(int index) => data.Value.ElementAt(data.Value.Count() - ++index);

                ///////////////////////////

                var zigZag = new ZigZag();
                zigZag.Init(null, DataProvider);
                zigZag.Calculate(data.Value);
                _zzBuffer = new List <decimal>(zigZag.Series[0].Values.Select(s => (decimal)s.Value));

                _hl[0] = 666;

                if (_hl[0] == 666)
                {
                    var zCount = 0;
                    for (var i = 0; i <= _zzBuffer.Count && zCount <= 3; i++)
                    {
                        if (_zzBuffer[i] == 0)
                        {
                            continue;
                        }

                        _hl[zCount]     = _zzBuffer[i];
                        _hlTime[zCount] = RatesArray(i).Date;
                        zCount++;
                    }

                    _trendDirection = CheckTrend(_hl[0], _hl[1], _hl[2], _hl[3]);
                    _fibo00         = _hl[0];
                    _fibo100        = _hl[1];
                    _fiboBase       = Math.Abs(_fibo100 - _fibo00);
                }

                // high-low points mapping in concequence
                if (_zzBuffer[0] != 0 && _zzBuffer[0] != _hl[0])
                {
                    _hl[3]          = _hl[2];
                    _hl[2]          = _hl[1];
                    _hl[1]          = _hl[0];
                    _hl[0]          = _zzBuffer[0];
                    _hlTime[3]      = _hlTime[2];
                    _hlTime[2]      = _hlTime[1];
                    _hlTime[1]      = _hlTime[0];
                    _hlTime[0]      = RatesArray(0).Date;
                    _trendDirection = CheckTrend(_hl[0], _hl[1], _hl[2], _hl[3]);
                }

                if (BrokerAccounts == null)
                {
                    continue;
                }
                foreach (var brokerAccount in BrokerAccounts)
                {
                    if (GetPositions(brokerAccount, data.Key.Symbol)?.Count != 0)
                    {
                        continue;
                    }

                    switch (_trendDirection)
                    {
                    case 1:
                        _fiboBase = _fibo00 - _fibo100;
                        _fibo23   = _fibo00 - 0.236m * _fiboBase;
                        _fibo38   = _fibo00 - 0.382m * _fiboBase;
                        _fibo61   = _fibo00 - 0.618m * _fiboBase;
                        _fibo76   = _fibo00 - 0.764m * _fiboBase;
                        if (_hl[0] > _fibo00)
                        {
                            _fibo00 = _hl[0];
                            if (_hl[0] - _hl[1] > _fiboBase)
                            {
                                _fibo100 = _hl[1];
                            }
                        }

                        if (_hl[0] < _fibo100)
                        {
                            _fibo00         = _hl[0];
                            _fibo100        = _hl[1];
                            _trendDirection = CheckTrend(_hl[0], _hl[1], _hl[2], _hl[3]);
                        }

                        if (RatesArray(0).MeanClose - _fibo76 > Point * _safetyBuffer &&
                            _fibo76 - RatesArray(1).MeanClose > Point * _safetyBuffer ||
                            RatesArray(0).MeanClose - _fibo61 > Point * _safetyBuffer &&
                            _fibo61 - RatesArray(1).MeanClose > Point * _safetyBuffer ||
                            RatesArray(0).MeanClose - _fibo38 > Point * _safetyBuffer &&
                            _fibo38 - RatesArray(1).MeanClose > Point * _safetyBuffer ||
                            RatesArray(0).MeanClose - _fibo23 > Point * _safetyBuffer &&
                            _fibo23 - RatesArray(1).MeanClose > Point * _safetyBuffer)
                        {
                            var signal = TradeCheck(1, data.Key, GetCurrentBid(), GetCurrentAsk(), GetCurrentDate());
                            if (signal != null)
                            {
                                signals.Add(signal);
                            }
                        }

                        break;

                    case -1:
                        _fiboBase = _fibo100 - _fibo00;
                        _fibo23   = _fibo00 + 0.236m * _fiboBase;
                        _fibo38   = _fibo00 + 0.382m * _fiboBase;
                        _fibo61   = _fibo00 + 0.618m * _fiboBase;
                        _fibo76   = _fibo00 + 0.764m * _fiboBase;
                        if (_hl[0] < _fibo00)
                        {
                            _fibo00 = _hl[0];
                            if (_hl[1] - _hl[0] > _fiboBase)
                            {
                                _fibo100 = _hl[1];
                            }
                        }

                        if (_hl[0] > _fibo100)
                        {
                            _fibo00         = _hl[0];
                            _fibo100        = _hl[1];
                            _trendDirection = CheckTrend(_hl[0], _hl[1], _hl[2], _hl[3]);
                        }

                        if (_fibo76 - RatesArray(0).MeanClose > Point * _safetyBuffer &&
                            _fibo76 - RatesArray(1).MeanClose < Point * _safetyBuffer ||
                            _fibo61 - RatesArray(0).MeanClose > Point * _safetyBuffer &&
                            _fibo61 - RatesArray(1).MeanClose < Point * _safetyBuffer ||
                            _fibo38 - RatesArray(0).MeanClose > Point * _safetyBuffer &&
                            _fibo38 - RatesArray(1).MeanClose < Point * _safetyBuffer ||
                            _fibo23 - RatesArray(0).MeanClose > Point * _safetyBuffer &&
                            _fibo23 - RatesArray(1).MeanClose < Point * _safetyBuffer)
                        {
                            var signal = TradeCheck(-1, data.Key, GetCurrentBid(), GetCurrentAsk(), GetCurrentDate());
                            if (signal != null)
                            {
                                signals.Add(signal);
                            }
                        }

                        break;

                    case 0:
                        _fiboBase = 0;
                        _fibo23   = 0;
                        _fibo38   = 0;
                        _fibo61   = 0;
                        _fibo76   = 0;
                        break;
                    }
                }
            }

            return(signals);
        }