/// <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 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); }
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 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); } }
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); 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.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); ctx.SaveChanges(); return(true); }
public bool DeletePendingOrder(PENDING_ORDER order, TradeSharpConnection ctx, PendingOrderStatus status, int?positionID, string closeReason) { // получить текущую цену var pair = QuoteStorage.Instance.ReceiveValue(order.Symbol); var priceClosed = pair == null ? 0 : order.Side > 0 ? pair.bid : pair.ask; var hist = new PENDING_ORDER_CLOSED { OrderID = order.ID, AccountID = order.AccountID, Comment = order.Comment, ExpertComment = order.ExpertComment, Magic = order.Magic, PairOCO = order.PairOCO, PriceFrom = order.PriceFrom, PriceTo = order.PriceTo, Side = order.Side, Status = (int)status, Stoploss = order.Stoploss, Takeprofit = order.Takeprofit, Symbol = order.Symbol, TimeClosed = DateTime.Now, Volume = order.Volume, PriceClosed = (decimal)priceClosed, Position = positionID, CloseReason = closeReason }; try { ctx.PENDING_ORDER_CLOSED.Add(hist); var ord = ctx.PENDING_ORDER.FirstOrDefault(p => p.ID == order.ID); if (ord == null) { Logger.ErrorFormat("DeletePendingOrder - ордер {0} не найден", order.ID); ServiceManagerClientManagerProxy.Instance.NewOrderResponse(null, RequestStatus.ServerError, "crudsav"); return(false); } ctx.PENDING_ORDER.Remove(ord); ctx.SaveChanges(); return(true); } catch (Exception ex) { Logger.ErrorFormat("Ошибка в DeletePendingOrder (#{0}): {1}", order.ID, 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); } }
private void CloseOrders(ACCOUNT ac, TradeSharpConnection ctx) { var ordersToClose = ctx.POSITION.Where(p => p.AccountID == ac.ID).ToList(); foreach (var order in ordersToClose) { ctx.POSITION.Remove(order); } var pendingsToClose = ctx.PENDING_ORDER.Where(p => p.AccountID == ac.ID).ToList(); foreach (var order in pendingsToClose) { ctx.PENDING_ORDER.Remove(order); } ctx.SaveChanges(); }
/// <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(); }
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 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); }
private void ZeroBalance(ACCOUNT ac, TradeSharpConnection ctx) { if (ac.Balance == 0) { return; } var valueDate = DateTime.Now; var amount = ac.Balance; ac.Balance = 0; var bc = new BALANCE_CHANGE { AccountID = ac.ID, Amount = amount, ChangeType = (int)BalanceChangeType.Withdrawal, Description = "closing account", ValueDate = valueDate }; ctx.BALANCE_CHANGE.Add(bc); ctx.SaveChanges(); }
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 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 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 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(); } } }
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); }
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 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); }