public async Task PlaceMarketOrderTest()
        {
            _handler.Expect(HttpMethod.Post, $"{BaseUri}orders/market-order")
            .WithQueryString(new Dictionary <string, string>
            {
                ["figi"]            = Figi,
                ["brokerAccountId"] = BrokerAccountId
            })
            .WithJsonContentFromFile("market-order-request")
            .RespondJsonFromFile("market-order-response");

            var response =
                await _context.PlaceMarketOrderAsync(new MarketOrder(Figi, 10, OperationType.Buy,
                                                                     BrokerAccountId));

            var expected = new PlacedMarketOrder(
                "40fcdfa2-084b-41bc-8f9d-3414a5eb9e8c",
                OperationType.Buy,
                OrderStatus.Fill,
                "That's Why",
                10,
                5,
                new MoneyAmount(Currency.Usd, 1.44m));

            response.Should().BeEquivalentTo(expected);
        }
Пример #2
0
 public PlacedOrder(PlacedMarketOrder order, string name, DateTime time, decimal price) :
     this(order.OrderId, order.Operation, name, order.ExecutedLots, order.Status, time, price)
 {
 }
Пример #3
0
        public async Task Perform(DateTime time, CancellationToken ct)
        {
            Console.WriteLine($"PERFORM START {Stock} at {time}");

            var candles = await _contextProvider.Do(ctx => ctx.MarketCandlesAsync(Stock.Figi,
                                                                                  time.Subtract(TimeSpan.FromMinutes(20)), time,
                                                                                  CandleInterval.Minute), ct);

            ct.ThrowIfCancellationRequested();

            CandlePayload?candle = candles.Candles.LastOrDefault();

            candle.Dump();

            bool IsBuyStop() => candle != null && (Stock.Close - candle.Close >= Stock.Tick * 20);

            switch (Status)
            {
            case Init _:
            {
                if (IsBuyStop())
                {
                    Status = new BuyStop();
                }
                else if (candle != null)
                {
                    Status = new WaitingForBuy();
                }
            }
            break;

            case WaitingForBuy _:
            {
                if (candle == null)
                {
                    Status = new Closed();
                }
                else if (IsBuyStop())
                {
                    Status = new BuyStop();
                }
            }
            break;

            case BuyStop _:
            {
                if (candle == null)
                {
                    Status = new Closed();
                }
                else if (candle.Close > Stock.Close)
                {
                    PlacedMarketOrder order = await _contextProvider.Do(ctx => ctx.PlaceMarketOrderAsync(
                                                                            new MarketOrder(Stock.Figi, 1, OperationType.Buy)
                                                                            ), ct);

                    ct.ThrowIfCancellationRequested();
                    order.Dump();
                    _addOrder(new PlacedOrder(order, Stock.Name, time, candle.Close));

                    if (order.Status == OrderStatus.Rejected)
                    {
                        Console.WriteLine($"Buy order rejected: {order.RejectReason}");
                        break;
                    }

                    Status = new WaitingForSell
                    {
                        SellPrice  = candle.Close - Stock.Half(),
                        TakeProfit = candle.Close + Stock.Part(60M)
                    };
                }
            }
            break;

            case WaitingForSell status:
            {
                if (candle == null)
                {
                    break;
                }

                var possiblyNewStop = candle.Close - Stock.Half();
                if (possiblyNewStop > status.SellPrice)
                {
                    status.SellPrice = possiblyNewStop;
                    Console.WriteLine("Limit became higher");
                }

                if (candle.Close <= status.SellPrice ||
                    candle.Close >= status.TakeProfit && status.TakeProfit != default)
                {
                    var position = (await _contextProvider.Do(c => c.PortfolioAsync()))
                                   .Positions
                                   .FirstOrDefault(it => it.Figi == candle.Figi);
                    if (position != null)
                    {
                        var closeOrder = await _contextProvider.Do(ctx => ctx.PlaceMarketOrderAsync(
                                                                       new MarketOrder(Stock.Figi, 1, OperationType.Sell)
                                                                       ), ct);

                        ct.ThrowIfCancellationRequested();
                        closeOrder.Dump();
                        _addOrder(new PlacedOrder(closeOrder, Stock.Name, time, candle.Close));

                        if (closeOrder.Status == OrderStatus.Rejected)
                        {
                            Console.WriteLine($"Sell order rejected: {closeOrder.RejectReason}");
                            break;
                        }
                    }

                    Status = new Closed();
                }
            }
            break;
            }

            Console.WriteLine($"STATUS: {Status}");
        }