Beispiel #1
0
        public OrderDetails(IOrderDetails item, bool deep = false)
        {
            if (item == null)
            {
                return;
            }

            this.OrderDetailsId = item.OrderDetailsId;
            this.OrderId        = item.OrderId;
            this.ProductId      = item.ProductId;
            this.UnitPrice      = item.UnitPrice;
            this.Amount         = item.Amount;
            this.Discount       = item.Discount;

            if (deep)
            {
                if (item.Order != null)
                {
                    this.Order = new Order(item.Order, deep);
                }
                if (item.Product != null)
                {
                    this.Product = new Product(item.Product, deep);
                }
            }
        }
 public virtual void AddOrder(IOrderDetails order)
 {
     if (order.Side == OrderSide.Buy)
     {
         AddBuyOrder(order);
     }
     else
     {
         AddSellOrder(order);
     }
 }
        public virtual void AddBuyOrder(IOrderDetails order)
        {
            lock (SyncRoot)
            {
                if (order.Side == OrderSide.Buy && (order.Result == OrderResult.Filled || order.Result == OrderResult.FilledPartially))
                {
                    string  feesPair           = order.FeesCurrency + tradingService.Config.Market;
                    decimal feesPairCurrency   = (feesPair == order.Pair) ? order.Fees : 0;
                    decimal feesMarketCurrency = tradingService.CalculateOrderFees(order);
                    decimal balanceOffset      = -feesMarketCurrency;

                    if (!order.IsNormalized || order.Pair.EndsWith(Constants.Markets.USDT))
                    {
                        balanceOffset -= order.Cost;
                        AddBalance(balanceOffset);
                    }
                    else
                    {
                        string normalizedMarket = tradingService.Exchange.GetPairMarket(order.OriginalPair) == Constants.Markets.USDT ?
                                                  tradingService.Config.Market + tradingService.Exchange.GetPairMarket(order.OriginalPair) :
                                                  tradingService.Exchange.GetPairMarket(order.OriginalPair) + tradingService.Config.Market;

                        if (tradingPairs.TryGetValue(normalizedMarket, out TradingPair normalizedMarketPair))
                        {
                            if (normalizedMarketPair.Cost > order.Cost)
                            {
                                decimal amount = order.Cost / tradingService.GetPrice(normalizedMarket, TradePriceType.Bid);
                                normalizedMarketPair.Amount -= amount;
                                if (normalizedMarketPair.Amount <= 0)
                                {
                                    tradingPairs.TryRemove(normalizedMarket, out normalizedMarketPair);
                                    if (normalizedMarketPair.Amount < 0)
                                    {
                                        loggingService.Error($"Normalized pair {normalizedMarket} has negative amount: {normalizedMarketPair.Amount}");
                                    }
                                }
                            }
                            else
                            {
                                tradingPairs.TryRemove(normalizedMarket, out normalizedMarketPair);
                            }
                        }
                        else
                        {
                            loggingService.Error($"Unable to get normalized pair {normalizedMarketPair}");
                        }
                    }

                    AddOrUpdatePair(order, order.Pair, feesMarketCurrency, feesPairCurrency);
                }
            }
        }
        public ITradingPair AddOrUpdatePair(IOrderDetails order, string pair, decimal feesMarketCurrency, decimal feesPairCurrency, decimal?amountOverride = null, decimal?averagePriceOverride = null)
        {
            decimal amount          = amountOverride ?? order.AmountFilled;
            decimal amountAfterFees = amount - feesPairCurrency;
            decimal averagePrice    = averagePriceOverride ?? (order.AveragePrice + (feesMarketCurrency / amount));

            if (tradingPairs.TryGetValue(pair, out TradingPair tradingPair))
            {
                if (!tradingPair.OrderIds.Contains(order.OrderId))
                {
                    tradingPair.OrderIds.Add(order.OrderId);
                    tradingPair.OrderDates.Add(order.Date);
                }
                tradingPair.AveragePrice = (tradingPair.Cost + amountAfterFees * averagePrice) / (tradingPair.Amount + amountAfterFees);
                tradingPair.Amount      += amountAfterFees;
                tradingPair.Fees        += feesMarketCurrency;
                tradingPair.SetMetadata(tradingPair.Metadata.MergeWith(order.Metadata));
            }
            else
            {
                tradingPair = new TradingPair
                {
                    Pair     = pair,
                    OrderIds = new List <string> {
                        order.OrderId
                    },
                    OrderDates = new List <DateTimeOffset> {
                        order.Date
                    },
                    AveragePrice = averagePrice,
                    Amount       = amountAfterFees,
                    Fees         = feesMarketCurrency,
                    Metadata     = order.Metadata
                };
                tradingPairs.TryAdd(pair, tradingPair);
                tradingPair.SetCurrentValues(tradingService.GetPrice(tradingPair.Pair), tradingService.Exchange.GetPriceSpread(tradingPair.Pair));
                tradingPair.Metadata.CurrentRating = tradingPair.Metadata.Signals != null?signalsService.GetRating(tradingPair.Pair, tradingPair.Metadata.Signals) : null;

                tradingPair.Metadata.CurrentGlobalRating = signalsService.GetGlobalRating();
                if (tradingPair.Metadata.LastBuyMargin == null)
                {
                    tradingPair.Metadata.LastBuyMargin = tradingPair.CurrentMargin;
                }
            }
            return(tradingPair);
        }
Beispiel #5
0
        public decimal CalculateOrderFees(IOrderDetails order)
        {
            decimal orderFees = 0;

            if (order.Fees != 0 && order.FeesCurrency != null)
            {
                if (order.FeesCurrency == Config.Market)
                {
                    orderFees = order.Fees;
                }
                else
                {
                    string feesPair = order.FeesCurrency + Config.Market;
                    orderFees = GetPrice(feesPair, TradePriceType.Ask) * order.Fees;
                }
            }
            return(orderFees);
        }
 public AdminController(
     IUserData userData,
     UserManager <User> userManager, IHostingEnvironment hostingEnvironment,
     ISize reposSize, IBrand reposBrand,
     IShipper reposShipper, IProduct reposProduct,
     ICategory reposCategory, ISupplier reposSupplier, IProductSize reposProductSize, IOrderDetails reposOrderDetails,
     IOrder reposOrder, ApplicationDbContext context, Microsoft.AspNetCore.SignalR.IHubContext <NotificationsHub> hubContext)
 {
     this.userData       = userData;
     this.userManager    = userManager;
     _hostingEnvironment = hostingEnvironment;
     _reposSize          = reposSize;
     _reposBrand         = reposBrand;
     _reposShipper       = reposShipper;
     _reposProduct       = reposProduct;
     _reposCategory      = reposCategory;
     _reposSupplier      = reposSupplier;
     _reposProductSize   = reposProductSize;
     _reposOrder         = reposOrder;
     _reposOrderDetails  = reposOrderDetails;
     _context            = context;
     _hubContext         = hubContext;
 }
Beispiel #7
0
        private void ArbitrageReverse(ArbitrageOptions options)
        {
            string       marketPair            = Exchange.GetArbitrageMarketPair(options.Arbitrage.Market);
            ITradingPair existingMarketPair    = Account.GetTradingPair(marketPair);
            IPairConfig  pairConfig            = GetPairConfig(options.Pair);
            bool         useExistingMarketPair = (existingMarketPair != null && existingMarketPair.CurrentCost > pairConfig.BuyMaxCost &&
                                                  existingMarketPair.AveragePrice <= existingMarketPair.CurrentPrice);

            var buyMarketPairOptions = new BuyOptions(marketPair)
            {
                Arbitrage     = true,
                MaxCost       = pairConfig.BuyMaxCost,
                ManualOrder   = options.ManualOrder,
                IgnoreBalance = useExistingMarketPair,
                Metadata      = options.Metadata
            };

            if (CanBuy(buyMarketPairOptions, out string message))
            {
                IOrderDetails buyMarketPairOrderDetails = null;
                if (useExistingMarketPair)
                {
                    buyMarketPairOrderDetails = Account.AddBlankOrder(buyMarketPairOptions.Pair,
                                                                      buyMarketPairOptions.MaxCost.Value / GetPrice(buyMarketPairOptions.Pair, TradePriceType.Ask),
                                                                      includeFees: false);
                    loggingService.Info($"Use existing market pair for arbitrage: {marketPair}. " +
                                        $"Average price: {existingMarketPair.AveragePrice}, Current price: {existingMarketPair.CurrentPrice}");
                }
                else
                {
                    buyMarketPairOrderDetails = orderingService.PlaceBuyOrder(buyMarketPairOptions);
                }

                if (buyMarketPairOrderDetails.Result == OrderResult.Filled)
                {
                    decimal buyArbitragePairMultiplier = pairConfig.ArbitrageBuyMultiplier ?? DEFAULT_ARBITRAGE_BUY_MULTIPLIER;
                    decimal buyMarketPairFees          = CalculateOrderFees(buyMarketPairOrderDetails);
                    string  arbitragePair          = Exchange.ChangeMarket(options.Pair, options.Arbitrage.Market.ToString());
                    decimal buyArbitragePairAmount = options.Arbitrage.Market == ArbitrageMarket.USDT ?
                                                     buyMarketPairOrderDetails.AmountFilled * GetPrice(buyMarketPairOrderDetails.Pair, TradePriceType.Ask, normalize: false) / GetPrice(arbitragePair, TradePriceType.Ask) :
                                                     buyMarketPairOrderDetails.AmountFilled / GetPrice(arbitragePair, TradePriceType.Ask);

                    var buyArbitragePairOptions = new BuyOptions(arbitragePair)
                    {
                        Arbitrage   = true,
                        ManualOrder = options.ManualOrder,
                        Amount      = buyArbitragePairAmount * buyArbitragePairMultiplier,
                        Metadata    = options.Metadata
                    };

                    IOrderDetails buyArbitragePairOrderDetails = orderingService.PlaceBuyOrder(buyArbitragePairOptions);
                    if (buyArbitragePairOrderDetails.Result == OrderResult.Filled)
                    {
                        decimal buyArbitragePairFees = CalculateOrderFees(buyArbitragePairOrderDetails);
                        options.Metadata.FeesNonDeductible = buyMarketPairFees * buyArbitragePairMultiplier;
                        var sellArbitragePairOptions = new SellOptions(buyArbitragePairOrderDetails.Pair)
                        {
                            Arbitrage   = true,
                            Amount      = buyArbitragePairOrderDetails.AmountFilled,
                            ManualOrder = options.ManualOrder,
                            Metadata    = options.Metadata
                        };

                        TradingPair existingArbitragePair = Account.GetTradingPair(buyArbitragePairOrderDetails.Pair) as TradingPair;
                        existingArbitragePair.OverrideCost(buyArbitragePairOrderDetails.Cost + buyArbitragePairFees * 2);
                        IOrderDetails sellArbitragePairOrderDetails = orderingService.PlaceSellOrder(sellArbitragePairOptions);
                        existingArbitragePair.OverrideCost(null);

                        if (sellArbitragePairOrderDetails.Result == OrderResult.Filled)
                        {
                            loggingService.Info($"{pairConfig.ArbitrageType} arbitrage successful: {marketPair} -> {arbitragePair} -> {existingArbitragePair.Pair}");
                        }
                        else
                        {
                            loggingService.Info($"Unable to arbitrage {options.Pair}. Reason: failed to sell arbitrage pair {arbitragePair}");
                            notificationService.Notify($"Unable to arbitrage {options.Pair}: Failed to sell arbitrage pair {arbitragePair}");
                        }
                    }
                    else
                    {
                        loggingService.Info($"Unable to arbitrage {options.Pair}. Reason: failed to buy arbitrage pair {arbitragePair}");
                        notificationService.Notify($"Unable to arbitrage {options.Pair}: Failed to buy arbitrage pair {arbitragePair}");
                    }
                }
                else
                {
                    loggingService.Info($"Unable to arbitrage {options.Pair}. Reason: failed to buy market pair {marketPair}");
                }
            }
            else
            {
                loggingService.Info($"Unable to arbitrage {options.Pair}: {message}");
            }
        }
        public IOrderDetails PlaceBuyOrder(BuyOptions options)
        {
            IOrderDetails orderDetails = null;

            trailingBuys.TryRemove(options.Pair, out BuyTrailingInfo buyTrailingInfo);
            trailingSells.TryRemove(options.Pair, out SellTrailingInfo sellTrailingInfo);

            if (tradingService.CanBuy(options, out string message))
            {
                IPairConfig  pairConfig   = tradingService.GetPairConfig(options.Pair);
                ITradingPair tradingPair  = tradingService.Account.GetTradingPair(options.Pair);
                decimal      currentPrice = tradingService.GetCurrentPrice(options.Pair);
                options.Metadata.TradingRules = pairConfig.Rules.ToList();
                if (options.Metadata.LastBuyMargin == null)
                {
                    options.Metadata.LastBuyMargin = tradingPair?.CurrentMargin ?? 0;
                }
                string signalRule = options.Metadata.SignalRule ?? "N/A";

                BuyOrder buyOrder = new BuyOrder
                {
                    Type   = pairConfig.BuyType,
                    Date   = DateTimeOffset.Now,
                    Pair   = options.Pair,
                    Amount = options.Amount ?? (options.MaxCost.Value / currentPrice),
                    Price  = currentPrice
                };

                if (!tradingService.Config.VirtualTrading)
                {
                    loggingService.Info($"Place buy order for {tradingPair?.FormattedName ?? options.Pair}. Price: {buyOrder.Price:0.00000000}, Amount: {buyOrder.Amount:0.########}, Signal Rule: {signalRule}");

                    try
                    {
                        lock (tradingService.Account.SyncRoot)
                        {
                            orderDetails = tradingService.PlaceOrder(buyOrder);
                            orderDetails.SetMetadata(options.Metadata);
                            tradingService.Account.AddBuyOrder(orderDetails);
                            tradingService.Account.Save();
                            tradingService.LogOrder(orderDetails);

                            tradingPair = tradingService.Account.GetTradingPair(options.Pair);
                            loggingService.Info("{@Trade}", orderDetails);
                            loggingService.Info($"Buy order result for {tradingPair.FormattedName}: {orderDetails.Result} ({orderDetails.Message}). Price: {orderDetails.AveragePrice:0.00000000}, Amount: {orderDetails.Amount:0.########}, Filled: {orderDetails.AmountFilled:0.########}, Cost: {orderDetails.AverageCost:0.00000000}");
                            notificationService.Notify($"Bought {tradingPair.FormattedName}. Amount: {orderDetails.AmountFilled:0.########}, Price: {orderDetails.AveragePrice:0.00000000}, Cost: {orderDetails.AverageCost:0.00000000}");
                        }
                    }
                    catch (Exception ex)
                    {
                        loggingService.Error($"Unable to place buy order for {options.Pair}", ex);
                        notificationService.Notify($"Unable to buy {options.Pair}: {ex.Message}");
                    }
                }
                else
                {
                    loggingService.Info($"Place virtual buy order for {tradingPair?.FormattedName ?? options.Pair}. Price: {buyOrder.Price:0.00000000}, Amount: {buyOrder.Amount:0.########}, Signal Rule: {signalRule}");

                    lock (tradingService.Account.SyncRoot)
                    {
                        decimal roundedAmount = Math.Round(buyOrder.Amount, 4);
                        orderDetails = new OrderDetails
                        {
                            Metadata     = options.Metadata,
                            OrderId      = DateTime.Now.ToFileTimeUtc().ToString(),
                            Side         = OrderSide.Buy,
                            Result       = OrderResult.Filled,
                            Date         = buyOrder.Date,
                            Pair         = buyOrder.Pair,
                            Amount       = roundedAmount,
                            AmountFilled = roundedAmount,
                            Price        = buyOrder.Price,
                            AveragePrice = buyOrder.Price
                        };
                        tradingService.Account.AddBuyOrder(orderDetails);
                        tradingService.Account.Save();
                        tradingService.LogOrder(orderDetails);

                        tradingPair = tradingService.Account.GetTradingPair(options.Pair);
                        loggingService.Info("{@Trade}", orderDetails);
                        loggingService.Info($"Virtual buy order result for {tradingPair.FormattedName}. Price: {orderDetails.AveragePrice:0.00000000}, Amount: {orderDetails.Amount:0.########}, Cost: {orderDetails.AverageCost:0.00000000}");
                        notificationService.Notify($"Bought {tradingPair.FormattedName}. Amount: {orderDetails.AmountFilled:0.########}, Price: {orderDetails.AveragePrice:0.00000000}, Cost: {orderDetails.AverageCost:0.00000000}");
                    }
                }

                tradingService.ReapplyTradingRules();
            }
            else
            {
                loggingService.Info(message);
            }
            return(orderDetails);
        }
Beispiel #9
0
        public void Swap(SwapOptions options)
        {
            lock (SyncRoot)
            {
                if (CanSwap(options, out string message))
                {
                    ITradingPair oldTradingPair = Account.GetTradingPair(options.OldPair);

                    var sellOptions = new SellOptions(options.OldPair)
                    {
                        Swap        = true,
                        SwapPair    = options.NewPair,
                        ManualOrder = options.ManualOrder
                    };

                    if (CanSell(sellOptions, out message))
                    {
                        decimal currentMargin       = oldTradingPair.CurrentMargin;
                        decimal additionalCosts     = oldTradingPair.AverageCostPaid - oldTradingPair.CurrentCost + (oldTradingPair.Metadata.AdditionalCosts ?? 0);
                        int     additionalDCALevels = oldTradingPair.DCALevel;

                        IOrderDetails sellOrderDetails = tradingTimedTask.PlaceSellOrder(sellOptions);
                        if (!Account.HasTradingPair(options.OldPair))
                        {
                            var buyOptions = new BuyOptions(options.NewPair)
                            {
                                Swap        = true,
                                ManualOrder = options.ManualOrder,
                                MaxCost     = sellOrderDetails.AverageCost,
                                Metadata    = options.Metadata
                            };
                            buyOptions.Metadata.LastBuyMargin       = currentMargin;
                            buyOptions.Metadata.SwapPair            = options.OldPair;
                            buyOptions.Metadata.AdditionalDCALevels = additionalDCALevels;
                            buyOptions.Metadata.AdditionalCosts     = additionalCosts;
                            IOrderDetails buyOrderDetails = tradingTimedTask.PlaceBuyOrder(buyOptions);

                            var newTradingPair = Account.GetTradingPair(options.NewPair) as TradingPair;
                            if (newTradingPair != null)
                            {
                                if (sellOrderDetails.Fees != 0 && sellOrderDetails.FeesCurrency != null)
                                {
                                    if (sellOrderDetails.FeesCurrency == Config.Market)
                                    {
                                        newTradingPair.Metadata.AdditionalCosts += sellOrderDetails.Fees;
                                    }
                                    else
                                    {
                                        string feesPair = sellOrderDetails.FeesCurrency + Config.Market;
                                        newTradingPair.Metadata.AdditionalCosts += GetCurrentPrice(feesPair) * sellOrderDetails.Fees;
                                    }
                                }
                                loggingService.Info($"Swap {oldTradingPair.FormattedName} for {newTradingPair.FormattedName}. Old margin: {oldTradingPair.CurrentMargin:0.00}, new margin: {newTradingPair.CurrentMargin:0.00}");
                            }
                            else
                            {
                                loggingService.Info($"Unable to swap {options.OldPair} for {options.NewPair}. Reason: failed to buy {options.NewPair}");
                                notificationService.Notify($"Unable to swap {options.OldPair} for {options.NewPair}: Failed to buy {options.NewPair}");
                            }
                        }
                        else
                        {
                            loggingService.Info($"Unable to swap {options.OldPair} for {options.NewPair}. Reason: failed to sell {options.OldPair}");
                        }
                    }
                    else
                    {
                        loggingService.Info($"Unable to swap {options.OldPair} for {options.NewPair}: {message}");
                    }
                }
                else
                {
                    loggingService.Info(message);
                }
            }
        }
Beispiel #10
0
        public void Swap(SwapOptions options)
        {
            lock (syncRoot)
            {
                PauseTasks();
                try
                {
                    if (CanSwap(options, out string message))
                    {
                        ITradingPair oldTradingPair = Account.GetTradingPair(options.OldPair);
                        var          sellOptions    = new SellOptions(options.OldPair)
                        {
                            Swap        = true,
                            ManualOrder = options.ManualOrder,
                            Metadata    = new OrderMetadata {
                                SwapPair = options.NewPair
                            }
                        };

                        if (CanSell(sellOptions, out message))
                        {
                            decimal currentMargin       = oldTradingPair.CurrentMargin;
                            decimal additionalCosts     = oldTradingPair.Cost - oldTradingPair.CurrentCost + (oldTradingPair.Metadata.AdditionalCosts ?? 0);
                            int     additionalDCALevels = oldTradingPair.DCALevel;

                            IOrderDetails sellOrderDetails = orderingService.PlaceSellOrder(sellOptions);
                            if (!Account.HasTradingPair(options.OldPair))
                            {
                                var buyOptions = new BuyOptions(options.NewPair)
                                {
                                    Swap        = true,
                                    ManualOrder = options.ManualOrder,
                                    MaxCost     = sellOrderDetails.Cost,
                                    Metadata    = options.Metadata
                                };
                                buyOptions.Metadata.LastBuyMargin       = currentMargin;
                                buyOptions.Metadata.SwapPair            = options.OldPair;
                                buyOptions.Metadata.AdditionalDCALevels = additionalDCALevels;
                                buyOptions.Metadata.AdditionalCosts     = additionalCosts;
                                IOrderDetails buyOrderDetails = orderingService.PlaceBuyOrder(buyOptions);

                                var newTradingPair = Account.GetTradingPair(options.NewPair) as TradingPair;
                                if (newTradingPair != null)
                                {
                                    newTradingPair.Metadata.AdditionalCosts += CalculateOrderFees(sellOrderDetails);
                                    loggingService.Info($"Swap {oldTradingPair.FormattedName} for {newTradingPair.FormattedName}. " +
                                                        $"Old margin: {oldTradingPair.CurrentMargin:0.00}, new margin: {newTradingPair.CurrentMargin:0.00}");
                                }
                                else
                                {
                                    loggingService.Info($"Unable to swap {options.OldPair} for {options.NewPair}. Reason: failed to buy {options.NewPair}");
                                    notificationService.Notify($"Unable to swap {options.OldPair} for {options.NewPair}: Failed to buy {options.NewPair}");
                                }
                            }
                            else
                            {
                                loggingService.Info($"Unable to swap {options.OldPair} for {options.NewPair}. Reason: failed to sell {options.OldPair}");
                            }
                        }
                        else
                        {
                            loggingService.Info($"Unable to swap {options.OldPair} for {options.NewPair}: {message}");
                        }
                    }
                    else
                    {
                        loggingService.Info(message);
                    }
                }
                finally
                {
                    ContinueTasks();
                }
            }
        }
Beispiel #11
0
        public virtual ITradeResult AddSellOrder(IOrderDetails order)
        {
            lock (SyncRoot)
            {
                if (tradingPairs.TryGetValue(order.Pair, out TradingPair tradingPair))
                {
                    if (order.Side == OrderSide.Sell && (order.Result == OrderResult.Filled || order.Result == OrderResult.FilledPartially))
                    {
                        decimal balanceDifference = order.AverageCost;

                        if (order.Fees != 0 && order.FeesCurrency != null)
                        {
                            if (order.FeesCurrency == tradingService.Config.Market)
                            {
                                tradingPair.FeesMarketCurrency += order.Fees;
                                balanceDifference -= order.Fees;
                            }
                            else
                            {
                                string feesPair = order.FeesCurrency + tradingService.Config.Market;
                                tradingPair.FeesMarketCurrency += tradingService.GetCurrentPrice(feesPair) * order.Fees;
                            }
                        }
                        balance += balanceDifference;
                        decimal profit = (order.AverageCost - tradingPair.AverageCostPaid - (tradingPair.Metadata.AdditionalCosts ?? 0)) * (order.AmountFilled / tradingPair.TotalAmount);

                        var tradeResult = new TradeResult
                        {
                            IsSuccessful       = true,
                            Metadata           = order.Metadata,
                            Pair               = order.Pair,
                            Amount             = order.AmountFilled,
                            OrderDates         = tradingPair.OrderDates,
                            AveragePricePaid   = tradingPair.AveragePricePaid,
                            FeesPairCurrency   = tradingPair.FeesPairCurrency,
                            FeesMarketCurrency = tradingPair.FeesMarketCurrency,
                            SellDate           = order.Date,
                            SellPrice          = order.AveragePrice,
                            BalanceDifference  = balanceDifference,
                            Profit             = profit
                        };

                        if (tradingPair.TotalAmount > order.AmountFilled)
                        {
                            tradingPair.TotalAmount -= order.AmountFilled;

                            if (!isInitialRefresh && tradingPair.AverageCostPaid <= tradingService.Config.MinCost)
                            {
                                tradingPairs.TryRemove(order.Pair, out tradingPair);
                            }
                        }
                        else
                        {
                            tradingPairs.TryRemove(order.Pair, out tradingPair);
                        }

                        return(tradeResult);
                    }
                    else
                    {
                        return(new TradeResult {
                            IsSuccessful = false
                        });
                    }
                }
                else
                {
                    return(new TradeResult {
                        IsSuccessful = false
                    });
                }
            }
        }
 public PromotionEngine(IOrderDetails orderDetails)
 {
     myOrderDetails = orderDetails;
 }
Beispiel #13
0
 public OrderDetails(IOrderDetails orderDetails)
 {
     OrderId   = orderDetails.GetOrderId();
     OrderList = orderDetails.GetOrderList();
 }
        public virtual ITradeResult AddSellOrder(IOrderDetails order)
        {
            ITradeResult tradeResult = new TradeResult();

            lock (SyncRoot)
            {
                if (tradingPairs.TryGetValue(order.Pair, out TradingPair tradingPair))
                {
                    if (order.Side == OrderSide.Sell && (order.Result == OrderResult.Filled || order.Result == OrderResult.FilledPartially))
                    {
                        string  feesPair           = order.FeesCurrency + tradingService.Config.Market;
                        decimal feesPairCurrency   = (feesPair == order.Pair) ? order.Fees : 0;
                        decimal feesMarketCurrency = tradingService.CalculateOrderFees(order);
                        decimal amountDifference   = order.AmountFilled / tradingPair.Amount;
                        decimal balanceOffset      = -feesMarketCurrency;

                        if (!order.IsNormalized || order.Pair.EndsWith(Constants.Markets.USDT))
                        {
                            balanceOffset += order.Cost;
                            AddBalance(balanceOffset);
                        }
                        else
                        {
                            string normalizedMarket = tradingService.Exchange.GetPairMarket(order.OriginalPair) == Constants.Markets.USDT ?
                                                      tradingService.Config.Market + tradingService.Exchange.GetPairMarket(order.OriginalPair) :
                                                      tradingService.Exchange.GetPairMarket(order.OriginalPair) + tradingService.Config.Market;

                            decimal price  = tradingService.GetPrice(normalizedMarket, TradePriceType.Ask);
                            decimal amount = (order.Cost - feesMarketCurrency) / price;
                            AddOrUpdatePair(order, normalizedMarket, feesMarketCurrency, feesPairCurrency, amount, price);
                        }

                        decimal sellFees = feesMarketCurrency + tradingPair.Fees * amountDifference;
                        tradingPair.Fees += feesMarketCurrency - sellFees;
                        decimal costDifference = order.Cost - tradingPair.GetPartialCost(order.AmountFilled) - (tradingPair.Metadata.AdditionalCosts ?? 0);
                        decimal profit         = costDifference * amountDifference - feesMarketCurrency;

                        if (tradingPair.Amount > order.AmountFilled)
                        {
                            tradingPair.Amount -= order.AmountFilled;
                            if (tradingPair.CurrentCost < tradingService.Config.MinCost)
                            {
                                tradingPair.OrderDates.Clear();
                            }
                        }
                        else
                        {
                            tradingPairs.TryRemove(order.Pair, out tradingPair);
                        }

                        tradeResult = new TradeResult
                        {
                            IsSuccessful  = true,
                            Pair          = order.Pair,
                            Amount        = order.AmountFilled,
                            OrderDates    = tradingPair.OrderDates,
                            AveragePrice  = tradingPair.AveragePrice,
                            Fees          = sellFees,
                            SellDate      = order.Date,
                            SellPrice     = order.AveragePrice,
                            BalanceOffset = balanceOffset,
                            Profit        = profit,
                            Metadata      = order.Metadata,
                        };
                    }
                }
            }
            return(tradeResult);
        }
Beispiel #15
0
 public OrderDetailsController(IOrderDetails _IOrderDetails)
 {
     _OrderDetails = _IOrderDetails;
 }
Beispiel #16
0
 public void LogOrder(IOrderDetails order)
 {
     OrderHistory.Push(order);
 }
Beispiel #17
0
        private void ArbitrageDirect(ArbitrageOptions options)
        {
            string       arbitragePair            = options.Pair;
            ITradingPair existingArbitragePair    = this.Account.GetTradingPair(arbitragePair);
            IPairConfig  pairConfig               = this.GetPairConfig(options.Pair);
            bool         useExistingArbitragePair = (existingArbitragePair != null && existingArbitragePair.CurrentCost > pairConfig.BuyMaxCost &&
                                                     existingArbitragePair.AveragePrice <= existingArbitragePair.CurrentPrice);

            var buyArbitragePairOptions = new BuyOptions(arbitragePair)
            {
                Arbitrage     = true,
                MaxCost       = pairConfig.BuyMaxCost,
                ManualOrder   = options.ManualOrder,
                IgnoreBalance = useExistingArbitragePair,
                Metadata      = options.Metadata
            };

            if (this.CanBuy(buyArbitragePairOptions, out string message))
            {
                IOrderDetails buyArbitragePairOrderDetails = null;
                if (useExistingArbitragePair)
                {
                    buyArbitragePairOrderDetails = this.Account.AddBlankOrder(buyArbitragePairOptions.Pair,
                                                                              buyArbitragePairOptions.MaxCost.Value / this.GetPrice(buyArbitragePairOptions.Pair, TradePriceType.Ask),
                                                                              includeFees: false);
                    loggingService.Info($"Use existing arbitrage pair for arbitrage: {arbitragePair}. " +
                                        $"Average price: {existingArbitragePair.AveragePrice}, Current price: {existingArbitragePair.CurrentPrice}");
                }
                else
                {
                    buyArbitragePairOrderDetails = orderingService.PlaceBuyOrder(buyArbitragePairOptions);
                }

                if (buyArbitragePairOrderDetails.Result == OrderResult.Filled)
                {
                    decimal buyArbitragePairFees     = this.CalculateOrderFees(buyArbitragePairOrderDetails);
                    string  flippedArbitragePair     = this.Exchange.ChangeMarket(arbitragePair, options.Arbitrage.Market.ToString());
                    var     sellArbitragePairOptions = new SellOptions(flippedArbitragePair)
                    {
                        Arbitrage   = true,
                        Amount      = buyArbitragePairOrderDetails.AmountFilled,
                        ManualOrder = options.ManualOrder,
                        Metadata    = options.Metadata.MergeWith(new OrderMetadata
                        {
                            IsTransitional = true
                        })
                    };

                    IOrderDetails sellArbitragePairOrderDetails = orderingService.PlaceSellOrder(sellArbitragePairOptions);
                    if (sellArbitragePairOrderDetails.Result == OrderResult.Filled)
                    {
                        decimal sellArbitragePairMultiplier = pairConfig.ArbitrageSellMultiplier ?? DEFAULT_ARBITRAGE_SELL_MULTIPLIER;
                        decimal sellArbitragePairFees       = this.CalculateOrderFees(sellArbitragePairOrderDetails);
                        options.Metadata.FeesNonDeductible = buyArbitragePairFees * sellArbitragePairMultiplier;
                        decimal sellMarketPairAmount = sellArbitragePairOrderDetails.AmountFilled * this.GetPrice(flippedArbitragePair, TradePriceType.Bid, normalize: false) * sellArbitragePairMultiplier;
                        string  marketPair           = this.Exchange.GetArbitrageMarketPair(options.Arbitrage.Market);

                        var sellMarketPairOptions = new SellOptions(marketPair)
                        {
                            Arbitrage   = true,
                            Amount      = sellMarketPairAmount,
                            ManualOrder = options.ManualOrder,
                            Metadata    = options.Metadata.MergeWith(new OrderMetadata
                            {
                                IsTransitional = false,
                                OriginalPair   = arbitragePair
                            })
                        };

                        existingArbitragePair = this.Account.GetTradingPair(marketPair);
                        existingArbitragePair.OverrideCost((buyArbitragePairOrderDetails.Cost + sellArbitragePairFees * 2) * sellArbitragePairMultiplier);
                        IOrderDetails sellMarketPairOrderDetails = orderingService.PlaceSellOrder(sellMarketPairOptions);
                        existingArbitragePair.OverrideCost(null);

                        if (sellMarketPairOrderDetails.Result == OrderResult.Filled)
                        {
                            loggingService.Info($"{pairConfig.ArbitrageType} arbitrage successful: {arbitragePair} -> {flippedArbitragePair} -> {marketPair}");
                        }
                        else
                        {
                            loggingService.Info($"Unable to arbitrage {options.Pair}. Reason: failed to sell market pair {arbitragePair}");
                            notificationService.Notify($"Unable to arbitrage {options.Pair}: Failed to sell market pair {arbitragePair}");
                        }
                    }
                    else
                    {
                        loggingService.Info($"Unable to arbitrage {options.Pair}. Reason: failed to sell arbitrage pair {flippedArbitragePair}");
                        notificationService.Notify($"Unable to arbitrage {options.Pair}: Failed to sell arbitrage pair {flippedArbitragePair}");
                    }
                }
                else
                {
                    loggingService.Info($"Unable to arbitrage {options.Pair}. Reason: failed to buy arbitrage pair {arbitragePair}");
                }
            }
            else
            {
                loggingService.Info($"Unable to arbitrage {options.Pair}: {message}");
            }
        }
 public OrderDetailsController(IOrderDetails orderDetails)
 {
     this._orderDetails = orderDetails;
 }
Beispiel #19
0
        public virtual void AddBuyOrder(IOrderDetails order)
        {
            lock (SyncRoot)
            {
                if (order.Side == OrderSide.Buy && (order.Result == OrderResult.Filled || order.Result == OrderResult.FilledPartially))
                {
                    decimal balanceDifference  = -order.AverageCost;
                    decimal feesPairCurrency   = 0;
                    decimal feesMarketCurrency = 0;
                    decimal amountAfterFees    = order.AmountFilled;

                    if (order.Fees != 0 && order.FeesCurrency != null)
                    {
                        if (order.FeesCurrency == tradingService.Config.Market)
                        {
                            feesMarketCurrency = order.Fees;
                            balanceDifference -= order.Fees;
                        }
                        else
                        {
                            string feesPair = order.FeesCurrency + tradingService.Config.Market;
                            if (feesPair == order.Pair)
                            {
                                feesPairCurrency = order.Fees;
                                amountAfterFees -= order.Fees;
                            }
                            else
                            {
                                feesMarketCurrency = tradingService.GetCurrentPrice(feesPair) * order.Fees;
                            }
                        }
                    }
                    balance += balanceDifference;

                    if (tradingPairs.TryGetValue(order.Pair, out TradingPair tradingPair))
                    {
                        if (!tradingPair.OrderIds.Contains(order.OrderId))
                        {
                            tradingPair.OrderIds.Add(order.OrderId);
                            tradingPair.OrderDates.Add(order.Date);
                        }
                        tradingPair.AveragePricePaid    = (tradingPair.AverageCostPaid + order.AverageCost) / (tradingPair.TotalAmount + order.AmountFilled);
                        tradingPair.FeesPairCurrency   += feesPairCurrency;
                        tradingPair.FeesMarketCurrency += feesMarketCurrency;
                        tradingPair.TotalAmount        += amountAfterFees;
                        tradingPair.Metadata            = tradingPair.Metadata.MergeWith(order.Metadata);
                    }
                    else
                    {
                        tradingPair = new TradingPair
                        {
                            Pair     = order.Pair,
                            OrderIds = new List <string> {
                                order.OrderId
                            },
                            OrderDates = new List <DateTimeOffset> {
                                order.Date
                            },
                            AveragePricePaid   = order.AveragePrice,
                            FeesPairCurrency   = feesPairCurrency,
                            FeesMarketCurrency = feesMarketCurrency,
                            TotalAmount        = amountAfterFees,
                            Metadata           = order.Metadata
                        };
                        tradingPairs.TryAdd(order.Pair, tradingPair);
                        tradingPair.SetCurrentValues(tradingService.GetCurrentPrice(tradingPair.Pair), tradingService.GetCurrentSpread(tradingPair.Pair));
                        tradingPair.Metadata.CurrentRating = tradingPair.Metadata.Signals != null?signalsService.GetRating(tradingPair.Pair, tradingPair.Metadata.Signals) : null;

                        tradingPair.Metadata.CurrentGlobalRating = signalsService.GetGlobalRating();
                    }
                }
            }
        }
        public OrderDetailsPresenter(IOrderDetails orderDetailsView)
        {
            view = orderDetailsView;

            view.OrderDetailsUpdated += View_OrderDetailsUpdated;
        }
        public IOrderDetails PlaceSellOrder(SellOptions options)
        {
            IOrderDetails orderDetails = null;

            trailingSells.TryRemove(options.Pair, out SellTrailingInfo sellTrailingInfo);
            trailingBuys.TryRemove(options.Pair, out BuyTrailingInfo buyTrailingInfo);

            if (tradingService.CanSell(options, out string message))
            {
                IPairConfig  pairConfig  = tradingService.GetPairConfig(options.Pair);
                ITradingPair tradingPair = tradingService.Account.GetTradingPair(options.Pair);
                tradingPair.SetCurrentValues(tradingService.GetCurrentPrice(options.Pair), tradingService.GetCurrentSpread(options.Pair));

                SellOrder sellOrder = new SellOrder
                {
                    Type   = pairConfig.SellType,
                    Date   = DateTimeOffset.Now,
                    Pair   = options.Pair,
                    Amount = options.Amount ?? tradingPair.TotalAmount,
                    Price  = tradingPair.CurrentPrice
                };

                if (!tradingService.Config.VirtualTrading)
                {
                    loggingService.Info($"Place sell order for {tradingPair.FormattedName}. Price: {sellOrder.Price:0.00000000}, Amount: {sellOrder.Amount:0.########}, Margin: {tradingPair.CurrentMargin:0.00}");

                    try
                    {
                        lock (tradingService.Account.SyncRoot)
                        {
                            orderDetails = tradingService.PlaceOrder(sellOrder);
                            tradingPair.Metadata.SwapPair = options.SwapPair;
                            orderDetails.SetMetadata(tradingPair.Metadata);
                            ITradeResult tradeResult = tradingService.Account.AddSellOrder(orderDetails);
                            tradeResult.SetSwap(options.Swap);
                            tradingService.Account.Save();
                            tradingService.LogOrder(orderDetails);

                            decimal soldMargin = (tradeResult.Profit / (tradeResult.AverageCost + (tradeResult.Metadata.AdditionalCosts ?? 0)) * 100);
                            string  swapPair   = options.SwapPair != null ? $", Swap Pair: {options.SwapPair}" : "";
                            loggingService.Info("{@Trade}", orderDetails);
                            loggingService.Info("{@Trade}", tradeResult);
                            loggingService.Info($"Sell order result for {tradingPair.FormattedName}: {orderDetails.Result} ({orderDetails.Message}). Price: {orderDetails.AveragePrice:0.00000000}, Amount: {orderDetails.Amount:0.########}, Filled: {orderDetails.AmountFilled:0.########}, Margin: {soldMargin:0.00}, Profit: {tradeResult.Profit:0.00000000}");
                            notificationService.Notify($"Sold {tradingPair.FormattedName}. Amount: {orderDetails.AmountFilled:0.########}, Price: {orderDetails.AveragePrice:0.00000000}, Margin: {soldMargin:0.00}, Profit: {tradeResult.Profit:0.00000000}{swapPair}");
                        }
                    }
                    catch (Exception ex)
                    {
                        loggingService.Error($"Unable to place sell order for {options.Pair}", ex);
                        notificationService.Notify($"Unable to sell {options.Pair}: {ex.Message}");
                    }
                }
                else
                {
                    loggingService.Info($"Place virtual sell order for {tradingPair.FormattedName}. Price: {sellOrder.Price:0.00000000}, Amount: {sellOrder.Amount:0.########}");

                    lock (tradingService.Account.SyncRoot)
                    {
                        orderDetails = new OrderDetails
                        {
                            Metadata     = tradingPair.Metadata,
                            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
                        };
                        tradingPair.Metadata.SwapPair = options.SwapPair;
                        ITradeResult tradeResult = tradingService.Account.AddSellOrder(orderDetails);
                        tradeResult.SetSwap(options.Swap);
                        tradingService.Account.Save();
                        tradingService.LogOrder(orderDetails);

                        decimal soldMargin = (tradeResult.Profit / (tradeResult.AverageCost + (tradeResult.Metadata.AdditionalCosts ?? 0)) * 100);
                        string  swapPair   = options.SwapPair != null ? $", Swap Pair: {options.SwapPair}" : "";
                        loggingService.Info("{@Trade}", orderDetails);
                        loggingService.Info("{@Trade}", tradeResult);
                        loggingService.Info($"Virtual sell order result for {tradingPair.FormattedName}. Price: {orderDetails.AveragePrice:0.00000000}, Amount: {orderDetails.Amount:0.########}, Margin: {tradingPair.CurrentMargin:0.00}, Profit: {tradeResult.Profit:0.00000000}");
                        notificationService.Notify($"Sold {tradingPair.FormattedName}. Amount: {orderDetails.AmountFilled:0.########}, Price: {orderDetails.AveragePrice:0.00000000}, Margin: {tradingPair.CurrentMargin:0.00}, Profit: {tradeResult.Profit:0.00000000}{swapPair}");
                    }
                }

                tradingService.ReapplyTradingRules();
            }
            else
            {
                loggingService.Info(message);
            }
            return(orderDetails);
        }