public void ProcessAllRules()
        {
            if (tradingService.Config.BuyEnabled)
            {
                IEnumerable <ISignal> allSignals = signalsService.GetAllSignals();
                if (allSignals != null)
                {
                    IEnumerable <IRule> enabledRules = signalsService.Rules.Entries.Where(r => r.Enabled);
                    if (enabledRules.Any())
                    {
                        var           groupedSignals = allSignals.Where(s => tradingService.GetPairConfig(s.Pair).BuyEnabled).GroupBy(s => s.Pair).ToDictionary(g => g.Key, g => g.ToDictionary(s => s.Name, s => s));
                        double?       globalRating   = signalsService.GetGlobalRating();
                        List <String> excludedPairs  = GetExcludedPairs();

                        if (signalsService.RulesConfig.ProcessingMode == RuleProcessingMode.FirstMatch)
                        {
                            excludedPairs.AddRange(trailingSignals.Keys);
                        }

                        foreach (IRule rule in enabledRules)
                        {
                            foreach (var group in groupedSignals)
                            {
                                Dictionary <string, ISignal> signals = group.Value;
                                ProcessRule(rule, signals, group.Key, excludedPairs, globalRating);
                            }
                        }
                    }

                    healthCheckService.UpdateHealthCheck(Constants.HealthChecks.SignalRulesProcessed, $"Rules: {enabledRules.Count()}, Trailing signals: {trailingSignals.Count}");
                }
            }
        }
Example #2
0
        public IActionResult BuyDefault(BuyRequest buyRequest)
        {
            if (Application.Resolve <ICoreService>().Config.ReadOnlyMode)
            {
                return(new BadRequestResult());
            }

            if (!string.IsNullOrWhiteSpace(buyRequest.Pair))
            {
                ISignalsService signalsService = Application.Resolve <ISignalsService>();
                ITradingService tradingService = Application.Resolve <ITradingService>();

                tradingService.Buy(new BuyOptions(buyRequest.Pair)
                {
                    MaxCost        = tradingService.GetPairConfig(buyRequest.Pair).BuyMaxCost,
                    IgnoreExisting = true,
                    ManualOrder    = true,
                    Metadata       = new OrderMetadata
                    {
                        BoughtGlobalRating = signalsService.GetGlobalRating()
                    }
                });

                return(new OkResult());
            }
            else
            {
                return(new BadRequestResult());
            }
        }
        public void InitiateBuy(BuyOptions options)
        {
            IPairConfig pairConfig = tradingService.GetPairConfig(options.Pair);

            if (!options.ManualOrder && pairConfig.BuyTrailing != 0)
            {
                if (!trailingBuys.ContainsKey(options.Pair))
                {
                    StopTrailingSell(options.Pair);
                    decimal currentPrice  = tradingService.GetPrice(options.Pair);
                    decimal currentMargin = 0;

                    var trailingInfo = new BuyTrailingInfo
                    {
                        BuyOptions         = options,
                        Trailing           = pairConfig.BuyTrailing,
                        TrailingStopMargin = pairConfig.BuyTrailingStopMargin,
                        TrailingStopAction = pairConfig.BuyTrailingStopAction,
                        InitialPrice       = currentPrice,
                        LastTrailingMargin = currentMargin,
                        BestTrailingMargin = currentMargin
                    };

                    if (trailingBuys.TryAdd(options.Pair, trailingInfo))
                    {
                        if (LoggingEnabled)
                        {
                            ITradingPair tradingPair = tradingService.Account.GetTradingPair(options.Pair);
                            loggingService.Info($"Start trailing buy {tradingPair?.FormattedName ?? options.Pair}. " +
                                                $"Price: {currentPrice:0.00000000}, Margin: {currentMargin:0.00}");
                        }
                    }
                }
            }
            else
            {
                orderingService.PlaceBuyOrder(options);
            }
        }
        public TradingPairResponse TradingPairs()
        {
            ICoreService    coreService    = Application.Resolve <ICoreService>();
            ITradingService tradingService = Application.Resolve <ITradingService>();

            IEnumerable <TradingPairApiModel> tradingPairs = from tradingPair in tradingService.Account.GetTradingPairs()
                                                             let pairConfig = tradingService.GetPairConfig(tradingPair.Pair)
                                                                              select new TradingPairApiModel
            {
                Name            = tradingPair.Pair,
                DCA             = tradingPair.DCALevel,
                TradingViewName = $"{tradingService.Config.Exchange.ToUpperInvariant()}:{tradingPair.Pair}",
                Margin          = tradingPair.CurrentMargin.ToString("0.00"),
                Target          = pairConfig.SellMargin.ToString("0.00"),
                CurrentPrice    = tradingPair.CurrentPrice.ToString("0.00000000"),
                CurrentSpread   = tradingPair.CurrentSpread.ToString("0.00"),
                BoughtPrice     = tradingPair.AveragePrice.ToString("0.00000000"),
                Cost            = tradingPair.Cost.ToString("0.00000000"),
                CurrentCost     = tradingPair.CurrentCost.ToString("0.00000000"),
                Amount          = tradingPair.Amount.ToString("0.########"),
                OrderDates      = tradingPair.OrderDates.Select(d => d.ToOffset(TimeSpan.FromHours(coreService.Config.TimezoneOffset)).ToString("yyyy-MM-dd HH:mm:ss")),
                OrderIds        = tradingPair.OrderIds,
                Age             = tradingPair.CurrentAge.ToString("0.00"),
                CurrentRating   = tradingPair.Metadata.CurrentRating?.ToString("0.000") ?? "N/A",
                BoughtRating    = tradingPair.Metadata.BoughtRating?.ToString("0.000") ?? "N/A",
                SignalRule      = tradingPair.Metadata.SignalRule ?? "N/A",
                SwapPair        = tradingPair.Metadata.SwapPair,
                TradingRules    = pairConfig.Rules,
                IsTrailingSell  = tradingService.GetTrailingSells().Contains(tradingPair.Pair),
                IsTrailingBuy   = tradingService.GetTrailingBuys().Contains(tradingPair.Pair),
                LastBuyMargin   = tradingPair.Metadata.LastBuyMargin?.ToString("0.00") ?? "N/A",
                Config          = pairConfig
            };

            return(new TradingPairResponse
            {
                TradingPairs = tradingPairs.ToList()
            });
        }
Example #5
0
        public IOrderDetails PlaceBuyOrder(BuyOptions options)
        {
            OrderDetails orderDetails = new OrderDetails();

            tradingService.StopTrailingBuy(options.Pair);
            tradingService.StopTrailingSell(options.Pair);

            try
            {
                ITradingPair tradingPair = tradingService.Account.GetTradingPair(options.Pair, includeDust: true);
                options.Price  = tradingService.GetPrice(options.Pair, TradePriceType.Ask, normalize: false);
                options.Amount = options.Amount ?? (options.MaxCost.Value / (options.Pair.EndsWith(Constants.Markets.USDT) ? 1 : options.Price));
                options.Price  = tradingService.Exchange.ClampOrderPrice(options.Pair, options.Price.Value);
                options.Amount = tradingService.Exchange.ClampOrderAmount(options.Pair, options.Amount.Value);

                if (tradingService.CanBuy(options, out string message))
                {
                    IPairConfig pairConfig = tradingService.GetPairConfig(options.Pair);
                    BuyOrder    buyOrder   = new BuyOrder
                    {
                        Type   = pairConfig.BuyType,
                        Date   = DateTimeOffset.Now,
                        Pair   = options.Pair,
                        Price  = options.Price.Value,
                        Amount = options.Amount.Value
                    };

                    lock (tradingService.Account.SyncRoot)
                    {
                        loggingService.Info($"Place buy order for {tradingPair?.FormattedName ?? options.Pair}. " +
                                            $"Price: {buyOrder.Price:0.00000000}, Amount: {buyOrder.Amount:0.########}, Signal Rule: " + (options.Metadata.SignalRule ?? "N/A"));

                        if (!tradingService.Config.VirtualTrading)
                        {
                            orderDetails = tradingService.Exchange.PlaceOrder(buyOrder) as OrderDetails;
                        }
                        else
                        {
                            string pairMarket = tradingService.Exchange.GetPairMarket(options.Pair);
                            orderDetails = new OrderDetails
                            {
                                OrderId      = DateTime.Now.ToFileTimeUtc().ToString(),
                                Side         = OrderSide.Buy,
                                Result       = OrderResult.Filled,
                                Date         = buyOrder.Date,
                                Pair         = buyOrder.Pair,
                                Amount       = buyOrder.Amount,
                                AmountFilled = buyOrder.Amount,
                                Price        = buyOrder.Price,
                                AveragePrice = buyOrder.Price,
                                Fees         = buyOrder.Amount * buyOrder.Price * tradingService.Config.VirtualTradingFees,
                                FeesCurrency = pairMarket
                            };
                        }

                        NormalizeOrder(orderDetails, TradePriceType.Ask);
                        options.Metadata.TradingRules  = pairConfig.Rules.ToList();
                        options.Metadata.LastBuyMargin = options.Metadata.LastBuyMargin ?? tradingPair?.CurrentMargin ?? null;
                        orderDetails.Metadata          = options.Metadata;
                        tradingService.Account.AddBuyOrder(orderDetails);
                        tradingService.Account.Save();
                        tradingService.LogOrder(orderDetails);

                        decimal fees = tradingService.CalculateOrderFees(orderDetails);
                        tradingPair = tradingService.Account.GetTradingPair(orderDetails.Pair, includeDust: true);
                        loggingService.Info("{@Trade}", orderDetails);
                        loggingService.Info($"Buy order result for {orderDetails.OriginalPair ?? tradingPair.FormattedName}: {orderDetails.Result} ({orderDetails.Message}). " +
                                            $"Price: {orderDetails.AveragePrice:0.00000000}, Amount: {orderDetails.Amount:0.########}, " +
                                            $"Filled: {orderDetails.AmountFilled:0.########}, Cost: {orderDetails.Cost:0.00000000}, Fees: {fees:0.00000000}");
                        notificationService.Notify($"Bought {tradingPair.FormattedName}. Amount: {orderDetails.AmountFilled:0.########}, " +
                                                   $"Price: {orderDetails.AveragePrice:0.00000000}, Cost: {(orderDetails.Cost + fees):0.00000000}");
                    }

                    tradingService.ReapplyTradingRules();
                }
                else
                {
                    loggingService.Info(message);
                }
            }
            catch (Exception ex)
            {
                loggingService.Error($"Unable to place buy order for {options.Pair}", ex);
                notificationService.Notify($"Unable to buy {options.Pair}: {ex.Message}");
            }
            return(orderDetails);
        }
        private void ProcessRules()
        {
            if (tradingService.Config.BuyEnabled)
            {
                var allSignals = signalsService.GetAllSignals();
                if (allSignals != null)
                {
                    var enabledRules = signalsService.Rules.Entries.Where(r => r.Enabled);
                    if (enabledRules.Any())
                    {
                        var    groupedSignals = allSignals.Where(s => tradingService.GetPairConfig(s.Pair).BuyEnabled).GroupBy(s => s.Pair).ToDictionary(g => g.Key, g => g.ToDictionary(s => s.Name, s => s));
                        double?globalRating   = signalsService.GetGlobalRating();

                        var excludedPairs = tradingService.Config.ExcludedPairs
                                            .Concat(tradingService.Account.GetTradingPairs().Select(p => p.Pair))
                                            .Concat(tradingService.GetTrailingBuys()).ToList();

                        if (signalsService.RulesConfig.ProcessingMode == RuleProcessingMode.FirstMatch)
                        {
                            excludedPairs.AddRange(trailingSignals.Keys);
                        }

                        foreach (var rule in enabledRules)
                        {
                            foreach (var group in groupedSignals)
                            {
                                string pair = group.Key;
                                Dictionary <string, ISignal> signals    = group.Value;
                                ITradingPair tradingPair                = tradingService.Account.GetTradingPair(pair);
                                IEnumerable <IRuleCondition> conditions = rule.Trailing != null && rule.Trailing.Enabled ? rule.Trailing.StartConditions : rule.Conditions;
                                List <SignalTrailingInfo>    trailingInfoList;

                                if (!excludedPairs.Contains(pair) && (!trailingSignals.TryGetValue(pair, out trailingInfoList) || !trailingInfoList.Any(t => t.Rule == rule)) &&
                                    rulesService.CheckConditions(conditions, signals, globalRating, pair, tradingPair))
                                {
                                    IEnumerable <ISignal> ruleSignals = signals.Where(s => conditions.Any(c => c.Signal == s.Key)).Select(s => s.Value);
                                    if (rule.Trailing != null && rule.Trailing.Enabled)
                                    {
                                        if (trailingInfoList == null)
                                        {
                                            trailingInfoList = new List <SignalTrailingInfo>();
                                            trailingSignals.TryAdd(pair, trailingInfoList);
                                        }

                                        trailingInfoList.Add(new SignalTrailingInfo
                                        {
                                            Rule      = rule,
                                            StartTime = DateTimeOffset.Now
                                        });

                                        string ruleSignalsList = String.Join(", ", ruleSignals.Select(s => s.Name));
                                        if (LoggingEnabled)
                                        {
                                            loggingService.Info($"Start trailing signal for {pair}. Rule: {rule.Name}, Signals: {ruleSignalsList}");
                                        }
                                    }
                                    else
                                    {
                                        InitiateBuy(pair, rule, ruleSignals);
                                    }

                                    if (signalsService.RulesConfig.ProcessingMode == RuleProcessingMode.FirstMatch)
                                    {
                                        excludedPairs.Add(pair);
                                    }
                                }
                            }
                        }
                    }

                    healthCheckService.UpdateHealthCheck(Constants.HealthChecks.SignalRulesProcessed, $"Rules: {enabledRules.Count()}, Trailing signals: {trailingSignals.Count}");
                }
            }
        }
        public MarketPairsResponse MarketPairs(MarketPairsRequest request)
        {
            if (request?.SignalsFilter == null)
            {
                throw new ArgumentNullException(nameof(request));
            }

            ICoreService    coreService    = Application.Resolve <ICoreService>();
            ITradingService tradingService = Application.Resolve <ITradingService>();
            ISignalsService signalsService = Application.Resolve <ISignalsService>();

            IEnumerable <ISignal> allSignals = signalsService.GetAllSignals();

            if (allSignals != null)
            {
                if (request.SignalsFilter.Count > 0)
                {
                    allSignals = allSignals.Where(s => request.SignalsFilter.Contains(s.Name));
                }

                var groupedSignals = allSignals.GroupBy(s => s.Pair).ToDictionary(g => g.Key, g => g.AsEnumerable());

                IEnumerable <MarketPairApiModel> marketPairs = from signalGroup in groupedSignals
                                                               let pair = signalGroup.Key
                                                                          let pairConfig = tradingService.GetPairConfig(pair)
                                                                                           select new MarketPairApiModel
                {
                    Name             = pair,
                    TradingViewName  = $"{tradingService.Config.Exchange.ToUpperInvariant()}:{pair}",
                    VolumeList       = signalGroup.Value.Select(s => new NameValue <long?>(s.Name, s.Volume)),
                    VolumeChangeList = signalGroup.Value.Select(s => new NameValue <double?>(s.Name, s.VolumeChange)),
                    Price            = tradingService.GetPrice(pair).ToString("0.00000000"),
                    PriceChangeList  = signalGroup.Value.Select(s => new NameValue <decimal?>(s.Name, s.PriceChange)),
                    RatingList       = signalGroup.Value.Select(s => new NameValue <double?>(s.Name, s.Rating)),
                    RatingChangeList = signalGroup.Value.Select(s => new NameValue <double?>(s.Name, s.RatingChange)),
                    VolatilityList   = signalGroup.Value.Select(s => new NameValue <double?>(s.Name, s.Volatility)),
                    Spread           = tradingService.Exchange.GetPriceSpread(pair).ToString("0.00"),
                    ArbitrageList    = from market in Enum.GetNames(typeof(ArbitrageMarket)).Where(m => m != tradingService.Config.Market)
                                       let arbitrage = tradingService.Exchange.GetArbitrage(pair, tradingService.Config.Market, new List <ArbitrageMarket> {
                        Enum.Parse <ArbitrageMarket>(market)
                    })
                                                       select new ArbitrageInfo
                    {
                        Name      = $"{arbitrage.Market}-{arbitrage.Type.ToString()[0]}",
                        Arbitrage = arbitrage.IsAssigned ? arbitrage.Percentage.ToString("0.00") : "N/A"
                    },
                    SignalRules    = signalsService.GetTrailingInfo(pair)?.Select(ti => ti.Rule.Name) ?? Array.Empty <string>(),
                    HasTradingPair = tradingService.Account.HasTradingPair(pair),
                    Config         = pairConfig
                };

                return(new MarketPairsResponse
                {
                    MarketPairs = marketPairs.ToList()
                });
            }
            else
            {
                return(null);
            }
        }