Example #1
0
        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);
        }
Example #2
0
        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;
            }
        }
Example #3
0
        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);
            }
        }
Example #4
0
        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);
        }