diff --git a/InterReact.Tests/SystemTests/Orders/CompletedOrdersTest.cs b/InterReact.Tests/SystemTests/Orders/CompletedOrdersTest.cs index c3b6179..8ef1b6c 100644 --- a/InterReact.Tests/SystemTests/Orders/CompletedOrdersTest.cs +++ b/InterReact.Tests/SystemTests/Orders/CompletedOrdersTest.cs @@ -7,18 +7,18 @@ public class Completed : CollectionTestBase public Completed(ITestOutputHelper output, TestFixture fixture) : base(output, fixture) { } - //[Fact] - //public async Task CompletedOrdersAsyncTest() - //{ - // bool api = true; + [Fact] + public async Task CompletedOrdersAsyncTest() + { + bool api = true; - // IList orders = await Client - // .Service - // .GetCompleteOrdersAsync(api); + IList orders = await Client + .Service + .GetCompleteOrdersAsync(api); - // Write($"Complete orders found: {orders.Count}."); + Write($"Complete orders found: {orders.Count}."); - // foreach (CompletedOrder order in orders) - // Write(order.Stringify()); - //} + foreach (CompletedOrder order in orders) + Write(order.Stringify()); + } } diff --git a/InterReact.Tests/SystemTests/Orders/OpenOrderTests.cs b/InterReact.Tests/SystemTests/Orders/OpenOrderTests.cs index b604ea9..ed6d09e 100644 --- a/InterReact.Tests/SystemTests/Orders/OpenOrderTests.cs +++ b/InterReact.Tests/SystemTests/Orders/OpenOrderTests.cs @@ -6,20 +6,48 @@ public class Open : CollectionTestBase { public Open(ITestOutputHelper output, TestFixture fixture) : base(output, fixture) { } - //[Fact(Skip = "Test may conflict when run together with order placement tests")] - //public async Task OpenOrdersAsyncTest() - //{ - // await Task.Delay(3000); + [Fact] + public async Task OpenOrdersAsyncTest() + { + await Task.Delay(1000); - // IList list = await Client - // .Service - // .GetOpenOrdersAsync(OpenOrdersRequestType.OpenOrders) - // .WaitAsync(TimeSpan.FromSeconds(10)); + // 1 place order + // Place the order with orderId: orderId + var contract = new Contract() + { + SecurityType = ContractSecurityType.Stock, + Symbol = "AMZN", + Currency = "USD", + Exchange = "SMART" + }; - // Write($"Open orders found: {list.Count}."); + int orderId = Client.Request.GetNextId(); - // foreach (object item in list) - // Write(item.Stringify()); - //} + var order = new Order() + { + Action = OrderAction.Buy, + TotalQuantity = 1, + OrderType = OrderTypes.Limit, + LimitPrice = 1, + TimeInForce = OrderTimeInForce.GoodUntilCancelled + }; + + OrderMonitor orderMonitor = await Client.Service.PlaceOrderAsync(order, contract); + + //2 Request Open Order + IList openOrders = await Client + .Service + .RequestOpenOrdersAsync() + .WaitAsync(TimeSpan.FromSeconds(1)); + + Write($"Open orders found: {openOrders.Count}."); + + foreach (Object item in openOrders) + Write(item.Stringify()); + + //3 cancel Order + orderMonitor.CancelOrder(); + orderMonitor.Dispose(); + } } diff --git a/InterReact.Tests/SystemTests/Orders/OrderIntegrationTests.cs b/InterReact.Tests/SystemTests/Orders/OrderIntegrationTests.cs new file mode 100644 index 0000000..fcd2ec8 --- /dev/null +++ b/InterReact.Tests/SystemTests/Orders/OrderIntegrationTests.cs @@ -0,0 +1,87 @@ +using InterReact; +using Stringification; +using System.Reactive.Linq; +using System.Reactive.Threading.Tasks; + +namespace Orders +{ + public class OrderIntegrationTests: CollectionTestBase + { + + public OrderIntegrationTests(ITestOutputHelper output, TestFixture fixture) : base(output, fixture) { } + + + [Fact] + public async Task Place_GetOpen_Cancel_Order_Test() + { + // Place the order with orderId: orderId + var contract = new Contract() + { + SecurityType = ContractSecurityType.Stock, + Symbol = "AMZN", + Currency = "USD", + Exchange = "SMART" + }; + + int orderId = Client.Request.GetNextId(); + + var order = new Order() + { + Action = OrderAction.Buy, + TotalQuantity = 1, + OrderType = OrderTypes.Limit, + LimitPrice = 1, + TimeInForce = OrderTimeInForce.GoodUntilCancelled + }; + + OrderMonitor orderMonitor = await Client.Service.PlaceOrderAsync(order, contract); + + orderMonitor.CancelOrder(); + + OrderStatusReport report = await orderMonitor + .Messages + .OfType() + .Take(TimeSpan.FromSeconds(3)) + .FirstOrDefaultAsync(); + + //orderMonitor.Dispose(); + Assert.True(report.Status == OrderStatus.Cancelled || report.Status == OrderStatus.ApiCancelled); + + + // 等待1秒 + await Task.Delay(1000); + + + // Get the order, if contains orderId, succeed + Task> task2 = Client + .Response + .Take(TimeSpan.FromSeconds(3)) + .ToList() + .ToTask(); + + Client.Request.RequestOpenOrders(); + var openOrder = await task2; + Assert.IsType(openOrder); + + // 等待1秒 + await Task.Delay(1000); + + + // cancel the order + Task task3 = Client + .Response + .WithOrderId(orderId) + .OfType() + .Take(TimeSpan.FromSeconds(3)) + .FirstOrDefaultAsync() + .ToTask(); + Client.Request.CancelOrder(orderId); + Execution? execution3 = await task3; + Assert.NotNull(execution3); + + await Task.Run(() => Console.WriteLine("3")); + } + + + } +} diff --git a/InterReact.Tests/SystemTests/Orders/OrderMonitorTest.cs b/InterReact.Tests/SystemTests/Orders/OrderMonitorTest.cs index e21a07e..75a3239 100644 --- a/InterReact.Tests/SystemTests/Orders/OrderMonitorTest.cs +++ b/InterReact.Tests/SystemTests/Orders/OrderMonitorTest.cs @@ -28,7 +28,7 @@ public async Task OrderMonitorTest() OrderType = OrderTypes.Market }; - OrderMonitor orderMonitor = Client.Service.PlaceOrder(order, contract); + OrderMonitor orderMonitor = await Client.Service.PlaceOrderAsync(order, contract); orderMonitor .Messages @@ -66,7 +66,7 @@ public async Task OrderMonitorCancellationTest() OrderType = OrderTypes.Market }; - OrderMonitor orderMonitor = Client.Service.PlaceOrder(order, contract); + OrderMonitor orderMonitor = await Client.Service.PlaceOrderAsync(order, contract); orderMonitor.CancelOrder(); @@ -109,7 +109,7 @@ public async Task OrderMonitorModificationTest() }; // Place the order - OrderMonitor orderMonitor = Client.Service.PlaceOrder(order, contract); + OrderMonitor orderMonitor = await Client.Service.PlaceOrderAsync(order, contract); //await Task.Delay(100); diff --git a/InterReact/InterReact.csproj b/InterReact/InterReact.csproj index 954b2ee..c51ab18 100644 --- a/InterReact/InterReact.csproj +++ b/InterReact/InterReact.csproj @@ -18,6 +18,7 @@ true All CA1848; + InterReact.IBKR diff --git a/InterReact/Services/OrderMonitor.cs b/InterReact/Services/OrderMonitor.cs index 279b216..5b7c632 100644 --- a/InterReact/Services/OrderMonitor.cs +++ b/InterReact/Services/OrderMonitor.cs @@ -1,4 +1,6 @@ using System.Reactive.Subjects; +using System.Reactive.Linq; +using System.Reactive.Threading.Tasks; namespace InterReact; @@ -7,8 +9,41 @@ public partial class Service /// /// Places an order and returns an OrderMonitor object (below) which can be used to monitor the order. /// - public OrderMonitor PlaceOrder(Order order, Contract contract) => - new(order, contract, Request, Response); + public async Task PlaceOrderAsync(Order order, Contract contract) + { + return await Task.Run(() => + { + return new OrderMonitor(order, contract, Request, Response); + }); + } + + public async Task> RequestOpenOrdersAsync() + { + Task> task = + Response + .OfType() + .Take(TimeSpan.FromMilliseconds(500)) + .ToList() + .ToTask(); + Request.RequestOpenOrders(); + var orders = await task; + return orders; + } + + public async Task> GetCompleteOrdersAsync(bool api) + { + Task> task = + Response + .OfType() + .Take(TimeSpan.FromMilliseconds(500)) + .ToList() + .ToTask(); + + Request.RequestCompletedOrders(api); + + var completedOrders = await task; + return completedOrders; + } } ///