diff --git a/Client/Components/BaseComponent.razor.cs b/Client/Components/BaseComponent.razor.cs index 80361fcd9..f65161256 100644 --- a/Client/Components/BaseComponent.razor.cs +++ b/Client/Components/BaseComponent.razor.cs @@ -8,6 +8,8 @@ namespace Client.Components { public class BaseComponent : ComponentBase { + private static object protection = new(); + /// /// Updater /// @@ -18,9 +20,12 @@ public class BaseComponent : ComponentBase /// protected virtual Task Render(Action action) => Updater.Send(() => { - action(); - InvokeAsync(StateHasChanged); - Thread.Sleep(1); + lock (protection) + { + action(); + InvokeAsync(StateHasChanged); + Thread.Sleep(1); + } }).Task; } } diff --git a/Core/Validators/OrderPriceValidator.cs b/Core/Validators/OrderPriceValidator.cs index 8413561ae..22d973c6a 100644 --- a/Core/Validators/OrderPriceValidator.cs +++ b/Core/Validators/OrderPriceValidator.cs @@ -22,10 +22,10 @@ public OrderPriceValidator() Include(new OrderValidator()); When(o => _orderTypes.ContainsKey(o.Type ?? OrderTypeEnum.None) is false, () => RuleFor(o => o.Transaction.Price).NotEmpty()); - When(o => Equals(o.Side, OrderSideEnum.Buy) && Equals(o.Type, OrderTypeEnum.Stop), () => RuleFor(o => o.Transaction.Price).GreaterThanOrEqualTo(o => o.Transaction.Instrument.Points.Last().Ask)); - When(o => Equals(o.Side, OrderSideEnum.Sell) && Equals(o.Type, OrderTypeEnum.Stop), () => RuleFor(o => o.Transaction.Price).LessThanOrEqualTo(o => o.Transaction.Instrument.Points.Last().Bid)); - When(o => Equals(o.Side, OrderSideEnum.Buy) && Equals(o.Type, OrderTypeEnum.Limit), () => RuleFor(o => o.Transaction.Price).LessThanOrEqualTo(o => o.Transaction.Instrument.Points.Last().Ask)); - When(o => Equals(o.Side, OrderSideEnum.Sell) && Equals(o.Type, OrderTypeEnum.Limit), () => RuleFor(o => o.Transaction.Price).GreaterThanOrEqualTo(o => o.Transaction.Instrument.Points.Last().Bid)); + When(o => o.Side is OrderSideEnum.Buy && o.Type is OrderTypeEnum.Stop, () => RuleFor(o => o.Transaction.Price).GreaterThanOrEqualTo(o => o.Transaction.Instrument.Points.Last().Ask)); + When(o => o.Side is OrderSideEnum.Sell && o.Type is OrderTypeEnum.Stop, () => RuleFor(o => o.Transaction.Price).LessThanOrEqualTo(o => o.Transaction.Instrument.Points.Last().Bid)); + When(o => o.Side is OrderSideEnum.Buy && o.Type is OrderTypeEnum.Limit, () => RuleFor(o => o.Transaction.Price).LessThanOrEqualTo(o => o.Transaction.Instrument.Points.Last().Ask)); + When(o => o.Side is OrderSideEnum.Sell && o.Type is OrderTypeEnum.Limit, () => RuleFor(o => o.Transaction.Price).GreaterThanOrEqualTo(o => o.Transaction.Instrument.Points.Last().Bid)); When(o => Equals(o.Side, OrderSideEnum.Buy) && Equals(o.Type, OrderTypeEnum.StopLimit), () => { diff --git a/Gateways/Simulation/Libs/Adapter.cs b/Gateways/Simulation/Libs/Adapter.cs index 30ece8885..b5d5d24d1 100644 --- a/Gateways/Simulation/Libs/Adapter.cs +++ b/Gateways/Simulation/Libs/Adapter.cs @@ -327,8 +327,8 @@ protected virtual PositionModel CreatePosition(OrderModel order) /// protected virtual PositionModel UpdatePosition(OrderModel nextOrder, PositionModel previousPosition) { - var isSameBuy = Equals(previousPosition.Order.Side, OrderSideEnum.Buy) && Equals(nextOrder.Side, OrderSideEnum.Buy); - var isSameSell = Equals(previousPosition.Order.Side, OrderSideEnum.Sell) && Equals(nextOrder.Side, OrderSideEnum.Sell); + var isSameBuy = previousPosition.Order.Side is OrderSideEnum.Buy && nextOrder.Side is OrderSideEnum.Buy; + var isSameSell = previousPosition.Order.Side is OrderSideEnum.Sell && nextOrder.Side is OrderSideEnum.Sell; nextOrder.Transaction.Status = OrderStatusEnum.Filled; @@ -346,10 +346,11 @@ protected virtual PositionModel UpdatePosition(OrderModel nextOrder, PositionMod /// /// /// - protected virtual PositionModel IncreasePosition(OrderModel order, PositionModel previousPosition) + protected virtual PositionModel IncreasePosition(OrderModel order, PositionModel previousPos) { var nextOrder = order.Clone() as OrderModel; - var nextPosition = previousPosition.Clone() as PositionModel; + var nextPosition = previousPos.Clone() as PositionModel; + var previousPosition = previousPos.Clone() as PositionModel; nextPosition.Orders = previousPosition.Orders.Concat(new[] { nextOrder }).ToList(); nextPosition.Order.Transaction.Id = nextOrder.Transaction.Id; @@ -383,10 +384,11 @@ protected virtual PositionModel IncreasePosition(OrderModel order, PositionModel /// /// /// - protected virtual PositionModel DecreasePosition(OrderModel order, PositionModel previousPosition) + protected virtual PositionModel DecreasePosition(OrderModel order, PositionModel previousPos) { var nextOrder = order.Clone() as OrderModel; - var nextPosition = previousPosition.Clone() as PositionModel; + var nextPosition = previousPos.Clone() as PositionModel; + var previousPosition = previousPos.Clone() as PositionModel; nextPosition.Orders = previousPosition.Orders.Concat(new[] { nextOrder }).ToList(); nextPosition.Order.Transaction.Id = nextOrder.Transaction.Id; @@ -439,12 +441,12 @@ protected virtual void OnPointUpdate(object sender, NotifyCollectionChangedEvent } var isExecutable = false; - var isBuyStop = Equals(order.Side, OrderSideEnum.Buy) && Equals(order.Type, OrderTypeEnum.Stop); - var isSellStop = Equals(order.Side, OrderSideEnum.Sell) && Equals(order.Type, OrderTypeEnum.Stop); - var isBuyLimit = Equals(order.Side, OrderSideEnum.Buy) && Equals(order.Type, OrderTypeEnum.Limit); - var isSellLimit = Equals(order.Side, OrderSideEnum.Sell) && Equals(order.Type, OrderTypeEnum.Limit); - var isBuyStopLimit = Equals(order.Side, OrderSideEnum.Buy) && Equals(order.Type, OrderTypeEnum.StopLimit) && pointModel.Ask >= order.ActivationPrice; - var isSellStopLimit = Equals(order.Side, OrderSideEnum.Sell) && Equals(order.Type, OrderTypeEnum.StopLimit) && pointModel.Bid <= order.ActivationPrice; + var isBuyStop = order.Side is OrderSideEnum.Buy && order.Type is OrderTypeEnum.Stop; + var isSellStop = order.Side is OrderSideEnum.Sell && order.Type is OrderTypeEnum.Stop; + var isBuyLimit = order.Side is OrderSideEnum.Buy && order.Type is OrderTypeEnum.Limit; + var isSellLimit =order.Side is OrderSideEnum.Sell && order.Type is OrderTypeEnum.Limit; + var isBuyStopLimit = order.Side is OrderSideEnum.Buy && order.Type is OrderTypeEnum.StopLimit && pointModel.Ask >= order.ActivationPrice; + var isSellStopLimit = order.Side is OrderSideEnum.Sell && order.Type is OrderTypeEnum.StopLimit && pointModel.Bid <= order.ActivationPrice; if (isBuyStopLimit || isSellStopLimit) { diff --git a/Gateways/Simulation/Tests/DecreasePosition.cs b/Gateways/Simulation/Tests/DecreasePosition.cs index 1b448f57d..0f7c63148 100644 --- a/Gateways/Simulation/Tests/DecreasePosition.cs +++ b/Gateways/Simulation/Tests/DecreasePosition.cs @@ -31,8 +31,7 @@ public void Decrease() }).First(); - var previousPosition = Account.ActivePositions[orderY.Transaction.Id]; - var nextPosition = base.DecreasePosition(order, previousPosition); + var nextPosition = base.DecreasePosition(order, Account.ActivePositions[orderY.Transaction.Id]); Assert.Single(Account.Positions); Assert.Empty(Account.ActiveOrders); @@ -67,6 +66,8 @@ public void Decrease() // Gain + var previousPosition = Account.Positions.Last(); + Assert.Equal(previousPosition.GainLossEstimate, previousPosition.GainLoss); Assert.Equal(previousPosition.GainLossPointsEstimate, previousPosition.GainLossPoints); } @@ -83,8 +84,7 @@ public void Close() }).First(); - var previousPosition = Account.ActivePositions[orderY.Transaction.Id]; - var nextPosition = base.DecreasePosition(order, previousPosition); + var nextPosition = base.DecreasePosition(order, Account.ActivePositions[orderY.Transaction.Id]); Assert.Single(Account.Positions); Assert.Single(Account.ActivePositions); @@ -119,6 +119,8 @@ public void Close() // Gain + var previousPosition = Account.Positions.Last(); + Assert.Equal(previousPosition.GainLossEstimate, previousPosition.GainLoss); Assert.Equal(previousPosition.GainLossPointsEstimate, previousPosition.GainLossPoints); } @@ -135,8 +137,7 @@ public void Inverse() }).First(); - var previousPosition = Account.ActivePositions[orderY.Transaction.Id]; - var nextPosition = base.DecreasePosition(order, previousPosition); + var nextPosition = base.DecreasePosition(order, Account.ActivePositions[orderY.Transaction.Id]); Assert.Single(Account.Positions); Assert.Empty(Account.ActiveOrders); @@ -171,6 +172,8 @@ public void Inverse() // Gain + var previousPosition = Account.Positions.Last(); + Assert.Equal(previousPosition.GainLossEstimate, previousPosition.GainLoss); Assert.Equal(previousPosition.GainLossPointsEstimate, previousPosition.GainLossPoints); } diff --git a/Gateways/Simulation/Tests/IncreasePosition.cs b/Gateways/Simulation/Tests/IncreasePosition.cs index 7a9d09592..37f6dcc90 100644 --- a/Gateways/Simulation/Tests/IncreasePosition.cs +++ b/Gateways/Simulation/Tests/IncreasePosition.cs @@ -33,8 +33,7 @@ public void Increase() // Increase - var previousPosition = Account.ActivePositions[orderY.Transaction.Id]; - var nextPosition = base.IncreasePosition(order, previousPosition); + var nextPosition = base.IncreasePosition(order, Account.ActivePositions[orderY.Transaction.Id]); var averageTradePrice = nextPosition.Orders.Sum(o => o.Transaction.Volume * o.Transaction.Price) / nextPosition.Orders.Sum(o => o.Transaction.Volume); @@ -72,11 +71,6 @@ public void Increase() Assert.Equal(nextPosition.Order.Transaction.Price, averageTradePrice); Assert.Equal(nextPosition.Order.Transaction.Volume, order.Transaction.Volume + orderY.Transaction.Volume); - // Gain - - Assert.Equal(previousPosition.GainLossEstimate, previousPosition.GainLoss); - Assert.Equal(previousPosition.GainLossPointsEstimate, previousPosition.GainLossPoints); - // Estimate var step = instrumentY.StepValue / instrumentY.StepSize;