public string AddNewSpotItem(TradeSharpConnection context, SpotModel model)
        {
            var result = string.Empty;
            var newContext = EnsureContext(ref context);
            try
            {
                var spot = new SPOT
                {
                    ComBase = model.ComBase,
                    ComCounter = model.ComCounter,
                    Title = model.Title,
                    CodeFXI = model.CodeFXI,
                    MinVolume = model.MinVolume,
                    MinStepVolume = model.MinStepVolume,
                    Precise = model.Precise,
                    SwapBuy = model.SwapBuy,
                    SwapSell = model.SwapSell,
                    Description = model.Description
                };

                context.SPOT.Add(spot);
                context.SaveChanges();
            }
            catch (Exception ex)
            {
                Logger.Error("AddNewSpotItem()", ex);
                result = ex.Message;
            }
            finally
            {
                if (newContext != null) newContext.Dispose();
            }
            return result;
        }
 public string DeleteSpotItem(TradeSharpConnection context, string title)
 {
     var result = string.Empty;
     var newContext = EnsureContext(ref context);
     try
     {
         var itemToDel = context.SPOT.Single(x => x.Title == title);
         context.SPOT.Remove(itemToDel);
         context.SaveChanges();
     }
     catch (Exception ex)
     {
         Logger.Error("DeleteSpotItem()", ex);
         result = ex.Message;
     }
     finally
     {
         if (newContext != null) newContext.Dispose();
     }
     return result;
 }
        /// <summary>
        /// Метод пересчитывает баланс во всех операциях, кроме закрытия или отмены сделок
        /// </summary>
        public void UpdateBalanceChange(TradeSharpConnection ctx, MarketOrder closedPos, bool deleteTransferOnly)
        {
            // поправить трансфер по счету и баланс
            var dealDescr = string.Format("{1} #{0}", closedPos.ID, Resource.TitleMarketOrderResult);
            var trans = ctx.BALANCE_CHANGE.FirstOrDefault(c => c.AccountID == closedPos.AccountID &&
                                                               (c.ChangeType ==
                                                                (int)BalanceChangeType.Profit ||
                                                                c.ChangeType ==
                                                                (int)BalanceChangeType.Loss) && c.Description.Equals(dealDescr, StringComparison.OrdinalIgnoreCase));
            if (deleteTransferOnly)
            {
                if (trans == null) return;
                ctx.BALANCE_CHANGE.Remove(trans);
            }
            else
            {
                // изменить или добавить перевод
                if (trans == null)
                {
                    trans = new BALANCE_CHANGE { Description = dealDescr, AccountID = closedPos.AccountID };
                    ctx.BALANCE_CHANGE.Add(trans);
                }
                trans.Amount = (decimal)Math.Abs(closedPos.ResultDepo);
                trans.ChangeType = closedPos.ResultDepo > 0
                                       ? (int)BalanceChangeType.Profit
                                       : (int)BalanceChangeType.Loss;
                if (closedPos.TimeExit != null)
                    trans.ValueDate = closedPos.TimeExit.Value;
            }

            //ctx.BALANCE_CHANGE.ApplyCurrentValues(trans);
            ctx.SaveChanges();
        }
        /// <summary>
        /// Пересчёт баланса для указанного счёта. Применяется, например, после отмены уже закрытых сделок
        /// </summary>
        /// <param name="ctx"></param>
        /// <param name="accountId">уникаьлный идентификатор счёта, для которого пересчитываем баланс</param>
        public bool ReCalculateAccountBalance(TradeSharpConnection ctx, int accountId)
        {
            try
            {
                Logger.Info(string.Format("Пытыемся пересчитать баланс для счёта {0}", accountId));
                var bal = ctx.BALANCE_CHANGE.Where(b => b.AccountID == accountId).Sum(c =>
                                                                                      (c.ChangeType ==(int)BalanceChangeType.Deposit ||
                                                                                       c.ChangeType ==(int)BalanceChangeType.Profit ||
                                                                                       c.ChangeType ==(int) BalanceChangeType.Swap ? 1: -1)*c.Amount);

                var acc = ctx.ACCOUNT.Single(a => a.ID == accountId);
                acc.Balance = bal;
                ctx.SaveChanges();

                return true;
            }
            catch (InvalidOperationException ex)
            {
                Logger.Error(string.Format(
                        "ReCalculateAccountBalance(). Не удалось пересчитать балланс {0}. Возможно нет ни одной проводки по счёту.",accountId), ex);
            }
            catch (Exception ex)
            {

                Logger.Error(string.Format("ReCalculateAccountBalance(). Не удалось пересчитать балланс счёта {0}.", accountId),ex);
            }
            return false;
        }
        public RequestStatus UnsubscribeUserFromPortfolio(TradeSharpConnection ctx, string subscriberLogin,
            bool deletePortfolio, bool deleteSubscriptions)
        {
            try
            {
                var user = ctx.PLATFORM_USER.FirstOrDefault(u => u.Login == subscriberLogin);
                if (user == null)
                    return RequestStatus.Unauthorized;

                var subscriptions = ctx.USER_TOP_PORTFOLIO.Where(u => u.User == user.ID).ToList();
                foreach (var portfolioSub in subscriptions)
                {
                    // удалить подписку
                    ctx.USER_TOP_PORTFOLIO.Remove(portfolioSub);
                    Logger.InfoFormat("UnsubscribeUserFromPortfolio({0}) - отписан от портфеля", subscriberLogin);

                    // если подписка была на пользовательский портфель - удалить пользовательский портфель
                    if (deletePortfolio)
                    {
                        var portfolio = ctx.TOP_PORTFOLIO.Single(p => p.Id == portfolioSub.Portfolio);
                        if (portfolio.OwnerUser == user.ID)
                            ctx.TOP_PORTFOLIO.Remove(portfolio);
                    }

                    if (!deleteSubscriptions) continue;

                    // удалить подписки на сервисы
                    var subs = ctx.SUBSCRIPTION.Where(s => s.User == user.ID).ToList();
                    foreach (var sub in subs)
                        ctx.SUBSCRIPTION.Remove(sub);
                }
                ctx.SaveChanges();

                return RequestStatus.OK;
            }
            catch (Exception ex)
            {
                Logger.Error("Ошибка в UnsubscribePortfolio()", ex);
                return RequestStatus.ServerError;
            }
        }
        public WalletError ChargeFeeOnSubscription(TradeSharpConnection ctx, SERVICE service, int usr, bool renewSubscription)
        {
            try
            {
                // создать платеж с кошелька usr на кошелек владельца сервиса (service)
                if (service.FixedPrice == 0)
                    return WalletError.OK; // все на шарку!
                var price = service.FixedPrice > 0
                                ? service.FixedPrice
                                : GetFeeByUserBalance(ctx, service);
                if (price == 0) return WalletError.OK;

                var usrWallet = ctx.WALLET.FirstOrDefault(w => w.User == usr);
                if (usrWallet == null)
                {
                    Logger.Error("ChargeFeeOnSubscription(usrId=" + usr + ") - wallet is not found");
                    return WalletError.ServerError;
                }

                if (HasUserPaidTheService(ctx, service, usr))
                    return WalletError.OK;

                // посчитать в валюте пользователя
                var usrAmount = price;
                if (usrWallet.Currency != service.Currency)
                {
                    string strError;
                    var targetAmount = DalSpot.Instance.ConvertSourceCurrencyToTargetCurrency(usrWallet.Currency, service.Currency,
                                                                           (double)usrAmount,
                                                                           QuoteStorage.Instance.ReceiveAllData(),
                                                                           out strError);
                    if (!targetAmount.HasValue)
                    {
                        Logger.ErrorFormat("ChargeFeeOnSubscription(usrId={0}) - currency rate is not found ({1}/{2})",
                            usr, usrWallet.Currency, service.Currency);
                        return WalletError.CurrencyExchangeFailed;
                    }
                    usrAmount = targetAmount.Value;
                }

                // если объем превышает возможности пользователя...
                if (usrWallet.Balance < usrAmount)
                {
                    Logger.InfoFormat("ChargeFeeOnSubscription(usrId={0}) - not enough money ({1}, needed {2})",
                            usr, usrAmount, usrWallet.Balance);
                    return WalletError.InsufficientFunds;
                }

                usrWallet.Balance -= usrAmount;
                var trans = ctx.TRANSFER.Add(new TRANSFER
                {
                    Amount = usrAmount,
                    TargetAmount = price,
                    Comment = "Fee on srv " + service.ID,
                    RefWallet = service.User,
                    User = usr,
                    ValueDate = DateTime.Now,
                    Subscription = service.ID
                });
                Logger.InfoFormat("Добавляется трансфер: usr={0}, comment={1}",
                    usr, trans.Comment);

                // добавить денег владельцу
                ctx.TRANSFER.Add(new TRANSFER
                {
                    Amount = price,
                    TargetAmount = usrAmount,
                    Comment = "Paid for srv " + service.ID,
                    RefWallet = usr,
                    User = service.User,
                    ValueDate = DateTime.Now,
                    Subscription = service.ID
                });
                var ownerWallet = ctx.WALLET.First(w => w.User == service.User);
                ownerWallet.Balance += price;

                // обновить подписку
                if (renewSubscription)
                {
                    var sub = ctx.SUBSCRIPTION.FirstOrDefault(s => s.Service == service.ID);
                    if (sub != null && sub.RenewAuto)
                    {
                        sub.TimeStarted = DateTime.Now.Date;
                        sub.TimeEnd = sub.TimeStarted.AddDays(1);
                    }
                }

                Logger.InfoFormat("ChargeFeeOnSubscription() - сохранение");
                ctx.SaveChanges();
            }
            catch (Exception ex)
            {
                Logger.Error("Error in ChargeFeeOnSubscription()", ex);
                return WalletError.ServerError;
            }
            return WalletError.OK;
        }
        public RequestStatus SubscribeUserOnPortfolio(
            TradeSharpConnection ctx,
            string subscriberLogin,
            TopPortfolio portfolio,
            decimal? maxFee,
            AutoTradeSettings tradeAutoSettings)
        {
            var user = ctx.PLATFORM_USER.FirstOrDefault(u => u.Login == subscriberLogin);
            if (user == null)
                return RequestStatus.Unauthorized;

            TOP_PORTFOLIO targetPortfolio = null;
            if (portfolio.Id > 0)
                targetPortfolio = ctx.TOP_PORTFOLIO.FirstOrDefault(p => p.Id == portfolio.Id);
            if (targetPortfolio != null)
                portfolio.ManagedAccount = targetPortfolio.ManagedAccount;

            // если портфель - пользовательский - сохранить его
            // для пользователя или обновить его имеющийся портфель
            if (!portfolio.IsCompanyPortfolio)
            {
                Logger.Info("SubscribeOnPortfolio() - user portfolio");
                try
                {
                    var existPortfolio = ctx.TOP_PORTFOLIO.FirstOrDefault(p => p.OwnerUser == user.ID);
                    if (existPortfolio != null)
                    {
                        if (!LinqToEntity.DecoratePortfolio(existPortfolio).AreSame(portfolio))
                        {
                            // удалить старый портфель пользователя
                            ctx.TOP_PORTFOLIO.Remove(existPortfolio);
                            existPortfolio = null;
                        }
                        else
                            targetPortfolio = existPortfolio;
                    }
                    // создать портфель пользователя
                    if (existPortfolio == null)
                    {
                        targetPortfolio = LinqToEntity.UndecoratePortfolio(portfolio);
                        targetPortfolio.OwnerUser = user.ID;
                        targetPortfolio.ManagedAccount = null;
                        ctx.TOP_PORTFOLIO.Add(targetPortfolio);
                        ctx.SaveChanges();
                    }
                }
                catch (DbEntityValidationException dbEx)
                {
                    Logger.Error("SubscribeUserOnPortfolio - ошибка сохранения портфеля");
                    foreach (var validationErrors in dbEx.EntityValidationErrors)
                    {
                        foreach (var validationError in validationErrors.ValidationErrors)
                        {
                            Logger.ErrorFormat("Свойство: {0}, ошибка: {1}",
                                validationError.PropertyName, validationError.ErrorMessage);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error("Ошибка в SubscribeOnPortfolio() - обновление портфеля", ex);
                    return RequestStatus.ServerError;
                }
            }
            else
            {// портфель компании
                Logger.Info("SubscribeOnPortfolio() - company portfolio");
                if (targetPortfolio == null)
                {
                    Logger.Error("Пользователь запросил несуществующий портфель компании " + portfolio.Id);
                    return RequestStatus.ServerError;
                }
            }

            // очистить подписки пользователя на портфели
            // и привязать его к целевому портфелю
            //Logger.Info("SubscribeOnPortfolio() - removing bindings");
            var oldBinding = ctx.USER_TOP_PORTFOLIO.FirstOrDefault(u => u.User == user.ID);
            // "посмотреть" настройки портфельной торговли в имеющейся подписке
            if (tradeAutoSettings == null)
            {
                if (oldBinding == null)
                {
                    Logger.ErrorFormat("Подписка пользователя {0} на портфель {1} - нет данных по автоматической торговле",
                        user.Login, portfolio.Id > 0 ? portfolio.Id.ToString() : portfolio.Name);
                    return RequestStatus.BadRequest;
                }
                tradeAutoSettings = new AutoTradeSettings
                {
                    FixedVolume = oldBinding.FixedVolume,
                    HedgingOrdersEnabled = oldBinding.HedgingOrdersEnabled,
                    MaxLeverage = oldBinding.MaxLeverage,
                    MaxVolume = oldBinding.MaxVolume,
                    MinVolume = oldBinding.MinVolume,
                    PercentLeverage = oldBinding.PercentLeverage ?? 100,
                    StepVolume = oldBinding.StepVolume,
                    TargetAccount = oldBinding.TargetAccount,
                    TradeAuto = oldBinding.AutoTrade ?? false,
                    VolumeRound = (VolumeRoundType?)oldBinding.VolumeRound
                };
            }

            if (oldBinding != null)
                ctx.USER_TOP_PORTFOLIO.Remove(oldBinding);

            //Logger.Info("SubscribeOnPortfolio() - adding binding");
            ctx.USER_TOP_PORTFOLIO.Add(new USER_TOP_PORTFOLIO
            {
                User = user.ID,
                Portfolio = targetPortfolio.Id,
                MaxFee = maxFee,
                AutoTrade = tradeAutoSettings.TradeAuto,
                MaxLeverage = tradeAutoSettings.MaxLeverage,
                PercentLeverage = tradeAutoSettings.PercentLeverage,
                HedgingOrdersEnabled = tradeAutoSettings.HedgingOrdersEnabled,
                FixedVolume = tradeAutoSettings.FixedVolume,
                MinVolume = tradeAutoSettings.MinVolume,
                MaxVolume = tradeAutoSettings.MaxVolume,
                VolumeRound = (int?)tradeAutoSettings.VolumeRound,
                StepVolume = tradeAutoSettings.StepVolume,
                TargetAccount = tradeAutoSettings.TargetAccount
            });
            ctx.SaveChanges();
            //Logger.Info("SubscribeOnPortfolio() - changes are saved");

            // найти трейдеров, удовлетворяющих критерию
            List<PerformerStat> performers;
            try
            {
                try
                {
                    performers = TradeSharpAccountStatistics.Instance.proxy.GetAllPerformersWithCriteria(true,
                        targetPortfolio.Criteria, targetPortfolio.ParticipantCount,
                        !targetPortfolio.DescendingOrder, (float?)targetPortfolio.MarginValue, 0);
                }
                catch (Exception ex)
                {
                    Logger.Error(
                        "Ошибка в SubscribeOnPortfolio() - получение перформеров (" + targetPortfolio.Criteria + ")",
                        ex);
                    return RequestStatus.ServerError;
                }

                if (performers == null)
                {
                    Logger.Error("Ошибка в SubscribeOnPortfolio() - список перформеров не получен (" + targetPortfolio.Criteria + ")");
                    return RequestStatus.ServerError;
                }
            }
            catch (Exception ex)
            {
                Logger.Error("Ошибка в SubscribeOnPortfolio() - подписка", ex);
                return RequestStatus.ServerError;
            }

            // сравнить полученный список с текущими подписками заказчика ("инвестора")
            // сформировать список для "отписки" и список для подписки
            var performerAcs = performers.Select(p => p.Account).ToList();
            var subsToRemove = ctx.SUBSCRIPTION.Where(s => s.User == user.ID &&
                s.SERVICE1.ServiceType == (int)PaidServiceType.Signals &&
                !performerAcs.Contains(s.SERVICE1.AccountId ?? 0)).ToList();

            foreach (var sub in subsToRemove)
            {
                WalletError error;
                SubscribeOnService(ctx, user.ID, sub.Service, false, true, tradeAutoSettings, out error);
                if (error != WalletError.OK)
                {
                    Logger.ErrorFormat("Portfolio - unsubscribe user {0} from srv {1}: error {2}",
                        user.ID, sub.Service, error);
                }
            }

            // новоподписавшиеся
            foreach (var pf in performers)
            {
                WalletError error;
                SubscribeOnService(ctx, user.ID, pf.Service, true, false, tradeAutoSettings, out error);
                if (error != WalletError.OK)
                {
                    Logger.DebugFormat("Подписка SubscribeOnPortfolio({0}), сигн. {1}: {2}",
                        subscriberLogin, pf.Service, error);
                }
            }
            return RequestStatus.OK;
        }
        public bool SubscribeOnService(TradeSharpConnection ctx,
            int userId, int serviceId, bool renewAuto, bool unsubscribe,
            AutoTradeSettings tradeSets, out WalletError error)
        {
            // имеющаяся подписка
            var subs = ctx.SUBSCRIPTION.FirstOrDefault(s => s.Service == serviceId && s.User == userId);

            // просто отписаться от сервиса
            if (unsubscribe)
            {
                error = WalletError.OK;
                if (subs == null)
                    return true;
                ctx.SUBSCRIPTION.Remove(subs);
                try
                {
                    ctx.SaveChanges();
                }
                catch (Exception ex)
                {
                    Logger.Error("Ошибка удаления подписки (SubscribeOnService)", ex);
                    error = WalletError.ServerError;
                    return false;
                }

                return true;
            }

            var paidService = ctx.SERVICE.FirstOrDefault(s => s.ID == serviceId);
            if (paidService == null)
            {
                error = WalletError.InvalidData;
                return false;
            }

            // проверить - не подписывается ли пользователь сам на себя?
            if (paidService.User == userId)
            {
                error = WalletError.InvalidData;
                return false;
            }

            // провести списание денежных средств
            // содрать денежку
            var feeError = ChargeFeeOnSubscription(ctx, serviceId, userId, false);
            if (feeError != WalletError.OK)
            {
                error = feeError;
                return false;
            }

            // продлить или обновить подписку
            var subExists = subs != null;
            if (subs == null)
                subs = new SUBSCRIPTION();
            subs.RenewAuto = renewAuto;
            subs.TimeEnd = DateTime.Now.Date.AddDays(1);
            subs.TimeStarted = DateTime.Now.Date;
            subs.User = userId;
            subs.Service = serviceId;
            if (!subExists)
                ctx.SUBSCRIPTION.Add(subs);

            // обновить или создать настройки торговли
            var signalTradeSets = ctx.SUBSCRIPTION_SIGNAL.FirstOrDefault(s => s.Service == serviceId && s.User == userId);
            var setsExists = signalTradeSets != null;
            if (signalTradeSets == null)
                signalTradeSets = new SUBSCRIPTION_SIGNAL();
            signalTradeSets.AutoTrade = tradeSets.TradeAuto;
            signalTradeSets.FixedVolume = tradeSets.FixedVolume;
            signalTradeSets.HedgingOrdersEnabled = tradeSets.HedgingOrdersEnabled;
            signalTradeSets.MaxLeverage = tradeSets.MaxLeverage;
            signalTradeSets.MaxVolume = tradeSets.MaxVolume;
            signalTradeSets.MinVolume = tradeSets.MinVolume;
            signalTradeSets.PercentLeverage = tradeSets.PercentLeverage;
            signalTradeSets.Service = serviceId;
            signalTradeSets.StepVolume = tradeSets.StepVolume;
            signalTradeSets.User = userId;
            signalTradeSets.TargetAccount = tradeSets.TargetAccount;
            signalTradeSets.VolumeRound = (int?)tradeSets.VolumeRound;
            if (!setsExists)
                ctx.SUBSCRIPTION_SIGNAL.Add(signalTradeSets);

            try
            {
                ctx.SaveChanges();
            }
            catch (Exception ex)
            {
                Logger.Error("Ошибка сохранения подписки (SubscribeOnService)", ex);
                error = WalletError.ServerError;
                return false;
            }

            error = WalletError.OK;
            return true;
        }
 private static void CorrectBalance(int acId, decimal deltaAmount, TradeSharpConnection conn)
 {
     // поправить депозит
     var bc = new BALANCE_CHANGE
     {
         AccountID = acId,
         ValueDate = DateTime.Now,
         Amount = deltaAmount,
         ChangeType = (int) BalanceChangeType.Withdrawal,
         Description = "public offering"
     };
     conn.BALANCE_CHANGE.Add(bc);
     conn.SaveChanges();
     var userId = conn.PLATFORM_USER_ACCOUNT.First(a => a.Account == acId).PlatformUser;
     var tr = new TRANSFER
     {
         ValueDate = bc.ValueDate,
         BalanceChange = bc.ID,
         Amount = -deltaAmount,
         Comment = "public offering",
         User = userId,
         TargetAmount = - deltaAmount
     };
     conn.TRANSFER.Add(tr);
 }
 private bool ModifyOpenedPosition(MarketOrder order, TradeSharpConnection ctx, POSITION pos, 
     out string errorString)
 {
     errorString = string.Empty;
     if (order.IsClosed)
     {
         var closed = new POSITION_CLOSED
         {
             AccountID = pos.AccountID,
             ID = pos.ID,
             Comment = order.Comment,
             ExitReason = (int) order.ExitReason,
             Magic = order.Magic,
             ExpertComment = order.ExpertComment,
             PendingOrderID = order.PendingOrderID,
             PriceBest = (decimal?) order.PriceBest,
             PriceEnter = (decimal) order.PriceEnter,
             PriceExit = (decimal) (order.PriceExit ?? 0),
             PriceWorst = (decimal?) order.PriceWorst,
             ResultBase = (decimal) order.ResultBase,
             ResultDepo = (decimal) order.ResultDepo,
             ResultPoints = (decimal) order.ResultPoints,
             Side = order.Side,
             Stoploss = (decimal?) order.StopLoss,
             Swap = (decimal) (order.Swap ?? 0),
             Symbol = order.Symbol,
             Takeprofit = (decimal?) order.TakeProfit,
             TimeEnter = order.TimeEnter,
             TimeExit = order.TimeExit ?? default(DateTime),
             Volume = order.Volume
         };
         ctx.POSITION.Remove(pos);
         ctx.POSITION_CLOSED.Add(closed);
         return true;
     }
     pos.Comment = order.Comment;
     pos.Magic = order.Magic;
     pos.ExpertComment = order.ExpertComment;
     pos.PendingOrderID = order.PendingOrderID;
     pos.PriceBest = (decimal?) order.PriceBest;
     pos.PriceEnter = (decimal) order.PriceEnter;
     pos.PriceWorst = (decimal?) order.PriceWorst;
     pos.Side = order.Side;
     pos.Stoploss = (decimal?) order.StopLoss;
     pos.Symbol = order.Symbol;
     pos.Takeprofit = (decimal?) order.TakeProfit;
     pos.TimeEnter = order.TimeEnter;
     pos.Volume = order.Volume;
     pos.State = (int) order.State;
     pos.MasterOrder = order.MasterOrder;
     ctx.SaveChanges();
     return true;
 }
        private Wallet GetMoneyFromUserOwnedAccount(int accountId, decimal amountInSrcCurrency, out WalletError error,
                                                    ACCOUNT account, WALLET wallet, TradeSharpConnection ctx, PLATFORM_USER user)
        {
            var amountWallet = amountInSrcCurrency;
            if (account.Currency != wallet.Currency)
            {
                // найти котировку и перевести
                string errorString;
                var amountTarget = DalSpot.Instance.ConvertSourceCurrencyToTargetCurrency(wallet.Currency,
                                                                                          account.Currency,
                                                                                          (double) amountWallet,
                                                                                          QuoteStorage.Instance.ReceiveAllData(),
                                                                                          out errorString);
                if (!amountTarget.HasValue)
                {
                    Logger.ErrorFormat("DepositOrWithdraw({0} {1}): {2} (withdraw)",
                                       amountInSrcCurrency, account.Currency + "/" + wallet.Currency,
                                       errorString);
                    error = WalletError.CurrencyExchangeFailed;
                    return null;
                }
                amountWallet = amountTarget.Value;
            }

            // достаточно ли средств на счете?
            // проверить средства / зарезервированное марж. обеспечение
            decimal equity, usedMargin;
            if (!GetAccountEquityAndUsedMargin(account, out equity, out usedMargin))
            {
                error = WalletError.ServerError;
                return null;
            }
            if (equity - usedMargin < amountInSrcCurrency)
            {
                error = WalletError.ServerError;
                return null;
            }

            // списать со счета в пользу кошелька
            wallet.Balance += amountInSrcCurrency;
            account.Balance -= amountInSrcCurrency;
            var date = DateTime.Now;
            var bc = ctx.BALANCE_CHANGE.Add(new BALANCE_CHANGE
                {
                    AccountID = accountId,
                    Amount = amountInSrcCurrency,
                    ChangeType = (int) BalanceChangeType.Withdrawal,
                    ValueDate = date,
                    Description = "Списание на кошелек №" + wallet.User
                });
            ctx.SaveChanges();
            ctx.TRANSFER.Add(new TRANSFER
                {
                    Amount = amountWallet,
                    TargetAmount = amountWallet,
                    User = user.ID,
                    Comment = "Вывод средств со счета №" + account.ID,
                    ValueDate = date,
                    BalanceChange = bc.ID,
                });

            ctx.SaveChanges();
            error = WalletError.OK;
            return LinqToEntity.DecorateWallet(wallet);
        }
        private bool CreateOrUpdateServiceFeeRecords(PaidService service, TradeSharpConnection ctx, bool existedService)
        {
            if (service.serviceRates == null)
                service.serviceRates = new List<PaidServiceRate>();
            try
            {
                if ((service.serviceRates == null || service.serviceRates.Count == 0) && !existedService)
                    return true;

                // сервис уже был зарегистрирован?
                if (existedService)
                {
                    var rates = ctx.SERVICE_RATE.Where(r => r.Service == service.Id).ToList();
                    if (rates.Count == 0 && service.serviceRates.Count == 0)
                        return true;
                    // рейты не изменились?
                    if (rates.Count == service.serviceRates.Count)
                        if (rates.All(r => service.serviceRates.Any(sr =>
                                                                    sr.Amount == r.Amount &&
                                                                    sr.UserBalance == r.UserBalance &&
                                                                    (int)sr.RateType == r.RateType)))
                            return true;
                    // удалить имеющиеся рейты
                    foreach (var rate in rates)
                        ctx.SERVICE_RATE.Remove(rate);
                }

                // добавить рейты
                foreach (var rate in service.serviceRates)
                    ctx.SERVICE_RATE.Add(new SERVICE_RATE
                    {
                        Amount = rate.Amount,
                        Service = service.Id,
                        UserBalance = rate.UserBalance,
                        RateType = (int)rate.RateType
                    });

                ctx.SaveChanges();

                return true;
            }
            catch (Exception ex)
            {
                Logger.Error("CreateOrUpdateServiceFeeRecords() error", ex);
                return false;
            }
        }
        private static Wallet PutMoneyOnUserOwnedAccount(int accountId, decimal amountInSrcCurrency, out WalletError error,
                                                         WALLET wallet, ACCOUNT account, TradeSharpConnection ctx,
                                                         PLATFORM_USER user)
        {
            // достаточно ли денег в кошельке?
            if (amountInSrcCurrency > wallet.Balance)
            {
                error = WalletError.InsufficientFunds;
                return null;
            }

            // перевести объем в валюту счета
            var amount = amountInSrcCurrency;
            if (account.Currency != wallet.Currency)
            {
                // найти котировку и перевести
                string errorString;
                var amountTarget = DalSpot.Instance.ConvertSourceCurrencyToTargetCurrency(account.Currency,
                                                                                          wallet.Currency, (double) amount,
                                                                                          QuoteStorage.Instance.ReceiveAllData(),
                                                                                          out errorString);
                if (!amountTarget.HasValue)
                {
                    Logger.ErrorFormat("DepositOrWithdraw({0} {1}): {2}",
                                       amountInSrcCurrency, account.Currency + "/" + wallet.Currency,
                                       errorString);
                    error = WalletError.CurrencyExchangeFailed;
                    return null;
                }
                amount = amountTarget.Value;
            }

            // списать с кошелька и пополнить счет
            wallet.Balance -= amountInSrcCurrency;
            account.Balance += amount;
            var dateOper = DateTime.Now;
            var balanceChange = ctx.BALANCE_CHANGE.Add(new BALANCE_CHANGE
                {
                    AccountID = accountId,
                    Amount = amount,
                    ChangeType = (int) BalanceChangeType.Deposit,
                    ValueDate = dateOper,
                    Description = "Пополнение с кошелька №" + wallet.User
                });
            try
            {
                ctx.SaveChanges();
            }
            catch (Exception ex)
            {
                Logger.Error("DepositOrWithdraw() - error saving balance change", ex);
                error = WalletError.ServerError;
                return null;
            }

            var balanceChangeId = balanceChange.ID;
            ctx.TRANSFER.Add(new TRANSFER
                {
                    Amount = -amountInSrcCurrency,
                    TargetAmount = -amountInSrcCurrency,
                    User = user.ID,
                    Comment = "Т. счет №" + account.ID,
                    ValueDate = dateOper,
                    BalanceChange = balanceChangeId,
                });

            try
            {
                ctx.SaveChanges();
            }
            //catch (System.Data.Entity.Infrastructure.DbUpdateConcurrencyException)
            //{
            //}
            catch (Exception ex)
            {
                Logger.Error("DepositOrWithdraw() - error saving transfer for user " + user.ID +
                             ", balance change Id: " + balanceChangeId + ", user: " + user.ID, ex);
                error = WalletError.ServerError;
                return null;
            }
            error = WalletError.OK;
            return LinqToEntity.DecorateWallet(wallet);
        }
        public string EditSpotItem(TradeSharpConnection context, SpotModel model)
        {
            var result = string.Empty;
            var newContext = EnsureContext(ref context);
            try
            {
                var itemToEdit = context.SPOT.Single(x => x.Title == model.Title);

                itemToEdit.ComBase = model.ComBase;
                itemToEdit.ComCounter = model.ComCounter;
                itemToEdit.Title = model.Title;
                itemToEdit.CodeFXI = model.CodeFXI;
                itemToEdit.MinVolume = model.MinVolume;
                itemToEdit.MinStepVolume = model.MinStepVolume;
                itemToEdit.Precise = model.Precise;
                itemToEdit.SwapBuy = model.SwapBuy;
                itemToEdit.SwapSell = model.SwapSell;
                itemToEdit.Description = model.Description;

                context.SaveChanges();
            }
            catch (Exception ex)
            {
                Logger.Error("EditSpotItem()", ex);
                result = ex.Message;
            }
            finally
            {
                if (newContext != null) newContext.Dispose();
            }
            return result;
        }
 public bool UpdateAccountBalance(TradeSharpConnection ctx,
     ACCOUNT account, decimal amount, BalanceChangeType changeType,
     string description, DateTime valueDate, int? positionId)
 {
     var bc = new BALANCE_CHANGE
     {
         AccountID = account.ID,
         Amount = amount,
         ChangeType = (int)changeType,
         Description = description,
         ValueDate = valueDate,
         Position = positionId
     };
     try
     {
         ctx.BALANCE_CHANGE.Add(bc);
         account.Balance += ((changeType == BalanceChangeType.Deposit ||
             changeType == BalanceChangeType.Profit) ? amount : -amount);
         ctx.SaveChanges();
         return true;
     }
     catch (Exception ex)
     {
         Logger.ErrorFormat("Ошибка обновления баланса счета {0} на сумму {1}: {2}",
             account.ID, amount, ex);
         return false;
     }
 }
 private bool ModifyClosedPosition(MarketOrder order, TradeSharpConnection ctx, POSITION_CLOSED pos,
     out string errorString)
 {
     errorString = string.Empty;
     if (order.IsClosed)
     {
         var opened = new POSITION
         {
             AccountID = pos.AccountID,
             ID = pos.ID,
             Comment = order.Comment,
             Magic = order.Magic,
             ExpertComment = order.ExpertComment,
             PendingOrderID = order.PendingOrderID,
             PriceBest = (decimal?)order.PriceBest,
             PriceEnter = (decimal)order.PriceEnter,
             PriceWorst = (decimal?)order.PriceWorst,
             Side = order.Side,
             Stoploss = (decimal?)order.StopLoss,
             Symbol = order.Symbol,
             Takeprofit = (decimal?)order.TakeProfit,
             TimeEnter = order.TimeEnter,
             Volume = order.Volume,
             State = (int) order.State,
             MasterOrder = order.MasterOrder
         };
         ctx.POSITION_CLOSED.Remove(pos);
         ctx.POSITION.Add(opened);
         ctx.SaveChanges();
         Logger.InfoFormat("Closed order {0} {1} {2} {3} was reopened",
             pos.ID, pos.Side > 0 ? "BUY" : "SELL", pos.Volume, pos.Symbol);
         return true;
     }
     pos.Comment = order.Comment;
     pos.Magic = order.Magic;
     pos.ExpertComment = order.ExpertComment;
     pos.PendingOrderID = order.PendingOrderID;
     pos.PriceBest = (decimal?)order.PriceBest;
     pos.PriceEnter = (decimal)order.PriceEnter;
     pos.PriceWorst = (decimal?)order.PriceWorst;
     pos.Side = order.Side;
     pos.Stoploss = (decimal?)order.StopLoss;
     pos.Symbol = order.Symbol;
     pos.Takeprofit = (decimal?)order.TakeProfit;
     if (order.TimeEnter != default(DateTime))
         pos.TimeEnter = order.TimeEnter;
     pos.Volume = order.Volume;
     pos.ExitReason = (int) order.ExitReason;
     pos.PriceExit = (decimal) (order.PriceExit ?? 0);
     pos.PriceWorst = (decimal?) order.PriceWorst;
     pos.ResultBase = (decimal)order.ResultBase;
     pos.ResultDepo = (decimal)order.ResultDepo;
     pos.ResultPoints = (decimal)order.ResultPoints;
     pos.TimeExit = order.TimeExit ?? default(DateTime);
     pos.Swap = (decimal) (order.Swap ?? 0);
     Logger.InfoFormat("Closed order {0} {1} {2} {3} was modified",
             pos.ID, pos.Side > 0 ? "BUY" : "SELL", pos.Volume, pos.Symbol);
     ctx.SaveChanges();
     return true;
 }
Exemple #17
0
        private void DoFixtransactions(BackgroundWorkerTask taskParam)
        {
            var accountList = (List<int>) taskParam.DataParam;
            int accountNumber = 0;
            foreach (var id in accountList)
            {
                if (workerQuote.CancellationPending) break;
                var accountId = id;
                using (var db = new TradeSharpConnection())
                {
                    foreach (var order in db.POSITION_CLOSED.Where(p => p.AccountID == accountId))
                    {
                        if (workerQuote.CancellationPending) break;
                        var orderId = order.ID;
                        if (db.BALANCE_CHANGE.Any(bc => bc.Position == orderId)) continue;

                        var changeType = (int) (order.ResultDepo > 0 ? BalanceChangeType.Profit : BalanceChangeType.Loss);
                        var closeTime = order.TimeExit;
                        var orderResult = Math.Abs(order.ResultDepo);
                        var missIdBc = db.BALANCE_CHANGE.FirstOrDefault(b => b.AccountID == accountId &&
                                                                             b.ValueDate == closeTime &&
                                                                             b.Amount == orderResult);
                        if (missIdBc != null)
                        {
                            missIdBc.Position = orderId;
                            missIdBc.ChangeType = changeType;
                        }
                        else
                            db.BALANCE_CHANGE.Add(new BALANCE_CHANGE
                            {
                                AccountID = order.AccountID,
                                Position = order.ID,
                                Amount = order.ResultDepo,
                                ChangeType = changeType,
                                ValueDate = order.TimeExit
                            });
                    }
                    db.SaveChanges();
                }
                workerQuote.ReportProgress(100*(accountNumber++)/accountList.Count);
            }
        }
        public RequestStatus InvestOrWithdrawFromPamm(decimal sumInWalletCurrency, bool withdrawNotInvest,
                                                      bool withdrawAll,
                                                      TradeSharpConnection databaseConnection)
        {
            this.sumInWalletCurrency = sumInWalletCurrency;
            this.withdrawNotInvest = withdrawNotInvest;
            this.withdrawAll = withdrawAll;

            var checkStatus = CheckAmount();
            if (checkStatus != RequestStatus.OK)
                return checkStatus;

            ctx = databaseConnection ?? DatabaseContext.Instance.Make();
            try
            {
                // найти подписанта
                var subscriber = ctx.PLATFORM_USER.FirstOrDefault(u => u.Login == login);
                if (subscriber == null)
                {
                    Logger.ErrorFormat("InvestOrWithdrawFromPamm(login={0}) - подписант не найден", login);
                    return RequestStatus.IncorrectData;
                }

                // владелец целевого ПАММ-счета
                var stat = FindPAMMServiceWithOwner();
                if (stat != RequestStatus.OK)
                    return stat;

                // посчитать средства по счету
                var account = ctx.ACCOUNT.First(a => a.ID == accountId);
                var quotes = QuoteStorage.Instance.ReceiveAllData();
                bool noQuoteError;

                List<AccountShare> shares;
                var equity = WalletManager.CalculateAccountEquityWithShares(ctx, account, owner.ID, quotes, out shares,
                                                                            out noQuoteError);
                if (noQuoteError)
                {
                    Logger.ErrorFormat(
                        "InvestOrWithdrawFromPamm(acc={0}) - невозможно произвести расчет текущей прибыли - нет котировок",
                        accountId);
                    return RequestStatus.ServerError;
                }
                decimal amountInAccountCurx;
                // пересчитать сумму в валюту ПАММа
                // проверить не выводит ли / не заводит ли слишком много?
                var status = CheckShareAndUpdateSubscriberWallet(shares, subscriber, account, quotes,
                                                                 out amountInAccountCurx);
                if (status != RequestStatus.OK)
                    return status;

                // добавить денег и пересчитать дольки
                var newEquity = equity + (withdrawNotInvest ? -1 : 1)*amountInAccountCurx;
                var sharePercent = amountInAccountCurx*100/newEquity;
                var sharesNew = shares.Select(s => new AccountShare
                    {
                        UserId = s.UserId,
                        ShareMoney = s.ShareMoney,
                        SharePercent = s.ShareMoney*100/newEquity,
                        HWM = s.HWM
                    }).ToList();

                // доля нового совладельца - пополнить или создать запись
                if (!withdrawNotInvest)
                {
                    var newOwnerShare = sharesNew.FirstOrDefault(s => s.UserId == subscriber.ID);
                    if (newOwnerShare != null)
                    {
                        newOwnerShare.SharePercent += sharePercent;
                        newOwnerShare.ShareMoney += amountInAccountCurx;
                    }
                    else
                    {
                        sharesNew.Add(new AccountShare
                            {
                                ShareMoney = amountInAccountCurx,
                                SharePercent = sharePercent,
                                UserId = subscriber.ID,
                                HWM = amountInAccountCurx
                            });
                    }
                }

                // найти существующую подписку и либо добавить денег,
                // либо создать новую подписку
                var subscriptExists = ctx.SUBSCRIPTION.Any(s => s.Service == service.ID && s.User == subscriber.ID);
                if (!subscriptExists && !withdrawNotInvest)
                {
                    // добавить подписку
                    ctx.SUBSCRIPTION.Add(new SUBSCRIPTION
                        {
                            User = subscriber.ID,
                            RenewAuto = false,
                            Service = service.ID,
                            TimeStarted = DateTime.Now,
                            TimeEnd = DateTime.Now
                        });
                }
                else if (subscriptExists && withdrawNotInvest && withdrawAll)
                {
                    // удалить подписку
                    ctx.SUBSCRIPTION.Remove(
                        ctx.SUBSCRIPTION.First(s => s.Service == service.ID && s.User == subscriber.ID));
                }

                // модифицировать записи ACCOUNT_SHARE
                UpdateShares(sharesNew, subscriber.ID);

                // пополнить баланс счета
                account.Balance += amountInAccountCurx;

                // сохранить изменения
                ctx.SaveChanges();
                return RequestStatus.OK;
            } // using ...
            catch (Exception ex)
            {
                Logger.Error("Ошибка в InvestOrWithdrawFromPamm", ex);
                return RequestStatus.ServerError;
            }
            finally
            {
                if (databaseConnection == null)
                    ctx.Dispose();
            }
        }