internal static void Decline(Guid matchId) { Guid negotiationId = Guid.Empty; long rowVersion = long.MinValue; DataModel dataModel = new DataModel(); try { DataModel.DataLock.EnterReadLock(); // This context is used to keep track of the locks aquired for the ancillary data. TransactionScope transactionScope = new TransactionScope(); DataModelTransaction dataModelTransaction = DataModelTransaction.Current; MatchRow matchRow = DataModel.Match.MatchKey.Find(matchId); if (matchRow != null) { WorkingOrderRow workingOrderRow = matchRow.WorkingOrderRow; // See if there is already a pending offer. bool isFound = false; foreach (NegotiationRow innerNegotiationRow in matchRow.GetNegotiationRows()) { if (innerNegotiationRow.StatusId == StatusMap.FromCode(Status.Declined)) { throw new Exception("This offer has previously been declined."); } if (innerNegotiationRow.StatusId == StatusMap.FromCode(Status.Pending)) { // Call the internal method to complete the operation. rowVersion = innerNegotiationRow.RowVersion; negotiationId = innerNegotiationRow.NegotiationId; dataModel.UpdateNegotiation( null, null, false, null, null, new Object[] { negotiationId }, null, rowVersion, StatusMap.FromCode(Status.Declined)); isFound = true; } } // Call the internal method to complete the operation. if (!isFound) { negotiationId = Guid.NewGuid(); dataModel.CreateNegotiation(workingOrderRow.BlotterId, null, false, matchId, negotiationId, 0.0m, StatusMap.FromCode(Status.Declined)); } // If there's a counter offer, then notify the couter part that the offer has been declined. This will find the contra matching record. MatchRow contraMatchRow = DataModel.Match.MatchKeyWorkingOrderIdContraOrderId.Find( new object[] { matchRow.ContraOrderId, matchRow.WorkingOrderId }); if (contraMatchRow == null) { throw new Exception(string.Format("Corruption: the match record for {0}, {1} can't be found", matchRow.ContraOrderId, matchRow.WorkingOrderId)); } // When both sides have agreed to the Negotiation, the Destination Orders are generated. foreach (NegotiationRow contraNegotiationRow in contraMatchRow.GetNegotiationRows()) { if (contraNegotiationRow.StatusId == StatusMap.FromCode(Status.Pending)) { dataModel.UpdateNegotiation( null, null, false, null, null, new Object[] { contraNegotiationRow.NegotiationId }, null, contraNegotiationRow.RowVersion, StatusMap.FromCode(Status.Declined)); } } } } finally { // Release the tables. DataModel.DataLock.ExitReadLock(); } }
/// <summary>Inserts a Negotiation record using Metadata Parameters.</summary> internal static void Offer(Guid matchId, Decimal quantity) { Guid negotiationId = Guid.Empty; DataModel dataModel = new DataModel(); try { DataModel.DataLock.EnterReadLock(); MatchRow matchRow = DataModel.Match.MatchKey.Find(matchId); if (matchRow != null) { // Rule #1: Insure that there are no pending offers. foreach (NegotiationRow innerNegotiationRow in matchRow.GetNegotiationRows()) { if (innerNegotiationRow.StatusId == StatusMap.FromCode(Status.Pending)) { throw new Exception("There is already an offer pending."); } if (innerNegotiationRow.StatusId == StatusMap.FromCode(Status.Declined)) { throw new Exception("This offer has previously been declined."); } } // Time stamps and user stamps Guid createdUserId = TradingSupport.UserId; DateTime createdTime = DateTime.UtcNow; Guid modifiedUserId = TradingSupport.UserId; DateTime modifiedTime = createdTime; // This will find the contra matching record. MatchRow contraMatchRow = DataModel.Match.MatchKeyWorkingOrderIdContraOrderId.Find( new Object[] { matchRow.ContraOrderId, matchRow.WorkingOrderId }); if (contraMatchRow == null) { throw new Exception( string.Format("Corruption: the match record for {0}, {1} can't be found", matchRow.ContraOrderId, matchRow.WorkingOrderId)); } // This is the order on the other side of the match. WorkingOrderRow contraWorkingOrderRow = contraMatchRow.WorkingOrderRow; // When both sides have agreed to the Negotiation, the Destination Orders are generated. NegotiationRow contraNegotiationRow = null; foreach (NegotiationRow innerNegotiationRow in contraMatchRow.GetNegotiationRows()) { if (innerNegotiationRow.StatusId == StatusMap.FromCode(Status.Pending)) { contraNegotiationRow = innerNegotiationRow; break; } } // This means that there's an offer on the other side. if (contraNegotiationRow == null) { // There is no opposite side of this transaction yet. It will be placed in the negotation table and wait there // until it times out, or the other side accepts the offer. negotiationId = Guid.NewGuid(); dataModel.CreateNegotiation( contraWorkingOrderRow.BlotterId, null, false, contraMatchRow.MatchId, negotiationId, quantity, StatusMap.FromCode(Status.Pending)); } else { // At this point, there is an offer on both sides of the match for a follow-on order. We'll create orders and // executions for both sides of the trade for the minimum agreed upon quantity. WorkingOrderRow workingOrderRow = matchRow.WorkingOrderRow; WorkingOrderRow contraOrderRow = contraNegotiationRow.MatchRow.WorkingOrderRow; // The quantity of this negotiation will be the minimum of the two offers. decimal matchedQuantity = quantity < contraNegotiationRow.Quantity ? quantity : contraNegotiationRow.Quantity; // Create the order on this side of the trade. Guid destinationOrderId = Guid.NewGuid(); dataModel.CreateDestinationOrder( workingOrderRow.BlotterId, null, null, createdTime, createdUserId, destinationId, destinationOrderId, null, null, null, null, workingOrderRow[DataModel.WorkingOrder.LimitPriceColumn], modifiedTime, modifiedUserId, matchedQuantity, workingOrderRow.OrderTypeId, workingOrderRow.SecurityId, modifiedTime, workingOrderRow.SettlementId, workingOrderRow.SideId, StateMap.FromCode(State.Acknowledged), StatusMap.FromCode(Status.New), workingOrderRow[DataModel.WorkingOrder.StopPriceColumn], workingOrderRow.TimeInForceId, modifiedTime, null, workingOrderRow.WorkingOrderId); // The the trade is executed at the current price. PriceRow priceRow = DataModel.Price.PriceKey.Find(workingOrderRow.SecurityId, workingOrderRow.SettlementId); // Create the Execution for this side of the trade. Guid executionId = Guid.NewGuid(); dataModel.CreateExecution( null, workingOrderRow.BlotterId, null, null, null, createdTime, createdUserId, destinationOrderId, StateMap.FromCode(State.Acknowledged), executionId, priceRow.LastPrice, matchedQuantity, null, null, null, modifiedTime, modifiedUserId, null, null, null, null, StateMap.FromCode(State.Sent), null, null, null, null); // There is no opposite side of this transaction yet. It will be placed in the negotation table and wait there // until it times out, or the other side accepts the offer. negotiationId = Guid.NewGuid(); dataModel.CreateNegotiation( workingOrderRow.BlotterId, executionId, false, matchId, negotiationId, quantity, StatusMap.FromCode(Status.Accepted)); // Create an order for the agreed upon quantity. // Create the order on this side of the trade. Guid contraDestinationOrderId = Guid.NewGuid(); dataModel.CreateDestinationOrder( contraWorkingOrderRow.BlotterId, null, null, createdTime, createdUserId, destinationId, contraDestinationOrderId, null, null, null, null, contraWorkingOrderRow[DataModel.WorkingOrder.LimitPriceColumn], modifiedTime, modifiedUserId, matchedQuantity, contraWorkingOrderRow.OrderTypeId, contraWorkingOrderRow.SecurityId, modifiedTime, contraWorkingOrderRow.SettlementId, contraWorkingOrderRow.SideId, StateMap.FromCode(State.Acknowledged), StatusMap.FromCode(Status.New), contraWorkingOrderRow[DataModel.WorkingOrder.StopPriceColumn], contraWorkingOrderRow.TimeInForceId, modifiedTime, null, contraWorkingOrderRow.WorkingOrderId); // Create the Execution for this side of the trade. Guid contraExecutionId = Guid.NewGuid(); dataModel.CreateExecution( null, contraWorkingOrderRow.BlotterId, null, null, null, createdTime, createdUserId, contraDestinationOrderId, StateMap.FromCode(State.Acknowledged), contraExecutionId, priceRow.LastPrice, matchedQuantity, null, null, null, modifiedTime, modifiedUserId, null, null, null, null, StateMap.FromCode(State.Sent), null, null, null, null); // Update the contra offer. dataModel.UpdateNegotiation( contraWorkingOrderRow.BlotterId, contraExecutionId, false, null, null, new Object[] { contraNegotiationRow.NegotiationId }, null, contraNegotiationRow.RowVersion, StatusMap.FromCode(Status.Accepted)); } } } finally { // Release the tables. DataModel.DataLock.ExitReadLock(); } }