public IOrderDetails PlaceSellOrder(SellOptions options) { OrderDetails orderDetails = new OrderDetails(); tradingService.StopTrailingSell(options.Pair); tradingService.StopTrailingBuy(options.Pair); try { string normalizedPair = tradingService.NormalizePair(options.Pair); ITradingPair tradingPair = tradingService.Account.GetTradingPair(normalizedPair, includeDust: true); options.Price = tradingService.GetPrice(options.Pair, TradePriceType.Bid); options.Amount = options.Amount ?? tradingPair?.Amount ?? 0; options.Price = options.Price != 1 ? tradingService.Exchange.ClampOrderPrice(options.Pair, options.Price.Value) : 1; // 1 = USDT price options.Amount = tradingService.Exchange.ClampOrderAmount(options.Pair, options.Amount.Value); if (tradingService.CanSell(options, out string message)) { IPairConfig pairConfig = tradingService.GetPairConfig(normalizedPair); SellOrder sellOrder = new SellOrder { Type = pairConfig.SellType, Date = DateTimeOffset.Now, Pair = options.Pair, Price = options.Price.Value, Amount = options.Amount.Value }; lock (tradingService.Account.SyncRoot) { tradingPair.SetCurrentValues(tradingService.GetPrice(normalizedPair), tradingService.Exchange.GetPriceSpread(normalizedPair)); string sellPairName = normalizedPair != options.Pair ? options.Pair : tradingPair.FormattedName; loggingService.Info($"Place sell order for {sellPairName}. " + $"Price: {sellOrder.Price:0.00000000}, Amount: {sellOrder.Amount:0.########}, Margin: {tradingPair.CurrentMargin:0.00}"); if (!tradingService.Config.VirtualTrading) { orderDetails = tradingService.Exchange.PlaceOrder(sellOrder) as OrderDetails; } else { string pairMarket = tradingService.Exchange.GetPairMarket(options.Pair); orderDetails = new OrderDetails { OrderId = DateTime.Now.ToFileTimeUtc().ToString(), Side = OrderSide.Sell, Result = OrderResult.Filled, Date = sellOrder.Date, Pair = sellOrder.Pair, Amount = sellOrder.Amount, AmountFilled = sellOrder.Amount, Price = sellOrder.Price, AveragePrice = sellOrder.Price, Fees = sellOrder.Amount * sellOrder.Price * tradingService.Config.VirtualTradingFees, FeesCurrency = pairMarket }; } NormalizeOrder(orderDetails, TradePriceType.Bid); tradingPair.SetMetadata(tradingPair.Metadata.MergeWith(options.Metadata)); orderDetails.Metadata = tradingPair.Metadata; var tradeResult = tradingService.Account.AddSellOrder(orderDetails) as TradeResult; tradeResult.IsSwap = options.Swap; tradeResult.IsArbitrage = options.Arbitrage; tradingService.Account.Save(); tradingService.LogOrder(orderDetails); decimal fees = tradingService.CalculateOrderFees(orderDetails); decimal margin = (tradeResult.Profit / (tradeResult.Cost + (tradeResult.Metadata.AdditionalCosts ?? 0)) * 100); string swapPair = options.Metadata.SwapPair != null ? $", Swap Pair: {options.Metadata.SwapPair}" : ""; string arbitrage = options.Metadata.Arbitrage != null ? $", Arbitrage: {options.Metadata.Arbitrage} ({options.Metadata.ArbitragePercentage:0.00})" : ""; loggingService.Info("{@Trade}", orderDetails); loggingService.Info("{@Trade}", tradeResult); loggingService.Info($"Sell 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}, Margin: {margin:0.00}, Profit: {tradeResult.Profit:0.00000000}{swapPair}{arbitrage}"); notificationService.Notify($"Sold {tradingPair.FormattedName}. Amount: {orderDetails.AmountFilled:0.########}, " + $"Price: {orderDetails.AveragePrice:0.00000000}, Margin: {margin:0.00}, Profit: {tradeResult.Profit:0.00000000}{swapPair}{arbitrage}"); } tradingService.ReapplyTradingRules(); } else { loggingService.Info(message); } } catch (Exception ex) { loggingService.Error($"Unable to place sell order for {options.Pair}", ex); notificationService.Notify($"Unable to sell {options.Pair}: {ex.Message}"); } return(orderDetails); }