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}"); } } }
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() }); }
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); } }