Exemple #1
0
        private static void CreateAccounts(IAccountServiceRpcClient client)
        {
            int             numThreads  = 10;
            int             numAccounts = 877;
            ParallelOptions opt         = new ParallelOptions()
            {
                MaxDegreeOfParallelism = numThreads
            };

            Parallel.For(0, numAccounts, opt, i => {
                var req = new AccountRequest {
                    FirstName = "Anthony " + i,
                    LastName  = "Chang"
                };
                Task <AccountResponse> resp = null;
                try {
                    resp = client.CreateAccountAsync(req).ResponseAsync;
                    resp.Wait();
                    Account account = resp.Result.Data;
                    Display(account.ToString());
                } catch (Exception e) {
                    Display("An error occurred: " + e.Message);
                }
            });
        }
 public OrderService(IDemoExchangeDbContextFactory <OrderContext> orderContextFactory,
                     ISubscriber subscriber, IAccountServiceRpcClient accountService)
 {
     this.orderContextFactory = orderContextFactory;
     this.subscriber          = subscriber;
     this.accountService      = accountService;
 }
Exemple #3
0
        private static void AccountTester(IAccountServiceRpcClient client)
        {
            var req = new CanFillOrderRequest {
                Order = new Order {
                    AccountId = "6056cfb6-a4ee-4a98-b71e-c082a732c473"
                },
                FillQuantity = 100
            };
            Task <CanFillOrderResponse> resp = null;

            try {
                resp = client.CanFillOrderAsync(req).ResponseAsync;
                resp.Wait();
                bool canFill = resp.Result.Value;
                Display("canFill: " + canFill);
            } catch (Exception e) {
                Display("An error occurred: " + e.Message);
            }
            Task <AccountList> listResp = null;

            try {
                listResp = client.ListAsync(new Empty()).ResponseAsync;
                listResp.Wait();
                ICollection <Account> data = listResp.Result.Accounts;
                data.ToList().ForEach(account => Display(account.ToString()));
            } catch (Exception e) {
                Display("An error occurred: " + e.Message);
            }
        }
Exemple #4
0
 public ApiGateway(IAccountServiceRpcClient accountService,
                   IOrderServiceRpcClient orderService, IQuoteServiceRpcClient quoteService)
 {
     this.accountService = accountService;
     this.orderService   = orderService;
     this.quoteService   = quoteService;
 }
Exemple #5
0
        public Simulator( //IOrderTestPerfService service,
            IAccountServiceRpcClient accountClient,
            IOrderServiceRpcClient orderClient)
        {
            // this.service = service;
            this.accountClient = accountClient;
            this.orderClient   = orderClient;
            var httpHandler = new HttpClientHandler();

            httpHandler.ServerCertificateCustomValidationCallback =
                HttpClientHandler.DangerousAcceptAnyServerCertificateValidator;
            var channel = GrpcChannel.ForAddress("https://hela:8090",
                                                 new GrpcChannelOptions {
                HttpHandler = httpHandler
            });

            this.apiClient = new ErxService.ErxServiceClient(channel);
        }
        private OrderTransactionResponseBL TryFillOrderBook(IAccountServiceRpcClient accountService)
        {
#if PERF_FINEST
            long start = Now;
#endif

            OrderBL            buyOrder     = BuyBook.First;
            OrderBL            sellOrder    = SellBook.First;
            List <OrderBL>     orders       = new List <OrderBL>();
            List <Transaction> transactions = new List <Transaction>();
            // QUESTION: Execute the limit order at sell price benefits BUYER fat finger
            //           What to do if SELLER fat finger? Shouldn't that give the SELLER
            //           the higher BID price?
            decimal executionPrice = sellOrder.StrikePrice;
            int     fillQuantity   = Math.Min(buyOrder.OpenQuantity, sellOrder.OpenQuantity);
            Task <CanFillOrderResponse> buyerResponse = accountService
                                                        .CanFillOrderAsync(new CanFillOrderRequest {
                Order        = buyOrder.ToMessage(),
                FillQuantity = fillQuantity
            }).ResponseAsync;
            Task <CanFillOrderResponse> sellerResponse = accountService
                                                         .CanFillOrderAsync(new CanFillOrderRequest {
                Order        = sellOrder.ToMessage(),
                FillQuantity = fillQuantity
            }).ResponseAsync;
            Task.WaitAll(buyerResponse, sellerResponse);
            bool canExecute = true;
            if (!buyerResponse.Result.Value)
            {
                BuyBook.RemoveOrder(buyOrder);
                buyOrder.Cancel();
                orders.Add(buyOrder);
                canExecute = false;
                // TODO: Publish order has been cancelled
            }
            if (!sellerResponse.Result.Value)
            {
                SellBook.RemoveOrder(sellOrder);
                sellOrder.Cancel();
                orders.Add(sellOrder);
                canExecute = false;
                // TODO: Publish order has been cancelled
            }
            if (!canExecute)
            {
                return(new OrderTransactionResponseBL(new OrderTransactionBL(orders, transactions)));
            }

            buyOrder.OpenQuantity  -= fillQuantity;
            sellOrder.OpenQuantity -= fillQuantity;
            Transaction transaction = new Transaction(buyOrder, sellOrder, buyOrder.Ticker,
                                                      fillQuantity, executionPrice);
            transactions.Add(transaction);
            orders.Add(SellBook.First);
            if (SellBook.First.IsFilled)
            {
                OrderBL filledOrder = SellBook.First;
                SellBook.RemoveOrder(filledOrder);
                filledOrder.Complete();
            }
            orders.Add(BuyBook.First);
            if (BuyBook.First.IsFilled)
            {
                OrderBL filledOrder = BuyBook.First;
                BuyBook.RemoveOrder(filledOrder);
                filledOrder.Complete();
            }
#if PERF_FINEST
            Logger.Here().Information(String.Format("TryFillOrderBook executed in {0} milliseconds", ((Now - start) / TimeSpan.TicksPerMillisecond)));
#endif

            return(new OrderTransactionResponseBL(new OrderTransactionBL(orders, transactions)));
        }
        private OrderTransactionResponseBL FillMarketOrder(IAccountServiceRpcClient accountService,
                                                           OrderBL order, OrderBook book)
        {
#if PERF_FINEST
            long start = Now;
#endif
            CheckArgument(!order.Action.Equals(book.Type), "Error: Wrong book");

            bool               done         = false;
            List <OrderBL>     orders       = new List <OrderBL>();
            List <Transaction> transactions = new List <Transaction>();
            while (!done)
            {
                if (book.IsEmpty)
                {
                    throw new SystemException("Order book is empty");          // TODO: Handle order book is empty
                }
                OrderBL buyOrder       = order.IsBuyOrder ? order : book.First;
                OrderBL sellOrder      = order.IsSellOrder ? order : book.First;
                decimal executionPrice = order.IsBuyOrder ? sellOrder.StrikePrice : buyOrder.StrikePrice;
                int     fillQuantity   = Math.Min(buyOrder.OpenQuantity, sellOrder.OpenQuantity);
                // QUESTION: Many issues here, partial fill, etc
                Task <CanFillOrderResponse> buyerResponse = accountService
                                                            .CanFillOrderAsync(new CanFillOrderRequest {
                    Order        = buyOrder.ToMessage(),
                    FillQuantity = fillQuantity
                }).ResponseAsync;
                Task <CanFillOrderResponse> sellerResponse = accountService
                                                             .CanFillOrderAsync(new CanFillOrderRequest {
                    Order        = sellOrder.ToMessage(),
                    FillQuantity = fillQuantity
                }).ResponseAsync;
                Task.WaitAll(buyerResponse, sellerResponse);
                bool canExecute = true;
                if (!buyerResponse.Result.Value)
                {
                    if (!order.IsBuyOrder)
                    {
                        BuyBook.RemoveOrder(buyOrder);
                    }
                    buyOrder.Cancel();
                    orders.Add(buyOrder);
                    canExecute = false;
                    // TODO: Publish order has been cancelled
                }
                if (!sellerResponse.Result.Value)
                {
                    if (!order.IsSellOrder)
                    {
                        SellBook.RemoveOrder(sellOrder);
                    }
                    sellOrder.Cancel();
                    orders.Add(sellOrder);
                    canExecute = false;
                    // TODO: Publish order has been cancelled
                }
                if (!order.IsOpen)
                {
                    return(new OrderTransactionResponseBL(new OrderTransactionBL(orders, transactions)));
                }
                if (!canExecute)
                {
                    continue;
                }

                buyOrder.OpenQuantity  -= fillQuantity;
                sellOrder.OpenQuantity -= fillQuantity;
                Transaction transaction = new Transaction(buyOrder, sellOrder, buyOrder.Ticker,
                                                          fillQuantity, executionPrice);
                transactions.Add(transaction);
                orders.Add(book.First);
                if (book.First.IsFilled)
                {
                    OrderBL filledOrder = book.First;
                    book.RemoveOrder(filledOrder);
                    filledOrder.Complete();
                }
                if (order.IsFilled)
                {
                    order.Complete();
                    orders.Add(order);
                    done = true;
                }
            }
#if PERF_FINEST
            Logger.Here().Information(String.Format("Market order executed in {0} milliseconds", ((Now - start) / TimeSpan.TicksPerMillisecond)));
#endif

            return(new OrderTransactionResponseBL(new OrderTransactionBL(orders, transactions)));
        }
        // QUESTION: Consider making async: https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap
        public OrderResponseBL SubmitOrder(IOrderContext context, ISubscriber subscriber, IAccountServiceRpcClient accountService, OrderBL order)
        {
#if (PERF || PERF_FINE || PERF_FINEST)
            long start = Now;
#endif
            OrderResponseBL insertResponse = InsertOrder(context, subscriber, order);
            if (insertResponse.HasErrors)
            {
                return(insertResponse);
            }

            OrderBook book = order.IsMarketOrder ?
                             order.IsBuyOrder ? SellBook : BuyBook :
                             order.IsBuyOrder ? BuyBook : SellBook;
            if (order.IsMarketOrder)
            {
                // QUESTION: Could potentially optimize to not do an initial save of a Market order
                //           but can we allow order entry during market close hours? What's MarketOnOpen?
                // The actual outcome of the match will be responded back asynchronously
                OrderTransactionResponseBL fillResponse = FillMarketOrder(accountService, order, book);
                if (fillResponse.HasErrors)
                {
                    return(insertResponse);
                }
                fillResponse = SaveOrderTransaction(context, subscriber, fillResponse.Data);
                if (fillResponse.HasErrors)
                {
                    return(insertResponse);
                }
#if DIAGNOSTICS
                DiagnosticsWriteDetails(fillResponse.Data);
#endif
#if (PERF || PERF_FINE || PERF_FINEST)
                Logger.Here().Information(String.Format("SubmitOrder: Market order executed in {0} milliseconds", ((Now - start) / TimeSpan.TicksPerMillisecond)));
#endif
                return(new OrderResponseBL(order));
            }

            book.AddOrder(order);
            bool done = false;
            while (!done)
            {
                if (BuyBook.IsEmpty || SellBook.IsEmpty)
                {
                    throw new SystemException("Order book is empty");                                 // TODO: Handle order book is empty
                }
                // The new order triggered a match
                // We'll try to match it here, but respond back with the insertResponse regardless
                // The actual outcome of the match will be responded back asynchronously
                if (BuyBook.First.StrikePrice >= SellBook.First.StrikePrice)
                {
                    OrderTransactionResponseBL fillResponse = TryFillOrderBook(accountService);
                    if (fillResponse.HasErrors)
                    {
                        return(insertResponse);
                    }
                    fillResponse = SaveOrderTransaction(context, subscriber, fillResponse.Data);
                    if (fillResponse.HasErrors)
                    {
                        return(insertResponse);
                    }
#if DIAGNOSTICS
                    DiagnosticsWriteDetails(fillResponse.Data);
#endif
                }
                else
                {
                    done = true;
                }
            }
#if (PERF || PERF_FINE || PERF_FINEST)
            Logger.Here().Information(String.Format("SubmitOrder: Processed in {0} milliseconds", ((Now - start) / TimeSpan.TicksPerMillisecond)));
#endif
            return(insertResponse);
        }