/// <summary> /// Chooses or creates a model for the appraisal. /// </summary> /// <param name="accountId">The account used to select a model.</param> public static int SelectModel(int accountId) { // The logic in this method will determine if a temporary model is needed and built it. If a temporary model is // required, it will be built using this command batch. In all cases, the appropriate model for the given account will // be returned to the caller. In some cases, a model will be constructed on the fly from the existing values in the // account. These temporary models will use most of the position and trading tables ModelBatch modelBatch = null; try { // Lock the tables Debug.Assert(!ClientMarketData.AreLocksHeld); ClientMarketData.AccountLock.AcquireReaderLock(CommonTimeout.LockWait); ClientMarketData.AllocationLock.AcquireReaderLock(CommonTimeout.LockWait); ClientMarketData.CurrencyLock.AcquireReaderLock(CommonTimeout.LockWait); ClientMarketData.DebtLock.AcquireReaderLock(CommonTimeout.LockWait); ClientMarketData.EquityLock.AcquireReaderLock(CommonTimeout.LockWait); ClientMarketData.ModelLock.AcquireWriterLock(CommonTimeout.LockWait); ClientMarketData.SectorTargetLock.AcquireWriterLock(CommonTimeout.LockWait); ClientMarketData.PositionTargetLock.AcquireWriterLock(CommonTimeout.LockWait); ClientMarketData.ObjectLock.AcquireWriterLock(CommonTimeout.LockWait); ClientMarketData.ObjectTreeLock.AcquireWriterLock(CommonTimeout.LockWait); ClientMarketData.OrderLock.AcquireReaderLock(CommonTimeout.LockWait); ClientMarketData.PriceLock.AcquireReaderLock(CommonTimeout.LockWait); ClientMarketData.ProposedOrderLock.AcquireReaderLock(CommonTimeout.LockWait); ClientMarketData.SchemeLock.AcquireReaderLock(CommonTimeout.LockWait); ClientMarketData.SectorLock.AcquireReaderLock(CommonTimeout.LockWait); ClientMarketData.SecurityLock.AcquireReaderLock(CommonTimeout.LockWait); ClientMarketData.TaxLotLock.AcquireReaderLock(CommonTimeout.LockWait); ClientMarketData.TransactionTypeLock.AcquireReaderLock(CommonTimeout.LockWait); // Find the account record that is being opened. ClientMarketData.AccountRow accountRow = ClientMarketData.Account.FindByAccountId(accountId); if (accountRow == null) { throw new Exception(String.Format("Account {0} has been deleted", accountId)); } // The objective is to find out whether a 'Self' model must be created from the existing positions, or whether a // an empty or a copy of a model is required to view an account appraisal. The first test is to see whether any model // has been assigned to the account. if (accountRow.IsModelIdNull()) { // This will create an empty position model for the appraisal. modelBatch = Models.CreateEmptyModel(accountRow); } else { // At this point, a model has been assigned to the account. Get the model and find out if a temporary copy // needs to be made. ClientMarketData.ModelRow modelRow = ClientMarketData.Model.FindByModelId(accountRow.ModelId); if (modelRow == null) { throw new Exception(String.Format("Model {0} has been deleted", accountRow.ModelId)); } // A 'self' model is one that requires a calculation of the current positions. if (!modelRow.SectorSelf && !modelRow.SecuritySelf) { // Currently, the existing model is used on an appraisal. Any changes to the model in the appraisal view // will be stored in the persistent model. It may be useful sometime in the future to make a copy of the // model and prompt the user to save it when the appraisal is closed. return(modelRow.ModelId); } else { // Make sure that the account has been assigned a scheme before attempting to build a model from it. if (accountRow.IsSchemeIdNull()) { throw new Exception(String.Format("No scheme has been assigned to account {0}.", accountRow)); } // If the account has a default scheme, make sure it still exists. ClientMarketData.SchemeRow schemeRow = ClientMarketData.Scheme.FindBySchemeId(accountRow.SchemeId); if (schemeRow == null) { throw new ArgumentException("This scheme has been deleted", accountRow.SchemeId.ToString()); } // Create a model based on the current sector totals. if (modelRow.SectorSelf) { modelBatch = Models.CreateSectorSelfModel(accountRow, schemeRow); } // Create a model based on the current position totals. if (modelRow.SecuritySelf) { modelBatch = Models.CreatePositionSelfModel(accountRow, schemeRow); } } } } finally { // Release the table locks. if (ClientMarketData.AccountLock.IsReaderLockHeld) { ClientMarketData.AccountLock.ReleaseReaderLock(); } if (ClientMarketData.AllocationLock.IsReaderLockHeld) { ClientMarketData.AllocationLock.ReleaseReaderLock(); } if (ClientMarketData.CurrencyLock.IsReaderLockHeld) { ClientMarketData.CurrencyLock.ReleaseReaderLock(); } if (ClientMarketData.DebtLock.IsReaderLockHeld) { ClientMarketData.DebtLock.ReleaseReaderLock(); } if (ClientMarketData.EquityLock.IsReaderLockHeld) { ClientMarketData.EquityLock.ReleaseReaderLock(); } if (ClientMarketData.ModelLock.IsWriterLockHeld) { ClientMarketData.ModelLock.ReleaseWriterLock(); } if (ClientMarketData.SectorTargetLock.IsWriterLockHeld) { ClientMarketData.SectorTargetLock.ReleaseWriterLock(); } if (ClientMarketData.PositionTargetLock.IsWriterLockHeld) { ClientMarketData.PositionTargetLock.ReleaseWriterLock(); } if (ClientMarketData.ObjectLock.IsWriterLockHeld) { ClientMarketData.ObjectLock.ReleaseWriterLock(); } if (ClientMarketData.ObjectTreeLock.IsWriterLockHeld) { ClientMarketData.ObjectTreeLock.ReleaseWriterLock(); } if (ClientMarketData.OrderLock.IsReaderLockHeld) { ClientMarketData.OrderLock.ReleaseReaderLock(); } if (ClientMarketData.PriceLock.IsReaderLockHeld) { ClientMarketData.PriceLock.ReleaseReaderLock(); } if (ClientMarketData.ProposedOrderLock.IsReaderLockHeld) { ClientMarketData.ProposedOrderLock.ReleaseReaderLock(); } if (ClientMarketData.SchemeLock.IsReaderLockHeld) { ClientMarketData.SchemeLock.ReleaseReaderLock(); } if (ClientMarketData.SectorLock.IsReaderLockHeld) { ClientMarketData.SectorLock.ReleaseReaderLock(); } if (ClientMarketData.SecurityLock.IsReaderLockHeld) { ClientMarketData.SecurityLock.ReleaseReaderLock(); } if (ClientMarketData.TaxLotLock.IsReaderLockHeld) { ClientMarketData.TaxLotLock.ReleaseReaderLock(); } if (ClientMarketData.TransactionTypeLock.IsReaderLockHeld) { ClientMarketData.TransactionTypeLock.ReleaseReaderLock(); } Debug.Assert(!ClientMarketData.AreLocksHeld); } // At this point, a batch is ready to be sent that will create the model and populate it with target values. The data // structure is an overloaded version of the 'RemoteBatch' class. The 'ModelBatch' contains a member which references // the 'modelId' return value from the creation of the model. This value will be returned to the caller as a reference // to the temporary model. ClientMarketData.Send(modelBatch); // Rethrow a generic error message for the failed model. if (modelBatch.HasExceptions) { throw new Exception("Can't create model."); } // Return the model identifier generated by the server. return((int)modelBatch.ModelIdParameter.Value); }