예제 #1
0
 /// <summary>
 /// Updates the status of the Working Order.
 /// </summary>
 /// <param name="workingOrderRow">The Working Order to be modified.</param>
 /// <param name="status">The new status of the Working Order.</param>
 private static void UpdateWorkingOrderStatus(WorkingOrderRow workingOrderRow, Status status)
 {
     // It is a good idea to have a central method for updating the Working Order in the event the parameter order changes.
     WorkingOrder.dataModel.UpdateWorkingOrder(null, null, null, null, null, null, null, null, null, null, null, null,
                                               null, null, null, null, workingOrderRow.RowVersion, null, null, null, null, null, StatusMap.FromCode(status), null, null, null,
                                               null, null, null, null, null, new object[] { workingOrderRow.WorkingOrderId });
 }
예제 #2
0
        /// <summary>
        /// Handles a Destination Order entering the error state.
        /// </summary>
        private static void SetErrorAction(Object[] key, params Object[] parameters)
        {
            // A middle tier context is also required for a transacted update.
            DataModelTransaction dataModelTransaction = DataModelTransaction.Current;

            // It is possible that the Working Order that is the object of this status update operation may have been deleted since the action was
            // created.  This is not an error condition.  If there is no Working Order to update, then the operation is just terminated prematurely.
            WorkingOrderRow workingOrderRow = DataModel.WorkingOrder.WorkingOrderKey.Find(key);

            if (workingOrderRow == null)
            {
                return;
            }
            workingOrderRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
            dataModelTransaction.AddLock(workingOrderRow);
            if (workingOrderRow.RowState == DataRowState.Detached)
            {
                return;
            }

            // The Working Order reflects an 'Error' Status if any of its Destination Orders have an error.
            if (workingOrderRow.StatusId != StatusMap.FromCode(Status.Error))
            {
                UpdateWorkingOrderStatus(workingOrderRow, Status.Error);
            }
        }
예제 #3
0
        /// <summary>
        /// Changes the state of the Working Order to reflect a filledly filled state.
        /// </summary>
        private static void OnFilledAction(Object[] key, params Object[] parameters)
        {
            // A middle tier context is also required for a transacted update.
            DataModelTransaction dataModelTransaction = DataModelTransaction.Current;

            // It is possible that the Working Order that is the object of this status update operation may have been deleted since the action was
            // created.  This is not an error condition.  If there is no Working Order to update, then the operation is just terminated prematurely.
            WorkingOrderRow workingOrderRow = DataModel.WorkingOrder.WorkingOrderKey.Find(key);

            if (workingOrderRow == null)
            {
                return;
            }
            workingOrderRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
            dataModelTransaction.AddLock(workingOrderRow);
            if (workingOrderRow.RowState == DataRowState.Detached)
            {
                return;
            }

            // The error status on a Working Order cannot be cleared with a fill.
            if (workingOrderRow.StatusId != StatusMap.FromCode(Status.Error))
            {
                // The Working Order is 'Filled' when the quantity executed is the same as the quantity ordered.
                Decimal quantityOrdered  = WorkingOrder.GetSourceOrderQuantity(dataModelTransaction, workingOrderRow);
                Decimal quantityExecuted = WorkingOrder.GetExecutionQuantity(dataModelTransaction, workingOrderRow);
                if (quantityOrdered == quantityExecuted)
                {
                    UpdateWorkingOrderStatus(workingOrderRow, Status.Filled);
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Changes the state of the Working Order to reflect a partially filled status.
        /// </summary>
        private static void OnPartialAction(Object[] key, params Object[] parameters)
        {
            // A middle tier context is also required for a transacted update.
            DataModelTransaction dataModelTransaction = DataModelTransaction.Current;

            // It is possible that the Working Order that is the object of this status update operation may have been deleted since the action was
            // created.  This is not an error condition.  If there is no Working Order to update, then the operation is just terminated prematurely.
            WorkingOrderRow workingOrderRow = DataModel.WorkingOrder.WorkingOrderKey.Find(key);

            if (workingOrderRow == null)
            {
                return;
            }
            workingOrderRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
            dataModelTransaction.AddLock(workingOrderRow);
            if (workingOrderRow.RowState == DataRowState.Detached)
            {
                return;
            }

            // The error status on a Working Order cannot be cleared with a partial fill.  Otherwise, a partial fill on any of the Destination Orders is
            // reflected in the status of the parent Working Order.
            if (workingOrderRow.StatusId != StatusMap.FromCode(Status.Error))
            {
                if (workingOrderRow.StatusId != StatusMap.FromCode(Status.PartiallyFilled))
                {
                    UpdateWorkingOrderStatus(workingOrderRow, Status.PartiallyFilled);
                }
            }
        }
예제 #5
0
        /// <summary>
        /// Changes the state of the Working Order to reflect a filledly filled state.
        /// </summary>
        private static void ClearErrorAction(Object[] key, params Object[] parameters)
        {
            // A middle tier context is also required for a transacted update.
            DataModelTransaction dataModelTransaction = DataModelTransaction.Current;

            // It is possible that the Working Order that is the object of this status update operation may have been deleted since the action was
            // created.  This is not an error condition.  If there is no Working Order to update, then the operation is just terminated prematurely.
            WorkingOrderRow workingOrderRow = DataModel.WorkingOrder.WorkingOrderKey.Find(key);

            if (workingOrderRow == null)
            {
                return;
            }
            workingOrderRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
            dataModelTransaction.AddLock(workingOrderRow);
            if (workingOrderRow.RowState == DataRowState.Detached)
            {
                return;
            }

            // The 'Error' status is only cleared when all the Destination Orders are valid.
            Boolean isErrorStatus = false;

            foreach (DestinationOrderRow siblingOrderRow in workingOrderRow.GetDestinationOrderRows())
            {
                siblingOrderRow.AcquireReaderLock(dataModelTransaction);
                if (siblingOrderRow.StatusId == StatusMap.FromCode(Status.Error))
                {
                    isErrorStatus = true;
                    break;
                }
            }

            // The proper Working Order status must be evaluated when the error status is cleared.
            if (!isErrorStatus)
            {
                // The aggregates will determine the new state of the Working Order.
                Decimal quantityExecuted = WorkingOrder.GetExecutionQuantity(dataModelTransaction, workingOrderRow);
                Decimal quantityOrdered  = WorkingOrder.GetSourceOrderQuantity(dataModelTransaction, workingOrderRow);

                // This restores the 'New' status when the canceled Destination Order was the only order with any fills.
                if (quantityExecuted == 0.0M && workingOrderRow.StatusId != StatusMap.FromCode(Status.New))
                {
                    UpdateWorkingOrderStatus(workingOrderRow, Status.New);
                }

                // This restores the 'Partially Filled' status when other executions remain.
                if (0.0M < quantityExecuted && quantityExecuted < quantityOrdered && workingOrderRow.StatusId != StatusMap.FromCode(Status.PartiallyFilled))
                {
                    UpdateWorkingOrderStatus(workingOrderRow, Status.PartiallyFilled);
                }

                // This restores the 'Filled' status when the quantity executed is the same as the quantity ordered.
                if (quantityExecuted == quantityOrdered && workingOrderRow.StatusId != StatusMap.FromCode(Status.Filled))
                {
                    UpdateWorkingOrderStatus(workingOrderRow, Status.Filled);
                }
            }
        }
예제 #6
0
        /// <summary>
        /// Find the blotter than contains this credit card.
        /// </summary>
        /// <param name="transaction">The transaction object.</param>
        /// <param name="creditCardId">The credit card id.</param>
        /// <returns>The blotter id of the blotter that contains this credit card.</returns>
        private Guid FindContainingBlotter(DataModelTransaction transaction, Guid creditCardId)
        {
            WorkingOrderRow workingOrderRow = this.FindWorkingOrder(transaction, creditCardId);

            workingOrderRow.AcquireReaderLock(transaction);
            Guid blotterId = workingOrderRow.BlotterId;

            workingOrderRow.ReleaseLock(transaction.TransactionId);

            return(blotterId);
        }
        /// <summary>
        /// Update working order time.
        /// </summary>
        /// <param name="workingOrderId"></param>
        public void UpdateModifyTime(Guid workingOrderId)
        {
            WorkingOrderRow workingOrderRow = DataModel.WorkingOrder.WorkingOrderKey.Find(workingOrderId);

            if (workingOrderRow != null && workingOrderRow.RowState != DataRowState.Detached)
            {
                workingOrderRow.AcquireReaderLock(DataModelTransaction.Current);
                this.Update(new WorkingOrderRecord()
                {
                    RowId = workingOrderRow.WorkingOrderId, RowVersion = workingOrderRow.RowVersion, BlotterId = workingOrderRow.BlotterId
                });
            }
        }
        /// <summary>
        /// Delete a working order row.
        /// </summary>
        /// <param name="record">The working order record to delete.</param>
        /// <returns>Error code of any failure, or Success.</returns>
        public override ErrorCode Delete(WorkingOrderRecord record)
        {
            DataModel            dataModel       = new DataModel();
            DataModelTransaction transaction     = DataModelTransaction.Current;
            WorkingOrderRow      workingOrderRow = DataModel.WorkingOrder.WorkingOrderKey.Find((Guid)record.RowId);

            if (workingOrderRow == null)
            {
                return(ErrorCode.RecordNotFound);
            }

            return(DeleteRow(dataModel, transaction, workingOrderRow));
        }
예제 #9
0
        /// <summary>
        /// Event handler for a match.
        /// </summary>
        /// <param name="sender">The object that originated the event.</param>
        /// <param name="e">The event arguments.</param>
        private void OnMatchRowChanged(Object sender, MatchRowChangeEventArgs e)
        {
            // When a new, pending match record has been added to the data mode, start a thread that will
            // display the notification window.
            if (e.Action == DataRowAction.Commit && e.Row.RowState != DataRowState.Detached)
            {
                if (e.Row.StatusRow.StatusCode == Status.Active ||
                    e.Row.StatusRow.StatusCode == Status.PartialMatch ||
                    e.Row.StatusRow.StatusCode == Status.ValidMatch ||
                    e.Row.StatusRow.StatusCode == Status.ValidMatchFunds ||
                    e.Row.StatusRow.StatusCode == Status.Declined)
                {
                    NotificationInfo notificationInfo = new NotificationInfo();

                    // The match record, working order, order type and security records are used to construct the title, symbol and
                    // logo used by the notification window.
                    MatchRow        matchRow        = e.Row;
                    WorkingOrderRow workingOrderRow = matchRow.WorkingOrderRow;
                    OrderTypeRow    orderTypeRow    = workingOrderRow.OrderTypeRow;
                    SecurityRow     securityRow     = workingOrderRow.SecurityRowByFK_Security_WorkingOrder_SecurityId;

                    // This is the primary method of identifying a match between two working orders.
                    notificationInfo.MatchId = matchRow.MatchId;

                    // The current status of the match is used to tell whether we're coming or going.
                    notificationInfo.Status = matchRow.StatusRow.StatusCode;

                    // Get the security symbol.
                    notificationInfo.Symbol = securityRow.Symbol;

                    // Create a logo bitmap.
                    notificationInfo.Logo = securityRow.IsLogoNull() ? String.Empty : securityRow.Logo;

                    // Provide a handler for the notification.
                    if (!securityRow.EntityRow.TypeRow.IsNotifyingTypeNull())
                    {
                        notificationInfo.NotifierType = securityRow.EntityRow.TypeRow.NotifyingType;

                        // Construct the title for the notification window.
                        notificationInfo.Message = String.Format("{0} of {1}", workingOrderRow.SideRow.Description, securityRow.Symbol);

                        // Now that the information has been extracted for the data model, the background execution queue can handle the rest of the
                        // notification of the user.
                        this.OnNotification(notificationInfo);
                    }
                }
            }
        }
예제 #10
0
        /// <summary>
        /// update the order modify time, but dont save it. this will be used as a message to
        /// re-process the order
        /// </summary>
        /// <param name="utcModTime"></param>
        /// <param name="workingOrderId"></param>
        private static void UpdateOrderModifyTime(DateTime utcModTime, Guid workingOrderId)
        {
            using (TransactionScope transactionScope = new TransactionScope())
            {
                // This provides a context for any transactions.
                DataModelTransaction dataModelTransaction = DataModelTransaction.Current;
                WorkingOrderRow      workingOrderRow      = DataModel.WorkingOrder.WorkingOrderKey.Find(workingOrderId);
                if (workingOrderRow == null)
                {
                    return;
                }

                DataModel dataModel = new DataModel();
                workingOrderRow.AcquireWriterLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                try
                {
                    if (workingOrderRow.RowState == System.Data.DataRowState.Deleted ||
                        workingOrderRow.RowState == System.Data.DataRowState.Detached)
                    {
                        return;
                    }

                    DataModel.DataLock.EnterWriteLock();
                    try
                    {
                        workingOrderRow.BeginEdit();
                        workingOrderRow[DataModel.WorkingOrder.ModifiedTimeColumn] = utcModTime;
                    }
                    finally
                    {
                        workingOrderRow.EndEdit();
                        workingOrderRow.RejectChanges();
                        DataModel.DataLock.ExitWriteLock();
                    }
                }
                finally
                {
                    workingOrderRow.ReleaseWriterLock(dataModelTransaction.TransactionId);
                }
            }
        }
예제 #11
0
        /// <summary>
        /// The sum total of the quantities of all the source orders in a given working order.
        /// </summary>
        /// <param name="dataModelTransaction"></param>
        /// <param name="workingOrderRow">A working order row.</param>
        /// <returns>The total quantity of all the source orders associated with the working order.</returns>
        internal static Decimal GetSourceOrderQuantity(DataModelTransaction dataModelTransaction, WorkingOrderRow workingOrderRow)
        {
            // This will aggregate all the source order quantities.  Note that the rows are kept locked for the duration of the transaction.  This guarantees
            // the integrity of the aggregate values.
            Decimal sourceOrderQuantity = 0.0m;

            foreach (SourceOrderRow sourceOrderRow in workingOrderRow.GetSourceOrderRows())
            {
                try
                {
                    sourceOrderRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                    sourceOrderQuantity += sourceOrderRow.OrderedQuantity;
                }
                finally
                {
                    sourceOrderRow.ReleaseLock(dataModelTransaction.TransactionId);
                }
            }

            // This is the sum total of all the source orders in the given working order.
            return(sourceOrderQuantity);
        }
예제 #12
0
        /// <summary>
        /// The sum total of the quantities of all the destination orders in a given working order.
        /// </summary>
        /// <param name="dataModelTransaction"></param>
        /// <param name="workingOrderRow">A working order row.</param>
        /// <returns>The total quantity of all the destination orders associated with the working order.</returns>
        internal static Decimal GetExecutionQuantity(DataModelTransaction dataModelTransaction, WorkingOrderRow workingOrderRow)
        {
            // This will aggregate all the execution quantities.  Note that the records are locked for the duration of the transaction to insure the integrity
            // of the aggregates.
            Decimal executionQuantity = 0.0m;

            foreach (DestinationOrderRow destinationOrderRow in workingOrderRow.GetDestinationOrderRows())
            {
                destinationOrderRow.AcquireReaderLock(dataModelTransaction);
                if (destinationOrderRow.StatusId != StatusMap.FromCode(Status.Canceled))
                {
                    foreach (ExecutionRow executionRow in destinationOrderRow.GetExecutionRows())
                    {
                        executionRow.AcquireReaderLock(dataModelTransaction);
                        executionQuantity += executionRow.ExecutionQuantity;
                    }
                }
            }

            // This is the aggregate quantity executed for the given working order.
            return(executionQuantity);
        }
예제 #13
0
        /// <summary>
        /// The sum total of the quantities of all the destination orders in a given working order.
        /// </summary>
        /// <param name="dataModelTransaction"></param>
        /// <param name="workingOrderRow">A working order row.</param>
        /// <returns>The total quantity of all the destination orders associated with the working order.</returns>
        internal static Decimal GetDestinationOrderQuantity(DataModelTransaction dataModelTransaction, WorkingOrderRow workingOrderRow)
        {
            // This is the accumulator for the quantity held in the destination orders.
            Decimal destinationOrderQuantity = 0.0m;

            // This will aggregate all the destination order quantities.  The tables must be locked in succession as they are
            // read from the table.
            foreach (DestinationOrderRow destinationOrderRow in workingOrderRow.GetDestinationOrderRows())
            {
                destinationOrderRow.AcquireReaderLock(dataModelTransaction);
                destinationOrderQuantity += destinationOrderRow.OrderedQuantity;
            }

            // This is the sum total of all the destination orders in the given working order.
            return(destinationOrderQuantity);
        }