Ejemplo n.º 1
0
        /// <summary>
        /// Creates orders in the simulated order book.
        /// </summary>
        private static void OrderHandler()
        {
            // This thread will create orders in the simulated order book from destination orders placed in the queue.  This thread
            // is necessary due to the locking architecture that prevents accessing the data model during a commit operation (which
            // is where the event indicating a new or changed destination order originates).
            while (MarketSimulator.IsBrokerSimulatorThreadRunning)
            {
                // This thread will wait here until a destination order is available in the queue.
                DataModel.DestinationOrderRow destinationOrderRow = MarketSimulator.orderQueue.Dequeue();

                // The code that adds an order to the simulated book must have exclusive access to the simulated data model.
                lock (MarketSimulator.syncRoot)
                {
                    // The primary data model needs to be accessed also for ancillary data associated with the new order.
                    using (TransactionScope transactionScope = new TransactionScope())
                    {
                        try
                        {
                            // This context is used to keep track of the locks aquired for the ancillary data.
                            DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction;

                            // Lock the destination order.
                            destinationOrderRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                            dataModelTransaction.AddLock(destinationOrderRow);

                            // Lock the Security.
                            DataModel.SecurityRow securityRow = destinationOrderRow.SecurityRowByFK_Security_DestinationOrder_SecurityId;
                            securityRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                            dataModelTransaction.AddLock(securityRow);

                            // The working order row must be locked to examine the flags
                            DataModel.WorkingOrderRow workingOrderRow = destinationOrderRow.WorkingOrderRow;
                            workingOrderRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                            dataModelTransaction.AddLock(workingOrderRow);

                            // Lock the Entity.
                            DataModel.EntityRow entityRow = securityRow.EntityRow;
                            entityRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                            dataModelTransaction.AddLock(entityRow);

                            // Calculate the quantity executed on this order (some orders are created with executions, such as crossed orders.)
                            Decimal quantityExecuted = 0.0M;
                            foreach (DataModel.ExecutionRow executionRow in destinationOrderRow.GetExecutionRows())
                            {
                                executionRow.AcquireReaderLock(dataModelTransaction);
                                dataModelTransaction.AddLock(executionRow);
                                quantityExecuted += executionRow.ExecutionQuantity;
                            }

                            // The simulated order is added to the book.  This collects all the information required to simulate the execution of this order.
                            DataSetMarket.OrderRow orderRow = MarketSimulator.dataSetMarket.Order.NewOrderRow();
                            orderRow.BlotterId          = destinationOrderRow.BlotterId;
                            orderRow.DestinationOrderId = destinationOrderRow.DestinationOrderId;
                            orderRow.OrderTypeCode      = OrderTypeMap.FromId(destinationOrderRow.OrderTypeId);
                            orderRow.QuantityOrdered    = destinationOrderRow.OrderedQuantity;
                            orderRow.QuantityExecuted   = quantityExecuted;
                            orderRow.SideCode           = SideMap.FromId(destinationOrderRow.SideId);
                            orderRow.Symbol             = securityRow.Symbol;
                            orderRow.TimeInForceCode    = TimeInForceMap.FromId(destinationOrderRow.TimeInForceId);
                            MarketSimulator.dataSetMarket.Order.AddOrderRow(orderRow);

                            // Adding the first order to the simulated order book will enable the simulation thread to begin processing the orders.  The order
                            // simulation thread will continue until the book is filled.
                            if (MarketSimulator.dataSetMarket.Order.Count == 1)
                            {
                                MarketSimulator.orderEvent.Set();
                            }
                        }
                        catch { }

                        // The locks are no longer required.
                        transactionScope.Complete();
                    }
                }
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Simulation of brokers executing destination orders.
        /// </summary>
        private static void SimulateBroker()
        {
            // This will seed the random number generator.
            Random random = new Random(DateTime.Now.Millisecond);

            // An instance of the data model is required to update it.
            DataModel dataModel = new DataModel();

            // This set of claims gives the current thread the authority to update the price table.
            List <Claim> listClaims = new List <Claim>();

            listClaims.Add(new Claim(Teraque.ClaimTypes.Create, Teraque.Resources.Application, Rights.PossessProperty));
            listClaims.Add(new Claim(Teraque.ClaimTypes.Update, Teraque.Resources.Application, Rights.PossessProperty));
            listClaims.Add(new Claim(Teraque.ClaimTypes.Read, Teraque.Resources.Application, Rights.PossessProperty));
            ClaimSet adminClaims = new DefaultClaimSet(null, listClaims);
//			Thread.CurrentPrincipal = new ClaimsPrincipal(new GenericIdentity("Broker Service"), adminClaims);

            // Every execution requires a user identifier (the user who created the execution) and the broker who executed the
            // trade.  These values are hard coded at the moment but should be more intelligently assigned in the future.
            Guid userId   = Guid.Empty;
            Guid brokerId = Guid.Empty;

            // Operating values are required for the simulation that come from the data model.
            using (TransactionScope transactionScope = new TransactionScope())
            {
                // The middle tier context allows ADO operations to participate in the transaction.
                DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction;

                // The broker for all the executions is hard coded.
                DataModel.EntityRow brokerRow = DataModel.Entity.EntityKeyExternalId0.Find(new object[] { "ZODIAC SECURITIES" });
                brokerRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                dataModelTransaction.AddLock(brokerRow);
                brokerId = brokerRow.EntityId;

                // The user who creates these executions is hard coded.
                DataModel.EntityRow userRow = DataModel.Entity.EntityKeyExternalId0.Find(new object[] { "ADMINISTRATOR" });
                userRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout);
                dataModelTransaction.AddLock(userRow);
                userId = userRow.EntityId;

                // The data model doesn't need to be locked any more.
                transactionScope.Complete();
            }

            // This thread will run until an external thread sets this property to 'false'.
            while (MarketSimulator.IsBrokerSimulatorThreadRunning)
            {
                // Wait for orders to show up in the simulated order book.
                MarketSimulator.orderEvent.WaitOne();

                // The simulator parameters need to be locked for each batch of simulated price changes.
                try
                {
                    Monitor.Enter(MarketSimulator.syncRoot);

                    // This will select a random price in the table and change the price by a random amount.
                    if (MarketSimulator.dataSetMarket.Order.Rows.Count > 0)
                    {
                        // Select a random row from the order book.
                        int orderIndex = random.Next(MarketSimulator.dataSetMarket.Order.Rows.Count);
                        DataSetMarket.OrderRow orderRow = MarketSimulator.dataSetMarket.Order[orderIndex];
                        if (orderRow.IsBusy)
                        {
                            Thread.Sleep(0);
                            continue;
                        }
                        orderRow.IsBusy = true;

                        // This transaction is required to add the new execution.
                        using (TransactionScope transactionScope = new TransactionScope())
                        {
                            // The middle tier context allows ADO operations to participate in the transaction.
                            DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction;

                            // This will simulate a random selection of a price change is quoted. The 'quoteColumn' variable can be
                            // used to reference the selected quote from any price row.  Below, a random row will be selected for
                            // the price change.
                            int actionTypeIndex = random.Next(Enum.GetValues(typeof(ActionType)).Length);
                            switch ((ActionType)Enum.GetValues(typeof(ActionType)).GetValue(actionTypeIndex))
                            {
                            case ActionType.Execute:

                                // This creates a random execution of the remaining shares on the order.
                                DateTime dateTime         = DateTime.Now;
                                Guid     blotterId        = orderRow.BlotterId;
                                Decimal  quantityLeaves   = orderRow.QuantityOrdered - orderRow.QuantityExecuted;
                                Decimal  quantityExecuted = quantityLeaves <= 100 ?
                                                            quantityLeaves :
                                                            Convert.ToDecimal(random.Next(1, Convert.ToInt32(quantityLeaves / 100.0M))) * 100.0M;
                                DataSetMarket.PriceRow priceRow =
                                    MarketSimulator.dataSetMarket.Price.FindByConfigurationIdSymbol("US TICKER", orderRow.Symbol);
                                Decimal executionPrice = 0.0M;
                                if (priceRow != null)
                                {
                                    executionPrice = orderRow.SideCode == SideCode.Buy || orderRow.SideCode == SideCode.BuyCover ?
                                                     priceRow.BidPrice :
                                                     priceRow.AskPrice;
                                }
                                Guid executionId        = Guid.NewGuid();
                                Guid destinationOrderId = orderRow.DestinationOrderId;

                                // When the order is completed, it is removed from the order book.  When the order book is empty, the thread goes to sleep
                                // until another thread puts something in the order queue.
                                orderRow.QuantityExecuted += quantityExecuted;
                                if (orderRow.QuantityOrdered == orderRow.QuantityExecuted)
                                {
                                    MarketSimulator.dataSetMarket.Order.RemoveOrderRow(orderRow);
                                    if (MarketSimulator.dataSetMarket.Order.Count == 0)
                                    {
                                        MarketSimulator.orderEvent.Reset();
                                    }
                                }

                                if (quantityExecuted > 0)
                                {
                                    Monitor.Exit(MarketSimulator.syncRoot);

                                    dataModel.CreateExecution(
                                        0.0M,
                                        blotterId,
                                        null,
                                        brokerId,
                                        0.0M,
                                        dateTime,
                                        userId,
                                        destinationOrderId,
                                        StateMap.FromCode(StateCode.Acknowledged),
                                        executionId,
                                        executionPrice,
                                        quantityExecuted,
                                        null,
                                        null,
                                        false,
                                        dateTime,
                                        userId,
                                        null,
                                        null,
                                        null,
                                        null,
                                        StateMap.FromCode(StateCode.Acknowledged),
                                        0.0M,
                                        0.0M,
                                        0.0M,
                                        0.0M);
                                    Monitor.Enter(MarketSimulator.syncRoot);
                                }

                                break;
                            }

                            // This will commit the changes to the order book.
                            transactionScope.Complete();
                        }

                        // This allows another thread to work the order.
                        orderRow.IsBusy = false;
                    }
                }
                finally
                {
                    Monitor.Exit(MarketSimulator.syncRoot);
                }

                // This allows other threads the chance to run.
                Thread.Sleep(0);
            }
        }