Beispiel #1
0
        public SellResults Calculate(IList <Share> shares, int sharesSold, double sellPricePerShare, DateTime sellDate)
        {
            var result = new SellResults();

            var sharesBeforeDate         = 0;
            var sharesBeforeDatePriceMax = 0.0;

            var i = 0;

            while (i < shares.Count && shares[i].PurchaseDate <= sellDate)
            {
                sharesBeforeDate        += shares[i].Shares;
                sharesBeforeDatePriceMax = Math.Max(sharesBeforeDatePriceMax, shares[i].Price);

                i++;
            }

            if (sharesBeforeDate < sharesSold)
            {
                throw new InvalidOperationException("Not enough shares to sell by the specified date");
            }

            var sharesAfterDate         = 0;
            var sharesAfterDatePriceMax = 0.0;

            while (i < shares.Count)
            {
                sharesAfterDate        += shares[i].Shares;
                sharesAfterDatePriceMax = Math.Max(sharesAfterDatePriceMax, shares[i].Price);

                i++;
            }

            var sellingSharesTotal   = sharesBeforeDatePriceMax * sharesSold;
            var remainingShares      = 0;
            var remainingSharesTotal = 0.0;
            var remainingSharesPrice = Math.Max(sharesBeforeDatePriceMax, sharesAfterDatePriceMax);

            remainingShares      = sharesBeforeDate - sharesSold + sharesAfterDate;
            remainingSharesTotal = remainingShares * remainingSharesPrice;

            result.CostPriceSoldShares = sharesBeforeDatePriceMax;
            result.GainLossOnSale      = sellPricePerShare * sharesSold - result.CostPriceSoldShares * sharesSold;
            result.RemainingShares     = remainingShares;
            result.CostPriceRemaining  = remainingSharesPrice * (result.RemainingShares > 0 ? 1 : 0);
            return(result);
        }
Beispiel #2
0
        public SellResults Calculate(IList <Share> shares, int sharesSold, double sellPricePerShare, DateTime sellDate)
        {
            var result = new SellResults();

            var sharesBeforeDate      = 0;
            var sharesBeforeDateTotal = 0.0;

            var sharesSelling = sharesSold;

            var sharesRemainingInSplit      = 0;
            var sharesRemainingInSplitTotal = 0.0;

            var i = 0;

            while (i < shares.Count && shares[i].PurchaseDate <= sellDate && sharesSelling > shares[i].Shares)
            {
                sharesBeforeDate      += shares[i].Shares;
                sharesBeforeDateTotal += shares[i].Total;

                sharesSelling -= shares[i].Shares;
                i++;
            }

            if (sharesSelling <= shares[i].Shares && shares[i].PurchaseDate <= sellDate)
            {
                sharesBeforeDate      += sharesSelling;
                sharesBeforeDateTotal += sharesSelling * shares[i].Price;

                sharesRemainingInSplit      = shares[i].Shares - sharesSelling;
                sharesRemainingInSplitTotal = sharesRemainingInSplit * shares[i].Price;
                i++;
            }

            if (sharesBeforeDate < sharesSold)
            {
                throw new InvalidOperationException("Not enough shares to sell by the specified date");
            }

            var sharesAfterDate     = 0;
            var shareAfterDateTotal = 0.0;

            while (i < shares.Count)
            {
                sharesAfterDate     += shares[i].Shares;
                shareAfterDateTotal += shares[i].Total;

                i++;
            }

            var remainingShares      = 0;
            var remainingSharesTotal = 0.0;

            remainingShares      = sharesRemainingInSplit + sharesAfterDate;
            remainingSharesTotal = sharesRemainingInSplitTotal + shareAfterDateTotal;

            var remainingSharesPrice = remainingSharesTotal / remainingShares;

            result.CostPriceSoldShares = sharesBeforeDateTotal / sharesBeforeDate;
            result.GainLossOnSale      = sellPricePerShare * sharesSold - result.CostPriceSoldShares * sharesSold;
            result.RemainingShares     = remainingShares;
            result.CostPriceRemaining  = remainingSharesPrice * (result.RemainingShares > 0 ? 1 : 0);
            return(result);
        }
        public SellResults Calculate(IList <Share> shares, int sharesSold, double sellPricePerShare, DateTime sellDate)
        {
            var result = new SellResults();

            var sharesRemaining = 0;
            var sharesToSell    = sharesSold;

            var sellingShares      = 0;
            var sellingSharesTotal = 0.0;

            var splitPosition             = 0;
            var remainingSharesAfter      = 0; //shares after date
            var remainingSharesAfterTotal = 0.0;

            var remainingSharesBefore      = 0; //shares before split position
            var remainingSharesBeforeTotal = 0.0;

            var remainingSharesInSplit     = 0; //shares remaining in the split position
            var remaininSharesInSplitTotal = 0.0;

            for (int i = shares.Count - 1; i >= 0; i--)
            {
                if (shares[i].PurchaseDate > sellDate)
                {
                    remainingSharesAfter      += shares[i].Shares;
                    remainingSharesAfterTotal += shares[i].Total;
                }
                else
                {
                    sharesRemaining = sharesToSell - shares[i].Shares;
                    if (sharesRemaining > 0)
                    {
                        sellingShares      += shares[i].Shares;
                        sellingSharesTotal += shares[i].Total;
                        sharesToSell        = sharesRemaining;
                        continue;
                    }
                    else
                    {
                        var finalFillingShares = shares[i].Shares + sharesRemaining;
                        sellingShares      += finalFillingShares;
                        sellingSharesTotal += finalFillingShares * shares[i].Price;

                        remainingSharesInSplit     = shares[i].Shares - finalFillingShares;
                        remaininSharesInSplitTotal = remainingSharesInSplit * shares[i].Price;

                        splitPosition = i;
                        break;
                    }
                }
            }

            if (sellingShares != sharesSold)
            {
                throw new InvalidOperationException("Not enough shares to sell by the specified date");
            }

            //Calculate remaining positions before split
            for (int i = splitPosition - 1; i >= 0; i--)
            {
                remainingSharesBefore      += shares[i].Shares;
                remainingSharesBeforeTotal += shares[i].Total;
            }
            //Combine
            var totalRemainingShares      = remainingSharesBefore + remainingSharesInSplit + remainingSharesAfter;
            var totalRemainingSharesTotal = remainingSharesBeforeTotal + remaininSharesInSplitTotal + remainingSharesAfterTotal;


            result.CostPriceSoldShares = sellingSharesTotal / sellingShares;
            result.GainLossOnSale      = sellPricePerShare * sharesSold - result.CostPriceSoldShares * sharesSold;
            result.RemainingShares     = totalRemainingShares;
            result.CostPriceRemaining  = (totalRemainingSharesTotal / totalRemainingShares) * (result.RemainingShares > 0 ? 1 : 0);
            return(result);
        }