Exemplo n.º 1
0
 protected override IWebSocket OnGetTradesWebSocket(Func <KeyValuePair <string, ExchangeTrade>, Task> callback, params string[] marketSymbols)
 {
     /*
      * spot request:
      * {"op": "subscribe", "args": ["spot/trade:BTC-USD"]}
      * futures request:
      * {"op": "subscribe", "args":["futures/trade:BTC-USD-190628"]}
      * swap request:
      * {"op": "subscribe", “args":["swap/trade:BTC-USD-SWAP"]}
      */
     /*
      *       response:
      *       {
      *                "table": "swap/trade",
      *                "data": [{
      *                              "instrument_id": "BTC-USD-SWAP",
      *                              "price": "3250",
      *                              "side": "sell",
      *                              "size": "1",
      *                              "timestamp": "2018-12-17T09:48:41.903Z",
      *                              "trade_id": "126518511769403393"
      *                }]
      *       }
      */
     return(ConnectWebSocketOkex(async(_socket) =>
     {
         await AddMarketSymbolsToChannel(_socket, "/trade:{0}", marketSymbols);
     }, async(_socket, symbol, sArray, token) =>
     {
         ExchangeTrade trade = token.ParseTrade(amountKey: "size", priceKey: "price",
                                                typeKey: "side", timestampKey: "timestamp",
                                                timestampType: TimestampType.Iso8601, idKey: "trade_id");
         await callback(new KeyValuePair <string, ExchangeTrade>(symbol, trade));
     }));
 }
        public Task <ExchangeTrade> MarketTrade(MarketTradeRequest request)
        {
            if (!Prices.TryGetValue(request.Market, out var price))
            {
                throw new Exception($"Cannot found MOCK price for {request.Market}");
            }


            var oppVol = double.Parse(((decimal)price * (decimal)request.Volume * -1m).ToString(CultureInfo.InvariantCulture));

            var trade = new ExchangeTrade()
            {
                Id             = Guid.NewGuid().ToString("N"),
                Price          = price,
                Side           = request.Side,
                Volume         = request.Volume,
                Market         = request.Market,
                OppositeVolume = oppVol,
                Timestamp      = DateTime.UtcNow,
                ReferenceId    = request.ReferenceId,
                Source         = Name,
            };

            Trades[Name].Add(trade);

            return(Task.FromResult(trade));
        }
Exemplo n.º 3
0
        public async Task ExternalTrade_FullHedge_Sell()
        {
            _manager.Start();

            var trades = new List <WalletTradeMessage>()
            {
                new WalletTradeMessage()
                {
                    BrokerId = "broker",
                    WalletId = "TEST",
                    ClientId = "client",
                    Trade    = new WalletTrade("1", "BTCUSD", 10000, -2, 20000,
                                               "1", OrderType.Market, 1, DateTime.UtcNow, OrderSide.Sell, 3, string.Empty, 0),
                }
            };

            var trade2 = new ExchangeTrade()
            {
                Id             = "11",
                Price          = 11000,
                Volume         = 2,
                Side           = OrderSide.Buy,
                Market         = "BTC/USD",
                OppositeVolume = -22000,
                Timestamp      = DateTime.UtcNow,
                ReferenceId    = "1",

                Source            = "FTX",
                AssociateSymbol   = "BTCUSD",
                AssociateBrokerId = "broker",
                AssociateWalletId = "TEST"
            };

            await _manager.RegisterLocalTradesAsync(trades);

            await _manager.RegisterHedgeTradeAsync(trade2);

            _repository.Data.Should().BeEmpty();
            _portfolioReport.ClosedPosition.Should().HaveCount(1);

            var position = _portfolioReport.ClosedPosition.First();

            position.Should().BeEquivalentTo(new
            {
                IsOpen           = false,
                Side             = OrderSide.Sell,
                BaseAsset        = "BTC",
                QuotesAsset      = "USD",
                BaseVolume       = 0,
                QuoteVolume      = -2000,
                ResultPercentage = -10
            });
        }
Exemplo n.º 4
0
        public async Task ExternalTrade_FullHedge()
        {
            _repository.Data["1"] = new PositionPortfolio()
            {
                Id          = "1",
                WalletId    = "TEST",
                Symbol      = "BTCUSD",
                IsOpen      = true,
                Side        = OrderSide.Buy,
                BaseAsset   = "BTC",
                QuotesAsset = "USD",
                BaseVolume  = 2,
                QuoteVolume = -20000,
                OpenTime    = DateTime.UtcNow
            };

            _manager.Start();

            var trade = new ExchangeTrade()
            {
                Id             = "11",
                Price          = 11000,
                Volume         = -2,
                Side           = OrderSide.Sell,
                Market         = "BTC/USD",
                OppositeVolume = 22000,
                Timestamp      = DateTime.UtcNow,
                ReferenceId    = "1",

                Source            = "FTX",
                AssociateSymbol   = "BTCUSD",
                AssociateBrokerId = "broker",
                AssociateWalletId = "TEST"
            };

            await _manager.RegisterHedgeTradeAsync(trade);

            _repository.Data.Should().BeEmpty();
            _portfolioReport.ClosedPosition.Should().HaveCount(1);

            var position = _portfolioReport.ClosedPosition.First();

            position.Should().BeEquivalentTo(new
            {
                IsOpen      = false,
                Side        = OrderSide.Buy,
                BaseAsset   = "BTC",
                QuotesAsset = "USD",
                BaseVolume  = 0,
                QuoteVolume = 2000
            });
        }
        private IEnumerable <ExchangeTrade> ParseTradesWebSocket(JToken token)
        {
            var exchangeTradeList = new List <ExchangeTrade>();

            foreach (var jtoken in token)
            {
                var timeSpan = TimeSpan.Parse(jtoken[3].ToStringInvariant());
                var dateTime = DateTime.Today;
                dateTime = dateTime.Add(timeSpan);
                var universalTime = dateTime.ToUniversalTime();
                var exchangeTrade = new ExchangeTrade
                {
                    Id        = jtoken[0].ConvertInvariant(0L),
                    Price     = jtoken[1].ConvertInvariant(new decimal()),
                    Amount    = jtoken[2].ConvertInvariant(new decimal()),
                    Timestamp = universalTime,
                    IsBuy     = jtoken[4].ToStringInvariant().EqualsWithOption("bid", StringComparison.OrdinalIgnoreCase)
                };
                exchangeTradeList.Add(exchangeTrade);
            }

            return(exchangeTradeList);
        }
Exemplo n.º 6
0
 // Extension Method: Display contents of an ExchangeTrade object
 public static void Print(this ExchangeTrade t)
 {
     Console.WriteLine("{0} {1} {2}", t.Timestamp.ToDisplay(), t.Price, t.Amount);
 }
Exemplo n.º 7
0
        public async Task <ExchangeTrade> MarketTrade(MarketTradeRequest request)
        {
            try
            {
                using var action = MyTelemetry.StartActivity("FTX Market Trade");
                request.AddToActivityAsJsonTag("request");

                var refId = request.ReferenceId ?? Guid.NewGuid().ToString("N");

                refId.AddToActivityAsTag("reference-id");

                var size = (decimal)Math.Abs(request.Volume);

                var resp = await _restApi.PlaceOrderAsync(request.Market,
                                                          request.Side == OrderSide.Buy?SideType.buy : SideType.sell, 0, OrderType.market,
                                                          size, refId, true);

                resp.AddToActivityAsJsonTag("marketOrder-response");

                if (!resp.Success && resp.Error != "Duplicate client order ID")
                {
                    throw new Exception(
                              $"Cannot place marketOrder. Error: {resp.Error}. Request: {JsonConvert.SerializeObject(request)}. Reference: {refId}");
                }

                action?.AddTag("is-duplicate", resp.Error == "Duplicate client order ID");

                var tradeData = await _restApi.GetOrderStatusByClientIdAsync(refId);

                if (!tradeData.Success)
                {
                    throw new Exception(
                              $"Cannot get order state. Error: {resp.Error}. Request: {JsonConvert.SerializeObject(request)}. Reference: {refId}");
                }

                if (tradeData.Result.Status != "closed")
                {
                    await _restApi.CancelOrderByClientIdAsync(refId);
                }

                tradeData = await _restApi.GetOrderStatusByClientIdAsync(refId);

                tradeData.AddToActivityAsJsonTag("order-status-response");

                if (!tradeData.Success)
                {
                    throw new Exception(
                              $"Cannot get second order state. Error: {resp.Error}. Request: {JsonConvert.SerializeObject(request)}. Reference: {refId}");
                }

                size = tradeData.Result.FilledSize ?? 0;
                if (tradeData.Result.Side == "sell")
                {
                    size = size * -1;
                }

                var trade = new ExchangeTrade()
                {
                    Id          = (tradeData.Result.Id ?? 0).ToString(CultureInfo.InvariantCulture),
                    Market      = tradeData.Result.Market,
                    Side        = tradeData.Result.Side == "buy" ? OrderSide.Buy : OrderSide.Sell,
                    Price       = (double)(tradeData.Result.AvgFillPrice ?? 0),
                    ReferenceId = tradeData.Result.ClientId,
                    Source      = FtxConst.Name,
                    Volume      = (double)size,
                    Timestamp   = tradeData.Result.CreatedAt
                };

                trade.AddToActivityAsJsonTag("response");

                if (resp.Error == "Duplicate client order ID")
                {
                    _logger.LogInformation("Ftx trade is Duplicate. Request: {requestJson}. Trade: {tradeJson}",
                                           JsonConvert.SerializeObject(request), JsonConvert.SerializeObject(trade));
                }
                else
                {
                    _logger.LogInformation("Ftx trade is done. Request: {requestJson}. Trade: {tradeJson}",
                                           JsonConvert.SerializeObject(request), JsonConvert.SerializeObject(trade));
                }

                return(trade);
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Cannot execute trade. Request: {requestJson}",
                                 JsonConvert.SerializeObject(request));
                throw;
            }
        }