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 int SendCloseRequestsInner(int[] orderId, PositionExitReason reason, out RequestStatus lastStatus) { var countOk = 0; lastStatus = RequestStatus.OK; try { using (var ctx = DatabaseContext.Instance.Make()) { foreach (var posId in orderId) { var pos = ctx.POSITION.FirstOrDefault(p => p.ID == posId); lastStatus = pos == null ? RequestStatus.NotFound : managerTrade.SendCloseRequest(pos, reason); if (lastStatus == RequestStatus.OK) { countOk++; } } } } catch (Exception ex) { Logger.Error("Ошибка в PlatformManager.SendCloseRequest", ex); lastStatus = RequestStatus.ServerError; } return(countOk); }
public RequestStatus SendCloseRequest(MarketOrder order, PositionExitReason reason) { var requestedPrice = 0M; var quote = QuoteStorage.Instance.ReceiveValue(order.Symbol); if (quote != null) { requestedPrice = (decimal)(order.Side > 0 ? quote.bid : quote.ask); } if (!order.MasterOrder.HasValue) { Logger.DebugFormat("{0}: SendCloseRequest - закрытие ордера {1} - MasterOrder не задан", DealerCode, order.ToStringShort()); return(RequestStatus.DealerError); } var status = MakeMarketRequest(new TradeTransactionRequest { Account = order.AccountID, ClosingPositionId = order.MasterOrder, Comment = order.Comment, ExpertComment = order.ExpertComment, Id = order.ID, Magic = order.Magic, RequestedPrice = requestedPrice, SlippageAbs = 0, Side = order.Side, Symbol = order.Symbol, Volume = order.Volume }, order); return(status); }
public RequestStatus SendCloseRequest(int orderId, PositionExitReason reason) { RequestStatus status; SendCloseRequestsInner(new[] { orderId }, reason, out status); return(status); }
public RequestStatus SendCloseRequest(MarketOrder order, PositionExitReason reason) { // получить счет RequestStatus error; var acDecorated = ServerInterface.GetAccount(order.AccountID); if (acDecorated == null) { return(RequestStatus.ServerError); } // подготовить запрос TradeSharp.ProviderProxyContract.Entity.MarketOrder request; if (!MakeMarketRequest(acDecorated, order.Symbol, order.Magic, order.Volume, -order.Side, OrderType.Market, 0, 0, string.Format("close order #{0}", order.ID), order.ID, order.Comment, order.ExpertComment, order.TrailLevel1, order.TrailTarget1, out error, out request)) { return(error); } exitReasonByOrderId.UpdateValues(order.ID, reason); // отправить запрос на вход в рынок (оно же - закрытие позиции) в соотв сессию if (!request.SendToQueue(false)) { errorStorage.AddMessage(new ErrorMessage(DateTime.Now, ErrorMessageType.ОшибкаОтправки, "Невозможно отправить сообщение (CloseOrder) в очередь MQ", null)); return(RequestStatus.DealerError); } return(RequestStatus.OK); }
public RequestStatus SendCloseRequestSafe(int accountId, int orderId, PositionExitReason reason) { if (InvokeRequired) { return((RequestStatus)Invoke(new Func <int, int, PositionExitReason, RequestStatus>(SendCloseRequestUnsafe), accountId, orderId, reason)); } return(SendCloseRequestUnsafe(accountId, orderId, reason)); }
/// <summary> /// Вспомогательный метод - закрывает позицию текушими значниями времени и катеровок /// </summary> /// <param name="closeDealIdValue"></param> /// <param name="warningList"></param> /// <param name="validationErrorList"></param> /// <param name="timeExit"></param> /// <param name="ddlExitReasonValue"></param> /// <returns></returns> private ActionResult CloseDaelCurrentTimeValues(string closeDealIdValue, List <string> warningList, List <string> validationErrorList, DateTime timeExit, PositionExitReason ddlExitReasonValue) { var strings = GetSidePriceListById(closeDealIdValue); var adoHalper = new DatabaseQuoteEnquirer(); var tickers = strings.Select(x => x.Split('_')[0]).Distinct(); var quotes = tickers.ToDictionary(x => x, x => adoHalper.GetQuoteStoredProc(x)); var lstStoragePrice = new List <Tuple <string, int, float> >(); foreach (var inp in strings) { var input = inp.Split('_'); var side = Utils.dealSide[input[1]]; var quote = quotes.Where(x => x.Key == input[0]).ToList(); if (quote.Any()) { var price = quote.First().Value.bid; if (side == -1) { price = quote.First().Value.ask; } lstStoragePrice.Add(new Tuple <string, int, float>(input[0], side, price)); } else { warningList.Add(String.Format("{0} : {1} {2}. {3}.", Resource.ErrorMessage, Resource.ErrorMessageQuoteNotFound, input[0], Resource.ErrorMessageTransactionsOnPairWillNotClosed)); Logger.Error(String.Format("CloseOrCancelDeal - попытка принудительно закрыть сделки администратором. " + "Ошибка: для валютной пары {0} не найдены катировка. Сделки по этой валютной паре не будут закрыты.", input[0])); } } if (validationErrorList.Count > 0) { ViewBag.ErrorList = validationErrorList; ViewBag.WarningList = warningList; var model = GetPositionsEditModel(closeDealIdValue); return(View("SafePositionEdit", model)); } var successCloseDeals = positionRepository.ClosingPositions(closeDealIdValue, timeExit, ddlExitReasonValue, lstStoragePrice); var msg = successCloseDeals.Count < 10 ? string.Format("{0}: {1}. {2}", Resource.MessageMarketOrderClosed, string.Join(", ", successCloseDeals), Resource.ErrorMessageClosedNotAllTransactions) : string.Format("{0} {1} {2}. {3}", Resource.MessageMarketOrderClosed, string.Join(", ", successCloseDeals.Take(10)), Resource.TextEtc, Resource.ErrorMessageClosedNotAllTransactions); return(RedirectToAction("PositionList", new { message = msg, positionId = -1 })); }
public RequestStatus SendCloseByTickerRequestSafe(int accountId, string ticker, PositionExitReason reason) { if (InvokeRequired) { return((RequestStatus)Invoke(new Func <int, string, PositionExitReason, RequestStatus>(SendCloseByTickerRequestUnsafe), accountId, ticker, reason)); } return(SendCloseByTickerRequestUnsafe(accountId, ticker, reason)); }
public virtual RequestStatus SendCloseRequest(MarketOrder order, PositionExitReason reason) { // получить цену 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); // закрыть ордер немедленно return ServerInterface.CloseOrder(order, (decimal)price, reason) ? RequestStatus.OK : RequestStatus.ServerError; }
public virtual RequestStatus SendCloseRequest(MarketOrder order, PositionExitReason reason) { // получить цену 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); // закрыть ордер немедленно return(ServerInterface.CloseOrder(order, (decimal)price, reason) ? RequestStatus.OK : RequestStatus.ServerError); }
public bool CloseOrder(int orderId, decimal price, PositionExitReason exitReason) { MarketOrder orderDecor; using (var ctx = DatabaseContext.Instance.Make()) { var orderQuery = ctx.POSITION.Where(p => p.ID == orderId).ToList(); if (orderQuery.Count == 0) { Logger.ErrorFormat("CloseOrder(Id = {0}) - позиция не найдена", orderId); return(false); } orderDecor = LinqToEntity.DecorateOrder(orderQuery[0]); } return(CloseOrder(orderDecor, price, exitReason)); }
public override RequestStatus SendCloseRequest(ProtectedOperationContext ctx, int accountId, int orderId, PositionExitReason reason) { var pos = positions.FirstOrDefault(o => o.ID == orderId); if (pos == null) { return(RequestStatus.NotFound); } var quote = quotesStorage.ReceiveValue(pos.Symbol); if (quote == null) { return(RequestStatus.NoPrice); } ClosePositionAndCalculateProfit(pos, quote, reason); return(RequestStatus.OK); }
public RequestStatus SendCloseByTickerRequest(ProtectedOperationContext ctx, int accountId, string ticker, PositionExitReason reason) { try { return(Proxy.SendCloseByTickerRequest(ctx, accountId, ticker, reason)); } catch (Exception ex) { RenewChannel(); try { return(Proxy.SendCloseByTickerRequest(ctx, accountId, ticker, reason)); } catch (Exception ex2) { return(RequestStatus.ServerError); } } }
private void TryCloseOrder(MarketOrder pos, PositionExitReason reason) { // проверка - не вызывается ли метод раз за разом для одной и той же позиции, // которую невозможно закрыть, например, из-за недостатка свободной маржи DateTime lastTime; if (orderFloodTimes.TryGetValue(pos.ID, out lastTime)) { if (DateTime.Now < lastTime) { return; } } orderFloodTimes.Remove(pos.ID); // отправить запрос proxyTrade.SendCloseRequest(ProtectedOperationContext.MakeServerSideContext(), pos.AccountID, pos.ID, reason); // не допустить забивание потока попытками закрыть позу... orderFloodTimes.Add(pos.ID, DateTime.Now.AddMilliseconds(OrderFloodTimeoutMils)); }
public override RequestStatus SendCloseByTickerRequest(ProtectedOperationContext ctx, int accountId, string ticker, PositionExitReason reason) { var posToClose = positions.Where(p => p.Symbol == ticker).ToList(); if (posToClose.Count == 0) { return(RequestStatus.OK); } var quote = quotesStorage.ReceiveValue(ticker); if (quote == null) { return(RequestStatus.NoPrice); } foreach (var pos in posToClose) { ClosePositionAndCalculateProfit(pos, quote, reason); } return(RequestStatus.OK); }
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 RequestStatus SendCloseRequest(POSITION order, PositionExitReason reason) { Account account; var dealer = GetDealerByAccount(order.AccountID, out account); if (dealer == null) { return(RequestStatus.GroupUnsupported); } // проверить маржинальные требования decimal equity; if (!tradeManager.IsEnterEnabled(order.AccountID, order.Symbol, -order.Side, order.Volume, out equity)) { return(RequestStatus.MarginOrLeverageExceeded); } try { var res = dealer.SendCloseRequest(LinqToEntity.DecorateOrder(order), reason); if (res == RequestStatus.OK) { Logger.InfoFormat("Ордер {0} закрыт, счет {1} символ {2}, объем {3}, тип {4}", order.ID, order.AccountID, order.Symbol, order.Volume, order.Side == 1 ? "buy": "sell"); } else { Logger.ErrorFormat("Ошибка закрытия ордера {0} - ответ дилера:{1}", order.ID, res); } return(res); } catch (Exception ex) { Logger.ErrorFormat("Ошибка дилера {0}: {1}", dealer, ex); return(RequestStatus.DealerError); } }
public RequestStatus SendCloseRequest(ProtectedOperationContext secCtx, int accountId, int orderId, PositionExitReason reason) { if (UserOperationRightsStorage.IsProtectedOperation(UserOperation.CloseOrder)) { if (!UserSessionStorage.Instance.PermitUserOperation(secCtx, UserOperationRightsStorage.IsTradeOperation(UserOperation.ModifyOrder), true)) { return(RequestStatus.Unauthorized); } } // получить позу POSITION order; using (var ctx = DatabaseContext.Instance.Make()) { order = ctx.POSITION.FirstOrDefault(p => p.ID == orderId && p.AccountID == accountId); if (order != null) { if (order.State != (int)PositionState.Opened) { return(RequestStatus.BadRequest); } } } if (order == null) { return(RequestStatus.NotFound); } AccountLogger.InfoFormat("Вызов SendCloseRequest(acc #{0}, orderId #{1}, us. machine \"{2}\")", accountId, orderId, secCtx.userMachineName); return(SendCloseRequest(order, reason)); }
/// <summary> /// Вспомогательный метод - закрывает позицию текушими значниями времени и катеровок /// </summary> /// <param name="closeDealIdValue"></param> /// <param name="warningList"></param> /// <param name="validationErrorList"></param> /// <param name="timeExit"></param> /// <param name="ddlExitReasonValue"></param> /// <returns></returns> private ActionResult CloseDaelCurrentTimeValues(string closeDealIdValue, List<string> warningList, List<string> validationErrorList, DateTime timeExit, PositionExitReason ddlExitReasonValue) { var strings = GetSidePriceListById(closeDealIdValue); var adoHalper = new DatabaseQuoteEnquirer(); var tickers = strings.Select(x => x.Split('_')[0]).Distinct(); var quotes = tickers.ToDictionary(x => x, x => adoHalper.GetQuoteStoredProc(x)); var lstStoragePrice = new List<Tuple<string, int, float>>(); foreach (var inp in strings) { var input = inp.Split('_'); var side = Utils.dealSide[input[1]]; var quote = quotes.Where(x => x.Key == input[0]).ToList(); if (quote.Any()) { var price = quote.First().Value.bid; if (side == -1) price = quote.First().Value.ask; lstStoragePrice.Add(new Tuple<string, int, float>(input[0], side, price)); } else { warningList.Add(String.Format("{0} : {1} {2}. {3}.", Resource.ErrorMessage, Resource.ErrorMessageQuoteNotFound, input[0], Resource.ErrorMessageTransactionsOnPairWillNotClosed)); Logger.Error(String.Format("CloseOrCancelDeal - попытка принудительно закрыть сделки администратором. " + "Ошибка: для валютной пары {0} не найдены катировка. Сделки по этой валютной паре не будут закрыты.",input[0])); } } if (validationErrorList.Count > 0) { ViewBag.ErrorList = validationErrorList; ViewBag.WarningList = warningList; var model = GetPositionsEditModel(closeDealIdValue); return View("SafePositionEdit", model); } var successCloseDeals = positionRepository.ClosingPositions(closeDealIdValue, timeExit, ddlExitReasonValue, lstStoragePrice); var msg = successCloseDeals.Count < 10 ? string.Format("{0}: {1}. {2}", Resource.MessageMarketOrderClosed, string.Join(", ", successCloseDeals), Resource.ErrorMessageClosedNotAllTransactions) : string.Format("{0} {1} {2}. {3}", Resource.MessageMarketOrderClosed, string.Join(", ", successCloseDeals.Take(10)), Resource.TextEtc, Resource.ErrorMessageClosedNotAllTransactions); return RedirectToAction("PositionList", new { message = msg, positionId = -1 }); }
public override RequestStatus SendCloseByTickerRequest(ProtectedOperationContext ctx, int accountId, string ticker, PositionExitReason reason) { if (IsDayOff()) return RequestStatus.WrongTime; return base.SendCloseByTickerRequest(ctx, accountId, ticker, reason); }
public override RequestStatus SendCloseRequest(ProtectedOperationContext ctx, int accountId, int orderId, PositionExitReason reason) { if (IsDayOff()) return RequestStatus.WrongTime; return base.SendCloseRequest(ctx, accountId, orderId, reason); }
public int SendCloseRequests(int[] orderIds, PositionExitReason reason) { RequestStatus status; return SendCloseRequestsInner(orderIds, reason, out status); }
public RequestStatus SendCloseRequest(MarketOrder order, PositionExitReason reason) { var requestedPrice = 0M; var quote = QuoteStorage.Instance.ReceiveValue(order.Symbol); if (quote != null) requestedPrice = (decimal) (order.Side > 0 ? quote.bid : quote.ask); if (!order.MasterOrder.HasValue) { Logger.DebugFormat("{0}: SendCloseRequest - закрытие ордера {1} - MasterOrder не задан", DealerCode, order.ToStringShort()); return RequestStatus.DealerError; } var status = MakeMarketRequest(new TradeTransactionRequest { Account = order.AccountID, ClosingPositionId = order.MasterOrder, Comment = order.Comment, ExpertComment = order.ExpertComment, Id = order.ID, Magic = order.Magic, RequestedPrice = requestedPrice, SlippageAbs = 0, Side = order.Side, Symbol = order.Symbol, Volume = order.Volume }, order); return status; }
public bool CloseOrder(MarketOrder order, decimal price, PositionExitReason exitReason) { using (var ctx = DatabaseContext.Instance.Make()) { var account = ctx.ACCOUNT.FirstOrDefault(ac => ac.ID == order.AccountID); if (account == null) { Logger.ErrorFormat("Закрытие ордера #{0}: невозможно прочитать данные счета ({1})", order.ID, order.AccountID); return(false); } // провести ордер через биллинг ORDER_BILL bill = null; if (order.State == PositionState.Opened) { bill = BillingManager.ProcessPriceForOrderClosing(order, LinqToEntity.DecorateAccount(account), ctx); } // посчитать результат // и обновить объект order.State = PositionState.Closed; order.PriceExit = (float?)price; var deltaAbs = order.Side * (order.PriceExit.Value - order.PriceEnter); order.ResultPoints = DalSpot.Instance.GetPointsValue(order.Symbol, deltaAbs); var deltaDepo = deltaAbs * order.Volume; var quotes = QuoteStorage.Instance.ReceiveAllData(); string errorStr; var resultedDepo = DalSpot.Instance.ConvertToTargetCurrency(order.Symbol, false, account.Currency, deltaDepo, quotes, out errorStr, false); if (!resultedDepo.HasValue) { Logger.ErrorFormat("#{0} ({1} {2}{3}, {4:f1} пп): ошибка расчета прибыли в валюте депозита - {5}", order.ID, order.Side > 0 ? "B" : "S", order.Symbol, order.Volume, order.ResultPoints, errorStr); return(false); } order.ResultDepo = (float)resultedDepo.Value; //order.Swap = (float)swap; order.ExitReason = exitReason; order.TimeExit = DateTime.Now; var posClosed = LinqToEntity.UndecorateClosedPosition(order); POSITION pos = null; try { // занести ордер в список закрытых позиций (создать новую запись "истории") ctx.POSITION_CLOSED.Add(posClosed); // удалить открытый ордер pos = ctx.POSITION.FirstOrDefault(p => p.ID == order.ID); if (pos == null) { Logger.ErrorFormat("CloseOrder - позиция {0} не найдена", order.ID); ServiceManagerClientManagerProxy.Instance.CloseOrderResponse(null, RequestStatus.ServerError, "crudsav"); return(false); } ctx.POSITION.Remove(pos); // посчитать профиты if (bill != null) { BillingManager.ProcessOrderClosing(order, account, bill, ctx, quotes, brokerRepository.BrokerCurrency); } // сохранить изменения ctx.SaveChanges(); // обновить баланс var resultAbs = Math.Abs(order.ResultDepo); if (!UpdateAccountBalance(ctx, account, (decimal)resultAbs, order.ResultDepo >= 0 ? BalanceChangeType.Profit : BalanceChangeType.Loss, string.Format("результат сделки #{0}", posClosed.ID), DateTime.Now, order.ID)) { Logger.ErrorFormat("Не удалось применить обновление баланса #{0}", posClosed.ID); } } catch (OptimisticConcurrencyException ex) { Logger.Error("CloseOrder - OptimisticConcurrencyException", ex); ctx.Entry(posClosed).State = EntityState.Modified; ((IObjectContextAdapter)ctx).ObjectContext.Refresh(RefreshMode.ClientWins, posClosed); if (pos != null) { ctx.Entry(pos).State = EntityState.Modified; ((IObjectContextAdapter)ctx).ObjectContext.Refresh(RefreshMode.ClientWins, pos); } ctx.SaveChanges(); } catch (Exception ex) { Logger.ErrorFormat("Ошибка закрытия позиции {0} (счет #{1}) (фиксация в БД): {2}", order.ID, order.AccountID, ex); ServiceManagerClientManagerProxy.Instance.CloseOrderResponse(null, RequestStatus.ServerError, "crudsave"); return(false); } } // уведомить клиента ServiceManagerClientManagerProxy.Instance.CloseOrderResponse(order, RequestStatus.OK, ""); // разослать торговый сигнал MakeOrderClosedSignal(order.AccountID, order.ID, (float)price); return(true); }
public RequestStatus SendCloseRequest(ProtectedOperationContext ctx, int accountId, int orderId, PositionExitReason reason) { throw new NotImplementedException(); }
public override RequestStatus SendCloseByTickerRequest(ProtectedOperationContext ctx, int accountId, string ticker, PositionExitReason reason) { return(proxyTrade.proxy.SendCloseByTickerRequest(ctx, accountId, ticker, reason)); }
public abstract RequestStatus SendCloseByTickerRequest(ProtectedOperationContext ctx, int accountId, string ticker, PositionExitReason reason);
private static RequestStatus SendCloseByTickerRequestUnsafe(int accountId, string ticker, PositionExitReason reason) { try { var res = serverProxyTrade.proxy.SendCloseByTickerRequest( CurrentProtectedContext.Instance.MakeProtectedContext(), accountId, ticker, reason); if (res != RequestStatus.OK) { Instance.ShowMsgWindowSafe(new AccountEvent( Localizer.GetString("MessageErrorExecutingOrder"), EnumFriendlyName <RequestStatus> .GetString(res), AccountEventCode.ServerMessage)); } return(res); } catch (Exception ex) { Logger.Error("SendCloseByTickerRequest", ex); return(RequestStatus.NoConnection); } }
public override RequestStatus SendCloseByTickerRequest(ProtectedOperationContext ctx, int accountId, string ticker, PositionExitReason reason) { if (IsDayOff()) { return(RequestStatus.WrongTime); } return(base.SendCloseByTickerRequest(ctx, accountId, ticker, reason)); }
public RequestStatus SendCloseByTickerRequest(ProtectedOperationContext ctx, int accountId, string ticker, PositionExitReason reason) { return(Channel.SendCloseByTickerRequest(ctx, accountId, ticker, reason)); }
public RequestStatus SendCloseRequest(ProtectedOperationContext ctx, int accountId, int orderId, PositionExitReason reason) { return(Channel.SendCloseRequest(ctx, accountId, orderId, reason)); }
private int SendCloseRequestsInner(int[] orderId, PositionExitReason reason, out RequestStatus lastStatus) { var countOk = 0; lastStatus = RequestStatus.OK; try { using (var ctx = DatabaseContext.Instance.Make()) { foreach (var posId in orderId) { var pos = ctx.POSITION.FirstOrDefault(p => p.ID == posId); lastStatus = pos == null ? RequestStatus.NotFound : managerTrade.SendCloseRequest(pos, reason); if (lastStatus == RequestStatus.OK) countOk++; } } } catch (Exception ex) { Logger.Error("Ошибка в PlatformManager.SendCloseRequest", ex); lastStatus = RequestStatus.ServerError; } return countOk; }
public override RequestStatus SendCloseRequest(ProtectedOperationContext ctx, int accountId, int orderId, PositionExitReason reason) { return proxyTrade.proxy.SendCloseRequest(ctx, accountId, orderId, reason); }
public override RequestStatus SendCloseByTickerRequest(ProtectedOperationContext ctx, int accountId, string ticker, PositionExitReason reason) { return proxyTrade.proxy.SendCloseByTickerRequest(ctx, accountId, ticker, reason); }
public RequestStatus SendCloseRequest(int orderId, PositionExitReason reason) { RequestStatus status; SendCloseRequestsInner(new[] { orderId }, reason, out status); return status; }
public override RequestStatus SendCloseRequest(ProtectedOperationContext ctx, int accountId, int orderId, PositionExitReason reason) { return(proxyTrade.proxy.SendCloseRequest(ctx, accountId, orderId, reason)); }
public RequestStatus SendCloseByTickerRequest(ProtectedOperationContext ctx, int accountId, string ticker, PositionExitReason reason) { throw new NotImplementedException(); }
public abstract RequestStatus SendCloseRequest(ProtectedOperationContext ctx, int accountId, int orderId, PositionExitReason reason);
/// <summary> /// Закрытие сделок /// </summary> /// <param name="strId">Уникальные идентификаторы закрываемых сделок, перечисленные через запятую</param> /// <param name="timeExit">Время выхода</param> /// <param name="exitReason">Symbol, Side (в виде Ask и Bid), Price</param> /// <param name="lstPrice">Причина закрытия сделки, указанная пользователем</param> public List <string> ClosingPositions(string strId, DateTime timeExit, PositionExitReason exitReason, List <Tuple <string, int, float> > lstPrice) { Logger.Info("Начинаем закрывать сделки " + strId); var result = new List <string>(); var id = strId.ToIntArrayUniform(); try { using (var ctx = DatabaseContext.Instance.Make()) { // Вытаскиваем все открытые сделки, которые нужно закрыть var selOrders = new List <MarketOrder>(); // ReSharper disable LoopCanBeConvertedToQuery foreach (var order in ctx.POSITION.Where(x => id.Contains(x.ID))) { selOrders.Add(LinqToEntity.DecorateOrder(order)); } // ReSharper restore LoopCanBeConvertedToQuery if (selOrders.Count != id.Length) { Logger.Error("ClosingPositions() - в таблице 'POSITION' не найдены некоторые или все сделки с идентификаторами " + strId); } // Группируем все сделки по счётам var selOrderGroupByAccount = selOrders.GroupBy(x => x.AccountID); // Перебираем все счета foreach (var orderGroup in selOrderGroupByAccount) { // Список удачно закрытых сделок в текущем счёте var successClosedPositions = new List <string>(); var acc = accountRepository.GetAccount(orderGroup.Key); if (acc == null) { Logger.Error("ClosingPositions() - не удалось получить счёт " + orderGroup.Key); continue; } Logger.Info("Начинаем закрывать сделки в счёте " + orderGroup.Key); // Перебираем все сделки в текущем счёте foreach (var order in orderGroup) { #region //Ищем цену выхода, указанную пользователем, для сделок с таким тикером и направлением var priceExitTuple = lstPrice.FirstOrDefault(x => x.Item1 == order.Symbol && x.Item2 == order.Side); if (priceExitTuple == null) { Logger.Error(string.Format("ClosingPositions() - не найдена цена выхода, указанная пользователем, для сделок счёта {0} с тикером {1} и направлением {2}", order.ID, order.Symbol, order.Side)); continue; } var closedOrder = order.MakeCopy(); closedOrder.State = PositionState.Closed; closedOrder.TimeExit = timeExit; closedOrder.PriceExit = priceExitTuple.Item3; closedOrder.ExitReason = exitReason; // посчитать прибыль string errorStr; if (!DealProfitCalculator.CalculateOrderProfit(closedOrder, acc.Currency, priceExitTuple.Item3, out errorStr)) { if (!string.IsNullOrEmpty(errorStr)) { Logger.Error("Сделка " + closedOrder.ID + " не будет закрыта - не удалось пересчитать прибыль : " + errorStr); } continue; } var balance = new BALANCE_CHANGE { AccountID = order.AccountID, ChangeType = closedOrder.ResultBase > 0 ? (int)BalanceChangeType.Profit : (int)BalanceChangeType.Loss, Description = string.Format("результат сделки #{0}", order.ID), Amount = (decimal)Math.Abs(closedOrder.ResultDepo), ValueDate = closedOrder.TimeExit.Value }; // убрать сделку из числа открытых, добавить закрытую и добавить проводку по счету try { // убрать var pos = ctx.POSITION.FirstOrDefault(p => p.ID == order.ID); ctx.POSITION.Remove(pos); Logger.Info("запись о сделке " + order.ID + " удалена из таблици POSITION"); ctx.POSITION_CLOSED.Add(LinqToEntity.UndecorateClosedPosition(closedOrder)); Logger.Info("запись о сделке " + order.ID + " добавленав таблицу POSITION_CLOSED"); // добавить проводку по счету ctx.BALANCE_CHANGE.Add(balance); var acBase = ctx.ACCOUNT.FirstOrDefault(ac => ac.ID == order.AccountID); if (acBase == null) { Logger.Error("ClosingPositions() - не удалось найти счёт " + order.AccountID + " в таблице 'ACCOUNT', что бы добавить проводку"); continue; } acBase.Balance += (decimal)closedOrder.ResultDepo; Logger.Info("Баланс счёта " + order.AccountID + " изменён на величину " + (decimal)closedOrder.ResultDepo); } catch (Exception ex) { Logger.Error("ClosingPositions() - Ошибка при попытке убрать сделку из числа открытых, добавить закрытую и добавить проводку по счету", ex); continue; } #endregion successClosedPositions.Add(order.ID.ToString()); Logger.Error("Сделка " + order.ID + " отредактирована удачно"); } ReCalculateAccountBalance(ctx, acc.ID); Logger.Info("Начинаем сохранять в базу данных изменения по счёту " + orderGroup.Key); ctx.SaveChanges(); result.AddRange(successClosedPositions); } if (result.Count == 0) { Logger.Info("Не удалось закрыть ни одной из указанных сделок"); } else { Logger.Info("Изменения сохранены. Из указанных сделок " + strId + " закрыты следующие: " + string.Join(", ", result)); } } } catch (Exception ex) { Logger.Error("ClosingPositions() - возникла ошибка при попытке сохранить изменения в базу данных. Не удалось закрыть сделки " + strId, ex); } return(result); }
private void TryCloseOrder(MarketOrder pos, PositionExitReason reason) { // проверка - не вызывается ли метод раз за разом для одной и той же позиции, // которую невозможно закрыть, например, из-за недостатка свободной маржи DateTime lastTime; if (orderFloodTimes.TryGetValue(pos.ID, out lastTime)) if (DateTime.Now < lastTime) return; orderFloodTimes.Remove(pos.ID); // отправить запрос proxyTrade.SendCloseRequest(ProtectedOperationContext.MakeServerSideContext(), pos.AccountID, pos.ID, reason); // не допустить забивание потока попытками закрыть позу... orderFloodTimes.Add(pos.ID, DateTime.Now.AddMilliseconds(OrderFloodTimeoutMils)); }
/// <summary> /// Закрытие сделок /// </summary> /// <param name="strId">Уникальные идентификаторы закрываемых сделок, перечисленные через запятую</param> /// <param name="timeExit">Время выхода</param> /// <param name="exitReason">Symbol, Side (в виде Ask и Bid), Price</param> /// <param name="lstPrice">Причина закрытия сделки, указанная пользователем</param> public List<string> ClosingPositions(string strId, DateTime timeExit, PositionExitReason exitReason, List<Tuple<string, int, float>> lstPrice) { Logger.Info("Начинаем закрывать сделки " + strId); var result = new List<string>(); var id = strId.ToIntArrayUniform(); try { using (var ctx = DatabaseContext.Instance.Make()) { // Вытаскиваем все открытые сделки, которые нужно закрыть var selOrders = new List<MarketOrder>(); // ReSharper disable LoopCanBeConvertedToQuery foreach (var order in ctx.POSITION.Where(x => id.Contains(x.ID))) selOrders.Add(LinqToEntity.DecorateOrder(order)); // ReSharper restore LoopCanBeConvertedToQuery if (selOrders.Count != id.Length) Logger.Error("ClosingPositions() - в таблице 'POSITION' не найдены некоторые или все сделки с идентификаторами " + strId); // Группируем все сделки по счётам var selOrderGroupByAccount = selOrders.GroupBy(x => x.AccountID); // Перебираем все счета foreach (var orderGroup in selOrderGroupByAccount) { // Список удачно закрытых сделок в текущем счёте var successClosedPositions = new List<string>(); var acc = accountRepository.GetAccount(orderGroup.Key); if (acc == null) { Logger.Error("ClosingPositions() - не удалось получить счёт " + orderGroup.Key); continue; } Logger.Info("Начинаем закрывать сделки в счёте " + orderGroup.Key); // Перебираем все сделки в текущем счёте foreach (var order in orderGroup) { #region //Ищем цену выхода, указанную пользователем, для сделок с таким тикером и направлением var priceExitTuple = lstPrice.FirstOrDefault(x => x.Item1 == order.Symbol && x.Item2 == order.Side); if (priceExitTuple == null) { Logger.Error(string.Format("ClosingPositions() - не найдена цена выхода, указанная пользователем, для сделок счёта {0} с тикером {1} и направлением {2}", order.ID, order.Symbol, order.Side)); continue; } var closedOrder = order.MakeCopy(); closedOrder.State = PositionState.Closed; closedOrder.TimeExit = timeExit; closedOrder.PriceExit = priceExitTuple.Item3; closedOrder.ExitReason = exitReason; // посчитать прибыль string errorStr; if (!DealProfitCalculator.CalculateOrderProfit(closedOrder, acc.Currency, priceExitTuple.Item3, out errorStr)) { if (!string.IsNullOrEmpty(errorStr)) Logger.Error("Сделка " + closedOrder.ID + " не будет закрыта - не удалось пересчитать прибыль : " + errorStr); continue; } var balance = new BALANCE_CHANGE { AccountID = order.AccountID, ChangeType = closedOrder.ResultBase > 0 ? (int)BalanceChangeType.Profit : (int)BalanceChangeType.Loss, Description = string.Format("результат сделки #{0}", order.ID), Amount = (decimal)Math.Abs(closedOrder.ResultDepo), ValueDate = closedOrder.TimeExit.Value }; // убрать сделку из числа открытых, добавить закрытую и добавить проводку по счету try { // убрать var pos = ctx.POSITION.FirstOrDefault(p => p.ID == order.ID); ctx.POSITION.Remove(pos); Logger.Info("запись о сделке " + order.ID + " удалена из таблици POSITION"); ctx.POSITION_CLOSED.Add(LinqToEntity.UndecorateClosedPosition(closedOrder)); Logger.Info("запись о сделке " + order.ID + " добавленав таблицу POSITION_CLOSED"); // добавить проводку по счету ctx.BALANCE_CHANGE.Add(balance); var acBase = ctx.ACCOUNT.FirstOrDefault(ac => ac.ID == order.AccountID); if (acBase == null) { Logger.Error("ClosingPositions() - не удалось найти счёт " + order.AccountID + " в таблице 'ACCOUNT', что бы добавить проводку"); continue; } acBase.Balance += (decimal)closedOrder.ResultDepo; Logger.Info("Баланс счёта " + order.AccountID + " изменён на величину " + (decimal)closedOrder.ResultDepo); } catch (Exception ex) { Logger.Error("ClosingPositions() - Ошибка при попытке убрать сделку из числа открытых, добавить закрытую и добавить проводку по счету", ex); continue; } #endregion successClosedPositions.Add(order.ID.ToString()); Logger.Error("Сделка " + order.ID + " отредактирована удачно"); } ReCalculateAccountBalance(ctx, acc.ID); Logger.Info("Начинаем сохранять в базу данных изменения по счёту " + orderGroup.Key); ctx.SaveChanges(); result.AddRange(successClosedPositions); } if (result.Count == 0) Logger.Info("Не удалось закрыть ни одной из указанных сделок"); else Logger.Info("Изменения сохранены. Из указанных сделок " + strId + " закрыты следующие: " + string.Join(", ", result)); } } catch (Exception ex) { Logger.Error("ClosingPositions() - возникла ошибка при попытке сохранить изменения в базу данных. Не удалось закрыть сделки " + strId, ex); } return result; }
public bool CloseOrder(MarketOrder order, decimal price, PositionExitReason exitReason) { using (var ctx = DatabaseContext.Instance.Make()) { var account = ctx.ACCOUNT.FirstOrDefault(ac => ac.ID == order.AccountID); if (account == null) { Logger.ErrorFormat("Закрытие ордера #{0}: невозможно прочитать данные счета ({1})", order.ID, order.AccountID); return false; } // провести ордер через биллинг ORDER_BILL bill = null; if (order.State == PositionState.Opened) bill = BillingManager.ProcessPriceForOrderClosing(order, LinqToEntity.DecorateAccount(account), ctx); // посчитать результат // и обновить объект order.State = PositionState.Closed; order.PriceExit = (float?)price; var deltaAbs = order.Side * (order.PriceExit.Value - order.PriceEnter); order.ResultPoints = DalSpot.Instance.GetPointsValue(order.Symbol, deltaAbs); var deltaDepo = deltaAbs * order.Volume; var quotes = QuoteStorage.Instance.ReceiveAllData(); string errorStr; var resultedDepo = DalSpot.Instance.ConvertToTargetCurrency(order.Symbol, false, account.Currency, deltaDepo, quotes, out errorStr, false); if (!resultedDepo.HasValue) { Logger.ErrorFormat("#{0} ({1} {2}{3}, {4:f1} пп): ошибка расчета прибыли в валюте депозита - {5}", order.ID, order.Side > 0 ? "B" : "S", order.Symbol, order.Volume, order.ResultPoints, errorStr); return false; } order.ResultDepo = (float)resultedDepo.Value; //order.Swap = (float)swap; order.ExitReason = exitReason; order.TimeExit = DateTime.Now; var posClosed = LinqToEntity.UndecorateClosedPosition(order); POSITION pos = null; try { // занести ордер в список закрытых позиций (создать новую запись "истории") ctx.POSITION_CLOSED.Add(posClosed); // удалить открытый ордер pos = ctx.POSITION.FirstOrDefault(p => p.ID == order.ID); if (pos == null) { Logger.ErrorFormat("CloseOrder - позиция {0} не найдена", order.ID); ServiceManagerClientManagerProxy.Instance.CloseOrderResponse(null, RequestStatus.ServerError, "crudsav"); return false; } ctx.POSITION.Remove(pos); // посчитать профиты if (bill != null) BillingManager.ProcessOrderClosing(order, account, bill, ctx, quotes, brokerRepository.BrokerCurrency); // сохранить изменения ctx.SaveChanges(); // обновить баланс var resultAbs = Math.Abs(order.ResultDepo); if (!UpdateAccountBalance(ctx, account, (decimal)resultAbs, order.ResultDepo >= 0 ? BalanceChangeType.Profit : BalanceChangeType.Loss, string.Format("результат сделки #{0}", posClosed.ID), DateTime.Now, order.ID)) Logger.ErrorFormat("Не удалось применить обновление баланса #{0}", posClosed.ID); } catch (OptimisticConcurrencyException ex) { Logger.Error("CloseOrder - OptimisticConcurrencyException", ex); ctx.Entry(posClosed).State = EntityState.Modified; ((IObjectContextAdapter)ctx).ObjectContext.Refresh(RefreshMode.ClientWins, posClosed); if (pos != null) { ctx.Entry(pos).State = EntityState.Modified; ((IObjectContextAdapter)ctx).ObjectContext.Refresh(RefreshMode.ClientWins, pos); } ctx.SaveChanges(); } catch (Exception ex) { Logger.ErrorFormat("Ошибка закрытия позиции {0} (счет #{1}) (фиксация в БД): {2}", order.ID, order.AccountID, ex); ServiceManagerClientManagerProxy.Instance.CloseOrderResponse(null, RequestStatus.ServerError, "crudsave"); return false; } } // уведомить клиента ServiceManagerClientManagerProxy.Instance.CloseOrderResponse(order, RequestStatus.OK, ""); // разослать торговый сигнал MakeOrderClosedSignal(order.AccountID, order.ID, (float)price); return true; }
public RequestStatus SendCloseRequest(MarketOrder order, PositionExitReason reason) { // получить счет RequestStatus error; var acDecorated = ServerInterface.GetAccount(order.AccountID); if (acDecorated == null) return RequestStatus.ServerError; // подготовить запрос TradeSharp.ProviderProxyContract.Entity.MarketOrder request; if (!MakeMarketRequest(acDecorated, order.Symbol, order.Magic, order.Volume, -order.Side, OrderType.Market, 0, 0, string.Format("close order #{0}", order.ID), order.ID, order.Comment, order.ExpertComment, order.TrailLevel1, order.TrailTarget1, out error, out request)) return error; exitReasonByOrderId.UpdateValues(order.ID, reason); // отправить запрос на вход в рынок (оно же - закрытие позиции) в соотв сессию if (!request.SendToQueue(false)) { errorStorage.AddMessage(new ErrorMessage(DateTime.Now, ErrorMessageType.ОшибкаОтправки, "Невозможно отправить сообщение (CloseOrder) в очередь MQ", null)); return RequestStatus.DealerError; } return RequestStatus.OK; }
/// <summary> /// Close position request /// </summary> protected RequestStatus CloseMarketOrder(int orderId, PositionExitReason reason = PositionExitReason.ClosedByRobot) { return(robotContext.SendCloseRequest(protectedContext.MakeProtectedContext(), robotContext.AccountInfo.ID, orderId, reason)); }
private void ClosePositionAndCalculateProfit(MarketOrder pos, QuoteData quote, PositionExitReason reason) { pos.PriceExit = pos.Side < 0 ? quote.ask : quote.bid; // убираем проскальзывания на истории if (pos.StopLoss != null && pos.StopLoss != 0) { if ((pos.StopLoss > pos.PriceExit && pos.Side == 1) || (pos.StopLoss < pos.PriceExit && pos.Side == -1)) { pos.PriceExit = pos.StopLoss; } } else if (pos.TakeProfit != null && pos.TakeProfit != 0) { if ((pos.TakeProfit < pos.PriceExit && pos.Side == 1) || (pos.TakeProfit > pos.PriceExit && pos.Side == -1)) { pos.PriceExit = pos.TakeProfit; } } pos.TimeExit = curModelTime; //quote.time; pos.State = PositionState.Closed; var deltaAbs = pos.Side * (pos.PriceExit.Value - pos.PriceEnter); pos.ResultPoints = DalSpot.Instance.GetPointsValue(pos.Symbol, deltaAbs); pos.ResultDepo = (float)profitCalculator.CalculatePositionProfit(pos, AccountInfo.Currency, quotesStorage.ReceiveAllData()); pos.ResultDepo = pos.ResultDepo; pos.ExitReason = reason; // скорректировать баланс AccountInfo.Balance += (decimal)pos.ResultDepo; // обновить историю и убрать позицию из списка posHistory.Add(pos); Positions.Remove(pos); }
/// <summary> /// Close position request /// </summary> protected RequestStatus CloseMarketOrder(int orderId, PositionExitReason reason = PositionExitReason.ClosedByRobot) { return robotContext.SendCloseRequest(protectedContext.MakeProtectedContext(), robotContext.AccountInfo.ID, orderId, reason); }