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); }
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 ? "Нет входа в рынок" : "Вход в рынок"; }
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); } }
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"); }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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; }
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; } }
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; } } }
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; }
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); }
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); } } }
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; }
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); }