Ejemplo n.º 1
0
 /// <summary>
 /// Handles the deletion of a Execution row.
 /// </summary>
 /// <param name="sender">The object that originated the event.</param>
 /// <param name="executionRowChangeEventArgs">The event arguments.</param>
 void OnExecutionRowDeleted(Object sender, DataModel.ExecutionRowChangeEventArgs executionRowChangeEventArgs)
 {
     // We're only interested in deletes that affect the WorkingOrder records in this blotter.
     if (executionRowChangeEventArgs.Action == DataRowAction.Delete)
     {
         // Filtering requires a little more work with a deleted record.  We need to first find the original record and then look up the destination and
         // working order to which it belonged.  We don't need to check for the existence of the destination order or working order as we know that this
         // execution was just deleted and, for it to have existed in the first place, there must have been a parent destination and working order.
         DataModel.ExecutionRow executionRow = executionRowChangeEventArgs.Row;
         Guid destinationOrderId             = (Guid)executionRow[DataModel.Execution.DestinationOrderIdColumn, DataRowVersion.Original];
         DataModel.DestinationOrderRow destinationOrderRow = DataModel.DestinationOrder.DestinationOrderKey.Find(destinationOrderId);
         DataModel.WorkingOrderRow     workingOrderRow     = destinationOrderRow.WorkingOrderRow;
         if (this.blotterIdSet.Contains(workingOrderRow.BlotterId))
         {
             // Once the quantity has been removed from the totals, the percent executed can be updated.
             this.ExecutionQuantity -= (Decimal)executionRow[DataModel.Execution.ExecutionQuantityColumn, DataRowVersion.Original];
             this.ExecutedPercent    = this.DestinationOrderQuantity == 0.0m ? 0.0 : Convert.ToDouble(this.ExecutionQuantity / this.DestinationOrderQuantity);
         }
     }
 }
Ejemplo n.º 2
0
 /// <summary>
 /// Handles a change to the Execution row.
 /// </summary>
 /// <param name="sender">The object that originated the event.</param>
 /// <param name="executionRowChangeEventArgs">The event arguments.</param>
 void OnExecutionRowChanged(Object sender, DataModel.ExecutionRowChangeEventArgs executionRowChangeEventArgs)
 {
     // We're only interested in additions and changes that affect the WorkingOrder records in this blotter.
     if (executionRowChangeEventArgs.Action == DataRowAction.Add || executionRowChangeEventArgs.Action == DataRowAction.Change)
     {
         // This is designed to filter out all events that don't pertain to this blotter.
         DataModel.ExecutionRow        executionRow        = executionRowChangeEventArgs.Row;
         DataModel.DestinationOrderRow destinationOrderRow = executionRow.DestinationOrderRow;
         DataModel.WorkingOrderRow     workingOrderRow     = destinationOrderRow.WorkingOrderRow;
         if (this.blotterIdSet.Contains(workingOrderRow.BlotterId))
         {
             // Once the previous execution is subtracted and the current execution added to the totals we can calculate the percent executed.
             if (executionRow.HasVersion(DataRowVersion.Original))
             {
                 this.executionQuantityField -= (Decimal)executionRow[DataModel.Execution.ExecutionQuantityColumn, DataRowVersion.Original];
             }
             this.ExecutionQuantity += executionRow.ExecutionQuantity;
             this.ExecutedPercent    = this.DestinationOrderQuantity == 0.0m ? 0.0 : Convert.ToDouble(this.ExecutionQuantity / this.DestinationOrderQuantity);
         }
     }
 }
Ejemplo n.º 3
0
        /// <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;
            }
        }