public void TestEnumToInt() { TradeActionBuySell enum1 = TradeActionBuySell.Buy; PositionDirection enum2 = PositionDirection.LongPosition; Assert.AreEqual(enum1.ToInt(), enum2.ToInt()); }
/// <summary> /// Calculates the average basis cost of a sequence of trades /// </summary> /// <param name="trades">Ordered list of trades. Reordered in ascending date order upon entry.</param> /// <param name="direction">Calculates for a long position or short. Throws an exception if the first trade in the sequence does not match</param> /// <returns>The average cost per share of remaining shares at the end of the trade sequence. Throws an exception if the position ever flips long/short</returns> public static decimal AverageCost(this List <Trade> trades, PositionDirection direction) { // Order the trades trades = new List <Trade>(trades).OrderBy(x => x.TradeDate).ToList(); // Check direction if ((int)trades.FirstOrDefault().TradeActionBuySell != (int)direction) { throw new InvalidTradeForPositionException(); } // Iterate through the trades and compute average cost int sharesOpen = 0; decimal averageCost = 0; foreach (var trd in trades) { // Buy trades increase position and update average price // Sell trades reduce position if (trd.TradeActionBuySell.ToInt() == direction.ToInt()) { averageCost = ((averageCost * sharesOpen) + (trd.TotalCashImpactAbsolute)) / (sharesOpen += trd.Quantity); } else if (trd.TradeActionBuySell.ToInt() == -direction.ToInt()) { sharesOpen -= trd.Quantity; } // sharesOpen should always be positive, otherwise we have flipped long/short if (sharesOpen < 0) { throw new InvalidTradeForPositionException(); } } return(Math.Round(averageCost, 3)); }