/// <summary> /// Relieves the passed Taxlot /// </summary> /// <param name="env">Environment</param> /// <param name="lot">The Tax Lot to relieve</param> /// <param name="trade">The current trade</param> /// <param name="quantity">Quantity to relieve</param> /// <param name="fxrate">Appropriate fxrate</param> internal static TaxLot RelieveTaxLot(PostingEngineEnvironment env, TaxLotDetail lot, Transaction trade, double quantity, bool reverse = false) { var prevFxRate = FxRates.Find(lot.Trade.TradeDate, lot.Trade.SettleCurrency).Rate; var investmentAtCost = quantity * lot.Trade.SettleNetPrice * prevFxRate; if (reverse) { investmentAtCost = investmentAtCost * -1; } var tl = new TaxLot { Trade = trade, TradeDate = trade.TradeDate, InvestmentAtCost = investmentAtCost, // Needs to be the Investment Cost that we are relieving from the Tax BusinessDate = env.ValueDate, OpeningLotId = lot.Trade.LpOrderId, ClosingLotId = trade.LpOrderId, TradePrice = lot.Trade.SettleNetPrice, CostBasis = trade.SettleNetPrice, Quantity = quantity }; CalculateRealizedPnl(env, tl); tl.Save(env.Connection, env.Transaction); return(tl); }
/// <summary> /// Calculate the Realized Pnl based on the relieved Tax Lot /// </summary> /// <param name="createdTaxLot">The Relief</param> /// <param name="taxLotToRelieve">The target taxlot</param> public static double CalculateRealizedPnl(PostingEngineEnvironment env, TaxLot createdTaxLot) { var priceDiff = (createdTaxLot.CostBasis - createdTaxLot.TradePrice); var realizedPnl = 0.0; double multiplier = 1.0; if (env.SecurityDetails.ContainsKey(createdTaxLot.Trade.BloombergCode)) { multiplier = env.SecurityDetails[createdTaxLot.Trade.BloombergCode].Multiplier; } double fxrate = 1.0; // Lets get fx rate if needed if (!createdTaxLot.Trade.SettleCurrency.Equals(env.BaseCurrency)) { fxrate = Convert.ToDouble(FxRates.Find(env.ValueDate, createdTaxLot.Trade.SettleCurrency).Rate); } if (createdTaxLot.Trade.IsBuy()) { realizedPnl = priceDiff * createdTaxLot.Quantity; } else if (createdTaxLot.Trade.IsSell()) { realizedPnl = priceDiff * Math.Abs(createdTaxLot.Quantity); } else if (createdTaxLot.Trade.IsShort()) { realizedPnl = priceDiff * createdTaxLot.Quantity; } else if (createdTaxLot.Trade.IsCover()) { realizedPnl = priceDiff * createdTaxLot.Quantity * -1; } createdTaxLot.RealizedPnl = realizedPnl * fxrate * multiplier; return(createdTaxLot.RealizedPnl); }
/// <summary> /// Relieves the passed TaxLostStatus, this should only be used for FORWARDS etc that expire /// </summary> /// <param name="env">Environment</param> /// <param name="lot">The Tax Lot to relieve</param> /// <param name="trade">The current trade</param> /// <param name="quantity">Quantity to relieve</param> /// <param name="fxrate">Appropriate fxrate</param> internal static TaxLot RelieveTaxLot(PostingEngineEnvironment env, Transaction taxLotToRelieve, Transaction trade, double quantity, bool reverse = false) { var SettleNetPrice = trade.SettleNetPrice; if (taxLotToRelieve.LpOrderId.Equals(trade.LpOrderId)) { // Same, so we are dealing with the same trade, so we are backing out the same trade SettleNetPrice = MarketPrices.GetPrice(env, trade.SettleDate, trade).Price; } var prevFxRate = FxRates.Find(taxLotToRelieve.TradeDate, taxLotToRelieve.SettleCurrency).Rate; var investmentAtCost = quantity * taxLotToRelieve.SettleNetPrice * prevFxRate; if (reverse) { investmentAtCost = investmentAtCost * -1; } var tl = new TaxLot { Trade = trade, TradeDate = trade.TradeDate, InvestmentAtCost = investmentAtCost, // Needs to be the Investment Cost that we are relieving from the Tax BusinessDate = env.ValueDate, OpeningLotId = taxLotToRelieve.LpOrderId, ClosingLotId = trade.LpOrderId, TradePrice = taxLotToRelieve.SettleNetPrice, CostBasis = SettleNetPrice, Quantity = quantity }; CalculateRealizedPnl(env, tl); tl.Save(env.Connection, env.Transaction); return(tl); }
/// <summary> /// Displays the item information and item data information /// for the given investment itemSummary. /// </summary> /// <param name="itemSummary">an itemSummary whose containerType is 'stocks'</param> public void displayInvestmentDataForItem(ItemSummary itemSummary) { System.Console.WriteLine(""); String containerType = itemSummary.contentServiceInfo.containerInfo.containerName; if (!containerType.Equals(ContainerTypes.INVESTMENT)) { throw new Exception("DisplayInvestmentDataForItem called with invalid container type" + containerType); } DisplayItemInfo displayItemInfo = new DisplayItemInfo(); displayItemInfo.displayItemSummaryInfo(itemSummary); // Get ItemData ItemData1 itemData = itemSummary.itemData; if (itemData == null) { System.Console.WriteLine("\tItemData is null"); } else { // InvestmentData object[] accounts = itemData.accounts; if (accounts == null || accounts.Length == 0) { System.Console.WriteLine("\tNo accounts"); } else { System.Console.WriteLine("\n\t\t**InvestmentData**"); for (int i = 0; i < accounts.Length; i++) { InvestmentData investment = (InvestmentData)accounts[i]; System.Console.WriteLine("\t\tAccount Name: " + investment.accountName); System.Console.WriteLine("\t\tAccount Number: " + investment.accountNumber); System.Console.WriteLine("\t\tAccount Holder: " + investment.accountHolder); System.Console.WriteLine("\t\tAccount Type: " + investment.acctType); System.Console.WriteLine("\t\tCash: " + investment.cash); System.Console.WriteLine("\t\tTotal Balance: " + investment.totalBalance.amount); System.Console.WriteLine("\t\tTotal Vested Balance: " + investment.totalVestedBalance.amount); System.Console.WriteLine("\t\tTotal Unvested Balance: " + investment.totalUnvestedBalance.amount); System.Console.WriteLine("\t\tMargin Balance: " + investment.marginBalance.amount); System.Console.WriteLine("\t\tlastUpdated: " + UtcToDateTime(investment.lastUpdated.Value)); // HoldingData object[] holdings = investment.holdings; if (holdings == null || holdings.Length == 0) { System.Console.WriteLine("\t\tNo investment holdings."); } else { System.Console.WriteLine("\t\t\t**HoldingData**"); for (int j = 0; j < holdings.Length; j++) { HoldingData holding = (HoldingData)holdings[j]; System.Console.WriteLine("\t\t\tHoldingData Symbol: " + holding.symbol); System.Console.WriteLine("\t\t\tHoldingData Quantity: " + holding.quantity); System.Console.WriteLine("\t\t\tHoldingData Value: " + holding.value.amount); System.Console.WriteLine("\t\t\tHoldingData Description: " + holding.description); System.Console.WriteLine("\t\t\tHoldingData Price: " + holding.price.amount); System.Console.WriteLine("\t\t\tHoldingData Link: " + holding.link); System.Console.WriteLine("\t\t\tHoldingData HoldingType: " + holding.holdingType); System.Console.WriteLine("\t\t\tHoldingData HoldingTypeId: " + holding.holdingTypeId); System.Console.WriteLine("\t\t\tHoldingData Percentage Allocaton: " + holding.percentAllocation); System.Console.WriteLine("\t\t\tHoldingData Percantage Change: " + holding.percentageChange); System.Console.WriteLine("\t\t\tHoldingData Employee Contribution: " + holding.employeeContribution); System.Console.WriteLine("\t\t\tHoldingData Employeer Contribution: " + holding.employerContribution); System.Console.WriteLine("\t\t\tHoldingData Cusip Number: " + holding.cusipNumber); System.Console.WriteLine("\t\t\tHoldingData Daily Change: " + holding.dailyChange); System.Console.WriteLine("\t\t\tHoldingData Cost Basis: " + holding.costBasis.amount + "\n"); // TaxLots object[] taxLots = holding.taxLots; if (taxLots == null || taxLots.Length == 0) { System.Console.WriteLine("\t\t\tNo holdings taxLots"); } else { System.Console.WriteLine("\t\t\t\t**TaxLot**"); for (int u = 0; u < taxLots.Length; u++) { TaxLot taxLot = (TaxLot)taxLots[u]; System.Console.WriteLine("\t\t\t\tTaxLot Symbol: " + taxLot.symbol); System.Console.WriteLine("\t\t\t\tTaxLot Description: " + taxLot.description); System.Console.WriteLine("\t\t\t\tTaxLot Quantity: " + taxLot.quantity); System.Console.WriteLine("\t\t\t\tTaxLot Amount: " + taxLot.amount.amount); System.Console.WriteLine("\t\t\t\tTaxLot Price: " + taxLot.price.amount); System.Console.WriteLine("\t\t\t\tTaxLot Link: " + taxLot.link); System.Console.WriteLine("\t\t\t\tTaxLot Cusip Number: " + taxLot.cusipNumber + "\n"); } } // End TaxLot } } // End HoldingData // InvestmentTransactionData object[] investTransactions = investment.investmentTransactions; if (investTransactions == null || investTransactions.Length == 0) { System.Console.WriteLine("\t\tNo investment tranactions"); } else { System.Console.WriteLine("\t\t\t**InvestmentTransactionsData**"); for (int j = 0; j < investTransactions.Length; j++) { InvestmentTransactionsData trans = (InvestmentTransactionsData)investTransactions[j]; System.Console.WriteLine("\t\t\tTranaction.symbol: " + trans.symbol); System.Console.WriteLine("\t\t\tTranaction.amount: " + trans.amount.amount); System.Console.WriteLine("\t\t\tTranaction.price : " + trans.price.amount); System.Console.WriteLine("\t\t\tTranaction.quantity : " + trans.quantity); System.Console.WriteLine("\t\t\tTranaction.transDate : " + trans.transDate.date); System.Console.WriteLine("\t\t\tTransaction.description: " + trans.description); System.Console.WriteLine("\t\t\tTranaction.link : " + trans.link); System.Console.WriteLine("\t\t\tTranaction.transactionType : " + trans.transactionType); System.Console.WriteLine("\t\t\tTranaction.confirmantionNumber : " + trans.confirmationNumber + "\n"); } } // End InvestmentTransactionData } } // End InvestmentData } /* * // Get AccountHistory * object[] acctHistories = itemData.accountHistory; * if(acctHistories == null || acctHistories.Length == 0) * { * System.Console.WriteLine("\tNo Account History"); * } * else * { * System.Console.WriteLine("\n\t**Account History**"); * for(int i = 0; i < acctHistories.Length; i++) * { * AccountHistory acctHistory = (AccountHistory)acctHistories[i]; * * System.Console.WriteLine("\tAccount ID: {0}", acctHistory.accountId ); * * // Get History * object[] histories = acctHistory.history; * if(histories == null || histories.Length == 0) * { * System.Console.WriteLine("\t\tNo History"); * } * else * { * System.Console.WriteLine("\t\t**History**"); * for(int j = 0; j < histories.Length; j++) * { * InvestmentData investment = (InvestmentData) histories[j]; * System.Console.WriteLine("\t\taccountName: "+ investment.accountName ); * System.Console.WriteLine("\t\taccountNumber: "+ investment.accountNumber ); * System.Console.WriteLine("\t\taccountHolder: "+ investment.accountHolder ); * System.Console.WriteLine("\t\tacctType: "+ investment.acctType ); * System.Console.WriteLine("\t\tcash: "+ investment.cash ); * System.Console.WriteLine("\t\ttotalBalance: "+ investment.totalBalance.amount ); * System.Console.WriteLine("\t\ttotalVestedBalance: "+ investment.totalVestedBalance.amount ); * System.Console.WriteLine("\t\ttotalUnvestedBalance: "+ investment.totalUnvestedBalance.amount ); * System.Console.WriteLine("\t\tmarginBalance: "+ investment.marginBalance.amount ); * System.Console.WriteLine("\t\tlastUpdated: " + UtcToDateTime(investment.lastUpdated.Value) + "\n"); * } * } * } * } * // AccountHistory*/ }
public object AlleviateTaxLot(AlleviateTaxLotDto obj) { try { string symbol = obj.ProspectiveTrade.Symbol; string side = obj.ProspectiveTrade.Side; string message = "Tax Lot(s) Alleviated Successfully"; if (side.Equals("COVER")) { if (!obj.OpenTaxLots.All(x => x.Side.Equals("SHORT"))) { message = "All selected lots are not SHORT"; } } else if (side.Equals("SELL")) { if (!obj.OpenTaxLots.All(x => x.Side.Equals("BUY"))) { message = "All selected lots are not BUY"; } } else { message = "Incorrect side for this transaction"; } int lotSum = obj.OpenTaxLots.Sum(x => Math.Abs(x.RemainingQuantity)); int prospectiveTradeQuantity = Math.Abs(obj.ProspectiveTrade.RemainingQuantity); if (lotSum < prospectiveTradeQuantity) { //message = "Quantity Mismatch"; } List <TaxLot> taxLotList = new List <TaxLot>(); foreach (var item in obj.OpenTaxLots) { TaxLot t = new TaxLot(); if (prospectiveTradeQuantity == 0) { break; } else if (Math.Abs(item.RemainingQuantity) <= prospectiveTradeQuantity) { item.Status = "Closed"; if (Math.Abs(item.RemainingQuantity) < prospectiveTradeQuantity) { t.Quantity = Math.Abs(item.RemainingQuantity); } else { t.Quantity = prospectiveTradeQuantity; } prospectiveTradeQuantity -= Math.Abs(item.RemainingQuantity); item.RemainingQuantity = 0; } else if (Math.Abs(item.RemainingQuantity) > prospectiveTradeQuantity) { item.Status = "Partially Closed"; int absRemainingQuantity = Math.Abs(item.RemainingQuantity) - prospectiveTradeQuantity; t.Quantity = prospectiveTradeQuantity; prospectiveTradeQuantity = 0; if (item.RemainingQuantity < 0) { item.RemainingQuantity = absRemainingQuantity * -1; } else { item.RemainingQuantity = absRemainingQuantity; } } t.OpeningLotId = item.OpenLotId; t.ClosingLotId = obj.ProspectiveTrade.LpOrderId; //TODO. temporary assignment for now t.BusinessDate = DateTime.UtcNow; t.RealizedPnl = (obj.ProspectiveTrade.TradePrice - item.TradePrice) * t.Quantity; t.CostBasis = obj.ProspectiveTrade.TradePrice; t.TradePrice = item.TradePrice; t.TradeDate = DateTime.UtcNow; t.Quantity = SignedValueBasedOnSide(t.Quantity, obj.ProspectiveTrade.Side); t.InvestmentAtCost = t.Quantity * t.TradePrice * -1; taxLotList.Add(t); } SqlHelper sqlHelper = new SqlHelper(connectionString); sqlHelper.VerifyConnection(); sqlHelper.SqlBeginTransaction(); InsertTaxLot(taxLotList, sqlHelper); UpdateTaxLotStatus(obj.OpenTaxLots, sqlHelper); sqlHelper.SqlCommitTransaction(); sqlHelper.CloseConnection(); return(Utils.Wrap(true, null, HttpStatusCode.OK, message)); } catch (Exception ex) { throw ex; } }
internal static void GenerateCloseOutPostings(PostingEngineEnvironment env, TaxLotDetail lot, TaxLot taxlot, Transaction element, TaxLotStatus taxlotStatus, string fund) { double multiplier = 1.0; if (env.SecurityDetails.ContainsKey(element.BloombergCode)) { multiplier = env.SecurityDetails[element.BloombergCode].Multiplier; } double fxrate = 1.0; // Lets get fx rate if needed if (!element.SettleCurrency.Equals(env.BaseCurrency)) { fxrate = Convert.ToDouble(FxRates.Find(env.ValueDate, element.SettleCurrency).Rate); } var prevPrice = MarketPrices.GetPrice(env, env.PreviousValueDate, lot.Trade).Price; var unrealizedPnl = Math.Abs(taxlotStatus.Quantity) * (element.SettleNetPrice - prevPrice) * multiplier; unrealizedPnl = Math.Abs(unrealizedPnl) * CommonRules.DetermineSign(taxlotStatus.Trade); var buyTrade = env.FindTrade(lot.Trade.LpOrderId); ReverseUnrealizedPnl( env, buyTrade, element, unrealizedPnl, MarketPrices.GetPrice(env, env.PreviousValueDate, lot.Trade).Price, element.SettleNetPrice, fxrate); var PnL = taxlot.RealizedPnl; PostRealizedPnl( env, buyTrade, PnL, taxlot.TradePrice, taxlot.CostBasis, fxrate); var listOfFromTags = new List <Tag> { Tag.Find("SecurityType"), Tag.Find("CustodianCode") }; Account fromAccount = null; Account toAccount = null; if (element.IsDerivative()) { return; } else { var accountType = (buyTrade.IsShort() || buyTrade.IsCover()) ? "SHORT POSITIONS AT COST" : "LONG POSITIONS AT COST"; var markToMarketAccount = (buyTrade.IsShort() || buyTrade.IsCover()) ? "Mark to Market Shorts" : "Mark to Market Longs"; fromAccount = new AccountUtils().CreateAccount(AccountType.Find(accountType), listOfFromTags, element); toAccount = new AccountUtils().CreateAccount(AccountType.Find(markToMarketAccount), listOfFromTags, element); } new AccountUtils().SaveAccountDetails(env, fromAccount); new AccountUtils().SaveAccountDetails(env, toAccount); // Now Generate Entries var fromJournal = new Journal(element) { Account = fromAccount, CreditDebit = env.DebitOrCredit(fromAccount, PnL), When = env.ValueDate, StartPrice = taxlot.TradePrice, EndPrice = taxlot.CostBasis, Value = PnL, FxRate = 1, Event = Event.REALIZED_PNL, Fund = env.GetFund(element), }; var toJournal = new Journal(fromJournal) { Account = toAccount, CreditDebit = env.DebitOrCredit(toAccount, PnL * -1), Value = PnL * -1, }; env.Journals.AddRange(new[] { fromJournal, toJournal }); }