/// <summary> /// подвинуть nextUpdateTime чуть назад, так, чтобы след. обновление произошло не позднее, /// чем через maxMillisecondsDelay милисекунд /// </summary> public void HurryUpUpdateMaxDelay(int maxMillisecondsDelay) { var delay = (nextUpdateTime.GetLastHit() - DateTime.Now).TotalMilliseconds; if (delay > maxMillisecondsDelay) { nextUpdateTime.SetTime(DateTime.Now.AddMilliseconds(maxMillisecondsDelay)); } }
private void CheckRoomEntered() { while (!isStopping) { Thread.Sleep(100); if (!sender.IsOnline) { continue; } var checkTime = liveRoomCheckTime.GetLastHit(); if (checkTime > DateTime.Now) { continue; } foreach (var room in ChatSettings.Instance.Rooms) { bool timeoutFlag; if (!enteredRooms.Contains(room, LockTimeout, out timeoutFlag)) { try { // TODO: пароль берется из оперативного списка. если вход не удался, то пароль сбрасывается sender.EnterRoom(room, GetRoomPassword(room)); } catch (Exception ex) { Logger.Error("Ошибка входа в комнату чата (ChatControlBackEnd.CheckRoomEntered)", ex); } } } liveRoomCheckTime.SetTime(DateTime.Now + aliveTimeSpan); } }
public RequestStatus SendCloseRequest(MarketOrder order, PositionExitReason reason) { if (string.IsNullOrEmpty(order.ExpertComment)) { Logger.ErrorFormat("SignalDealer.SendCloseRequest({0}) - поле ExpertComment не заполнено", order.ID); //return RequestStatus.DealerError; } // получить цену var quote = QuoteStorage.Instance.ReceiveValue(order.Symbol); if (quote == null) { return(RequestStatus.NoPrice); } var price = order.Side > 0 ? quote.GetPrice(QuoteType.Bid) : quote.GetPrice(QuoteType.Ask); // отправить сигнал var signal = new ManagerSignal { Id = order.ExpertComment, PriceClose = (decimal)price, Category = signalCategoryCode, Symbol = order.Symbol, Leverage = 0, Price = (decimal)order.PriceEnter, Side = order.Side }; var timeExec = new ThreadSafeTimeStamp(); timeExec.Touch(); if (!string.IsNullOrEmpty(order.ExpertComment) && !SendSignal(signal, false)) { return(RequestStatus.DealerError); } var endTime = DateTime.Now - timeExec.GetLastHit(); Logger.InfoFormat("Время исполнения SendCloseRequest SendSignal: {0} секунд, {1} миллисекунд", endTime.TotalSeconds, endTime.TotalMilliseconds); timeExec.Touch(); // закрыть ордер немедленно var result = ServerInterface.CloseOrder(order, (decimal)price, reason); endTime = DateTime.Now - timeExec.GetLastHit(); Logger.InfoFormat("Время исполнения SendCloseRequest - CloseOrder: {0} секунд, {1} миллисекунд", endTime.TotalSeconds, endTime.TotalMilliseconds); return(result ? RequestStatus.OK : RequestStatus.ServerError); }
public User GetUser(int id) { var result = GetAllUsers().FirstOrDefault(u => u.ID == id); if (result == null && DateTime.Now.Subtract(lastRequestTime.GetLastHit()).TotalMinutes > 1) { if (GetAllPlatformUsers == null) { return(null); } users.AddRange(GetAllPlatformUsers().Select(u => new User(u)), LockTimeout); result = GetAllUsers().FirstOrDefault(u => u.ID == id); } return(result); }
public void ThreadSafeTimeStampTest() { var timeSt = new ThreadSafeTimeStamp(); var method = new WaitCallback(s => { for (var i = 0; i < 4; i++) { timeSt.Touch(); Thread.Sleep(200); var delta = (DateTime.Now - timeSt.GetLastHit()).TotalMilliseconds; } }); ThreadPool.QueueUserWorkItem(method); ThreadPool.QueueUserWorkItem(method); }
private void StoreRoutine() { const int iterationLen = 100; int nIters = storeInterval / iterationLen; int curIter = 0; while (!isStopping) { curIter++; if (curIter <= nIters) { Thread.Sleep(iterationLen); continue; } curIter = 0; // сохранить котировки из списка bool isTimeout; var candles = queueCandles.ExtractAll(QueueTimeout, out isTimeout); if (isTimeout) { loggerNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMagicQueueTimeout, 60 * 1000 * 10, "QuoteStoreStream: таймаут чтения очереди ({0}), длина очереди {1}", QueueTimeout, queueLength); continue; } if (candles.Count == 0) { var lastTime = lastQuoteTime.GetLastHit(); if ((DateTime.Now - lastTime).TotalMilliseconds > ModuleStatusController.MaxMillsBetweenQuotes) { ModuleStatusController.Instance.Status.AddError(ServiceProcessState.HasCriticalErrors, "quote stream", DateTime.Now, "QUOTE"); } continue; } lastQuoteTime.Touch(); ModuleStatusController.Instance.Status.RemoveError(ServiceProcessState.HasCriticalErrors, "QUOTE"); queueLength = 0; // собственно сохранить DoSaveCandles(candles); } }
public void OnCandleUpdated(CandleData updatedCandle, List <CandleData> newCandles) { if (updatedCandle == null) { return; } // перерисовка должна производиться не чаще, чем раз в N секунд // (если свеча просто обновилась) if (newCandles == null || newCandles.Count == 0) { var deltaSeconds = (DateTime.Now - lastUpdateTime.GetLastHit()).TotalSeconds; if (deltaSeconds < redrawSeconds) { return; } } BuildSeries(owner); }
private void CheckTimeout() { // поток котировок может быть не включен в рабочий день if (!WorkingDay.Instance.IsWorkingDay(DateTime.Now)) { return; } var delta = (DateTime.Now - lastMessageReceived.GetLastHit()).TotalMilliseconds; if (delta < timeoutIntervalMils) { return; } Logger.Error("TCPFeeder: сработал таймаут TCP получателя котировок, перезапускаем"); // инициировать таймаут /*receiver.Stop(); * lastMessageReceived.Touch(); * * StartTcpReceiver();*/ }
private void TranslateOrdersToMt4(List <MarketOrder> orders) { orders = orders.Where(o => o.State == PositionState.Opened).ToList(); if ((DateTime.Now - timeSinceActList.GetLastHit()).TotalMilliseconds > MilsBetweenSendActualOrdersList) { SendActualOrdersCommand(orders); SendReportCommand(); timeSinceActList.Touch(); } if (!ordersAreRead) { ordersAreRead = true; currentOrders = orders; return; } var ordersNew = (from order in orders let orderId = order.ID where !currentOrders.Any(o => o.ID == orderId) select order).ToList(); var ordersClosed = (from order in currentOrders let orderId = order.ID where !orders.Any(o => o.ID == orderId) select order).ToList(); currentOrders = orders; // сформировать и отправить команды на закрытие ордеров if (ordersClosed.Count > 0) { SendCloseCommands(ordersClosed); } if (ordersNew.Count > 0) { SendOpenCommands(ordersNew); } }
private void CheckTimeout() { // поток котировок может быть не включен в рабочий день if (!WorkingDay.Instance.IsWorkingDay(DateTime.Now)) { return; } var delta = (DateTime.Now - lastMessageReceived.GetLastHit()).TotalMilliseconds; if (delta < timeoutIntervalMils) { return; } return; // инициировать таймаут //client.Stop(); //lastMessageReceived.Touch(); //Logger.InfoFormat("TcpQuoteReceiver - таймаут, {0} секунд", (int)(delta / 1000)); //client = new TcpReceiverClient(AppConfig.GetStringParam("Quote.ServerHost", "70.38.11.49"), // AppConfig.GetIntParam("Quote.ServerPort", 55056)); //client.OnTcpPacketReceived += OnTcpPacketReceived; //client.Connect(); }
public override List <string> OnQuotesReceived(string[] names, CandleDataBidAsk[] quotes, bool isHistoryStartOff) { if (isHistoryStartOff) { return(new List <string>()); } if (!string.IsNullOrEmpty(errorMessage)) { var evts = new List <string> { errorMessage }; errorMessage = string.Empty; return(evts); } var evsList = spamMessage.GetMessages().Select(m => m.b).ToList(); if (TradeSharpAccount > 0) { var account = robotContext.AccountInfo; if (account != null && account.ID != TradeSharpAccount) { spamMessage.PutMessage(SpamMessage.MessageCategory.AccountMismatch, "Открыт счет #" + account.ID + ", ожидается счет #" + TradeSharpAccount); return(evsList); } } if (!initMessageWasSent) { // сообщить - привет, я торговый робот, делаю то-то и то-то initMessageWasSent = true; evsList.Add(string.Format("MT4 робот, слушает порт {0}, отправляет на порт {1}", portOwn, portMt4)); } // проверить время с последней проверки ордеров var lastTime = timeSinceUpdate.GetLastHit(); var nowTime = DateTime.Now; var milsPassed = (nowTime - lastTime).TotalMilliseconds; if (milsPassed < MilsBetweenChecks) { return(evsList); } timeSinceUpdate.Touch(); // транслировать сделки в МТ4 if (Mode == RobotMode.УправлятьМТ4) { List <MarketOrder> orders; // проверить имеющиеся ордера GetMarketOrders(out orders, false); TranslateOrdersToMt4(orders); return(evsList); } // копировать сделки из МТ4 if (Mode == RobotMode.КопироватьОрдераМТ4) { CopyOrdersFromMt4(evsList); return(evsList); } return(evsList); }
public RequestStatus SendNewOrderRequest(Account account, MarketOrder order, OrderType orderType, decimal requestedPrice, decimal slippagePoints) { order.TimeEnter = DateTime.Now; order.State = PositionState.Opened; // подставить текущую цену var quote = QuoteStorage.Instance.ReceiveValue(order.Symbol); if (quote == null) { return(RequestStatus.NoPrice); } order.PriceEnter = order.Side > 0 ? quote.ask : quote.bid; // проверить проскальзывание if (slippagePoints != 0) { var slippageAbs = DalSpot.Instance.GetAbsValue(order.Symbol, slippagePoints); var delta = Math.Abs(order.PriceEnter - (float)requestedPrice); if (delta > (float)slippageAbs) { return(RequestStatus.Slippage); } } if (account.Balance <= 0) { Logger.ErrorFormat("SendNewOrderRequest (счет {0}) - баланс счета равен 0", account.ID); return(RequestStatus.DealerError); } // получить уникальный Id сигнала, он же - Magic для ордера // посчитать плечо, пересчитав объем в валюту депо bool areEqual, inverse; var baseTicker = DalSpot.Instance.FindSymbol(order.Symbol, true, account.Currency, out inverse, out areEqual); if (!areEqual && string.IsNullOrEmpty(baseTicker)) { Logger.ErrorFormat("SendNewOrderRequest - неизвестный сивол пересчета базовой валюты ({0})", order.Symbol); return(RequestStatus.DealerError); } var rateDepo = 1f; if (!areEqual) { var baseQuote = QuoteStorage.Instance.ReceiveValue(baseTicker); if (baseQuote == null) { Logger.ErrorFormat("SendNewOrderRequest - нет котировки {0} для пересчета базовой валюты", baseQuote); return(RequestStatus.DealerError); } rateDepo = inverse ? 1 / quote.ask : quote.bid; } var volumeDepo = order.Volume * rateDepo; var leverage = (decimal)volumeDepo / account.Balance; // отправить сигнал var signal = new ManagerSignal { Id = DateTime.Now.Ticks.ToString(), Price = (decimal)order.PriceEnter, Side = order.Side, Symbol = order.Symbol, Leverage = (decimal)leverage, Category = signalCategoryCode }; // !!! // переделал ID сигнала в запись поля expertComment вместо comment //order.Comment = signal.Id; order.ExpertComment = signal.Id; // отправка сигнала успешна?) var timeExec = new ThreadSafeTimeStamp(); timeExec.Touch(); if (!SendSignal(signal, true)) { return(RequestStatus.DealerError); } int posID; // сохранить ордер (и уведомить клиента) var endTime = DateTime.Now - timeExec.GetLastHit(); Logger.InfoFormat("Время исполнения SendNewOrderRequest SendSignal: {0} секунд, {1} миллисекунд", endTime.TotalSeconds, endTime.TotalMilliseconds); timeExec.Touch(); var result = ServerInterface.SaveOrderAndNotifyClient(order, out posID); endTime = DateTime.Now - timeExec.GetLastHit(); Logger.InfoFormat("Время исполнения SendNewOrderRequest - SaveOrderAndNotifyClient: {0} секунд, {1} миллисекунд", endTime.TotalSeconds, endTime.TotalMilliseconds); return(result ? RequestStatus.OK : RequestStatus.SerializationError); }
private void DoSend() { Chat = new ChatClientStable(chatCallback, TerminalBindings.Chat); Chat.Connected += () => { if (Connected != null) { Connected(); } }; Chat.Disconnected += () => { if (Disconnected != null) { Disconnected(); } }; UserInfoSource = new UserInfoExCache(TradeSharpAccountStatistics.Instance.proxy); while (!isStopping) { bool timeoutFlag; var allRequests = requests.ExtractAll(lockTimeout, out timeoutFlag); if (timeoutFlag) { continue; } // флаг повтора запроса; // перезапросы возникают из-за ошибок сети; // в этом случае ожидание между запросами увеличено, чтобы не загружать проц без пользы var repeatRequest = false; foreach (var request in allRequests) { try { switch (request.Code) { case RequestCode.GetAllUsers: request.Id = Chat.GetAllUsers((string)request.Arguments[0]); break; case RequestCode.Enter: request.Id = Chat.Enter((User)request.Arguments[0]); break; case RequestCode.Exit: request.Id = Chat.Exit(); break; case RequestCode.GetRooms: request.Id = Chat.GetRooms(); break; case RequestCode.EnterRoom: request.Id = Chat.EnterRoom((string)request.Arguments[0], (string)request.Arguments[1]); break; case RequestCode.MoveToRoom: request.Id = Chat.MoveToRoom((int)request.Arguments[0], (string)request.Arguments[1], (string)request.Arguments[2]); break; case RequestCode.LeaveRoom: request.Id = Chat.LeaveRoom((string)request.Arguments[0]); break; case RequestCode.CreateRoom: request.Id = Chat.CreateRoom((Room)request.Arguments[0]); break; case RequestCode.DestroyRoom: request.Id = Chat.DestroyRoom((string)request.Arguments[0]); break; case RequestCode.SendPrivateMessage: request.Id = Chat.SendPrivateMessage((int)request.Arguments[0], (string)request.Arguments[1]); break; case RequestCode.SendMessage: request.Id = Chat.SendMessage((string)request.Arguments[0], (string)request.Arguments[1]); break; case RequestCode.GetPendingMessages: request.Id = Chat.GetPendingMessages((DateTime)request.Arguments[0], (string)request.Arguments[1]); break; case RequestCode.GetPendingPrivateMessages: request.Id = Chat.GetPendingPrivateMessages((DateTime)request.Arguments[0], (int)request.Arguments[1]); break; case RequestCode.Ping: Chat.Ping(); break; case RequestCode.GetUserInfoEx: var userinfo = UserInfoSource.GetUserInfo((int)request.Arguments[0]); if (UserInfoExReceived != null) { UserInfoExReceived(userinfo ?? new UserInfoEx { Id = (int)request.Arguments[0] }); } break; case RequestCode.SetUserInfoEx: UserInfoSource.SetUserInfo((UserInfoEx)request.Arguments[0]); break; } if (request.Id == 0) { QueueRequest(request); // if server refused request - try again repeatRequest = true; } else if (request.Id != -1) // skip Ping, GetUserInfoEx, SetUserInfoEx { request.Status = ChatResultCode.InProgress; pendingRequests.UpdateValues(request.Id, request); /*if (pendingRequestsLock.TryEnterWriteLock(lockTimeout)) * { * pendingRequests.Add(request.Id, request); * pendingRequestsLock.ExitWriteLock(); * } * else * Console.WriteLine("ChatSender.DoSend: pendingRequestsWriteLock timeout");*/ var requestCopy = new ChatRequest(request); if (RequestQueuedOnServer != null) { RequestQueuedOnServer(requestCopy); } if (forwardAnswers.ContainsKey(request.Id)) { pendingRequests.Remove(request.Id); requestCopy.Status = forwardAnswers.ReceiveValue(request.Id); if (RequestProcessed != null) { RequestProcessed(requestCopy); } forwardAnswers.Remove(request.Id); } } } catch (Exception ex) // probably communication error { Logger.ErrorFormat("DoSend exception: {0}", ex); if (request.Code != RequestCode.Ping) { QueueRequest(request); } repeatRequest = true; } } //проверка соединения - ping if (allRequests.Count == 0) { if (DateTime.Now.Subtract(lastConnectionCheck.GetLastHit()).TotalSeconds > 15) { var request = new ChatRequest(RequestCode.Ping, new List <object>(), -1); QueueRequest(request); lastConnectionCheck.Touch(); } } Thread.Sleep(repeatRequest ? 1000 : 100); } }
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 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); }