示例#1
0
        /// <summary>
        /// Handles a change to a cancelled state.
        /// </summary>
        /// <param name="workingOrderRow">The parent working order.</param>
        static void OnCanceledAction(DataModel.WorkingOrderRow workingOrderRow)
        {
            // A transaction is needed to handle the change.
            DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction;

            // This will lock the WorkingOrderRow while we examine it.
            workingOrderRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
            dataModelTransaction.AddLock(workingOrderRow);
            if (workingOrderRow.RowState == DataRowState.Detached)
            {
                return;
            }

            // When a destination order is canceled we will return the order to its previous state (as determined by aggregating the executed and destination
            // quantities).  The only exception to this is when the working order is in the error state.
            if (workingOrderRow.StatusCode != StatusCode.Error)
            {
                Decimal quantityExecuted = WorkingOrderService.GetExecutionQuantity(dataModelTransaction, workingOrderRow);
                Decimal quantityOrdered  = WorkingOrderService.GetSourceOrderQuantity(dataModelTransaction, workingOrderRow);
                if (quantityExecuted == 0.0M && workingOrderRow.StatusCode != StatusCode.New)
                {
                    WorkingOrderService.UpdateWorkingOrderStatus(workingOrderRow, StatusCode.New);
                }
                if (0.0M < quantityExecuted && quantityExecuted < quantityOrdered && workingOrderRow.StatusCode != StatusCode.PartiallyFilled)
                {
                    WorkingOrderService.UpdateWorkingOrderStatus(workingOrderRow, StatusCode.PartiallyFilled);
                }
            }
        }
示例#2
0
        /// <summary>
        /// Handles a change to a filled state.
        /// </summary>
        /// <param name="workingOrderRow">The parent working order.</param>
        static void OnFilledAction(DataModel.WorkingOrderRow workingOrderRow)
        {
            // A transaction is needed to handle the change.
            DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction;

            // This will lock the WorkingOrderRow while we examine it.
            workingOrderRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
            dataModelTransaction.AddLock(workingOrderRow);
            if (workingOrderRow.RowState == DataRowState.Detached)
            {
                return;
            }

            // This will mark the working order as filled when the quantity executed is the same as the quantity ordered.  The only exception to this is when ng
            // the workiorder is in an error state.
            if (workingOrderRow.StatusCode != StatusCode.Error)
            {
                Decimal quantityOrdered  = WorkingOrderService.GetSourceOrderQuantity(dataModelTransaction, workingOrderRow);
                Decimal quantityExecuted = WorkingOrderService.GetExecutionQuantity(dataModelTransaction, workingOrderRow);
                if (quantityOrdered == quantityExecuted)
                {
                    WorkingOrderService.UpdateWorkingOrderStatus(workingOrderRow, StatusCode.Filled);
                }
            }
        }
        /// <summary>
        /// Validates the source order row when it is deleted.
        /// </summary>
        /// <param name="sourceOrderRow">The source order row that was deleted.</param>
        static void OnSourceOrderDelete(DataModel.SourceOrderRow sourceOrderRow)
        {
            // We'll need to add several rows to the transaction as we validate the source order deletion.
            DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction;

            // There is no implicit locking mechanism for deleted rows, so we need to lock the record manually as we access the parent working order of the deleted
            // source order.
            DataModel.WorkingOrderRow workingOrderRow = null;
            try
            {
                DataModel.DataLock.EnterReadLock();
                workingOrderRow = ((DataModel.WorkingOrderRow)(sourceOrderRow.GetParentRow(DataModel.SourceOrder.WorkingOrderSourceOrderRelation, DataRowVersion.Original)));
            }
            finally
            {
                DataModel.DataLock.ExitReadLock();
            }
            workingOrderRow.AcquireReaderLock(dataModelTransaction);

            // This will insure that the quantity ordered doesn't fall below the quantity placed with brokers and exchanges.
            Decimal sourceOrderQuantity      = WorkingOrderService.GetSourceOrderQuantity(dataModelTransaction, workingOrderRow);
            Decimal destinationOrderQuantity = WorkingOrderService.GetDestinationOrderQuantity(dataModelTransaction, workingOrderRow);

            if (sourceOrderQuantity < destinationOrderQuantity)
            {
                throw new FaultException <DestinationQuantityFault>(
                          new DestinationQuantityFault(workingOrderRow.WorkingOrderId, sourceOrderQuantity, destinationOrderQuantity));
            }
        }
        /// <summary>
        /// Validates the source order row when it changes.
        /// </summary>
        /// <param name="sourceOrderRow">The source order row that was changed.</param>
        static void OnSourceOrderChange(DataModel.SourceOrderRow sourceOrderRow)
        {
            // We can't allow the quantity of source order shares to drop below the quantity of destination order shares.  We only need to check for this condition
            // when the quantity of the source order record has changed.
            Decimal originalQuantity = (Decimal)sourceOrderRow[DataModel.SourceOrder.OrderedQuantityColumn, DataRowVersion.Original];
            Decimal currentQuantity  = (Decimal)sourceOrderRow[DataModel.SourceOrder.OrderedQuantityColumn, DataRowVersion.Current];

            if (originalQuantity < currentQuantity)
            {
                // We'll need to lock several records in order to check source order and destination order totals.
                DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction;

                // Get the working order associated with this source order and lock it.
                DataModel.WorkingOrderRow workingOrderRow = sourceOrderRow.WorkingOrderRow;
                workingOrderRow.AcquireReaderLock(dataModelTransaction);

                // Now aggregate the source order quantities and the destination order quantities.  Throw an exception if the source orders are less than the
                // destination orders (we can't have less quantity ordered than we've placed with brokers and exchanges).
                Decimal sourceOrderQuantity      = WorkingOrderService.GetSourceOrderQuantity(dataModelTransaction, workingOrderRow);
                Decimal destinationOrderQuantity = WorkingOrderService.GetDestinationOrderQuantity(dataModelTransaction, workingOrderRow);
                if (sourceOrderQuantity < destinationOrderQuantity)
                {
                    throw new FaultException <DestinationQuantityFault>(
                              new DestinationQuantityFault(workingOrderRow.WorkingOrderId, sourceOrderQuantity, destinationOrderQuantity));
                }
            }
        }
示例#5
0
        /// <summary>
        /// Handler for validating Destination Order records.
        /// </summary>
        /// <param name="sender">The object that originated the event.</param>
        /// <param name="e">The event arguments.</param>
        static void OnDestinationOrderAdd(DataModel.DestinationOrderRow destinationOrderRow)
        {
            // A transaction is needed to handle the change.
            DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction;

            DataModel.WorkingOrderRow workingOrderRow = destinationOrderRow.WorkingOrderRow;
            workingOrderRow.AcquireReaderLock(dataModelTransaction);

            Decimal sourceOrderQuantity      = WorkingOrderService.GetSourceOrderQuantity(dataModelTransaction, workingOrderRow);
            Decimal destinationOrderQuantity = WorkingOrderService.GetDestinationOrderQuantity(dataModelTransaction, workingOrderRow);

            if (sourceOrderQuantity < destinationOrderQuantity)
            {
                throw new FaultException <DestinationQuantityFault>(
                          new DestinationQuantityFault(workingOrderRow.WorkingOrderId, sourceOrderQuantity, destinationOrderQuantity));
            }
        }
示例#6
0
        /// <summary>
        /// Handles a change to a error state.
        /// </summary>
        /// <param name="workingOrderRow">The parent working order.</param>
        static void OnClearErrorAction(DataModel.WorkingOrderRow workingOrderRow)
        {
            // A transaction is needed to handle the change.
            DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction;

            // This will lock the WorkingOrderRow while we examine it.
            workingOrderRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
            dataModelTransaction.AddLock(workingOrderRow);
            if (workingOrderRow.RowState == DataRowState.Detached)
            {
                return;
            }

            // The error status is cleared only when none of the sibling destination orders has an error.
            Boolean isErrorStatus = false;

            foreach (DataModel.DestinationOrderRow siblingOrderRow in workingOrderRow.GetDestinationOrderRows())
            {
                siblingOrderRow.AcquireReaderLock(dataModelTransaction);
                if (siblingOrderRow.StatusCode == StatusCode.Error)
                {
                    isErrorStatus = true;
                    break;
                }
            }

            // If none of the siblings has an error, the we're going to set the working order's status to what it was before the error occurred.
            if (!isErrorStatus)
            {
                Decimal quantityExecuted = WorkingOrderService.GetExecutionQuantity(dataModelTransaction, workingOrderRow);
                Decimal quantityOrdered  = WorkingOrderService.GetSourceOrderQuantity(dataModelTransaction, workingOrderRow);
                if (quantityExecuted == 0.0M && workingOrderRow.StatusCode != StatusCode.New)
                {
                    WorkingOrderService.UpdateWorkingOrderStatus(workingOrderRow, StatusCode.New);
                }
                if (0.0M < quantityExecuted && quantityExecuted < quantityOrdered && workingOrderRow.StatusCode != StatusCode.PartiallyFilled)
                {
                    WorkingOrderService.UpdateWorkingOrderStatus(workingOrderRow, StatusCode.PartiallyFilled);
                }
                if (quantityExecuted == quantityOrdered && workingOrderRow.StatusCode != StatusCode.Filled)
                {
                    WorkingOrderService.UpdateWorkingOrderStatus(workingOrderRow, StatusCode.Filled);
                }
            }
        }
示例#7
0
        /// <summary>
        /// Handles a change to a error state.
        /// </summary>
        /// <param name="workingOrderRow">The parent working order.</param>
        static void OnSetErrorAction(DataModel.WorkingOrderRow workingOrderRow)
        {
            // A transaction is needed to handle the change.
            DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction;

            // This will lock the WorkingOrderRow while we examine it.
            workingOrderRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
            dataModelTransaction.AddLock(workingOrderRow);
            if (workingOrderRow.RowState == DataRowState.Detached)
            {
                return;
            }

            // This logic is simple enough, set to an error state if we're not already there.
            if (workingOrderRow.StatusCode != StatusCode.Error)
            {
                WorkingOrderService.UpdateWorkingOrderStatus(workingOrderRow, StatusCode.Error);
            }
        }
示例#8
0
        /// <summary>
        /// Handles a change to a partially executed state.
        /// </summary>
        /// <param name="workingOrderRow">The parent working order.</param>
        static void OnPartialAction(DataModel.WorkingOrderRow workingOrderRow)
        {
            // A transaction is needed to handle the change.
            DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction;

            // This will lock the WorkingOrderRow while we examine it.
            workingOrderRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
            dataModelTransaction.AddLock(workingOrderRow);
            if (workingOrderRow.RowState == DataRowState.Detached)
            {
                return;
            }

            // The working order is considered partially filled if any of its destination orders are partially filled.  The only exception to this is when the
            // working order is in an error state.
            if (workingOrderRow.StatusCode != StatusCode.Error && workingOrderRow.StatusCode != StatusCode.PartiallyFilled)
            {
                WorkingOrderService.UpdateWorkingOrderStatus(workingOrderRow, StatusCode.PartiallyFilled);
            }
        }
示例#9
0
        /// <summary>
        /// Handler for validating Destination Order records.
        /// </summary>
        /// <param name="sender">The object that originated the event.</param>
        /// <param name="e">The event arguments.</param>
        static void OnDestinationOrderChange(DataModel.DestinationOrderRow destinationOrderRow)
        {
            // A transaction is needed to handle the change.
            DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction;

            // If the quantity has changed then we need to make sure that the quantity sent to a destination (broker, exchange, etc.) is not less than the amount
            // ordered.  That is, we can't accept a change that leaves us overcommited with a destination.
            Decimal originalQuantity = (Decimal)destinationOrderRow[DataModel.DestinationOrder.OrderedQuantityColumn, DataRowVersion.Original];
            Decimal currentQuantity  = (Decimal)destinationOrderRow[DataModel.DestinationOrder.OrderedQuantityColumn, DataRowVersion.Current];

            if (originalQuantity < currentQuantity)
            {
                // We need to aggregate at the working order, so we need to lock the working order while we do our sums.
                DataModel.WorkingOrderRow workingOrderRow = destinationOrderRow.WorkingOrderRow;
                workingOrderRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                dataModelTransaction.AddLock(workingOrderRow);

                // This will aggregate the source and destination orders and throw an exception if this transaction would leave us overcommitted with the
                // destination.
                Decimal sourceOrderQuantity      = WorkingOrderService.GetSourceOrderQuantity(dataModelTransaction, workingOrderRow);
                Decimal destinationOrderQuantity = WorkingOrderService.GetDestinationOrderQuantity(dataModelTransaction, workingOrderRow);
                if (sourceOrderQuantity < destinationOrderQuantity)
                {
                    throw new FaultException <DestinationQuantityFault>(
                              new DestinationQuantityFault(workingOrderRow.WorkingOrderId, sourceOrderQuantity, destinationOrderQuantity));
                }
            }

            // If the StatusCode of the destination order has changed then find the right handler for the state change and go execute the business logic for this
            // change.  The 'statusChangeMap' is a two dimensional Dictionary (hash table) using the previous and current states to find the right handler.
            StatusCode previousStatusCode = (StatusCode)destinationOrderRow[DataModel.DestinationOrder.StatusCodeColumn, DataRowVersion.Original];
            StatusCode currentStatusCode  = destinationOrderRow.StatusCode;

            if (previousStatusCode != currentStatusCode)
            {
                statusChangeMap[previousStatusCode][currentStatusCode](destinationOrderRow.WorkingOrderRow);
            }
        }