コード例 #1
0
        protected override async Task DoWork(PairConfig pair, CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    using (BinanceSocketClient client = new BinanceSocketClient())
                    {
                        CallResult <UpdateSubscription> res = client.SubscribeToBookTickerUpdates(pair.Symbol, async(data) =>
                        {
                            Book book            = new Book();
                            book.ExchangeCode    = Exchange.Code;
                            book.Symbol          = data.Symbol;
                            book.BestAskPrice    = data.BestAskPrice;
                            book.BestAskQuantity = data.BestAskQuantity;
                            book.BestBidPrice    = data.BestBidPrice;
                            book.BestBidQuantity = data.BestBidQuantity;

                            await _bookProcessor.Create(book);
                        });

                        res.Data.ConnectionLost     += () => { _logger.LogError($"Connection to {Exchange} is lost"); };
                        res.Data.ConnectionRestored += (data) => { _logger.LogError($"Connection to {Exchange} is Restored"); };

                        while (!stoppingToken.IsCancellationRequested)
                        {
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError($"{Exchange.Description} Trades service failed with message {ex.Message}", ex);
                }
            }
        }
コード例 #2
0
 public Task <PairConfig> Update(PairConfig entity)
 {
     return(WithConnection((connection, transaction) =>
     {
         return _pairConfigManager.Update(entity, connection, transaction);
     }));
 }
コード例 #3
0
        protected override async Task DoWork(PairConfig config, CancellationToken stoppingToken)
        {
            _logger.LogTrace($"{Exchange.Description} Candles monitor is started");

            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    using (BinanceClient client = new BinanceClient())
                    {
                        DateTime    now          = DateTime.UtcNow;
                        IPeriodCode candlePeriod = config.Timeframe.HasValue ? PeriodCode.Create(config.Timeframe.Value) : DefaultCandleInterval;

                        WebCallResult <IEnumerable <BinanceKline> > klines = client.GetKlines(config.Symbol, candlePeriod.ToPeriodCode(), now.AddDays(-30), now, 500);
                        _logger.LogTrace($"Received candles from {Exchange.Description}");

                        List <Candle> candles = klines.Data.Select(x => x.ToCandle(config.Symbol, candlePeriod)).ToList();
                        foreach (Candle candle in candles)
                        {
                            await _candleProcessor.Create(candle);
                        }
                    }

                    await Task.Delay(TimeSpan.FromHours(1));
                }
                catch (Exception ex)
                {
                    _logger.LogError($"{Exchange.Description} Candles service failed with message: {ex.Message}", ex);
                }
            }
        }
コード例 #4
0
        public Task <Deal> Sell(TradingForecast forecast, PairConfig config)
        {
            return(WithConnection(async(connection, transaction) =>
            {
                Book book = await _bookManager.GetLast(forecast.ExchangeCode, forecast.Symbol, connection, transaction);
                Balance balance = await _balanceManager.Get(config.AssetOne, forecast.ExchangeCode, connection, transaction);

                Order order = new Order();
                order.ExchangeCode = forecast.ExchangeCode;
                order.Symbol = forecast.Symbol;
                order.TradingModeCode = TradingModeCode.AUTO;
                order.FillPoliticsCode = FillPoliticsCode.GTC;
                order.OrderStatusCode = OrderStatusCode.PENDING;
                order.OrderTypeCode = OrderTypeCode.LMT;
                order.OrderSideCode = OrderSideCode.SELL;

                decimal availableQuantity = (balance.Available <= config.MaxOrderAmount.Value / book.BestBidPrice ? balance.Available : balance.Available / book.BestBidPrice);

                if (availableQuantity < config.MinOrderAmount.Value / book.BestBidPrice)
                {
                    throw new Exception($"Not enough funds. Exchange code: {forecast.ExchangeCode}, Asset: {config.AssetTwo}");
                }

                decimal quantity = Math.Round(availableQuantity, 3);

                order.Price = book.BestBidPrice;
                order.Amount = quantity;

                Deal deal = await _dealProcessor.CreateForOrder(order);
                return deal;
            }));
        }
コード例 #5
0
        public void SetBoolean()
        {
            var    config = new PairConfig();
            object ob     = true;

            config.SetField("is load", ob);

            Assert.That(config.ShouldLoad, Is.True);
        }
コード例 #6
0
        public async Task <Deal> UpdateForOrder(Order order, PairConfig config)
        {
            if (!order.DealId.HasValue)
            {
                return(null);
            }

            return(await WithConnection(async (connection, transaction) =>
            {
                Deal deal = await _dealManager.Get(order.DealId.Value, connection, transaction);
                if (deal == null)
                {
                    throw new Exception($"Deal {order.DealId} not found");
                }

                Order storedOrder = await _orderManager.Update(order, connection, transaction);

                if (order.OrderSideCode == OrderSideCode.BUY.Code)
                {
                    deal.AvgOpenPrice = order.Price;
                    deal.Amount = order.Amount;
                    deal.EstimatedFee = order.Fee *order.Price;
                    deal.TakeProfit = order.Price + order.Price * (decimal)config.DefaultTakeProfitPercent / 100;
                    deal.StopLoss = order.Price - order.Price * (decimal)config.DefaultStopLossPercent / 100;

                    if (order.TradingModeCode == TradingModeCode.AUTO.Code)
                    {
                        Order sellOrder = new Order();
                        sellOrder.ExchangeCode = deal.Exchange;
                        sellOrder.Symbol = deal.Symbol;
                        sellOrder.TradingModeCode = TradingModeCode.AUTO.Code;
                        sellOrder.FillPoliticsCode = FillPoliticsCode.GTC.Code;
                        sellOrder.OrderStatusCode = OrderStatusCode.PENDING.Code;
                        sellOrder.DealId = deal.Id;
                        sellOrder.OrderTypeCode = OrderTypeCode.LMT.Code;
                        sellOrder.OrderSideCode = OrderSideCode.SELL.Code;
                        sellOrder.Amount = deal.Amount;
                        sellOrder.Price = deal.TakeProfit;
                        sellOrder.StopLoss = deal.StopLoss;

                        await _orderManager.Create(order, connection, transaction);
                    }
                }
                else
                {
                    deal.AvgClosePrice = order.Price;
                    deal.EstimatedFee += order.Fee;
                    deal.StatusCode = OrderStatusCode.Create(order.OrderStatusCode).ToDealCode().Code;
                }

                deal = await _dealManager.Update(deal, connection, transaction);
                deal.Orders.Add(storedOrder);
                return deal;
            }));
        }
コード例 #7
0
        public async Task StopLoss(Trade trade, PairConfig config)
        {
            await WithConnection(async (connection, transaction) =>
            {
                IExchangeCode exchangeCode = ExchangeCode.Create(trade.ExchangeCode);

                IEnumerable <Deal> deals = await _dealManager.GetOpenDeals(trade.ExchangeCode, trade.Symbol, connection, transaction);
                foreach (Deal deal in deals)
                {
                    deal.Orders = await _orderManager.GetOrdersByDealId(deal.Id, connection, transaction) as List <Order>;
                    if (deal.StopLoss.HasValue && trade.Price < deal.StopLoss.Value)
                    {
                        foreach (Order dealOrder in deal.Orders)
                        {
                            if (dealOrder.OrderStatusCode == OrderStatusCode.PENDING.Code || dealOrder.OrderStatusCode == OrderStatusCode.EXPIRED.Code || dealOrder.OrderStatusCode == OrderStatusCode.HOLD.Code)
                            {
                                await _orderManager.Delete(dealOrder.Id, connection, transaction);
                            }
                            else if (dealOrder.OrderStatusCode == OrderStatusCode.LISTED.Code)
                            {
                                dealOrder.OrderStatusCode = OrderStatusCode.CANCELED.Code;
                                dealOrder.Updated         = DateTime.UtcNow;
                                dealOrder.UpdateRequired  = true;

                                await _orderManager.Update(dealOrder, connection, transaction);

                                NatsClient client = _connector.Client;
                                await client.PubAsJsonAsync(_settings.Value.OrdersQueueName, new Notification <Order>()
                                {
                                    Code = ActionCode.UPDATED.Code, Payload = dealOrder
                                });
                            }
                        }

                        Order order            = new Order();
                        order.ExchangeCode     = trade.ExchangeCode;
                        order.Symbol           = trade.Symbol;
                        order.TradingModeCode  = TradingModeCode.AUTO;
                        order.FillPoliticsCode = FillPoliticsCode.GTC;
                        order.OrderStatusCode  = OrderStatusCode.PENDING;
                        order.DealId           = deal.Id;
                        order.OrderTypeCode    = OrderTypeCode.MKT;
                        order.OrderSideCode    = OrderSideCode.SELL;
                        order.Amount           = deal.Amount;

                        order.Id = await _orderManager.Create(order, connection, transaction);
                    }
                }

                return(Task.CompletedTask);
            });
        }
コード例 #8
0
        protected override async Task DoWork(PairConfig pair, CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    using (BinanceSocketClient client = new BinanceSocketClient())
                    {
                        ConnectionInfo cnInfo = new ConnectionInfo(_settings.Value.BusConnectionString);
                        using (NatsClient natsClient = new NatsClient(cnInfo))
                        {
                            if (!natsClient.IsConnected)
                            {
                                natsClient.Connect();
                            }

                            CallResult <UpdateSubscription> successKline = null;
                            successKline = client.SubscribeToTradeUpdates(pair.Symbol, async(data) =>
                            {
                                Trade trade = data.ToEntity();

                                if (!_settings.Value.DisadleDealsSaving)
                                {
                                    long id = await _tradesProcessor.Create(trade);
                                }

                                await natsClient.PubAsJsonAsync(_settings.Value.TradesQueueName, new Notification <Trade>()
                                {
                                    Code = ActionCode.CREATED.Code, Payload = trade
                                });
                            });

                            successKline.Data.ConnectionLost     += () => { _logger.LogError($"Connection to {Exchange} is lost"); };
                            successKline.Data.ConnectionRestored += (data) => { _logger.LogError($"Connection to {Exchange} is Restored"); };

                            while (!stoppingToken.IsCancellationRequested)
                            {
                            }

                            natsClient.Disconnect();
                            await client.Unsubscribe(successKline.Data);
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError($"{Exchange.Description} Trades service failed with message {ex.Message}", ex);
                }
            }
        }
コード例 #9
0
        protected override async Task DoWork(PairConfig pair, CancellationToken stoppingToken)
        {
            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    await _tradesProcessor.ClearData(Exchange.Code, pair.Symbol);

                    await _bookProcessor.ClearData(Exchange.Code, pair.Symbol);

                    await Task.Delay(TimeSpan.FromHours(1));
                }
                catch (Exception ex)
                {
                    _logger.LogError($"{Exchange.Description} Trades service failed with message {ex.Message}", ex);
                }
            }
        }
コード例 #10
0
        private void CreatePair(Config config, string pair, IExchangeConfig client)
        {
            if (config.Pairs.ContainsKey(pair))
            {
                return;
            }
            var newConfig = new PairConfig {
                PlatformVariables = new Dictionary <string, object>()
            };

            if (client != null)
            {
                foreach (var pairVariable in client.PairVariables)
                {
                    newConfig.PlatformVariables.Add(pairVariable.Key, pairVariable.Value);
                }
            }
            config.Pairs.Add(pair, newConfig);
        }
コード例 #11
0
        protected override async Task DoWork(PairConfig pair, CancellationToken stoppingToken)
        {
            _logger.LogInformation($"{Exchange.Description} Candles worker is started");

            IPeriodCode candlePeriod = pair.Timeframe.HasValue ? PeriodCode.Create(pair.Timeframe.Value) : DefaultCandleInterval;

            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    using (BinanceSocketClient client = new BinanceSocketClient())
                    {
                        ConnectionInfo cnInfo = new ConnectionInfo(_settings.Value.BusConnectionString);
                        using (NatsClient natsClient = new NatsClient(cnInfo))
                        {
                            if (!natsClient.IsConnected)
                            {
                                natsClient.Connect();
                            }

                            CallResult <UpdateSubscription> successKline = client.SubscribeToKlineUpdates(pair.Symbol, candlePeriod.ToPeriodCode(), async(data) =>
                            {
                                await SaveCandle(data.Data, natsClient);
                            });

                            successKline.Data.ConnectionLost     += () => { _logger.LogError($"Connection to {Exchange} is lost"); };
                            successKline.Data.ConnectionRestored += (data) => { _logger.LogError($"Connection to {Exchange} is Restored"); };

                            while (!stoppingToken.IsCancellationRequested)
                            {
                            }

                            natsClient.Disconnect();
                            await client.Unsubscribe(successKline.Data);
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError($"{Exchange.Description} Candles service failed with message: {ex.Message}", ex);
                }
            }
        }
コード例 #12
0
        public async Task <PairConfig> Update(PairConfig entity, IDbConnection connection, IDbTransaction transaction = null)
        {
            string query = @"update
								PairConfigs
							set
								updated = @updated,
								isEnabled = @isEnabled,
								strategyId = @strategyId,
								refreshDelaySeconds = @refreshDelaySeconds,
								defaultStopLossPercent = @defaultStopLossPercent,
								defaultTakeProfitPercent = @defaultTakeProfitPercent,
								isTestMode = @isTestMode,
								exchangeFeeSell = @exchangeFeeSell,
								exchangeFeeBuy = @exchangeFeeBuy,
								tradingLockedTill = @tradingLockedTill,
								isMaxAmountPercent = @isMaxAmountPercent,
								maxOrderAmount = @maxOrderAmount
							where
								id = @id
							returning *;"                            ;

            return(await connection.QuerySingleAsync <PairConfig>(query,
                                                                  new
            {
                updated = DateTime.UtcNow,
                isEnabled = entity.IsEnabled,
                strategyId = entity.StrategyId,
                refreshDelaySeconds = entity.RefreshDelaySeconds,
                defaultStopLossPercent = entity.DefaultStopLossPercent,
                defaultTakeProfitPercent = entity.DefaultTakeProfitPercent,
                isTestMode = entity.IsTestMode,
                exchangeFeeSell = entity.ExchangeFeeSell,
                exchangeFeeBuy = entity.ExchangeFeeBuy,
                tradingLockedTill = entity.TradingLockedTill,
                minOrderAmount = entity.MinOrderAmount,
                maxOrderAmount = entity.MaxOrderAmount
            }, transaction));
        }
コード例 #13
0
 public Task TakeProfit(Trade trade, PairConfig config)
 {
     throw new NotImplementedException();
 }
コード例 #14
0
 protected abstract Task DoWork(PairConfig config, CancellationToken stoppingToken);
コード例 #15
0
        protected override async Task DoWork(PairConfig config, CancellationToken stoppingToken)
        {
            ExchangeConfig exchangeConfig = await _exchangeConfigProcessor.GetExchangeConfig(Exchange.Code);

            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    string listenKey = String.Empty;
                    using (BinanceClient client = new BinanceClient())
                    {
                        listenKey = client.StartUserStream().Data;
                    }

                    using (BinanceSocketClient socketClient = new BinanceSocketClient())
                    {
                        ConnectionInfo cnInfo = new ConnectionInfo(_settings.Value.BusConnectionString);
                        using (NatsClient natsClient = new NatsClient(cnInfo))
                        {
                            if (!natsClient.IsConnected)
                            {
                                natsClient.Connect();
                            }

                            CallResult <UpdateSubscription> successAccount = socketClient.SubscribeToUserDataUpdates(listenKey,
                                                                                                                     accountData =>
                            {
                            },
                                                                                                                     async orderData =>
                            {
                                Order order = orderData.ToOrder();
                                Deal deal   = await _dealProcessor.UpdateForOrder(order, config);

                                await natsClient.PubAsJsonAsync(_settings.Value.OrdersQueueName, new Notification <Deal>()
                                {
                                    Code = ActionCode.UPDATED.Code, Payload = deal
                                });
                            },
                                                                                                                     ocoOrderData =>
                            {
                            },
                                                                                                                     async balancesData =>
                            {
                                IEnumerable <Balance> balances = balancesData.Select(x => x.ToBalance());
                                foreach (Balance balance in balances)
                                {
                                    await _balanceProcessor.UpdateOrCreate(balance);
                                }
                            },
                                                                                                                     onAccountBalanceUpdate =>
                            {
                            });

                            while (!stoppingToken.IsCancellationRequested)
                            {
                            }

                            natsClient.Disconnect();
                            await socketClient.UnsubscribeAll();
                        }
                    }
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex.Message);
                }
            }
        }
コード例 #16
0
        public async Task <long> Create(PairConfig entity, IDbConnection connection, IDbTransaction transaction = null)
        {
            string query = @"insert into
								PairConfigs
								(
									id,
									created,
									updated,
									isEnabled,
									isDeleted,
									exchangeCode,
									symbol,
									strategyId,
									refreshDelaySeconds,
									defaultStopLossPercent,
									defaultTakeProfitPercent,
									isTestMode,
									exchangeFeeSell,
									exchangeFeeBuy,
									tradingLockedTill,
									minOrderAmount,
									maxOrderAmount
								)
							values
								(
									default,
									@created,
									null,
									true,
									false,
									@exchangeCode,
									@symbol,
									@strategyId,
									@refreshDelaySeconds,
									@defaultStopLossPercent,
									@defaultTakeProfitPercent,
									@isTestMode,
									@exchangeFeeSell,
									@exchangeFeeBuy,
									@tradingLockedTill,
									@minOrderAmount,
									@maxOrderAmount
								)
							returning id;"                            ;

            return(await connection.QuerySingleAsync <long>(query,
                                                            new
            {
                created = DateTime.UtcNow,
                exchangeCode = entity.ExchangeCode,
                symbol = entity.Symbol,
                strategyId = entity.StrategyId,
                refreshDelaySeconds = entity.RefreshDelaySeconds,
                defaultStopLossPercent = entity.DefaultStopLossPercent,
                defaultTakeProfitPercent = entity.DefaultTakeProfitPercent,
                isTestMode = entity.IsTestMode,
                exchangeFeeSell = entity.ExchangeFeeSell,
                exchangeFeeBuy = entity.ExchangeFeeBuy,
                tradingLockedTill = entity.TradingLockedTill,
                maxOrderAmount = entity.MaxOrderAmount,
                minOrderAmount = entity.MinOrderAmount
            }, transaction));
        }
コード例 #17
0
        public async Task <ExchangeOrder> Send(Order order, ExchangeConfig config)
        {
            ExchangeOrder exchangeOrder = null;
            PairConfig    pairConfig    = config.Pairs.FirstOrDefault(x => x.Symbol.Equals(order.Symbol));

            if (order.UpdateRequired)
            {
                using (BinanceClient client = new BinanceClient(new BinanceClientOptions()
                {
                    ApiCredentials = new ApiCredentials(config.ApiKey, config.ApiSecret)
                }))
                {
                    if (order.OrderStatusCode == OrderStatusCode.PENDING)
                    {
                        (bool success, string error, BinancePlacedOrder order)result;;
                        if (order.OrderTypeCode == OrderTypeCode.MKT.Code)
                        {
                            if (pairConfig.IsTestMode)
                            {
                                WebCallResult <BinancePlacedOrder> orderResult = await client.PlaceTestOrderAsync(order.Symbol, (OrderSide)order.OrderSideCode, OrderType.Market, order.Amount.Value, null, order.Id.ToString(), null, TimeInForce.GoodTillCancel);

                                result = (orderResult.Success, orderResult.Error.Message, orderResult.Data);
                            }
                            else
                            {
                                WebCallResult <BinancePlacedOrder> orderResult = await client.PlaceOrderAsync(order.Symbol, (OrderSide)order.OrderSideCode, OrderType.Market, order.Amount.Value, null, order.Id.ToString(), null, TimeInForce.GoodTillCancel);

                                result = (orderResult.Success, orderResult.Error.Message, orderResult.Data);
                            }
                        }
                        else if (order.OrderTypeCode == OrderTypeCode.LMT.Code)
                        {
                            if (pairConfig.IsTestMode)
                            {
                                WebCallResult <BinancePlacedOrder> orderResult = await client.PlaceTestOrderAsync(order.Symbol, (OrderSide)order.OrderSideCode, OrderType.Limit, order.Amount.Value, null, order.Id.ToString(), order.Price, TimeInForce.GoodTillCancel);

                                result = (orderResult.Success, orderResult.Error.Message, orderResult.Data);
                            }
                            else
                            {
                                WebCallResult <BinancePlacedOrder> orderResult = await client.PlaceOrderAsync(order.Symbol, (OrderSide)order.OrderSideCode, OrderType.Limit, order.Amount.Value, null, order.Id.ToString(), order.Price, TimeInForce.GoodTillCancel);

                                result = (orderResult.Success, orderResult.Error.Message, orderResult.Data);
                            }
                        }
                        else if (order.OrderTypeCode == OrderTypeCode.LST.Code)
                        {
                            if (pairConfig.IsTestMode)
                            {
                                // OCO Order can't be used in test mode
                                WebCallResult <BinancePlacedOrder> orderResult = await client.PlaceTestOrderAsync(order.Symbol, (OrderSide)order.OrderSideCode, OrderType.Limit, order.Amount.Value, null, order.Id.ToString(), order.Price, TimeInForce.GoodTillCancel);

                                result = (orderResult.Success, orderResult.Error.Message, orderResult.Data);
                            }
                            else
                            {
                                if (order.OrderSideCode == OrderSideCode.BUY.Code)
                                {
                                    // For now let's use limit standard order
                                    WebCallResult <BinancePlacedOrder> orderResult = await client.PlaceOrderAsync(order.Symbol, OrderSide.Buy, OrderType.Limit, order.Amount.Value, null, order.Id.ToString(), order.Price, TimeInForce.GoodTillCancel);

                                    result = (orderResult.Success, orderResult.Error.Message, orderResult.Data);
                                }
                                else
                                {
                                    WebCallResult <BinanceOrderList> orderResult = await client.PlaceOCOOrderAsync(order.Symbol, OrderSide.Sell, order.Amount.Value, order.Price.Value, order.StopLoss.Value);

                                    result = (orderResult.Success, orderResult.Error.Message, orderResult.Data.OrderReports.First());
                                }
                            }
                        }
                        else
                        {
                            throw new Exception($"{order.Id} selected order type isn't supported");
                        }

                        if (!result.success)
                        {
                            throw new Exception(result.error);
                        }

                        exchangeOrder = result.order.ToOrder();
                        _logger.LogInformation($"{Exchange.Description} - Order {order.Id} has been processed with status: {result.order.Status}");
                    }
                    else if (order.OrderStatusCode == OrderStatusCode.CANCELED)
                    {
                        WebCallResult <BinanceCanceledOrder> cancelResult = await client.CancelOrderAsync(order.Symbol, order.ExchangeOrderId);

                        if (!cancelResult.Success)
                        {
                            throw new Exception(cancelResult.Error.Message);
                        }

                        exchangeOrder = cancelResult.Data.ToOrder();
                        _logger.LogInformation($"{Exchange.Description} - Order {order.Id} has been processed with status: {cancelResult.Data.Status}");
                    }
                    else
                    {
                        throw new Exception($"{Exchange.Description} - Can't update update order {order.Id}: wrong status");
                    }
                }
            }

            return(exchangeOrder);
        }