Example #1
0
        /// <summary>
        /// Find the oldest holdings that still have UnitsRemaining, and decrement them by the
        /// number of units we are selling.  This might have to sell from multiple SecurityPurchases
        /// in order to cover the requested number of units.  If there are not enough units to cover
        /// the sale then we have a problem and we return a SecuritySale containing the Error information.
        /// </summary>
        /// <param name="dateSold">The date of the sale</param>
        /// <param name="units">The number of units sold</param>
        /// <param name="amount">The total amount we received from the sale</param>
        /// <returns></returns>
        public IEnumerable <SecuritySale> Sell(DateTime dateSold, decimal units, decimal amount)
        {
            decimal salePricePerUnit = amount / units;

            foreach (var purchase in list)
            {
                SecuritySale sale = purchase.Sell(dateSold, units, salePricePerUnit);
                if (sale != null)
                {
                    sale.Account = this.Account;
                    units       -= sale.UnitsSold;
                    yield return(sale);

                    if (units <= 0)
                    {
                        // done!
                        break;
                    }
                }
            }

            if (Math.Floor(units) > 0)
            {
                // Generate an error item so we can report this problem later.
                pending.Add(new SecuritySale()
                {
                    Security         = this.Security,
                    Account          = this.Account,
                    DateSold         = dateSold,
                    UnitsSold        = units,
                    SalePricePerUnit = salePricePerUnit
                });
            }
        }
Example #2
0
        /// <summary>
        /// For a roll-up report where individual SecuritySale is too much detail we
        /// can consolidate here, but only if the SalePricePerUnit and CostBasisPerUnit
        /// match.  If they do not match then we set them to zero so they are reported
        /// as "unknown".
        /// </summary>
        /// <param name="cg">The other sale to consolidate</param>
        internal void Consolidate(SecuritySale cg)
        {
            this.UnitsSold += cg.UnitsSold;

            if (this.DateAcquired != cg.DateAcquired)
            {
                // will be reported to IRS as "VARIOUS"
                this.DateAcquired     = null;
                this.CostBasisPerUnit = 0;
            }
            if (this.SalePricePerUnit != cg.SalePricePerUnit)
            {
                this.SalePricePerUnit = 0;
            }

            if (this.CostBasisPerUnit != cg.CostBasisPerUnit)
            {
                this.CostBasisPerUnit = 0;
            }
        }