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);
        }
示例#2
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}");
            }
        }
示例#3
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();
                    }
                }
            }
        }