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); }
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; }
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); }
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); } } }
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(); } } }
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; }
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); }
public OrderDetailsController(IOrderDetails _IOrderDetails) { _OrderDetails = _IOrderDetails; }
public void LogOrder(IOrderDetails order) { OrderHistory.Push(order); }
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; }
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); }