コード例 #1
0
        /// <summary>
        /// Constructs a well formed, but empty, AppraisalDocument.
        /// </summary>
        public AppraisalDocument()
        {
            // Initialize the members.
            this.accountRow = null;
            this.modelRow   = null;

            // Create the root element and add it to the document.
            this.AppendChild(new AppraisalElement(this));
        }
コード例 #2
0
ファイル: Account.cs プロジェクト: DonaldAirey/quasar
        private void Initialize(ClientMarketData.AccountRow accountRow)
        {
            // Initialize the base class.
            base.Initialize(accountRow.ObjectRow);

            // Initialize the record from the data model.
            this.accountType  = (AccountType)accountRow.AccountTypeCode;
            this.baseCurrency = Security.Make(accountRow.SecurityRow);
            this.mnemonic     = accountRow.Mnemonic;
        }
コード例 #3
0
        /// <summary>
        /// Returns a set of orders that will achieve the targets specified by the model.
        /// </summary>
        /// <param name="accountRow">The account or parent account to be rebalanced.</param>
        /// <param name="modelRow">The target percentages to use for rebalancing.</param>
        /// <returns>A Dataset of new, updated and deleted orders.</returns>
        public static RemoteBatch Rebalance(ClientMarketData.AccountRow accountRow, ClientMarketData.ModelRow modelRow)
        {
            // The orders to insert, update and delete orders to achieve the target percentages will be put in this DataSet.
            RemoteBatch       remoteBatch       = new RemoteBatch();
            RemoteTransaction remoteTransaction = remoteBatch.Transactions.Add();

            // Rebalance the parent account and all it's children.
            SelectedSecurity.RecurseAccounts(remoteBatch, remoteTransaction, accountRow, modelRow);

            // This is the sucessful result of rebalancing.
            return(remoteBatch);
        }
コード例 #4
0
ファイル: Account.cs プロジェクト: DonaldAirey/quasar
        /// <summary>
        /// Initializes a Account.
        /// </summary>
        /// <param name="configurationId">Defines which external fields are used to identify an object.</param>
        /// <param name="accountId">The account identifier.</param>
        /// <returns>A account record, null if the identifier doesn't exist.</returns>
        protected override void Initialize(int accountId)
        {
            // Use the specified configuration to find the internal account identifier.
            ClientMarketData.AccountRow accountRow = ClientMarketData.Account.FindByAccountId(accountId);
            if (accountRow == null)
            {
                throw new Exception(String.Format("Account {0} doesn't exist", accountId));
            }

            // Initialize the base class.
            base.Initialize(accountId);

            // Initialize the record from the data model.
            this.accountType  = (AccountType)accountRow.AccountTypeCode;
            this.baseCurrency = Security.Make(accountRow.CurrencyId);
            this.mnemonic     = accountRow.IsMnemonicNull() ? string.Empty : accountRow.Mnemonic;
        }
コード例 #5
0
        /// <summary>
        /// Returns a set of orders that will achieve the targets specified by the model.
        /// </summary>
        /// <param name="accountRow">The account or parent account to be rebalanced.</param>
        /// <param name="modelRow">The target percentages to use for rebalancing.</param>
        /// <returns>A Dataset of new, updated and deleted orders.</returns>
        public static RemoteBatch Rebalance(ClientMarketData.AccountRow accountRow, ClientMarketData.ModelRow modelRow)
        {
            // Make sure the scheme still exists in the in-memory database.  We need it to rebalance the appraisal.
            ClientMarketData.SchemeRow schemeRow;
            if ((schemeRow = ClientMarketData.Scheme.FindBySchemeId(modelRow.SchemeId)) == null)
            {
                throw new ArgumentException("Scheme doesn't exist in the ClientMarketData", modelRow.SchemeId.ToString());
            }

            // The final result of this method is a command batch that can be sent to the server.
            RemoteBatch       remoteBatch       = new RemoteBatch();
            RemoteTransaction remoteTransaction = remoteBatch.Transactions.Add();

            // Rebalance the parent account and all it's children.
            RecurseAccounts(remoteBatch, remoteTransaction, accountRow, modelRow, schemeRow);

            // The sucessful result of rebalancing.
            return(remoteBatch);
        }
コード例 #6
0
        /// <summary>
        /// Creates a common element for the AppraisalDocument.
        /// </summary>
        /// <param name="name">The local name of the node.</param>
        /// <param name="appraisalDocument">The parent document.</param>
        public AppraisalElement(AppraisalDocument appraisalDocument) : base("Appraisal", appraisalDocument)
        {
            // The top level account information is used to add the user data to the top level of the appraisal.
            ClientMarketData.AccountRow accountRow = appraisalDocument.AccountRow;

            // Add any top-level data associated with this account (such as aggregate risk, account level quantitative
            // calculations, etc.
            if (accountRow != null)
            {
                if (!accountRow.IsUserData0Null())
                {
                    AddAttribute("UserData0", accountRow.UserData0.ToString());
                }
                if (!accountRow.IsUserData1Null())
                {
                    AddAttribute("UserData1", accountRow.UserData1.ToString());
                }
                if (!accountRow.IsUserData2Null())
                {
                    AddAttribute("UserData2", accountRow.UserData2.ToString());
                }
                if (!accountRow.IsUserData3Null())
                {
                    AddAttribute("UserData3", accountRow.UserData3.ToString());
                }
                if (!accountRow.IsUserData4Null())
                {
                    AddAttribute("UserData4", accountRow.UserData4.ToString());
                }
                if (!accountRow.IsUserData5Null())
                {
                    AddAttribute("UserData5", accountRow.UserData5.ToString());
                }
                if (!accountRow.IsUserData6Null())
                {
                    AddAttribute("UserData6", accountRow.UserData6.ToString());
                }
                if (!accountRow.IsUserData7Null())
                {
                    AddAttribute("UserData7", accountRow.UserData7.ToString());
                }
            }
        }
コード例 #7
0
        /// <summary>
        /// Returns a set of orders that will achieve the targets specified by the model.
        /// </summary>
        /// <param name="accountRow">The account or parent account to be rebalanced.</param>
        /// <param name="modelRow">The target percentages to use for rebalancing.</param>
        /// <returns>A Dataset of new, updated and deleted orders.</returns>
        public static RemoteBatch Rebalance(ClientMarketData.AccountRow accountRow, ClientMarketData.ModelRow modelRow)
        {
            // The orders to insert, update and delete orders to achieve the target percentages will be put in this
            // DataSet.
            RemoteBatch       remoteBatch       = new RemoteBatch();
            RemoteTransaction remoteTransaction = remoteBatch.Transactions.Add();

            // The outline of the appraisal will be needed to make calculations based on a position, that is a security,
            // account, position type combination.  Note that we're also including all the model securities in the
            // outline.  This triggers a rebalance if a security exists in the model, but doesn't exist yet in the
            // appraisal.
            AppraisalSet appraisalSet = new Appraisal(accountRow, modelRow, true);

            // Rebalance the parent account and all it's children.
            Security.RecurseAccounts(remoteBatch, remoteTransaction, appraisalSet, accountRow, modelRow);

            // This is the sucessful result of rebalancing.
            return(remoteBatch);
        }
コード例 #8
0
        /// <summary>
        /// Recursively creates instructions to delete proposed order of the given position.
        /// </summary>
        /// <param name="remoteBatch">The object type containing the method to delete the order relationship.</param>
        /// <param name="remoteTransaction">Groups several commands into a unit for execution.</param>
        /// <param name="accountRow">An account record, used to select proposed order records.</param>
        private static void Delete(RemoteBatch remoteBatch, RemoteTransaction remoteTransaction,
                                   ClientMarketData.AccountRow accountRow, ClientMarketData.SecurityRow securityRow, int positionTypeCode)
        {
            // Run through each of the proposed orders in this account and create a record to have them deleted.
            object[] key = new object[] { accountRow.AccountId, securityRow.SecurityId, positionTypeCode };
            foreach (DataRowView dataRowView in
                     MarketData.ProposedOrder.UKProposedOrderAccountIdSecurityIdPositionTypeCode.FindRows(key))
            {
                // This is used to reference the current proposed order that matches the position criteria.
                ClientMarketData.ProposedOrderRow proposedOrderRow = (ClientMarketData.ProposedOrderRow)dataRowView.Row;

                // Child proposed orders aren't deleted directly, they can only be deleted when the parent is deleted.  The best
                // example of this is cash.  An account can have both child cash (related to an equity trade) or parent cash (cash
                // added directly to the account with no offsetting trade).  If a reqest is made to delete cash, only the parent
                // cash should be deleted.  The account will appear to have a cash balance until the equity attached to the child
                // cash is deleted.
                if (!Relationship.IsChildProposedOrder(proposedOrderRow))
                {
                    Delete(remoteBatch, remoteTransaction, proposedOrderRow);
                }
            }
        }
コード例 #9
0
ファイル: Models.cs プロジェクト: DonaldAirey/quasar
        /// <summary>
        /// Creates a temporary, empty model portfolio.
        /// </summary>
        /// <param name="accountRow">An account record.</param>
        /// <returns>A batch of commands that will create the empty model.</returns>
        private static ModelBatch CreateEmptyModel(ClientMarketData.AccountRow accountRow)
        {
            // Create the batch and fill it in with the assembly and type needed for this function.
            ModelBatch     modelBatch     = new ModelBatch();
            RemoteAssembly remoteAssembly = modelBatch.Assemblies.Add("Service.Core");
            RemoteType     remoteType     = remoteAssembly.Types.Add("Shadows.WebService.Core.Model");

            // This method will insert a generic, empty, security level model.
            RemoteMethod insertModel = remoteType.Methods.Add("Insert");

            insertModel.Parameters.Add("modelId", DataType.Int, Direction.ReturnValue);
            insertModel.Parameters.Add("rowVersion", DataType.Long, Direction.Output);
            insertModel.Parameters.Add("modelTypeCode", ModelType.Security);
            insertModel.Parameters.Add("name", "Untitled");
            insertModel.Parameters.Add("schemeId", accountRow.SchemeId);
            insertModel.Parameters.Add("algorithmId", Algorithm.SecurityRebalancer);
            insertModel.Parameters.Add("temporary", true);

            // Save the reference to the 'modelId' return parameter.
            modelBatch.ModelIdParameter = insertModel.Parameters["modelId"];

            // This batch will create an empty, position based model.
            return(modelBatch);
        }
コード例 #10
0
        /// <summary>
        /// Fills the OrderForm table with instructions to create, delete or update proposed orders.
        /// </summary>
        /// <param name="accountId">Identifiers the destination account of the proposed order.</param>
        /// <param name="securityId">Identifies the security being trade.</param>
        /// <param name="positionTypeCode">Identifies the long or short position of the trade.</param>
        /// <param name="settlementId"></param>
        /// <param name="proposedQuantity">The signed (relative) quantity of the trade.</param>
        public static void Create(RemoteBatch remoteBatch, RemoteTransaction remoteTransaction,
                                  ClientMarketData.AccountRow accountRow, ClientMarketData.SecurityRow securityRow, int positionTypeCode,
                                  decimal proposedQuantity)
        {
            // If the proposed quantity is to be zero, we'll delete all proposed orders for this position in the parent and
            // descendant accounts.  Otherwise, a command batch will be created to clear any child proposed orders and create or
            // update a proposed order for the parent account.
            if (proposedQuantity == 0.0M)
            {
                ProposedOrder.Delete(remoteBatch, remoteTransaction, accountRow, securityRow, positionTypeCode);
            }
            else
            {
                // The strategy here is to cycle through all the existing proposed orders looking for any that match the account
                // id, security id and position type of the new order.  If none is found, we create a new order. If one is found,
                // we modify it for the new quantity.  Any additional proposed orders are deleted.  This flag lets us know if any
                // existing proposed orders match the position attributes.
                bool firstTime = true;

                // Cycle through each of the proposed orders in the given account looking for a matching position.
                object[] key = new object[] { accountRow.AccountId, securityRow.SecurityId, positionTypeCode };
                foreach (DataRowView dataRowView in ClientMarketData.ProposedOrder.UKProposedOrderAccountIdSecurityIdPositionTypeCode.FindRows(key))
                {
                    // This is used to reference the current proposed order that matches the position criteria.
                    ClientMarketData.ProposedOrderRow parentProposedOrderRow = (ClientMarketData.ProposedOrderRow)dataRowView.Row;

                    // This check is provided for currency-like assets.  There may be many proposed orders for currency
                    // transactions that are used to settle other trades.  The user can also enter currency orders directly into
                    // the appraisal.  Any manual deposits or withdrawls should not impact settlement orders.  This check will skip
                    // any trade that is linked to another order.
                    if (Shadows.Quasar.Common.Relationship.IsChildProposedOrder(parentProposedOrderRow))
                    {
                        continue;
                    }

                    // Recycle the first proposed order that matches the position criteria.  Any additional proposed orders for the
                    // same account, security, position type will be deleted.
                    if (firstTime)
                    {
                        // Any proposed orders found after this one will be deleted.  This variable will also indicate that an
                        // existing proposed order was recycled.  After the loop is run on this position, a new order will be
                        // created if an existing order couldn't be recycled.
                        firstTime = false;

                        // Create the command to update this proposed order.
                        Update(remoteBatch, remoteTransaction, parentProposedOrderRow, proposedQuantity);
                    }
                    else
                    {
                        // Any order that isn't recycled is considered to be redundant.  That is, this order has been superceded by
                        // the recycled order.  Clearing any redundant orders makes the operation more intuitive: the user knows
                        // that the only order on the books is the one they entered.  They don't have to worry about artifacts from
                        // other operations.
                        Delete(remoteBatch, remoteTransaction, parentProposedOrderRow);
                    }
                }

                // This will create a new proposed order if an existing one couldn't be found above for recycling.
                if (firstTime == true)
                {
                    Insert(remoteBatch, remoteTransaction, accountRow, securityRow, positionTypeCode, proposedQuantity);
                }
            }
        }
コード例 #11
0
ファイル: Account.cs プロジェクト: DonaldAirey/quasar
        public bool Contains(Security security, int positionType)
        {
            try
            {
                // Lock the tables.
                Debug.Assert(!ClientMarketData.AreLocksHeld);
                ClientMarketData.AccountLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.AllocationLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.OrderLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.ProposedOrderLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.TaxLotLock.AcquireReaderLock(CommonTimeout.LockWait);

                ClientMarketData.AccountRow accountRow = ClientMarketData.Account.FindByAccountId(this.AccountId);

                foreach (ClientMarketData.TaxLotRow taxLotRow in accountRow.GetTaxLotRows())
                {
                    if (taxLotRow.SecurityId == security.SecurityId && taxLotRow.PositionTypeCode == positionType)
                    {
                        return(true);
                    }
                }

                foreach (ClientMarketData.ProposedOrderRow proposedOrderRow in accountRow.GetProposedOrderRows())
                {
                    if (proposedOrderRow.SecurityId == security.SecurityId && proposedOrderRow.PositionTypeCode == positionType)
                    {
                        return(true);
                    }
                }

                foreach (ClientMarketData.OrderRow orderRow in accountRow.GetOrderRows())
                {
                    if (orderRow.SecurityId == security.SecurityId && orderRow.PositionTypeCode == positionType)
                    {
                        return(true);
                    }
                }

                foreach (ClientMarketData.AllocationRow allocationRow in accountRow.GetAllocationRows())
                {
                    if (allocationRow.SecurityId == security.SecurityId && allocationRow.PositionTypeCode == positionType)
                    {
                        return(true);
                    }
                }

                return(false);
            }
            finally
            {
                // Release the table locks.
                if (ClientMarketData.AccountLock.IsReaderLockHeld)
                {
                    ClientMarketData.AccountLock.ReleaseReaderLock();
                }
                if (ClientMarketData.AllocationLock.IsReaderLockHeld)
                {
                    ClientMarketData.AllocationLock.ReleaseReaderLock();
                }
                if (ClientMarketData.OrderLock.IsReaderLockHeld)
                {
                    ClientMarketData.OrderLock.ReleaseReaderLock();
                }
                if (ClientMarketData.ProposedOrderLock.IsReaderLockHeld)
                {
                    ClientMarketData.ProposedOrderLock.ReleaseReaderLock();
                }
                if (ClientMarketData.TaxLotLock.IsReaderLockHeld)
                {
                    ClientMarketData.TaxLotLock.ReleaseReaderLock();
                }
                Debug.Assert(!ClientMarketData.AreLocksHeld);
            }
        }
コード例 #12
0
        /// <summary>
        /// Recursively calculates proposed orders for a sector.
        /// </summary>
        /// <param name="sector">Gives the current sector (sector) for the calculation.</param>
        private static void RecurseSectors(RemoteBatch remoteBatch, RemoteTransaction remoteTransaction,
                                           ClientMarketData.CurrencyRow currencyRow, ClientMarketData.ModelRow modelRow, AppraisalSet.ObjectRow driverObject,
                                           decimal actualSectorMarketValue, decimal targetSectorMarketValue)
        {
            // Run through each of the positions in the sector and calculate the current percentage of the position within
            // the sector.  We're going to keep this percentage as we rebalance to the new sector market value.
            foreach (AppraisalSet.SecurityRow driverSecurity in driverObject.GetSecurityRows())
            {
                foreach (AppraisalSet.PositionRow driverPosition in driverSecurity.GetPositionRows())
                {
                    // We need to know what kind of security we're dealing with when calculating market values and quantities
                    // below.
                    ClientMarketData.SecurityRow securityRow =
                        ClientMarketData.Security.FindBySecurityId(driverSecurity.SecurityId);

                    // In this rebalancing operation, the cash balance is dependant on the securities bought and sold.  When
                    // stocks are bought or sold below, they will impact the underlying currency.  We can not balance to a
                    // currency target directly.
                    if (securityRow.SecurityTypeCode == SecurityType.Currency)
                    {
                        continue;
                    }

                    // Calculate the proposed orders for each account.  The fraction of the security within the sector will
                    // stay the same, even though the sector may increase or decrease with respect to the total market value.
                    foreach (AppraisalSet.AccountRow driverAccount in driverPosition.GetAccountRows())
                    {
                        // The underlying currency is needed for the market value calculations.
                        ClientMarketData.AccountRow accountRow = ClientMarketData.Account.FindByAccountId(driverAccount.AccountId);

                        // Sector rebalancing keeps the percentage of a security within the sector constant.  Only the overall
                        // percentage of the sector with respect to the NAV changes.  To accomplish this, we first calculate
                        // the percentage of the security within the sector before we rebalance the sector.
                        decimal actualPositionMarketValue = MarketValue.Calculate(currencyRow,
                                                                                  accountRow, securityRow, driverPosition.PositionTypeCode,
                                                                                  MarketValueFlags.EntirePosition);

                        // Calculate the target market value as a percentage of the entire sector (use zero if the sector has
                        // no market value to prevent divide by zero errors).
                        decimal targetPositionMarketValue = (actualSectorMarketValue == 0) ? 0.0M :
                                                            actualPositionMarketValue * targetSectorMarketValue / actualSectorMarketValue;

                        // The target proposed orders market value keeps the percentage of the position constant while
                        // changing the overall sector percentage.
                        decimal proposedMarketValue = targetPositionMarketValue - MarketValue.Calculate(currencyRow,
                                                                                                        accountRow, securityRow, driverPosition.PositionTypeCode,
                                                                                                        MarketValueFlags.ExcludeProposedOrder);

                        // Calculate the quantity needed to hit the target market value and round it according to the
                        // model.  Note that the market values and prices are all denominated in the currency of the
                        // parent account.  Also note the quantityFactor is needed for the proper quantity calculation.
                        decimal proposedQuantity = proposedMarketValue / (Price.Security(currencyRow, securityRow) *
                                                                          securityRow.PriceFactor * securityRow.QuantityFactor);

                        // If we have an equity, round to the model's lot size.
                        if (securityRow.SecurityTypeCode == SecurityType.Equity)
                        {
                            proposedQuantity = Math.Round(proposedQuantity / modelRow.EquityRounding, 0) *
                                               modelRow.EquityRounding;
                        }

                        // A debt generally needs to be rounded to face.
                        if (securityRow.SecurityTypeCode == SecurityType.Debt)
                        {
                            proposedQuantity = Math.Round(proposedQuantity / modelRow.DebtRounding, 0) *
                                               modelRow.DebtRounding;
                        }

                        // Have the Order Form Builder object construct an order based on the quantity we've calcuated from
                        // the market value.  This method will fill in the defaults needed for a complete proposed order.
                        ProposedOrder.Create(remoteBatch, remoteTransaction, accountRow, securityRow,
                                             driverAccount.PositionTypeCode, proposedQuantity);
                    }
                }
            }

            // Recurse into each of the sub-sectors.  This allows us to rebalance with any number of levels to the
            // hierarchy.  Eventually, we will run across a sector with security positions in it and end up doing some
            // real work.
            foreach (AppraisalSet.ObjectTreeRow driverTree in
                     driverObject.GetObjectTreeRowsByFKObjectObjectTreeParentId())
            {
                SectorMerge.RecurseSectors(remoteBatch, remoteTransaction, currencyRow, modelRow,
                                           driverTree.ObjectRowByFKObjectObjectTreeChildId, actualSectorMarketValue,
                                           targetSectorMarketValue);
            }
        }
コード例 #13
0
        public void CalculateFields()
        {
            // The block order document has an operation that displays distinct values when the occur.  For instance, if
            // all the orders in the block have the same time in force, then that time in force will appear in the
            // document at the block level.  However, if any one of the elements is different from the others, the same
            // column would be blanked out to show that there is more than one value associated with this attribute of the
            // block.  The first order is used as a seed for this operation.  If any element in the block doesn't share
            // the first order's attribute, then that attribute is left blank.
            decimal       quantityOrdered = 0.0M;
            OrdersElement firstOrder      = (OrdersElement)this.SelectSingleNode(".//Order");

            if (firstOrder != null)
            {
                // Aggregates by Orders.
                int     orders                 = 0;
                int     securityIdSum          = 0;
                int     accountIdSum           = 0;
                int     transactionTypeCodeSum = 0;
                int     timeInForceCodeSum     = 0;
                int     orderTypeCodeSum       = 0;
                decimal price1Sum              = 0.0M;
                decimal price2Sum              = 0.0M;

                foreach (OrdersElement ordersElement in this.SelectNodes("Order"))
                {
                    orders++;
                    securityIdSum          += ordersElement.OrderRow.SecurityId;
                    accountIdSum           += ordersElement.OrderRow.AccountId;
                    transactionTypeCodeSum += ordersElement.OrderRow.TransactionTypeCode;
                    timeInForceCodeSum     += ordersElement.OrderRow.TimeInForceCode;
                    orderTypeCodeSum       += ordersElement.OrderRow.OrderTypeCode;
                    price1Sum       += ordersElement.OrderRow.IsPrice1Null() ? 0.0M : ordersElement.OrderRow.Price1;
                    price2Sum       += ordersElement.OrderRow.IsPrice2Null() ? 0.0M : ordersElement.OrderRow.Price2;
                    quantityOrdered += ordersElement.OrderRow.Quantity;
                }

                if (securityIdSum == firstOrder.OrderRow.SecurityId * orders)
                {
                    AddAttribute("SecurityId", firstOrder.OrderRow.SecurityId);

                    ClientMarketData.SecurityRow securityRow = firstOrder.OrderRow.SecurityRowByFKSecurityOrderSecurityId;
                    AddAttribute("SecurityName", securityRow.ObjectRow.Name);
                    AddAttribute("SecuritySymbol", securityRow.Symbol);

                    ClientMarketData.PriceRow priceRow = ClientMarketData.Price.FindBySecurityIdCurrencyId(
                        firstOrder.OrderRow.SecurityId, firstOrder.OrderRow.SettlementId);
                    if (priceRow != null)
                    {
                        AddAttribute("LastPrice", priceRow.LastPrice);
                        AddAttribute("BidPrice", priceRow.BidPrice);
                        AddAttribute("BidSize", priceRow.BidSize);
                        AddAttribute("AskPrice", priceRow.AskPrice);
                        AddAttribute("AskSize", priceRow.AskSize);
                    }

                    // Add Fixed Income Fundamentals where they exist.
                    foreach (ClientMarketData.DebtRow debtRow in securityRow.GetDebtRowsByFKSecurityDebtDebtId())
                    {
                        if (!debtRow.IsIssuerIdNull())
                        {
                            AddAttribute("IssuerId", debtRow.IssuerId);
                        }
                        AddAttribute("DebtTypeCode", debtRow.DebtTypeCode);
                        AddAttribute("Coupon", debtRow.Coupon);
                        AddAttribute("MaturityDate", debtRow.MaturityDate.ToShortDateString());
                    }
                }

                if (accountIdSum == firstOrder.OrderRow.AccountId * orders)
                {
                    AddAttribute("AccountId", firstOrder.OrderRow.AccountId);

                    ClientMarketData.AccountRow accountRow = firstOrder.OrderRow.AccountRow;
                    AddAttribute("AccountName", accountRow.ObjectRow.Name);
                }

                if (transactionTypeCodeSum == firstOrder.OrderRow.TransactionTypeCode * orders)
                {
                    AddAttribute("TransactionTypeCode", firstOrder.OrderRow.TransactionTypeCode);
                    AddAttribute("TransactionTypeName", firstOrder.OrderRow.TransactionTypeRow.Mnemonic);
                }

                if (timeInForceCodeSum == firstOrder.OrderRow.TimeInForceCode * orders)
                {
                    AddAttribute("TimeInForceCode", firstOrder.OrderRow.TimeInForceCode);
                    AddAttribute("TimeInForceName", firstOrder.OrderRow.TimeInForceRow.Mnemonic);
                }

                if (orderTypeCodeSum == firstOrder.OrderRow.OrderTypeCode * orders)
                {
                    AddAttribute("OrderTypeCode", firstOrder.OrderRow.OrderTypeCode);
                    AddAttribute("OrderTypeName", firstOrder.OrderRow.OrderTypeRow.Mnemonic);
                }

                if (!firstOrder.OrderRow.IsPrice1Null() && price1Sum == firstOrder.OrderRow.Price1 * orders)
                {
                    AddAttribute("Price1", firstOrder.OrderRow.Price1);
                }

                if (!firstOrder.OrderRow.IsPrice2Null() && price2Sum == firstOrder.OrderRow.Price2 * orders)
                {
                    AddAttribute("Price2", firstOrder.OrderRow.Price2);
                }

                // HACK - Trade and Settlement are defaulted.  These should be distinct elements from the executions.
                AddAttribute("TradeDate", DateTime.Now.ToShortDateString());
                AddAttribute("SettlementDate", DateTime.Now.ToShortDateString());
            }

            AddAttribute("QuantityOrdered", quantityOrdered);

            // Aggregate Placements
            decimal           quantityPlaced = 0.0M;
            PlacementsElement firstPlacement = (PlacementsElement)this.SelectSingleNode(".//Placement");

            if (firstPlacement != null)
            {
                // Aggregates by Placements.
                int placements  = 0;
                int brokerIdSum = 0;

                foreach (PlacementsElement placementsElement in this.SelectNodes("Placement"))
                {
                    placements++;
                    brokerIdSum    += placementsElement.PlacementRow.BrokerId;
                    quantityPlaced += placementsElement.PlacementRow.Quantity;
                }

                if (brokerIdSum == firstPlacement.PlacementRow.BrokerId * placements)
                {
                    AddAttribute("PlacementBrokerId", firstPlacement.PlacementRow.BrokerId);
                    AddAttribute("PlacementBrokerSymbol", firstPlacement.PlacementRow.BrokerRow.Symbol);
                }
            }

            AddAttribute("QuantityPlaced", quantityPlaced);

            // Aggregate Execution
            decimal          quantityExecuted = 0.0M;
            ExecutionElement firstExecution   = (ExecutionElement)this.SelectSingleNode(".//Execution");

            if (firstExecution != null)
            {
                // Aggregates by Execution.
                int placements  = 0;
                int brokerIdSum = 0;

                foreach (ExecutionElement placementsElement in this.SelectNodes("Execution"))
                {
                    placements++;
                    brokerIdSum      += placementsElement.ExecutionRow.BrokerId;
                    quantityExecuted += placementsElement.ExecutionRow.Quantity;
                }

                if (brokerIdSum == firstExecution.ExecutionRow.BrokerId * placements)
                {
                    AddAttribute("PlacementBrokerId", firstExecution.ExecutionRow.BrokerId);
                    AddAttribute("PlacementBrokerSymbol", firstExecution.ExecutionRow.BrokerRow.Symbol);
                }
            }

            AddAttribute("QuantityExecuted", quantityExecuted);
        }
コード例 #14
0
        /// <summary>
        /// Constructs an AppraisalDocument.
        /// </summary>
        /// <param name="accountRow">A record containing the account or fund data.</param>
        /// <param name="modelRow">A record containing the model that is superimposed on the appraisal data for
        /// rebalancing.</param>
        public AppraisalDocument(ClientMarketData.AccountRow accountRow, ClientMarketData.ModelRow modelRow)
        {
            // Create a view of the proposed orders that makes it easy to aggregate by position.
            this.proposedOrderView      = new DataView(ClientMarketData.ProposedOrder);
            this.proposedOrderView.Sort = "[AccountId], [SecurityId], [PositionTypeCode]";

            // Create a view of the orders that makes it easy to aggregate by position.
            this.orderView      = new DataView(ClientMarketData.Order);
            this.orderView.Sort = "[AccountId], [SecurityId], [PositionTypeCode]";

            // Create a view of the allocations that makes it easy to aggregate by position.
            this.allocationView      = new DataView(ClientMarketData.Allocation);
            this.allocationView.Sort = "[AccountId], [SecurityId], [PositionTypeCode]";

            // This makes the account and model avaiable to the recursive methods.
            this.accountRow = accountRow;
            this.modelRow   = modelRow;

            // Create the root element and add it to the document.
            AppraisalElement rootElement = new AppraisalElement(this);

            this.AppendChild(rootElement);

            // Create and populate the DataSet that represents the outline of the appraisal.  This function creates a
            // set of linked structures that contains only the sectors, securities and positions that will appear in
            // this document. This driver is built from the bottom up, meaning that we start with the tax lots,
            // proposed orders, orders and allocations associated with the given account and build the driver up to
            // the topmost security classification scheme.  The alternative -- starting with the classification scheme
            // and building down until we join with the tax lots, etc, -- turned out to be six times slower.
            this.appraisal = new Common.Appraisal(accountRow, modelRow, true);

            // This sector is a catch-all heading for securities not mapped to the given hierarchy.  If everything is
            // mapped, then this sector won't appear in the document.
            SectorElement unclassifiedSector = null;

            // Now that the driver is built, we can begin constructing the document.  The first section is the
            // 'Unclassified' sector.  This section catches all securities that aren't explicitly mapped to the
            // hierarchy.  This is important because classification schemes are not guaranteed to map every security.
            // Without this section, those unmapped securities wouldn't appear on the appraisal and wouldn't be
            // included in the NAV calculation.  That is very bad.  Note also that we skip over the classification
            // scheme record during the check.  We know that the security classification scheme is at the top of the
            // hierarchy and won't have any parents.  Every other record that doesn't have a parent in the hierarchy
            // is 'Unclassified'.
            foreach (AppraisalSet.SecurityRow parentSecurity in this.appraisal.Security)
            {
                if (parentSecurity.ObjectRow.GetObjectTreeRowsByFKObjectObjectTreeChildId().Length == 0)
                {
                    // If the document doesn't have an 'Unclassified' sector yet, then add the sector heading.  All
                    // secutiries that are not mapped to the given hierarchy will appear under this catch-all header.
                    if (unclassifiedSector == null)
                    {
                        rootElement.InsertBySortOrder(unclassifiedSector = new SectorElement(this));
                    }

                    // Attach the each of the unclassified securities to the unclassified sector heading.
                    BuildDocument(unclassifiedSector, parentSecurity.ObjectRow);
                }
            }

            // The report is built recursively.  The 'AppraisalSet', constructed above, represents an 'inner join' of the
            // hierarchy information to the active position information.  We'll begin traversing the 'AppraisalSet' from
            // the top level security: a single node representing the classification scheme.
            foreach (AppraisalSet.SchemeRow schemeRow in this.appraisal.Scheme)
            {
                foreach (AppraisalSet.ObjectTreeRow objectTreeRow in schemeRow.ObjectRow.GetObjectTreeRowsByFKObjectObjectTreeParentId())
                {
                    BuildDocument(rootElement, objectTreeRow.ObjectRowByFKObjectObjectTreeChildId);
                }
            }
        }
コード例 #15
0
        private static void Update(RemoteBatch remoteBatch, RemoteTransaction remoteTransaction,
                                   ClientMarketData.ProposedOrderRow parentProposedOrder, decimal quantityInstruction)
        {
            // These define the assembly and the types within those assemblies that will be used to create the proposed orders on
            // the middle tier.
            RemoteAssembly remoteAssembly    = remoteBatch.Assemblies.Add("Service.Core");
            RemoteType     proposedOrderType = remoteAssembly.Types.Add("Shadows.WebService.Core.ProposedOrder");

            ClientMarketData.AccountRow  accountRow  = parentProposedOrder.AccountRow;
            ClientMarketData.SecurityRow securityRow = parentProposedOrder.SecurityRowByFKSecurityProposedOrderSecurityId;

            // This will turn the signed quantity into an absolute quantity and a transaction code (e.g. -1000 is turned into a
            // SELL of 1000 shares).
            decimal parentQuantity = Math.Abs(quantityInstruction);

            int parentTransactionTypeCode = TransactionType.Calculate(securityRow.SecurityTypeCode,
                                                                      parentProposedOrder.PositionTypeCode, quantityInstruction);

            // The time in force first comes from the user preferences, next, account settings and finally defaults to a day
            // orders.
            int timeInForceCode = !ClientPreferences.IsTimeInForceCodeNull() ? ClientPreferences.TimeInForceCode :
                                  !accountRow.IsTimeInForceCodeNull() ? accountRow.TimeInForceCode : TimeInForce.DAY;

            // The destination blotter comes first from the user preferences, second from the account preferences, and finally uses
            // the auto-routing logic.
            int blotterId = !ClientPreferences.IsBlotterIdNull() ? ClientPreferences.BlotterId :
                            !accountRow.IsBlotterIdNull() ? accountRow.BlotterId :
                            TradingSupport.AutoRoute(securityRow, parentQuantity);

            // Create a command to update the proposed order.
            RemoteMethod updateParent = proposedOrderType.Methods.Add("Update");

            updateParent.Transaction = remoteTransaction;
            updateParent.Parameters.Add("rowVersion", parentProposedOrder.RowVersion);
            updateParent.Parameters.Add("proposedOrderId", parentProposedOrder.ProposedOrderId);
            updateParent.Parameters.Add("accountId", parentProposedOrder.AccountId);
            updateParent.Parameters.Add("securityId", parentProposedOrder.SecurityId);
            updateParent.Parameters.Add("settlementId", parentProposedOrder.SettlementId);
            updateParent.Parameters.Add("blotterId", blotterId);
            updateParent.Parameters.Add("positionTypeCode", parentProposedOrder.PositionTypeCode);
            updateParent.Parameters.Add("transactionTypeCode", parentTransactionTypeCode);
            updateParent.Parameters.Add("timeInForceCode", timeInForceCode);
            updateParent.Parameters.Add("orderTypeCode", OrderType.Market);
            updateParent.Parameters.Add("quantity", parentQuantity);

            foreach (ClientMarketData.ProposedOrderTreeRow proposedOrderTree in
                     parentProposedOrder.GetProposedOrderTreeRowsByFKProposedOrderProposedOrderTreeParentId())
            {
                ClientMarketData.ProposedOrderRow childProposedOrder =
                    proposedOrderTree.ProposedOrderRowByFKProposedOrderProposedOrderTreeChildId;

                // If this is the settlement part of the order, then adjust the quantity.
                if (childProposedOrder.SecurityId == parentProposedOrder.SettlementId)
                {
                    // The settlement security is needed for the calculation of the cash impact of this trade.
                    ClientMarketData.CurrencyRow currencyRow =
                        MarketData.Currency.FindByCurrencyId(childProposedOrder.SettlementId);

                    decimal marketValue = parentQuantity * securityRow.QuantityFactor *
                                          Price.Security(currencyRow, securityRow) * securityRow.PriceFactor *
                                          TransactionType.GetCashSign(parentTransactionTypeCode);

                    decimal childQuantity = Math.Abs(marketValue);

                    int childTransactionTypeCode = TransactionType.Calculate(securityRow.SecurityTypeCode,
                                                                             parentProposedOrder.PositionTypeCode, marketValue);

                    // Create a command to update the proposed order.
                    RemoteMethod updateChild = proposedOrderType.Methods.Add("Update");
                    updateChild.Transaction = remoteTransaction;
                    updateChild.Parameters.Add("rowVersion", childProposedOrder.RowVersion);
                    updateChild.Parameters.Add("proposedOrderId", childProposedOrder.ProposedOrderId);
                    updateChild.Parameters.Add("accountId", childProposedOrder.AccountId);
                    updateChild.Parameters.Add("securityId", childProposedOrder.SecurityId);
                    updateChild.Parameters.Add("settlementId", childProposedOrder.SettlementId);
                    updateChild.Parameters.Add("blotterId", blotterId);
                    updateChild.Parameters.Add("positionTypeCode", parentProposedOrder.PositionTypeCode);
                    updateChild.Parameters.Add("transactionTypeCode", childTransactionTypeCode);
                    updateChild.Parameters.Add("timeInForceCode", timeInForceCode);
                    updateChild.Parameters.Add("orderTypeCode", OrderType.Market);
                    updateChild.Parameters.Add("quantity", childQuantity);
                }
            }
        }
コード例 #16
0
        /// <summary>
        /// Recursively rebalances an account and all it's children.
        /// </summary>
        /// <param name="accountRow">The parent account to be rebalanced.</param>
        private static void RecurseAccounts(RemoteBatch remoteBatch, RemoteTransaction remoteTransaction,
                                            AppraisalSet appraisalSet, ClientMarketData.AccountRow accountRow, ClientMarketData.ModelRow modelRow)
        {
            // The base currency of the account is used to cacluate market values.
            ClientMarketData.CurrencyRow currencyRow = ClientMarketData.Currency.FindByCurrencyId(accountRow.CurrencyId);

            // Calculate the total market value for the appraisal.  This will be the denominator in all calculations involving
            // portfolio percentages.
            decimal accountMarketValue = MarketValue.Calculate(currencyRow, accountRow, MarketValueFlags.EntirePosition);

            // Cycle through all the positions of the appraisal using the current account and calculate the size and direction of
            // the trade needed to bring it to the model's target percent.
            foreach (AppraisalSet.SecurityRow driverSecurity in appraisalSet.Security)
            {
                // We need to reference the security row in the ClientMarketData to price this item.
                ClientMarketData.SecurityRow securityRow = ClientMarketData.Security.FindBySecurityId(driverSecurity.SecurityId);

                // In this rebalancing operation, the cash balance is dependant on the securities bought and sold. The assumption
                // is made that we won't implicitly add or remove cash to accomplish the reblancing operation. When stocks are
                // bought or sold below, they will impact the underlying currency.  A cash target can be reached by setting all the
                // other percentages up properly.  As long as the total percentage in a model is 100%, the proper cash target will
                // be calculated.  We don't have to do anything with this asset type.
                if (securityRow.SecurityTypeCode == SecurityType.Currency)
                {
                    continue;
                }

                // This section will calculate the difference in between the actual and target market values for each
                // position and create orders that will bring the account to the targeted percentages.
                foreach (AppraisalSet.PositionRow driverPosition in driverSecurity.GetPositionRows())
                {
                    // Calculate the proposed quantity needed to bring this asset/account combination to the percentage given by
                    // the model.  First, find the target percent.  If it's not there, we assume a target of zero (meaning sell all
                    // holdings).
                    ClientMarketData.PositionTargetRow positionTargetRow =
                        ClientMarketData.PositionTarget.FindByModelIdSecurityIdPositionTypeCode(modelRow.ModelId,
                                                                                                securityRow.SecurityId, driverPosition.PositionTypeCode);
                    decimal targetPositionPercent = positionTargetRow == null ? 0.0M : positionTargetRow.Percent;

                    // The market value of this trade will be the target market value less the current market value of
                    // this position (without including the existing proposed orders in the current market value
                    // calculation).
                    decimal targetPositionMarketValue = targetPositionPercent * accountMarketValue;
                    decimal actualPositionMarketValue = MarketValue.Calculate(currencyRow, accountRow, securityRow,
                                                                              driverPosition.PositionTypeCode, MarketValueFlags.ExcludeProposedOrder);
                    decimal proposedMarketValue = targetPositionMarketValue - actualPositionMarketValue;

                    // Calculate the quantity needed to hit the target market value and round it according to the model. Note that
                    // the market values and prices are all denominated in the currency of the parent account. Also note the
                    // quantityFactor is needed for the proper quantity calculation.
                    decimal price            = Price.Security(currencyRow, securityRow);
                    decimal proposedQuantity = price == 0.0M ? 0.0M : proposedMarketValue / (price * securityRow.QuantityFactor);

                    // If we have an equity, round to the model's lot size.  Common values are 100 and 1.
                    if (securityRow.SecurityTypeCode == SecurityType.Equity)
                    {
                        proposedQuantity = Math.Round(proposedQuantity / modelRow.EquityRounding, 0) * modelRow.EquityRounding;
                    }

                    // A debt generally needs to be rounded to face.
                    if (securityRow.SecurityTypeCode == SecurityType.Debt)
                    {
                        proposedQuantity = Math.Round(proposedQuantity / modelRow.DebtRounding, 0) * modelRow.DebtRounding;
                    }

                    // Have the Order Form Builder object construct an order based on the new proposed quantity.  This method will
                    // fill in the defaults needed for a complete Proposed Order.  It will also create an deposit or widthdrawal
                    // from an account to cover the transaction.
                    ProposedOrder.Create(remoteBatch, remoteTransaction, accountRow, securityRow, driverPosition.PositionTypeCode,
                                         proposedQuantity);
                }
            }

            // Now that we've rebalanced the parent account, cycle through all the children accounts and rebalance them.
            foreach (ClientMarketData.ObjectTreeRow objectTreeRow in
                     accountRow.ObjectRow.GetObjectTreeRowsByFKObjectObjectTreeParentId())
            {
                foreach (ClientMarketData.AccountRow childAccount in
                         objectTreeRow.ObjectRowByFKObjectObjectTreeChildId.GetAccountRows())
                {
                    Security.RecurseAccounts(remoteBatch, remoteTransaction, appraisalSet, childAccount, modelRow);
                }
            }
        }
コード例 #17
0
        /// <summary>
        /// Creates an element in the Appraisal Document that represents a fund's or account's position.
        /// </summary>
        /// <param name="appraisalDocument">The parent document.</param>
        /// <param name="driverAccount">Identifies the individual position at the account/security/position level.</param>
        public AccountElement(AppraisalDocument appraisalDocument, AppraisalSet.AccountRow driverAccount) :
            base("Account", appraisalDocument)
        {
            // Get the account record from the account id.  This record drives most of the data that appears in this element.
            ClientMarketData.AccountRow accountRow =
                ClientMarketData.Account.FindByAccountId(driverAccount.AccountId);

            // Count up the compliance violations
            int violationCount = 0;

            foreach (DataRowView dataRowView in
                     ClientMarketData.Violation.UKViolationAccountIdSecurityIdPositionTypeCode.FindRows(
                         new object[] { driverAccount.AccountId, driverAccount.SecurityId, driverAccount.PositionTypeCode }))
            {
                ClientMarketData.ViolationRow violationRow = (ClientMarketData.ViolationRow)dataRowView.Row;
                if (violationRow.RestrictionRow.Severity > 0)
                {
                    violationCount++;
                }
            }
            AddAttribute("Violation", violationCount);

            // Add the essential attributes to the element.
            AddAttribute("AccountId", accountRow.AccountId.ToString());

            // Aggregate the tax lot positions and cost.
            decimal taxLotQuantity = 0.0M;
            decimal taxLotCost     = 0.0M;

            foreach (ClientMarketData.TaxLotRow taxLotRow in accountRow.GetTaxLotRows())
            {
                if (taxLotRow.SecurityId == driverAccount.SecurityId &&
                    taxLotRow.PositionTypeCode == driverAccount.PositionTypeCode)
                {
                    taxLotQuantity += taxLotRow.Quantity;
                    taxLotCost     += taxLotRow.Cost * taxLotRow.Quantity;
                }
            }
            AddAttribute("TaxLotQuantity", taxLotQuantity.ToString());
            AddAttribute("TaxLotCost", taxLotCost.ToString());

            // Aggregate the proposed orders positions.
            decimal proposedOrderQuantity = 0.0M;

            foreach (DataRowView dataRowView in
                     appraisalDocument.proposedOrderView.FindRows(new object[] { driverAccount.AccountId, driverAccount.SecurityId,
                                                                                 driverAccount.PositionTypeCode }))
            {
                ClientMarketData.ProposedOrderRow proposedOrderRow = (ClientMarketData.ProposedOrderRow)dataRowView.Row;
                proposedOrderQuantity += proposedOrderRow.Quantity *
                                         proposedOrderRow.TransactionTypeRow.QuantitySign;
            }
            AddAttribute("ProposedOrderQuantity", proposedOrderQuantity.ToString());

            // Aggregate the orders.
            decimal orderQuantity = 0.0M;

            foreach (DataRowView dataRowView in
                     appraisalDocument.orderView.FindRows(new object[] { driverAccount.AccountId, driverAccount.SecurityId,
                                                                         driverAccount.PositionTypeCode }))
            {
                ClientMarketData.OrderRow orderRow = (ClientMarketData.OrderRow)dataRowView.Row;
                orderQuantity += orderRow.Quantity *
                                 orderRow.TransactionTypeRow.QuantitySign;
            }
            AddAttribute("OrderQuantity", orderQuantity.ToString());

            // Aggregate the allocations.
            decimal allocationQuantity = 0.0M;

            foreach (DataRowView dataRowView in
                     appraisalDocument.allocationView.FindRows(new object[] { driverAccount.AccountId, driverAccount.SecurityId,
                                                                              driverAccount.PositionTypeCode }))
            {
                ClientMarketData.AllocationRow allocationRow = (ClientMarketData.AllocationRow)dataRowView.Row;
                allocationQuantity += allocationRow.Quantity *
                                      allocationRow.TransactionTypeRow.QuantitySign;
            }
            AddAttribute("AllocationQuantity", allocationQuantity.ToString());
        }
コード例 #18
0
        internal static Position Make(int accountId, int securityId, int positionTypeCode)
        {
            Position position = new Position();

            ClientMarketData.AccountRow accountRow =
                ClientMarketData.Account.FindByAccountId(accountId);
            if (accountRow == null)
            {
                throw new Exception(string.Format("Account {0} doesn't exist", accountId));
            }

            ClientMarketData.SecurityRow securityRow =
                ClientMarketData.Security.FindBySecurityId(securityId);
            if (securityRow == null)
            {
                throw new Exception(string.Format("Security {0} doesn't exist", securityId));
            }

            // Look up the position record.
            ClientMarketData.PositionRow positionRow =
                ClientMarketData.Position.FindByAccountIdSecurityIdPositionTypeCode(accountId, securityId, positionTypeCode);

            // We can always create a position.  There may be no information associated with it, but it can be created just the
            // same.
            position.account      = Account.Make(accountId);
            position.security     = Security.Make(securityId);
            position.positionType = (PositionType)positionTypeCode;

            // If we have a record for the price/currency combination, then update it with the new price.
            if (positionRow != null)
            {
                if (!positionRow.IsUserData0Null())
                {
                    position.userData0 = positionRow.UserData0;
                }
                if (!positionRow.IsUserData1Null())
                {
                    position.userData1 = positionRow.UserData1;
                }
                if (!positionRow.IsUserData2Null())
                {
                    position.userData2 = positionRow.UserData2;
                }
                if (!positionRow.IsUserData3Null())
                {
                    position.userData3 = positionRow.UserData3;
                }
                if (!positionRow.IsUserData4Null())
                {
                    position.userData4 = positionRow.UserData4;
                }
                if (!positionRow.IsUserData5Null())
                {
                    position.userData5 = positionRow.UserData5;
                }
                if (!positionRow.IsUserData6Null())
                {
                    position.userData6 = positionRow.UserData6;
                }
                if (!positionRow.IsUserData7Null())
                {
                    position.userData7 = positionRow.UserData7;
                }
            }

            return(position);
        }
コード例 #19
0
ファイル: Account.cs プロジェクト: DonaldAirey/quasar
        public PositionList GetPositions(Sector sector)
        {
            PositionList positionList = new PositionList();

            try
            {
                // Lock the tables.
                Debug.Assert(!ClientMarketData.AreLocksHeld);
                ClientMarketData.AccountLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.AllocationLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.ObjectLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.ObjectTreeLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.OrderLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.PositionLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.ProposedOrderLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.SectorLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.SecurityLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.TaxLotLock.AcquireReaderLock(CommonTimeout.LockWait);

                ClientMarketData.AccountRow accountRow = ClientMarketData.Account.FindByAccountId(this.AccountId);

                ClientMarketData.SectorRow sectorRow = ClientMarketData.Sector.FindBySectorId(sector.SectorId);

                // Aggregate the tax lot quantities.
                foreach (ClientMarketData.TaxLotRow taxLotRow in accountRow.GetTaxLotRows())
                {
                    if (IsSecurityInSector(sectorRow, taxLotRow.SecurityRow))
                    {
                        positionList.Add(Position.Make(this.AccountId, taxLotRow.SecurityId, taxLotRow.PositionTypeCode));
                    }
                }

                // Aggregate the proposed ordered quantities
                foreach (ClientMarketData.ProposedOrderRow proposedOrderRow in accountRow.GetProposedOrderRows())
                {
                    if (IsSecurityInSector(sectorRow, proposedOrderRow.SecurityRowByFKSecurityProposedOrderSecurityId))
                    {
                        positionList.Add(Position.Make(this.AccountId, proposedOrderRow.SecurityId, proposedOrderRow.PositionTypeCode));
                    }
                }

                // Aggregate the ordered quantities
                foreach (ClientMarketData.OrderRow orderRow in accountRow.GetOrderRows())
                {
                    if (IsSecurityInSector(sectorRow, orderRow.SecurityRowByFKSecurityOrderSecurityId))
                    {
                        positionList.Add(Position.Make(this.AccountId, orderRow.SecurityId, orderRow.PositionTypeCode));
                    }
                }

                // Aggregate the allocated quantities
                foreach (ClientMarketData.AllocationRow allocationRow in accountRow.GetAllocationRows())
                {
                    if (IsSecurityInSector(sectorRow, allocationRow.SecurityRowByFKSecurityAllocationSecurityId))
                    {
                        positionList.Add(Position.Make(this.AccountId, allocationRow.SecurityId, allocationRow.PositionTypeCode));
                    }
                }
            }
            finally
            {
                // Locks are no longer needed on the price table.
                if (ClientMarketData.AccountLock.IsReaderLockHeld)
                {
                    ClientMarketData.AccountLock.ReleaseReaderLock();
                }
                if (ClientMarketData.AllocationLock.IsReaderLockHeld)
                {
                    ClientMarketData.AllocationLock.ReleaseReaderLock();
                }
                if (ClientMarketData.ObjectLock.IsReaderLockHeld)
                {
                    ClientMarketData.ObjectLock.ReleaseReaderLock();
                }
                if (ClientMarketData.ObjectTreeLock.IsReaderLockHeld)
                {
                    ClientMarketData.ObjectTreeLock.ReleaseReaderLock();
                }
                if (ClientMarketData.OrderLock.IsReaderLockHeld)
                {
                    ClientMarketData.OrderLock.ReleaseReaderLock();
                }
                if (ClientMarketData.PositionLock.IsReaderLockHeld)
                {
                    ClientMarketData.PositionLock.ReleaseReaderLock();
                }
                if (ClientMarketData.ProposedOrderLock.IsReaderLockHeld)
                {
                    ClientMarketData.ProposedOrderLock.ReleaseReaderLock();
                }
                if (ClientMarketData.SectorLock.IsReaderLockHeld)
                {
                    ClientMarketData.SectorLock.ReleaseReaderLock();
                }
                if (ClientMarketData.SecurityLock.IsReaderLockHeld)
                {
                    ClientMarketData.SecurityLock.ReleaseReaderLock();
                }
                if (ClientMarketData.TaxLotLock.IsReaderLockHeld)
                {
                    ClientMarketData.TaxLotLock.ReleaseReaderLock();
                }
                Debug.Assert(!ClientMarketData.AreLocksHeld);
            }

            return(positionList);
        }
コード例 #20
0
ファイル: Order.cs プロジェクト: DonaldAirey/quasar
        /// <summary>
        /// Creates a denormalized order record from a local record.
        /// </summary>
        /// <param name="localOrder">A local order record.</param>
        /// <returns>A order record that is independant of the global data set for all the anscillary data.</returns>
        public static OrderSet.OrderRow Create(LocalOrderSet.OrderRow localOrder)
        {
            // Create a new, empty order record.
            OrderSet.OrderRow orderRow = orderSet.Order.NewOrderRow();

            // This new record is a copy of a local record and uses the local system of identifiers.
            orderRow.IsLocal = true;

            // Copy each field that has an analog in the local record set into the new record.
            foreach (DataColumn dataColumn in localOrder.Table.Columns)
            {
                orderRow[dataColumn.ColumnName] = localOrder[dataColumn];
            }

            // AccountId cross-referenced data is filled in here.
            if (!localOrder.IsAccountIdNull())
            {
                ClientMarketData.AccountRow accountRow = ClientMarketData.Account.FindByAccountId(orderRow.AccountId);
                if (accountRow != null)
                {
                    orderRow.AccountMnemonic = accountRow.Mnemonic;
                    orderRow.AccountName     = accountRow.ObjectRow.Name;
                }
            }

            // SecurityId cross-referenced data is filled in here.
            if (!localOrder.IsSecurityIdNull())
            {
                ClientMarketData.SecurityRow securityRow = ClientMarketData.Security.FindBySecurityId(orderRow.SecurityId);
                if (securityRow != null)
                {
                    orderRow.SecuritySymbol = securityRow.Symbol;
                    orderRow.SecurityName   = securityRow.ObjectRow.Name;
                }
            }

            // CurrencyId cross-referenced data is filled in here.
            if (!localOrder.IsSettlementIdNull())
            {
                ClientMarketData.CurrencyRow currencyRow = ClientMarketData.Currency.FindByCurrencyId(orderRow.SettlementId);
                if (currencyRow != null)
                {
                    orderRow.SettlementSymbol = currencyRow.SecurityRow.Symbol;
                    orderRow.SettlementName   = currencyRow.SecurityRow.ObjectRow.Name;
                }
            }

            // BrokerId cross-referenced data is filled in here.
            if (!localOrder.IsBrokerIdNull())
            {
                ClientMarketData.BrokerRow brokerRow = ClientMarketData.Broker.FindByBrokerId(orderRow.BrokerId);
                if (brokerRow != null)
                {
                    orderRow.BrokerSymbol = brokerRow.Symbol;
                    orderRow.BrokerName   = brokerRow.ObjectRow.Name;
                }
            }

            // TransactionType cross-referenced data is filled in here.
            if (!localOrder.IsTransactionTypeCodeNull())
            {
                ClientMarketData.TransactionTypeRow transactionTypeRow = ClientMarketData.TransactionType.FindByTransactionTypeCode(orderRow.TransactionTypeCode);
                if (transactionTypeRow != null)
                {
                    orderRow.TransactionTypeMnemonic = transactionTypeRow.Mnemonic;
                }
            }

            // TimeInForce cross-referenced data is filled in here.
            if (!localOrder.IsTimeInForceCodeNull())
            {
                ClientMarketData.TimeInForceRow timeInForceRow = ClientMarketData.TimeInForce.FindByTimeInForceCode(orderRow.TimeInForceCode);
                if (timeInForceRow != null)
                {
                    orderRow.TimeInForceMnemonic = timeInForceRow.Mnemonic;
                }
            }

            // TimeInForce cross-referenced data is filled in here.
            if (!localOrder.IsOrderTypeCodeNull())
            {
                ClientMarketData.OrderTypeRow orderTypeRow = ClientMarketData.OrderType.FindByOrderTypeCode(orderRow.OrderTypeCode);
                if (orderTypeRow != null)
                {
                    orderRow.OrderTypeMnemonic = orderTypeRow.Mnemonic;
                }
            }

            // This is a complete record of the order, including the referenced data.
            return(orderRow);
        }
コード例 #21
0
ファイル: Account.cs プロジェクト: DonaldAirey/quasar
        public decimal GetMarketValue(Sector sector)
        {
            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.ObjectLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.ObjectTreeLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.OrderLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.PriceLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.ProposedOrderLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.SectorLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.SecurityLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.TaxLotLock.AcquireReaderLock(CommonTimeout.LockWait);
                ClientMarketData.TransactionTypeLock.AcquireReaderLock(CommonTimeout.LockWait);

                ClientMarketData.AccountRow accountRow = ClientMarketData.Account.FindByAccountId(this.AccountId);
                ClientMarketData.SectorRow  sectorRow  = ClientMarketData.Sector.FindBySectorId(sector.SectorId);
                return(Common.MarketValue.Calculate(accountRow.CurrencyRow, accountRow, sectorRow,
                                                    MarketValueFlags.EntirePosition | MarketValueFlags.IncludeChildAccounts));
            }
            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.ObjectLock.IsReaderLockHeld)
                {
                    ClientMarketData.ObjectLock.ReleaseReaderLock();
                }
                if (ClientMarketData.ObjectTreeLock.IsReaderLockHeld)
                {
                    ClientMarketData.ObjectTreeLock.ReleaseReaderLock();
                }
                if (ClientMarketData.OrderLock.IsReaderLockHeld)
                {
                    ClientMarketData.OrderLock.ReleaseReaderLock();
                }
                if (ClientMarketData.PriceLock.IsReaderLockHeld)
                {
                    ClientMarketData.PriceLock.ReleaseReaderLock();
                }
                if (ClientMarketData.ProposedOrderLock.IsReaderLockHeld)
                {
                    ClientMarketData.ProposedOrderLock.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);
            }
        }
コード例 #22
0
ファイル: Models.cs プロジェクト: DonaldAirey/quasar
        /// <summary>
        /// Creates a temporary model based on the current sector level targets.
        /// </summary>
        /// <param name="accountRow">An account used as a basis for the targets.</param>
        /// <param name="schemeRow">The scheme used to select sector targets.</param>
        /// <returns>A batch of commands that will create a model containing the current sector weights of the account.</returns>
        private static ModelBatch CreateSectorSelfModel(ClientMarketData.AccountRow accountRow, ClientMarketData.SchemeRow schemeRow)
        {
            // This command batch will create a temporary model and populate it with the current position level percentages as the
            // target values.
            ModelBatch        modelBatch        = new ModelBatch();
            RemoteTransaction remoteTransaction = modelBatch.Transactions.Add();
            RemoteAssembly    remoteAssembly    = modelBatch.Assemblies.Add("Service.Core");
            RemoteType        remoteType        = remoteAssembly.Types.Add("Shadows.WebService.Core.Model");

            // Create the temporary model.
            RemoteMethod insertModel = remoteType.Methods.Add("Insert");

            insertModel.Parameters.Add("modelId", DataType.Int, Direction.ReturnValue);
            insertModel.Parameters.Add("rowVersion", DataType.Long, Direction.Output);
            insertModel.Parameters.Add("modelTypeCode", ModelType.Sector);
            insertModel.Parameters.Add("name", "Untitled");
            insertModel.Parameters.Add("schemeId", schemeRow.SchemeId);
            insertModel.Parameters.Add("algorithmId", Algorithm.SectorMergeRebalancer);
            insertModel.Parameters.Add("temporary", true);

            // The 'Self Sector' uses the market value of all the account and sub-account.
            decimal accountMarketValue = MarketValue.Calculate(accountRow.CurrencyRow, accountRow,
                                                               MarketValueFlags.EntirePosition | MarketValueFlags.IncludeChildAccounts);

            // No need to construct a model if the account market value is zero.
            if (accountMarketValue != 0.0M)
            {
                // Create a new outline for the model to follow.  This will collect the tax lots, proposed orders, orders
                // and allocations into industry classification sectors.
                Common.Appraisal appraisal = new Common.Appraisal(accountRow, schemeRow, true);

                // The object Type for this operation.
                RemoteType sectorTargetType = remoteAssembly.Types.Add("Shadows.WebService.Core.SectorTarget");

                // Now that we have an outline to follow, we are going to run through each of the sectors, calculate the market
                // value, and create an entry in the temporary model for that sector and it's current weight of the overall market
                // value.
                foreach (AppraisalSet.SchemeRow driverScheme in appraisal.Scheme)
                {
                    foreach (AppraisalSet.ObjectTreeRow driverTree in
                             driverScheme.ObjectRow.GetObjectTreeRowsByFKObjectObjectTreeParentId())
                    {
                        foreach (AppraisalSet.SectorRow driverSector in
                                 driverTree.ObjectRowByFKObjectObjectTreeChildId.GetSectorRows())
                        {
                            // This sector is the destination for the market value calculation.
                            ClientMarketData.SectorRow sectorRow = ClientMarketData.Sector.FindBySectorId(driverSector.SectorId);

                            // Calculate the market value of all the securities held by all the accounts in the current sector.
                            decimal sectorMarketValue = MarketValue.Calculate(accountRow.CurrencyRow, accountRow, sectorRow,
                                                                              MarketValueFlags.EntirePosition | MarketValueFlags.IncludeChildAccounts);

                            // Add the position level target to the model.
                            RemoteMethod insertSector = sectorTargetType.Methods.Add("Insert");
                            insertSector.Parameters.Add("modelId", insertModel.Parameters["modelId"]);
                            insertSector.Parameters.Add("sectorId", sectorRow.SectorId);
                            insertSector.Parameters.Add("percent", sectorMarketValue / accountMarketValue);
                        }
                    }
                }
            }

            // Save the reference to the 'modelId' return parameter.
            modelBatch.ModelIdParameter = insertModel.Parameters["modelId"];

            // This batch will create a temporary model based on the sector totals of the original account.
            return(modelBatch);
        }
コード例 #23
0
        /// <summary>
        /// Creates an XML Element representing a placment in the order document.
        /// </summary>
        /// <param name="xmlDocument">The destination XML document.</param>
        /// <param name="orderRow">A order record.</param>
        public LocalOrderElement(XmlDocument xmlDocument, LocalOrderSet.OrderRow orderRow) :
            base("LocalOrder", xmlDocument)
        {
            // Add the attributes of a order to this record.
            AddAttribute("OrderId", orderRow.OrderId.ToString());

            // Account field
            if (!orderRow.IsAccountIdNull())
            {
                AddAttribute("AccountId", orderRow.AccountId.ToString());

                ClientMarketData.AccountRow accountRow = ClientMarketData.Account.FindByAccountId(orderRow.AccountId);
                if (accountRow != null)
                {
                    AddAttribute("AccountId", accountRow.AccountId.ToString());
                    AddAttribute("AccountName", accountRow.ObjectRow.Name);
                    AddAttribute("AccountMnemonic", accountRow.Mnemonic);
                }
            }

            // Security field
            if (!orderRow.IsSecurityIdNull())
            {
                AddAttribute("SecurityId", orderRow.SecurityId.ToString());

                ClientMarketData.SecurityRow securityRow = ClientMarketData.Security.FindBySecurityId(orderRow.SecurityId);
                if (securityRow != null)
                {
                    AddAttribute("SecurityId", securityRow.SecurityId.ToString());
                    AddAttribute("SecurityName", securityRow.ObjectRow.Name);
                    AddAttribute("SecuritySymbol", securityRow.Symbol);
                }
            }

            // Broker field
            if (!orderRow.IsBrokerIdNull())
            {
                AddAttribute("BrokerId", orderRow.BrokerId.ToString());

                ClientMarketData.BrokerRow brokerRow = ClientMarketData.Broker.FindByBrokerId(orderRow.BrokerId);
                if (brokerRow != null)
                {
                    AddAttribute("BrokerId", brokerRow.BrokerId.ToString());
                    AddAttribute("BrokerName", brokerRow.ObjectRow.Name);
                    AddAttribute("BrokerSymbol", brokerRow.Symbol);
                    if (!brokerRow.IsPhoneNull())
                    {
                        AddAttribute("BrokerPhone", brokerRow.Phone);
                    }
                }
            }

            // TransactionType field
            if (!orderRow.IsTransactionTypeCodeNull())
            {
                AddAttribute("TransactionTypeCode", orderRow.TransactionTypeCode.ToString());

                ClientMarketData.TransactionTypeRow transactionTypeRow = ClientMarketData.TransactionType.FindByTransactionTypeCode(orderRow.TransactionTypeCode);
                if (transactionTypeRow != null)
                {
                    AddAttribute("TransactionTypeMnemonic", transactionTypeRow.Mnemonic);
                }
            }

            // TimeInForce field
            if (!orderRow.IsTimeInForceCodeNull())
            {
                AddAttribute("TimeInForceCode", orderRow.TimeInForceCode.ToString());

                ClientMarketData.TimeInForceRow timeInForceRow = ClientMarketData.TimeInForce.FindByTimeInForceCode(orderRow.TimeInForceCode);
                if (timeInForceRow != null)
                {
                    AddAttribute("TimeInForceMnemonic", timeInForceRow.Mnemonic);
                }
            }

            // OrderType field
            if (!orderRow.IsOrderTypeCodeNull())
            {
                AddAttribute("OrderTypeCode", orderRow.OrderTypeCode.ToString());

                ClientMarketData.OrderTypeRow orderTypeRow = ClientMarketData.OrderType.FindByOrderTypeCode(orderRow.OrderTypeCode);
                if (orderTypeRow != null)
                {
                    AddAttribute("OrderTypeMnemonic", orderTypeRow.Mnemonic);
                }
            }

            if (!orderRow.IsQuantityNull())
            {
                AddAttribute("Quantity", orderRow.Quantity.ToString());
            }
            if (!orderRow.IsPrice1Null())
            {
                AddAttribute("Price1", orderRow.Price1.ToString());
            }
            if (!orderRow.IsPrice2Null())
            {
                AddAttribute("Price2", orderRow.Price2.ToString());
            }
        }
コード例 #24
0
ファイル: Models.cs プロジェクト: DonaldAirey/quasar
        /// <summary>
        /// Creates a temporary model based on the current position level targets.
        /// </summary>
        /// <param name="accountRow">An account used as a basis for the targets.</param>
        /// <param name="schemeRow">The scheme used to select sector targets.</param>
        /// <returns>A batch of commands that will create a model containing the current position weights of the account.</returns>
        private static ModelBatch CreatePositionSelfModel(ClientMarketData.AccountRow accountRow, ClientMarketData.SchemeRow schemeRow)
        {
            // Create the batch and fill it in with the assembly and type needed for this function.
            ModelBatch        modelBatch        = new ModelBatch();
            RemoteTransaction remoteTransaction = modelBatch.Transactions.Add();
            RemoteAssembly    remoteAssembly    = modelBatch.Assemblies.Add("Service.Core");
            RemoteType        remoteType        = remoteAssembly.Types.Add("Shadows.WebService.Core.Model");

            // Create the temporary, position model based on the scheme used by the original account.
            RemoteMethod insertModel = remoteType.Methods.Add("Insert");

            insertModel.Parameters.Add("modelId", DataType.Int, Direction.ReturnValue);
            insertModel.Parameters.Add("rowVersion", DataType.Long, Direction.Output);
            insertModel.Parameters.Add("modelTypeCode", ModelType.Security);
            insertModel.Parameters.Add("name", "Untitled");
            insertModel.Parameters.Add("schemeId", schemeRow.SchemeId);
            insertModel.Parameters.Add("algorithmId", Algorithm.SecurityRebalancer);
            insertModel.Parameters.Add("temporary", true);

            // The 'Self Security' model uses the market value of all the positions, regardless of account or sub-account, when
            // calculating the denominator for the percentages.
            decimal accountMarketValue = MarketValue.Calculate(accountRow.CurrencyRow, accountRow,
                                                               MarketValueFlags.EntirePosition | MarketValueFlags.IncludeChildAccounts);

            // If the account market value is zero, we can't do much more to create a model.
            if (accountMarketValue != 0.0M)
            {
                // Create a new outline for the model to follow.  This will collect the tax lots, proposed orders orders and
                // allocations into positions that can be used for calculating percentages.
                Common.Appraisal appraisal = new Common.Appraisal(accountRow, true);

                // Run through each of the positions, starting with the security.
                foreach (AppraisalSet.SecurityRow driverSecurity in appraisal.Security)
                {
                    // This is a position is the destination for the market value calculation.
                    ClientMarketData.SecurityRow securityRow =
                        ClientMarketData.Security.FindBySecurityId(driverSecurity.SecurityId);

                    // The object Type for this operation.
                    RemoteType positionTargetType = remoteAssembly.Types.Add("Shadows.WebService.Core.PositionTarget");

                    // Run through each of the positions in the appraisal calculating the market value of each position. The ratio
                    // of this market value to the account's market value is the model percentage.
                    foreach (AppraisalSet.PositionRow positionRow in driverSecurity.GetPositionRows())
                    {
                        // Calculate the market value of the given position.
                        decimal securityMarketValue = MarketValue.Calculate(accountRow.CurrencyRow, accountRow,
                                                                            securityRow, positionRow.PositionTypeCode,
                                                                            MarketValueFlags.EntirePosition | MarketValueFlags.EntirePosition);

                        // Add the position level target to the model.
                        RemoteMethod insertPosition = positionTargetType.Methods.Add("Insert");
                        insertPosition.Parameters.Add("modelId", insertModel.Parameters["modelId"]);
                        insertPosition.Parameters.Add("securityId", securityRow.SecurityId);
                        insertPosition.Parameters.Add("positionTypeCode", positionRow.PositionTypeCode);
                        insertPosition.Parameters.Add("percent", securityMarketValue / accountMarketValue);
                    }
                }
            }

            // Save the reference to the 'modelId' return parameter.
            modelBatch.ModelIdParameter = insertModel.Parameters["modelId"];

            // This batch will create a temporary model based on the position totals of the original account.
            return(modelBatch);
        }
コード例 #25
0
ファイル: Models.cs プロジェクト: DonaldAirey/quasar
        /// <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);
        }
コード例 #26
0
ファイル: Account.cs プロジェクト: DonaldAirey/quasar
 public Account(int objectId) : base(objectId)
 {
     // Initialize the object
     ClientMarketData.AccountRow accountRow = ClientMarketData.Account.FindByAccountId(objectId);
 }
コード例 #27
0
        /// <summary>
        /// Rebalances an account to the sector targets, then recursively rebalances the children accounts.
        /// </summary>
        /// <param name="orderFormBuilder">A collection of orders.</param>
        /// <param name="accountRow">The parent account to be rebalanced.</param>
        /// <param name="modelRow">The model containing the sector targets.</param>
        /// <param name="schemeRow">The outline scheme used to define the sector contents.</param>
        private static void RecurseAccounts(RemoteBatch remoteBatch, RemoteTransaction remoteTransaction,
                                            ClientMarketData.AccountRow accountRow, ClientMarketData.ModelRow modelRow, ClientMarketData.SchemeRow schemeRow)
        {
            // All the market values of all the securities in this account are normalized to a single currency so they can
            // be aggregated.
            ClientMarketData.CurrencyRow currencyRow = ClientMarketData.Currency.FindByCurrencyId(accountRow.CurrencyId);

            // Calculate the total market value for the appraisal without including child accounts.  This is a 'Wrap'
            // rebalancing, so we're only concerned with what's in this account.  The account's market value will be the
            // denominator in all calculations involving sector percentages.
            decimal accountMarketValue = MarketValue.Calculate(currencyRow, accountRow,
                                                               MarketValueFlags.EntirePosition);

            // The outline of the appraisal will be needed to make market value calculations based on a sector.  Note that
            // we're not including the child accounts in the outline.  Wrap rebalancing works only on a single account at
            // a time.
            AppraisalSet appraisalSet = new Appraisal(accountRow, schemeRow, false);

            // By cycling through all the immediate children of the scheme record, we'll have covered the top-level
            // sectors in this appraisal.
            foreach (AppraisalSet.SchemeRow driverScheme in appraisalSet.Scheme)
            {
                foreach (AppraisalSet.ObjectTreeRow driverTree in
                         driverScheme.ObjectRow.GetObjectTreeRowsByFKObjectObjectTreeParentId())
                {
                    foreach (AppraisalSet.SectorRow driverSector in
                             driverTree.ObjectRowByFKObjectObjectTreeChildId.GetSectorRows())
                    {
                        // Find the sectors row record that corresponds to the current sector in the appraisal set.
                        ClientMarketData.SectorRow sectorRow = ClientMarketData.Sector.FindBySectorId(driverSector.SectorId);

                        // Get the market value of the top-level sector, including all sub-sectors and all positions
                        // belonging to only the current account.
                        decimal actualSectorMarketValue = MarketValue.Calculate(currencyRow, accountRow, sectorRow,
                                                                                MarketValueFlags.EntirePosition);

                        // This will find the model percentage of the current top-level sector.  If the sector wasn't
                        // specified in the model, assume a value of zero, which would indicate that we're to sell the
                        // entire sector.
                        ClientMarketData.SectorTargetRow sectorTargetRow =
                            ClientMarketData.SectorTarget.FindByModelIdSectorId(modelRow.ModelId, driverSector.SectorId);
                        decimal targetPercent = (sectorTargetRow == null) ? 0.0M : sectorTargetRow.Percent;

                        // The sector's target market value is calculated from the model percentage and the current
                        // account market value.  This is placed in a member variable so it's available to the methods
                        // when we recurse.
                        decimal targetSectorMarketValue = accountMarketValue * targetPercent;

                        // Now that we have a sector target to shoot for, recursively descend into the structure
                        // calculating proposed orders.
                        SectorWrap.RecurseSectors(remoteBatch, remoteTransaction, modelRow, driverSector, actualSectorMarketValue,
                                                  targetSectorMarketValue);
                    }
                }
            }

            // Now that we've rebalanced the parent account, cycle through all the children accounts and rebalance them.
            foreach (ClientMarketData.ObjectTreeRow objectTreeRow in
                     accountRow.ObjectRow.GetObjectTreeRowsByFKObjectObjectTreeParentId())
            {
                foreach (ClientMarketData.AccountRow childAccount in
                         objectTreeRow.ObjectRowByFKObjectObjectTreeChildId.GetAccountRows())
                {
                    SectorWrap.RecurseAccounts(remoteBatch, remoteTransaction, childAccount, modelRow, schemeRow);
                }
            }
        }
コード例 #28
0
        /// <summary>
        /// Rebalances an AppraisalModelSet to sector targets.  The model is applied to the aggregate market value of the
        /// account and it's children.
        /// </summary>
        /// <param name="accountId">The parent account to be rebalanced.</param>
        /// <param name="modelId">The sector model to be used.</param>
        /// <returns>A set of proposed orders.</returns>
        public static RemoteBatch Rebalance(ClientMarketData.AccountRow accountRow, ClientMarketData.ModelRow modelRow)
        {
            // Make sure the scheme still exists in the in-memory database.  We need it to rebalance to calculate
            // sector totals.
            ClientMarketData.SchemeRow schemeRow;
            if ((schemeRow = ClientMarketData.Scheme.FindBySchemeId(modelRow.SchemeId)) == null)
            {
                throw new ArgumentException("Scheme doesn't exist in the ClientMarketData", modelRow.SchemeId.ToString());
            }

            // All the market values need to be normalized to a single currency so the sectors can be aggregated. This
            // value is made available to all methods through a member rather than passed on the stack.
            ClientMarketData.CurrencyRow currencyRow = accountRow.CurrencyRow;

            // The final result of this method is a command batch that can be sent to the server.
            RemoteBatch       remoteBatch       = new RemoteBatch();
            RemoteTransaction remoteTransaction = remoteBatch.Transactions.Add();

            // Calculate the total market value for the appraisal and all the sub-accounts.  This will be the denominator
            // in all calculations involving sector percentages.  This feature makes a 'Merge' rebalancer different from a
            // 'Wrap' rebalance.  The 'Wrap' uses the sub-account's market value as the denominator when calculating
            // sector market values.
            decimal accountMarketValue = MarketValue.Calculate(accountRow.CurrencyRow, accountRow,
                                                               MarketValueFlags.EntirePosition | MarketValueFlags.IncludeChildAccounts);

            // The outline of the appraisal will be needed to make calculations based on a position, that is a security,
            // account, position type combination grouped by a security classification scheme.
            AppraisalSet appraisalSet = new Appraisal(accountRow, schemeRow, true);

            // By cycling through all the immediate children of the scheme record, we'll have covered the top-level
            // sectors in this appraisal.
            foreach (AppraisalSet.SchemeRow driverScheme in appraisalSet.Scheme)
            {
                foreach (AppraisalSet.ObjectTreeRow driverTree in driverScheme.ObjectRow.GetObjectTreeRowsByFKObjectObjectTreeParentId())
                {
                    foreach (AppraisalSet.SectorRow driverSector in driverTree.ObjectRowByFKObjectObjectTreeChildId.GetSectorRows())
                    {
                        // The appraisal set collects the ids of the records used.  We need to look up the actual sector
                        // record from the ClientMarketData in order to search through it and aggregate sub-sectors and
                        // securities.
                        ClientMarketData.SectorRow sectorRow = ClientMarketData.Sector.FindBySectorId(driverSector.SectorId);

                        // Get the market value of the top-level sector, including all subaccounts and all positions.
                        decimal actualSectorMarketValue = MarketValue.Calculate(currencyRow, accountRow,
                                                                                sectorRow, MarketValueFlags.EntirePosition | MarketValueFlags.IncludeChildAccounts);

                        // This will find the model percentage of the current top-level sector.  If the sector wasn't
                        // specified in the model, assume a value of zero, which would indicate that we're to sell the
                        // entire sector.
                        ClientMarketData.SectorTargetRow sectorTargetRow =
                            ClientMarketData.SectorTarget.FindByModelIdSectorId(modelRow.ModelId, driverSector.SectorId);
                        decimal targetPercent = sectorTargetRow == null ? 0.0M : sectorTargetRow.Percent;

                        // The target market value is calculated from the model percentage and the actual aggregate
                        // account market value.
                        decimal targetSectorMarketValue = accountMarketValue * targetPercent;

                        // Now that we have a target to shoot for, recursively descend into the structure calculating
                        // propsed orders.
                        RecurseSectors(remoteBatch, remoteTransaction, currencyRow, modelRow, driverSector.ObjectRow,
                                       actualSectorMarketValue, targetSectorMarketValue);
                    }
                }
            }

            // This object holds a complete set of proposed orders to achieve the sector targets in the model.
            return(remoteBatch);
        }
コード例 #29
0
        /// <summary>
        /// Recursively calculates proposed orders for a sector.
        /// </summary>
        /// <param name="sector">Gives the current sector (sector) for the calculation.</param>
        private static void RecurseSectors(RemoteBatch remoteBatch, RemoteTransaction remoteTransaction, ClientMarketData.ModelRow modelRow,
                                           AppraisalSet.SectorRow driverSector, decimal actualSectorMarketValue, decimal targetSectorMarketValue)
        {
            // The main idea here is to keep the ratio of the security to the sector constant, while changing the market
            // value of the sector.  Scan each of the securities belonging to this sector.
            foreach (AppraisalSet.ObjectTreeRow objectTreeRow in
                     driverSector.ObjectRow.GetObjectTreeRowsByFKObjectObjectTreeParentId())
            {
                // Cycle through each of the securities in the sector.  We're going to keep the ratio of the security the
                // same as we target a different sector total.
                foreach (AppraisalSet.SecurityRow driverSecurity in
                         objectTreeRow.ObjectRowByFKObjectObjectTreeChildId.GetSecurityRows())
                {
                    foreach (AppraisalSet.PositionRow driverPosition in driverSecurity.GetPositionRows())
                    {
                        // We need to reference the security record for calculating proposed orders and the market value
                        // of the trade.
                        ClientMarketData.SecurityRow securityRow =
                            ClientMarketData.Security.FindBySecurityId(driverSecurity.SecurityId);

                        // In this rebalancing operation, the cash balance is dependant on the securities bought and
                        // sold.  When stocks are bought or sold below, they will impact the underlying currency.  A cash
                        // target can be reached by setting all the other percentages up properly.  As long as the total
                        // percentage in a model is 100%, the proper cash target will be calculated.  We don't have to do
                        // anything with this asset type.
                        if (securityRow.SecurityTypeCode == SecurityType.Currency)
                        {
                            continue;
                        }

                        // The ratio of the security within the sector will stay constant, even though the sector may
                        // increase or decrease with the target in the model.  Note that there's only one account in the
                        // 'Accounts' table of the driver because this is a 'Wrap' operation.
                        foreach (AppraisalSet.AccountRow driverAccount in driverPosition.GetAccountRows())
                        {
                            // Find the account associated with the driver record.
                            ClientMarketData.AccountRow accountRow =
                                ClientMarketData.Account.FindByAccountId(driverAccount.AccountId);

                            // The market value of all the securities are normalized to the base currency of the account
                            // so they can be aggregated.
                            ClientMarketData.CurrencyRow currencyRow =
                                ClientMarketData.Currency.FindByCurrencyId(accountRow.CurrencyId);

                            // Sector rebalancing keeps the percentage of a security within the sector constant.  Only the
                            // overall percentage of the sector with respect to the NAV changes.  The first step in this
                            // rebalancing operation is to calculate the market value of the given position.
                            decimal actualPositionMarketValue = MarketValue.Calculate(currencyRow, accountRow,
                                                                                      securityRow, driverPosition.PositionTypeCode, MarketValueFlags.EntirePosition);

                            // The target market value operation keeps the percentage of the position constant while
                            // changing the overall sector percentage.
                            decimal targetPositionMarketValue = (actualSectorMarketValue == 0) ? 0.0M :
                                                                actualPositionMarketValue * targetSectorMarketValue / actualSectorMarketValue;

                            // Calculate the market value of an order that will achieve the target.  Note that we're not
                            // including the existing proposed orders in the market value, but we did include them when
                            // calculating the account's market value.  This allows us to put in what-if orders that will
                            // impact the market value before we do the rebalancing.
                            decimal proposedMarketValue = targetPositionMarketValue - MarketValue.Calculate(currencyRow,
                                                                                                            accountRow, securityRow, driverPosition.PositionTypeCode,
                                                                                                            MarketValueFlags.ExcludeProposedOrder);

                            // Calculate the quantity needed to hit the target market value and round it according to the
                            // model.  Note that the market values and prices are all denominated in the currency of the
                            // parent account.  Also note the quantityFactor is needed for the proper quantity
                            // calculation.
                            decimal proposedQuantity = proposedMarketValue /
                                                       (Price.Security(currencyRow, securityRow) * securityRow.QuantityFactor);

                            // If we have an equity, round to the model's lot size.
                            if (securityRow.SecurityTypeCode == SecurityType.Equity)
                            {
                                proposedQuantity = Math.Round(proposedQuantity / modelRow.EquityRounding, 0) *
                                                   modelRow.EquityRounding;
                            }

                            // A debt generally needs to be rounded to face.
                            if (securityRow.SecurityTypeCode == SecurityType.Debt)
                            {
                                proposedQuantity = Math.Round(proposedQuantity / modelRow.DebtRounding, 0) *
                                                   modelRow.DebtRounding;
                            }

                            // Have the OrderForm object construct an order based on the quantity we've calcuated
                            // from the market value.  This will fill in the defaults for the order and translate the
                            // signed quantities into transaction codes.
                            ProposedOrder.Create(remoteBatch, remoteTransaction, accountRow, securityRow,
                                                 driverAccount.PositionTypeCode, proposedQuantity);
                        }
                    }
                }

                // Recurse into each of the sub-sectors.  This allows us to rebalance with any number of levels to the
                // hierarchy.  Eventually, we will run across a sector with security positions in it and end up doing some
                // real work.
                foreach (AppraisalSet.SectorRow childSector in objectTreeRow.ObjectRowByFKObjectObjectTreeChildId.GetSectorRows())
                {
                    SectorWrap.RecurseSectors(remoteBatch, remoteTransaction, modelRow, childSector, actualSectorMarketValue, targetSectorMarketValue);
                }
            }
        }
コード例 #30
0
        /// <summary>
        /// Creates a command in a RemoteBatch structure to insert a proposed order.
        /// </summary>
        /// <param name="remoteBatch"></param>
        /// <param name="remoteTransaction"></param>
        /// <param name="accountRow"></param>
        /// <param name="securityRow"></param>
        /// <param name="positionTypeCode"></param>
        /// <param name="quantityInstruction"></param>
        private static void Insert(RemoteBatch remoteBatch, RemoteTransaction remoteTransaction,
                                   ClientMarketData.AccountRow accountRow, ClientMarketData.SecurityRow securityRow, int positionTypeCode,
                                   decimal quantityInstruction)
        {
            // These define the assembly and the types within those assemblies that will be used to create the proposed orders on
            // the middle tier.
            RemoteAssembly remoteAssembly        = remoteBatch.Assemblies.Add("Service.Core");
            RemoteType     proposedOrderType     = remoteAssembly.Types.Add("Shadows.WebService.Core.ProposedOrder");
            RemoteType     proposedOrderTreeType = remoteAssembly.Types.Add("Shadows.WebService.Core.ProposedOrderTree");

            // Find the default settlement for this order.
            int settlementId = Shadows.Quasar.Common.Security.GetDefaultSettlementId(securityRow);

            // As a convention between the rebalancing section and the order generation, the parentQuantity passed into this method
            // is a signed value where the negative values are treated as 'Sell' instructions and the positive values meaning
            // 'Buy'. This will adjust the parentQuantity so the trading methods can deal with an unsigned value, which is more
            // natural for trading.
            decimal parentQuantity = Math.Abs(quantityInstruction);

            // This will turn the signed parentQuantity into an absolute parentQuantity and a transaction code (e.g. -1000 is
            // turned into a SELL of 1000 shares).
            int parentTransactionTypeCode = TransactionType.Calculate(securityRow.SecurityTypeCode, positionTypeCode, quantityInstruction);

            // The time in force first comes from the user preferences, next, account settings and finally defaults to a day
            // orders.
            int timeInForceCode = !ClientPreferences.IsTimeInForceCodeNull() ?
                                  ClientPreferences.TimeInForceCode : !accountRow.IsTimeInForceCodeNull() ? accountRow.TimeInForceCode :
                                  TimeInForce.DAY;

            // The destination blotter comes first from the user preferences, second from the account preferences, and finally uses
            // the auto-routing logic.
            int parentBlotterId = ClientPreferences.IsBlotterIdNull() ? (accountRow.IsBlotterIdNull() ?
                                                                         TradingSupport.AutoRoute(securityRow, parentQuantity) : accountRow.BlotterId) : ClientPreferences.BlotterId;

            // Create a command to delete the relationship between the parent and child.
            RemoteMethod insertParent = proposedOrderType.Methods.Add("Insert");

            insertParent.Transaction = remoteTransaction;
            insertParent.Parameters.Add("proposedOrderId", DataType.Int, Direction.ReturnValue);
            insertParent.Parameters.Add("blotterId", parentBlotterId);
            insertParent.Parameters.Add("accountId", accountRow.AccountId);
            insertParent.Parameters.Add("securityId", securityRow.SecurityId);
            insertParent.Parameters.Add("settlementId", settlementId);
            insertParent.Parameters.Add("positionTypeCode", positionTypeCode);
            insertParent.Parameters.Add("transactionTypeCode", parentTransactionTypeCode);
            insertParent.Parameters.Add("timeInForceCode", timeInForceCode);
            insertParent.Parameters.Add("orderTypeCode", OrderType.Market);
            insertParent.Parameters.Add("quantity", parentQuantity);

            // Now it's time to create an order for the settlement currency.
            if (securityRow.SecurityTypeCode == SecurityType.Equity || securityRow.SecurityTypeCode == SecurityType.Debt)
            {
                // The underlying currency is needed for the market value calculations.
                ClientMarketData.CurrencyRow currencyRow = MarketData.Currency.FindByCurrencyId(settlementId);

                decimal marketValue = parentQuantity * securityRow.QuantityFactor * Price.Security(currencyRow, securityRow)
                                      * securityRow.PriceFactor * TransactionType.GetCashSign(parentTransactionTypeCode);

                // The stragegy for handling the settlement currency changes is to calculate the old market value, calculate the
                // new market value, and add the difference to the running total for the settlement currency of this security. The
                // new market value is the impact of the trade that was just entered.
                int childTransactionTypeCode = TransactionType.Calculate(securityRow.SecurityTypeCode, positionTypeCode,
                                                                         marketValue);
                decimal childQuantity = Math.Abs(marketValue);

                // The destination blotter comes first from the user preferences, second from the account preferences, and finally
                // uses the auto-routing logic.
                int childBlotterId = ClientPreferences.IsBlotterIdNull() ? (accountRow.IsBlotterIdNull() ?
                                                                            TradingSupport.AutoRoute(currencyRow.SecurityRow, childQuantity) : accountRow.BlotterId) :
                                     ClientPreferences.BlotterId;

                // Fill in the rest of the fields and the defaulted fields for this order. Create a command to delete the
                // relationship between the parent and child.
                RemoteMethod insertChild = proposedOrderType.Methods.Add("Insert");
                insertChild.Transaction = remoteTransaction;
                insertChild.Parameters.Add("proposedOrderId", DataType.Int, Direction.ReturnValue);
                insertChild.Parameters.Add("blotterId", childBlotterId);
                insertChild.Parameters.Add("accountId", accountRow.AccountId);
                insertChild.Parameters.Add("securityId", settlementId);
                insertChild.Parameters.Add("settlementId", settlementId);
                insertChild.Parameters.Add("transactionTypeCode", childTransactionTypeCode);
                insertChild.Parameters.Add("positionTypeCode", positionTypeCode);
                insertChild.Parameters.Add("timeInForceCode", timeInForceCode);
                insertChild.Parameters.Add("orderTypeCode", OrderType.Market);
                insertChild.Parameters.Add("quantity", childQuantity);

                RemoteMethod insertRelation = proposedOrderTreeType.Methods.Add("Insert");
                insertRelation.Transaction = remoteTransaction;
                insertRelation.Parameters.Add("parentId", insertParent.Parameters["proposedOrderId"]);
                insertRelation.Parameters.Add("childId", insertChild.Parameters["proposedOrderId"]);
            }
        }