Пример #1
0
        /// <summary>Archives a Price record.</summary>
        /// <param name="transaction">Commits or rejects a set of commands as a unit</param>
        /// <param name="RowVersion">The version number of this row.</param>
        /// <param name="securityId">The value for the SecurityId column.</param>
        /// <param name="archive">true to archive the object, false to unarchive it.</param>
        public static void Archive(AdoTransaction adoTransaction, SqlTransaction sqlTransaction, long rowVersion, int securityId)
        {
            // Accessor for the Price Table.
            ServerMarketData.PriceDataTable priceTable = ServerMarketData.Price;
            // Rule #1: Make sure the record exists before updating it.
            ServerMarketData.PriceRow priceRow = priceTable.FindBySecurityId(securityId);
            if ((priceRow == null))
            {
                throw new Exception(string.Format("The Price table does not have an element identified by {0}", securityId));
            }
            // Rule #2: Optimistic Concurrency Check
            if ((priceRow.RowVersion != rowVersion))
            {
                throw new System.Exception("This record is busy.  Please try again later.");
            }
            // Archive the child records.
            for (int index = 0; (index < priceRow.GetWorkingOrderRows().Length); index = (index + 1))
            {
                ServerMarketData.WorkingOrderRow childWorkingOrderRow = priceRow.GetWorkingOrderRows()[index];
                WorkingOrder.Archive(adoTransaction, sqlTransaction, childWorkingOrderRow.RowVersion, childWorkingOrderRow.WorkingOrderId);
            }
            // Increment the row version
            rowVersion = ServerMarketData.RowVersion.Increment();
            // Delete the record in the ADO database.
            priceRow[priceTable.RowVersionColumn] = rowVersion;
            adoTransaction.DataRows.Add(priceRow);
            priceRow.Delete();
            // Archive the record in the SQL database.
            SqlCommand sqlCommand = new SqlCommand("update \"Price\" set \"IsArchived\" = 1 where \"SecurityId\"=@securityId");

            sqlCommand.Connection  = sqlTransaction.Connection;
            sqlCommand.Transaction = sqlTransaction;
            sqlCommand.Parameters.Add(new SqlParameter("@securityId", SqlDbType.Int, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, securityId));
            sqlCommand.ExecuteNonQuery();
        }
Пример #2
0
        /// <summary>ArchiveChildrens a Currency record.</summary>
        /// <param name="transaction">Commits or rejects a set of commands as a unit</param>
        /// <param name="rowVersion">the version number of this row.</param>
        /// <param name="currencyId">The value for the CurrencyId column.</param>
        /// <param name="archive">true to archive the object, false to unarchive it.</param>
        internal new static void ArchiveChildren(AdoTransaction adoTransaction, SqlTransaction sqlTransaction, long rowVersion, int currencyId)
        {
            // Accessor for the Currency Table.
            ServerMarketData.CurrencyDataTable currencyTable = ServerMarketData.Currency;
            // This record can be used to iterate through all the children.
            ServerMarketData.CurrencyRow currencyRow = currencyTable.FindByCurrencyId(currencyId);
            // Archive the child records.
            for (int index = 0; (index < currencyRow.GetAccountBaseRows().Length); index = (index + 1))
            {
                ServerMarketData.AccountBaseRow childAccountBaseRow = currencyRow.GetAccountBaseRows()[index];
                AccountBase.ArchiveChildren(adoTransaction, sqlTransaction, childAccountBaseRow.RowVersion, childAccountBaseRow.AccountBaseId);
            }
            for (int index = 0; (index < currencyRow.GetPriceRows().Length); index = (index + 1))
            {
                ServerMarketData.PriceRow childPriceRow = currencyRow.GetPriceRows()[index];
                Price.Archive(adoTransaction, sqlTransaction, childPriceRow.RowVersion, childPriceRow.SecurityId);
            }
            // Increment the row version
            rowVersion = ServerMarketData.RowVersion.Increment();
            // Delete the record in the ADO database.
            currencyRow[currencyTable.RowVersionColumn] = rowVersion;
            adoTransaction.DataRows.Add(currencyRow);
            currencyRow.Delete();
            // Archive the record in the SQL database.
            SqlCommand sqlCommand = new SqlCommand("update \"Currency\" set \"IsArchived\" = 1 where \"CurrencyId\"=@currencyId");

            sqlCommand.Connection  = sqlTransaction.Connection;
            sqlCommand.Transaction = sqlTransaction;
            sqlCommand.Parameters.Add(new SqlParameter("@currencyId", SqlDbType.Int, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, currencyId));
            sqlCommand.ExecuteNonQuery();
        }
Пример #3
0
        /// <summary>
        /// Authorizes a Price to be returned to the client.
        /// </summary>
        /// <param name="userDataRow">Identifies the current user.</param>
        /// <param name="priceDataRow">The record to be tested for authorization.</param>
        /// <returns>true if the record belongs in the user's hierarchy.</returns>
        public static bool FilterPrice(DataRow userDataRow, DataRow priceDataRow)
        {
            // This will test the record and return true if it belongs to the hierarchies this user is authorized to view.  False
            // if the record should not be included in the user's data model.
            ServerMarketData.UserRow  userRow  = (ServerMarketData.UserRow)userDataRow;
            ServerMarketData.PriceRow priceRow = (ServerMarketData.PriceRow)priceDataRow;

            foreach (ServerMarketData.SourceOrderRow sourceOrderRow in priceRow.SecurityRow.GetSourceOrderRowsBySecuritySourceOrderSecurityId())
            {
                if (Hierarchy.IsDescendant(userRow.SystemFolderRow.FolderRow.ObjectRow, sourceOrderRow.WorkingOrderRow.BlotterRow.ObjectRow))
                {
                    return(true);
                }
            }

            foreach (ServerMarketData.SourceOrderRow sourceOrderRow in priceRow.SecurityRow.GetSourceOrderRowsBySecuritySourceOrderSettlementId())
            {
                if (Hierarchy.IsDescendant(userRow.SystemFolderRow.FolderRow.ObjectRow, sourceOrderRow.WorkingOrderRow.BlotterRow.ObjectRow))
                {
                    return(true);
                }
            }

            return(false);
        }
Пример #4
0
 /// <summary>Loads a Price record using Metadata Parameters.</summary>
 /// <param name="transaction">Contains the parameters and exceptions for this command.</param>
 public static void Load(ParameterList parameters)
 {
     // Accessor for the Price Table.
     ServerMarketData.PriceDataTable priceTable = ServerMarketData.Price;
     // Extract the parameters from the command batch.
     AdoTransaction adoTransaction = parameters["adoTransaction"];
     SqlTransaction sqlTransaction = parameters["sqlTransaction"];
     object configurationId = parameters["configurationId"].Value;
     object askPrice = parameters["askPrice"].Value;
     object askSize = parameters["askSize"].Value;
     object bidPrice = parameters["bidPrice"].Value;
     object bidSize = parameters["bidSize"].Value;
     object closePrice = parameters["closePrice"].Value;
     string externalCurrencyId = parameters["currencyId"];
     object highPrice = parameters["highPrice"].Value;
     object lastPrice = parameters["lastPrice"].Value;
     object lastSize = parameters["lastSize"].Value;
     object lowPrice = parameters["lowPrice"].Value;
     object openPrice = parameters["openPrice"].Value;
     object priceChange = parameters["priceChange"].Value;
     string externalSecurityId = parameters["securityId"];
     object volume = parameters["volume"].Value;
     object volumeWeightedAveragePrice = parameters["volumeWeightedAveragePrice"].Value;
     // The row versioning is largely disabled for external operations.
     long rowVersion = long.MinValue;
     // Resolve External Identifiers
     int currencyId = Currency.FindRequiredKey(configurationId, "currencyId", externalCurrencyId);
     int securityId = Security.FindRequiredKey(configurationId, "securityId", externalSecurityId);
     // Find the record using the unique identifier.  If it doesn't exist, it will be inserted, if it does exist,
     // it will be updated.
     ServerMarketData.PriceRow priceRow = priceTable.FindBySecurityId(securityId);
     if ((priceRow == null))
     {
         // Call the internal 'Insert' method to complete the operation.
         MarkThree.Guardian.Core.Price.Insert(adoTransaction, sqlTransaction, ref rowVersion, askPrice, askSize, bidPrice, bidSize, closePrice, currencyId, highPrice, lastPrice, lastSize, lowPrice, openPrice, priceChange, securityId, volume, volumeWeightedAveragePrice);
     }
     else
     {
         // This will bypass the optimistic concurrency checking required by the internal method.
         rowVersion = ((long)(priceRow[priceTable.RowVersionColumn]));
         // Call the internal 'Update' method to complete the operation.
         MarkThree.Guardian.Core.Price.Update(adoTransaction, sqlTransaction, ref rowVersion, askPrice, askSize, bidPrice, bidSize, closePrice, currencyId, highPrice, lastPrice, lastSize, lowPrice, openPrice, priceChange, securityId, volume, volumeWeightedAveragePrice);
     }
     // Return values
     parameters["rowVersion"] = rowVersion;
 }
Пример #5
0
 /// <summary>Archives a Price record using Metadata Parameters.</summary>
 /// <param name="transaction">Contains the parameters and exceptions for this command.</param>
 public static void Archive(ParameterList parameters)
 {
     // Accessor for the Price Table.
     ServerMarketData.PriceDataTable priceTable = ServerMarketData.Price;
     // Extract the parameters from the command batch.
     AdoTransaction adoTransaction = parameters["adoTransaction"];
     SqlTransaction sqlTransaction = parameters["sqlTransaction"];
     object configurationId = parameters["configurationId"].Value;
     string externalSecurityId = parameters["securityId"];
     // Resolve External Identifiers
     int securityId = Security.FindRequiredKey(configurationId, "securityId", externalSecurityId);
     // The row versioning is largely disabled for external operations.
     long rowVersion = long.MinValue;
     // While the optimistic concurrency checking is disabled for the external methods, the internal methods
     // still need to perform the check.  This ncurrency checking logic by finding the current row version to be
     // will bypass the coused when the internal method is called.
     ServerMarketData.PriceRow priceRow = priceTable.FindBySecurityId(securityId);
     rowVersion = ((long)(priceRow[priceTable.RowVersionColumn]));
     // Call the internal method to complete the operation.
     MarkThree.Guardian.Core.Price.Archive(adoTransaction, sqlTransaction, rowVersion, securityId);
 }
Пример #6
0
        /// <summary>
        /// Generates random price movements.
        /// </summary>
        private static void MarketThread()
        {
            // Keep looping until the thread is terminated.
            while (true)
            {
                try
                {
                    // Lock the tables.
                    Debug.Assert(!ServerMarketData.AreLocksHeld);
                    ServerMarketData.EquityLock.AcquireReaderLock(Timeout.Infinite);
                    ServerMarketData.PriceLock.AcquireWriterLock(Timeout.Infinite);
                    ServerMarketData.SecurityLock.AcquireReaderLock(Timeout.Infinite);

                    // Pick a random security to move from the tax lot tables.  This insures us that the ticks we get are
                    // relative to the demo.
                    int index = Random.Next(0, ServerMarketData.Equity.Rows.Count);
                    ServerMarketData.EquityRow   equityRow   = ServerMarketData.Equity[index];
                    ServerMarketData.SecurityRow securityRow = equityRow.SecurityRowByFKSecurityEquityEquityId;

                    // Find a price that matches the equity's default settlement.  This is the price record that will be updated
                    // with the simulated market conditions.
                    ServerMarketData.PriceRow priceRow = ServerMarketData.Price.FindBySecurityIdCurrencyId(equityRow.EquityId, equityRow.SettlementId);
                    if (priceRow == null)
                    {
                        continue;
                    }

                    // Randomly change the bid, last or asked price.
                    switch (Random.Next(3))
                    {
                    case 0:

                        // The bid price is moved randomly away from the last price.
                        decimal bidChange = (decimal)(Math.Round(Random.NextDouble() * 0.25, 2));
                        priceRow.RowVersion = ServerMarketData.RowVersion.Increment();
                        priceRow.BidPrice   = priceRow.LastPrice - bidChange;
                        priceRow.BidSize    = (decimal)(Math.Round(Random.NextDouble() * 10.0, 0) * 100.0 + 100);
                        break;

                    case 1:

                        // The price is moved randomly from one to 10 tenths of a percent.
                        decimal randomPercent = (decimal)(Math.Round(Random.NextDouble() * 0.010, 3) - 0.005);
                        priceRow.RowVersion  = ServerMarketData.RowVersion.Increment();
                        priceRow.PriceChange = Math.Round(priceRow.LastPrice * randomPercent, 2);
                        priceRow.LastPrice  += priceRow.PriceChange;
                        priceRow.LastSize    = (decimal)(Math.Round(Random.NextDouble() * 10.0, 0) * 100.0 + 100);
                        break;

                    case 2:

                        // The ask price is moved randomly away from the last price.
                        decimal askChange = (decimal)(Math.Round(Random.NextDouble(), 2) * 0.25);
                        priceRow.RowVersion = ServerMarketData.RowVersion.Increment();
                        priceRow.AskPrice   = priceRow.LastPrice + askChange;
                        priceRow.AskSize    = (decimal)(Math.Round(Random.NextDouble() * 10.0, 0) * 100.0 + 100);
                        break;
                    }
                }
                catch (Exception exception)
                {
                    // Write the error and stack trace out to the debug listener
                    Debug.WriteLine(String.Format("{0}, {1}", exception.Message, exception.StackTrace));
                }
                finally
                {
                    // Release the global tables.
                    if (ServerMarketData.EquityLock.IsReaderLockHeld)
                    {
                        ServerMarketData.EquityLock.ReleaseReaderLock();
                    }
                    if (ServerMarketData.PriceLock.IsWriterLockHeld)
                    {
                        ServerMarketData.PriceLock.ReleaseWriterLock();
                    }
                    if (ServerMarketData.SecurityLock.IsReaderLockHeld)
                    {
                        ServerMarketData.SecurityLock.ReleaseReaderLock();
                    }
                    Debug.Assert(!ServerMarketData.AreLocksHeld);
                }

                // The controls how often the simulator picks another price.
                Thread.Sleep(Price.Timer);
            }
        }
Пример #7
0
        private static void ProcessSecurity(int securityId, int currencyId)
        {
            bool didDataChange = false;

            try
            {
                // Lock the tables.
                Debug.Assert(!ServerMarketData.IsLocked);
                ServerMarketData.PriceLock.AcquireWriterLock(Timeout.Infinite);
                ServerMarketData.SecurityLock.AcquireReaderLock(Timeout.Infinite);


                // get the price row associated with this security
                ServerMarketData.PriceRow priceRow = ServerMarketData.Price.FindBySecurityId(securityId);

                // if the row does not exist add it
                if (priceRow == null)
                {
                    priceRow = ServerMarketData.Price.NewPriceRow();
                    //priceRow.RowVersion = ServerMarketData.RowVersion.Increment();
                    priceRow.SecurityId = securityId;
                    priceRow.CurrencyId = currencyId;
                    priceRow.LastPrice  = 1.0M;
                    priceRow.AskPrice   = 1.01M;
                    priceRow.BidPrice   = 0.99M;
                    priceRow.Volume     = 0.0M;
                    priceRow.VolumeWeightedAveragePrice = priceRow.LastPrice;
                    priceRow.HighPrice  = priceRow.LastPrice;
                    priceRow.LowPrice   = priceRow.LastPrice;
                    priceRow.OpenPrice  = priceRow.LastPrice;
                    priceRow.ClosePrice = priceRow.LastPrice;

                    ServerMarketData.Price.AddPriceRow(priceRow);

                    openingPriceMap.Add(priceRow.SecurityId, priceRow.LastPrice);
                }

                // if we got a row then process it
                if (priceRow != null)
                {
                    // get the opening price
                    decimal openingPrice = priceRow.LastPrice;
                    if (openingPriceMap.Contains(securityId))
                    {
                        openingPrice = (decimal)openingPriceMap[securityId];
                    }
                    if (openingPrice == 0)
                    {
                        openingPrice = 10;
                    }

                    // if we do not already have a volume or approx every 50th(ish) time update the volume
                    if (priceRow.Volume <= 0 || (random.Next(50) == 0))
                    {
                        // if this security ID is not already in the volume table pick a randon volume divergrance (-50% to 50%)
                        // and add it to the table
                        double volumeDivergence = 0.0;
                        if (volumeDivergenceMap.Contains(securityId))
                        {
                            volumeDivergence = (double)volumeDivergenceMap[securityId];
                        }
                        else
                        {
                            volumeDivergence = (double)random.Next(-50, 50);
                        }

                        // increase or decrease by up to 1%
                        int divergenceChangePercent = random.Next(-100, 100);

                        // don't go over 50% up or down
                        volumeDivergence = Math.Max(-50.0, Math.Min(50.0, volumeDivergence + ((double)divergenceChangePercent / 100.0)));

                        // update the volume divergence table
                        volumeDivergenceMap[securityId] = volumeDivergence;

                        // get the estimated volume for this time of day
                        decimal projectVolume = ProjectedVolume(DateTime.Now, priceRow.SecurityRow.AverageDailyVolume);

                        // adjust it by the divergence we are using and update the price table
                        priceRow.Volume = (int)(projectVolume - (int)((double)projectVolume * (volumeDivergence / 100.0)));
                        didDataChange   = true;
                    }

                    // base the frequency of price updates to the ADV of the security
                    int updateFrequency = 10;
                    if (priceRow.SecurityRow.AverageDailyVolume < 1000000)      /* UNDER 1M about every 75 loops*/
                    {
                        updateFrequency = 75;
                    }
                    else
                    if (priceRow.SecurityRow.AverageDailyVolume < 5000000)      /* 1M to 5M about every 30 loops */
                    {
                        updateFrequency = 30;
                    }
                    else
                    {
                        updateFrequency = 20;                                    /* OVER 5M about every 20 loops*/
                    }
                    // about once every X loops update the price
                    if (random.Next(updateFrequency) == 0)
                    {
                        // the anount of change will be based on stock price
                        // < $10 ==     always 0.01 (plus or minus)
                        // $10 - 25 ==  0.01 to 0.02 (plus or minus)
                        // $25 - 100 == 0.01 to 0.03 (plus or minus)
                        // > $100  == 0.01 to 0.05 (plus or minus)
                        double priceChange = 0;
                        if (priceRow.LastPrice < 10)
                        {
                            priceChange = 0.01 - ((double)random.Next(3) * 0.01);
                        }
                        else
                        if (priceRow.LastPrice < 25)
                        {
                            priceChange = 0.02 - ((double)random.Next(5) * 0.01);
                        }
                        else
                        if (priceRow.LastPrice < 100)
                        {
                            priceChange = 0.03 - ((double)random.Next(7) * 0.01);
                        }
                        else
                        {
                            priceChange = 0.05 - ((double)random.Next(11) * 0.01);
                        }

                        // change the last price
                        decimal newPrice          = priceRow.LastPrice + (decimal)priceChange;
                        decimal lastChange        = openingPrice - newPrice;
                        double  lastChangepercent = ((double)(openingPrice - lastChange)) / (double)openingPrice;

                        // don't let it go over 20% change per day
                        if (Math.Abs(lastChangepercent) < 20)
                        {
                            priceRow.LastPrice = newPrice;
                        }

                        // set the spread to be 1 to 5 cents
                        int     spreadInCents = random.Next(1, 5);
                        decimal spread        = (decimal)spreadInCents / 100m;

                        // set the bid to be 0 to (spread - 1) cents below the price
                        priceRow.BidPrice = priceRow.LastPrice - ((decimal)random.Next(spreadInCents) / 100m);

                        // set the ask based on the spread
                        priceRow.AskPrice = priceRow.BidPrice + spread;

                        // set the bid ask size
                        priceRow.BidSize = random.Next(1, 999) * 100;
                        priceRow.AskSize = random.Next(1, 999) * 100;

                        // check to see if we are at a new high or low for the day
                        if (priceRow.LastPrice > priceRow.HighPrice)
                        {
                            priceRow.HighPrice = priceRow.LastPrice;
                        }
                        if (priceRow.LastPrice < priceRow.LowPrice)
                        {
                            priceRow.LowPrice = priceRow.LastPrice;
                        }


                        // set the VWAP to be the average of the open and last
                        // however don't let it be more than 5% from the last
                        decimal newVwap           = (priceRow.LastPrice + priceRow.OpenPrice) / 2;
                        decimal fivePercentOfLast = priceRow.LastPrice * 0.05M;
                        priceRow.VolumeWeightedAveragePrice = Math.Max(Math.Min(newVwap, (priceRow.LastPrice + fivePercentOfLast)), (priceRow.LastPrice - fivePercentOfLast));
                        didDataChange = true;
                    }
                }

                // if something changeds update the data model
                if (didDataChange)
                {
                    priceRow.RowVersion = ServerMarketData.RowVersion.Increment();
                    priceRow.AcceptChanges();
                }
            }
            catch (Exception exception)
            {
                // Write the error and stack trace out to the debug listener
                MarkThree.EventLog.Error(String.Format("{0}, {1}", exception.Message, exception.StackTrace));
            }
            finally
            {
                // Release the global tables.
                if (ServerMarketData.PriceLock.IsWriterLockHeld)
                {
                    ServerMarketData.PriceLock.ReleaseWriterLock();
                }
                if (ServerMarketData.SecurityLock.IsReaderLockHeld)
                {
                    ServerMarketData.SecurityLock.ReleaseReaderLock();
                }
                Debug.Assert(!ServerMarketData.IsLocked);
            }
        }
Пример #8
0
        /// <summary>ArchiveChildrens a Security record.</summary>
        /// <param name="transaction">Commits or rejects a set of commands as a unit</param>
        /// <param name="rowVersion">the version number of this row.</param>
        /// <param name="securityId">The value for the SecurityId column.</param>
        /// <param name="archive">true to archive the object, false to unarchive it.</param>
        internal static void ArchiveChildren(AdoTransaction adoTransaction, SqlTransaction sqlTransaction, long rowVersion, int securityId)
        {
            // Accessor for the Security Table.
            ServerMarketData.SecurityDataTable securityTable = ServerMarketData.Security;
            // This record can be used to iterate through all the children.
            ServerMarketData.SecurityRow securityRow = securityTable.FindBySecurityId(securityId);
            // Archive the child records.
            for (int index = 0; (index < securityRow.GetAccountBaseRows().Length); index = (index + 1))
            {
                ServerMarketData.AccountBaseRow childAccountBaseRow = securityRow.GetAccountBaseRows()[index];
                AccountBase.ArchiveChildren(adoTransaction, sqlTransaction, childAccountBaseRow.RowVersion, childAccountBaseRow.AccountBaseId);
            }
            for (int index = 0; (index < securityRow.GetAllocationRowsBySecurityAllocationSecurityId().Length); index = (index + 1))
            {
                ServerMarketData.AllocationRow childAllocationRow = securityRow.GetAllocationRowsBySecurityAllocationSecurityId()[index];
                Allocation.Archive(adoTransaction, sqlTransaction, childAllocationRow.RowVersion, childAllocationRow.AllocationId);
            }
            for (int index = 0; (index < securityRow.GetAllocationRowsBySecurityAllocationSettlementId().Length); index = (index + 1))
            {
                ServerMarketData.AllocationRow childAllocationRow = securityRow.GetAllocationRowsBySecurityAllocationSettlementId()[index];
                Allocation.Archive(adoTransaction, sqlTransaction, childAllocationRow.RowVersion, childAllocationRow.AllocationId);
            }
            for (int index = 0; (index < securityRow.GetCurrencyRows().Length); index = (index + 1))
            {
                ServerMarketData.CurrencyRow childCurrencyRow = securityRow.GetCurrencyRows()[index];
                Currency.ArchiveChildren(adoTransaction, sqlTransaction, childCurrencyRow.RowVersion, childCurrencyRow.CurrencyId);
            }
            for (int index = 0; (index < securityRow.GetDebtRowsBySecurityDebtDebtId().Length); index = (index + 1))
            {
                ServerMarketData.DebtRow childDebtRow = securityRow.GetDebtRowsBySecurityDebtDebtId()[index];
                Debt.ArchiveChildren(adoTransaction, sqlTransaction, childDebtRow.RowVersion, childDebtRow.DebtId);
            }
            for (int index = 0; (index < securityRow.GetDebtRowsBySecurityDebtSettlementId().Length); index = (index + 1))
            {
                ServerMarketData.DebtRow childDebtRow = securityRow.GetDebtRowsBySecurityDebtSettlementId()[index];
                Debt.ArchiveChildren(adoTransaction, sqlTransaction, childDebtRow.RowVersion, childDebtRow.DebtId);
            }
            for (int index = 0; (index < securityRow.GetEquityRowsBySecurityEquityEquityId().Length); index = (index + 1))
            {
                ServerMarketData.EquityRow childEquityRow = securityRow.GetEquityRowsBySecurityEquityEquityId()[index];
                Equity.ArchiveChildren(adoTransaction, sqlTransaction, childEquityRow.RowVersion, childEquityRow.EquityId);
            }
            for (int index = 0; (index < securityRow.GetEquityRowsBySecurityEquitySettlementId().Length); index = (index + 1))
            {
                ServerMarketData.EquityRow childEquityRow = securityRow.GetEquityRowsBySecurityEquitySettlementId()[index];
                Equity.ArchiveChildren(adoTransaction, sqlTransaction, childEquityRow.RowVersion, childEquityRow.EquityId);
            }
            for (int index = 0; (index < securityRow.GetPositionRows().Length); index = (index + 1))
            {
                ServerMarketData.PositionRow childPositionRow = securityRow.GetPositionRows()[index];
                Position.Archive(adoTransaction, sqlTransaction, childPositionRow.RowVersion, childPositionRow.AccountId, childPositionRow.SecurityId, childPositionRow.PositionTypeCode);
            }
            for (int index = 0; (index < securityRow.GetPriceRows().Length); index = (index + 1))
            {
                ServerMarketData.PriceRow childPriceRow = securityRow.GetPriceRows()[index];
                Price.Archive(adoTransaction, sqlTransaction, childPriceRow.RowVersion, childPriceRow.SecurityId);
            }
            for (int index = 0; (index < securityRow.GetSourceOrderRowsBySecuritySourceOrderSecurityId().Length); index = (index + 1))
            {
                ServerMarketData.SourceOrderRow childSourceOrderRow = securityRow.GetSourceOrderRowsBySecuritySourceOrderSecurityId()[index];
                SourceOrder.Archive(adoTransaction, sqlTransaction, childSourceOrderRow.RowVersion, childSourceOrderRow.SourceOrderId);
            }
            for (int index = 0; (index < securityRow.GetSourceOrderRowsBySecuritySourceOrderSettlementId().Length); index = (index + 1))
            {
                ServerMarketData.SourceOrderRow childSourceOrderRow = securityRow.GetSourceOrderRowsBySecuritySourceOrderSettlementId()[index];
                SourceOrder.Archive(adoTransaction, sqlTransaction, childSourceOrderRow.RowVersion, childSourceOrderRow.SourceOrderId);
            }
            for (int index = 0; (index < securityRow.GetTaxLotRows().Length); index = (index + 1))
            {
                ServerMarketData.TaxLotRow childTaxLotRow = securityRow.GetTaxLotRows()[index];
                TaxLot.Archive(adoTransaction, sqlTransaction, childTaxLotRow.RowVersion, childTaxLotRow.TaxLotId);
            }
            for (int index = 0; (index < securityRow.GetWorkingOrderRowsBySecurityWorkingOrderSecurityId().Length); index = (index + 1))
            {
                ServerMarketData.WorkingOrderRow childWorkingOrderRow = securityRow.GetWorkingOrderRowsBySecurityWorkingOrderSecurityId()[index];
                WorkingOrder.Archive(adoTransaction, sqlTransaction, childWorkingOrderRow.RowVersion, childWorkingOrderRow.WorkingOrderId);
            }
            for (int index = 0; (index < securityRow.GetWorkingOrderRowsBySecurityWorkingOrderSettlementId().Length); index = (index + 1))
            {
                ServerMarketData.WorkingOrderRow childWorkingOrderRow = securityRow.GetWorkingOrderRowsBySecurityWorkingOrderSettlementId()[index];
                WorkingOrder.Archive(adoTransaction, sqlTransaction, childWorkingOrderRow.RowVersion, childWorkingOrderRow.WorkingOrderId);
            }
            // Increment the row version
            rowVersion = ServerMarketData.RowVersion.Increment();
            // Delete the record in the ADO database.
            securityRow[securityTable.RowVersionColumn] = rowVersion;
            adoTransaction.DataRows.Add(securityRow);
            securityRow.Delete();
            // Archive the record in the SQL database.
            SqlCommand sqlCommand = new SqlCommand("update \"Security\" set \"IsArchived\" = 1 where \"SecurityId\"=@securityId");

            sqlCommand.Connection  = sqlTransaction.Connection;
            sqlCommand.Transaction = sqlTransaction;
            sqlCommand.Parameters.Add(new SqlParameter("@securityId", SqlDbType.Int, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, securityId));
            sqlCommand.ExecuteNonQuery();
        }
Пример #9
0
        public static void OnUpdateSymbolDM(object wrapper, DMUpdateSymbolArgs args)
        {
            // StockInfo object holding the new symbol data for this update
            StockInfo stockInfo = args.stockInfo;

            try
            {
                // Lock the tables.
                Debug.Assert(!ServerMarketData.IsLocked);
                ServerMarketData.EquityLock.AcquireReaderLock(Timeout.Infinite);
                ServerMarketData.PriceLock.AcquireWriterLock(Timeout.Infinite);
                ServerMarketData.SecurityLock.AcquireReaderLock(Timeout.Infinite);

                // make sure the symbol is in the hash table - and that we added it to the data manager
                if (!symbolToSecurityIdTable.ContainsKey(stockInfo.Symbol))
                {
                    throw new Exception("Received update for unknown symbol: " + stockInfo.Symbol);
                }

                // get the security id of the symbol
                int securityID = (int)symbolToSecurityIdTable[stockInfo.Symbol];

                // get the security row
                ServerMarketData.SecurityRow securityRow = ServerMarketData.Security.FindBySecurityId(securityID);
                if (securityRow == null)
                {
                    throw new Exception("Warning: Could not find security row for symbol: " + stockInfo.Symbol);
                }

                //int equityId = Security.FindRequiredKey(configurationId, "equityId", externalEquityId);
                // Only Equities are priced by this simulator.  All others are ignored.
                ServerMarketData.EquityRow equityRow = ServerMarketData.Equity.FindByEquityId(securityRow.SecurityId);
                if (equityRow != null)
                {
                    // Find a price that matches the equity's default settlement.  This is the price record that will be updated
                    // with the simulated market conditions.
                    ServerMarketData.PriceRow priceRow = ServerMarketData.Price.FindBySecurityId(securityRow.SecurityId);
                    if (priceRow == null)
                    {
                        priceRow = ServerMarketData.Price.NewPriceRow();
                        //priceRow.RowVersion = ServerMarketData.RowVersion.Increment();
                        priceRow.SecurityId = equityRow.EquityId;
                        priceRow.CurrencyId = equityRow.SettlementId;
                        priceRow.LastPrice  = 0.0M;
                        priceRow.AskPrice   = 0.0M;
                        priceRow.BidPrice   = 0.0M;
                        priceRow.Volume     = 0.0M;
                        priceRow.ClosePrice = 0.0M;
                        priceRow.VolumeWeightedAveragePrice = 0.0M;
                        priceRow.HighPrice = 0.0M;
                        priceRow.LowPrice  = 0.0M;
                        ServerMarketData.Price.AddPriceRow(priceRow);
                    }

                    // set the new values from the real time event into the price row
                    priceRow.BidSize   = stockInfo.BidSize;
                    priceRow.BidPrice  = Convert.ToDecimal(stockInfo.BidPrice);
                    priceRow.AskPrice  = Convert.ToDecimal(stockInfo.AskPrice);
                    priceRow.AskSize   = Convert.ToDecimal(stockInfo.AskSize);
                    priceRow.LastPrice = Convert.ToDecimal(stockInfo.LastPrice);
                    priceRow.LastSize  = stockInfo.TradeVolume;
                    priceRow.Volume    = Convert.ToDecimal(stockInfo.TotalVolume);
                    priceRow.VolumeWeightedAveragePrice = (Convert.ToDecimal(stockInfo.LastPrice) + Convert.ToDecimal(stockInfo.OpenPrice)) / 2;
                    priceRow.OpenPrice  = Convert.ToDecimal(stockInfo.OpenPrice);
                    priceRow.LowPrice   = Convert.ToDecimal(stockInfo.LowPrice);
                    priceRow.HighPrice  = Convert.ToDecimal(stockInfo.HighPrice);
                    priceRow.ClosePrice = Convert.ToDecimal(stockInfo.PreviousPrice);

                    // increment the RowVersion so the client notices!!!
                    priceRow.RowVersion = ServerMarketData.RowVersion.Increment();

                    // commit the changes
                    priceRow.AcceptChanges();
                }
            }
            catch (Exception exception)
            {
                String msg = String.Format("{0}, {1}", exception.Message, exception.StackTrace);

                // Write the error and stack trace out to the debug listener
                //Debug.WriteLine(msg);
                MarkThree.EventLog.Warning(msg);
            }
            finally
            {
                // Release the global tables.
                if (ServerMarketData.EquityLock.IsReaderLockHeld)
                {
                    ServerMarketData.EquityLock.ReleaseReaderLock();
                }
                if (ServerMarketData.PriceLock.IsWriterLockHeld)
                {
                    ServerMarketData.PriceLock.ReleaseWriterLock();
                }
                if (ServerMarketData.SecurityLock.IsReaderLockHeld)
                {
                    ServerMarketData.SecurityLock.ReleaseReaderLock();
                }
                Debug.Assert(!ServerMarketData.IsLocked);
            }
        }
Пример #10
0
        /// <summary>
        /// Generates random Price movements.
        /// </summary>
        private static void ExecutionThread(params object[] argument)
        {
            // Extract the thread arguments.  The simulator will execute orders placed with this broker.
            int brokerId = (int)argument[0];

            // Continually execute trades from the local order book when they exist.
            while (true)
            {
                // Wait until there is something in the order book to execute.
                Broker.orderBookEvent.WaitOne();

                // These parameters are used to create the filled execution.
                int      blockOrderId   = 0;
                decimal  quantity       = 0.0M;
                decimal  price          = 0.0M;
                DateTime tradeDate      = DateTime.MinValue;
                DateTime settlementDate = DateTime.MinValue;

                // This will insure that we survive any single error on a random execution.
                try
                {
                    // Lock the Order Book.
                    Broker.orderBookLock.AcquireWriterLock(CommonTimeout.LockWait);

                    // Lock the tables.
                    Debug.Assert(!ServerMarketData.AreLocksHeld);
                    ServerMarketData.DebtLock.AcquireReaderLock(Timeout.Infinite);
                    ServerMarketData.ExecutionLock.AcquireWriterLock(Timeout.Infinite);
                    ServerMarketData.EquityLock.AcquireReaderLock(Timeout.Infinite);
                    ServerMarketData.HolidayLock.AcquireReaderLock(Timeout.Infinite);
                    ServerMarketData.PriceLock.AcquireReaderLock(Timeout.Infinite);
                    ServerMarketData.SecurityLock.AcquireReaderLock(Timeout.Infinite);

                    // Now that the tables are locked, the trade and settlement dates can be calcualted.
                    tradeDate      = Trading.TradeDate(0, 0, DateTime.Now);
                    settlementDate = Trading.SettlementDate(0, 0, tradeDate);

                    // Pick a random order to fill.
                    if (Broker.orderBook.Order.Rows.Count > 0)
                    {
                        int orderIndex = Random.Next(0, Broker.orderBook.Order.Rows.Count);
                        OrderBook.OrderRow orderRow = Broker.orderBook.Order[orderIndex];
                        blockOrderId = orderRow.BlockOrderId;

                        // Find the security associated with this placement.
                        ServerMarketData.SecurityRow securityRow = ServerMarketData.Security.FindBySecurityId(orderRow.SecurityId);
                        if (securityRow == null)
                        {
                            continue;
                        }

                        // A settlement Price is required to find the Price of a security.  For many issues, the default can
                        // be found from the defaults.  If a settlement currency isn't available, this issue can't be executed.
                        object settlementId = null;
                        foreach (ServerMarketData.DebtRow debtsRow in securityRow.GetDebtRowsByFKSecurityDebtDebtId())
                        {
                            settlementId = debtsRow.SettlementId;
                        }
                        foreach (ServerMarketData.EquityRow equityRow in securityRow.GetEquityRowsByFKSecurityEquityEquityId())
                        {
                            settlementId = equityRow.SettlementId;
                        }
                        if (settlementId == null)
                        {
                            continue;
                        }

                        // Simulate an executed quantity for this order.
                        decimal quantityLeaves = orderRow.QuantityOrdered - orderRow.QuantityExecuted;
                        if (quantityLeaves >= 100.0M)
                        {
                            quantity = Random.Next(100, Convert.ToInt32((quantityLeaves > maxExecution) ? maxExecution : quantityLeaves));
                            quantity = Math.Round(quantity / 100.0M) * 100.0M;
                        }

                        // When the quantity is zero, the order has been filled and can be removed from the local order book.  When
                        // the book is empty, then this thread can be paused until a new order is generated from a new placement.
                        // In either event, when there are no shares in the order book, there can be no executions.  When there's
                        // nothing to execute, delete the order and go look for another order to fill.
                        if (quantity == 0.0M)
                        {
                            orderRow.Delete();
                            orderRow.AcceptChanges();
                            if (orderBook.Order.Rows.Count == 0)
                            {
                                Broker.orderBookEvent.Reset();
                            }
                            continue;
                        }

                        // Update the amount executed on this order.
                        orderRow.QuantityExecuted += quantity;

                        // Select a Price for the execution.
                        ServerMarketData.PriceRow priceRow = ServerMarketData.Price.FindBySecurityIdCurrencyId(securityRow.SecurityId,
                                                                                                               (int)settlementId);
                        if (priceRow != null)
                        {
                            price = priceRow.LastPrice;
                        }
                    }
                }
                catch (Exception exception)
                {
                    // Display the error.
                    Debug.WriteLine(exception.Message);
                }
                finally
                {
                    // Release the order book.
                    if (Broker.orderBookLock.IsWriterLockHeld)
                    {
                        Broker.orderBookLock.ReleaseWriterLock();
                    }

                    // Release the tables.
                    if (ServerMarketData.DebtLock.IsReaderLockHeld)
                    {
                        ServerMarketData.DebtLock.ReleaseReaderLock();
                    }
                    if (ServerMarketData.EquityLock.IsReaderLockHeld)
                    {
                        ServerMarketData.EquityLock.ReleaseReaderLock();
                    }
                    if (ServerMarketData.ExecutionLock.IsWriterLockHeld)
                    {
                        ServerMarketData.ExecutionLock.ReleaseWriterLock();
                    }
                    if (ServerMarketData.HolidayLock.IsReaderLockHeld)
                    {
                        ServerMarketData.HolidayLock.ReleaseReaderLock();
                    }
                    if (ServerMarketData.PriceLock.IsReaderLockHeld)
                    {
                        ServerMarketData.PriceLock.ReleaseReaderLock();
                    }
                    if (ServerMarketData.SecurityLock.IsReaderLockHeld)
                    {
                        ServerMarketData.SecurityLock.ReleaseReaderLock();
                    }
                    Debug.Assert(!ServerMarketData.AreLocksHeld);
                }

                // Create an execution record for this fill.
                Transaction transaction = new Transaction();
                Shadows.WebService.Trading.Execution.Insert(transaction);
                transaction.BeginTransaction();
                try
                {
                    long rowVersion = 0L;
                    Shadows.WebService.Trading.Execution.Insert(transaction, blockOrderId, brokerId, ref rowVersion, quantity, price, null,
                                                                null, null, null, null, null, tradeDate, settlementDate);
                    transaction.Commit();
                }
                catch
                {
                    transaction.Rollback();
                }
                transaction.EndTransaction();

                // Sleep for a random amount of time between execution.
                Thread.Sleep(Random.Next(50, 300));
            }
        }
Пример #11
0
        /// <summary>Inserts a Price record.</summary>
        /// <param name="transaction">Commits or rejects a set of commands as a unit</param>
        /// <param name="askPrice">The value for the AskPrice column.</param>
        /// <param name="askSize">The value for the AskSize column.</param>
        /// <param name="bidPrice">The value for the BidPrice column.</param>
        /// <param name="bidSize">The value for the BidSize column.</param>
        /// <param name="closePrice">The value for the ClosePrice column.</param>
        /// <param name="currencyId">The value for the CurrencyId column.</param>
        /// <param name="highPrice">The value for the HighPrice column.</param>
        /// <param name="lastPrice">The value for the LastPrice column.</param>
        /// <param name="lastSize">The value for the LastSize column.</param>
        /// <param name="lowPrice">The value for the LowPrice column.</param>
        /// <param name="openPrice">The value for the OpenPrice column.</param>
        /// <param name="priceChange">The value for the PriceChange column.</param>
        /// <param name="securityId">The value for the SecurityId column.</param>
        /// <param name="volume">The value for the Volume column.</param>
        /// <param name="volumeWeightedAveragePrice">The value for the VolumeWeightedAveragePrice column.</param>
        public static void Insert(
            AdoTransaction adoTransaction,
            SqlTransaction sqlTransaction,
            ref long rowVersion,
            object askPrice,
            object askSize,
            object bidPrice,
            object bidSize,
            object closePrice,
            int currencyId,
            object highPrice,
            object lastPrice,
            object lastSize,
            object lowPrice,
            object openPrice,
            object priceChange,
            int securityId,
            object volume,
            object volumeWeightedAveragePrice)
        {
            // Accessor for the Price Table.
            ServerMarketData.PriceDataTable priceTable = ServerMarketData.Price;
            // Apply Defaults
            if ((askPrice == null))
            {
                askPrice = 0.0m;
            }
            if ((askSize == null))
            {
                askSize = 0.0m;
            }
            if ((bidPrice == null))
            {
                bidPrice = 0.0m;
            }
            if ((bidSize == null))
            {
                bidSize = 0.0m;
            }
            if ((closePrice == null))
            {
                closePrice = 0.0m;
            }
            if ((highPrice == null))
            {
                highPrice = 0.0m;
            }
            if ((lastPrice == null))
            {
                lastPrice = 0.0m;
            }
            if ((lastSize == null))
            {
                lastSize = 0.0m;
            }
            if ((lowPrice == null))
            {
                lowPrice = 0.0m;
            }
            if ((openPrice == null))
            {
                openPrice = 0.0m;
            }
            if ((priceChange == null))
            {
                priceChange = 0.0m;
            }
            if ((volume == null))
            {
                volume = 0.0m;
            }
            if ((volumeWeightedAveragePrice == null))
            {
                volumeWeightedAveragePrice = 0.0m;
            }
            // Increment the row version
            rowVersion = ServerMarketData.RowVersion.Increment();
            // Insert the record into the ADO database.
            ServerMarketData.PriceRow priceRow = priceTable.NewPriceRow();
            priceRow[priceTable.RowVersionColumn]  = rowVersion;
            priceRow[priceTable.AskPriceColumn]    = askPrice;
            priceRow[priceTable.AskSizeColumn]     = askSize;
            priceRow[priceTable.BidPriceColumn]    = bidPrice;
            priceRow[priceTable.BidSizeColumn]     = bidSize;
            priceRow[priceTable.ClosePriceColumn]  = closePrice;
            priceRow[priceTable.CurrencyIdColumn]  = currencyId;
            priceRow[priceTable.HighPriceColumn]   = highPrice;
            priceRow[priceTable.LastPriceColumn]   = lastPrice;
            priceRow[priceTable.LastSizeColumn]    = lastSize;
            priceRow[priceTable.LowPriceColumn]    = lowPrice;
            priceRow[priceTable.OpenPriceColumn]   = openPrice;
            priceRow[priceTable.PriceChangeColumn] = priceChange;
            priceRow[priceTable.SecurityIdColumn]  = securityId;
            priceRow[priceTable.VolumeColumn]      = volume;
            priceRow[priceTable.VolumeWeightedAveragePriceColumn] = volumeWeightedAveragePrice;
            priceTable.AddPriceRow(priceRow);
            adoTransaction.DataRows.Add(priceRow);
            // Insert the record into the SQL database.
            SqlCommand sqlCommand = new SqlCommand(@"insert ""Price"" (""rowVersion"",""AskPrice"",""AskSize"",""BidPrice"",""BidSize"",""ClosePrice"",""CurrencyId"",""HighPrice"",""LastPrice"",""LastSize"",""LowPrice"",""OpenPrice"",""SecurityId"",""Volume"",""VolumeWeightedAveragePrice"") values (@rowVersion,@askPrice,@askSize,@bidPrice,@bidSize,@closePrice,@currencyId,@highPrice,@lastPrice,@lastSize,@lowPrice,@openPrice,@securityId,@volume,@volumeWeightedAveragePrice)");

            sqlCommand.Connection  = sqlTransaction.Connection;
            sqlCommand.Transaction = sqlTransaction;
            sqlCommand.Parameters.Add(new SqlParameter("@rowVersion", SqlDbType.BigInt, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, rowVersion));
            sqlCommand.Parameters.Add(new SqlParameter("@askPrice", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, askPrice));
            sqlCommand.Parameters.Add(new SqlParameter("@askSize", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, askSize));
            sqlCommand.Parameters.Add(new SqlParameter("@bidPrice", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, bidPrice));
            sqlCommand.Parameters.Add(new SqlParameter("@bidSize", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, bidSize));
            sqlCommand.Parameters.Add(new SqlParameter("@closePrice", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, closePrice));
            sqlCommand.Parameters.Add(new SqlParameter("@currencyId", SqlDbType.Int, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, currencyId));
            sqlCommand.Parameters.Add(new SqlParameter("@highPrice", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, highPrice));
            sqlCommand.Parameters.Add(new SqlParameter("@lastPrice", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, lastPrice));
            sqlCommand.Parameters.Add(new SqlParameter("@lastSize", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, lastSize));
            sqlCommand.Parameters.Add(new SqlParameter("@lowPrice", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, lowPrice));
            sqlCommand.Parameters.Add(new SqlParameter("@openPrice", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, openPrice));
            sqlCommand.Parameters.Add(new SqlParameter("@securityId", SqlDbType.Int, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, securityId));
            sqlCommand.Parameters.Add(new SqlParameter("@volume", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, volume));
            sqlCommand.Parameters.Add(new SqlParameter("@volumeWeightedAveragePrice", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, volumeWeightedAveragePrice));
            sqlCommand.ExecuteNonQuery();
        }
Пример #12
0
        /// <summary>Updates a Price record.</summary>
        /// <param name="transaction">Commits or rejects a set of commands as a unit</param>
        /// <param name="rowVersion">The version number of the row</param>
        /// <param name="askPrice">The value for the AskPrice column.</param>
        /// <param name="askSize">The value for the AskSize column.</param>
        /// <param name="bidPrice">The value for the BidPrice column.</param>
        /// <param name="bidSize">The value for the BidSize column.</param>
        /// <param name="closePrice">The value for the ClosePrice column.</param>
        /// <param name="currencyId">The value for the CurrencyId column.</param>
        /// <param name="highPrice">The value for the HighPrice column.</param>
        /// <param name="lastPrice">The value for the LastPrice column.</param>
        /// <param name="lastSize">The value for the LastSize column.</param>
        /// <param name="lowPrice">The value for the LowPrice column.</param>
        /// <param name="openPrice">The value for the OpenPrice column.</param>
        /// <param name="priceChange">The value for the PriceChange column.</param>
        /// <param name="securityId">The value for the SecurityId column.</param>
        /// <param name="volume">The value for the Volume column.</param>
        /// <param name="volumeWeightedAveragePrice">The value for the VolumeWeightedAveragePrice column.</param>
        public static void Update(
            AdoTransaction adoTransaction,
            SqlTransaction sqlTransaction,
            ref long rowVersion,
            object askPrice,
            object askSize,
            object bidPrice,
            object bidSize,
            object closePrice,
            object currencyId,
            object highPrice,
            object lastPrice,
            object lastSize,
            object lowPrice,
            object openPrice,
            object priceChange,
            int securityId,
            object volume,
            object volumeWeightedAveragePrice)
        {
            // Accessor for the Price Table.
            ServerMarketData.PriceDataTable priceTable = ServerMarketData.Price;
            // Rule #1: Make sure the record exists before updating it.
            ServerMarketData.PriceRow priceRow = priceTable.FindBySecurityId(securityId);
            if ((priceRow == null))
            {
                throw new Exception(string.Format("The Price table does not have an element identified by {0}", securityId));
            }
            // Rule #2: Optimistic Concurrency Check
            if ((priceRow.RowVersion != rowVersion))
            {
                throw new System.Exception("This record is busy.  Please try again later.");
            }
            // Apply Defaults
            if ((askPrice == null))
            {
                askPrice = priceRow[priceTable.AskPriceColumn];
            }
            if ((askSize == null))
            {
                askSize = priceRow[priceTable.AskSizeColumn];
            }
            if ((bidPrice == null))
            {
                bidPrice = priceRow[priceTable.BidPriceColumn];
            }
            if ((bidSize == null))
            {
                bidSize = priceRow[priceTable.BidSizeColumn];
            }
            if ((closePrice == null))
            {
                closePrice = priceRow[priceTable.ClosePriceColumn];
            }
            if ((currencyId == null))
            {
                currencyId = priceRow[priceTable.CurrencyIdColumn];
            }
            if ((highPrice == null))
            {
                highPrice = priceRow[priceTable.HighPriceColumn];
            }
            if ((lastPrice == null))
            {
                lastPrice = priceRow[priceTable.LastPriceColumn];
            }
            if ((lastSize == null))
            {
                lastSize = priceRow[priceTable.LastSizeColumn];
            }
            if ((lowPrice == null))
            {
                lowPrice = priceRow[priceTable.LowPriceColumn];
            }
            if ((openPrice == null))
            {
                openPrice = priceRow[priceTable.OpenPriceColumn];
            }
            if ((priceChange == null))
            {
                priceChange = priceRow[priceTable.PriceChangeColumn];
            }
            if ((volume == null))
            {
                volume = priceRow[priceTable.VolumeColumn];
            }
            if ((volumeWeightedAveragePrice == null))
            {
                volumeWeightedAveragePrice = priceRow[priceTable.VolumeWeightedAveragePriceColumn];
            }
            // Increment the row version
            rowVersion = ServerMarketData.RowVersion.Increment();
            // Update the record in the ADO database.
            priceRow[priceTable.RowVersionColumn]  = rowVersion;
            priceRow[priceTable.AskPriceColumn]    = askPrice;
            priceRow[priceTable.AskSizeColumn]     = askSize;
            priceRow[priceTable.BidPriceColumn]    = bidPrice;
            priceRow[priceTable.BidSizeColumn]     = bidSize;
            priceRow[priceTable.ClosePriceColumn]  = closePrice;
            priceRow[priceTable.CurrencyIdColumn]  = currencyId;
            priceRow[priceTable.HighPriceColumn]   = highPrice;
            priceRow[priceTable.LastPriceColumn]   = lastPrice;
            priceRow[priceTable.LastSizeColumn]    = lastSize;
            priceRow[priceTable.LowPriceColumn]    = lowPrice;
            priceRow[priceTable.OpenPriceColumn]   = openPrice;
            priceRow[priceTable.PriceChangeColumn] = priceChange;
            priceRow[priceTable.VolumeColumn]      = volume;
            priceRow[priceTable.VolumeWeightedAveragePriceColumn] = volumeWeightedAveragePrice;
            adoTransaction.DataRows.Add(priceRow);
            // Update the record in the SQL database.
            SqlCommand sqlCommand = new SqlCommand(@"update ""Price"" set ""RowVersion""=@rowVersion,""AskPrice""=@askPrice,""AskSize""=@askSize,""BidPrice""=@bidPrice,""BidSize""=@bidSize,""ClosePrice""=@closePrice,""CurrencyId""=@currencyId,""HighPrice""=@highPrice,""LastPrice""=@lastPrice,""LastSize""=@lastSize,""LowPrice""=@lowPrice,""OpenPrice""=@openPrice,""Volume""=@volume,""VolumeWeightedAveragePrice""=@volumeWeightedAveragePrice where ""SecurityId""=@securityId");

            sqlCommand.Connection  = sqlTransaction.Connection;
            sqlCommand.Transaction = sqlTransaction;
            sqlCommand.Parameters.Add(new SqlParameter("@rowVersion", SqlDbType.BigInt, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, rowVersion));
            sqlCommand.Parameters.Add(new SqlParameter("@askPrice", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, askPrice));
            sqlCommand.Parameters.Add(new SqlParameter("@askSize", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, askSize));
            sqlCommand.Parameters.Add(new SqlParameter("@bidPrice", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, bidPrice));
            sqlCommand.Parameters.Add(new SqlParameter("@bidSize", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, bidSize));
            sqlCommand.Parameters.Add(new SqlParameter("@closePrice", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, closePrice));
            sqlCommand.Parameters.Add(new SqlParameter("@currencyId", SqlDbType.Int, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, currencyId));
            sqlCommand.Parameters.Add(new SqlParameter("@highPrice", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, highPrice));
            sqlCommand.Parameters.Add(new SqlParameter("@lastPrice", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, lastPrice));
            sqlCommand.Parameters.Add(new SqlParameter("@lastSize", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, lastSize));
            sqlCommand.Parameters.Add(new SqlParameter("@lowPrice", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, lowPrice));
            sqlCommand.Parameters.Add(new SqlParameter("@openPrice", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, openPrice));
            sqlCommand.Parameters.Add(new SqlParameter("@securityId", SqlDbType.Int, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, securityId));
            sqlCommand.Parameters.Add(new SqlParameter("@volume", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, volume));
            sqlCommand.Parameters.Add(new SqlParameter("@volumeWeightedAveragePrice", SqlDbType.Decimal, 0, ParameterDirection.Input, false, 0, 0, null, DataRowVersion.Current, volumeWeightedAveragePrice));
            // Update the record in the SQL database.
            sqlCommand.ExecuteNonQuery();
        }