/// <summary>
        /// Handler for validating Execution records.
        /// </summary>
        /// <param name="sender">The object that originated the event.</param>
        /// <param name="e">The event arguments.</param>
        internal static void OnExecutionRowValidate(object sender, DataModel.ExecutionRowChangeEventArgs e)
        {
            DataModel.DestinationOrderRow destinationOrderRow;
            Decimal executedQuantity;
            DataModelTransaction dataModelTransaction;
            Decimal orderedQuantity;

            // The Business Rules will be enforced on this Execution.  Note that it is locked at the point this handler is called.
            DataModel.ExecutionRow executionRow = e.Row;

            // The action on the row determines which rule to evaluate.
            switch (e.Action)
            {
            case DataRowAction.Add:

                // This rule will update the status of the owning Destination Order based on the quantity executed.
                dataModelTransaction = DataModel.CurrentTransaction;

                // The aggregate of the quantities executed will determine whether the Destination Order requires a status change.
                destinationOrderRow = executionRow.DestinationOrderRow;
                destinationOrderRow.AcquireReaderLock(dataModelTransaction);
                if (destinationOrderRow.RowState == DataRowState.Detached)
                {
                    return;
                }

                // This calculates the quantity outstanding on an order and the quantity executed on the order.
                orderedQuantity  = destinationOrderRow.OrderedQuantity - destinationOrderRow.CanceledQuantity;
                executedQuantity = 0.0M;
                foreach (DataModel.ExecutionRow siblingRow in destinationOrderRow.GetExecutionRows())
                {
                    siblingRow.AcquireReaderLock(dataModelTransaction);
                    executedQuantity += siblingRow.ExecutionQuantity;
                }

                // This rule will set the status on the owning Destination Order based on the amont outstanding and the amount ordered.  First, if the quantity
                // executed is greater than the quantity ordered, the Order goes into an error state.  We can't reject executions as they come from an external
                // source, but the order can be flag and put into an error state.
                if (executedQuantity > orderedQuantity)
                {
                    if (destinationOrderRow.StatusCode != StatusCode.Error)
                    {
                        DestinationOrderService.UpdateDestinationOrderStatus(destinationOrderRow, StatusCode.Error);
                    }
                }
                else
                {
                    // When the total quantity executed is reduced to zero then the order goes back into the initial state.
                    if (executedQuantity == 0.0m)
                    {
                        if (destinationOrderRow.StatusCode != StatusCode.New)
                        {
                            DestinationOrderService.UpdateDestinationOrderStatus(destinationOrderRow, StatusCode.New);
                        }
                    }
                    else
                    {
                        // While the executed quantity is still less than the outstanding quantity the order is consdered to be partially filled.  Otherwise,
                        // the order is completely filled.
                        if (executedQuantity < orderedQuantity)
                        {
                            if (destinationOrderRow.StatusCode != StatusCode.PartiallyFilled)
                            {
                                DestinationOrderService.UpdateDestinationOrderStatus(destinationOrderRow, StatusCode.PartiallyFilled);
                            }
                        }
                        else
                        {
                            if (destinationOrderRow.StatusCode != StatusCode.Filled)
                            {
                                DestinationOrderService.UpdateDestinationOrderStatus(destinationOrderRow, StatusCode.Filled);
                            }
                        }
                    }
                }

                break;

            case DataRowAction.Delete:

                // A middle tier context is required to lock the rows so the quantities can be aggregated.
                dataModelTransaction = DataModel.CurrentTransaction;

                // The aggregate of the quantities executed will determine whether the Destination Order requires a status change.
                destinationOrderRow = (DataModel.DestinationOrderRow)executionRow.GetParentRow(
                    DataModel.Execution.DestinationOrderExecutionRelation,
                    DataRowVersion.Original);
                destinationOrderRow.AcquireReaderLock(dataModelTransaction);
                if (destinationOrderRow.RowState == DataRowState.Detached)
                {
                    return;
                }

                // This calculates the quantity outstanding on an order and the quantity executed on the order.
                orderedQuantity  = destinationOrderRow.OrderedQuantity - destinationOrderRow.CanceledQuantity;
                executedQuantity = 0.0M;
                foreach (DataModel.ExecutionRow siblingRow in destinationOrderRow.GetExecutionRows())
                {
                    siblingRow.AcquireReaderLock(dataModelTransaction);
                    executedQuantity += siblingRow.ExecutionQuantity;
                }

                // When the total quantity executed is reduced to zero then the order goes back into the initial state.  Note that it is impossible for the
                // order to transition into a error state by deleting an execution.
                if (executedQuantity == 0.0m)
                {
                    if (destinationOrderRow.StatusCode != StatusCode.New)
                    {
                        DestinationOrderService.UpdateDestinationOrderStatus(destinationOrderRow, StatusCode.New);
                    }
                }
                else
                {
                    // While the executed quantity is still less than the outstanding quantity the order is consdered to be partially filled.  Note that it is
                    // impossible for the order to transition to a filled state by deleting an execution.
                    if (executedQuantity < orderedQuantity)
                    {
                        if (destinationOrderRow.StatusCode != StatusCode.PartiallyFilled)
                        {
                            DestinationOrderService.UpdateDestinationOrderStatus(destinationOrderRow, StatusCode.PartiallyFilled);
                        }
                    }
                }

                break;
            }
        }
Beispiel #2
0
 public void CreateDestinationOrders(DestinationOrderInfo[] destinationOrders)
 {
     // Create the orders.
     DestinationOrderService.CreateDestinationOrders(destinationOrders);
 }
Beispiel #3
0
 public void DestroyDestinationOrders(DestinationOrderReference[] destinationOrders)
 {
     // Destroy the orders.
     DestinationOrderService.DestroyDestinationOrders(destinationOrders);
 }
Beispiel #4
0
 public void ClearOrders()
 {
     // Clear all the executions and then all the destination orders.
     ExecutionService.Truncate();
     DestinationOrderService.Truncate();
 }