/// <summary> /// Handles a change to a DestinationOrder row. /// </summary> /// <param name="sender">The Object that originated the event.</param> /// <param name="destinationOrderRowChangeEventArgs">The event arguments.</param> protected virtual void OnDestinationOrderRowChanged(Object sender, DataModel.DestinationOrderRowChangeEventArgs destinationOrderRowChangeEventArgs) { // Validate the parameters. if (sender == null) { throw new ArgumentNullException("sender"); } if (destinationOrderRowChangeEventArgs == null) { throw new ArgumentNullException("destinationOrderRowChangeEventArgs"); } // We're only interested in additions and changes that affect the WorkingOrder records in this blotter. if (destinationOrderRowChangeEventArgs.Action == DataRowAction.Add || destinationOrderRowChangeEventArgs.Action == DataRowAction.Change) { DataModel.WorkingOrderRow workingOrderRow = destinationOrderRowChangeEventArgs.Row.WorkingOrderRow; if (this.blotterIdSet.Contains(workingOrderRow.BlotterId)) { Int32 index = this.BinarySearch(order => order.WorkingOrderId, workingOrderRow.WorkingOrderId); if (index >= 0) { this.UpdateDestinationOrderQuantity(this[index], workingOrderRow); } } } }
/// <summary> /// Handles the deletion of a DestinationOrder row. /// </summary> /// <param name="sender">The object that originated the event.</param> /// <param name="destinationOrderRowChangeEventArgs">The event arguments.</param> protected virtual void OnDestinationOrderRowDeleted(Object sender, DataModel.DestinationOrderRowChangeEventArgs destinationOrderRowChangeEventArgs) { // Validate the parameters. if (sender == null) { throw new ArgumentNullException("sender"); } if (destinationOrderRowChangeEventArgs == null) { throw new ArgumentNullException("destinationOrderRowChangeEventArgs"); } // We're only interested in deletes that affect the WorkingOrder records in this blotter. if (destinationOrderRowChangeEventArgs.Action == DataRowAction.Delete) { Guid workingOrderId = (Guid)destinationOrderRowChangeEventArgs.Row[DataModel.DestinationOrder.WorkingOrderIdColumn, DataRowVersion.Original]; DataModel.WorkingOrderRow workingOrderRow = DataModel.WorkingOrder.WorkingOrderKey.Find(workingOrderId); if (workingOrderRow != null && this.blotterIdSet.Contains(workingOrderRow.BlotterId)) { Int32 index = this.BinarySearch(order => order.WorkingOrderId, workingOrderRow.WorkingOrderId); if (index >= 0) { this.UpdateDestinationOrderQuantity(this[index], workingOrderRow); } } } }
/// <summary> /// Handles a change to the DestinationOrder table. /// </summary> /// <param name="sender">The object that originated the event.</param> /// <param name="e">The event data.</param> static void OnDestinationOrderRowChanging(object sender, DataModel.DestinationOrderRowChangeEventArgs e) { // This will pump the committed destination orders into the simulation. if (e.Action == DataRowAction.Commit && e.Row.RowState == DataRowState.Added) { MarketSimulator.orderQueue.Enqueue(e.Row); } }
/// <summary> /// Handles a change to the DestinationOrder table. /// </summary> /// <param name="sender">The object that originated the event.</param> /// <param name="e">The event data.</param> static void OnDestinationOrderRowChanged(object sender, DataModel.DestinationOrderRowChangeEventArgs e) { // This will turn new DestinationOrder records into orders that can be sent to a destination for execution. if (e.Action == DataRowAction.Add) { // The current transaction is going to be needed to lock records. DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction; // Create a new message for the order we're going to build from the DestinationOrder. Message message = new Message(); // The market execution engine will need to know the source firm so it knows how to route the order back. OrganizationPrincipal organizationPrincipal = Thread.CurrentPrincipal as OrganizationPrincipal; message.SenderCompID = organizationPrincipal.Organization; // Copy the basic properties of the DestinationOrder into the message. DataModel.DestinationOrderRow destinationOrderRow = e.Row; message.ClOrdID = destinationOrderRow.DestinationOrderId.ToString(); message.OrderQty = destinationOrderRow.OrderedQuantity; message.OrdType = destinationOrderRow.OrderTypeCode; message.SideCode = destinationOrderRow.SideCode; message.TimeInForceCode = destinationOrderRow.TimeInForceCode; // Get the symbol to use as a security identifier. DataModel.SecurityRow securityRow = destinationOrderRow.SecurityRowByFK_Security_DestinationOrder_SecurityId; securityRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout); dataModelTransaction.AddLock(securityRow); if (securityRow.RowState == DataRowState.Detached) { throw new FaultException <RecordNotFoundFault>(new RecordNotFoundFault("Security", new Object[] { destinationOrderRow.SecurityId })); } message.Symbol = securityRow.Symbol; // This will put the new order in a queue. The DestinatonThread will pull it out, batch it up and send it to the destination to be executed. lock (MarketEngine.syncRoot) { MarketEngine.messageQueue.Enqueue(message); if (messageQueue.Count == 1) { MarketEngine.orderEvent.Set(); } } } }
/// <summary> /// Handles the deletion of a DestinationOrder row. /// </summary> /// <param name="sender">The object that originated the event.</param> /// <param name="destinationOrderRowChangeEventArgs">The event arguments.</param> void OnDestinationOrderRowDeleted(Object sender, DataModel.DestinationOrderRowChangeEventArgs destinationOrderRowChangeEventArgs) { // We're only interested in deletes that affect the WorkingOrder records in this blotter. if (destinationOrderRowChangeEventArgs.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 working order to // which it belonged. We don't need to check for the existence of the working order as we know that this order was just deleted and, for it to have // existed in the first place, there must have been a working order. DataModel.DestinationOrderRow destinationOrderRow = destinationOrderRowChangeEventArgs.Row; Guid workingOrderId = (Guid)destinationOrderRow[DataModel.DestinationOrder.WorkingOrderIdColumn, DataRowVersion.Original]; DataModel.WorkingOrderRow workingOrderRow = DataModel.WorkingOrder.WorkingOrderKey.Find(workingOrderId); if (this.blotterIdSet.Contains(workingOrderRow.BlotterId)) { // Once the quantity has been removed from the totals, the percent ordered and executed can be updated. this.DestinationOrderQuantity -= (Decimal)destinationOrderRow[DataModel.DestinationOrder.OrderedQuantityColumn, DataRowVersion.Original] - (Decimal)destinationOrderRow[DataModel.DestinationOrder.CanceledQuantityColumn, DataRowVersion.Original]; this.OrderedPercent = this.SourceOrderQuantity == 0.0m ? 0.0 : Convert.ToDouble(this.DestinationOrderQuantity / this.SourceOrderQuantity); this.ExecutedPercent = this.DestinationOrderQuantity == 0.0m ? 0.0 : Convert.ToDouble(this.ExecutionQuantity / this.DestinationOrderQuantity); } } }
/// <summary> /// Handles a change to a DestinationOrder row. /// </summary> /// <param name="sender">The Object that originated the event.</param> /// <param name="destinationOrderRowChangeEventArgs">The event arguments.</param> void OnDestinationOrderRowChanged(Object sender, DataModel.DestinationOrderRowChangeEventArgs destinationOrderRowChangeEventArgs) { // We're only interested in additions and changes that affect the WorkingOrder records in this blotter. if (destinationOrderRowChangeEventArgs.Action == DataRowAction.Add || destinationOrderRowChangeEventArgs.Action == DataRowAction.Change) { // This is designed to filter out all events that don't pertain to this blotter. DataModel.DestinationOrderRow destinationOrderRow = destinationOrderRowChangeEventArgs.Row; if (this.blotterIdSet.Contains(destinationOrderRow.WorkingOrderRow.BlotterId)) { // Once the previous order is subtracted and the current order added to the totals we can calculate the percentages of orders completed and // executed. if (destinationOrderRow.HasVersion(DataRowVersion.Original)) { this.destinationOrderQuantityField -= (Decimal)destinationOrderRow[DataModel.DestinationOrder.OrderedQuantityColumn, DataRowVersion.Original] - (Decimal)destinationOrderRow[DataModel.DestinationOrder.CanceledQuantityColumn, DataRowVersion.Original]; } this.DestinationOrderQuantity += destinationOrderRow.OrderedQuantity - destinationOrderRow.CanceledQuantity; this.OrderedPercent = this.SourceOrderQuantity == 0.0m ? 0.0 : Convert.ToDouble(this.DestinationOrderQuantity / this.SourceOrderQuantity); this.ExecutedPercent = this.DestinationOrderQuantity == 0.0m ? 0.0 : Convert.ToDouble(this.ExecutionQuantity / this.DestinationOrderQuantity); } } }
/// <summary> /// Validates a change to a Source Order. /// </summary> /// <param name="sender">The object that originated the event.</param> /// <param name="e">The event data.</param> internal static void OnDestinationOrderRowValidate(object sender, DataModel.DestinationOrderRowChangeEventArgs e) { // Use the map to call the handler for the action. Note that I would rather do nothing than incur conditional logic. DestinationOrderService.destinationOrderHandlerMap[e.Action](e.Row); }