public void CorrectCapitalUsageReturnedWhenAddingOrderToEmptyPosition() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 12, Instrument = _instrument, FXRateToBase = 1 }; var res = pos.AddOrder(o); Assert.AreEqual(1200, res); }
/// <summary> /// Add an order to a trade. /// Returns true if the trade is found and the order successfully added. /// </summary> protected bool SetTrade(Order order, Trade trade) { if(trade == null) { Logger.Log(LogLevel.Warn, "User script {0} tried to add order {1} to a null trade", this.GetType().Name, order); return false; } if(!trade.Open) { Logger.Log(LogLevel.Warn, "User script {0} tried to add order {1} to a closed trade: {2}", this.GetType().Name, order, trade); return false; } TradesRepository.AddOrder(trade, order); Logger.Log(LogLevel.Info, "User script {0} added order {1} to trade {2}", this.GetType().Name, order, trade); return true; }
public void CorrectCapitalUsageReturnedWhenRemovingFromExistingPosition() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 12, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); var o2 = new Order { Quantity = -50, Price = 11, Instrument = _instrument, FXRateToBase = 1 }; var res = pos.AddOrder(o2); Assert.AreEqual(0, res); }
public void AddOrderReturnsCorrectCurrentCapitalUsageWhenOpeningAPosition() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 12, Instrument = _instrument, FXRateToBase = 1 }; decimal capUsage = pos.AddOrder(o); Assert.AreEqual(1200, capUsage); }
public void AddOrderReturnsCorrectCurrentCapitalUsageWhenRemovingFromPosition() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 100, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); var o2 = new Order { Quantity = -50, Price = 11, Instrument = _instrument, FXRateToBase = 1 }; var capUsage = pos.AddOrder(o2); Assert.AreEqual(0, capUsage); }
private DateTime? GetReferenceTime(Order order, ExecutionBenchmark benchmark) { //If the user sets a fixed reference time, we use that one in all cases if(_referenceTime != null) { return order.TradeDate.Date + _referenceTime.Value; } //Otherwise use QDMS or the reference time set at the order if (benchmark == ExecutionBenchmark.Close) { var session = _instrumentSessions[order.InstrumentID] .FirstOrDefault(x => x.IsSessionEnd && (int)x.ClosingDay == order.TradeDate.DayOfWeek.ToInt()); if (session == null) return null; return order.TradeDate.Date + session.ClosingTime; } else if (benchmark == ExecutionBenchmark.Open) { var session = _instrumentSessions[order.InstrumentID] .Where(x => (int)x.ClosingDay == order.TradeDate.DayOfWeek.ToInt()) .OrderBy(x => x.OpeningTime) .FirstOrDefault(); if (session == null) return null; return order.TradeDate.Date + session.OpeningTime; } else if (benchmark == ExecutionBenchmark.VWAP) { throw new NotImplementedException(); } else if (benchmark == ExecutionBenchmark.Reference) { return order.ReferenceTime; } return new DateTime(1, 1, 1); }
public void CapitalUsageWhenEnteringAndExitingMultipleOrdersNearCloseIsCountedWithShortPosition() { var pos = new Position(_instrument); decimal orderCapitalUsage = 0; var o = new Order { Quantity = -100, Price = 10, Instrument = _instrument, FXRateToBase = 1, TradeDate = new DateTime(2000, 1, 1, 15, 59, 0) }; orderCapitalUsage = pos.AddOrder(o); Assert.AreEqual(0, orderCapitalUsage); var o2 = new Order { Quantity = -100, Price = 10, Instrument = _instrument, FXRateToBase = 1, TradeDate = new DateTime(2000, 1, 1, 15, 59, 1) }; orderCapitalUsage = pos.AddOrder(o2); Assert.AreEqual(0, orderCapitalUsage); var o3 = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1, TradeDate = new DateTime(2000, 1, 1, 15, 59, 2) }; orderCapitalUsage = pos.AddOrder(o3); Assert.AreEqual(1000, orderCapitalUsage); var o4 = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1, TradeDate = new DateTime(2000, 1, 1, 15, 59, 3) }; orderCapitalUsage = pos.AddOrder(o4); Assert.AreEqual(1000, orderCapitalUsage); pos.GetPnL(10, 1); Assert.AreEqual(2000, pos.Capital.Gross.Last()); Assert.AreEqual(2000, pos.Capital.Short.Last()); }
public void PnLIsDeferredForROACCalculationsIfNoCapitalIsUsed() { var pos = new Position(_instrument); var c = new CashTransaction { Amount = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddCashTransaction(c); pos.GetPnL(10, 1); var o = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); pos.GetPnL(10, 1); Assert.AreEqual(1 + (10d / (10 * 100)), pos.ROAC); }
public void CapitalUsageWhenEnteringAndExitingNearCloseIsCounted() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1, TradeDate = new DateTime(2000, 1, 1, 15, 59, 0) }; pos.AddOrder(o); var o2 = new Order { Quantity = -100, Price = 10, Instrument = _instrument, FXRateToBase = 1, TradeDate = new DateTime(2000, 1, 1, 15, 59, 1) }; pos.AddOrder(o2); pos.GetPnL(10, 1); Assert.AreEqual(1000, pos.Capital.Gross.Last()); Assert.AreEqual(1000, pos.Capital.Long.Last()); }
public void FifoPnLIsCorrectAfterAddingToPosition() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); var o2 = new Order { Quantity = 100, Price = 11, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o2); Assert.AreEqual(0, o.PerTradeFIFOPnL); Assert.AreEqual(0, o2.PerTradeFIFOPnL); }
public void ROACValueIsCorrectAfterReversing() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); var o2 = new Order { Quantity = -150, Price = 11, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o2); pos.GetPnL(11, 1); Assert.AreEqual(Math.Round(1 + (1.0 * 100) / (10 * 100 + 11 * 50), 5), Math.Round(pos.ROAC, 5)); }
public void ROACValueReflectsFXRateChanges() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); var o2 = new Order { Quantity = -50, Price = 11, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o2); pos.GetPnL(10, 1.1m); Assert.AreEqual(1.1, pos.ROAC); }
public void RealizedPnLValuesReflectFXRateChanges() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); var o2 = new Order { Quantity = -100, Price = 11, Instrument = _instrument, FXRateToBase = 1.05m }; pos.AddOrder(o2); Assert.AreEqual(155, pos.RealizedPnL); }
public void ROACValueIsCorrectWithCashTransactions() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); var c = new CashTransaction { Amount = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddCashTransaction(c); pos.GetPnL(10, 1); Assert.AreEqual(1.01, pos.ROAC); }
public void CorrectPriceBasisUpdateWhenAddingOrderToEmptyPosition() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 12, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); Assert.AreEqual(12, pos.CostBasis); }
public void ROACValueIsCorrectAfterPartialExit() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); var o2 = new Order { Quantity = -50, Price = 11, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o2); pos.GetPnL(10, 1); Assert.AreEqual(1.05, pos.ROAC); }
public void AddOrderTakesIntoAccountFXRate() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 100, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); var o2 = new Order { Quantity = -200, Price = 10, Instrument = _instrument, FXRateToBase = 1.1m }; var capUsage = pos.AddOrder(o2); Assert.AreEqual(1100, capUsage); }
public void UnrealizedPnLReturnsDiffernceBetweenTotalAndRealizedPnL() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); var o2 = new Order { Quantity = -50, Price = 11, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o2); pos.GetPnL(11, 1); Assert.AreEqual(50, pos.UnrealizedPnL); }
public void RealizedPnLValuesIncludeCommissions() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1, Commission = -5 }; pos.AddOrder(o); Assert.AreEqual(-5, pos.RealizedPnL); var o2 = new Order { Quantity = -100, Price = 11, Instrument = _instrument, FXRateToBase = 1, Commission = -5 }; pos.AddOrder(o2); Assert.AreEqual(90, pos.RealizedPnL); }
public void CorrectPriceBasisUpdateWhenReversingExistingPosition() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 12, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); var o2 = new Order { Quantity = -150, Price = 11, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o2); Assert.AreEqual(11, pos.CostBasis); }
public void FifoPnLTakesIntoAccountFXRate() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); var o2 = new Order { Quantity = -100, Price = 10, Instrument = _instrument, FXRateToBase = 1.1m }; pos.AddOrder(o2); Assert.AreEqual(0, o.PerTradeFIFOPnL); Assert.AreEqual(100, o2.PerTradeFIFOPnL); }
public void GetPnLReturnsCorrectPnLForShortPositions() { var pos = new Position(_instrument); var o = new Order { Quantity = -100, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); Assert.AreEqual(-100, pos.GetPnL(11, 1)); Assert.AreEqual(100, pos.GetPnL(10, 1)); }
public void AddingAnOrderForTheWrongInstrumentThrowsException() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); var o2 = new Order { Quantity = -50, Price = 11, Instrument = new Instrument { ID = 2, Multiplier = 1, AssetCategory = AssetClass.Stock }, FXRateToBase = 1 }; ActualValueDelegate<object> testDelegate = () => pos.AddOrder(o2); Assert.That(testDelegate, Throws.Exception); }
public void GetPnLIncludesCommissions() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1, Commission = -5 }; pos.AddOrder(o); Assert.AreEqual(100 - 5, pos.GetPnL(11, 1)); Assert.AreEqual(-100, pos.GetPnL(10, 1)); }
public void MultiPeriodCapitalUsageIsRecordedCorrectly() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); Assert.AreEqual(1000, pos.Capital.TodaysCapitalGross); Assert.AreEqual(1000, pos.Capital.TodaysCapitalLong); pos.GetPnL(10, 1); var o2 = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o2); var o3 = new Order { Quantity = -200, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o3); pos.GetPnL(10, 1); Assert.AreEqual(2000, pos.Capital.Gross.Last()); Assert.AreEqual(2000, pos.Capital.Long.Last()); pos.GetPnL(10, 1); var o4 = new Order { Quantity = 150, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o4); pos.GetPnL(10, 1); List<decimal> expectedCapitalGross = new List<decimal> { 1000, 2000, 0, 1500 }; for (int i = 0; i < expectedCapitalGross.Count; i++) { Assert.AreEqual(expectedCapitalGross[i], pos.Capital.Gross[i]); } }
public void GetPnLReturnsCorrectPnLWithBothRealizedAndUnrealizedPnL() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); var o2 = new Order { Quantity = -50, Price = 11, Instrument = _instrument, FXRateToBase = 1, }; pos.AddOrder(o2); Assert.AreEqual(50 * 1 + 50 * 2, pos.GetPnL(12, 1)); Assert.AreEqual(-2 * 50, pos.GetPnL(10, 1)); }
/// <summary> /// Gets the reference price for a particular order, given an execution benchmark. /// </summary> private decimal? GetReferencePrice(Order order, ExecutionBenchmark benchmark) { if (benchmark == ExecutionBenchmark.Close) { return order.ClosePrice; } else if (benchmark == ExecutionBenchmark.Open) { //For the open we need to look at the external data if (!_data.ContainsKey(order.InstrumentID)) return null; var bar = _data[order.InstrumentID].FirstOrDefault(x => x.DT.Date == order.TradeDate.Date); if (bar == null) return null; return bar.Open; } else if (benchmark == ExecutionBenchmark.VWAP) { throw new NotImplementedException(); } else if (benchmark == ExecutionBenchmark.Reference) { return order.ReferencePrice; } return 0; }
public void GetPnLReturnsCorrectPnLIncludingFXRateChanges() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 10, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); Assert.AreEqual(45, pos.GetPnL(11, 0.95m)); }
/// <summary> /// We have the reference time and price, now generate stats for every execution in the given order. /// </summary> private void GenerateStats(Order order, DateTime referenceTime, decimal referencePrice) { if (order.Executions == null) return; foreach (Execution ex in order.Executions) { Stats.Add(new ExecutionStats(ex, referencePrice, referenceTime)); } }
public void CumulativeCapitalUsedHasCorrectValueWhenReversing() { var pos = new Position(_instrument); var o = new Order { Quantity = 100, Price = 12, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o); var o2 = new Order { Quantity = -200, Price = 11, Instrument = _instrument, FXRateToBase = 1 }; pos.AddOrder(o2); Assert.AreEqual(12 * 100 + 11 * 100, pos.Capital.TodaysCapitalGross); Assert.AreEqual(12 * 100 - 11 * 100, pos.Capital.TodaysCapitalNet); Assert.AreEqual(12 * 100, pos.Capital.TodaysCapitalLong); Assert.AreEqual(11 * 100, pos.Capital.TodaysCapitalShort); }