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); }
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); }
private UserSettings() { lastTimeModified = new ThreadSafeTimeStamp(); }
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); }
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); }