private void OpenDeal(QuoteData quote, int dealSide) { var dealVolumeDepo = CalculateVolume(ticker); if (dealVolumeDepo == 0) { return; } decimal?stop = StopLossPoints == 0 ? (decimal?)null : (decimal)quote.bid - dealSide * DalSpot.Instance.GetAbsValue(ticker, (decimal)StopLossPoints); decimal?take = TakeProfitPoints == 0 ? (decimal?)null : (decimal)quote.bid + dealSide * DalSpot.Instance.GetAbsValue(ticker, (decimal)TakeProfitPoints); robotContext.SendNewOrderRequest( protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), new MarketOrder { AccountID = robotContext.AccountInfo.ID, Magic = Magic, Symbol = ticker, Volume = dealVolumeDepo, Side = dealSide, StopLoss = (float?)stop, TakeProfit = (float?)take, ExpertComment = "FibonacciRobot" }, OrderType.Market, 0, 0); }
public RequestStatus OpenPosition(string hash, string userLogin, long localTime, int accountId, string symbol, int volume, int side, float stopLoss, float takeProfit, int magic, string comment) { var status = CheckCredentials(hash, userLogin, localTime, accountId, true); if (status != RequestStatus.OK) { return(status); } status = managerTrade.SendNewOrderRequest(ProtectedOperationContext.MakeServerSideContext(), RequestUniqueId.Next(), new MarketOrder { AccountID = accountId, Symbol = symbol, Volume = volume, Side = side, StopLoss = stopLoss == 0 ? (float?)null : stopLoss, TakeProfit = takeProfit == 0 ? (float?)null : takeProfit, Magic = magic, Comment = comment }, OrderType.Market, 0, 0); return(status); }
private void OpenDeal(float price, int dealSide) { var dealVolumeDepo = CalculateVolume(ticker); if (dealVolumeDepo == 0) { return; } float?stop = StopLossPoints == 0 ? (float?)null : price - dealSide * DalSpot.Instance.GetAbsValue(ticker, (float)StopLossPoints); float?take = TakeProfitPoints == 0 ? (float?)null : price + dealSide * DalSpot.Instance.GetAbsValue(ticker, (float)TakeProfitPoints); robotContext.SendNewOrderRequest( protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), new MarketOrder { AccountID = robotContext.AccountInfo.ID, Magic = Magic, Symbol = ticker, Volume = dealVolumeDepo, Side = dealSide, StopLoss = stop, TakeProfit = take, ExpertComment = "RencoRobot" }, OrderType.Market, 0, 0); }
private void OpenDeal(float price, int dealSide) { var dealVolumeDepo = CalculateVolume(ticker, Leverage, FixedVolume); if (dealVolumeDepo == 0) { return; } var sl = stopLossPoints == 0 ? (float?)null : price - dealSide * DalSpot.Instance.GetAbsValue(ticker, (float)stopLossPoints); var tp = takeProfitPoints == 0 ? (float?)null : price + dealSide * DalSpot.Instance.GetAbsValue(ticker, (float)takeProfitPoints); // открыть сделку robotContext.SendNewOrderRequest( protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), new MarketOrder { AccountID = robotContext.AccountInfo.ID, Magic = Magic, Symbol = ticker, Volume = dealVolumeDepo, Side = dealSide, StopLoss = sl, TakeProfit = tp, ExpertComment = "CaymanRobot" }, OrderType.Market, 0, 0); }
/// <summary> /// Открыть новую сделку по указанной цене price, указанного типа dealSide (покупка или продажа) /// </summary> private void OpenDeal(float price, int dealSide) { var dealVolumeDepo = CalculateVolume(ticker); if (dealVolumeDepo == 0) { return; } // Пересчёт значений Stop loss и Take profit из пунктов в конкретную цену. Эти значения не могут быть 0 var stop = StopLossPoints == 0 ? (float?)null : price - dealSide * DalSpot.Instance.GetAbsValue(ticker, (float)StopLossPoints); var take = TakeProfitPoints == 0 ? (float?)null : price + dealSide * DalSpot.Instance.GetAbsValue(ticker, (float)TakeProfitPoints); robotContext.SendNewOrderRequest( protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), new MarketOrder { AccountID = robotContext.AccountInfo.ID, // Уникальный идентификатор чёта Magic = Magic, // Этот параметр позволяет отличать сделки разных роботов Symbol = ticker, // Инструмент по которому совершается сделка Volume = dealVolumeDepo, // Объём средств, на который совершается сделка Side = dealSide, // Устанавливаем тип сделки - покупка или продажа StopLoss = stop, // Устанавливаем величину Stop loss для открываемой сделки TakeProfit = take, // Устанавливаем величину Take profit для открываемой сделки ExpertComment = "MARobot" // Комментарий по сделке, оставленный роботом }, OrderType.Market, 0, 0); }
/// <summary> /// Send pending order /// </summary> /// <param name="magic"></param> /// <param name="symbol"></param> /// <param name="volume"></param> /// <param name="side"></param> /// <param name="pendingOrdType"></param> /// <param name="targetPriceFrom"></param> /// <param name="targetPriceTo"></param> /// <param name="dateFrom"></param> /// <param name="dateTo"></param> /// <param name="stopPrice"></param> /// <param name="takePrice"></param> /// <param name="comment"></param> /// <returns></returns> protected RequestStatus NewPendingOrder(PendingOrder order) { order.AccountID = robotContext.AccountInfo.ID; return(robotContext.SendNewPendingOrderRequest( protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), order)); }
/// <summary> /// Send market or instant order /// </summary> /// <param name="order">все параметры ордера</param> /// <param name="ordType"></param> /// <param name="slippagePoints"></param> /// <returns></returns> protected RequestStatus NewOrder(MarketOrder order, OrderType ordType, decimal requestedPrice, decimal slippagePoints) { order.Magic = magic; order.AccountID = robotContext.AccountInfo.ID; return(robotContext.SendNewOrderRequest( protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), order, ordType, requestedPrice, slippagePoints)); }
private bool OpenDeal(float price, int dealSide) { List <MarketOrder> orders; robotContext.GetMarketOrders(robotContext.AccountInfo.ID, out orders); orders = orders.Where(o => o.Magic == Magic && o.Symbol == ticker).ToList(); // закрыть сделки противонаправленные текущему знаку foreach (var order in orders.Where(o => o.Side != dealSide).ToList()) { robotContext.SendCloseRequest(protectedContext.MakeProtectedContext(), robotContext.AccountInfo.ID, order.ID, PositionExitReason.ClosedByRobot); } // если была, например, покупка - повторно не покупаем if (orders.Any(o => o.Side == dealSide)) { return(false); } var dealVolumeDepo = CalculateVolume(ticker); if (dealVolumeDepo == 0) { return(false); } // Пересчёт значений Stop loss и Take profit из пунктов в конкретную цену. Эти значения не могут быть 0 var stop = StopLossPoints == 0 ? (float?)null : price - dealSide * DalSpot.Instance.GetAbsValue(ticker, (float)StopLossPoints); var take = TakeProfitPoints == 0 ? (float?)null : price + dealSide * DalSpot.Instance.GetAbsValue(ticker, (float)TakeProfitPoints); robotContext.SendNewOrderRequest( protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), new MarketOrder { AccountID = robotContext.AccountInfo.ID, // Уникальный идентификатор чёта Magic = Magic, // Этот параметр позволяет отличать сделки разных роботов Symbol = ticker, // Инструмент по которому совершается сделка Volume = dealVolumeDepo, // Объём средств, на который совершается сделка Side = dealSide, // Устанавливаем тип сделки - покупка или продажа StopLoss = stop, // Устанавливаем величину Stop loss для открываемой сделки TakeProfit = take, // Устанавливаем величину Take profit для открываемой сделки ExpertComment = "IchimokuRobot" // Комментарий по сделке, оставленный роботом }, OrderType.Market, 0, 0); return(true); }
public RequestStatus SendNewPendingOrderRequestSafe(int requestUniqueId, PendingOrder order) { if (requestUniqueId == 0) { requestUniqueId = RequestUniqueId.Next(); } if (InvokeRequired) { return((RequestStatus)Invoke(new Func <PendingOrder, int, RequestStatus>(SendNewPendingOrderRequestUnsafe), order, requestUniqueId)); } return(SendNewPendingOrderRequestUnsafe(order, requestUniqueId)); }
private void OpenOrder(Cortege3 <string, int, DateTime> order) { var ticker = order.a; var side = order.b; var dealVolumeDepo = CalculateVolume(ticker); if (dealVolumeDepo == 0) { return; } float?sl = null; if (CheckDice(probStopLoss)) { var quote = QuoteStorage.Instance.ReceiveValue(ticker); if (quote != null) { var points = minStopPoints; if (CheckDice(propRandomStopStep)) { points = points + rnd.Next(maxStopPoints - minStopPoints + 1); } else { points = points + rnd.Next((maxStopPoints - minStopPoints) / stepStopPoints + 1) * stepStopPoints; } sl = side > 0 ? quote.ask : quote.bid; sl -= side * DalSpot.Instance.GetAbsValue(ticker, (float)points); } } robotContext.SendNewOrderRequest( protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), new MarketOrder { Symbol = ticker, Side = side, AccountID = robotContext.AccountInfo.ID, Magic = Magic, Volume = dealVolumeDepo, ExpertComment = "RandomRobot", Comment = "", StopLoss = sl, TakeProfit = null }, OrderType.Market, 0, 0); }
private void OpenDeal(float price, int dealSide, string symbol, List <PendingOrder> orders) { // такой ордер уже размещен? var minDeltaPrice = (float)pointCost[symbol] * 2; if (orders.Any(o => o.Side == dealSide && Math.Abs(o.PriceFrom - price) < minDeltaPrice)) { return; } var dealVolumeDepo = CalculateVolume(symbol); if (dealVolumeDepo == 0) { return; } float?stop = StopLossPoints == 0 ? (float?)null : price - dealSide * DalSpot.Instance.GetAbsValue(symbol, (float)StopLossPoints); float?take = TakeProfitPoints == 0 ? (float?)null : price + dealSide * DalSpot.Instance.GetAbsValue(symbol, (float)TakeProfitPoints); robotContext.SendNewPendingOrderRequest( protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), new PendingOrder { AccountID = robotContext.AccountInfo.ID, Magic = Magic, Symbol = symbol, Volume = dealVolumeDepo, Side = dealSide, StopLoss = stop, TakeProfit = take, ExpertComment = "Kovzharoff", PriceFrom = price, PriceSide = PendingOrderType.Stop }); }
private void OpenDeal(float price, int dealSide) { var dealVolumeDepo = CalculateVolume(ticker); if (dealVolumeDepo == 0) { return; } // Посчитать stopLoss и takeProfit stopLoss = StopLossPoints == 0 ? dealSide > 0 ? extremumQueue.Min(q => q.a) : extremumQueue.Max(q => q.a) : price - dealSide * DalSpot.Instance.GetAbsValue(ticker, (float)StopLossPoints); takeProfit = TakeProfitPoints == 0 ? extremumQueue.First.a : price + dealSide * DalSpot.Instance.GetAbsValue(ticker, (float)TakeProfitPoints); // очистить очередь экстремумов extremumQueue.Clear(); // открыть сделку robotContext.SendNewOrderRequest( protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), new MarketOrder { AccountID = robotContext.AccountInfo.ID, Magic = Magic, Symbol = ticker, Volume = dealVolumeDepo, Side = dealSide, StopLoss = stopLoss, TakeProfit = takeProfit * TakeRange / 100, ExpertComment = "DoubleTopRobot" }, OrderType.Market, 0, 0); }
private void OpenDeal(int dealSide) { var dealVolumeDepo = CalculateVolume(ticker); if (dealVolumeDepo == 0) { return; } // открыть сделку robotContext.SendNewOrderRequest( protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), new MarketOrder { AccountID = robotContext.AccountInfo.ID, Magic = Magic, Symbol = ticker, Volume = dealVolumeDepo, Side = dealSide, ExpertComment = "TailBodyRobot" }, OrderType.Market, 0, 0); }
private void CopyOrdersFromMt4(List <string> events) { if (!ordersFromMt4Received) { return; } try { // ордера из МТ4 var ordersMt4 = ordersFromMt4.ExtractAll(1000); // ордера из самого терминала List <MarketOrder> ordersTs; GetMarketOrders(out ordersTs, !ControlOrdersDisregardMagic); // для каждого ордера терминала найти аналогичный ордер в списке от МТ4 // "лишние" ордера удалить foreach (var orderTs in ordersTs) { var side = orderTs.Side; var symbol = orderTs.Symbol; var orderTicket = 0; if (orderTs.ExpertComment.StartsWith("Mt4ticket=")) { orderTicket = orderTs.ExpertComment.Substring("Mt4ticket=".Length).ToIntSafe() ?? 0; } var existOrderMt4 = ordersMt4.FirstOrDefault(o => o.Magic == orderTicket && o.Side == side && o.Symbol == symbol); if (existOrderMt4 == null) { // закрыть ордер events.Add(string.Format("Ордер {0} не найден в МТ4 (всего {1} ордеров) и будет закрыт", orderTs, ordersMt4.Count)); robotContext.SendCloseRequest(protectedContext.MakeProtectedContext(), robotContext.AccountInfo.ID, orderTs.ID, PositionExitReason.ClosedByRobot); continue; } // проверить, совпадают ли цены SL / TP для ордера в МТ4 и T# var deltaStop = DalSpot.Instance.GetPointsValue(symbol, Math.Abs((orderTs.StopLoss ?? 0) - (existOrderMt4.StopLoss ?? 0))); var deltaTake = DalSpot.Instance.GetPointsValue(symbol, Math.Abs((orderTs.TakeProfit ?? 0) - (existOrderMt4.TakeProfit ?? 0))); // обновить цены TP / SL if (deltaStop > 1 || deltaTake > 1) { orderTs.StopLoss = existOrderMt4.StopLoss; orderTs.TakeProfit = existOrderMt4.TakeProfit; robotContext.SendEditMarketRequest(protectedContext.MakeProtectedContext(), orderTs); } } // открыть новые ордера var requestsWhatHaveBeenAlreadySent = sentRequests.ExtractAll(1000); foreach (var orderMt4 in ordersMt4) { var orderTicket = orderMt4.Magic.Value; var side = orderMt4.Side; var symbol = orderMt4.Symbol; var comment = "Mt4ticket=" + orderTicket; if (ordersTs.Any(o => o.ExpertComment == comment && o.Side == side && o.Symbol == symbol)) { continue; } orderMt4.ExpertComment = comment; // пересчитать объем orderMt4.Volume = CalcTradeSharpDealVolume(orderMt4.Volume); if (orderMt4.Volume == 0) { continue; } orderMt4.AccountID = robotContext.AccountInfo.ID; orderMt4.Magic = Magic; // антифлад if (requestsWhatHaveBeenAlreadySent.Contains(orderTicket)) { continue; } // таки открыть ордер var response = robotContext.SendNewOrderRequest(protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), orderMt4, OrderType.Market, (decimal)orderMt4.PriceEnter, 0); requestsWhatHaveBeenAlreadySent.Add(orderTicket); } sentRequests.ReplaceRange(requestsWhatHaveBeenAlreadySent, 1000); } catch (Exception ex) { Logger.Error("Ошибка в CopyOrdersFromMt4()", ex); } finally { ordersFromMt4Received = false; } }
public override string ActivateScript(string ticker) { if (!AccountStatus.Instance.isAuthorized) { MessageBox.Show("Не авторизован"); return("Не авторизован"); } var equity = AccountStatus.Instance.AccountData.Equity; if (equity <= 0) { MessageBox.Show("На счете отсутствуют денежные средства"); return("На счете отсутствуют денежные средства"); } var orders = MarketOrdersStorage.Instance.MarketOrders.Where(o => o.Symbol == ticker).ToList(); var side = orders.Count == 0 ? DealType.Buy : (DealType)orders[0].Side; float?sl = orders.Count == 0 ? null : orders[0].StopLoss; // открыть окно выбора направления входа и SL var dlg = new TradeFromSLDlg(orders.Count, side, sl); if (dlg.ShowDialog() != DialogResult.OK) { return("Отменено пользователем"); } side = dlg.Side; var targetSl = dlg.StopLoss; // выставить стоп остальным ордерам foreach (var order in orders) { var delta = Math.Abs((order.StopLoss ?? 0) - targetSl); var deltaPoints = DalSpot.Instance.GetPointsValue(ticker, delta); if (deltaPoints < 2) { continue; } // редактировать ордер order.StopLoss = targetSl; MainForm.Instance.SendEditMarketRequestSafe(order); } // получить текущую цену var quotes = QuoteStorage.Instance.ReceiveAllData(); QuoteData quote; quotes.TryGetValue(ticker, out quote); if (quote == null) { return("Нет котировки " + ticker); } // коэфф пересчета из контрвалюты в валюту депо var kCounterDepo = 1f; if (!ticker.EndsWith("USD")) { kCounterDepo = 1 / ((quote.ask + quote.bid) * 0.5f); } // посчитать макс. допустимый объем входа исходя из просадки var ordersResult = orders.Sum(o => o.Volume * o.Side * (targetSl - o.PriceEnter) * kCounterDepo); // убыток (прибыль) по сделкам var priceEnter = side == DealType.Buy ? quote.ask : quote.bid; var orderLossAbs = ((int)side) * (decimal)(targetSl - priceEnter); decimal volumeMax = decimal.MaxValue; // от текущего баланса считать сумму потерь var loss = equity * lossPercent / 100; if (orderLossAbs < 0) { volumeMax = (decimal)kCounterDepo * (loss + (decimal)ordersResult) / (-orderLossAbs); } // вход невозможен if (volumeMax < 0) { var err = string.Format( "Потери по уже открытым позициям для SL {0:f4} ({1:f0}) превысят допустимый процент " + "потерь ({2:f1}%, {3:f0} USD)", targetSl, ordersResult, lossPercent, loss); MessageBox.Show(err); return(err); } // множитель для объема var indexK = orders.Count; if (indexK >= volumePercent.Length) { indexK = volumePercent.Length - 1; } var koeffVolume = volumePercent[indexK]; if (volumeMax < decimal.MaxValue) { volumeMax *= (koeffVolume / 100M); } // сравнить объем с предельно допустимым var maxVolumeDepo = equity * LeverageMax; var maxVolumeBase = maxVolumeDepo / (decimal)((quote.bid + quote.ask) * 0.5f); var volumeEnter = Math.Min(volumeMax, maxVolumeBase); // округлить объем var volume = MarketOrder.RoundDealVolume((int)volumeEnter, VolumeRound, volumeMin, volumeStep); if (volume == 0) { var err = string.Format("Объем входа ({0:f0}) после округления равен 0", volumeEnter); MessageBox.Show(err); return(err); } // подтвердить вход) if (confirmTrade) { var orderLoss = volume * ((int)side) * (targetSl - priceEnter); var lossStr = ordersResult != 0 ? string.Format("{0}{1:f0} по уже открытым ордерам и {2:f0} по новому ордеру", ordersResult > 0 ? "прибыль" : "", Math.Abs(ordersResult), (-orderLoss)) : (-orderLoss).ToString("f0"); var prompt = string.Format("Будет открыта позиция: {0} {1} {2}, SL={3:f4}. Потери при SL: {4}. Продолжить?", side, volume, ticker, targetSl, lossStr); if (MessageBox.Show(prompt, "Подтвердить сделку", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No) { return("Отменено пользователем"); } } // войти в рынок MainForm.Instance.SendNewOrderRequestSafe( RequestUniqueId.Next(), AccountStatus.Instance.accountID, new MarketOrder { Volume = volume, Side = (int)side, Symbol = ticker, StopLoss = targetSl }, (decimal)priceEnter, 0, OrderType.Market); return("Операция успешна"); }
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); }
public override string ActivateScript(string ticker) { if (!AccountStatus.Instance.isAuthorized) { MessageBox.Show("Не авторизован"); return("Не авторизован"); } var account = AccountStatus.Instance.AccountData; if (account == null) { MessageBox.Show("Не авторизован"); return("Не авторизован"); } var equity = account.Equity; if (equity <= 0) { MessageBox.Show("На счете отсутствуют денежные средства"); return("На счете отсутствуют денежные средства"); } var dealSide = side; decimal?sl = null, tp = null; float? trailLevel = null, trailTarget = null; // предполагаемая цена входа var quotes = QuoteStorage.Instance.ReceiveAllData(); QuoteData currentQuote; quotes.TryGetValue(ticker, out currentQuote); var reqPrice = currentQuote == null ? 0 : Side == DealType.Buy ? currentQuote.ask : currentQuote.bid; if (OrderType == ScriptOrderType.Отложенный && currentQuote == null) { return("Отложенный ордер не создан - нет котировки " + ticker); } // для отложенного ордера обязательно запросим цену decimal priceEnter = 0; float dealPrice = 0; if (RequestSide || OrderType == ScriptOrderType.Отложенный) { var dlg = new ScriptPartDepoFormDialog( (int)side, currentQuote == null ? (float?)null : currentQuote.bid, OrderType == ScriptOrderType.Отложенный) { TradeTicker = ticker }; if (dlg.ShowDialog() == DialogResult.Cancel) { return("Отменен"); } priceEnter = dlg.Price ?? 0; sl = dlg.SL; tp = dlg.TP; dealSide = (DealType)dlg.Side; if (dlg.Trailing != null && dlg.Trailing.Length == 2 && (dlg.Trailing[0] != 0 || dlg.Trailing[1] != 0)) { if (currentQuote == null) { var msg = string.Format("Нет котировки \"{0}\" для расчета пп трейлинга", ticker); MessageBox.Show(msg); return(msg); } var trailPrice = dlg.Trailing[0]; dealPrice = OrderType == ScriptOrderType.Отложенный ? (float)priceEnter : (dealSide == DealType.Buy ? currentQuote.ask : currentQuote.bid); var trailPips = DalSpot.Instance.GetPointsValue(ticker, ((int)dealSide) * (trailPrice - dealPrice)); // преобразовать цену в пп от входа trailLevel = trailPips; trailTarget = dlg.Trailing[1]; } } // объем в валюте депозита var volumeDepo = equity * leverage; var volumeBase = volumeDepo; // из объема депо пересчитать в объем базовой валюты var depoCurx = AccountStatus.Instance.AccountData.Currency; bool inverse, pairsEqual; var tickerTrans = DalSpot.Instance.FindSymbol(ticker, true, depoCurx, out inverse, out pairsEqual); if (!pairsEqual) { QuoteData quote; quotes.TryGetValue(tickerTrans, out quote); if (quote == null) { var msgError = string.Format( "Невозможно рассчитать объем - отсутствует котировка \"{0}\"", tickerTrans); MessageBox.Show(msgError); return(msgError); } var priceTrans = inverse ? 1 / quote.bid : quote.ask; volumeBase /= (decimal)priceTrans; } // округлить объем var lotSize = DalSpot.Instance.GetMinStepLot(ticker, account.Group); volumeBase = MarketOrder.RoundDealVolume((int)volumeBase, VolumeRound, lotSize.minVolume, lotSize.volumeStep); if (volumeBase == 0) { var msgError = $"Рассчетный объем входа ({volumeBase}) меньше допустимого ({lotSize.minVolume})"; MessageBox.Show(msgError); return(msgError); } // проверить количество входов (по тикеру либо вообще) var ordersCount = DealCounting == DealCountingType.ОбщийУчет ? MarketOrdersStorage.Instance.MarketOrders.Count : MarketOrdersStorage.Instance.MarketOrders.Count(o => o.Symbol == ticker); if (ordersCount >= dealsMax) { var msgError = DealCounting == DealCountingType.ОбщийУчет ? $"Уже открыто {ordersCount} сделок из {dealsMax} макс." : $"По \"{ticker}\" уже открыто {ordersCount} сделок из {dealsMax} макс."; MessageBox.Show(msgError); return(msgError); } // подтверждение var confirmPrice = dealPrice; if (confirmPrice == 0) { confirmPrice = (dealSide == DealType.Buy ? currentQuote.ask : currentQuote.bid); } if (confirmTrade) { if (MessageBox.Show(string.Format("Будет совершена {0} {1} {2} по {3}. Продолжить?", dealSide == DealType.Buy ? "покупка" : "продажа", volumeBase.ToStringUniformMoneyFormat(), depoCurx, confirmPrice.ToStringUniformPriceFormat()), "Подтверждение", MessageBoxButtons.YesNo) == DialogResult.No) { return("отменено пользователем"); } } // таки войти в рынок if (OrderType == ScriptOrderType.ыночный) { MainForm.Instance.SendNewOrderRequestSafe( RequestUniqueId.Next(), AccountStatus.Instance.accountID, new MarketOrder { Volume = (int)volumeBase, Side = (int)dealSide, Symbol = ticker, StopLoss = (float?)sl, TakeProfit = (float?)tp, TrailLevel1 = trailLevel, TrailTarget1 = trailTarget }, priceEnter, 0, Contract.Entity.OrderType.Market); } else { // создать отложенник var orderType = PendingOrderType.Limit; if (((int)dealSide == 1 && currentQuote.ask < (float)priceEnter) || ((int)dealSide == -1 && currentQuote.bid > (float)priceEnter)) { orderType = PendingOrderType.Stop; } var pendingOrder = new PendingOrder { AccountID = AccountStatus.Instance.accountID, Symbol = ticker, Volume = (int)volumeBase, Side = (int)dealSide, PriceSide = orderType, PriceFrom = (float)priceEnter, StopLoss = (float?)sl, TakeProfit = (float?)tp, TrailLevel1 = trailLevel, TrailTarget1 = trailTarget }; MainForm.Instance.SendNewPendingOrderRequestSafe(RequestUniqueId.Next(), pendingOrder); } return("Сделка с фиксированным плечом (" + dealSide + " " + ticker + ") совершена"); }
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); }
private void OpenMarket(int side, OrderType ordType) { Account account = null; if (AccountStatus.Instance.connectionStatus == AccountConnectionStatus.Connected) { account = AccountStatus.Instance.AccountData; } if (account == null) { MessageBox.Show(EnumFriendlyName <AccountConnectionStatus> .GetString(AccountConnectionStatus.NotConnected), Localizer.GetString("TitleWarning")); return; } var sl = tbSL.Text.Replace(",", ".").ToDecimalUniformSafe(); var tp = tbTP.Text.Replace(",", ".").ToDecimalUniformSafe(); float?[] trailingLevels; float?[] trailTargets; GetTrailingLevels(side, out trailingLevels, out trailTargets); var symbol = cbCurx.Text; // для инстант-ордера получить текущую цену var slipPoints = 0f; var requestedPrice = 0f; var quote = QuoteStorage.Instance.ReceiveValue(symbol); if (cbSlippage.Checked) { slipPoints = udSlippagePoints.Text.ToFloatUniform(); if (quote == null) { MessageBox.Show(string.Format(Localizer.GetString("MessageNoPriceForInstantOrderFmt"), symbol), Localizer.GetString("TitleWarning"), MessageBoxButtons.OK, MessageBoxIcon.Exclamation); return; } requestedPrice = side > 0 ? quote.ask : quote.bid; } var volm = cbVolume.Text.Replace(" ", "").ToInt(); // предупредить трейдера? if (!CheckMargin(symbol, side, volm)) { return; } RequestStatus status; try { status = MainForm.Instance.SendNewOrderRequestSafe( RequestUniqueId.Next(), account.ID, new MarketOrder { Volume = volm, Side = side, Symbol = symbol, StopLoss = (float?)(sl != 0 ? sl : null), TakeProfit = (float?)(tp != 0 ? tp : null), Magic = tbMagic.Text.ToIntSafe(), Comment = tbComment.Text, TrailLevel1 = trailingLevels[0], TrailTarget1 = trailTargets[0] }, (decimal)requestedPrice, (decimal)slipPoints, ordType); } catch (Exception ex) { Logger.Error("Server proxy: SendNewOrderRequest error: ", ex); MessageBox.Show(Localizer.GetString("MessageUnableToDeliverRequest"), Localizer.GetString("TitleError"), MessageBoxButtons.OK, MessageBoxIcon.Error); return; } if (status != RequestStatus.OK) { MessageBox.Show( EnumFriendlyName <RequestStatus> .GetString(status), Localizer.GetString("TitleError"), MessageBoxButtons.OK, MessageBoxIcon.Error); return; } }
private void MakePending(int side) { var priceVal = tbPrice.Text.Replace(",", ".").ToFloatUniformSafe(); if (!priceVal.HasValue) { MessageBox.Show(Localizer.GetString("MessagePriceNotProvided")); tbPrice.Focus(); return; } var price = priceVal.Value; if (price <= 0) { MessageBox.Show(Localizer.GetString("MessagePriceMustBePositive")); tbPrice.Text = ""; tbPrice.Focus(); return; } if (lastQuote == null) { MessageBox.Show(Localizer.GetString("MessageNoQuote")); return; } // создать новый отложенный ордер var volm = cbVolume.Text.Replace(" ", "").ToInt(); var orderType = PendingOrderType.Limit; if ((side == 1 && lastQuote.ask < price) || (side == -1 && lastQuote.bid > price)) { orderType = PendingOrderType.Stop; } var orderOCO = (PendingOrder)cbOrderOCO.SelectedItem; var orderOCOId = orderOCO == null ? (int?)null : orderOCO.ID; float?[] trailingLevels; float?[] trailTargets; GetTrailingLevels(side, out trailingLevels, out trailTargets); var order = new PendingOrder { AccountID = AccountStatus.Instance.accountID, Symbol = Ticker, Magic = tbMagic.Text.ToIntSafe(), Volume = volm, Side = side, PriceSide = orderType, PriceFrom = price, PriceTo = tbPriceTo.Text.Replace(",", ".").ToFloatUniformSafe(), TimeFrom = cbStartFrom.Checked ? dpTimeFrom.Value : (DateTime?)null, TimeTo = cbEndTime.Checked ? dpTimeTo.Value : (DateTime?)null, StopLoss = tbSL.Text.Replace(",", ".").ToFloatUniformSafe(), TakeProfit = tbTP.Text.Replace(",", ".").ToFloatUniformSafe(), PairOCO = orderOCOId > 0 ? orderOCO.ID : (int?)null, Comment = tbComment.Text, ExpertComment = tbExpertComment.Text, // трейлинг TrailLevel1 = trailingLevels[0], TrailLevel2 = trailingLevels[1], TrailLevel3 = trailingLevels[2], TrailLevel4 = trailingLevels[3], TrailTarget1 = trailTargets[0], TrailTarget2 = trailTargets[1], TrailTarget3 = trailTargets[2], TrailTarget4 = trailTargets[3], }; MainForm.Instance.SendNewPendingOrderRequestSafe(RequestUniqueId.Next(), order); }
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 void CheckPendingOrder(PendingOrder order, Dictionary <string, QuoteData> curPrices) { // проверка на зафлаживание if (pendingFloodTimes.ContainsKey(order.ID)) { var time = pendingFloodTimes[order.ID]; if (DateTime.Now < time) { return; } pendingFloodTimes.Remove(order.ID); } // отменить устаревший ордер) if (order.TimeTo.HasValue) { if (DateTime.Now > order.TimeTo) { //var pairCancel = curPrices.ContainsKey(order.Symbol) ? curPrices[order.Symbol] : null; //var priceCancel = pairCancel == null ? 0 : order.Side > 0 ? pairCancel.Bid : pairCancel.Ask; proxyTrade.SendDeletePendingOrderRequest(ProtectedOperationContext.MakeServerSideContext(), order, PendingOrderStatus.Отменен, null, "Экспирация"); return; } } // получить текущую котировку if (!curPrices.ContainsKey(order.Symbol)) { if ((DateTime.Now - timeStarted).TotalMilliseconds > MinMillsToReportError) { floodSafeLogger.LogMessageFormatCheckFlood(LogEntryType.Debug, MsgNoQuoteMagic, 5 * 60 * 1000, "CheckOrder: нет котировки по {0} для отлож. ордера #{1}", order.Symbol, order.ID); } return; } var pricePair = curPrices[order.Symbol]; var price = order.Side > 0 ? pricePair.ask : pricePair.bid; // проверить нахождение в рамках цены и времени if (order.TimeFrom.HasValue) { if (DateTime.Now < order.TimeFrom) { return; } } // цена... var orderFires = false; if (order.Side > 0 && ((PendingOrderPriceSide)order.PriceSide) == PendingOrderPriceSide.Limit) { if (price <= order.PriceFrom && (order.PriceTo == null ? true : price >= order.PriceTo)) { orderFires = true; } } else if (order.Side < 0 && ((PendingOrderPriceSide)order.PriceSide) == PendingOrderPriceSide.Limit) { if (price >= order.PriceFrom && (order.PriceTo == null ? true : price <= order.PriceTo)) { orderFires = true; } } else if (order.Side > 0 && ((PendingOrderPriceSide)order.PriceSide) == PendingOrderPriceSide.Stop) { if (price >= order.PriceFrom && (order.PriceTo == null ? true : price <= order.PriceTo)) { orderFires = true; } } else { if (price <= order.PriceFrom && (order.PriceTo == null ? true : price >= order.PriceTo)) { orderFires = true; } } if (!orderFires) { return; } Logger.InfoFormat("Активация отлож. ордера #{0} ({1} {2} at {3}), цена {4}", order.ID, (DealType)order.Side, order.PriceSide, order.PriceFrom.ToStringUniformPriceFormat(true), price.ToStringUniformPriceFormat(true)); // активировать ордер var orderMarket = new MarketOrder { AccountID = order.AccountID, Magic = order.Magic, Symbol = order.Symbol, Volume = order.Volume, Side = order.Side, StopLoss = order.StopLoss, TakeProfit = order.TakeProfit, Comment = string.Format("по ордеру #{0}", order.ID) }; var reqStatus = proxyTrade.SendNewOrderRequest( ProtectedOperationContext.MakeServerSideContext(), RequestUniqueId.Next(), orderMarket, OrderType.Market, 0, 0); // проскальзывание if (reqStatus == RequestStatus.OK) { // удалить парный ордер if (order.PairOCO.HasValue && order.PairOCO > 0) { List <PendingOrder> orders; try { proxyAccount.GetPendingOrders(order.AccountID, out orders); var orderPair = orders == null ? null : orders.FirstOrDefault(o => o.ID == order.PairOCO.Value); if (orderPair != null) { proxyTrade.SendDeletePendingOrderRequest(ProtectedOperationContext.MakeServerSideContext(), orderPair, PendingOrderStatus.Отменен, null, "OCO"); } } catch (Exception ex) { Logger.ErrorFormat("Ошибка удаления парного ордера {0} для ордера {1}: {2}", order.PairOCO, order, ex); } } // удалить ордер proxyTrade.SendDeletePendingOrderRequest(ProtectedOperationContext.MakeServerSideContext(), order, PendingOrderStatus.Отменен, null, "Активирован"); } else { // зафлаживание Logger.ErrorFormat("Ошибка активации отлож. ордера #{0}: {1}", order.ID, reqStatus); var nextTime = DateTime.Now.AddMilliseconds(PendingFloodTimeoutMils); if (pendingFloodTimes.ContainsKey(order.ID)) { pendingFloodTimes[order.ID] = nextTime; } else { pendingFloodTimes.Add(order.ID, nextTime); } } }
public override List <string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff) { var events = new List <string>(); if (tickers.Length == 0 || isHistoryStartOff) { return(events); } if (lastTrade == null) { lastTrade = new ThreadSafeTimeStamp(); lastTrade.Touch(); } // секунд с последнего трейда... var timeSince = (DateTime.Now - lastTrade.GetLastHit()).TotalSeconds; if (timeSince < tradeIntervalSec) { return(events); } lastTrade.Touch(); // затребовать все сделки со своим magic List <MarketOrder> orders; GetMarketOrders(out orders, true); var sides = tickers.ToDictionary(t => t, t => 1); if (orders != null) { foreach (var order in orders) { if (sides.ContainsKey(order.Symbol)) { sides[order.Symbol] = -order.Side; } // закрыть старую сделку CloseMarketOrder(order.ID); } } // открыть новые сделки foreach (var tickerSide in sides) { var newOrd = new MarketOrder { Symbol = tickerSide.Key, Side = tickerSide.Value, AccountID = robotContext.AccountInfo.ID, Magic = Magic, Volume = FixedVolume, ExpertComment = "SimpleTradeMachine" }; var rst = robotContext.SendNewOrderRequest(protectedContext.MakeProtectedContext(), RequestUniqueId.Next(), newOrd, OrderType.Market, 0, 0); } return(events); }