public override void Initialize(BacktestServerProxy.RobotContext grobotContext, CurrentProtectedContext protectedContext) { base.Initialize(grobotContext, protectedContext); // проверка настроек графиков if (Graphics.Count == 0) { Logger.DebugFormat("Atracotes MTS: настройки графиков не заданы"); return; } if (Graphics.Count > 1) { Logger.DebugFormat("Atracotes MTS: настройки графиков должны описывать один тикер / один ТФ"); return; } ticker = Graphics[0].a; lastBids = new Dictionary <string, double>(); foreach (var ind in IndexList) { ind.Initialize(); ind.lastIndicies = new List <double>(); ind.indexPeaks = new List <Cortege3 <decimal, int, decimal> >(); } candles = new List <CandleData>(); packer = new CandlePacker(Graphics[0].b); var levels = FiboLevels.ToFloatArrayUniform(); fiboLevels.Clear(); foreach (var level in levels) { try { fiboLevels.Add(level); } catch (FormatException) { } } tickerNames = DalSpot.Instance.GetTickerNames(); randomGener = new Random(DateTime.Now.Millisecond); lastBidLists = new Dictionary <string, List <double> >(); // по каждой валютной паре найти макс. количество отсчетов (из формулы индекса) InitLastBidLists(); //RobotTradeState = TradeState.НетПозиций; stopsOnPositions = StopPositionsState.Незащищены; TerminalLog.Instance.SaveRobotLog("Atracotes MTS: RobotTradeState = " + RobotTradeState); }
public override List<string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff) { if (/*formulaResolver == null || */packer == null) return null; curTime = quotes[0].timeClose; // обновить табличку цен for (var i = 0; i < names.Length; i++) { if (lastBids.ContainsKey(names[i])) lastBids[names[i]] = (double)quotes[i].close; else lastBids.Add(names[i], (double)quotes[i].close); } CandleDataBidAsk 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); var hints = new List<RobotHint>(); if (candle != null) { // закрылась полная свеча, проводим вычисления candles.Add(candle); countCandles++; // обновить очереди (для индекса, переменные вида usdjpy#15) if (lastBidLists.Count > 0) { foreach (var listTicker in lastBidLists) { double price; if (!lastBids.TryGetValue(listTicker.Key, out price)) price = 0; listTicker.Value.Add(price); } } // посчитать индексы foreach (var ind in IndexList) ind.CalculateValue(tickerNames, candles, lastBidLists, curTime, randomGener); // если это период "разгона" конвейера if (isHistoryStartOff) return null; var hintText = new StringBuilder(); List<MarketOrder> orders; #region ТОРГОВЫЙ МОДУЛЬ #region проверяем необходимость добавок к открытым позициям // проверяем состояние робота, если у нас нет позиций и робот торгует, возвращаем в исходное состояние GetMarketOrders(out orders); if (orders.Count == 0 && stopsOnPositions == StopPositionsState.ЗащитаУстановлена) { RobotTradeState = TradeState.ПоискТочекВхода; TerminalLog.Instance.SaveRobotLog("Atracotes MTS: Позиции закрылись"); TerminalLog.Instance.SaveRobotLog("Atracotes MTS: RobotTradeState = " + RobotTradeState); stopsOnPositions = StopPositionsState.Незащищены; } var addPosFlag = 0; if (RobotTradeState == TradeState.НаращиваниеПокупок || RobotTradeState == TradeState.НаращиваниеПродаж) { var side = RobotTradeState == TradeState.НаращиваниеПокупок ? 1 : RobotTradeState == TradeState.НаращиваниеПродаж ? -1 : 0; if (AddPositionRules == AddPositionRule.НаБареЛучшейЦены) { //GetMarketOrders(out orders); if (orders.Count == 0) { addPosFlag = RobotTradeState == TradeState.НаращиваниеПокупок ? 1 : -1; } else { var averagePrice = GetAveragePrice(orders, side, curQuote.close, ProtectType.ПоЛучшейПозиции); if (side == 1 && curQuote.close < averagePrice) addPosFlag = 1; if (side == -1 && curQuote.close > averagePrice) addPosFlag = -1; // проверяю достижение актуального фибоуровня if (ActualFiboLevel != null) { // если условие выполнилось, то мы не достигли уровня для открытия позиций if ((addPosFlag == 1 && ActualFiboLevel < curQuote.close) || (addPosFlag == -1 && ActualFiboLevel > curQuote.close)) addPosFlag = 0; } } } } if (addPosFlag != 0) { GetMarketOrders(out orders); var ordersCount = orders.Count; // проверяем можно ли еще открыть позиции if (ordersCount < CountTrades) { // открыть позу в направлении знака дивера robotContext.SendNewOrderRequest( protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), new MarketOrder { AccountID = robotContext.AccountInfo.ID, Magic = Magic, Symbol = ticker, Volume = GetTradeLot(), Side = addPosFlag, ExpertComment = "Atracotes MTS" }, OrderType.Market, 0, 0); if (ordersCount > 0) { hintText.AppendLine(string.Format("Добавка к {0}, текущая цена {1}", addPosFlag == 1 ? "покупкам" : "продажам", curQuote.close)); } else { hintText.AppendLine(string.Format("{0}, текущая цена {1}", addPosFlag == 1 ? "покупка" : "продажа", curQuote.close)); } TerminalLog.Instance.SaveRobotLog("Atracotes MTS: " + hintText); hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), hintText.ToString(), addPosFlag > 0 ? "BUY" : "SELL", "e", curQuote.close) { Time = curQuote.timeClose, ColorFill = addPosFlag > 0 ? Color.Green : Color.Red, ColorLine = Color.Black, RobotHintType = addPosFlag > 0 ? RobotHint.HintType.Покупка : RobotHint.HintType.Продажа }); stopsOnPositions = StopPositionsState.Незащищены; if (ordersCount + 1 == CountTrades) { RobotTradeState = TradeState.НабранПолныйОбъем; TerminalLog.Instance.SaveRobotLog("Atracotes MTS: RobotTradeState = " + RobotTradeState); } } } #endregion #region считаем зигзагу и уровни расширений var quotesList = candles.ToList(); var pivots = ZigZag.GetPivots(quotesList, ThresholdPercent, ZigZagSourceType); if (pivots.Count > 1) { // появились точки, рассчитываем уровни // проверяем процентный порог перешагнули или нет for (var i = pivots.Count; i > 1; i--) { var index0 = i - 1; var index1 = i - 2; var percent = Math.Abs(pivots[index0].b - pivots[index1].b) / pivots[index1].b * 100; if (percent > ThresholdPercent) { // процентный порог пройден, вычисляем уровни // теперь вычисляем уровни расширений var sign = pivots[index0].b > pivots[index1].b ? -1 : 1; var delta = Math.Abs(pivots[index0].b - pivots[index1].b); // очищаем все предыдущие уровни расширений как устаревшие // extLevels.Clear(); foreach (var level in fiboLevels) { var lev = new ExtensionsLevel { startIndex = countCandles > CandlesInIndexHistory ? countCandles - CandlesInIndexHistory + pivots[index0].a : pivots[index0].a, length = BarsCount, price = pivots[index0].b + delta * sign * (1 + level), delta = DalSpot.Instance.GetAbsValue(ticker, DeltaLevel), goalFrom = -sign }; extLevels.Add(lev); } break; } } } #endregion #region ищем дивергенции на индексах и курсе валютной пары var divergenceSign = 0; foreach (var ind in IndexList) { var commentOnDivergence = string.Empty; var indiDiverSign = ind.GetDivergenceSign(candles, out commentOnDivergence); if (indiDiverSign != 0) { if (hintText.Length != 0) hintText.AppendLine(); hintText.AppendLine("Дивергенция на индексе №" + indexList.IndexOf(ind)); hintText.AppendLine(commentOnDivergence); hintText.AppendLine("Переменные:"); // ReSharper disable PossibleNullReferenceException) foreach (var pair in ind.indexCalculator.varValues) // ReSharper restore PossibleNullReferenceException { hintText.AppendLine(string.Format("{1}{0}{2:f4}", (char)9, pair.Key, pair.Value)); } //hints.Add(new RobotHint(hintText.ToString(), //indiDiverSign > 0 ? "BUY" : "SELL", "e", curQuote.Bid) //{ // Time = candle.timeOpen, // ColorFill = indiDiverSign > 0 ? Color.Green : Color.Red, // ColorLine = Color.Black //}); } divergenceSign += indiDiverSign; } #endregion // теперь получен список дивергенций и уровни расширения. #region удаляем старые уровни for (var i = 0; i < extLevels.Count; i++) { // проверка актуальности уровня по свечам if (countCandles - 1 <= extLevels[i].startIndex + extLevels[i].length) continue; // уровень устарел, прошли максимальную длину свечей extLevels.RemoveAt(i); i--; } #endregion // проверяем достижение уровней расширения текущей ценой и если есть - входим в рынок divergenceSign = Math.Sign(divergenceSign); if (stopsOnPositions == StopPositionsState.Незащищены && divergenceSign != 0) { GetMarketOrders(out orders); stopsOnPositions = ProtectPositions(orders, -divergenceSign, curQuote.close); if (stopsOnPositions == StopPositionsState.ЗащитаУстановлена) { TerminalLog.Instance.SaveRobotLog("Atracotes MTS: Позиции защищены ны дивергенции"); hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), "Защита позиций на дивергенции", "PROTECT", -divergenceSign > 0 ? "PB" : "PS", curQuote.close) { Time = curQuote.timeClose, ColorFill = Color.Blue, ColorLine = Color.Black, RobotHintType = RobotHint.HintType.Поджатие }); } } if (true || RobotTradeState == TradeState.НетПозиций || RobotTradeState == TradeState.ПоискТочекВхода || RobotTradeState == TradeState.НабранПолныйОбъем) { foreach (var level in extLevels) { // проверяем попадание цены на уровень //var prevCandle = candles.GetItemByIndex(candles.Count() - 2, true); if ((level.goalFrom == -1 && candles[candles.Count - 1].close >= (level.price - level.delta)) || (level.goalFrom == 1 && candles[candles.Count - 1].close <= (level.price + level.delta))) { GetMarketOrders(out orders); if (stopsOnPositions == StopPositionsState.Незащищены && divergenceSign == 0) { // надо поджать позиции stopsOnPositions = ProtectPositions(orders, -level.goalFrom, curQuote.close); if (stopsOnPositions == StopPositionsState.ЗащитаУстановлена) { TerminalLog.Instance.SaveRobotLog("Atracotes MTS: Позиции защищены по достижению уровня расширения"); hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), "Защита позиций по достижению уровня расширения", "PROTECT", -level.goalFrom > 0 ? "PB" : "PS", curQuote.close) { Time = curQuote.timeClose, ColorFill = Color.Blue, ColorLine = Color.Black, RobotHintType = RobotHint.HintType.Поджатие }); } break; } if (divergenceSign == 0) continue; var ordersCount = orders.Count; // цена поднялась до целевого уровня var level1 = level; var ordersToClose = orders.FindAll(o => o.Side != divergenceSign); foreach (var order in ordersToClose) { robotContext.SendCloseRequest(protectedContext.MakeProtectedContext(), robotContext.AccountInfo.ID, order.ID, PositionExitReason.ClosedByRobot); ordersCount--; } // закрыли ордера и теперь начинаем открывать позиции в обратную сторону // проверяем можно ли еще открыть позиции if (ordersCount >= CountTrades) break; // не добавляем позиции по новому диверу if (RobotTradeState == TradeState.НаращиваниеПокупок && divergenceSign == 1 || RobotTradeState == TradeState.НаращиваниеПродаж && divergenceSign == -1) break; // открыть позу в направлении знака дивера robotContext.SendNewOrderRequest( protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), new MarketOrder { AccountID = robotContext.AccountInfo.ID, Magic = Magic, Symbol = ticker, Volume = GetTradeLot(), Side = divergenceSign, ExpertComment = "Atracotes MTS" }, OrderType.Market, 0, 0); hintText.AppendLine(string.Format("Пересечение уровня {0} {1}, текущая цена {2}", level1.price, level1.goalFrom == -1 ? "снизу" : "сверху", curQuote.close)); TerminalLog.Instance.SaveRobotLog("Atracotes MTS: " + hintText + ", " + (divergenceSign > 0 ? "покупка" : "продажа")); hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), hintText.ToString(), divergenceSign > 0 ? "BUY" : "SELL", "e", curQuote.close) { Time = curQuote.timeClose, ColorFill = divergenceSign > 0 ? Color.Green : Color.Red, ColorLine = Color.Black, RobotHintType = divergenceSign > 0 ? RobotHint.HintType.Покупка : RobotHint.HintType.Продажа }); RobotTradeState = divergenceSign == 1 ? TradeState.НаращиваниеПокупок : TradeState.НаращиваниеПродаж; TerminalLog.Instance.SaveRobotLog("Atracotes MTS: RobotTradeState = " + RobotTradeState); stopsOnPositions = StopPositionsState.Незащищены; break; } } } #endregion } var retHint = hints.Select(hint => hint.ToString()).ToList(); return retHint.Count > 0 ? retHint : null; }
public override void Initialize(BacktestServerProxy.RobotContext grobotContext, CurrentProtectedContext protectedContext) { base.Initialize(grobotContext, protectedContext); // проверка настроек графиков if (Graphics.Count == 0) { Logger.DebugFormat("Atracotes MTS: настройки графиков не заданы"); return; } if (Graphics.Count > 1) { Logger.DebugFormat("Atracotes MTS: настройки графиков должны описывать один тикер / один ТФ"); return; } ticker = Graphics[0].a; lastBids = new Dictionary<string, double>(); foreach (var ind in IndexList) { ind.Initialize(); ind.lastIndicies = new List<double>(); ind.indexPeaks = new List<Cortege3<decimal, int, decimal>>(); } candles = new List<CandleData>(); packer = new CandlePacker(Graphics[0].b); var levels = FiboLevels.ToFloatArrayUniform(); fiboLevels.Clear(); foreach (var level in levels) { try { fiboLevels.Add(level); } catch (FormatException) { } } tickerNames = DalSpot.Instance.GetTickerNames(); randomGener = new Random(DateTime.Now.Millisecond); lastBidLists = new Dictionary<string, List<double>>(); // по каждой валютной паре найти макс. количество отсчетов (из формулы индекса) InitLastBidLists(); //RobotTradeState = TradeState.НетПозиций; stopsOnPositions = StopPositionsState.Незащищены; TerminalLog.Instance.SaveRobotLog("Atracotes MTS: RobotTradeState = " + RobotTradeState); }
public override List <string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff) { if (/*formulaResolver == null || */ packer == null) { return(null); } curTime = quotes[0].timeClose; // обновить табличку цен for (var i = 0; i < names.Length; i++) { if (lastBids.ContainsKey(names[i])) { lastBids[names[i]] = (double)quotes[i].close; } else { lastBids.Add(names[i], (double)quotes[i].close); } } CandleDataBidAsk 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); var hints = new List <RobotHint>(); if (candle != null) { // закрылась полная свеча, проводим вычисления candles.Add(candle); countCandles++; // обновить очереди (для индекса, переменные вида usdjpy#15) if (lastBidLists.Count > 0) { foreach (var listTicker in lastBidLists) { double price; if (!lastBids.TryGetValue(listTicker.Key, out price)) { price = 0; } listTicker.Value.Add(price); } } // посчитать индексы foreach (var ind in IndexList) { ind.CalculateValue(tickerNames, candles, lastBidLists, curTime, randomGener); } // если это период "разгона" конвейера if (isHistoryStartOff) { return(null); } var hintText = new StringBuilder(); List <MarketOrder> orders; #region ТОРГОВЫЙ МОДУЛЬ #region проверяем необходимость добавок к открытым позициям // проверяем состояние робота, если у нас нет позиций и робот торгует, возвращаем в исходное состояние GetMarketOrders(out orders); if (orders.Count == 0 && stopsOnPositions == StopPositionsState.ЗащитаУстановлена) { RobotTradeState = TradeState.ПоискТочекВхода; TerminalLog.Instance.SaveRobotLog("Atracotes MTS: Позиции закрылись"); TerminalLog.Instance.SaveRobotLog("Atracotes MTS: RobotTradeState = " + RobotTradeState); stopsOnPositions = StopPositionsState.Незащищены; } var addPosFlag = 0; if (RobotTradeState == TradeState.НаращиваниеПокупок || RobotTradeState == TradeState.НаращиваниеПродаж) { var side = RobotTradeState == TradeState.НаращиваниеПокупок ? 1 : RobotTradeState == TradeState.НаращиваниеПродаж ? -1 : 0; if (AddPositionRules == AddPositionRule.НаБареЛучшейЦены) { //GetMarketOrders(out orders); if (orders.Count == 0) { addPosFlag = RobotTradeState == TradeState.НаращиваниеПокупок ? 1 : -1; } else { var averagePrice = GetAveragePrice(orders, side, curQuote.close, ProtectType.ПоЛучшейПозиции); if (side == 1 && curQuote.close < averagePrice) { addPosFlag = 1; } if (side == -1 && curQuote.close > averagePrice) { addPosFlag = -1; } // проверяю достижение актуального фибоуровня if (ActualFiboLevel != null) { // если условие выполнилось, то мы не достигли уровня для открытия позиций if ((addPosFlag == 1 && ActualFiboLevel < curQuote.close) || (addPosFlag == -1 && ActualFiboLevel > curQuote.close)) { addPosFlag = 0; } } } } } if (addPosFlag != 0) { GetMarketOrders(out orders); var ordersCount = orders.Count; // проверяем можно ли еще открыть позиции if (ordersCount < CountTrades) { // открыть позу в направлении знака дивера robotContext.SendNewOrderRequest( protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), new MarketOrder { AccountID = robotContext.AccountInfo.ID, Magic = Magic, Symbol = ticker, Volume = GetTradeLot(), Side = addPosFlag, ExpertComment = "Atracotes MTS" }, OrderType.Market, 0, 0); if (ordersCount > 0) { hintText.AppendLine(string.Format("Добавка к {0}, текущая цена {1}", addPosFlag == 1 ? "покупкам" : "продажам", curQuote.close)); } else { hintText.AppendLine(string.Format("{0}, текущая цена {1}", addPosFlag == 1 ? "покупка" : "продажа", curQuote.close)); } TerminalLog.Instance.SaveRobotLog("Atracotes MTS: " + hintText); hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), hintText.ToString(), addPosFlag > 0 ? "BUY" : "SELL", "e", curQuote.close) { Time = curQuote.timeClose, ColorFill = addPosFlag > 0 ? Color.Green : Color.Red, ColorLine = Color.Black, RobotHintType = addPosFlag > 0 ? RobotHint.HintType.Покупка : RobotHint.HintType.Продажа }); stopsOnPositions = StopPositionsState.Незащищены; if (ordersCount + 1 == CountTrades) { RobotTradeState = TradeState.НабранПолныйОбъем; TerminalLog.Instance.SaveRobotLog("Atracotes MTS: RobotTradeState = " + RobotTradeState); } } } #endregion #region считаем зигзагу и уровни расширений var quotesList = candles.ToList(); var pivots = ZigZag.GetPivots(quotesList, ThresholdPercent, ZigZagSourceType); if (pivots.Count > 1) { // появились точки, рассчитываем уровни // проверяем процентный порог перешагнули или нет for (var i = pivots.Count; i > 1; i--) { var index0 = i - 1; var index1 = i - 2; var percent = Math.Abs(pivots[index0].b - pivots[index1].b) / pivots[index1].b * 100; if (percent > ThresholdPercent) { // процентный порог пройден, вычисляем уровни // теперь вычисляем уровни расширений var sign = pivots[index0].b > pivots[index1].b ? -1 : 1; var delta = Math.Abs(pivots[index0].b - pivots[index1].b); // очищаем все предыдущие уровни расширений как устаревшие // extLevels.Clear(); foreach (var level in fiboLevels) { var lev = new ExtensionsLevel { startIndex = countCandles > CandlesInIndexHistory ? countCandles - CandlesInIndexHistory + pivots[index0].a : pivots[index0].a, length = BarsCount, price = pivots[index0].b + delta * sign * (1 + level), delta = DalSpot.Instance.GetAbsValue(ticker, DeltaLevel), goalFrom = -sign }; extLevels.Add(lev); } break; } } } #endregion #region ищем дивергенции на индексах и курсе валютной пары var divergenceSign = 0; foreach (var ind in IndexList) { var commentOnDivergence = string.Empty; var indiDiverSign = ind.GetDivergenceSign(candles, out commentOnDivergence); if (indiDiverSign != 0) { if (hintText.Length != 0) { hintText.AppendLine(); } hintText.AppendLine("Дивергенция на индексе №" + indexList.IndexOf(ind)); hintText.AppendLine(commentOnDivergence); hintText.AppendLine("Переменные:"); // ReSharper disable PossibleNullReferenceException) foreach (var pair in ind.indexCalculator.varValues) // ReSharper restore PossibleNullReferenceException { hintText.AppendLine(string.Format("{1}{0}{2:f4}", (char)9, pair.Key, pair.Value)); } //hints.Add(new RobotHint(hintText.ToString(), //indiDiverSign > 0 ? "BUY" : "SELL", "e", curQuote.Bid) //{ // Time = candle.timeOpen, // ColorFill = indiDiverSign > 0 ? Color.Green : Color.Red, // ColorLine = Color.Black //}); } divergenceSign += indiDiverSign; } #endregion // теперь получен список дивергенций и уровни расширения. #region удаляем старые уровни for (var i = 0; i < extLevels.Count; i++) { // проверка актуальности уровня по свечам if (countCandles - 1 <= extLevels[i].startIndex + extLevels[i].length) { continue; } // уровень устарел, прошли максимальную длину свечей extLevels.RemoveAt(i); i--; } #endregion // проверяем достижение уровней расширения текущей ценой и если есть - входим в рынок divergenceSign = Math.Sign(divergenceSign); if (stopsOnPositions == StopPositionsState.Незащищены && divergenceSign != 0) { GetMarketOrders(out orders); stopsOnPositions = ProtectPositions(orders, -divergenceSign, curQuote.close); if (stopsOnPositions == StopPositionsState.ЗащитаУстановлена) { TerminalLog.Instance.SaveRobotLog("Atracotes MTS: Позиции защищены ны дивергенции"); hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), "Защита позиций на дивергенции", "PROTECT", -divergenceSign > 0 ? "PB" : "PS", curQuote.close) { Time = curQuote.timeClose, ColorFill = Color.Blue, ColorLine = Color.Black, RobotHintType = RobotHint.HintType.Поджатие }); } } if (true || RobotTradeState == TradeState.НетПозиций || RobotTradeState == TradeState.ПоискТочекВхода || RobotTradeState == TradeState.НабранПолныйОбъем) { foreach (var level in extLevels) { // проверяем попадание цены на уровень //var prevCandle = candles.GetItemByIndex(candles.Count() - 2, true); if ((level.goalFrom == -1 && candles[candles.Count - 1].close >= (level.price - level.delta)) || (level.goalFrom == 1 && candles[candles.Count - 1].close <= (level.price + level.delta))) { GetMarketOrders(out orders); if (stopsOnPositions == StopPositionsState.Незащищены && divergenceSign == 0) { // надо поджать позиции stopsOnPositions = ProtectPositions(orders, -level.goalFrom, curQuote.close); if (stopsOnPositions == StopPositionsState.ЗащитаУстановлена) { TerminalLog.Instance.SaveRobotLog("Atracotes MTS: Позиции защищены по достижению уровня расширения"); hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), "Защита позиций по достижению уровня расширения", "PROTECT", -level.goalFrom > 0 ? "PB" : "PS", curQuote.close) { Time = curQuote.timeClose, ColorFill = Color.Blue, ColorLine = Color.Black, RobotHintType = RobotHint.HintType.Поджатие }); } break; } if (divergenceSign == 0) { continue; } var ordersCount = orders.Count; // цена поднялась до целевого уровня var level1 = level; var ordersToClose = orders.FindAll(o => o.Side != divergenceSign); foreach (var order in ordersToClose) { robotContext.SendCloseRequest(protectedContext.MakeProtectedContext(), robotContext.AccountInfo.ID, order.ID, PositionExitReason.ClosedByRobot); ordersCount--; } // закрыли ордера и теперь начинаем открывать позиции в обратную сторону // проверяем можно ли еще открыть позиции if (ordersCount >= CountTrades) { break; } // не добавляем позиции по новому диверу if (RobotTradeState == TradeState.НаращиваниеПокупок && divergenceSign == 1 || RobotTradeState == TradeState.НаращиваниеПродаж && divergenceSign == -1) { break; } // открыть позу в направлении знака дивера robotContext.SendNewOrderRequest( protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), new MarketOrder { AccountID = robotContext.AccountInfo.ID, Magic = Magic, Symbol = ticker, Volume = GetTradeLot(), Side = divergenceSign, ExpertComment = "Atracotes MTS" }, OrderType.Market, 0, 0); hintText.AppendLine(string.Format("Пересечение уровня {0} {1}, текущая цена {2}", level1.price, level1.goalFrom == -1 ? "снизу" : "сверху", curQuote.close)); TerminalLog.Instance.SaveRobotLog("Atracotes MTS: " + hintText + ", " + (divergenceSign > 0 ? "покупка" : "продажа")); hints.Add(new RobotHint(Graphics[0].a, Graphics[0].b.ToString(), hintText.ToString(), divergenceSign > 0 ? "BUY" : "SELL", "e", curQuote.close) { Time = curQuote.timeClose, ColorFill = divergenceSign > 0 ? Color.Green : Color.Red, ColorLine = Color.Black, RobotHintType = divergenceSign > 0 ? RobotHint.HintType.Покупка : RobotHint.HintType.Продажа }); RobotTradeState = divergenceSign == 1 ? TradeState.НаращиваниеПокупок : TradeState.НаращиваниеПродаж; TerminalLog.Instance.SaveRobotLog("Atracotes MTS: RobotTradeState = " + RobotTradeState); stopsOnPositions = StopPositionsState.Незащищены; break; } } } #endregion } var retHint = hints.Select(hint => hint.ToString()).ToList(); return(retHint.Count > 0 ? retHint : null); }