예제 #1
0
        public void SignAndNullReplacing()
        {
            var    resolver = new ExpressionResolver("sign(a ?? 5)");
            double result;
            var    vars = new Dictionary <string, double> {
                { "a", 0 }
            };
            var ret = resolver.Calculate(vars, out result);

            Assert.IsTrue(ret, resolver.Formula);
            Assert.AreEqual(Math.Sign(vars["a"] == 0 ? 5 : vars["a"]), result, resolver.Formula);
            vars["a"] = -1;
            ret       = resolver.Calculate(vars, out result);
            Assert.IsTrue(ret, resolver.Formula);
            Assert.AreEqual(Math.Sign(vars["a"] == 0 ? 5 : vars["a"]), result, resolver.Formula);
        }
예제 #2
0
        private void CalcButtonClick(object sender, EventArgs e)
        {
            if (!CheckFormula())
            {
                resultLabel.Text = "Ошибка в формуле";
                return;
            }
            var resolver = new ExpressionResolver(Formula.ToLower());
            var values   = new Dictionary <string, double>();

            foreach (var row in argumentsFastGrid.rows)
            {
                var arg = (FormulaArgument)row.ValueObject;
                values.Add(arg.Name.ToLower(), (double)arg.Value);
            }
            double result;
            var    resultFlag = resolver.Calculate(values, out result);

            if (!resultFlag)
            {
                resultLabel.Text = "Ошибка в расчете по формуле";
                return;
            }
            resultLabel.Text = result == 0 ? "Нет входа в рынок" : "Вход в рынок";
        }
예제 #3
0
        public static double Calculate(ExpressionResolver resolver, PerformerStat stat)
        {
            var ptrVal = new Dictionary <string, double>();

            try
            {
                foreach (var varName in resolver.GetVariableNames())
                {
                    var    val  = PerformerCriteriaFunctionCollection.Instance.propertyByVariable[varName].GetValue(stat, null);
                    double dVal = val is float
                                  ?(float)val
                                  : val is double
                                  ?(double)val
                                  : val is int?(int)val : val is decimal ? (float)(decimal)val : 0;
                    ptrVal.Add(varName, dVal);
                }
                double rst;
                resolver.Calculate(ptrVal, out rst);
                return(rst);
            }
            catch (Exception ex)
            {
                Logger.Error("Ошибка в Calculate(" + stat.Account + ")", ex);
                return(0);
            }
        }
예제 #4
0
        public void AdditionAndVarDisparity()
        {
            var    resolver = new ExpressionResolver("a + b + c");
            double result;
            var    vars = new Dictionary <string, double>();

            vars.Add("a", 1);
            vars.Add("b", 2);
            var ret = resolver.Calculate(vars, out result);

            Assert.IsFalse(ret, resolver.Formula + " lack of args");
            vars.Add("c", 3);
            ret = resolver.Calculate(vars, out result);
            Assert.IsTrue(ret, resolver.Formula);
            Assert.AreEqual(vars["a"] + vars["b"] + vars["c"], result, resolver.Formula);
            vars.Add("d", 4);
            ret = resolver.Calculate(vars, out result);
            Assert.IsTrue(ret, resolver.Formula + " excess of args");
        }
예제 #5
0
        public void Trigonometrical()
        {
            var    resolver = new ExpressionResolver("sin(a) / cos(a) - tan(a)");
            double result;
            var    vars = new Dictionary <string, double>();

            vars.Add("a", 0.3);
            var ret = resolver.Calculate(vars, out result);

            Assert.IsTrue(ret, resolver.Formula);
            Assert.AreEqual(Math.Sin(vars["a"]) / Math.Cos(vars["a"]) - Math.Tan(vars["a"]), result, resolver.Formula);
        }
예제 #6
0
        public void Logarithmic()
        {
            var    resolver = new ExpressionResolver("2.71 ^ ln(a) + 10 ^ lg(b)");
            double result;
            var    vars = new Dictionary <string, double>();

            vars.Add("a", 2);
            vars.Add("b", 3);
            var ret = resolver.Calculate(vars, out result);

            Assert.IsTrue(ret, resolver.Formula);
            Assert.AreEqual(Math.Pow(2.71, Math.Log(vars["a"])) + Math.Pow(10, Math.Log10(vars["b"])), result, resolver.Formula);
        }
예제 #7
0
        public void BracketDisparity()
        {
            var    resolver = new ExpressionResolver("(a + (b) * c");
            double result;
            var    vars = new Dictionary <string, double>();

            vars.Add("a", 1);
            vars.Add("b", 1);
            vars.Add("c", 1);
            var ret = resolver.Calculate(vars, out result);

            Assert.IsFalse(ret, resolver.Formula);
        }
예제 #8
0
        public void MultiplicationAndDivision()
        {
            var    resolver = new ExpressionResolver("a * b / c");
            double result;
            var    vars = new Dictionary <string, double>();

            vars.Add("a", 3);
            vars.Add("b", 4);
            vars.Add("c", 6);
            var ret = resolver.Calculate(vars, out result);

            Assert.IsTrue(ret, resolver.Formula);
            Assert.AreEqual(vars["a"] * vars["b"] / vars["c"], result, resolver.Formula);
        }
예제 #9
0
        public void SubtractionNegationAndSpacing()
        {
            var    resolver = new ExpressionResolver("-a -  -b - c");
            double result;
            var    vars = new Dictionary <string, double>();

            vars.Add("a", 1);
            vars.Add("b", 1);
            vars.Add("c", 1);
            var ret = resolver.Calculate(vars, out result);

            Assert.IsTrue(ret, resolver.Formula);
            Assert.AreEqual(-vars["a"] - -vars["b"] - vars["c"], result, resolver.Formula);
        }
예제 #10
0
        public void Logical()
        {
            var    resolver = new ExpressionResolver("a & b | c");
            double result;
            var    vars = new Dictionary <string, double>();

            vars.Add("a", 1);
            vars.Add("b", 0);
            vars.Add("c", 1);
            var ret = resolver.Calculate(vars, out result);

            Assert.IsTrue(ret, resolver.Formula);
            Assert.AreEqual(1, result, resolver.Formula);
        }
예제 #11
0
        public void Comparison()
        {
            var    resolver = new ExpressionResolver("a > b = c < d");
            double result;
            var    vars = new Dictionary <string, double>();

            vars.Add("a", 1);
            vars.Add("b", 2);
            vars.Add("c", 4);
            vars.Add("d", 3);
            var ret = resolver.Calculate(vars, out result);

            Assert.IsTrue(ret, resolver.Formula);
            var expected = vars["a"] > vars["b"] == vars["c"] < vars["d"];

            Assert.AreEqual(expected ? 1 : 0, result, resolver.Formula);
        }
예제 #12
0
        public void TestIndexFunction()
        {
            var    resolver = new ExpressionResolver("(close-close#40)*2");
            double result;
            var    vars = new Dictionary <string, double>
            {
                { "close", 1.35 },
                { "close#40", 1.34 }
            };
            var ret = resolver.Calculate(vars, out result);

            Assert.IsTrue(ret, resolver.Formula);

            const double resultRight = (1.35 - 1.34) * 2;
            var          delta       = Math.Abs(resultRight - result);

            Assert.Less(delta, 0.000001, "IndexFunction is calculated right");
        }
        public void CheckCondition()
        {
            IsTriggered = false;

            if (resolver == null)
            {
                return;
            }

            // получить значения переменных
            var varVal  = new Dictionary <string, double>();
            var timeNow = DateTime.Now;
            var quotes  = QuoteStorage.Instance.ReceiveAllData().ToDictionary(q => q.Key.ToLower(), q => q.Value);

            foreach (var ptrName in formulaParams)
            {
                var ptrVal = ExpressionResolverLiveParams.GetParamValue(ptrName, timeNow, false);
                if (ptrVal.HasValue)
                {
                    varVal.Add(ptrName, ptrVal.Value);
                    continue;
                }
                // получить котировку
                QuoteData quote;
                quotes.TryGetValue(ptrName.ToLower(), out quote);
                varVal.Add(ptrName, quote == null ? 0 : (quote.ask + quote.bid) * 0.5);
            }

            double result;

            try
            {
                resolver.Calculate(varVal, out result);
            }
            catch
            {
                result = 0;
            }

            // не 0 есть "истина"
            IsTriggered = result != 0;
        }
예제 #14
0
        private void BtnResultClick(object sender, EventArgs e)
        {
            // посчитать результат
            var ptrVal = grid.GetRowValues <ExpressionParameter>(false).ToDictionary(p => p.Name, p => p.Value);

            try
            {
                double rst;
                if (!resolver.Calculate(ptrVal, out rst))
                {
                    lblResult.Text = "?";
                    return;
                }
                lblResult.Text = rst.ToString();
            }
            catch (Exception ex)
            {
                lblResult.Text = ex.Message;
            }
        }
예제 #15
0
        public void CalculateValue(string[] tickerNames, List <CandleData> candles,
                                   Dictionary <string, List <double> > lastBidLists,
                                   DateTime curTime, Random randomGener)
        {
            if (resolver == null)
            {
                return;
            }
            // посчитать индекс
            double index;

            varValues = GetVariableValues(tickerNames, candles, lastBidLists, curTime, randomGener);
            if (resolver.Calculate(varValues, out index))
            {
                if (double.IsNaN(index))
                {
                    lastIndexValue = NanReplacement;
                }
                else
                {
                    lastIndexValue = index;
                }
            }
        }
예제 #16
0
        private void BtnMakeIndexClick(object sender, EventArgs e)
        {
            ExpressionResolver resv;

            try
            {
                resv = new ExpressionResolver(tbTickerFormula.Text);
            }
            catch (Exception ex)
            {
                Logger.Error("Ошибка разбора выражения", ex);
                MessageBox.Show(string.Format("Ошибка разбора выражения ({0})", ex.Message));
                return;
            }

            if (saveFileDialog.ShowDialog() != DialogResult.OK)
            {
                return;
            }
            var fileName = saveFileDialog.FileName;

            var names = resv.GetVariableNames();
            var curs  = new BacktestTickerCursor();

            try
            {
                curs.SetupCursor(quoteFolder, names, dpStart.Value);
            }
            catch (Exception ex)
            {
                Logger.Error("Ошибка установки курсора", ex);
                return;
            }

            StreamWriter sw;

            try
            {
                sw = new StreamWriter(fileName);
            }
            catch (Exception ex)
            {
                Logger.Error("Ошибка открытия файла на запись", ex);
                curs.Close();
                MessageBox.Show("Ошибка открытия файла на запись");
                return;
            }
            var saver = new QuoteSaver(tbTicker.Text);

            try
            {
                while (true)
                {
                    // посчитать индекс
                    var quotes = curs.GetCurrentQuotes();
                    if (quotes.Count == 0)
                    {
                        continue;
                    }
                    var date = quotes.Max(q => q.b.time);

                    var    quoteDic = quotes.ToDictionary(q => q.a, q => (double)q.b.bid);
                    double result;
                    resv.Calculate(quoteDic, out result);

                    // занести индекс в файл
                    saver.SaveQuote(sw, (float)result, (float)result, date);

                    if (!curs.MoveNext())
                    {
                        break;
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error("Ошибка формирования индекса", ex);
            }
            finally
            {
                curs.Close();
                sw.Close();
            }

            MessageBox.Show("Формирование индекса завершено");
            openFileDialog.FileName = saveFileDialog.FileName;
        }
예제 #17
0
        public override List <string> OnQuotesReceived(string[] names, QuoteData[] quotes, bool isHistoryStartOff)
        {
            if (formulaResolver == null || packer == null)
            {
                return(null);
            }
            curTime = quotes[0].time;

            // обновить табличку цен
            for (var i = 0; i < names.Length; i++)
            {
                if (lastBids.ContainsKey(names[i]))
                {
                    lastBids[names[i]] = quotes[i].bid;
                }
                else
                {
                    lastBids.Add(names[i], quotes[i].bid);
                }
            }

            QuoteData curQuote = null;

            for (var i = 0; i < names.Length; i++)
            {
                if (names[i] == ticker)
                {
                    curQuote = quotes[i];
                    break;
                }
            }

            if (curQuote == null)
            {
                return(null);                  // нет торгуемой котировки
            }
            // обновить свечки
            var candle = packer.UpdateCandle(curQuote.bid, curQuote.time);
            Dictionary <string, double> varValues = null;

            if (candle != null)
            {
                candles.Add(candle);
                countCandles++;
                // обновить очереди (для индекса, переменные вида usdjpy#15)
                if (lastBidLists.Count > 0)
                {
                    foreach (var listTicker in lastBidLists)
                    {
                        float price;
                        if (!lastBids.TryGetValue(listTicker.Key, out price))
                        {
                            price = 0;
                        }
                        listTicker.Value.Add(price);
                    }
                }
                // посчитать индекс
                double index;
                varValues = GetVariableValues();
                if (formulaResolver.Calculate(varValues, out index))
                {
                    lastIndexValue = double.IsNaN(index) ? 0 : (float)index;
                }
                lastIndicies.Add(lastIndexValue ?? 0);
            }

            // если это период "разгона" конвейера
            if (isHistoryStartOff)
            {
                return(null);
            }

            RobotHint hint = null;

            // получить знак дивергенции
            if (candle != null)
            {
                string             commentOnDivergence = string.Empty;
                var                divergenceSign      = GetDivergenceSign(out commentOnDivergence);
                List <MarketOrder> orders;
                robotContext.GetMarketOrders(robotContext.accountInfo.ID, out orders);
                if (divergenceSign != 0)
                {
                    var hintText = new StringBuilder();
                    hintText.AppendLine(commentOnDivergence);
                    hintText.AppendLine("Переменные:");
                    // ReSharper disable PossibleNullReferenceException)
                    foreach (var pair in varValues)
                    // ReSharper restore PossibleNullReferenceException
                    {
                        hintText.AppendLine(string.Format("{1}{0}{2:f4}", (char)9, pair.Key, pair.Value));
                    }

                    hint = new RobotHint(Graphics[0].a, Graphics[0].b.ToString(),
                                         hintText.ToString(), divergenceSign > 0 ? "BUY" : "SELL", "e", curQuote.bid)
                    {
                        Time = candle.timeOpen,
                        //curTime
                        ColorFill     = divergenceSign > 0 ? Color.Green : Color.Red,
                        ColorLine     = Color.Black,
                        RobotHintType = divergenceSign > 0
                                                       ? RobotHint.HintType.Покупка
                                                       : RobotHint.HintType.Продажа
                    };

                    // если получен сигнал на покупку - купить, закрыв продажи
                    // наоборот, если получен сигнал на продажу - продать, закрыв покупки
                    var ordersToClose = orders.FindAll(o => o.Side != divergenceSign);
                    foreach (var order in ordersToClose)
                    {
                        robotContext.SendCloseRequest(CurrentProtectedContext.Instance.MakeProtectedContext(),
                                                      robotContext.accountInfo.ID, order.ID, PositionExitReason.ClosedByRobot);
                    }

                    // открыть позу в направлении знака дивера
                    decimal?stop = StopLossPoints == 0
                                        ? (decimal?)null
                                        : (decimal)curQuote.bid -
                                   divergenceSign * DalSpot.Instance.GetAbsValue(ticker, (decimal)StopLossPoints);
                    decimal?take = TakeProfitPoints == 0
                                        ? (decimal?)null
                                        : (decimal)curQuote.bid +
                                   divergenceSign * DalSpot.Instance.GetAbsValue(ticker, (decimal)TakeProfitPoints);

                    robotContext.SendNewOrderRequest(CurrentProtectedContext.Instance.MakeProtectedContext(),
                                                     RequestUniqueId.Next(), robotContext.accountInfo.ID, Magic, ticker, Volume,
                                                     divergenceSign, OrderType.Market, 0, 0,
                                                     stop, take, null, null, string.Empty, "OscillatorBasedRobot");
                }
            }

            return(hint != null ? new List <string> {
                hint.ToString()
            } : null);
        }
예제 #18
0
        public void LogicalExpression()
        {
            var expressionResult = new Dictionary <string, Cortege2 <Dictionary <string, double>, double> >
            {
                {
                    "~a", new Cortege2 <Dictionary <string, double>, double>(new Dictionary <string, double>
                    {
                        { "a", 1 }
                    }, 0)
                },
                {
                    "a&~b", new Cortege2 <Dictionary <string, double>, double>(new Dictionary <string, double>
                    {
                        { "a", 1 },
                        { "b", 0 }
                    }, 1)
                },
                {
                    "~c!=~b", new Cortege2 <Dictionary <string, double>, double>(new Dictionary <string, double>
                    {
                        { "b", 1 },
                        { "c", 0 }
                    }, 1)
                },
                {
                    "(a=~b)&({c!=a}||~c)", new Cortege2 <Dictionary <string, double>, double>(new Dictionary <string, double>
                    {
                        { "a", 1 },
                        { "b", 0 },
                        { "c", 1 }       // not 0 therefore true
                    }, 0)
                },
                {
                    "(a = ~b) & ({c != a} || ~c)", new Cortege2 <Dictionary <string, double>, double>(new Dictionary <string, double>
                    {
                        { "a", 1 },
                        { "b", 0 },
                        { "c", 0 }       // not 0 therefore true
                    }, 1)
                },
                {
                    "(_pi&1)=(b&b)", new Cortege2 <Dictionary <string, double>, double>(new Dictionary <string, double>
                    {
                        { "b", 1 },
                    }, 1)
                }
            };

            foreach (var exRst in expressionResult)
            {
                var expression = exRst.Key;

                ExpressionResolver resolver;
                try
                {
                    resolver = new ExpressionResolver(expression);
                }
                catch (Exception ex)
                {
                    Assert.Fail("\"" + expression + "\" не распознано: " + ex);
                    continue;
                }

                var vars     = exRst.Value.a;
                var expected = exRst.Value.b;
                try
                {
                    double result;
                    var    rst = resolver.Calculate(vars, out result);
                    Assert.IsTrue(rst, expression + " is calculated");
                    Assert.AreEqual(expected, result, expression + " should be equal " + expected);
                }
                catch (Exception ex)
                {
                    Assert.Fail(expression + ": exception while calculate: " + ex);
                }
            }
        }
예제 #19
0
        private void BtnMakeIndexClick(object sender, EventArgs e)
        {
            ExpressionResolver resv;
            try
            {
                resv = new ExpressionResolver(tbTickerFormula.Text);
            }
            catch (Exception ex)
            {
                Logger.Error("Ошибка разбора выражения", ex);
                MessageBox.Show(string.Format("Ошибка разбора выражения ({0})", ex.Message));
                return;
            }

            if (saveFileDialog.ShowDialog() != DialogResult.OK) return;
            var fileName = saveFileDialog.FileName;

            var names = resv.GetVariableNames();
            var curs = new BacktestTickerCursor();
            try
            {
                curs.SetupCursor(quoteFolder, names, dpStart.Value);
            }
            catch (Exception ex)
            {
                Logger.Error("Ошибка установки курсора", ex);
                return;
            }

            StreamWriter sw;
            try
            {
                sw = new StreamWriter(fileName);
            }
            catch (Exception ex)
            {
                Logger.Error("Ошибка открытия файла на запись", ex);
                curs.Close();
                MessageBox.Show("Ошибка открытия файла на запись");
                return;
            }
            var saver = new QuoteSaver(tbTicker.Text);

            try
            {
                while (true)
                {
                    // посчитать индекс
                    var quotes = curs.GetCurrentQuotes();
                    if (quotes.Count == 0) continue;
                    var date = quotes.Max(q => q.b.time);

                    var quoteDic = quotes.ToDictionary(q => q.a, q => (double)q.b.bid);
                    double result;
                    resv.Calculate(quoteDic, out result);

                    // занести индекс в файл
                    saver.SaveQuote(sw, (float)result, (float)result, date);

                    if (!curs.MoveNext()) break;
                }
            }
            catch (Exception ex)
            {
                Logger.Error("Ошибка формирования индекса", ex);
            }
            finally
            {
                curs.Close();
                sw.Close();
            }

            MessageBox.Show("Формирование индекса завершено");
            openFileDialog.FileName = saveFileDialog.FileName;
        }
예제 #20
0
        private List <string> ProcessQuotes(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff)
        {
            var result = new List <string>();

            // дописываем лог
            foreach (var m in pendingLogMessages.Where(e => !logMessages.Contains(e)))
            {
                logMessages.Add(m);
                result.Add(MakeLog(m));
            }

            // проверяем инициализацию
            var message = "не инициализирован, остановлен";

            if (newsSettings == null || currencySettings == null)
            {
                if (!logMessages.Contains(message))
                {
                    logMessages.Add(message);
                    result.Add(MakeLog(message));
                }
                return(result);
            }

            // all ok inform
            // информируем о начале работы
            message = "запущен";
            if (!logMessages.Contains(message))
            {
                logMessages.Add(message);
                result.Add(MakeLog(message));
            }

            // saving to cache
            // сохраняем кэш котировок
            for (var i = 0; i < names.Length; i++)
            {
                var name = names[i];
                if (!quoteStorage.ContainsKey(name))
                {
                    quoteStorage.Add(name, new List <QuoteData>());
                }
                quoteStorage[name].Add(quotes[i].GetCloseQuote());
            }

            // if this call is used for caching quotes - exiting
            // если мы в режиме наполнения кэша - выходим
            if (isHistoryStartOff)
            {
                return(result);
            }

            // detemining model time
            // определение модельного времени
            if (quotes.Length == 0)
            {
                return(result);
            }
            var now = quotes[0].timeClose;

            // update orders' SL & TP
            // обновляем сделки
            List <MarketOrder> orders;

            robotContext.GetMarketOrders(robotContext.AccountInfo.ID, out orders);
            result.AddRange(UpdateOrders(now, orders));

            // working with news
            // make GrabNews calls unfrequent
            // сокращаем частоту вызовов GrabNews
            if ((now - lastGrabNewsCall.GetLastHit()).TotalSeconds < PauseForNewsReadingSeconds)
            {
                return(result);
            }
            var grab = true;                                        // in present - grab each PauseForNewsReadingSeconds

            if (now.Date < DateTime.Today)                          // working in the past (testing)
            {
                if (now.Date == lastGrabNewsCall.GetLastHit().Date) // grabbing only once in day
                {
                    grab = false;
                }
            }
            // grabbing
            // извлечение с Alpari
            if (grab)
            {
                List <string> parseErrors;
                var           news = GrabNews(new DateTime(now.Year, now.Month, now.Day), out parseErrors);
                foreach (var m in parseErrors.Where(e => !logMessages.Contains(e)))
                {
                    logMessages.Add(m);
                    result.Add(MakeLog(m));
                }
                if (news.Count == 0)
                {
                    logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error,
                                                          LogMsgNoNewsParsed, 1000 * 60 * 5, "Прочитано 0 новостей");
                }
                else
                {
                    logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Info,
                                                          LogMsgNewsParsed, 1000 * 60 * 5, "Прочитано {0} новостей",
                                                          news.Count);
                }
                freshNews.AddRange(news);
                lastGrabNewsCall.SetTime(now);
            }
            // processing
            // обработка новостей (внешний цикл)
            foreach (var curNews in freshNews)
            {
                var currentNews = curNews;

                // сверяем время
                if (oldNews.Contains(currentNews)) // news already processed
                {
                    continue;
                }
                // news obsolete
                // новость устарела
                if ((now - currentNews.Time - new TimeSpan(0, NewsProcessingDelayMinutes, 0)).TotalMinutes > NewsObsolescenceTimeMinutes)
                {
                    oldNews.Add(currentNews);
                    continue;
                }
                // news in future; skip processing
                // придержим новость на будущее
                if (currentNews.Time + new TimeSpan(0, NewsProcessingDelayMinutes, 0) > now)
                {
                    continue;
                }

                var timeNear = currentNews.Time.AddMinutes(TimeNearMinutes);
                var timeFar  = currentNews.Time.AddMinutes(-TimeFarMinutes);

                result.Add(MakeLog("обрабатывается " + currentNews));
                var chatMessage = "\n"; // здесь формируется сообщение в чат
                chatMessage += string.Format("Обрабатывается новость: [{0}] {1}\nВремя: {2}, прогноз: {3}, фактическое: {4}\n",
                                             currentNews.CountryCode, currentNews.Title, currentNews.Time,
                                             currentNews.ProjectedValue, currentNews.Value);

                // calc weights
                // вычисляем веса, определяем знак
                int valueWeight;
                if (currentNews.ProjectedValue > currentNews.Value)
                {
                    valueWeight = -1;
                }
                else if ((currentNews.ProjectedValue < currentNews.Value))
                {
                    valueWeight = 1;
                }
                else
                {
                    valueWeight = 0;
                }
                var delta = currentNews.ProjectedValue == 0
                                ? 100
                                : (int)Math.Abs((currentNews.Value - currentNews.ProjectedValue) / currentNews.ProjectedValue * 100);
                var newsWeight = GetWeight(currentNews.CountryCode, currentNews.Title, delta);
                // 4 debug

                /*if (newsWeight == 0)
                 * {
                 *  message = string.Format("Valuable news not processed: [{0}] {1}", currentNews.CountryCode,
                 *                              currentNews.Title);
                 *  if (!logMessages.Contains(message))
                 *  {
                 *      logMessages.Add(message);
                 *      result.AddRange(MakeLog(message));
                 *  }
                 * }*/
                var sign = valueWeight * newsWeight;
                if (sign == 0)
                {
                    oldNews.Add(currentNews);
                    chatMessage += "Результат: нет входа в рынок\n";
                    chatMessage += "Причина: " +
                                   (newsWeight == 0
                                        ? "вес новости равен 0\n"
                                        : "отклонение экономического показателя равно 0\n");
                    if (SendMessageInRoom != null)
                    {
                        SendMessageInRoom(chatMessage, chatRoom);
                    }
                    continue;
                }

                // gathering tickers for affected currecncies
                // определяем затронутые новостью валютные пары и их знак новостного сигнала
                var tickersAndSigns = new List <Cortege2 <string, int> >();
                var currencies      = currencySettings.Where(c => c.CountryCode == currentNews.CountryCode).Select(c => c.CurrencyCode);
                foreach (var currency in currencies)
                {
                    var cur = currency;
                    var tickersWithBaseCur = Graphics.Where(g => g.a.StartsWith(cur)).Select(g => g.a);
                    tickersAndSigns.AddRange(tickersWithBaseCur.Select(t => new Cortege2 <string, int>(t, sign)).ToList());
                    var tickersWithQuoteCur = Graphics.Where(g => g.a.EndsWith(cur)).Select(g => g.a);
                    tickersAndSigns.AddRange(
                        tickersWithQuoteCur.Select(t => new Cortege2 <string, int>(t, -sign)).ToList());
                }

                // processing tickers
                // работаем с выбранными валютными парами (внутренний цикл)
                foreach (var tickerAndSign in tickersAndSigns)
                {
                    var ticker  = tickerAndSign.a;
                    var curSign = tickerAndSign.b;

                    // определение действующей на этот момент котировки
                    var data = GetDataFromStorage(ticker, currentNews.Time, currentNews.Time.AddMinutes(5));
                    if (data.Count == 0)
                    {
                        chatMessage += "Результат: нет входа в рынок с " + ticker + "\n";
                        chatMessage += "Причина: нет котировки для " + ticker + " в диапазоне от " +
                                       currentNews.Time + " до " + currentNews.Time.AddMinutes(5) + "\n";
                        if (SendMessageInRoom != null)
                        {
                            SendMessageInRoom(chatMessage, chatRoom);
                        }
                        continue;
                    }

                    // опорное значение для определения трендов и величины сделки - цена спроса
                    var value = data[0].bid;

                    // определение тренда
                    int signNear = 0, signFar = 0;
                    data = GetDataFromStorage(ticker, timeNear, timeNear.AddMinutes(5));
                    if (data.Count == 0)
                    {
                        // 4 debug
                        var hint = new RobotHint(ticker, "", "insufficient data for near-trend",
                                                 curSign > 0 ? "BUY no near-data" : "SELL no near-data", "e", value)
                        {
                            Time = now, ColorFill = Color.Red
                        };
                        result.Add(hint.ToString());
                        chatMessage += "Результат: нет входа в рынок с " + ticker + "\n";
                        chatMessage += "Причина: недостаточно данных для определения тренда после выхода новости\n";
                        if (SendMessageInRoom != null)
                        {
                            SendMessageInRoom(chatMessage, chatRoom);
                        }
                        continue;
                    }
                    var valueNear = data[0].bid;
                    if (value > valueNear)
                    {
                        signNear = 1;
                    }
                    else if (value < valueNear)
                    {
                        signNear = -1;
                    }
                    data = GetDataFromStorage(ticker, timeFar, timeFar.AddMinutes(5));
                    if (data.Count == 0)
                    {
                        // 4 debug
                        var hint = new RobotHint(ticker, "", "insufficient data for far-trend",
                                                 curSign > 0 ? "BUY no far-data" : "SELL no far-data", "e", value)
                        {
                            Time = now, ColorFill = Color.Red
                        };
                        result.Add(hint.ToString());
                        chatMessage += "Результат: нет входа в рынок с " + ticker + "\n";
                        chatMessage += "Причина: недостаточно данных для определения тренда до выхода новости\n";
                        if (SendMessageInRoom != null)
                        {
                            SendMessageInRoom(chatMessage, chatRoom);
                        }
                        continue;
                    }
                    var valueFar = data[0].bid;
                    if (value > valueFar)
                    {
                        signFar = 1;
                    }
                    else if (value < valueFar)
                    {
                        signFar = -1;
                    }

                    // определяем необходимость входа в рынок
                    var values = new Dictionary <string, double>();
                    values.Add("tn", curSign);
                    values.Add("tba", signFar);
                    values.Add("tcb", signNear);
                    double formulaResult;
                    var    resultFlag = expressionResolver.Calculate(values, out formulaResult);
                    if (!resultFlag)
                    {
                        result.Add(MakeLog("Ошибка в расчете по формуле для входа в рынок"));
                        chatMessage += "Результат: нет входа в рынок с " + ticker + "\n";
                        chatMessage += "Причина: ошибка в расчете по формуле для входа в рынок\n";
                        if (SendMessageInRoom != null)
                        {
                            SendMessageInRoom(chatMessage, chatRoom);
                        }
                        continue;
                    }

                    // вход в рынок
                    var tradeSign = 0;
                    switch (EnterSign)
                    {
                    case EnterSignEnum.Tn:
                        tradeSign = curSign;
                        break;

                    case EnterSignEnum.NotTn:
                        tradeSign = -curSign;
                        break;

                    case EnterSignEnum.Tba:
                        tradeSign = signFar;
                        break;

                    case EnterSignEnum.NotTba:
                        tradeSign = -signFar;
                        break;

                    case EnterSignEnum.Tcb:
                        tradeSign = signNear;
                        break;

                    case EnterSignEnum.NotTcb:
                        tradeSign = -signNear;
                        break;
                    }
                    if (formulaResult != 0)
                    {
                        // если получен сигнал на покупку - купить, закрыв продажи
                        // наоборот, если получен сигнал на продажу - продать, закрыв покупки
                        robotContext.GetMarketOrders(robotContext.AccountInfo.ID, out orders);
                        var ordersToClose = orders.Where(o => o.Symbol == ticker && o.Side != tradeSign).ToList();
                        foreach (var order in ordersToClose)
                        {
                            robotContext.SendCloseRequest(protectedContext.MakeProtectedContext(),
                                                          robotContext.AccountInfo.ID, order.ID, PositionExitReason.ClosedByRobot);
                        }
                        // создаем ордер
                        var decreaseSl = DalSpot.Instance.GetAbsValue(ticker, (float)InitialSlPoints);
                        var slValue    = value - tradeSign * decreaseSl;
                        var decreaseTp = DalSpot.Instance.GetAbsValue(ticker, (float)InitialTpPoints);
                        var tpValue    = value + tradeSign * decreaseTp;
                        var newOrder   = new MarketOrder
                        {
                            AccountID     = robotContext.AccountInfo.ID,
                            Magic         = Magic,
                            Symbol        = ticker,
                            Volume        = Volume,
                            Side          = tradeSign,
                            StopLoss      = slValue,
                            TakeProfit    = tpValue,
                            ExpertComment = currentNews.Title
                        };

                        var status = robotContext.SendNewOrderRequest(protectedContext.MakeProtectedContext(),
                                                                      RequestUniqueId.Next(),
                                                                      newOrder,
                                                                      OrderType.Market, (decimal)value, 0);
                        if (status != RequestStatus.OK)
                        {
                            var hint = new RobotHint(ticker, "",
                                                     "SendNewOrderRequest error: " +
                                                     EnumFriendlyName <RequestStatus> .GetString(status) + " news: " +
                                                     currentNews,
                                                     tradeSign > 0 ? "BUY error" : "SELL error", "e", value)
                            {
                                Time      = now,
                                ColorFill = Color.Red
                            };
                            result.Add(hint.ToString());
                        }
                        else
                        {
                            var hint = new RobotHint(ticker, "", "SendNewOrderRequest Ok, news: " + currentNews,
                                                     tradeSign > 0 ? "BUY" : "SELL", "i", value)
                            {
                                Time = now, ColorFill = Color.Red
                            };
                            result.Add(MakeLog("вход в рынок по новости " + currentNews));
                            result.Add(hint.ToString());
                            chatMessage += "Результат: вход в рынок: " + (tradeSign > 0 ? "покупка " : "продажа ") + ticker + "\n";
                        }
                    }
                    else
                    {
                        var hint = new RobotHint(ticker, "", "Market condition fulfill failed, news: " + currentNews,
                                                 tradeSign > 0 ? "BUY no condition" : "SELL no condition", "e", value)
                        {
                            Time = now, RobotHintType = RobotHint.HintType.Стоп
                        };
                        result.Add(hint.ToString());
                        chatMessage += "Результат: нет входа в рынок с " + ticker + "\n";
                        chatMessage += "Причина: не выполнено условие входа\n";
                    }
                    if (SendMessageInRoom != null)
                    {
                        SendMessageInRoom(chatMessage, chatRoom);
                    }
                }
                oldNews.Add(currentNews);
            }
            return(result);
        }