예제 #1
0
        private async Task Handle(OrderHistoryEvent e)
        {
            var order        = e.OrderSnapshot;
            var isBasicOrder = new[]
            {
                OrderTypeContract.Market,
                OrderTypeContract.Limit,
                OrderTypeContract.Stop
            }
            .Contains(order.Type);

            if (!isBasicOrder || !order.ProductComplexityConfirmationReceived())
            {
                return;
            }

            _log.LogInformation($"Product complexity confirmation received for account {order.AccountId} and orderId {order.Id}");

            var entity = await _complexityWarningRepository.GetOrCreate(order.AccountId,
                                                                        () => ComplexityWarningState.Start(order.AccountId));

            entity.OnConfirmedOrderReceived(order.Id, order.CreatedTimestamp, _settings.ComplexityWarningsCount, out var confirmationFlagShouldBeSwitched);

            if (confirmationFlagShouldBeSwitched)
            {
                await _accountManagementService.UpdateComplexityWarningFlag(order.AccountId, shouldShowProductComplexityWarning : false, order.Id);

                _log.LogInformation($"Flag {BrokerFeature.ProductComplexityWarning} for account {entity.AccountId} is switched to off");
            }

            await _complexityWarningRepository.Save(entity);
        }
        public void ShouldBeAbleToSwitchFlag()
        {
            var subject = ComplexityWarningState.Start(AccountId);

            var epoch = DateTime.UnixEpoch;

            var dtAfterFirstOrder = epoch.AddDays(1);

            subject.OnConfirmedOrderReceived(orderId: Guid.NewGuid().ToString(), dtAfterFirstOrder, 2, out var confirmationFlagSwitched);
            confirmationFlagSwitched.Should().BeFalse("After first order confirmation flag should not be switched");
            subject.ShouldShowComplexityWarning.Should().BeTrue();
            subject.SwitchedToFalseAt.Should().BeNull();
            subject.ConfirmedOrders.Count.Should().Be(1);

            var dtAfterSecondOrder = epoch.AddDays(2);

            subject.OnConfirmedOrderReceived(orderId: Guid.NewGuid().ToString(), dtAfterSecondOrder, 2, out confirmationFlagSwitched);
            confirmationFlagSwitched.Should().BeTrue("After second order confirmation flag should be switched");
            subject.ShouldShowComplexityWarning.Should().BeFalse();
            subject.SwitchedToFalseAt.Should().Be(dtAfterSecondOrder);
            subject.ConfirmedOrders.Count.Should().Be(2);

            var dtAfterThirdOrder = epoch.AddDays(3);

            subject.OnConfirmedOrderReceived(orderId: Guid.NewGuid().ToString(), dtAfterThirdOrder, 2, out confirmationFlagSwitched);
            confirmationFlagSwitched.Should().BeFalse("After all next orders confirmation  flag should be untouched");
            subject.ShouldShowComplexityWarning.Should().BeFalse();
            subject.SwitchedToFalseAt.Should().Be(dtAfterSecondOrder);
            subject.ConfirmedOrders.Count.Should().Be(3);
        }
        public async Task Save(ComplexityWarningState entity)
        {
            await using var conn = new SqlConnection(_connectionString);

            var propsToUpdate   = typeof(DbSchema).GetProperties().Where(p => p.Name != nameof(DbSchema.RowVersion));
            var updateStatement = string.Join(",", propsToUpdate.Select(x => "[" + x.Name + "]=@" + x.Name));

            //Dapper.Contrib does not support optimistic concurrency, that's why we have to write plain sql here instead of Update
            //see https://github.com/StackExchange/Dapper/issues/851
            var sql         = @$ "
update dbo.MarginTradingAccountsComplexityWarnings
set {updateStatement}
where AccountId = @{nameof(DbSchema.AccountId)} and RowVersion = @{nameof(DbSchema.RowVersion)}
        public void ShouldNotRaiseFlagChangeOnRetry()
        {
            var subject = ComplexityWarningState.Start(AccountId);

            var orderId = Guid.NewGuid().ToString();
            var cnt     = 0;

            do
            {
                subject.OnConfirmedOrderReceived(orderId: orderId, DateTime.Now, 2, out var confirmationFlagSwitched);

                confirmationFlagSwitched.Should().BeFalse();
                subject.ShouldShowComplexityWarning.Should().BeTrue();
                subject.ConfirmedOrders.Count.Should().Be(1);

                cnt++;
            } while (cnt < 10);
        }
        public void ShouldBeAbleToResetConfirmation()
        {
            //Arrange
            var subject = ComplexityWarningState.Start(AccountId);

            var cnt = 0;

            do
            {
                subject.OnConfirmedOrderReceived(Guid.NewGuid().ToString(), DateTime.Now, 2, out var _);
                cnt++;
            } while (cnt < 10);

            subject.ShouldShowComplexityWarning.Should().BeFalse();
            subject.SwitchedToFalseAt.Should().NotBeNull();

            //Act
            subject.ResetConfirmation();

            //Assert
            subject.ShouldShowComplexityWarning.Should().BeTrue();
            subject.SwitchedToFalseAt.Should().BeNull();
            subject.ConfirmedOrders.Should().BeEmpty();
        }