public void AllInAllOutLong(FillGroupingMethod groupingMethod, FillMatchingMethod matchingMethod) { // Buy 1k, Sell 1k var builder = new TradeBuilder(groupingMethod, matchingMethod); var time = _startTime; // Buy 1k builder.ProcessFill(new OrderEvent(1, Symbol, time, OrderStatus.Filled, OrderDirection.Buy, fillPrice: 1.08m, fillQuantity: 1000, orderFee: OrderFee), ConversionRate); Assert.IsTrue(builder.HasOpenPosition(Symbol)); builder.SetMarketPrice(Symbol, 1.075m); builder.SetMarketPrice(Symbol, 1.10m); // Sell 1k builder.ProcessFill(new OrderEvent(2, Symbol, time.AddMinutes(10), OrderStatus.Filled, OrderDirection.Sell, fillPrice: 1.09m, fillQuantity: -1000, orderFee: OrderFee), ConversionRate); Assert.IsFalse(builder.HasOpenPosition(Symbol)); Assert.AreEqual(1, builder.ClosedTrades.Count); var trade = builder.ClosedTrades[0]; Assert.AreEqual(Symbol, trade.Symbol); Assert.AreEqual(time, trade.EntryTime); Assert.AreEqual(1.08m, trade.EntryPrice); Assert.AreEqual(TradeDirection.Long, trade.Direction); Assert.AreEqual(1000, trade.Quantity); Assert.AreEqual(time.AddMinutes(10), trade.ExitTime); Assert.AreEqual(1.09m, trade.ExitPrice); Assert.AreEqual(10, trade.ProfitLoss); Assert.AreEqual(2, trade.TotalFees); Assert.AreEqual(-5, trade.MAE); Assert.AreEqual(20m, trade.MFE); }
public void ScaleInScaleOut2Long(FillGroupingMethod groupingMethod, FillMatchingMethod matchingMethod) { // Buy 1k, Buy 2k, Sell 1k, Buy 1k, Sell 3k var builder = new TradeBuilder(groupingMethod, matchingMethod); var time = _startTime; // Buy 1k builder.ProcessFill(new OrderEvent(1, Symbol, time, OrderStatus.Filled, OrderDirection.Buy, fillPrice: 1.07m, fillQuantity: 1000, orderFee: OrderFee), ConversionRate); Assert.IsTrue(builder.HasOpenPosition(Symbol)); builder.SetMarketPrice(Symbol, 1.075m); // Buy 2k builder.ProcessFill(new OrderEvent(2, Symbol, time.AddMinutes(10), OrderStatus.Filled, OrderDirection.Buy, fillPrice: 1.08m, fillQuantity: 2000, orderFee: OrderFee), ConversionRate); Assert.IsTrue(builder.HasOpenPosition(Symbol)); builder.SetMarketPrice(Symbol, 1.065m); builder.SetMarketPrice(Symbol, 1.10m); // Sell 1k builder.ProcessFill(new OrderEvent(3, Symbol, time.AddMinutes(20), OrderStatus.Filled, OrderDirection.Sell, fillPrice: 1.09m, fillQuantity: -1000, orderFee: OrderFee), ConversionRate); Assert.IsTrue(builder.HasOpenPosition(Symbol)); // Buy 1k builder.ProcessFill(new OrderEvent(4, Symbol, time.AddMinutes(30), OrderStatus.Filled, OrderDirection.Buy, fillPrice: 1.08m, fillQuantity: 1000, orderFee: OrderFee), ConversionRate); Assert.IsTrue(builder.HasOpenPosition(Symbol)); // Sell 3k builder.ProcessFill(new OrderEvent(5, Symbol, time.AddMinutes(40), OrderStatus.Filled, OrderDirection.Sell, fillPrice: 1.09m, fillQuantity: -3000, orderFee: OrderFee), ConversionRate); Assert.IsFalse(builder.HasOpenPosition(Symbol)); switch (groupingMethod) { case FillGroupingMethod.FillToFill: { if (matchingMethod == FillMatchingMethod.FIFO) { Assert.AreEqual(3, builder.ClosedTrades.Count); var trade1 = builder.ClosedTrades[0]; Assert.AreEqual(Symbol, trade1.Symbol); Assert.AreEqual(time, trade1.EntryTime); Assert.AreEqual(1.07m, trade1.EntryPrice); Assert.AreEqual(TradeDirection.Long, trade1.Direction); Assert.AreEqual(1000, trade1.Quantity); Assert.AreEqual(time.AddMinutes(20), trade1.ExitTime); Assert.AreEqual(1.09m, trade1.ExitPrice); Assert.AreEqual(20, trade1.ProfitLoss); Assert.AreEqual(2, trade1.TotalFees); Assert.AreEqual(-5, trade1.MAE); Assert.AreEqual(30, trade1.MFE); var trade2 = builder.ClosedTrades[1]; Assert.AreEqual(Symbol, trade2.Symbol); Assert.AreEqual(time.AddMinutes(10), trade2.EntryTime); Assert.AreEqual(1.08m, trade2.EntryPrice); Assert.AreEqual(TradeDirection.Long, trade2.Direction); Assert.AreEqual(2000, trade2.Quantity); Assert.AreEqual(time.AddMinutes(40), trade2.ExitTime); Assert.AreEqual(1.09m, trade2.ExitPrice); Assert.AreEqual(20, trade2.ProfitLoss); Assert.AreEqual(2, trade2.TotalFees); Assert.AreEqual(-30, trade2.MAE); Assert.AreEqual(40, trade2.MFE); var trade3 = builder.ClosedTrades[2]; Assert.AreEqual(Symbol, trade3.Symbol); Assert.AreEqual(time.AddMinutes(30), trade3.EntryTime); Assert.AreEqual(1.08m, trade3.EntryPrice); Assert.AreEqual(TradeDirection.Long, trade3.Direction); Assert.AreEqual(1000, trade3.Quantity); Assert.AreEqual(time.AddMinutes(40), trade3.ExitTime); Assert.AreEqual(1.09m, trade3.ExitPrice); Assert.AreEqual(10, trade3.ProfitLoss); Assert.AreEqual(1, trade3.TotalFees); Assert.AreEqual(-15, trade3.MAE); Assert.AreEqual(20, trade3.MFE); } else { Assert.AreEqual(4, builder.ClosedTrades.Count); var trade1 = builder.ClosedTrades[0]; Assert.AreEqual(Symbol, trade1.Symbol); Assert.AreEqual(time.AddMinutes(10), trade1.EntryTime); Assert.AreEqual(1.08m, trade1.EntryPrice); Assert.AreEqual(TradeDirection.Long, trade1.Direction); Assert.AreEqual(1000, trade1.Quantity); Assert.AreEqual(time.AddMinutes(20), trade1.ExitTime); Assert.AreEqual(1.09m, trade1.ExitPrice); Assert.AreEqual(10, trade1.ProfitLoss); Assert.AreEqual(2, trade1.TotalFees); Assert.AreEqual(-15, trade1.MAE); Assert.AreEqual(20, trade1.MFE); var trade2 = builder.ClosedTrades[1]; Assert.AreEqual(Symbol, trade2.Symbol); Assert.AreEqual(time.AddMinutes(30), trade2.EntryTime); Assert.AreEqual(1.08m, trade2.EntryPrice); Assert.AreEqual(TradeDirection.Long, trade2.Direction); Assert.AreEqual(1000, trade2.Quantity); Assert.AreEqual(time.AddMinutes(40), trade2.ExitTime); Assert.AreEqual(1.09m, trade2.ExitPrice); Assert.AreEqual(10, trade2.ProfitLoss); Assert.AreEqual(2, trade2.TotalFees); Assert.AreEqual(-15, trade2.MAE); Assert.AreEqual(20, trade2.MFE); var trade3 = builder.ClosedTrades[2]; Assert.AreEqual(Symbol, trade3.Symbol); Assert.AreEqual(time.AddMinutes(10), trade3.EntryTime); Assert.AreEqual(1.08m, trade3.EntryPrice); Assert.AreEqual(TradeDirection.Long, trade3.Direction); Assert.AreEqual(1000, trade3.Quantity); Assert.AreEqual(time.AddMinutes(40), trade3.ExitTime); Assert.AreEqual(1.09m, trade3.ExitPrice); Assert.AreEqual(10, trade3.ProfitLoss); Assert.AreEqual(0, trade3.TotalFees); Assert.AreEqual(-15, trade3.MAE); Assert.AreEqual(20, trade3.MFE); var trade4 = builder.ClosedTrades[3]; Assert.AreEqual(Symbol, trade4.Symbol); Assert.AreEqual(time, trade4.EntryTime); Assert.AreEqual(1.07m, trade4.EntryPrice); Assert.AreEqual(TradeDirection.Long, trade4.Direction); Assert.AreEqual(1000, trade4.Quantity); Assert.AreEqual(time.AddMinutes(40), trade4.ExitTime); Assert.AreEqual(1.09m, trade4.ExitPrice); Assert.AreEqual(20, trade4.ProfitLoss); Assert.AreEqual(1, trade4.TotalFees); Assert.AreEqual(-5, trade4.MAE); Assert.AreEqual(30, trade4.MFE); } } break; case FillGroupingMethod.FlatToFlat: { Assert.AreEqual(1, builder.ClosedTrades.Count); var trade = builder.ClosedTrades[0]; Assert.AreEqual(Symbol, trade.Symbol); Assert.AreEqual(time, trade.EntryTime); Assert.AreEqual(1.0775m, trade.EntryPrice); Assert.AreEqual(TradeDirection.Long, trade.Direction); Assert.AreEqual(4000, trade.Quantity); Assert.AreEqual(time.AddMinutes(40), trade.ExitTime); Assert.AreEqual(1.09m, trade.ExitPrice); Assert.AreEqual(50, trade.ProfitLoss); Assert.AreEqual(5, trade.TotalFees); Assert.AreEqual(-50, trade.MAE); Assert.AreEqual(90, trade.MFE); } break; case FillGroupingMethod.FlatToReduced: { Assert.AreEqual(2, builder.ClosedTrades.Count); var trade1 = builder.ClosedTrades[0]; Assert.AreEqual(Symbol, trade1.Symbol); Assert.AreEqual(matchingMethod == FillMatchingMethod.FIFO ? time : time.AddMinutes(10), trade1.EntryTime); Assert.AreEqual(matchingMethod == FillMatchingMethod.FIFO ? 1.07m : 1.08m, trade1.EntryPrice); Assert.AreEqual(TradeDirection.Long, trade1.Direction); Assert.AreEqual(1000, trade1.Quantity); Assert.AreEqual(time.AddMinutes(20), trade1.ExitTime); Assert.AreEqual(1.09m, trade1.ExitPrice); Assert.AreEqual(matchingMethod == FillMatchingMethod.FIFO ? 20 : 10, trade1.ProfitLoss); Assert.AreEqual(3, trade1.TotalFees); Assert.AreEqual(matchingMethod == FillMatchingMethod.FIFO ? -5 : -15, trade1.MAE); Assert.AreEqual(matchingMethod == FillMatchingMethod.FIFO ? 30 : 20, trade1.MFE); var trade2 = builder.ClosedTrades[1]; Assert.AreEqual(Symbol, trade2.Symbol); Assert.AreEqual(matchingMethod == FillMatchingMethod.FIFO ? time.AddMinutes(10) : time, trade2.EntryTime); Assert.AreEqual(matchingMethod == FillMatchingMethod.FIFO ? 1.08m : 1.0766666666666666666666666667m, trade2.EntryPrice); Assert.AreEqual(TradeDirection.Long, trade2.Direction); Assert.AreEqual(3000, trade2.Quantity); Assert.AreEqual(time.AddMinutes(40), trade2.ExitTime); Assert.AreEqual(1.09m, trade2.ExitPrice); Assert.AreEqual(matchingMethod == FillMatchingMethod.FIFO ? 30 : 40, trade2.ProfitLoss); Assert.AreEqual(2, trade2.TotalFees); Assert.AreEqual(matchingMethod == FillMatchingMethod.FIFO ? -45 : -35, trade2.MAE); Assert.AreEqual(matchingMethod == FillMatchingMethod.FIFO ? 60 : 70, trade2.MFE); } break; } }
public void ScaleInAllOutShort(FillGroupingMethod groupingMethod, FillMatchingMethod matchingMethod) { // Sell 1k, Sell 1k, Buy 2k var builder = new TradeBuilder(groupingMethod, matchingMethod); var time = _startTime; // Sell 1k builder.ProcessFill(new OrderEvent(1, Symbol, time, OrderStatus.Filled, OrderDirection.Sell, fillPrice: 1.08m, fillQuantity: -1000, orderFee: OrderFee), ConversionRate); Assert.IsTrue(builder.HasOpenPosition(Symbol)); builder.SetMarketPrice(Symbol, 1.075m); // Sell 1k builder.ProcessFill(new OrderEvent(2, Symbol, time.AddMinutes(10), OrderStatus.Filled, OrderDirection.Sell, fillPrice: 1.07m, fillQuantity: -1000, orderFee: OrderFee), ConversionRate); Assert.IsTrue(builder.HasOpenPosition(Symbol)); builder.SetMarketPrice(Symbol, 1.065m); builder.SetMarketPrice(Symbol, 1.10m); // Buy 2k builder.ProcessFill(new OrderEvent(3, Symbol, time.AddMinutes(20), OrderStatus.Filled, OrderDirection.Buy, fillPrice: 1.09m, fillQuantity: 2000, orderFee: OrderFee), ConversionRate); Assert.IsFalse(builder.HasOpenPosition(Symbol)); if (groupingMethod == FillGroupingMethod.FillToFill) { Assert.AreEqual(2, builder.ClosedTrades.Count); var trade1 = builder.ClosedTrades[matchingMethod == FillMatchingMethod.FIFO ? 0 : 1]; Assert.AreEqual(Symbol, trade1.Symbol); Assert.AreEqual(time, trade1.EntryTime); Assert.AreEqual(1.08m, trade1.EntryPrice); Assert.AreEqual(TradeDirection.Short, trade1.Direction); Assert.AreEqual(1000, trade1.Quantity); Assert.AreEqual(time.AddMinutes(20), trade1.ExitTime); Assert.AreEqual(1.09m, trade1.ExitPrice); Assert.AreEqual(-10, trade1.ProfitLoss); Assert.AreEqual(matchingMethod == FillMatchingMethod.FIFO ? 2 : 1, trade1.TotalFees); Assert.AreEqual(-20, trade1.MAE); Assert.AreEqual(15, trade1.MFE); var trade2 = builder.ClosedTrades[matchingMethod == FillMatchingMethod.FIFO ? 1 : 0]; Assert.AreEqual(Symbol, trade2.Symbol); Assert.AreEqual(time.AddMinutes(10), trade2.EntryTime); Assert.AreEqual(1.07m, trade2.EntryPrice); Assert.AreEqual(TradeDirection.Short, trade2.Direction); Assert.AreEqual(1000, trade2.Quantity); Assert.AreEqual(time.AddMinutes(20), trade2.ExitTime); Assert.AreEqual(1.09m, trade2.ExitPrice); Assert.AreEqual(-20, trade2.ProfitLoss); Assert.AreEqual(matchingMethod == FillMatchingMethod.FIFO ? 1 : 2, trade2.TotalFees); Assert.AreEqual(-30, trade2.MAE); Assert.AreEqual(5, trade2.MFE); } else { Assert.AreEqual(1, builder.ClosedTrades.Count); var trade = builder.ClosedTrades[0]; Assert.AreEqual(Symbol, trade.Symbol); Assert.AreEqual(time, trade.EntryTime); Assert.AreEqual(1.075m, trade.EntryPrice); Assert.AreEqual(TradeDirection.Short, trade.Direction); Assert.AreEqual(2000, trade.Quantity); Assert.AreEqual(time.AddMinutes(20), trade.ExitTime); Assert.AreEqual(1.09m, trade.ExitPrice); Assert.AreEqual(-30, trade.ProfitLoss); Assert.AreEqual(3, trade.TotalFees); Assert.AreEqual(-50, trade.MAE); Assert.AreEqual(20, trade.MFE); } }
public void ReversalShortToLong(FillGroupingMethod groupingMethod, FillMatchingMethod matchingMethod) { // Sell 1k, Buy 2k, Sell 1k var builder = new TradeBuilder(groupingMethod, matchingMethod); var time = _startTime; // Sell 1k builder.ProcessFill(new OrderEvent(1, Symbols.EURUSD, time, OrderStatus.Filled, OrderDirection.Sell, fillPrice: 1.07m, fillQuantity: -1000, orderFee: OrderFee), ConversionRate); Assert.IsTrue(builder.HasOpenPosition(Symbols.EURUSD)); builder.SetMarketPrice(Symbols.EURUSD, 1.075m); // Buy 2k builder.ProcessFill(new OrderEvent(2, Symbols.EURUSD, time.AddMinutes(10), OrderStatus.Filled, OrderDirection.Buy, fillPrice: 1.08m, fillQuantity: 2000, orderFee: OrderFee), ConversionRate); Assert.IsTrue(builder.HasOpenPosition(Symbols.EURUSD)); builder.SetMarketPrice(Symbols.EURUSD, 1.065m); builder.SetMarketPrice(Symbols.EURUSD, 1.10m); // Sell 1k builder.ProcessFill(new OrderEvent(3, Symbols.EURUSD, time.AddMinutes(20), OrderStatus.Filled, OrderDirection.Sell, fillPrice: 1.09m, fillQuantity: -1000, orderFee: OrderFee), ConversionRate); Assert.IsFalse(builder.HasOpenPosition(Symbols.EURUSD)); Assert.AreEqual(2, builder.ClosedTrades.Count); var trade1 = builder.ClosedTrades[0]; Assert.AreEqual(Symbols.EURUSD, trade1.Symbol); Assert.AreEqual(time, trade1.EntryTime); Assert.AreEqual(1.07m, trade1.EntryPrice); Assert.AreEqual(TradeDirection.Short, trade1.Direction); Assert.AreEqual(1000, trade1.Quantity); Assert.AreEqual(time.AddMinutes(10), trade1.ExitTime); Assert.AreEqual(1.08m, trade1.ExitPrice); Assert.AreEqual(-10, trade1.ProfitLoss); Assert.AreEqual(2, trade1.TotalFees); Assert.AreEqual(-10, trade1.MAE); Assert.AreEqual(0, trade1.MFE); var trade2 = builder.ClosedTrades[1]; Assert.AreEqual(Symbols.EURUSD, trade2.Symbol); Assert.AreEqual(time.AddMinutes(10), trade2.EntryTime); Assert.AreEqual(1.08m, trade2.EntryPrice); Assert.AreEqual(TradeDirection.Long, trade2.Direction); Assert.AreEqual(1000, trade2.Quantity); Assert.AreEqual(time.AddMinutes(20), trade2.ExitTime); Assert.AreEqual(1.09m, trade2.ExitPrice); Assert.AreEqual(10, trade2.ProfitLoss); Assert.AreEqual(1, trade2.TotalFees); Assert.AreEqual(-15, trade2.MAE); Assert.AreEqual(20, trade2.MFE); }