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);
        }
Exemple #2
0
        public RequestStatus GetUserOwnAndSharedAccounts(string login,
                                                         ProtectedOperationContext secCtx,
                                                         out List <AccountShared> accounts)
        {
            accounts = new List <AccountShared>();
            if (!UserSessionStorage.Instance.PermitUserOperation(secCtx, false, true))
            {
                return(RequestStatus.Unauthorized);
            }

            try
            {
                Wallet userWallet;
                using (var ctx = DatabaseContext.Instance.Make())
                {
                    // получить собственные реальные! счета пользователя
                    var ownAccounts = (from ac in ctx.ACCOUNT
                                       join gr in ctx.ACCOUNT_GROUP on ac.AccountGroup equals gr.Code
                                       join pa in ctx.PLATFORM_USER_ACCOUNT on ac.ID equals pa.Account
                                       join u in ctx.PLATFORM_USER on pa.PlatformUser equals u.ID
                                       where u.Login == login && gr.IsReal
                                       select ac).ToList()
                                      .Select(a => new AccountShared(LinqToEntity.DecorateAccount(a), true)
                    {
                        SharePercent = 100
                    })
                                      .ToList();
                    // получить те счета, в которых у запросившего есть доля
                    var shares = (from sh in ctx.ACCOUNT_SHARE
                                  join u in ctx.PLATFORM_USER on sh.ShareOwner equals u.ID
                                  join ac in ctx.ACCOUNT on sh.Account equals ac.ID
                                  join gr in ctx.ACCOUNT_GROUP on ac.AccountGroup equals gr.Code
                                  where u.Login == login && gr.IsReal
                                  select new AccountShared
                    {
                        Account = new Account
                        {
                            ID = ac.ID,
                            Group = ac.AccountGroup,
                            Currency = ac.Currency,
                            Balance = ac.Balance
                        },
                        SharePercent = sh.Share
                    }).ToList();
                    // склеить оба списка
                    ownAccounts.ForEach(a =>
                    {
                        var sharedAccount = shares.FirstOrDefault(s => s.Account.ID == a.Account.ID);
                        if (sharedAccount != null)
                        {
                            a.SharePercent = sharedAccount.SharePercent;
                        }
                    });
                    accounts = ownAccounts.Union(shares, AccountShared.ComparerOnId.Instance).ToList();
                    if (accounts.Count == 0)
                    {
                        return(RequestStatus.OK);
                    }

                    userWallet = LinqToEntity.DecorateWallet((from w in ctx.WALLET
                                                              join u in ctx.PLATFORM_USER on w.User equals u.ID
                                                              where u.Login == login
                                                              select w).First());
                }

                // посчитать профит (equity) для счетов
                foreach (var account in accounts)
                {
                    var equity = profitCalculator.CalculateAccountEquity(account.Account.ID, account.Account.Balance,
                                                                         account.Account.Currency, TradeSharp.Contract.Util.BL.QuoteStorage.Instance.ReceiveAllData(), this);
                    account.Account.Equity   = equity;
                    account.ShareMoney       = account.Account.Equity * account.SharePercent / 100M;
                    account.ShareMoneyWallet = account.ShareMoney;

                    // посчитать долю в валюте кошелька
                    if (account.Currency == userWallet.Currency)
                    {
                        continue;
                    }
                    string errorString;
                    var    shareWallet = DalSpot.Instance.ConvertSourceCurrencyToTargetCurrency(userWallet.Currency, account.Currency,
                                                                                                (double)account.ShareMoney,
                                                                                                TradeSharp.Contract.Util.BL.QuoteStorage.Instance.ReceiveAllData(), out errorString);
                    account.ShareMoneyWallet = shareWallet ?? account.ShareMoney;
                    if (errorString != null)
                    {
                        Logger.ErrorFormat("GetUserOwnAndSharedAccounts({0}) - перевод средств из {1} в {2}: {3}",
                                           login, account.Currency, userWallet.Currency, errorString);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error("Ошибка в GetUserOwnAndSharedAccounts", ex);
                return(RequestStatus.ServerError);
            }
            return(RequestStatus.OK);
        }
Exemple #3
0
        /// <summary>
        /// вернуть акаунты, которыми трейдер владеет!
        /// опционально - исключив демки
        /// по каждому акаунту посчитать средства и резерв. маржу
        /// </summary>
        public AuthenticationResponse GetUserOwnedAccountsWithActualBalance(string login,
                                                                            ProtectedOperationContext secCtx, bool realOnly, out List <Account> accounts)
        {
            accounts = new List <Account>();
            try
            {
                if (UserOperationRightsStorage.IsProtectedOperation(UserOperation.GetAccountDetail))
                {
                    if (!UserSessionStorage.Instance.PermitUserOperation(secCtx,
                                                                         UserOperationRightsStorage.IsTradeOperation(UserOperation.GetAccountDetail), false))
                    {
                        return(AuthenticationResponse.WrongPassword);
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.Error("GetUserOwnedAccountsWithActualBalance - PermitUserOperation error", ex);
                return(AuthenticationResponse.ServerError);
            }

            try
            {
                using (var ctx = DatabaseContext.Instance.Make())
                {
                    try
                    {
                        var user = ctx.PLATFORM_USER.FirstOrDefault(ac => ac.Login == login);
                        if (user == null)
                        {
                            return(AuthenticationResponse.InvalidAccount);
                        }

                        var accountRoles = (from ar in ctx.PLATFORM_USER_ACCOUNT
                                            where ar.PlatformUser == user.ID &&
                                            ar.RightsMask == (int)AccountRights.Управление
                                            select ar);
                        foreach (var acRole in accountRoles)
                        {
                            var acId = acRole.Account;
                            var acc  = realOnly
                                ? ctx.ACCOUNT.FirstOrDefault(a => a.ID == acId && a.ACCOUNT_GROUP.IsReal)
                                : ctx.ACCOUNT.FirstOrDefault(a => a.ID == acId);
                            if (acc == null)
                            {
                                continue;
                            }

                            // заполнить данные о актуальном балансе и т.д. и т.п.
                            decimal equity, reservedMargin, exposure;
                            profitCalculator.CalculateAccountExposure(acId, out equity, out reservedMargin,
                                                                      out exposure, TradeSharp.Contract.Util.BL.QuoteStorage.Instance.ReceiveAllData(),
                                                                      ManagerAccount.Instance, accountRepository.GetAccountGroup);
                            var accountDec = LinqToEntity.DecorateAccount(acc);
                            accountDec.Equity     = equity;
                            accountDec.UsedMargin = reservedMargin;
                            accounts.Add(accountDec);
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Error("Ошибка в GetUserOwnedAccountsWithActualBalance", ex);
                        return(AuthenticationResponse.ServerError);
                    }
                    return(AuthenticationResponse.OK);
                }
            }
            catch (Exception ex)
            {
                Logger.Error("GetUserOwnedAccountsWithActualBalance - error making DB context", ex);
                return(AuthenticationResponse.ServerError);
            }
        }
Exemple #4
0
        /// <summary>
        /// вызывается дилером - в БД заносится новая поза (открытая либо в процессе открытия)
        /// отправить уведомление клиенту
        /// </summary>
        /// <param name="order">поза</param>
        /// <param name="posID">ID сущности из БД</param>
        /// <returns>OK?</returns>
        public bool SaveOrderAndNotifyClient(MarketOrder order, out int posID)
        {
            posID = -1;
            using (var ctx = DatabaseContext.Instance.Make())
            {
                var account = ctx.ACCOUNT.FirstOrDefault(ac => ac.ID == order.AccountID);
                if (account == null)
                {
                    return(false);
                }

                // провести ордер через биллинг
                OrderBill bill = null;
                if (order.State == PositionState.Opened)
                {
                    bill = BillingManager.ProcessOrderOpening(order, LinqToEntity.DecorateAccount(account));
                }

                var pos = new POSITION
                {
                    AccountID      = order.AccountID,
                    Comment        = order.Comment,
                    ExpertComment  = order.ExpertComment,
                    Magic          = order.Magic,
                    PendingOrderID = order.PendingOrderID,
                    PriceBest      = (decimal?)order.PriceBest,
                    PriceWorst     = (decimal?)order.PriceWorst,
                    PriceEnter     = (decimal)order.PriceEnter,
                    Side           = order.Side,
                    State          = ((int)order.State),
                    Stoploss       = (decimal?)order.StopLoss,
                    Symbol         = order.Symbol,
                    Takeprofit     = (decimal?)order.TakeProfit,
                    TimeEnter      = order.TimeEnter,
                    TrailLevel1    = (decimal?)order.TrailLevel1,
                    TrailLevel2    = (decimal?)order.TrailLevel2,
                    TrailLevel3    = (decimal?)order.TrailLevel3,
                    TrailLevel4    = (decimal?)order.TrailLevel4,
                    TrailTarget1   = (decimal?)order.TrailTarget1,
                    TrailTarget2   = (decimal?)order.TrailTarget2,
                    TrailTarget3   = (decimal?)order.TrailTarget3,
                    TrailTarget4   = (decimal?)order.TrailTarget4,
                    Volume         = order.Volume,
                    MasterOrder    = order.MasterOrder
                };

                account.POSITION.Add(pos);
                try
                {
                    ctx.SaveChanges();
                    posID    = pos.ID;
                    order.ID = posID;
                    if (bill != null)
                    {
                        BillingManager.SaveNewOrderBill(bill, pos.ID, ctx);
                    }
                    ctx.SaveChanges();
                }
                catch (Exception ex)
                {
                    Logger.Error("Ошибка сохранения сущности POSITION", ex);
                    ServiceManagerClientManagerProxy.Instance.NewOrderResponse(null,
                                                                               RequestStatus.ServerError, "crudsav");
                    return(false);
                }
            }
            // отправить уведомление клиенту
            ServiceManagerClientManagerProxy.Instance.NewOrderResponse(order, RequestStatus.OK, "");

            // разослать торговый сигнал?
            if (order.State == PositionState.Opened)
            {
                MakeSignalNewDeal(order.AccountID, order.Symbol, order.Side, order.Volume,
                                  order.StopLoss.HasValue ? (decimal)order.StopLoss.Value : (decimal?)null,
                                  order.TakeProfit.HasValue ? (decimal)order.TakeProfit.Value : (decimal?)null,
                                  posID, order.PriceEnter);
            }

            return(true);
        }