Esempio n. 1
0
        private void CommitStopout(MarginTradingAccount account)
        {
            var activeOrders = _ordersCache.ActiveOrders.GetOrdersByAccountIds(account.Id);

            var ordersToClose        = new List <Order>();
            var newAccountUsedMargin = account.GetUsedMargin();

            foreach (var order in activeOrders.OrderBy(o => o.GetTotalFpl()))
            {
                if (newAccountUsedMargin <= 0 ||
                    account.GetTotalCapital() / newAccountUsedMargin > account.GetMarginCallLevel())
                {
                    break;
                }

                ordersToClose.Add(order);
                newAccountUsedMargin -= order.GetMarginMaintenance();
            }

            if (!ordersToClose.Any())
            {
                return;
            }

            _stopoutEventChannel.SendEvent(this, new StopOutEventArgs(account, ordersToClose.ToArray()));

            foreach (var order in ordersToClose)
            {
                SetOrderToClosingState(order, OrderCloseReason.StopOut);
            }
        }
Esempio n. 2
0
 public void UpdateBalance(MarginTradingAccount account)
 {
     UpdateAccount(account.ClientId, account.Id, x =>
     {
         x.Balance = account.Balance;
         x.WithdrawTransferLimit = account.WithdrawTransferLimit;
     });
 }
Esempio n. 3
0
 public StopOutEventArgs(MarginTradingAccount account)
 {
     if (account == null)
     {
         throw new ArgumentNullException(nameof(account));
     }
     Account = account;
 }
        private static MarginTradingAccount GetDumbMarginTradingAccount()
        {
            var result = new MarginTradingAccount();

            result.AccountFpl.ActualHash     = 1;
            result.AccountFpl.CalculatedHash = 1;

            return(result);
        }
Esempio n. 5
0
 private void NotifyAccountLevelChanged(MarginTradingAccount account, AccountLevel newAccountLevel)
 {
     switch (newAccountLevel)
     {
     case AccountLevel.MarginCall:
         _marginCallEventChannel.SendEvent(this, new MarginCallEventArgs(account));
         break;
     }
 }
Esempio n. 6
0
        private void NotifyAccountStatsChanged(MarginTradingAccount account)
        {
            account.CacheNeedsToBeUpdated();

            // not needed right now

            //var stats = account.ToRabbitMqContract();

            //_rabbitMqNotifyService.UpdateAccountStats(new AccountStatsUpdateMessage {Accounts = new[] {stats}});
        }
Esempio n. 7
0
        public void SendEmailStopOutCyprus()
        {
            var testAccount = new MarginTradingAccount
            {
                Id          = "TestAccountId",
                BaseAssetId = "EUR",
                LegalEntity = LykkeConstants.LykkeCyprusLegalEntity
            };

            _emailService.SendStopOutEmailAsync(testAccount);
        }
Esempio n. 8
0
        public void SendEmailStopOut()
        {
            var testAccount = new MarginTradingAccount
            {
                Id          = "TestAccountId",
                BaseAssetId = "EUR",
                LegalEntity = "DEFAULT"
            };

            _emailService.SendStopOutEmailAsync(testAccount);
        }
Esempio n. 9
0
        private async Task Handle(FreezeAmountForWithdrawalCommand command, IEventPublisher publisher)
        {
            var(executionInfo, _) = await _operationExecutionInfoRepository.GetOrAddAsync(
                operationName : OperationName,
                operationId : command.OperationId,
                factory : () => new OperationExecutionInfo <WithdrawalFreezeOperationData>(
                    operationName: OperationName,
                    id: command.OperationId,
                    lastModified: _dateService.Now(),
                    data: new WithdrawalFreezeOperationData
            {
                State     = OperationState.Initiated,
                AccountId = command.AccountId,
                Amount    = command.Amount,
            }
                    ));

            MarginTradingAccount account = null;

            try
            {
                account = _accountsCacheService.Get(command.AccountId);
            }
            catch
            {
                publisher.PublishEvent(new AmountForWithdrawalFreezeFailedEvent(command.OperationId, _dateService.Now(),
                                                                                command.AccountId, command.Amount, $"Failed to get account {command.AccountId}"));
                return;
            }

            if (executionInfo.Data.SwitchState(OperationState.Initiated, OperationState.Started))
            {
                if (account.GetFreeMargin() >= command.Amount)
                {
                    await _accountUpdateService.FreezeWithdrawalMargin(command.AccountId, command.OperationId,
                                                                       command.Amount);

                    _chaosKitty.Meow(command.OperationId);

                    publisher.PublishEvent(new AmountForWithdrawalFrozenEvent(command.OperationId, _dateService.Now(),
                                                                              command.AccountId, command.Amount, command.Reason));
                }
                else
                {
                    publisher.PublishEvent(new AmountForWithdrawalFreezeFailedEvent(command.OperationId,
                                                                                    _dateService.Now(),
                                                                                    command.AccountId, command.Amount, "Not enough free margin"));
                }

                _chaosKitty.Meow(command.OperationId);

                await _operationExecutionInfoRepository.Save(executionInfo);
            }
        }
Esempio n. 10
0
        public async Task <DataReaderAccountBackendContract> GetAccountById(string id)
        {
            var account = await _accountsRepository.GetAsync(id);

            if (account == null)
            {
                throw new AccountNotFoundException(id, "Account was not found.");
            }

            return(ToBackendContract(MarginTradingAccount.Create(account), _dataReaderSettings.IsLive));
        }
 public static AccountRecord ConvertToDto(this MarginTradingAccount account)
 {
     return(new AccountRecord
     {
         Id = account.Id,
         ClientId = account.ClientId,
         TradingConditionId = account.TradingConditionId,
         BaseAssetId = account.BaseAssetId,
         Balance = account.Balance.GetValueOrDefault(),
         WithdrawTransferLimit = account.WithdrawTransferLimit.GetValueOrDefault()
     });
 }
Esempio n. 12
0
        public MarginTradingAccount GuessAccountWithOrder(Order order)
        {
            var accountFpl  = new AccountFpl();
            var newInstance = MarginTradingAccount.Create(_accountsCacheService.Get(order.ClientId, order.AccountId), accountFpl);

            var orders = _ordersCache.ActiveOrders.GetOrdersByInstrumentAndAccount(order.Instrument, order.AccountId).ToList();

            orders.Add(order);

            UpdateAccount(newInstance, accountFpl, orders.ToArray());

            return(newInstance);
        }
Esempio n. 13
0
 public StopOutEventArgs(MarginTradingAccount account, Order[] orders)
 {
     if (account == null)
     {
         throw new ArgumentNullException(nameof(account));
     }
     if (orders == null)
     {
         throw new ArgumentNullException(nameof(orders));
     }
     Account = account;
     Orders  = orders;
 }
Esempio n. 14
0
 public void TryAddNew(MarginTradingAccount account)
 {
     _lockSlim.EnterWriteLock();
     try
     {
         account.LastUpdateTime = _dateService.Now();
         _accounts.TryAdd(account.Id, account);
     }
     finally
     {
         _lockSlim.ExitWriteLock();
     }
 }
Esempio n. 15
0
        public MarginTradingAccount GuessAccountWithNewActiveOrder(Order order)
        {
            var newInstance = MarginTradingAccount.Create(_accountsCacheService.Get(order.ClientId, order.AccountId));

            var activeOrders = GetActiveOrders(newInstance.Id);

            activeOrders.Add(order);

            var pendingOrders = GetPendingOrders(newInstance.Id);

            UpdateAccount(newInstance, activeOrders, pendingOrders);

            return(newInstance);
        }
Esempio n. 16
0
 public static AccountStatEntity Create(MarginTradingAccount account, DateTime now)
 {
     return(new AccountStatEntity
     {
         Id = account.Id,
         PnL = account.GetPnl(),
         UnrealizedDailyPnl = account.GetUnrealizedDailyPnl(),
         UsedMargin = account.GetUsedMargin(),
         MarginInit = account.GetMarginInit(),
         OpenPositionsCount = account.GetOpenPositionsCount(),
         MarginCall1Level = account.GetMarginCall1Level(),
         MarginCall2Level = account.GetMarginCall2Level(),
         StopoutLevel = account.GetStopOutLevel(),
         WithdrawalFrozenMargin = account.GetFrozenMargin(),
         UnconfirmedMargin = account.GetUnconfirmedMargin(),
         HistoryTimestamp = now,
     });
 }
Esempio n. 17
0
        private void CommitStopout(MarginTradingAccount account)
        {
            var pendingOrders = _ordersCache.WaitingForExecutionOrders.GetOrdersByAccountIds(account.Id);

            var cancelledPendingOrders = new List <Order>();

            foreach (var pendingOrder in pendingOrders)
            {
                cancelledPendingOrders.Add(pendingOrder);
                CancelPendingOrder(pendingOrder.Id, OrderCloseReason.CanceledBySystem, "Stop out");
            }

            var activeOrders = _ordersCache.ActiveOrders.GetOrdersByAccountIds(account.Id);

            var ordersToClose        = new List <Order>();
            var newAccountUsedMargin = account.GetUsedMargin();

            foreach (var order in activeOrders.OrderBy(o => o.GetTotalFpl()))
            {
                if (newAccountUsedMargin <= 0 ||
                    account.GetTotalCapital() / newAccountUsedMargin > account.GetMarginCallLevel())
                {
                    break;
                }

                ordersToClose.Add(order);
                newAccountUsedMargin -= order.GetMarginMaintenance();
            }

            if (!ordersToClose.Any() && !cancelledPendingOrders.Any())
            {
                return;
            }

            _stopoutEventChannel.SendEvent(this,
                                           new StopOutEventArgs(account, ordersToClose.Concat(cancelledPendingOrders).ToArray()));

            foreach (var order in ordersToClose)
            {
                SetOrderToClosingState(order, OrderCloseReason.StopOut);
            }
        }
        public async Task <MarginTradingAccount> UpdateBalanceAsync(string clientId, string accountId, decimal amount, bool changeLimit)
        {
            var account = await _tableStorage.GetDataAsync(MarginTradingAccountEntity.GeneratePartitionKey(clientId), MarginTradingAccountEntity.GenerateRowKey(accountId));

            if (account != null)
            {
                account.Balance += (double)amount;

                if (changeLimit)
                {
                    account.WithdrawTransferLimit += (double)amount;
                }

                await _tableStorage.InsertOrMergeAsync(account);

                return(MarginTradingAccount.Create(account));
            }

            return(null);
        }
Esempio n. 19
0
 public static MarginTradingAccountClientContract ToClientContract(this MarginTradingAccount src)
 {
     return(new MarginTradingAccountClientContract
     {
         Id = src.Id,
         TradingConditionId = src.TradingConditionId,
         BaseAssetId = src.BaseAssetId,
         Balance = src.Balance,
         WithdrawTransferLimit = src.WithdrawTransferLimit,
         MarginCall = src.GetMarginCallLevel(),
         StopOut = src.GetStopOutLevel(),
         TotalCapital = src.GetTotalCapital(),
         FreeMargin = src.GetFreeMargin(),
         MarginAvailable = src.GetMarginAvailable(),
         UsedMargin = src.GetUsedMargin(),
         MarginInit = src.GetMarginInit(),
         PnL = src.GetPnl(),
         OpenPositionsCount = src.GetOpenPositionsCount(),
         MarginUsageLevel = src.GetMarginUsageLevel()
     });
 }
Esempio n. 20
0
        private void CommitStopOut(MarginTradingAccount account, InstrumentBidAskPair quote)
        {
            if (account.IsInLiquidation())
            {
                return;
            }

            var liquidationType = account.GetUsedMargin() == account.GetCurrentlyUsedMargin()
                ? LiquidationType.Normal
                : LiquidationType.Mco;

            _cqrsSender.SendCommandToSelf(new StartLiquidationInternalCommand
            {
                OperationId     = _identityGenerator.GenerateGuid(),//TODO: use quote correlationId
                AccountId       = account.Id,
                CreationTime    = _dateService.Now(),
                QuoteInfo       = quote?.ToJson(),
                LiquidationType = liquidationType,
                OriginatorType  = OriginatorType.System,
            });

            _stopOutEventChannel.SendEvent(this, new StopOutEventArgs(account));
        }
Esempio n. 21
0
 public MarginCallEventArgs(MarginTradingAccount account, AccountLevel level)
 {
     Account         = account ?? throw new ArgumentNullException(nameof(account));
     MarginCallLevel = level;
 }
Esempio n. 22
0
        public void OneTimeSetUp()
        {
            RegisterDependencies();
            _accountsCacheService        = Container.Resolve <IAccountsCacheService>();
            _tradingConditionsManager    = Container.Resolve <TradingConditionsManager>();
            _matchingEngineRoutesManager = Container.Resolve <MatchingEngineRoutesManager>();
            if (_matchingEngineRoutesManager == null)
            {
                throw new Exception("Unable to resolve MatchingEngineRoutesCacheService");
            }

            // Add user accounts
            var account1 = new MarginTradingAccount()
            {
                ClientId = "CLIENT001"
            };
            var account2 = new MarginTradingAccount()
            {
                ClientId = "CLIENT002"
            };
            var account3 = new MarginTradingAccount()
            {
                ClientId = "CLIENT003"
            };
            var account4 = new MarginTradingAccount()
            {
                ClientId = "CLIENT004"
            };

            _accountsCacheService.UpdateAccountsCache(account1.ClientId, new[] { account1 });
            _accountsCacheService.UpdateAccountsCache(account2.ClientId, new[] { account2 });
            _accountsCacheService.UpdateAccountsCache(account3.ClientId, new[] { account3 });
            _accountsCacheService.UpdateAccountsCache(account4.ClientId, new[] { account4 });

            // Add trading conditions
            System.Threading.Tasks.Task.Run(async() =>
            {
                await _tradingConditionsManager.AddOrReplaceTradingConditionAsync(new TradingCondition()
                {
                    Id = "TCID001", Name = "MarginTradingCondition 1", IsDefault = true
                });
                await _tradingConditionsManager.AddOrReplaceTradingConditionAsync(new TradingCondition()
                {
                    Id = "TCID003", Name = "MarginTradingCondition 3", IsDefault = false
                });
                await _tradingConditionsManager.AddOrReplaceTradingConditionAsync(new TradingCondition()
                {
                    Id = "TCID004", Name = "MarginTradingCondition 4", IsDefault = false
                });
                await _tradingConditionsManager.AddOrReplaceTradingConditionAsync(new TradingCondition()
                {
                    Id = "TCID005", Name = "MarginTradingCondition 5", IsDefault = false
                });
            }).Wait();


            System.Threading.Tasks.Task.Run(async() =>
            {
                await _matchingEngineRoutesManager.AddOrReplaceRouteAsync(new MatchingEngineRoute()
                {
                    Id = "1", Rank = 10, MatchingEngineId = "LYKKE"
                });
                await _matchingEngineRoutesManager.AddOrReplaceRouteAsync(new MatchingEngineRoute()
                {
                    Id = "2", Rank = 5, Instrument = "BTCUSD", MatchingEngineId = "ICM"
                });
                await _matchingEngineRoutesManager.AddOrReplaceRouteAsync(new MatchingEngineRoute()
                {
                    Id = "3", Rank = 4, TradingConditionId = "TCID001", Instrument = "EURCHF", Type = OrderDirection.Buy, MatchingEngineId = "LYKKE"
                });
                await _matchingEngineRoutesManager.AddOrReplaceRouteAsync(new MatchingEngineRoute()
                {
                    Id = "4", Rank = 3, TradingConditionId = "TCID001", ClientId = "CLIENT001", Instrument = "EURCHF", Type = OrderDirection.Buy, MatchingEngineId = "ICM"
                });
                await _matchingEngineRoutesManager.AddOrReplaceRouteAsync(new MatchingEngineRoute()
                {
                    Id = "5", Rank = 4, TradingConditionId = "TCID001", ClientId = "CLIENT002", Instrument = "EURCHF", Type = OrderDirection.Buy, MatchingEngineId = "LYKKE"
                });
                await _matchingEngineRoutesManager.AddOrReplaceRouteAsync(new MatchingEngineRoute()
                {
                    Id = "6", Rank = 4, Instrument = "EURCHF", Type = OrderDirection.Buy, MatchingEngineId = "LYKKE"
                });
                await _matchingEngineRoutesManager.AddOrReplaceRouteAsync(new MatchingEngineRoute()
                {
                    Id = "7", Rank = 4, Instrument = "EURCHF", MatchingEngineId = "LYKKE"
                });
                await _matchingEngineRoutesManager.AddOrReplaceRouteAsync(new MatchingEngineRoute()
                {
                    Id = "8", Rank = 5, ClientId = "CLIENT003", Instrument = "EURCHF", MatchingEngineId = "LYKKE"
                });
                await _matchingEngineRoutesManager.AddOrReplaceRouteAsync(new MatchingEngineRoute()
                {
                    Id = "9", Rank = 6, TradingConditionId = "TCID003", ClientId = "CLIENT002", Instrument = "EURCHF", Type = OrderDirection.Sell, MatchingEngineId = "ICM"
                });
                await _matchingEngineRoutesManager.AddOrReplaceRouteAsync(new MatchingEngineRoute()
                {
                    Id = "10", Rank = 4, TradingConditionId = "TCID004", ClientId = "CLIENT004", Instrument = "EURJPY", MatchingEngineId = "ICM"
                });
                await _matchingEngineRoutesManager.AddOrReplaceRouteAsync(new MatchingEngineRoute()
                {
                    Id = "11", Rank = 4, TradingConditionId = "TCID004", Instrument = "EURJPY", Type = OrderDirection.Buy, MatchingEngineId = "LYKKE"
                });
                await _matchingEngineRoutesManager.AddOrReplaceRouteAsync(new MatchingEngineRoute()
                {
                    Id = "12", Rank = 4, TradingConditionId = "TCID005", Instrument = "EURUSD", Type = OrderDirection.Buy, MatchingEngineId = "LYKKE"
                });
                await _matchingEngineRoutesManager.AddOrReplaceRouteAsync(new MatchingEngineRoute()
                {
                    Id = "13", Rank = 4, TradingConditionId = "TCID005", Instrument = "EURUSD", Type = OrderDirection.Buy, MatchingEngineId = "ICM"
                });
                await _matchingEngineRoutesManager.AddOrReplaceRouteAsync(new MatchingEngineRoute()
                {
                    Id = "14", Rank = 9, Instrument = "BTCEUR", MatchingEngineId = "LYKKE"
                });
                await _matchingEngineRoutesManager.AddOrReplaceRouteAsync(new MatchingEngineRoute()
                {
                    Id = "15", Rank = 7, Type = OrderDirection.Buy, MatchingEngineId = "ICM", Asset = "EUR"
                });
                await _matchingEngineRoutesManager.AddOrReplaceRouteAsync(new MatchingEngineRoute()
                {
                    Id = "16", Rank = 8, Type = OrderDirection.Sell, MatchingEngineId = "ICM", Asset = "EUR"
                });
            }).Wait();

            /* TABLE PROTOTYPE
             *  Id	Rank	tradingConditionId	clientId	instrument	type	matchingEngineId	asset
             *
             *  1	10	    *	                *	        *	        *	    LYKKE
             *  2	5	    *	                *	        BTCUSD	    *	    ICM
             *  3	4	    TCID001	            *	        EURCHF	    Buy	    LYKKE
             *  4	3	    TCID001	            CLIENT001	EURCHF	    Buy	    ICM
             *  5	4	    TCID001	            CLIENT002	EURCHF	    Buy	    LYKKE
             *  6	4	    *	                *	        EURCHF	    Buy	    LYKKE
             *  7	4	    *	                *	        EURCHF	    *	    LYKKE
             *  8	5	    *	                CLIENT003	EURCHF	    *	    LYKKE
             *  9	6	    TCID003	            CLIENT002	EURCHF	    Sell	ICM
             *  10	4	    TCID004	            CLIENT004	EURJPY	    *	    ICM
             *  11	4	    TCID004	            *	        EURJPY	    Buy	    LYKKE
             *  12	4	    TCID005	            *	        EURUSD	    Buy	    LYKKE
             *  13	4	    TCID005	            *	        EURUSD	    Buy	    ICM
             *  14	9	    *	                *	        BTCEUR	    *	    LYKKE
             *  15	7	    *	                *		                Buy	    ICM	                EUR
             *  16	8	    *	                *		                Buy     LYKKE	            EUR
             *
             *
             */
        }
 public async Task AddAsync(MarginTradingAccount account)
 {
     var entity = MarginTradingAccountEntity.Create(account);
     await _tableStorage.InsertOrMergeAsync(entity);
 }
Esempio n. 24
0
        private async Task Handle(BlockAccountsForDeletionCommand command, IEventPublisher publisher)
        {
            var executionInfo = await _operationExecutionInfoRepository.GetOrAddAsync(
                operationName : OperationName,
                operationId : command.OperationId,
                factory : () => new OperationExecutionInfo <DeleteAccountsOperationData>(
                    operationName: OperationName,
                    id: command.OperationId,
                    lastModified: _dateService.Now(),
                    data: new DeleteAccountsOperationData
            {
                State = OperationState.Initiated
            }
                    ));

            //todo think how to remove state saving from commands handler here and for Withdrawal
            if (executionInfo.Data.SwitchState(OperationState.Initiated, OperationState.Started))
            {
                var failedAccounts = new Dictionary <string, string>();

                foreach (var accountId in command.AccountIds)
                {
                    MarginTradingAccount account = null;
                    try
                    {
                        account = _accountsCacheService.Get(accountId);
                    }
                    catch (Exception exception)
                    {
                        failedAccounts.Add(accountId, exception.Message);
                        continue;
                    }

                    var positionsCount = _orderReader.GetPositions().Count(x => x.AccountId == accountId);
                    if (positionsCount != 0)
                    {
                        failedAccounts.Add(accountId, $"Account contain {positionsCount} open positions which must be closed before account deletion.");
                        continue;
                    }

                    var orders = _orderReader.GetPending().Where(x => x.AccountId == accountId).ToList();
                    if (orders.Any())
                    {
                        var(failedToCloseOrderId, failReason) = ((string)null, (string)null);
                        foreach (var order in orders)
                        {
                            try
                            {
                                _tradingEngine.CancelPendingOrder(order.Id, order.AdditionalInfo, command.OperationId,
                                                                  $"{nameof(DeleteAccountsCommandsHandler)}: force close all orders.",
                                                                  OrderCancellationReason.AccountInactivated);
                            }
                            catch (Exception exception)
                            {
                                failedToCloseOrderId = order.Id;
                                failReason           = exception.Message;
                                break;
                            }
                        }

                        if (failedToCloseOrderId != null)
                        {
                            failedAccounts.Add(accountId, $"Failed to close order [{failedToCloseOrderId}]: {failReason}.");
                            continue;
                        }
                    }

                    if (account.AccountFpl.WithdrawalFrozenMarginData.Any())
                    {
                        await _log.WriteErrorAsync(nameof(DeleteAccountsCommandsHandler),
                                                   nameof(BlockAccountsForDeletionCommand), account.ToJson(),
                                                   new Exception("While deleting an account it contained some frozen withdrawal data. Account is deleted."));
                    }

                    if (account.AccountFpl.UnconfirmedMarginData.Any())
                    {
                        await _log.WriteErrorAsync(nameof(DeleteAccountsCommandsHandler),
                                                   nameof(BlockAccountsForDeletionCommand), account.ToJson(),
                                                   new Exception("While deleting an account it contained some unconfirmed margin data. Account is deleted."));
                    }

                    if (account.Balance != 0)
                    {
                        await _log.WriteErrorAsync(nameof(DeleteAccountsCommandsHandler),
                                                   nameof(BlockAccountsForDeletionCommand), account.ToJson(),
                                                   new Exception("While deleting an account it's balance on side of TradingCore was non zero. Account is deleted."));
                    }

                    if (!await UpdateAccount(account, true,
                                             r => failedAccounts.Add(accountId, r), command.Timestamp))
                    {
                        continue;
                    }
                }

                publisher.PublishEvent(new AccountsBlockedForDeletionEvent(
                                           operationId: command.OperationId,
                                           eventTimestamp: _dateService.Now(),
                                           failedAccountIds: failedAccounts
                                           ));

                _chaosKitty.Meow($"{nameof(BlockAccountsForDeletionCommand)}: " +
                                 "Save_OperationExecutionInfo: " +
                                 $"{command.OperationId}");

                await _operationExecutionInfoRepository.Save(executionInfo);
            }
        }
Esempio n. 25
0
 public AccountBalanceChangedEventArgs([NotNull] MarginTradingAccount account)
 {
     Account = account ?? throw new ArgumentNullException(nameof(account));
 }
Esempio n. 26
0
        private async Task ValidateProductComplexityConfirmation(OrderPlaceRequest order, MarginTradingAccount account)
        {
            if (!await _featureManager.IsEnabledAsync(BrokerFeature.ProductComplexityWarning))
            {
                return;
            }

            var isBasicOrder = new[]
            {
                OrderTypeContract.Market,
                OrderTypeContract.Limit,
                OrderTypeContract.Stop
            }
            .Contains(order.Type);


            if (!isBasicOrder)
            {
                return;
            }

            var shouldShowProductComplexityWarning = AccountAdditionalInfoExtensions.Deserialize(account.AdditionalInfo).ShouldShowProductComplexityWarning ?? true;

            if (!shouldShowProductComplexityWarning)
            {
                return;
            }

            var productComplexityConfimationReceived = order.AdditionalInfo.ProductComplexityConfirmationReceived();

            if (!productComplexityConfimationReceived)
            {
                throw new ValidateOrderException(OrderRejectReason.AccountInvalidState,
                                                 $"Product complexity warning not received for order, placed by account {account.Id}");
            }
        }
Esempio n. 27
0
        public async Task Handle(AccountChangedEvent e)
        {
            var executionInfo = await _operationExecutionInfoRepository.GetOrAddAsync(
                operationName : OperationName,
                operationId : e.OperationId,
                factory : () => new OperationExecutionInfo <OperationData>(
                    operationName: OperationName,
                    id: e.OperationId,
                    lastModified: _dateService.Now(),
                    data: new OperationData {
                State = OperationState.Initiated
            }
                    ));

            if (executionInfo.Data.SwitchState(OperationState.Initiated, OperationState.Finished))
            {
                var updatedAccount = Convert(e.Account);

                switch (e.EventType)
                {
                case AccountChangedEventTypeContract.Created:
                    _accountsCacheService.TryAddNew(MarginTradingAccount.Create(updatedAccount));
                    break;

                case AccountChangedEventTypeContract.Updated:
                {
                    var account = _accountsCacheService.TryGet(e.Account.Id);
                    if (await ValidateAccount(account, e) &&
                        await _accountsCacheService.UpdateAccountChanges(updatedAccount.Id,
                                                                         updatedAccount.TradingConditionId, updatedAccount.WithdrawTransferLimit,
                                                                         updatedAccount.IsDisabled, updatedAccount.IsWithdrawalDisabled, e.ChangeTimestamp))
                    {
                        _accountUpdateService.RemoveLiquidationStateIfNeeded(e.Account.Id,
                                                                             "Trading conditions changed");
                    }
                    break;
                }

                case AccountChangedEventTypeContract.BalanceUpdated:
                {
                    if (e.BalanceChange != null)
                    {
                        var account = _accountsCacheService.TryGet(e.Account.Id);
                        if (await ValidateAccount(account, e))
                        {
                            switch (e.BalanceChange.ReasonType)
                            {
                            case AccountBalanceChangeReasonTypeContract.Withdraw:
                                await _accountUpdateService.UnfreezeWithdrawalMargin(updatedAccount.Id,
                                                                                     e.BalanceChange.Id);

                                break;

                            case AccountBalanceChangeReasonTypeContract.UnrealizedDailyPnL:
                                if (_ordersCache.Positions.TryGetPositionById(e.BalanceChange.EventSourceId,
                                                                              out var position))
                                {
                                    position.ChargePnL(e.BalanceChange.Id, e.BalanceChange.ChangeAmount);
                                }
                                else
                                {
                                    _log.WriteWarning("AccountChangedEvent Handler", e.ToJson(),
                                                      $"Position [{e.BalanceChange.EventSourceId} was not found]");
                                }
                                break;

                            case AccountBalanceChangeReasonTypeContract.RealizedPnL:
                                await _accountUpdateService.UnfreezeUnconfirmedMargin(e.Account.Id,
                                                                                      e.BalanceChange.EventSourceId);

                                break;
                            }

                            if (await _accountsCacheService.UpdateAccountBalance(updatedAccount.Id,
                                                                                 e.BalanceChange.Balance, e.ChangeTimestamp))
                            {
                                _accountUpdateService.RemoveLiquidationStateIfNeeded(e.Account.Id,
                                                                                     "Balance updated");
                                _accountBalanceChangedEventChannel.SendEvent(this,
                                                                             new AccountBalanceChangedEventArgs(updatedAccount));
                            }
                        }
                    }
                    else
                    {
                        _log.WriteWarning("AccountChangedEvent Handler", e.ToJson(), "BalanceChange info is empty");
                    }

                    break;
                }

                case AccountChangedEventTypeContract.Deleted:
                    //account deletion from cache is double-handled by CQRS flow
                    _accountsCacheService.Remove(e.Account.Id);
                    break;

                default:
                    await _log.WriteErrorAsync(nameof(AccountsProjection), nameof(AccountChangedEvent),
                                               e.ToJson(), new Exception("AccountChangedEventTypeContract was in incorrect state"));

                    break;
                }

                _chaosKitty.Meow(e.OperationId);

                await _operationExecutionInfoRepository.Save(executionInfo);
            }
        }
Esempio n. 28
0
        public async Task <IActionResult> AddMarginTradingAccount([FromBody] MarginTradingAccount account)
        {
            await _accountManager.AddAccountAsync(account.ClientId, account.BaseAssetId, account.TradingConditionId);

            return(Ok());
        }
Esempio n. 29
0
 public async Task <IEnumerable <DataReaderAccountBackendContract> > GetAccountsByClientId(string clientId)
 {
     return((await _accountsRepository.GetAllAsync(clientId))
            .Select(x => ToBackendContract(MarginTradingAccount.Create(x), _dataReaderSettings.IsLive)));
 }