public void ProfitCorrectlyCalculatedAfterSimpleEntryAndExit() { var pos = new CurrencyPosition(_currency); decimal fxRate = 1.35m; int quantity = 1000; var transaction1 = new FXTransaction { Quantity = quantity, Proceeds = fxRate * quantity, Cost = -fxRate * quantity, FXCurrency = _currency }; pos.AddFXTransaction(transaction1); decimal newFxRate = 1.36m; quantity = -quantity; var transaction2 = new FXTransaction { Quantity = quantity, Proceeds = newFxRate * quantity, Cost = -newFxRate * quantity, FXCurrency = _currency }; pos.AddFXTransaction(transaction2); Assert.AreEqual(-quantity * (newFxRate - fxRate), pos.RealizedPnL); pos.Update(newFxRate); Assert.AreEqual(-quantity * (newFxRate - fxRate), pos.TotalPnL); }
public void AddFXTransaction(FXTransaction transaction) { if(transaction.FXCurrency.ID != Currency.ID) { throw new Exception("Incorrect currency used."); } Transactions.Add(transaction); decimal fxRate = transaction.Proceeds / transaction.Quantity; //profit/loss if ((transaction.Quantity < 0 && Quantity > 0) || (transaction.Quantity > 0 && Quantity < 0)) { decimal profit = -Math.Min(Math.Abs(transaction.Quantity), Math.Abs(Quantity)) * (fxRate - CostBasis) * Math.Sign(transaction.Quantity); RealizedPnL += profit; _unrecognizedPnL += profit; } //update cost basis if(Quantity == 0) { //new position CostBasis = fxRate; PriorPeriodCostBasis = fxRate; } else if (Math.Sign(transaction.Quantity) == Math.Sign(Quantity)) { //adding to existing position CostBasis = (Quantity * CostBasis + transaction.Quantity * fxRate) / (Quantity + transaction.Quantity); PriorPeriodCostBasis = (Quantity * PriorPeriodCostBasis + transaction.Quantity * fxRate) / (Quantity + transaction.Quantity); } else if(Math.Abs(transaction.Quantity) > Math.Abs(Quantity)) { //removing from position...if we're reversing it, it's as if it's a new position CostBasis = fxRate; PriorPeriodCostBasis = fxRate; } Quantity += transaction.Quantity; }
public void QuantityAndPriceReflectAddedTransactions() { var pos = new CurrencyPosition(_currency); decimal fxRate = 1.35m; int quantity = 1000; var transaction1 = new FXTransaction { Quantity = quantity, Proceeds = fxRate * quantity, Cost = -fxRate * quantity, FXCurrency = _currency }; pos.AddFXTransaction(transaction1); Assert.AreEqual(quantity, pos.Quantity); Assert.AreEqual(fxRate, pos.CostBasis); Assert.AreEqual(fxRate, pos.PriorPeriodCostBasis); }
public void RealizedProfitsWithUpdateBetweenTradesCalculatedCorrectly() { var pos = new CurrencyPosition(_currency); decimal fxRate = 1.35m; int quantity = 1000; var transaction1 = new FXTransaction { Quantity = quantity, Proceeds = fxRate * quantity, Cost = -fxRate * quantity, FXCurrency = _currency }; pos.AddFXTransaction(transaction1); decimal newFxRate = 1.36m; pos.Update(newFxRate); Assert.AreEqual(quantity * (newFxRate - fxRate), pos.TotalPnL); int newQuantity = -1000; decimal newFxRate2 = 1.37m; var transaction2 = new FXTransaction { Quantity = newQuantity, Proceeds = newFxRate2 * newQuantity, Cost = -newFxRate2 * newQuantity, FXCurrency = _currency }; pos.AddFXTransaction(transaction2); Assert.AreEqual(-newQuantity * (newFxRate2 - fxRate), pos.RealizedPnL); }
/// <summary> /// /// </summary> /// <param name="o"></param> /// <returns>Capital usage by this order.</returns> public decimal AddOrder(Order o) { Open = true; if (!Positions.ContainsKey(o.Instrument.ID)) Positions.Add(o.Instrument.ID, new Position(o.Instrument, _optionsCapitalUsageMultiplier)); decimal orderCapUsage = Positions[o.Instrument.ID].AddOrder(o); _ordersRemaining--; if (o.CurrencyID > 1) { decimal quantity = -o.Quantity * o.Multiplier * o.Price; var ft = new FXTransaction { FXCurrency = o.Currency, FXCurrencyID = o.CurrencyID, Quantity = quantity, Proceeds = quantity * o.FXRateToBase, Cost = -quantity * o.FXRateToBase, DateTime = o.TradeDate }; AddFXTransaction(ft); } return orderCapUsage; }
public void AddFXTransaction(FXTransaction ft) { Open = true; if (!CurrencyPositions.ContainsKey(ft.FXCurrency.ID)) CurrencyPositions.Add(ft.FXCurrency.ID, new CurrencyPosition(ft.FXCurrency)); CurrencyPositions[ft.FXCurrency.ID].AddFXTransaction(ft); }
public void AddCashTransaction(CashTransaction ct) { Open = true; if (ct.InstrumentID.HasValue) { if (Positions.ContainsKey(ct.Instrument.ID)) Positions[ct.Instrument.ID].AddCashTransaction(ct); } else { //InstrumentID is null. This happens frequently //as many cash transactions are not related to a particular instrument Positions[NullInstrumentId].AddCashTransaction(ct); } if(ct.CurrencyID > 1) { var ft = new FXTransaction { FXCurrency = ct.Currency, FXCurrencyID = ct.CurrencyID, Quantity = ct.Amount, Proceeds = ct.Amount * ct.FXRateToBase, Cost = -ct.Amount * ct.FXRateToBase, DateTime = ct.TransactionDate }; AddFXTransaction(ft); } _cashTransactionsRemaining--; }