コード例 #1
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);
            }
        }
コード例 #2
0
        /// <summary>
        /// Simulation of price changes in a stock market.
        /// </summary>
        private static void SimulatePrice()
        {
            // This will seed the random number generator.
            Random random = new Random(DateTime.Now.Millisecond);

            // 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.ToArray());

//			Thread.CurrentPrincipal = new Teraque.ClaimsPrincipal(new GenericIdentity("Price Service"), adminClaims);

            // This thread will run until an external thread sets this property to 'false'.
            while (MarketSimulator.IsPriceSimulatorThreadRunning)
            {
                // The price changes are generated in batches since there is a modest overhead to creating each transaction and applying it to the shared data
                // model.
                using (TransactionScope transactionScope = new TransactionScope())
                {
                    // The middle tier context allows ADO operations to participate in the transaction.
                    DataModel            dataModel            = new DataModel();
                    DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction;

                    // The simulator parameters need to be locked for each batch of simulated price changes.
                    lock (MarketSimulator.syncRoot)
                    {
                        // The prices are not updated continously because it is trying to simulate a communication interface where a batch of prices is updated
                        // periodically.
                        for (int tick = 0; tick < MarketSimulator.batchSize; tick++)
                        {
                            // This will select a random price in the table and change the price by a random amount.
                            int priceIndex = random.Next(MarketSimulator.dataSetMarket.Price.Rows.Count);
                            DataSetMarket.PriceRow priceRow = MarketSimulator.dataSetMarket.Price[priceIndex];

                            // 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 quoteTypeIndex = random.Next(Enum.GetValues(typeof(QuoteType)).Length);
                            switch ((QuoteType)Enum.GetValues(typeof(QuoteType)).GetValue(quoteTypeIndex))
                            {
                            case QuoteType.Ask:

                                priceRow.AskPrice += Convert.ToDecimal(Math.Round(random.NextDouble() - 0.5, 2));
                                priceRow.AskSize  += Convert.ToDecimal(random.Next(1, 10));
                                break;

                            case QuoteType.Bid:

                                priceRow.BidPrice += Convert.ToDecimal(Math.Round(random.NextDouble() - 0.5, 2));
                                priceRow.BidSize  += Convert.ToDecimal(random.Next(1, 10));
                                break;

                            case QuoteType.Last:

                                priceRow.LastPrice += Convert.ToDecimal(Math.Round(random.NextDouble() - 0.5, 2));
                                priceRow.LastSize  += Convert.ToDecimal(random.Next(1, 10));
                                break;
                            }

                            // This does the work of updating the price table using the external identifiers and the newly generated prices.
                            dataModel.CreatePriceEx(priceRow.AskPrice, priceRow.AskSize, priceRow.BidPrice, priceRow.BidSize, 0.0M, priceRow.ConfigurationId,
                                                    0.0M, priceRow.LastPrice, priceRow.LastSize, 0.0M, 0.0M, 0.0M, new object[] { priceRow.Currency }, new object[] { priceRow.Symbol },
                                                    0.0M, 0.0M);
                        }

                        // This will commit the changes to the price table.
                        transactionScope.Complete();
                    }
                }

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