Exemple #1
0
 /// <summary>
 /// получить закрытые ордера по дате закрытия
 /// </summary>
 public RequestStatus GetHistoryOrdersByCloseDate(int?accountId, DateTime?startDate,
                                                  out List <MarketOrder> orders)
 {
     using (var ctx = DatabaseContext.Instance.Make())
     {
         try
         {
             var positions = from pos in ctx.POSITION_CLOSED
                             where
                             pos.AccountID == (accountId ?? pos.AccountID) &&
                             (pos.TimeExit >= startDate) || (!startDate.HasValue)
                             select pos;
             orders = new List <MarketOrder>();
             // ReSharper disable LoopCanBeConvertedToQuery
             foreach (var position in positions)
             // ReSharper restore LoopCanBeConvertedToQuery
             {
                 orders.Add(LinqToEntity.DecorateOrder(position));
             }
             return(RequestStatus.OK);
         }
         catch (Exception ex)
         {
             orders = null;
             Logger.ErrorFormat("Ошибка в GetHistoryOrdersByCloseDate({0}): {1}", accountId, ex);
             return(RequestStatus.ServerError);
         }
     }
 }
Exemple #2
0
 /// <summary>
 /// получить список открытых позиций
 /// </summary>
 public RequestStatus GetMarketOrders(int accountId, out List <MarketOrder> orders)
 {
     using (var ctx = DatabaseContext.Instance.Make())
         try
         {
             var positions = from pos in ctx.POSITION
                             where (pos.State == (int)(PositionState.Opened) || pos.State == (int)(PositionState.StartOpened) ||
                                    pos.State == (int)(PositionState.StartClosed)) && pos.AccountID == accountId
                             select pos;
             orders = new List <MarketOrder>();
             // ReSharper disable LoopCanBeConvertedToQuery
             foreach (var position in positions)
             // ReSharper restore LoopCanBeConvertedToQuery
             {
                 orders.Add(LinqToEntity.DecorateOrder(position));
             }
             return(RequestStatus.OK);
         }
         catch (Exception ex)
         {
             orders = null;
             Logger.ErrorFormat("Ошибка в GetMarketOrders({0}): {1}", accountId, ex);
             return(RequestStatus.ServerError);
         }
 }
        /// <summary>
        /// проверить SL, TP, трейлинги
        /// </summary>
        private void CheckOrders()
        {
            if (!WorkingDay.Instance.IsWorkingDay(DateTime.Now))
            {
                return;
            }

            var curPrices = QuoteStorage.Instance.ReceiveAllData();

            try
            {
                using (var ctx = DatabaseContext.Instance.Make())
                {
                    // позиции
                    foreach (var order in ctx.POSITION)
                    {
                        if ((PositionState)order.State != PositionState.Opened)
                        {
                            continue;
                        }
                        try
                        {
                            tradeManager.CheckOrder(LinqToEntity.DecorateOrder(order), curPrices);
                        }
                        catch (Exception ex)
                        {
                            Logger.Error("AccountCheckStream.CheckOrder() error", ex);
                        }
                    }

                    // отложенные ордера
                    foreach (var order in ctx.PENDING_ORDER)
                    {
                        try
                        {
                            tradeManager.CheckPendingOrder(LinqToEntity.DecoratePendingOrder(order), curPrices);
                        }
                        catch (Exception ex)
                        {
                            Logger.Error("AccountCheckStream.CheckPendingOrder() error", ex);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error("Ошибка в CheckOrders()", ex);
            }
        }
Exemple #4
0
 /// <summary>
 /// Заполняет список allOrders позициями (сделками) из БД
 /// </summary>
 private void MakeOrders()
 {
     allOrders = new List <MarketOrder>();
     using (var ctx = DatabaseContext.Instance.Make())
     {
         foreach (var pos in ctx.POSITION)
         {
             allOrders.Add(LinqToEntity.DecorateOrder(pos));
         }
         foreach (var pos in ctx.POSITION_CLOSED)
         {
             allOrders.Add(LinqToEntity.DecorateOrder(pos));
         }
     }
 }
Exemple #5
0
        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));
        }
Exemple #6
0
        /// <summary>
        /// формирует модель для представления PositionDetails
        /// </summary>
        /// <param name="positionId">Уникальным идентификатором является сделки</param>
        /// <remarks>Не тестируется</remarks>
        public MarketOrder GetPositionItemDetails(int positionId)
        {
            MarketOrder positionItem = null;

            try
            {
                using (var ctx = DatabaseContext.Instance.Make())
                {
                    // Проверяем, есть ли указанная сделка среди открытых (потому что их меньше), если нет - ищём её среди закрытых
                    if (ctx.POSITION.Any(x => x.ID == positionId))
                    {
                        POSITION position;
                        try
                        {
                            position = ctx.POSITION.Single(x => x.ID == positionId);
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(string.Format("GetPositionItemDetails() - При запросе подробностей о сделке c id {0} не удалось получить конкретный элемент из POSITION", positionId), ex);
                            return(null);
                        }
                        positionItem = LinqToEntity.DecorateOrder(position);
                    }
                    else
                    {
                        POSITION_CLOSED position;
                        try
                        {
                            position = ctx.POSITION_CLOSED.Single(x => x.ID == positionId);
                        }
                        catch (Exception ex)
                        {
                            Logger.Error(string.Format("GetPositionItemDetails() - При запросе подробностей о сделке c id {0} не удалось получить конкретный элемент из POSITION_CLOSED", positionId), ex);
                            return(null);
                        }
                        positionItem = LinqToEntity.DecorateOrder(position);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error("GetPositionItemDetails Exception", ex);
            }
            return(positionItem);
        }
        /// <summary>
        /// вернуть данные по счету для фермы роботов
        /// </summary>
        public bool GetAccountData(string login, string pwrd, int accountId,
                                   out Account account, out List <MarketOrder> openedOrders)
        {
            openedOrders = new List <MarketOrder>();
            account      = null;

            try
            {
                // проверить логин - пароль
                using (var db = DatabaseContext.Instance.Make())
                {
                    var user = db.PLATFORM_USER.FirstOrDefault(u => u.Login == login);
                    if (user == null)
                    {
                        return(false);
                    }
                    if (user.Password != pwrd)
                    {
                        return(false);
                    }

                    // выдернуть ордер из списка
                    var accountBase = db.ACCOUNT.FirstOrDefault(a => a.ID == accountId);
                    if (accountBase == null)
                    {
                        return(false);
                    }
                    account = LinqToEntity.DecorateAccount(accountBase);

                    // получить сделки
                    var lstPos = db.POSITION.Where(p => p.AccountID == accountId).ToList();
                    foreach (var pos in lstPos)
                    {
                        openedOrders.Add(LinqToEntity.DecorateOrder(pos));
                    }
                }
                return(true);
            }
            catch (Exception ex)
            {
                Logger.Error("Ошибка в GetAccountData()", ex);
                return(false);
            }
        }
Exemple #8
0
        public Dictionary <int, List <MarketOrder> > GetSignallersOpenTrades(int accountId)
        {
            var ordersByService = new Dictionary <int, List <MarketOrder> >();

            try
            {
                using (var ctx = DatabaseContext.Instance.Make())
                {
                    var subscribedServices =
                        (from sub in ctx.SUBSCRIPTION
                         join act in ctx.PLATFORM_USER_ACCOUNT on sub.User equals act.PlatformUser
                         join srv in ctx.SERVICE on sub.Service equals srv.ID
                         where act.RightsMask == (int)AccountRights.Управление && act.Account == accountId
                         select srv).ToList();
                    var accountsOfManagers = subscribedServices.Select(s => s.AccountId).ToList();

                    // получить сделки по счетам из списка signallerIds
                    var dealsList = ctx.POSITION.Where(p => p.State == (int)PositionState.Opened &&
                                                       accountsOfManagers.Contains(p.AccountID));
                    foreach (var deal in dealsList)
                    {
                        var dealDec   = LinqToEntity.DecorateOrder(deal);
                        var serviceId = subscribedServices.First(a => a.AccountId == dealDec.AccountID).ID;

                        List <MarketOrder> ordersLst;
                        if (ordersByService.TryGetValue(serviceId, out ordersLst))
                        {
                            ordersLst.Add(dealDec);
                            continue;
                        }
                        ordersLst = new List <MarketOrder> {
                            dealDec
                        };
                        ordersByService.Add(serviceId, ordersLst);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("Ошибка в GetSignallersOpenTrades({0}): {1}", accountId, ex);
            }
            return(ordersByService);
        }
Exemple #9
0
        //TODO - Метод не оптимальный. Для каждой вытащенной записи из БД в цикле foreach производится мапинг в "PositionItem" (Для каждой по отдельности).
        //TODO - Метод не оптимальный. Происходи 2 обращения к БД - нуждо использовать join или unit
        /// <summary>
        /// Получить список сделок по их уникальным идентификаторам
        /// </summary>
        /// <param name="idList">Массив уникальных идентификаторов позиций, которые нужно получить</param>
        /// <remarks>Тестируется</remarks>
        public List <PositionItem> GetPositionsById(int[] idList)
        {
            var result = new List <PositionItem>();

            if (idList == null || idList.Length == 0)
            {
                return(result);
            }
            try
            {
                using (var ctx = DatabaseContext.Instance.Make())
                {
                    // ReSharper disable LoopCanBeConvertedToQuery
                    foreach (var source in ctx.POSITION.Where(x => idList.Contains(x.ID)))
                    // ReSharper restore LoopCanBeConvertedToQuery
                    {
                        var marketOrder  = LinqToEntity.DecorateOrder(source);
                        var positionItem = new PositionItem(marketOrder);
                        result.Add(positionItem);
                    }

                    // ReSharper disable LoopCanBeConvertedToQuery
                    foreach (var source in ctx.POSITION_CLOSED.Where(x => idList.Contains(x.ID)))
                    // ReSharper restore LoopCanBeConvertedToQuery
                    {
                        var marketOrder = LinqToEntity.DecorateOrder(source);

                        //var positionItem = marketOrder as PositionItem;

                        var positionItem = new PositionItem(marketOrder);
                        result.Add(positionItem);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error("GetPositionsById()", ex);
            }
            return(result);
        }
 private void PerformStopout(ACCOUNT ac, Dictionary <string, QuoteData> quotes,
                             TradeSharpConnection ctx)
 {
     try
     {
         var sb     = new StringBuilder();
         var posReq = from pos in ctx.POSITION where pos.AccountID == ac.ID &&
                      pos.State == (int)PositionState.Opened select pos;
         var totalCount  = 0;
         var closedCount = 0;
         foreach (var pos in posReq)
         {
             totalCount++;
             // закрыть ордер
             QuoteData quote;
             quotes.TryGetValue(pos.Symbol, out quote);
             var price = quote == null ? 0 : quote.GetPrice(pos.Side > 0 ? QuoteType.Bid : QuoteType.Ask);
             if (price == 0)
             {
                 sb.AppendFormat("Невозможно закрыть ордер {0} ({1}): нет цены", pos.ID, pos.Symbol);
                 continue;
             }
             if (orderRepository.CloseOrder(LinqToEntity.DecorateOrder(pos),
                                            (decimal)price, PositionExitReason.Stopout))
             {
                 closedCount++;
             }
             sb.AppendFormat("позиция {0} закрыта по цене {1:f4} - стопаут. ", pos.ID, price);
         }
         if (ShouldLogStopout(ac.ID))
         {
             Logger.Info(string.Format("Счет {0}. Закрыто {1} из {2} позиций. ", ac.ID, closedCount, totalCount) + sb);
         }
     }
     catch (Exception ex)
     {
         loggerNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMagicStopout, 60 * 1000,
                                                  "Ошибка при выполнении стопаута {0}: {1}", ac.ID, ex);
     }
 }
Exemple #11
0
 public MarketOrder GetMarketOrder(int orderId)
 {
     using (var ctx = DatabaseContext.Instance.Make())
         try
         {
             var ps = from pos in ctx.POSITION
                      where pos.ID == orderId
                      select pos;
             // ReSharper disable LoopCanBeConvertedToQuery
             foreach (var position in ps)
             {
                 // ReSharper restore LoopCanBeConvertedToQuery
                 return(LinqToEntity.DecorateOrder(position));
             }
             return(null);
         }
         catch (Exception ex)
         {
             Logger.ErrorFormat("Ошибка в GetMarketOrder({0}): {1}", orderId, ex);
             return(null);
         }
 }
Exemple #12
0
        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 EditPosition(string hash, string userLogin, long localTime, int accountId,
                                          int orderId,
                                          float stopLoss, float takeProfit, int magic, string comment)
        {
            try
            {
                using (var ctx = DatabaseContext.Instance.Make())
                {
                    var status = CheckCredentials(hash, userLogin, localTime, accountId, true, ctx);
                    if (status != RequestStatus.OK)
                    {
                        return(status);
                    }

                    var pos = ctx.POSITION.FirstOrDefault(p => p.AccountID == accountId && p.ID == orderId);
                    if (pos == null)
                    {
                        return(RequestStatus.IncorrectData);
                    }

                    var order = LinqToEntity.DecorateOrder(pos);
                    order.StopLoss   = stopLoss == 0 ? (float?)null : stopLoss;
                    order.TakeProfit = takeProfit == 0 ? (float?)null : takeProfit;
                    order.Magic      = magic;
                    order.Comment    = comment;

                    status = managerTrade.SendEditMarketRequest(ProtectedOperationContext.MakeServerSideContext(), order);
                    return(status);
                }
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("Ошибка в EditPosition(user={0}, pos={1}): {2}",
                                   userLogin, orderId, ex);
                return(RequestStatus.ServerError);
            }
        }
Exemple #14
0
        public static int GetNewOrderVolume(TradeSignalActionTrade action,
                                            TradeSharpConnection ctx, SUBSCRIPTION_SIGNAL tradeSets)
        {
            // получить ордера по счету, посчитать актуальный баланс (средства) счета
            try
            {
                var account = ctx.ACCOUNT.FirstOrDefault(a => a.ID == tradeSets.TargetAccount.Value);
                if (account == null)
                {
                    Logger.ErrorFormat("Ошибка при расчете объема по счету {0}, ордер {1}: счет не найден",
                                       tradeSets.TargetAccount, action.OrderId);
                    return(0);
                }

                var equity = (double)account.Balance;

                // ордера
                var orders = ctx.POSITION.Where(p => p.AccountID == tradeSets.TargetAccount &&
                                                p.State == (int)PositionState.Opened).ToList().Select(o => LinqToEntity.DecorateOrder(o)).ToList();

                // проверить - нет ли противоположного ордера?
                var quotes = Contract.Util.BL.QuoteStorage.Instance.ReceiveAllData();

                if (orders.Count > 0)
                {
                    if (!(tradeSets.HedgingOrdersEnabled ?? false))
                    {
                        var hasOrdersCounter = orders.Any(p => p.Symbol == action.Ticker && p.Side != action.Side);
                        if (hasOrdersCounter)
                        {
                            logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Info, LogMsgContraOrders,
                                                                  1000 * 60 * 90, "Ордер {0} {1}, счет {2} - есть встречные ордера",
                                                                  action.Side > 0 ? "BUY" : "SELL", action.Ticker, tradeSets.TargetAccount);
                            return(0);
                        }
                    }

                    // посчитать профит по позам
                    bool noQuoteError;
                    var  openResult = DalSpot.Instance.CalculateOpenedPositionsCurrentResult(
                        orders, quotes, account.Currency, out noQuoteError);
                    if (noQuoteError)
                    {
                        logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMsgVolmCalcNoQuote,
                                                              1000 * 60 * 90, "GetNewOrderVolume - нет котировки");
                        return(0);
                    }
                    equity += openResult;
                }

                if (equity <= 0)
                {
                    logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMsgEquityIsNil,
                                                          1000 * 60 * 90, "Баланс счета {0}: {1}", account.ID, equity);
                    return(0);
                }

                // посчитать объем
                var volumeDepo = (tradeSets.PercentLeverage ?? 100) / 100f * equity * (double)action.Leverage;
                // пересчитать объем в базовую валюту
                string errorStr;
                var    volumeBase = DalSpot.Instance.ConvertToTargetCurrency(action.Ticker, true, account.Currency, volumeDepo,
                                                                             quotes, out errorStr);
                if (!volumeBase.HasValue)
                {
                    logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMsgVolmToBase,
                                                          1000 * 60 * 90, "GetNewOrderVolume - невозможно посчитать объем по сделке {0}, валюта счета {1}: {2}",
                                                          action.Ticker, account.Currency, errorStr);
                    return(0);
                }

                // округлить объем
                var volume = MarketOrder.RoundDealVolume((int)volumeBase,
                                                         (VolumeRoundType)(tradeSets.VolumeRound ?? (int)VolumeRoundType.Ближайшее),
                                                         tradeSets.MinVolume ?? 10000, tradeSets.StepVolume ?? 10000);
                if (volume == 0)
                {
                    var msg = string.Format("Полученный объем входа ({0}) округлен до 0", (int)volumeBase);
                    logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error,
                                                          LogMsgVolmRoundToZero, 1000 * 60 * 90, msg);
                    return(0);
                }

                // проверить на превышение плеча
                if ((tradeSets.MaxLeverage ?? 0) > 0)
                {
                    var totalExposure     = 0M;
                    var ordersBySignaller = orders.Where(position =>
                    {
                        int orderSignalCatId, parentDealId;
                        if (MarketOrder.GetTradeSignalFromDeal(position, out orderSignalCatId, out parentDealId))
                        {
                            return(orderSignalCatId == action.ServiceId);
                        }
                        return(false);
                    }).GroupBy(o => o.Symbol).ToDictionary(o => o.Key, o => o.ToList());

                    foreach (var orderByTicker in ordersBySignaller)
                    {
                        // суммарная экспозиция
                        var exp = orderByTicker.Value.Sum(o => o.Side * o.Volume);
                        if (orderByTicker.Key == action.Ticker)
                        {
                            exp += action.Side * volume;
                        }
                        if (exp == 0)
                        {
                            continue;
                        }

                        // перевести экспозицию в валюту депозита
                        var expBase = DalSpot.Instance.ConvertToTargetCurrency(action.Ticker, true, account.Currency,
                                                                               volumeDepo,
                                                                               quotes, out errorStr);
                        if (!expBase.HasValue)
                        {
                            logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMsgExposureNoQuote,
                                                                  1000 * 60 * 90,
                                                                  "GetNewOrderVolume - невозможно посчитать экспозицию по сделке " +
                                                                  "{0}, тикер {1}: {2}",
                                                                  action.Ticker, orderByTicker.Key, errorStr);
                            return(0);
                        }

                        totalExposure += Math.Abs(expBase.Value);
                    }
                    var totalLeverage = (double)totalExposure / equity;
                    // ReSharper disable PossibleInvalidOperationException
                    if (totalLeverage > tradeSets.MaxLeverage.Value)
                    // ReSharper restore PossibleInvalidOperationException
                    {
                        logNoFlood.LogMessageFormatCheckFlood(LogEntryType.Error, LogMsgMaxLevExceeded,
                                                              1000 * 60 * 90,
                                                              "GetNewOrderVolume - макс плечо ({0}) превышено, " +
                                                              "тикер {1}: плечо составит {2}",
                                                              tradeSets.MaxLeverage.Value,
                                                              action.Ticker, totalLeverage);
                        return(0);
                    }
                }

                return(volume);
            }
            catch (Exception ex)
            {
                Logger.ErrorFormat("Ошибка при расчете объема по счету {0}, ордер {1}: {2}",
                                   tradeSets.TargetAccount, action.OrderId, ex);
            }

            return(0);
        }
Exemple #15
0
        /// <summary>
        /// Редактирование 'опасных' полей сделок
        /// </summary>
        /// <param name="strId">Уникальные идентификаторы редактируемых сделок</param>
        /// <param name="currentState">Статус редактируемых сделок</param>
        /// <param name="newTicker">Новое значение инструмента</param>
        /// <param name="newSide">Новое значение типа сделки</param>
        /// <param name="newVolume">Новое значение объёма сделки</param>
        /// <param name="newEnterPrice">Новое значение цены входа</param>
        /// <param name="newExitPrice">Новое значение цены выхода</param>
        public bool EditDangerDeal(string strId, PositionState currentState, string newTicker, int?newSide, int?newVolume, float?newEnterPrice, float?newExitPrice)
        {
            var id = strId.ToIntArrayUniform();

            using (var ctx = DatabaseContext.Instance.Make())
            {
                var selOrders = new List <MarketOrder>();
                // ReSharper disable LoopCanBeConvertedToQuery
                if (currentState == PositionState.Closed)
                {
                    foreach (var order in ctx.POSITION_CLOSED.Where(x => id.Contains(x.ID)))
                    {
                        selOrders.Add(LinqToEntity.DecorateOrder(order));
                    }
                }
                else
                {
                    foreach (var order in ctx.POSITION.Where(x => id.Contains(x.ID)))
                    {
                        selOrders.Add(LinqToEntity.DecorateOrder(order));
                    }
                }
                // ReSharper restore LoopCanBeConvertedToQuery

                // Группируем все сделки по счётам
                var selOrderGroupByAccount = selOrders.GroupBy(x => x.AccountID);
                // Идём по счетам в группе
                foreach (var selOrderGroup in selOrderGroupByAccount)
                {
                    var acc = accountRepository.GetAccount(selOrderGroup.Key);

                    try
                    {
                        // Идём по сделкам в счёте
                        foreach (var order in selOrderGroup)
                        {
                            decimal?sl = null;
                            if (order.StopLoss.HasValue)
                            {
                                sl = Convert.ToDecimal(order.StopLoss);
                            }

                            decimal?tp = null;
                            if (order.TakeProfit.HasValue)
                            {
                                tp = Convert.ToDecimal(order.TakeProfit);
                            }

                            var timeEnter = order.TimeEnter;
                            var timeExit  = order.TimeExit;
                            var price     = newEnterPrice.HasValue ? newEnterPrice : order.PriceEnter;
                            var priceExit = newExitPrice.HasValue ? newExitPrice : order.PriceExit;
                            var volume    = newVolume.HasValue ? newVolume : order.Volume;
                            var symbol    = !string.IsNullOrEmpty(newTicker) && newTicker.ToLower() != "null" ? newTicker : order.Symbol;
                            var side      = newSide.HasValue ? newSide : order.Side;
                            var state     = order.State;
                            #region

                            MarketOrder ordClosed = null;
                            if (state == PositionState.Closed)
                            {
                                // посчитать профит по сделке
                                ordClosed           = order.MakeCopy();
                                ordClosed.State     = PositionState.Closed;
                                ordClosed.PriceExit = priceExit.Value;
                                ordClosed.TimeExit  = timeExit.Value;
                                string errorStr = null;
                                if (!priceExit.HasValue || !DealProfitCalculator.CalculateOrderProfit(ordClosed, acc.Currency, priceExit.Value, out errorStr))
                                {
                                    if (!string.IsNullOrEmpty(errorStr))
                                    {
                                        Logger.Error("Сделка " + order.ID + " не будет закрыта : " + errorStr);
                                    }
                                    else
                                    {
                                        Logger.Error("Сделка " + order.ID + ". не будет закрыта : не указана priceExit.");
                                    }
                                    continue;
                                }
                            }

                            try
                            {
                                //Если сделка из 'открытых'
                                if (state != PositionState.Closed)
                                {
                                    // поправить открытую позицию
                                    var pos = ctx.POSITION.First(p => p.ID == order.ID);
                                    pos.PriceEnter = Convert.ToDecimal(price.Value);
                                    pos.TimeEnter  = timeEnter;
                                    pos.Stoploss   = sl;
                                    pos.Takeprofit = tp;
                                    pos.Volume     = volume.Value;
                                    pos.Symbol     = symbol;
                                    pos.Side       = side.Value;
                                    pos.State      = (int)state;
                                }
                                else
                                {
                                    #region поправить закрытую позу и скорректировать результат

                                    var pos = ctx.POSITION_CLOSED.First(p => p.ID == order.ID);
                                    pos.PriceEnter   = Convert.ToDecimal(price.Value);
                                    pos.TimeEnter    = timeEnter;
                                    pos.Stoploss     = sl;
                                    pos.Takeprofit   = tp;
                                    pos.Volume       = volume.Value;
                                    pos.Symbol       = symbol;
                                    pos.Side         = side.Value;
                                    pos.PriceExit    = Convert.ToDecimal(priceExit.Value);
                                    pos.TimeExit     = timeExit.Value;
                                    pos.ResultDepo   = (decimal)ordClosed.ResultDepo;
                                    pos.ResultBase   = (decimal)ordClosed.ResultBase;
                                    pos.ResultPoints = (decimal)ordClosed.ResultPoints;

                                    #endregion

                                    // поправить проводку и баланс
                                    UpdateBalanceChange(ctx, ordClosed, false);
                                }
                            }
                            catch (Exception ex)
                            {
                                Logger.Error("Ошибка при редактировании сделки " + order.ID, ex);
                            }
                            #endregion

                            Logger.Info("Сделка " + order.ID + " отредактирована удачно.");
                        }
                        // коммит
                        ctx.SaveChanges();
                    }
                    catch (Exception ex)
                    {
                        Logger.Error("EditDangerDeal", ex);
                        return(false);
                    }

                    if (currentState == PositionState.Closed)
                    {
                        ReCalculateAccountBalance(ctx, acc.ID);
                    }
                }
                return(true);
            }
        }
Exemple #16
0
        public List <int> CancelingClosedPositions(string strId)
        {
            Logger.Info("Начинаем отменяем закрытые сделки " + strId);

            var result = new List <int>();
            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_CLOSED.Where(x => id.Contains(x.ID)))
                    {
                        selOrders.Add(LinqToEntity.DecorateOrder(order));
                    }
                    // ReSharper restore LoopCanBeConvertedToQuery

                    if (selOrders.Count != id.Length)
                    {
                        Logger.Error("CancelingClosedPositions() - в таблице 'POSITION_CLOSED' не найдены некоторые или все сделки с идентификаторами " + strId);
                    }

                    // Группируем все сделки по счетам
                    var selOrderGroupByAccount = selOrders.GroupBy(x => x.AccountID);

                    // Перебираем все счета
                    foreach (var orderGroup in selOrderGroupByAccount)
                    {
                        // Список удачно отменённых закрытых сделок текущего счёта
                        var successCanceledPositions = new List <int>();

                        var acc = accountRepository.GetAccount(orderGroup.Key);
                        if (acc == null)
                        {
                            Logger.Error("CancelingClosedPositions() - не удалось получить счёт " + orderGroup.Key);
                            continue;
                        }

                        Logger.Info("Начинаем отменять закрытые сделки в счёте " + orderGroup.Key);
                        Logger.Debug(string.Format("для счёта {0} количество BALANCE_CHANGE до отмены открытых сделок равно {1}",
                                                   orderGroup.Key, ctx.BALANCE_CHANGE.Count(c => c.AccountID == orderGroup.Key)));

                        // Перебираем все сделки в текущем счёте
                        foreach (var order in orderGroup)
                        {
                            #region убрать сделку из числа закрытых
                            try
                            {
                                var pos = ctx.POSITION_CLOSED.FirstOrDefault(p => p.ID == order.ID);
                                if (pos == null)
                                {
                                    Logger.Error("CancelingClosedPositions() - запись о сделке " + order.ID + " не найдена в таблице POSITION_CLOSED. Сделка не может быть отменена");
                                    continue;
                                }
                                ctx.POSITION_CLOSED.Remove(pos);
                                Logger.Info("запись о сделке " + order.ID + " удалена из таблици POSITION_CLOSED");
                            }
                            catch (Exception ex)
                            {
                                Logger.Error("CancelingClosedPositions() - Ошибка при попытке убрать сделку из числа закрытых", ex);
                                continue;
                            }
                            #endregion


                            var dealDescr = string.Format("{1} #{0}", order.ID, Resource.TitleMarketOrderResult);
                            var trans     = ctx.BALANCE_CHANGE.FirstOrDefault(c => c.AccountID == order.AccountID &&
                                                                              (c.ChangeType == (int)BalanceChangeType.Profit ||
                                                                               c.ChangeType == (int)BalanceChangeType.Loss) &&
                                                                              c.Description.Equals(dealDescr, StringComparison.OrdinalIgnoreCase));

                            if (trans == null)
                            {
                                Logger.Error("CancelingClosedPositions() - Ошибка при попытке убрать сделку из числа закрытых, не удалось найти транзакцию");
                                continue;
                            }
                            ctx.BALANCE_CHANGE.Remove(trans);
                            successCanceledPositions.Add(order.ID);
                        }
                        Logger.Info("Начинаем вспомогательное сохранение в базу данных");
                        ctx.SaveChanges();


                        Logger.Debug(string.Format("для счёта {0} количество BALANCE_CHANGE после отмены открытых сделок равно {1}",
                                                   orderGroup.Key, ctx.BALANCE_CHANGE.Count(c => c.AccountID == orderGroup.Key)));

                        ReCalculateAccountBalance(ctx, acc.ID);


                        Logger.Info("Начинаем сохранять в базу данных изменения по счёту " + orderGroup.Key);
                        ctx.SaveChanges();
                        result.AddRange(successCanceledPositions);
                    }
                    Logger.Info("Изменения сохранены. Cделки " + string.Join(", ", result) + " отменены");
                    if (id.Length - result.Count != 0)
                    {
                        Logger.Error("CancelingClosedPositions() - по каким то причинам, не удалось отменить " + (id.Length - result.Count) + " сделок");
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error("CancelingClosedPositions() - возникла ошибка при попытке сохранить изменения в базу данных. Не удалось отменить открытые сделки " + strId, ex);
            }
            Logger.Info("Сделки " + strId + " отменены");
            return(result);
        }
Exemple #17
0
        /// <summary>
        /// Отмена открытых сделок, без возможности восстановления
        /// </summary>
        /// <param name="strId">Уникальные идентификаторы отменяемых открытых сделок, перечисленные через запятую</param>
        /// <returns>Уникальные идентификаторы успешно отменённых открытых сделок</returns>
        public List <int> CancelingOpenPositions(string strId)
        {
            Logger.Info("Начинаем отменять открытые сделки " + strId);

            var result = new List <int>();
            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("CancelingOpenPositions() - в таблице 'POSITION' не найдены некоторые или все сделки с идентификаторами " + strId);
                    }

                    // Группируем все сделки по счётам
                    var selOrderGroupByAccount = selOrders.GroupBy(x => x.AccountID);

                    // Перебираем все счета
                    foreach (var orderGroup in selOrderGroupByAccount)
                    {
                        // Список удачно отменённых открытых сделок текущего счёта
                        var successCanceledPositions = new List <int>();

                        var acc = accountRepository.GetAccount(orderGroup.Key);
                        if (acc == null)
                        {
                            Logger.Error("CancelingOpenPositions() - не удалось получить счёт " + orderGroup.Key);
                            continue;
                        }

                        Logger.Info("Начинаем отменять открытые сделки в счёте " + orderGroup.Key);
                        // Перебираем все сделки в текущем счёте
                        foreach (var order in orderGroup)
                        {
                            // убрать сделку из числа открытых
                            try
                            {
                                var pos = ctx.POSITION.FirstOrDefault(p => p.ID == order.ID);
                                if (pos == null)
                                {
                                    Logger.Error("CancelingOpenPositions() - запись о сделке " + order.ID + " не найдена в таблице POSITION. Сделка не может быть отменена");
                                    continue;
                                }
                                ctx.POSITION.Remove(pos);
                                Logger.Info("запись о сделке " + order.ID + " удалена из таблици POSITION");
                            }
                            catch (Exception ex)
                            {
                                Logger.Error("CancelingOpenPositions() - Ошибка при попытке убрать сделку из числа открытых", ex);
                                continue;
                            }
                            successCanceledPositions.Add(order.ID);
                        }
                        Logger.Info("Начинаем сохранять в базу данных изменения по счёту " + orderGroup.Key);
                        ctx.SaveChanges();
                        result.AddRange(successCanceledPositions);
                    }
                    Logger.Info("Изменения сохранены. Cделки " + string.Join(", ", result) + " отменены");
                    if (id.Length - result.Count != 0)
                    {
                        Logger.Error("CancelingOpenPositions() - по каким то причинам, не удалось отменить " + (id.Length - result.Count) + " сделок");
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error("CancelingOpenPositions() - возникла ошибка при попытке сохранить изменения в базу данных. Не удалось отменить открытые сделки " + strId, ex);
            }
            Logger.Info("Сделки " + strId + " отменены");
            return(result);
        }
Exemple #18
0
        /// <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);
        }
Exemple #19
0
        /// <summary>
        /// Переоткрытие закрытых сделок
        /// </summary>
        /// <param name="strId">Уникальные идентификаторы сделокЮ которые нужно переоткрыть, перечисленные через запятую</param>
        /// <returns></returns>
        public bool ReopenPositions(string strId)
        {
            var id = strId.ToIntArrayUniform();

            using (var ctx = DatabaseContext.Instance.Make())
            {
                //  Метод GetPositionsById тут использовать не надо т.к. в нём тот же код, но с лишним обращением к таблице POSITION, а так же
                //  тут не нужно лишнее преобразование MarketOrder к PositionItem

                var selOrders = new List <MarketOrder>();
                // ReSharper disable LoopCanBeConvertedToQuery
                foreach (var order in ctx.POSITION_CLOSED.Where(x => id.Contains(x.ID)))
                {
                    selOrders.Add(LinqToEntity.DecorateOrder(order));
                }
                // ReSharper restore LoopCanBeConvertedToQuery


                // Группируем все сделки по счётам
                var selOrderGroupByAccount = selOrders.GroupBy(x => x.AccountID);

                // Идем по группам сделок в выборке
                foreach (var selOrderGroup in selOrderGroupByAccount)
                {
                    var balanceDelta = -selOrderGroup.Sum(o => o.ResultDepo);
                    try
                    {
                        // "освежить" ордера и запомнить, какие транзакции нужно будет удалить
                        var balanceChangeDescript = new List <Cortege2 <int, string> >();
                        foreach (var order in selOrderGroup)
                        {
                            balanceChangeDescript.Add(new Cortege2 <int, string>(order.ResultDepo >= 0 ? (int)BalanceChangeType.Profit
                                : (int)BalanceChangeType.Loss,
                                                                                 string.Format("{1} #{0}", order.ID, Resource.TitleMarketOrderResult)));

                            order.ResultBase   = 0;
                            order.ResultDepo   = 0;
                            order.ResultPoints = 0;
                            order.State        = PositionState.Opened;
                            order.PriceExit    = null;
                            order.TimeExit     = null;
                        }

                        // удалить закрытые позиции
                        foreach (var oldOrder in selOrderGroup)
                        {
                            var ord = ctx.POSITION_CLOSED.FirstOrDefault(o => o.ID == oldOrder.ID);
                            if (ord != null)
                            {
                                ctx.POSITION_CLOSED.Remove(ord);
                            }
                        }

                        // корректировать баланс
                        var account = ctx.ACCOUNT.FirstOrDefault(a => a.ID == selOrderGroup.Key);
                        if (account != null)
                        {
                            account.Balance += (decimal)balanceDelta;
                            //ctx.ACCOUNT.ApplyCurrentValues(account); //TODO убрал ApplyCurrentValues
                        }

                        // удалить трансферы
                        foreach (var transInfo in balanceChangeDescript)
                        {
                            var changeType = transInfo.a;
                            var transTitle = transInfo.b;
                            var trans      = ctx.BALANCE_CHANGE.FirstOrDefault(t => t.AccountID == selOrderGroup.Key &&
                                                                               t.ChangeType == changeType &&
                                                                               t.Description == transTitle);
                            if (trans != null)
                            {
                                ctx.BALANCE_CHANGE.Remove(trans);
                            }
                        }

                        // добавить открытые позиции
                        var ordersDb = selOrderGroup.Select(LinqToEntity.UndecorateOpenedPosition).ToList();
                        foreach (var ord in ordersDb)
                        {
                            ctx.POSITION.Add(ord);
                        }

                        // завершить транзакцию
                        ctx.SaveChanges();
                    }
                    catch (Exception ex)
                    {
                        Logger.Error("ReopenPositions(string strId)", ex);
                    }
                }
            }

            return(true);
        }