/// <summary> /// Handles a change to the Price table. /// </summary> /// <param name="sender">The object that originated the event.</param> /// <param name="priceRowChangeEventArgs">The event arguments.</param> protected virtual void OnPriceRowChanged(Object sender, DataModel.PriceRowChangeEventArgs priceRowChangeEventArgs) { // Validate the parameters. if (sender == null) { throw new ArgumentNullException("sender"); } if (priceRowChangeEventArgs == null) { throw new ArgumentNullException("priceRowChangeEventArgs"); } // We're only interested in adds and changes. if (priceRowChangeEventArgs.Action == DataRowAction.Add || priceRowChangeEventArgs.Action == DataRowAction.Change) { // Select all the WorkingOrderRows that are related to the Securities that are related to the PriceRow that has changed. We are looking for // changes to the price of items displayed in this blotter. DataModel.SecurityRow securityRow = priceRowChangeEventArgs.Row.SecurityRowByFK_Security_Price_SecurityId; var workingOrderRows = from workingOrderRow in securityRow.GetWorkingOrderRowsByFK_Security_WorkingOrder_SecurityId() select workingOrderRow; // Iterate through all the rows affected by the change to the Price row and update the properties related to the entity table. foreach (DataModel.WorkingOrderRow workingOrderRow in workingOrderRows) { if (this.blotterIdSet.Contains(workingOrderRow.BlotterId)) { // This will copy and commit the changes made to the Price row to the WorkingOrder record. Int32 index = this.BinarySearch(order => order.WorkingOrderId, workingOrderRow.WorkingOrderId); if (index >= 0) { // These factors are used display the market value using the notations provided for price and quantity. Decimal quantityFactor = workingOrderRow.SecurityRowByFK_Security_WorkingOrder_SecurityId.QuantityFactor; Decimal priceFactor = workingOrderRow.SecurityRowByFK_Security_WorkingOrder_SecurityId.PriceFactor; // This sets the prices and updates any field related to the prices. TType workingOrder = this[index]; this.workingOrderCollectionView.EditItem(workingOrder); workingOrder.AskPrice.Price = priceRowChangeEventArgs.Row.AskPrice; workingOrder.BidPrice.Price = priceRowChangeEventArgs.Row.BidPrice; workingOrder.LastPrice.Price = priceRowChangeEventArgs.Row.LastPrice; workingOrder.MarketValue = workingOrder.SourceOrderQuantity * quantityFactor * workingOrder.LastPrice.Price * priceFactor; this.workingOrderCollectionView.CommitEdit(); } } } } }
/// <summary> /// Copies the outline of a security position from the data model into the AppraisalSet. /// </summary> /// <param name="AccountId">AccountId of the position to search through.</param> /// <param name="SecurityId">SecurityId of the position to search through.</param> /// <param name="PositionTypeCode">Position Type Code of the position to search through.</param> /// <remarks> /// Table locks needed: /// Read: Security /// </remarks> protected void BuildSecurity(int AccountId, int SecurityId, int PositionTypeCode) { // See if the given security exists already in the table of security. If this is the first time we've // encountered this security, we need to add it to the driver tables and then recursively search the hierarchy // and add every parent sector all the way up to the security classification scheme. If we've run across it // already, we don't need to do anything related to the security. AppraisalSet.SecurityRow driverSecurity = this.Security.FindBySecurityId(SecurityId); if (driverSecurity == null) { // The AppraisalSet structure mirrors the structure of the MarketData. We have a common 'object' table that // all object can use to navigate the tree structure. When adding a new element to the data structure, // we need to add the object first to maintain integrity, then the security can be added. AppraisalSet.ObjectRow objectRow = this.Object.AddObjectRow(SecurityId); driverSecurity = this.Security.AddSecurityRow(objectRow); // Recursively search the hierarchy all the way up to the security classification scheme. This will add // any elements of the hierarchy that are not already part of the outline. Note that we first check to // see if the security belongs to the given security scheme before building the links. This saves us from // having unused fragments of other security scheme in the outline. This is useful when checking for // unclassified security. DataModel.SecurityRow securityRow = DataModel.Security.FindBySecurityId(SecurityId); if (IsObjectInScheme(securityRow.ObjectRow)) { BuildSector(securityRow.ObjectRow); BuildScheme(securityRow.ObjectRow); } } // At this point, we know that the security and all the sector have been added to the outline. Check to see // if the position -- that is, the combination of security and whether we own it or have borrowed it -- exist // in the outline. Add the combination if it doesn't. AppraisalSet.PositionRow positionRow = this.Position.FindBySecurityIdPositionTypeCode(SecurityId, PositionTypeCode); if (positionRow == null) { positionRow = this.Position.AddPositionRow(driverSecurity, PositionTypeCode); } // Finally, at the bottom of the list, is the account level information. This operation insures that only distinct account/position combinations // appear in the document. This is very useful if the same account were to appear in different groups. AppraisalSet.AccountRow driverAccount = this.Account.FindByAccountIdSecurityIdPositionTypeCode(AccountId, SecurityId, PositionTypeCode); if (driverAccount == null) { driverAccount = this.Account.AddAccountRow(AccountId, SecurityId, PositionTypeCode); } }
/// <summary> /// Handles a change to the DestinationOrder table. /// </summary> /// <param name="sender">The object that originated the event.</param> /// <param name="e">The event data.</param> static void OnDestinationOrderRowChanged(object sender, DataModel.DestinationOrderRowChangeEventArgs e) { // This will turn new DestinationOrder records into orders that can be sent to a destination for execution. if (e.Action == DataRowAction.Add) { // The current transaction is going to be needed to lock records. DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction; // Create a new message for the order we're going to build from the DestinationOrder. Message message = new Message(); // The market execution engine will need to know the source firm so it knows how to route the order back. OrganizationPrincipal organizationPrincipal = Thread.CurrentPrincipal as OrganizationPrincipal; message.SenderCompID = organizationPrincipal.Organization; // Copy the basic properties of the DestinationOrder into the message. DataModel.DestinationOrderRow destinationOrderRow = e.Row; message.ClOrdID = destinationOrderRow.DestinationOrderId.ToString(); message.OrderQty = destinationOrderRow.OrderedQuantity; message.OrdType = destinationOrderRow.OrderTypeCode; message.SideCode = destinationOrderRow.SideCode; message.TimeInForceCode = destinationOrderRow.TimeInForceCode; // Get the symbol to use as a security identifier. DataModel.SecurityRow securityRow = destinationOrderRow.SecurityRowByFK_Security_DestinationOrder_SecurityId; securityRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout); dataModelTransaction.AddLock(securityRow); if (securityRow.RowState == DataRowState.Detached) { throw new FaultException <RecordNotFoundFault>(new RecordNotFoundFault("Security", new Object[] { destinationOrderRow.SecurityId })); } message.Symbol = securityRow.Symbol; // This will put the new order in a queue. The DestinatonThread will pull it out, batch it up and send it to the destination to be executed. lock (MarketEngine.syncRoot) { MarketEngine.messageQueue.Enqueue(message); if (messageQueue.Count == 1) { MarketEngine.orderEvent.Set(); } } } }
public static int GetDefaultSettlementId(DataModel.SecurityRow securityRow) { // A settlement price is required to find the price of a security. For many issues, the default can be found from // the defaults. Others, such as currency transaction and exotic deals require an explicit settlement currency to // determine the price. foreach (DataModel.CurrencyRow currencyRow in securityRow.GetCurrencyRows()) { return(currencyRow.CurrencyId); } foreach (DataModel.DebtRow debtRow in securityRow.GetDebtRowsByFKSecurityDebtDebtId()) { return(debtRow.SettlementId); } foreach (DataModel.EquityRow equityRow in securityRow.GetEquityRowsByFKSecurityEquityEquityId()) { return(equityRow.SettlementId); } // Failure to find a settlement currency is a serious matter. throw new Exception(String.Format("Security {0} has no settlement currecy.", securityRow.SecurityId)); }
public static int GetDefaultSettlementId(int SecurityId) { try { // Lock the tables. Debug.Assert(!DataModel.IsLocked); DataModel.DebtLock.AcquireReaderLock(Timeout.Infinite); DataModel.EquityLock.AcquireReaderLock(Timeout.Infinite); DataModel.SecurityLock.AcquireReaderLock(Timeout.Infinite); // Make sure the security exists. We need it to find the default settlement security. DataModel.SecurityRow securityRow = DataModel.Security.FindBySecurityId(SecurityId); if (securityRow == null) { throw new Exception(String.Format("Security {0} doesn't exist", SecurityId)); } // This version of the method assumes that the locks have been aquired. return(GetDefaultSettlementId(securityRow)); } finally { // Release the table locks. if (DataModel.DebtLock.IsReaderLockHeld) { DataModel.DebtLock.ReleaseReaderLock(); } if (DataModel.EquityLock.IsReaderLockHeld) { DataModel.EquityLock.ReleaseReaderLock(); } if (DataModel.SecurityLock.IsReaderLockHeld) { DataModel.SecurityLock.ReleaseReaderLock(); } Debug.Assert(!DataModel.IsLocked); } }
public static int AutoRoute(DataModel.SecurityRow securityRow, decimal quantity) { // Use a blotter route for the security if it exists. foreach (DataModel.BlotterMapRow blotterMapRow in securityRow.GetBlotterMapRows()) { if (blotterMapRow.MinimumQuantity <= quantity && (blotterMapRow.IsMaximumQuantityNull() || quantity <= blotterMapRow.MaximumQuantity)) { return(blotterMapRow.BlotterId); } } // Return the default blotter. foreach (DataModel.BlotterRow blotterRow in DataModel.Blotter) { if (blotterRow.DefaultBlotter) { return(blotterRow.BlotterId); } } throw new Exception("Default Blotter is not set."); }
/// <summary> /// Calculates the price of a security. /// </summary> /// <param name="baseCurrency">The demonimation of the price.</param> /// <param name="securityRow">The security to be priced.</param> /// <returns>The price of the security in the requested denomination.</returns> public static decimal Security(DataModel.CurrencyRow baseCurrency, DataModel.SecurityRow securityRow) { // Calculate the price of a Currency. foreach (DataModel.CurrencyRow currencyRow in securityRow.GetCurrencyRows()) { return(Price.Currency(baseCurrency, currencyRow)); } // Calculate the price of a Debt. foreach (DataModel.DebtRow debtRow in securityRow.GetDebtRowsByFKSecurityDebtDebtId()) { return(Price.Debt(baseCurrency, debtRow)); } // Calculate the price of an Equity. foreach (DataModel.EquityRow equityRow in securityRow.GetEquityRowsByFKSecurityEquityEquityId()) { return(Price.Equity(baseCurrency, equityRow)); } // If the security isn't one of the major securityType, then it can't be priced. return(0.0M); }
/// <summary> /// Create an debt working order. /// </summary> void CreateDebt() { // All orders get a unique identifier. Guid workingOrderId = Guid.NewGuid(); // These records provide the starting point for generating the orders. DataModel.BlotterRow blotterRow = DataModel.Blotter.BlotterKey.Find(generatorInfo.BlotterId); DataModel.UserRow userRow = DataModel.User.UserKey.Find(generatorInfo.UserId); DataModel.CountryRow unitedStatesRow = DataModel.Country.CountryKeyExternalId0.Find("US"); DataModel.StatusRow statusRow = DataModel.Status.StatusKey.Find(StatusCode.New); // Generate the settlement currency DataModel.EntityRow usdEntityRow = DataModel.Entity.EntityKeyExternalId0.Find("USD"); DataModel.SecurityRow settlementCurrencyRow = DataModel.Security.SecurityKey.Find(usdEntityRow.EntityId); // The orders are an even mix of Buys and Sells. Most positions are long. Boolean isBuy = random.Next(2) == 0; Boolean isLong = random.Next(4) != 0; SideCode sideCode = isBuy && isLong ? SideCode.Buy : !isBuy && isLong ? SideCode.Sell : isBuy && !isLong ? SideCode.BuyCover : SideCode.SellShort; DataModel.SideRow sideRow = DataModel.Side.SideKey.Find(sideCode); // Find a random debt position that is unique to this blotter. DataModel.SecurityRow securityRow = null; while (securityRow == null) { // Select a random debt instrument for the next order. DataModel.DebtRow debtRow = DataModel.Debt[random.Next(DataModel.Debt.Count - 1)]; // Only generate orders for positions that are unique to this blotter. Position position = new Position(debtRow.DebtId, sideCode); if (!positionSet.Contains(position)) { securityRow = debtRow.SecurityRowByFK_Security_Debt_DebtId; positionSet.Add(position); } } // These orders will not match by default. We need to turn them on manually. DataModel.CrossingRow crossingRow = DataModel.Crossing.CrossingKey.Find(CrossingCode.NeverMatch); // Select a random Time In Force for this order. Most orders are Day orders but occationally we'll generate a GTC just to keep it interesting. TimeInForceCode timeInForce = random.Next(4) == 0 ? TimeInForceCode.GoodTillCancel : TimeInForceCode.Day; DataModel.TimeInForceRow timeInForceRow = DataModel.TimeInForce.TimeInForceKey.Find(timeInForce); // Generate the trade and settlement dates based on the current time and make sure it doesn't fall on a weekend. DateTime tradeDate = DateTime.Now; DateTime settlementDate = DateTime.Now; TimeSpan oneDay = TimeSpan.FromDays(1.0); for (Int32 dayIndex = 0; dayIndex < 3; dayIndex++) { settlementDate += oneDay; if (settlementDate.DayOfWeek == DayOfWeek.Saturday) { settlementDate += oneDay; } if (settlementDate.DayOfWeek == DayOfWeek.Sunday) { settlementDate += oneDay; } } // This will generate random matching preferences for the orders for demonstrating the matching box capabilities. Boolean isBrokerMatch = random.Next(20) == 0; Boolean isHedgeMatch = random.Next(15) == 0; Boolean isInstitutionMatch = true; // This randomizes the random matching patterns. Every now and then, don't match with anyone. if (random.Next(5) == 0) { isBrokerMatch = false; isHedgeMatch = false; isInstitutionMatch = false; } // <transaction> XElement elementTransaction = new XElement("transaction"); this.xDocument.Root.Add(elementTransaction); // <method name="StoreWorkingOrder"> XElement elementWorkingOrder = new XElement("method", new XAttribute("name", "StoreWorkingOrder")); elementTransaction.Add(elementWorkingOrder); // <parameter name="blotterKey" value="EMERGING MARKETS BLOTTER" /> elementWorkingOrder.Add( new XElement("parameter", new XAttribute("name", "blotterKey"), new XAttribute("value", blotterRow.EntityRow.ExternalId0))); // <parameter name="configurationId" value="US TICKER" /> elementWorkingOrder.Add(new XElement("parameter", new XAttribute("name", "configurationId"), new XAttribute("value", "CUSIP"))); // <parameter name="createdTime" value="5/6/2012 5:27:56 PM" /> elementWorkingOrder.Add(new XElement("parameter", new XAttribute("name", "createdTime"), new XAttribute("value", DateTime.Now.ToString("G")))); // <parameter name="crossingKey" value="NEVER MATCH" /> elementWorkingOrder.Add(new XElement("parameter", new XAttribute("name", "crossingKey"), new XAttribute("value", crossingRow.ExternalId0))); // <parameter name="externalId0" value="{bab88942-5c4e-440a-a352-c8e9b00fec12}" /> elementWorkingOrder.Add(new XElement("parameter", new XAttribute("name", "externalId0"), new XAttribute("value", workingOrderId.ToString("B")))); // <parameter name="isBrokerMatch" value="false" /> elementWorkingOrder.Add(new XElement("parameter", new XAttribute("name", "isBrokerMatch"), new XAttribute("value", isBrokerMatch))); // <parameter name="isHedgeMatch" value="false" /> elementWorkingOrder.Add(new XElement("parameter", new XAttribute("name", "isHedgeMatch"), new XAttribute("value", isHedgeMatch))); // <parameter name="isInstitutionMatch" value="true" /> elementWorkingOrder.Add(new XElement("parameter", new XAttribute("name", "isInstitutionMatch"), new XAttribute("value", isInstitutionMatch))); // <parameter name="modifiedTime" value="5/6/2012 5:27:56 PM" /> elementWorkingOrder.Add(new XElement("parameter", new XAttribute("name", "modifiedTime"), new XAttribute("value", DateTime.Now.ToString("G")))); // <parameter name="orderTypeKey" value="MKT" /> elementWorkingOrder.Add(new XElement("parameter", new XAttribute("name", "orderTypeKey"), new XAttribute("value", "MKT"))); // <parameter name="securityKeyBySecurityId" value="ODP" /> elementWorkingOrder.Add( new XElement("parameter", new XAttribute("name", "securityKeyBySecurityId"), new XAttribute("value", securityRow.EntityRow.ExternalId4))); // <parameter name="securityKeyBySettlementId" value="USD" /> elementWorkingOrder.Add( new XElement("parameter", new XAttribute("name", "securityKeyBySettlementId"), new XAttribute("value", settlementCurrencyRow.EntityRow.ExternalId0))); // <parameter name="settlementDate" value="5/9/2012 5:27:56 PM" /> elementWorkingOrder.Add(new XElement("parameter", new XAttribute("name", "settlementDate"), new XAttribute("value", settlementDate.ToString("G")))); // <parameter name="sideKey" value="SELL" /> elementWorkingOrder.Add(new XElement("parameter", new XAttribute("name", "sideKey"), new XAttribute("value", sideRow.ExternalId0))); // <parameter name="statusKey" value="NEW" /> elementWorkingOrder.Add(new XElement("parameter", new XAttribute("name", "statusKey"), new XAttribute("value", statusRow.ExternalId0))); // <parameter name="timeInForceKey" value="DAY" /> elementWorkingOrder.Add(new XElement("parameter", new XAttribute("name", "timeInForceKey"), new XAttribute("value", timeInForceRow.ExternalId0))); // <parameter name="tradeDate" value="5/6/2012 5:27:56 PM" /> elementWorkingOrder.Add(new XElement("parameter", new XAttribute("name", "tradeDate"), new XAttribute("value", tradeDate.ToString("G")))); // <parameter name="userKeyByCreatedUserId" value="DEV KAPOOR" /> elementWorkingOrder.Add( new XElement("parameter", new XAttribute("name", "userKeyByCreatedUserId"), new XAttribute("value", userRow.EntityRow.ExternalId0))); // <parameter name="userKeyByModifiedUserId" value="DEV KAPOOR" /> elementWorkingOrder.Add( new XElement("parameter", new XAttribute("name", "userKeyByModifiedUserId"), new XAttribute("value", userRow.EntityRow.ExternalId0))); // This will generate between one and three source orders for the working order. Source orders are a blocking concept. You can get several orders for // the same security on the same side for the same price. When this happens, it is much more efficient to block them as a single order and execute them // as a single order and allocate them back to the original orders when the order is done. Int32 sourceOrderCount = random.Next(1, 3); for (Int32 sourceOrderIndex = 0; sourceOrderIndex < sourceOrderCount; sourceOrderIndex++) { // This creates a unique identifier for the source order. Guid sourceOrderId = Guid.NewGuid(); // This generates a random quantity for the order between 100 and 10,000 shares. Decimal orderedQuantity = Convert.ToDecimal(random.Next(1, 100)) * 100.0M; // <method name="StoreSourceOrder"> XElement elementSourceOrder = new XElement("method", new XAttribute("name", "StoreSourceOrder")); elementTransaction.Add(elementSourceOrder); // <parameter name="configurationId" value="US TICKER" /> elementSourceOrder.Add(new XElement("parameter", new XAttribute("name", "configurationId"), new XAttribute("value", "CUSIP"))); // <parameter name="createdTime" value="2012-05-06T17:27:56.2658093-04:00" /> elementSourceOrder.Add(new XElement("parameter", new XAttribute("name", "createdTime"), new XAttribute("value", DateTime.Now))); // <parameter name="externalId0" value="{3c69e0a0-3316-4499-a7b1-6dda5a058837}" /> elementSourceOrder.Add(new XElement("parameter", new XAttribute("name", "externalId0"), new XAttribute("value", sourceOrderId.ToString("B")))); // <parameter name="modifiedTime" value="5/6/2012 5:27:56 PM" /> elementSourceOrder.Add(new XElement("parameter", new XAttribute("name", "modifiedTime"), new XAttribute("value", DateTime.Now.ToString("G")))); // <parameter name="orderedQuantity" value="4300.0" /> elementSourceOrder.Add(new XElement("parameter", new XAttribute("name", "orderedQuantity"), new XAttribute("value", orderedQuantity))); // <parameter name="orderTypeKey" value="MKT" /> elementSourceOrder.Add(new XElement("parameter", new XAttribute("name", "orderTypeKey"), new XAttribute("value", "MKT"))); // <parameter name="securityKeyBySecurityId" value="ODP" /> elementSourceOrder.Add( new XElement("parameter", new XAttribute("name", "securityKeyBySecurityId"), new XAttribute("value", securityRow.EntityRow.ExternalId4))); // <parameter name="securityKeyBySettlementId" value="USD" /> elementSourceOrder.Add( new XElement("parameter", new XAttribute("name", "securityKeyBySettlementId"), new XAttribute("value", settlementCurrencyRow.EntityRow.ExternalId0))); // <parameter name="settlementDate" value="2012-05-09T17:27:56.2528086-04:00" /> elementSourceOrder.Add(new XElement("parameter", new XAttribute("name", "settlementDate"), new XAttribute("value", settlementDate))); // <parameter name="sideKey" value="SELL" /> elementSourceOrder.Add(new XElement("parameter", new XAttribute("name", "sideKey"), new XAttribute("value", sideRow.ExternalId0))); // <parameter name="statusKey" value="NEW" /> elementSourceOrder.Add(new XElement("parameter", new XAttribute("name", "statusKey"), new XAttribute("value", statusRow.ExternalId0))); // <parameter name="timeInForceKey" value="DAY" /> elementSourceOrder.Add( new XElement("parameter", new XAttribute("name", "timeInForceKey"), new XAttribute("value", timeInForceRow.ExternalId0))); // <parameter name="tradeDate" value="5/6/2012 5:27:56 PM" /> elementSourceOrder.Add(new XElement("parameter", new XAttribute("name", "tradeDate"), new XAttribute("value", tradeDate.ToString("G")))); // <parameter name="userKeyByCreatedUserId" value="DEV KAPOOR" /> elementSourceOrder.Add( new XElement("parameter", new XAttribute("name", "userKeyByCreatedUserId"), new XAttribute("value", userRow.EntityRow.ExternalId0))); // <parameter name="userKeyByModifiedUserId" value="DEV KAPOOR" /> elementSourceOrder.Add( new XElement("parameter", new XAttribute("name", "userKeyByModifiedUserId"), new XAttribute("value", userRow.EntityRow.ExternalId0))); // <parameter name="workingOrderKey" value="{bab88942-5c4e-440a-a352-c8e9b00fec12}" /> elementSourceOrder.Add( new XElement("parameter", new XAttribute("name", "workingOrderKey"), new XAttribute("value", workingOrderId.ToString("B")))); } }
/// <summary> /// Calculates the market value of a position. /// </summary> /// <param name="baseCurrency">The base currency for the market value calculation.</param> /// <param name="accountRow">The identifier of the account.</param> /// <param name="SecurityId">The identifier of the security.</param> /// <param name="PositionTypeCode">The PositionTypeCode (long or short).</param> /// <param name="marketValueFlags">These flags direct what elements are included and whether to include /// children.</param> /// <returns></returns> public static decimal Calculate(DataModel.CurrencyRow baseCurrency, DataModel.AccountRow accountRow, DataModel.SecurityRow securityRow, int PositionTypeCode, MarketValueFlags marketValueFlags) { // This is the accumulator for market value. decimal marketValue = 0.0M; // Aggregate Tax Lots if ((marketValueFlags & MarketValueFlags.IncludeTaxLot) != 0) { foreach (DataModel.TaxLotRow taxLotRow in accountRow.GetTaxLotRows()) { if (taxLotRow.SecurityId == securityRow.SecurityId && taxLotRow.PositionTypeCode == PositionTypeCode) { marketValue += Calculate(baseCurrency, taxLotRow); } } } // Aggregate Proposed Order if ((marketValueFlags & MarketValueFlags.IncludeProposedOrder) != 0) { foreach (DataModel.ProposedOrderRow proposedOrderRow in accountRow.GetProposedOrderRows()) { if (proposedOrderRow.SecurityId == securityRow.SecurityId && proposedOrderRow.PositionTypeCode == PositionTypeCode) { marketValue += Calculate(baseCurrency, proposedOrderRow); } } } // Aggregate Order if ((marketValueFlags & MarketValueFlags.IncludeOrder) != 0) { foreach (DataModel.OrderRow SetPrice in accountRow.GetOrderRows()) { if (SetPrice.SecurityId == securityRow.SecurityId && SetPrice.PositionTypeCode == PositionTypeCode) { marketValue += Calculate(baseCurrency, SetPrice); } } } // Aggregate Allocation if ((marketValueFlags & MarketValueFlags.IncludeAllocation) != 0) { foreach (DataModel.AllocationRow allocationRow in accountRow.GetAllocationRows()) { if (allocationRow.SecurityId == securityRow.SecurityId && allocationRow.PositionTypeCode == PositionTypeCode) { marketValue += Calculate(baseCurrency, allocationRow); } } } // If sub-account are to be included, recurse into the account structures. if ((marketValueFlags & MarketValueFlags.IncludeChildAccounts) != 0) { foreach (DataModel.ObjectTreeRow objectTreeRow in accountRow.ObjectRow.GetObjectTreeRowsByFKObjectObjectTreeParentId()) { foreach (DataModel.AccountRow childAccount in objectTreeRow.ObjectRowByFKObjectObjectTreeChildId.GetAccountRows()) { marketValue += Calculate(baseCurrency, childAccount, securityRow, PositionTypeCode, marketValueFlags); } } } // This is the market value of the given account/security/position combination. return(marketValue); }
/// <summary> /// Calculates the number of shares in a given position. /// </summary> /// <param name="baseCurrency">The base currency for the market value calculation.</param> /// <param name="AccountId">The identifier of the account.</param> /// <param name="SecurityId">The identifier of the security.</param> /// <param name="positionTypeCode">The PositionTypeCode (long or short).</param> /// <param name="quantityFlags">These flags direct what elements are included and whether to include /// children.</param> /// <returns></returns> public static decimal Calculate(DataModel.AccountRow accountRow, DataModel.SecurityRow securityRow, int positionTypeCode, MarketValueFlags quantityFlags) { // This is the accumulator for market value. decimal quantity = 0.0M; // This key is used to find records that match the given position. object[] key = new object[] { accountRow.AccountId, securityRow.SecurityId, positionTypeCode }; // Aggregate Tax Lots if ((quantityFlags & MarketValueFlags.IncludeTaxLot) != 0) { foreach (DataRowView dataRowView in DataModel.TaxLot.UKTaxLotAccountIdSecurityIdPositionTypeCode.FindRows(key)) { quantity += ((DataModel.TaxLotRow)dataRowView.Row).Quantity; } } // Aggregate Proposed Order if ((quantityFlags & MarketValueFlags.IncludeProposedOrder) != 0) { foreach (DataRowView dataRowView in DataModel.ProposedOrder.UKProposedOrderAccountIdSecurityIdPositionTypeCode.FindRows(key)) { DataModel.ProposedOrderRow proposedProposedOrderRow = (DataModel.ProposedOrderRow)dataRowView.Row; quantity += proposedProposedOrderRow.Quantity * proposedProposedOrderRow.TransactionTypeRow.QuantitySign; } } // Aggregate Order if ((quantityFlags & MarketValueFlags.IncludeOrder) != 0) { foreach (DataRowView dataRowView in DataModel.Order.UKOrderAccountIdSecurityIdPositionTypeCode.FindRows(key)) { DataModel.OrderRow orderRow = (DataModel.OrderRow)dataRowView.Row; quantity += orderRow.Quantity * orderRow.TransactionTypeRow.QuantitySign; } } // Aggregate Allocation if ((quantityFlags & MarketValueFlags.IncludeAllocation) != 0) { foreach (DataRowView dataRowView in DataModel.Allocation.UKAllocationAccountIdSecurityIdPositionTypeCode.FindRows(key)) { DataModel.AllocationRow allocationRow = (DataModel.AllocationRow)dataRowView.Row; quantity += allocationRow.Quantity * allocationRow.TransactionTypeRow.QuantitySign; } } // If sub-account are to be included, recurse into the account structures. if ((quantityFlags & MarketValueFlags.IncludeChildAccounts) != 0) { foreach (DataModel.ObjectTreeRow objectTreeRow in accountRow.ObjectRow.GetObjectTreeRowsByFKObjectObjectTreeParentId()) { foreach (DataModel.AccountRow childAccount in objectTreeRow.ObjectRowByFKObjectObjectTreeChildId.GetAccountRows()) { quantity += Calculate(childAccount, securityRow, positionTypeCode, quantityFlags); } } } // This is the market value of the given account/security/position combination. return(quantity); }
/// <summary> /// Calculates the quantity of child order for a given position /// </summary> /// <param name="AccountId">The identifier of the account.</param> /// <param name="SecurityId">The identifier of the security.</param> /// <param name="positionTypeCode">The positionTypeCode (long or short).</param> /// <returns>The quantity of the child proposedOrder.</returns> public static decimal CalculateChildProposedQuantity(DataModel.AccountRow accountRow, DataModel.SecurityRow securityRow, int positionTypeCode) { // This is the accumulator for market value. decimal quantity = 0.0M; // Aggregate Proposed Order foreach (DataModel.ProposedOrderRow proposedOrderRow in accountRow.GetProposedOrderRows()) { if (Relationship.IsChildProposedOrder(proposedOrderRow) && proposedOrderRow.SecurityId == securityRow.SecurityId && proposedOrderRow.PositionTypeCode == positionTypeCode) { quantity += proposedOrderRow.Quantity * proposedOrderRow.TransactionTypeRow.QuantitySign; } } // If sub-account are to be included, recurse into the account structures. foreach (DataModel.ObjectTreeRow objectTreeRow in accountRow.ObjectRow.GetObjectTreeRowsByFKObjectObjectTreeParentId()) { foreach (DataModel.AccountRow childAccount in objectTreeRow.ObjectRowByFKObjectObjectTreeChildId.GetAccountRows()) { quantity += CalculateChildProposedQuantity(childAccount, securityRow, positionTypeCode); } } // This is the market value of the given account/security/position combination. return(quantity); }
/// <summary> /// Creates orders in the simulated order book. /// </summary> private static void OrderHandler() { // This thread will create orders in the simulated order book from destination orders placed in the queue. This thread // is necessary due to the locking architecture that prevents accessing the data model during a commit operation (which // is where the event indicating a new or changed destination order originates). while (MarketSimulator.IsBrokerSimulatorThreadRunning) { // This thread will wait here until a destination order is available in the queue. DataModel.DestinationOrderRow destinationOrderRow = MarketSimulator.orderQueue.Dequeue(); // The code that adds an order to the simulated book must have exclusive access to the simulated data model. lock (MarketSimulator.syncRoot) { // The primary data model needs to be accessed also for ancillary data associated with the new order. using (TransactionScope transactionScope = new TransactionScope()) { try { // This context is used to keep track of the locks aquired for the ancillary data. DataModelTransaction dataModelTransaction = DataModel.CurrentTransaction; // Lock the destination order. destinationOrderRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout); dataModelTransaction.AddLock(destinationOrderRow); // Lock the Security. DataModel.SecurityRow securityRow = destinationOrderRow.SecurityRowByFK_Security_DestinationOrder_SecurityId; securityRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout); dataModelTransaction.AddLock(securityRow); // The working order row must be locked to examine the flags DataModel.WorkingOrderRow workingOrderRow = destinationOrderRow.WorkingOrderRow; workingOrderRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout); dataModelTransaction.AddLock(workingOrderRow); // Lock the Entity. DataModel.EntityRow entityRow = securityRow.EntityRow; entityRow.AcquireReaderLock(dataModelTransaction.TransactionId, DataModel.LockTimeout); dataModelTransaction.AddLock(entityRow); // Calculate the quantity executed on this order (some orders are created with executions, such as crossed orders.) Decimal quantityExecuted = 0.0M; foreach (DataModel.ExecutionRow executionRow in destinationOrderRow.GetExecutionRows()) { executionRow.AcquireReaderLock(dataModelTransaction); dataModelTransaction.AddLock(executionRow); quantityExecuted += executionRow.ExecutionQuantity; } // The simulated order is added to the book. This collects all the information required to simulate the execution of this order. DataSetMarket.OrderRow orderRow = MarketSimulator.dataSetMarket.Order.NewOrderRow(); orderRow.BlotterId = destinationOrderRow.BlotterId; orderRow.DestinationOrderId = destinationOrderRow.DestinationOrderId; orderRow.OrderTypeCode = OrderTypeMap.FromId(destinationOrderRow.OrderTypeId); orderRow.QuantityOrdered = destinationOrderRow.OrderedQuantity; orderRow.QuantityExecuted = quantityExecuted; orderRow.SideCode = SideMap.FromId(destinationOrderRow.SideId); orderRow.Symbol = securityRow.Symbol; orderRow.TimeInForceCode = TimeInForceMap.FromId(destinationOrderRow.TimeInForceId); MarketSimulator.dataSetMarket.Order.AddOrderRow(orderRow); // Adding the first order to the simulated order book will enable the simulation thread to begin processing the orders. The order // simulation thread will continue until the book is filled. if (MarketSimulator.dataSetMarket.Order.Count == 1) { MarketSimulator.orderEvent.Set(); } } catch { } // The locks are no longer required. transactionScope.Complete(); } } } }