Example #1
0
        /// <summary>
        /// Creates an XML Element representing a broker in a execution document.
        /// </summary>
        /// <param name="xmlDocument">The destination XML document.</param>
        /// <param name="blockOrderRow">A broker record.</param>
        public BlockOrderElement(XmlDocument xmlDocument, ClientMarketData.BlockOrderRow blockOrderRow) : base("BlockOrder", xmlDocument)
        {
            // The block order id is occationally useful info at the root element.
            AddAttribute("BlockOrderId", blockOrderRow.BlockOrderId);

            // It's useful to have the transaction type so we know whether to add fees and commissions or subtract
            // them from the net calculations.
            AddAttribute("TransactionTypeCode", blockOrderRow.TransactionTypeCode);

            // Get a shortcut to the security.
            ClientMarketData.SecurityRow securityRow = blockOrderRow.SecurityRowByFKSecurityBlockOrderSecurityId;

            // Add Fixed Income Fundamentals where they exist.
            foreach (ClientMarketData.DebtRow debtRow in securityRow.GetDebtRowsByFKSecurityDebtDebtId())
            {
                // Add the fundamental data for the debt.
                if (!debtRow.IsIssuerIdNull())
                {
                    AddAttribute("IssuerId", debtRow.IssuerId.ToString());
                }
                AddAttribute("DebtTypeCode", debtRow.DebtTypeCode.ToString());
                AddAttribute("Coupon", debtRow.Coupon.ToString());
                AddAttribute("MaturityDate", debtRow.MaturityDate.ToShortDateString());
            }
        }
Example #2
0
        /// <summary>
        /// Creates an XML Element representing a blockOrder in a execution document.
        /// </summary>
        /// <param name="xmlDocument">The destination XML document.</param>
        /// <param name="blockOrderRow">A blockOrder record.</param>
        public BlockOrderElement(XmlDocument xmlDocument, ClientMarketData.BlockOrderRow blockOrderRow) : base("BlockOrder", xmlDocument)
        {
            // Add the attributes of a blockOrder to this record.
            AddAttribute("BlockOrderId", blockOrderRow.BlockOrderId.ToString());

            // If the security exists, add the basic data to the block information.
            ClientMarketData.SecurityRow securityRow = blockOrderRow.SecurityRowByFKSecurityBlockOrderSecurityId;
            AddAttribute("SecurityId", securityRow.SecurityId.ToString());
            AddAttribute("SecuritySymbol", securityRow.Symbol);
            AddAttribute("SecurityName", securityRow.ObjectRow.Name);

            // It's useful to have the transaction type so we know whether to add fees and commissions or subtract
            // them from the net calculations.
            AddAttribute("TransactionTypeCode", blockOrderRow.TransactionTypeCode.ToString());
            AddAttribute("TransactionTypeDescription", blockOrderRow.TransactionTypeRow.Description);

            decimal quantityOrdered = 0.0M;

            foreach (ClientMarketData.OrderRow orderRow in blockOrderRow.GetOrderRows())
            {
                quantityOrdered += orderRow.Quantity;
            }

            AddAttribute("QuantityOrdered", quantityOrdered.ToString());
        }
Example #3
0
        public BlockOrderElement(BlockOrderDocument blockOrderDocument, ClientMarketData.BlockOrderRow blockOrderRow) :
            base("BlockOrder", blockOrderDocument)
        {
            this.blockOrderRow = blockOrderRow;

            AddAttribute("BlockOrderId", this.blockOrderRow.BlockOrderId);
            AddAttribute("StatusCode", this.blockOrderRow.StatusCode);
            AddAttribute("StatusName", this.blockOrderRow.StatusRow.Mnemonic);
        }
Example #4
0
		/// <summary>
		/// Creates a block order.
		/// </summary>
		/// <param name="configurationId">Defines which external fields are used to identify an object.</param>
		/// <param name="blotterId">The destination blotter for the trade.</param>
		/// <param name="securityId">The security.</param>
		/// <param name="transactionType">The type of transaction.</param>
		public BlockOrder(Blotter blotter, Security security, TransactionType transactionType)
		{

			// Create a block order on the server.
			RemoteBatch remoteBatch = new RemoteBatch();
			RemoteAssembly remoteAssembly = remoteBatch.Assemblies.Add("Service.Trading");
			RemoteType remoteType = remoteAssembly.Types.Add("Shadows.WebService.Trading.BlockOrder");
			RemoteMethod remoteMethod = remoteType.Methods.Add("Insert");
			remoteMethod.Parameters.Add("blockOrderId", DataType.Int, Direction.ReturnValue);
			remoteMethod.Parameters.Add("blotterId", blotter.BlotterId);
			remoteMethod.Parameters.Add("securityId", security.SecurityId);
			remoteMethod.Parameters.Add("settlementId", security.SettlementId);
			remoteMethod.Parameters.Add("transactionTypeCode", (int)transactionType);
			ClientMarketData.Execute(remoteBatch);

			// Now that the block order is created, construct the in-memory version of the record.
			int blockOrderId = (int)remoteMethod.Parameters["blockOrderId"].Value;

			try
			{

				// Lock the tables.
				Debug.Assert(!ClientMarketData.AreLocksHeld);
				ClientMarketData.BlockOrderLock.AcquireReaderLock(CommonTimeout.LockWait);
				ClientMarketData.ObjectLock.AcquireReaderLock(CommonTimeout.LockWait);
				ClientMarketData.SecurityLock.AcquireReaderLock(CommonTimeout.LockWait);

				ClientMarketData.BlockOrderRow blockOrderRow = ClientMarketData.BlockOrder.FindByBlockOrderId(blockOrderId);
				if (blockOrderRow == null)
					throw new Exception(String.Format("BlockOrder {0} doesn't exist", blockOrderId));

				this.blockOrderId = blockOrderRow.BlockOrderId;
				this.security = Security.Make(blockOrderRow.SecurityRowByFKSecurityBlockOrderSecurityId.SecurityId);
				this.settlement = Security.Make(blockOrderRow.SecurityRowByFKSecurityBlockOrderSettlementId.SecurityId);
				this.transactionType = (TransactionType)blockOrderRow.TransactionTypeCode;

			}
			finally
			{

				// Release the table locks.
				if (ClientMarketData.BlockOrderLock.IsReaderLockHeld) ClientMarketData.BlockOrderLock.ReleaseReaderLock();
				if (ClientMarketData.ObjectLock.IsReaderLockHeld) ClientMarketData.ObjectLock.ReleaseReaderLock();
				if (ClientMarketData.SecurityLock.IsReaderLockHeld) ClientMarketData.SecurityLock.ReleaseReaderLock();
				Debug.Assert(!ClientMarketData.AreLocksHeld);

			}

		}
Example #5
0
        /// <summary>
        /// Constructs a well formed Document Object Model for a group of executions on a block order.
        /// </summary>
        /// <param name="blockOrderId">The block order for which we want a execution document.</param>
        public ExecutionDocument(int blockOrderId, ExecutionSet executionSet)
        {
            // Create the root element for the document.
            XmlElement rootElement = this.CreateElement("Execution");

            this.AppendChild(rootElement);

            // This list is used to sort the executions.
            ArrayList executionsList = new ArrayList();

            // Start with the block order.  All the executions flow from this record.
            ClientMarketData.BlockOrderRow blockOrderRow = ClientMarketData.BlockOrder.FindByBlockOrderId(blockOrderId);
            if (blockOrderRow != null)
            {
                // This element holds all the information related to the block order.
                XmlElement blockOrderElement = this.CreateBlockOrderElement(blockOrderRow);
                rootElement.AppendChild(blockOrderElement);

                // We are going to run through all the executions posted against the block order and construct a
                // hierarchical structure of brokers.  Since they aren't arranged that way in the data model, we need to
                // scan the whole table looking for distinct brokers.
                foreach (ClientMarketData.ExecutionRow executionRow in blockOrderRow.GetExecutionRows())
                {
                    // Sort the list of executions by the created time.
                    int index;
                    for (index = 0; index < executionsList.Count; index++)
                    {
                        if (((ClientMarketData.ExecutionRow)executionsList[index]).CreatedTime > executionRow.CreatedTime)
                        {
                            executionsList.Insert(index, executionRow);
                            break;
                        }
                    }

                    // If the row wasn't sorted into the array above, it's added to the end of the list here.
                    if (index == executionsList.Count)
                    {
                        executionsList.Add(executionRow);
                    }
                }

                // Add all of the executions as children of the broker.
                foreach (ClientMarketData.ExecutionRow executionRow in executionsList)
                {
                    blockOrderElement.AppendChild(this.CreateGlobalExecutionElement(executionRow));
                }

                // Add the local executions.
                ExecutionSet.BlockOrderRow localBlockOrder = executionSet.BlockOrder.FindByBlockOrderId(blockOrderId);
                if (localBlockOrder != null)
                {
                    foreach (ExecutionSet.ExecutionRow executionRow in localBlockOrder.GetExecutionRows())
                    {
                        if (executionRow.RowState == DataRowState.Detached)
                        {
                            Console.WriteLine("{0} is Detached", executionRow["ExecutionId", DataRowVersion.Original]);
                        }
                        blockOrderElement.AppendChild(this.CreateLocalExecutionElement(executionRow));
                    }
                }
            }

            // The placeholder is a queue for the document manager to create a new execution.
            this.DocumentElement.AppendChild(this.CreatePlaceholderElement());
        }
Example #6
0
 /// <summary>
 /// Creates a broker element for the ExecutionDocument
 /// </summary>
 /// <param name="blockOrderRow">A Broker record</param>
 /// <returns>An element that represents a broker.</returns>
 public BlockOrderElement CreateBlockOrderElement(ClientMarketData.BlockOrderRow blockOrderRow)
 {
     return(new BlockOrderElement(this, blockOrderRow));
 }
Example #7
0
        public static void Distribute(int blockOrderId)
        {
            // This batch will be filled in with the allocations.
            RemoteBatch remoteBatch = null;

            try
            {
                // Lock all the tables that we'll reference while building a blotter document.
                Debug.Assert(!ClientMarketData.AreLocksHeld);
                ClientMarketData.AllocationLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.BlockOrderLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.ExecutionLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.OrderLock.AcquireReaderLock(CommonTimeout.LockWait);

                // Find the block order that is to be allocated.
                ClientMarketData.BlockOrderRow blockOrderRow = ClientMarketData.BlockOrder.FindByBlockOrderId(blockOrderId);
                if (blockOrderRow == null)
                {
                    throw new Exception(String.Format("Block Id {0} doesn't exist", blockOrderId));
                }

                // Aggregate the total quantity ordered.  This becomes the demoninator for the pro-rata calculation.
                decimal orderedQuantity = 0.0M;
                foreach (ClientMarketData.OrderRow orderRow in blockOrderRow.GetOrderRows())
                {
                    orderedQuantity += orderRow.Quantity;
                }

                // These values will total up all the executions posted against this block order.  The pro-rata
                // allocation will divide all the executions up against the ratio of the quantity ordered against the
                // total quantity ordered.  The price is an average price of all the executions.
                decimal  executedQuantity        = 0.0M;
                decimal  executedPrice           = 0.0M;
                decimal  executedCommission      = 0.0M;
                decimal  executedAccruedInterest = 0.0M;
                decimal  executedUserFee0        = 0.0M;
                decimal  executedUserFee1        = 0.0M;
                decimal  executedUserFee2        = 0.0M;
                decimal  executedUserFee3        = 0.0M;
                DateTime tradeDate      = DateTime.MinValue;
                DateTime settlementDate = DateTime.MinValue;

                // Total up all the executions against this block.
                foreach (ClientMarketData.ExecutionRow executionRow in blockOrderRow.GetExecutionRows())
                {
                    executedQuantity        += executionRow.Quantity;
                    executedPrice           += executionRow.Price * executionRow.Quantity;
                    executedCommission      += executionRow.Commission;
                    executedAccruedInterest += executionRow.AccruedInterest;
                    executedUserFee0        += executionRow.UserFee0;
                    executedUserFee1        += executionRow.UserFee1;
                    executedUserFee2        += executionRow.UserFee2;
                    executedUserFee3        += executionRow.UserFee3;
                    tradeDate      = executionRow.TradeDate;
                    settlementDate = executionRow.SettlementDate;
                }

                // Calculate the average price.
                decimal averagePrice = Math.Round((executedQuantity > 0.0M) ? executedPrice / executedQuantity : 0.0M, 2);

                // These values are used to keep track of how much has been allocated.  Because of the nature of a
                // pro-rata allocation, there will be an odd remainder after the allocation is finished.  We will
                // arbitrarily pick the last order in the block order and give it the remainer of the order.  To do that,
                // totals have to be kept of all the allocations that have been created before the last one.
                decimal allocatedQuantity        = 0.0M;
                decimal allocatedCommission      = 0.0M;
                decimal allocatedAccruedInterest = 0.0M;
                decimal allocatedUserFee0        = 0.0M;
                decimal allocatedUserFee1        = 0.0M;
                decimal allocatedUserFee2        = 0.0M;
                decimal allocatedUserFee3        = 0.0M;

                // Put all the allocations in a single batch.
                remoteBatch = new RemoteBatch();
                RemoteAssembly remoteAssembly = remoteBatch.Assemblies.Add("Service.Core");
                RemoteType     remoteType     = remoteAssembly.Types.Add("Shadows.WebService.Core.Allocation");

                // Allocate the order back to the original accounts.  Because odd values can be generated when dividing by the
                // pro-rata value, the last order will get the remaining portions of the execution.
                int orderCounter = blockOrderRow.GetOrderRows().Length;
                foreach (ClientMarketData.OrderRow orderRow in blockOrderRow.GetOrderRows())
                {
                    decimal quantity;
                    decimal commission;
                    decimal accruedInterest;
                    decimal userFee0;
                    decimal userFee1;
                    decimal userFee2;
                    decimal userFee3;

                    // The last account in the order is arbitrarily given the remaining parts of the execution.
                    if (--orderCounter == 0)
                    {
                        quantity        = executedQuantity - allocatedQuantity;
                        commission      = executedCommission - allocatedCommission;
                        accruedInterest = executedAccruedInterest = allocatedAccruedInterest;
                        userFee0        = executedUserFee0 - allocatedUserFee0;
                        userFee1        = executedUserFee1 - allocatedUserFee1;
                        userFee2        = executedUserFee2 - allocatedUserFee2;
                        userFee3        = executedUserFee3 - allocatedUserFee3;
                    }
                    else
                    {
                        // Calcuation the proportion of the trade destined for the current order.  The proportion is
                        // based on the amount of the original order against the block total.
                        quantity        = Math.Round(executedQuantity * orderRow.Quantity / orderedQuantity, 0);
                        commission      = Math.Round(executedCommission * orderRow.Quantity / orderedQuantity, 2);
                        accruedInterest = Math.Round(executedAccruedInterest * orderRow.Quantity / orderedQuantity, 2);
                        userFee0        = Math.Round(executedUserFee0 * orderRow.Quantity / orderedQuantity, 2);
                        userFee1        = Math.Round(executedUserFee1 * orderRow.Quantity / orderedQuantity, 2);
                        userFee2        = Math.Round(executedUserFee2 * orderRow.Quantity / orderedQuantity, 2);
                        userFee3        = Math.Round(executedUserFee3 * orderRow.Quantity / orderedQuantity, 2);
                    }

                    // Keep a running total of the amount allocated so far.  This will be used to calculate the last order's
                    // portion when the loop has finished.
                    allocatedQuantity        += quantity;
                    allocatedCommission      += commission;
                    allocatedAccruedInterest += accruedInterest;
                    allocatedUserFee0        += userFee0;
                    allocatedUserFee1        += userFee1;
                    allocatedUserFee2        += userFee2;
                    allocatedUserFee3        += userFee3;

                    // If the allocation has a positive quantity to register, then post it to the server.
                    if (quantity > 0.0M)
                    {
                        // Call the web service to add the new execution.
                        RemoteMethod remoteMethod = remoteType.Methods.Add("Insert");
                        remoteMethod.Parameters.Add("blockOrderId", orderRow.BlockOrderId);
                        remoteMethod.Parameters.Add("accountId", orderRow.AccountId);
                        remoteMethod.Parameters.Add("securityId", orderRow.SecurityId);
                        remoteMethod.Parameters.Add("settlementId", orderRow.SettlementId);
                        remoteMethod.Parameters.Add("positionTypeCode", orderRow.PositionTypeCode);
                        remoteMethod.Parameters.Add("transactionTypeCode", orderRow.TransactionTypeCode);
                        remoteMethod.Parameters.Add("quantity", quantity);
                        remoteMethod.Parameters.Add("price", averagePrice);
                        remoteMethod.Parameters.Add("commission", commission);
                        remoteMethod.Parameters.Add("accruedInterest", accruedInterest);
                        remoteMethod.Parameters.Add("userFee0", userFee0);
                        remoteMethod.Parameters.Add("userFee1", userFee1);
                        remoteMethod.Parameters.Add("userFee2", userFee2);
                        remoteMethod.Parameters.Add("userFee3", userFee3);
                        remoteMethod.Parameters.Add("tradeDate", tradeDate);
                        remoteMethod.Parameters.Add("settlementDate", settlementDate);
                        remoteMethod.Parameters.Add("createdTime", DateTime.Now);
                        remoteMethod.Parameters.Add("createdLoginId", ClientPreferences.LoginId);
                        remoteMethod.Parameters.Add("modifiedTime", DateTime.Now);
                        remoteMethod.Parameters.Add("modifiedLoginId", ClientPreferences.LoginId);
                    }
                }
            }
            catch (Exception exception)
            {
                // This signals that the batch isn't valid and shouldn't be sent.
                remoteBatch = null;

                // This will catch all remaining exceptions.
                Debug.WriteLine(exception.Message);
            }
            finally
            {
                // Release the locks obtained to produce the blotter report.
                if (ClientMarketData.AllocationLock.IsReaderLockHeld)
                {
                    ClientMarketData.AllocationLock.ReleaseReaderLock();
                }
                if (ClientMarketData.BlockOrderLock.IsReaderLockHeld)
                {
                    ClientMarketData.BlockOrderLock.ReleaseReaderLock();
                }
                if (ClientMarketData.ExecutionLock.IsReaderLockHeld)
                {
                    ClientMarketData.ExecutionLock.ReleaseReaderLock();
                }
                if (ClientMarketData.OrderLock.IsReaderLockHeld)
                {
                    ClientMarketData.OrderLock.ReleaseReaderLock();
                }
                Debug.Assert(!ClientMarketData.AreLocksHeld);
            }

            // Once the locks are release, the batch can be sent to the server.
            if (remoteBatch != null)
            {
                ClientMarketData.Send(remoteBatch);
            }
        }