private void AddSharesAndCalculateNewAverageCostBasis(string symbol, int quantity, float price_per_share, DateTimeOffset purchased_at) { //Check if we already have a holding like this EquityHolding nh = null; foreach (EquityHolding h in EquityHoldings) { if (h.Symbol.ToUpper() == symbol.ToUpper()) { nh = h; } } //Create a new one if we couldn't find this holding that already exists. if (nh == null) { nh = new EquityHolding(); nh.Symbol = symbol.ToUpper().Trim(); nh.Quantity = 0; nh.AverageCostBasis = 0; EquityHoldings.Add(nh); } //Calculate the new Average Per Share Cost basis float CurrentTotalCost = nh.AverageCostBasis * nh.Quantity; float NewTotalCost = price_per_share * quantity; float NewAvgCostBasis = (CurrentTotalCost + NewTotalCost) / (quantity + nh.Quantity); nh.AverageCostBasis = NewAvgCostBasis; //add the shares we are buying to the balane nh.Quantity = nh.Quantity + quantity; //Log the transaction EquityTransaction et = new EquityTransaction(); et.TransactedOn = purchased_at; et.Quantity = quantity; et.StockSymbol = symbol.ToUpper().Trim(); et.OrderType = TransactionType.Buy; et.PriceExecutedAt = price_per_share; EquityTransactionLog.Add(et); }
public async Task TradeEquityAsync(string symbol, int quantity, TransactionType order_type) { Equity e = Equity.Create(symbol); try { await e.DownloadSummaryAsync(); } catch { throw new Exception("Critical error while fetching equity '" + symbol + "'. Does this equity exist?"); } if (order_type == TransactionType.Buy) { //Be sure we have enough cash to buy float cash_needed = e.Summary.Price * quantity; if (Cash < cash_needed) { throw new Exception("You do not have enough cash to execute this buy order of " + symbol.ToUpper() + ". Cash needed: $" + cash_needed.ToString("#,##0.00") + ". Cash balance: $" + Cash.ToString("#,##0.00")); } AddSharesAndCalculateNewAverageCostBasis(symbol.ToUpper().Trim(), quantity, e.Summary.Price, DateTimeOffset.Now); //Edit cash and add the shares we are buying to the balane Cash = Cash - cash_needed; } else if (order_type == TransactionType.Sell) { //Find our holding EquityHolding eh = null; foreach (EquityHolding ceh in EquityHoldings) { if (ceh.Symbol.ToUpper() == symbol.ToUpper()) { eh = ceh; } } //Throw an error if we do not have any of those shares. if (eh == null) { throw new Exception("You do not have any shares of " + symbol.ToUpper() + " to sell."); } //Throw an error if we do not have enough shares if (eh.Quantity < quantity) { throw new Exception("You do not have " + quantity.ToString() + " shares to sell! You only have " + eh.Quantity.ToString() + " shares."); } //Execute the transaction Cash = Cash + (quantity * e.Summary.Price); eh.Quantity = eh.Quantity - quantity; //Save the transaction log EquityTransaction et = new EquityTransaction(); et.UpdateTransactionTime(); et.StockSymbol = symbol.ToUpper().Trim(); et.OrderType = TransactionType.Sell; et.Quantity = quantity; et.PriceExecutedAt = e.Summary.Price; EquityTransactionLog.Add(et); //Remove the holding if it now 0 if (eh.Quantity == 0) { EquityHoldings.Remove(eh); } } //Take out the commission (if any) if (TradeCost > 0) { EditCash(TradeCost * -1, CashTransactionType.TradingRelatedCharge); } }
public async Task <EquityHoldingPerformance[]> CalculateEquityHoldingPerformances() { List <EquityHoldingPerformance> ToReturn = new List <EquityHoldingPerformance>(); //Check if there are no holdings if (EquityHoldings.Count == 0) { return(ToReturn.ToArray()); } //Get a list of all equities List <string> Stocks = new List <string>(); foreach (EquityHolding eh in EquityHoldings) { if (Stocks.Contains(eh.Symbol.Trim().ToUpper()) == false) { Stocks.Add(eh.Symbol.Trim().ToUpper()); } } //Get all stock data BatchStockDataProvider bsdp = new BatchStockDataProvider(); EquitySummaryData[] ESDs = await bsdp.GetBatchEquitySummaryData(Stocks.ToArray()); //Check if we have all of them if (Stocks.Count != ESDs.Length) { string DontHave = ""; foreach (string s in Stocks) { bool HasIt = false; foreach (EquitySummaryData esd in ESDs) { if (esd.StockSymbol.Trim().ToUpper() == s.Trim().ToUpper()) { HasIt = true; } } if (HasIt == false) { DontHave = DontHave + s + ","; } } throw new Exception("Unable to calculate all of the performance logs for your holdings because access of data failed: " + DontHave); } //Calculate the performances foreach (string s in Stocks) { EquityHoldingPerformance ehp = new EquityHoldingPerformance(); //Find the right Equity Data EquitySummaryData esd = null; foreach (EquitySummaryData es in ESDs) { if (es.StockSymbol.Trim().ToUpper() == s.Trim().ToUpper()) { esd = es; } } if (esd == null) { throw new Exception("Fatal error while calculating performance for " + s + "."); } //Find the right equity holding EquityHolding eh = null; foreach (EquityHolding h in EquityHoldings) { if (h.Symbol.Trim().ToUpper() == s.Trim().ToUpper()) { eh = h; } } if (eh == null) { throw new Exception("Fatal error while find holding for " + s + "."); } //Add symbol ehp.Symbol = s.Trim().ToUpper(); //Get dollars invested ehp.DollarsInvested = eh.AverageCostBasis * eh.Quantity; //Get holding value ehp.HoldingValue = eh.Quantity * esd.Price; //Get dollar profit ehp.DollarProfit = ehp.HoldingValue - ehp.DollarsInvested; //Get percent profit ehp.PercentProfit = ehp.DollarProfit / ehp.DollarsInvested; ToReturn.Add(ehp); } //Return them return(ToReturn.ToArray()); }