Пример #1
0
        /// <summary>
        /// Private helper method that validates inputs given for a transfer and builds/intiates a new transfer object.
        /// </summary>
        /// <param name="originExchange"></param>
        /// <param name="destinationExchange"></param>
        /// <param name="amount"></param>
        /// <param name="arbitrationTradeId"></param>
        /// <returns></returns>
        private static Transfer ValidateInputsAndBuildTransferObject(BaseExchange originExchange, BaseExchange destinationExchange, decimal amount)
        {
            DateTime currentDateTime = DateTime.Now;

            if (originExchange == null)
            {
                throw new ArgumentException("OriginExchange cannot be null.");
            }

            if (destinationExchange == null)
            {
                throw new ArgumentException("DestinationExchange cannot be null.");
            }

            if (amount <= 0)
            {
                throw new ArgumentException("Amount must be greater than 0.");
            }

            //Make sure there is enough bitcoins in the OriginExchange to execute the transfer
            if (originExchange.AvailableBtc < amount)
            {
                throw new NotEnoughBtcException("The exchange " + originExchange.Name + " does not have enough bitcoins (" + originExchange.AvailableBtc + ") to execute a transfer of " + amount + ".");
            }

            Transfer returnTransfer = new Transfer(originExchange, destinationExchange, amount);

            //Set up times for this transfer
            returnTransfer.InitiateDateTime = currentDateTime;
            returnTransfer.CompleteDateTime = currentDateTime.AddMinutes(TRANSFER_TIME_MINUTES);

            return(returnTransfer);
        }
Пример #2
0
        public static List <Transfer> DetectAndExecuteRollupTransfers_Simulate(int rollupNumber, int arbitrationRunId, List <BaseExchange> exchanges, ILog log = null)
        {
            DataTable       transfersToExecute = CalculateRollupTransfers(rollupNumber, arbitrationRunId);
            List <Transfer> transfers          = null;

            //If there were transfers found that need to be executed.
            if (transfersToExecute != null)
            {
                foreach (DataRow transferRow in transfersToExecute.Rows)
                {
                    BaseExchange originExchange      = GetExchangeFromListByName((string)transferRow["BUY_EXCHANGE"], exchanges);
                    BaseExchange destinationExchange = GetExchangeFromListByName((string)transferRow["SELL_EXCHANGE"], exchanges);
                    decimal      amount = TypeConversion.ParseStringToDecimalStrict(transferRow["AMOUNT"].ToString());

                    try
                    {
                        //This might throw a NotEnoughBtcException
                        Transfer transfer = ValidateInputsAndBuildTransferObject(originExchange, destinationExchange, amount);

                        //Setting transfer list here, because at least one transfer was found and properly built
                        if (transfers == null)
                        {
                            transfers = new List <Transfer>();
                        }

                        //Simulate the transfer by updatjing the appropriate exchange amounts, making sure to take into account transfer fees
                        originExchange.AvailableBtc       = originExchange.AvailableBtc - amount;
                        destinationExchange.BTCInTransfer = destinationExchange.BTCInTransfer + amount - originExchange.BtcTransferFee;

                        //Save the transfer object to the DB before returning
                        transfer.PersistToDb();

                        //If a log was given, create a log message
                        if (log != null)
                        {
                            log.Info(String.Format(LOG_MESSAGE, transfer.Id.Value, transfer.Amount, transfer.OriginExchange.Name, transfer.DestinationExchange.Name));
                        }

                        //Update all the necessary arbitration trades with the transfer id
                        UpdateArbitrationTradesWithTransferId(arbitrationRunId, transfer.OriginExchange.Name, transfer.DestinationExchange.Name, transfer.Id.Value);

                        transfers.Add(transfer);
                    }
                    catch (NotEnoughBtcException e)
                    {
                        //This may or may not be a valid error. If there is not enough btc for the transfer, but there is btc in transfer, then it's ok, the transfers
                        //just need to get caught up. In this case, do nothing; just need to wait until the transfer complete and try again. But, if there is still not
                        //enough btc while accounting for the amount in transfer, this is a legitmate error, so rethrow.
                        if (!(Decimal.Add(originExchange.AvailableBtc, originExchange.BTCInTransfer) >= amount))
                        {
                            throw;
                        }
                    }
                }
            }

            return(transfers);
        }
Пример #3
0
        public Transfer(BaseExchange originExchange, BaseExchange destinationExchange, decimal amount)
        {
            _originExchange      = originExchange;
            _destinationExchange = destinationExchange;
            _amount = amount;

            //Initialize completed to false
            _completed = false;
        }
Пример #4
0
 public ArbitrationOpportunity(BaseExchange buyExchange, BaseExchange sellExchange)
 {
     _buyExchange      = buyExchange;
     _sellExchange     = sellExchange;
     _arbitrationRunId = ArbitrationRunId;
     _buyAmount        = 0.0m;
     _buyPrice         = 0.0m;
     _totalBuyCost     = 0.0m;
     _sellPrice        = 0.0m;
     _totalSellCost    = 0.0m;
     _profit           = 0.0m;
 }
Пример #5
0
 /// <summary>
 /// Legacy construtor that sets both buy and sell amount to the given amount. Leaving this constructor in here mosty for legacy purposes.
 /// </summary>
 /// <param name="amount">Sets both buy amount and sell amount.</param>
 public ArbitrationOpportunity(BaseExchange buyExchange, BaseExchange sellExchange, decimal amount, decimal buyPrice, decimal totalBuyCost, decimal sellPrice, decimal totalSellCost, decimal profit, int arbitrationRunId)
 {
     _buyExchange      = buyExchange;
     _sellExchange     = sellExchange;
     _arbitrationRunId = arbitrationRunId;
     _buyAmount        = amount;
     _buyPrice         = buyPrice;
     _totalBuyCost     = totalBuyCost;
     _sellPrice        = sellPrice;
     _totalSellCost    = totalSellCost;
     _profit           = profit;
 }
Пример #6
0
        /// <summary>
        /// Calculates profit with the exchange fees taken into account. If arbitration is still possible, ReturnOpportunity and MaxBTC are updated as needed.
        /// Returns a bool indicating if profit is possible between the two exchanges.
        /// </summary>
        /// <param name="tradeAmount">That amount of BTC to be traded between the two exchanges.</param>
        /// <param name="buyExchange">The exchange to buy from; where the ask order is being fulfilled.</param>
        /// <param name="sellExchange">The exchange to sell at; where the bid order is being fulfilled.</param>
        /// <param name="returnOpportunity">ArbitrationOpportunity that is being used to keep track of the total arbitration between the buy and sell exchanges. Note,
        ///     this variable is passed in by reference, so the object that is passed to this method is directly updated.</param>
        /// <param name="ask">Ask order that is being used from the buy exchange.</param>
        /// <param name="bid">Bid order that is being used from the sell exchange.</param>
        /// <param name="availableBtc">The amount of BTC available for an aribtration trade. Note, this variable is passed in to by reference,
        ///     so the object that is passed to this method is directly updated.</param>
        /// <param name="availableFiat">The amount of fiat available for an arbitration trade. Note, this variable is passed in to by reference,
        ///     so the object that is passed to this method is directly updated</param>
        /// <returns>Returns a boolean. True if the profit can be made from the given ask and bid. False if no arbitration can occur.</returns>
        private static bool CalculateArbitration(decimal tradeAmount, BaseExchange buyExchange, BaseExchange sellExchange, ref ArbitrationOpportunity returnOpportunity, Order ask, Order bid, ref decimal availableBtc, ref decimal availableFiat)
        {
            decimal sellAmount;
            decimal buyCost;

            if (buyExchange.CurrencyTypeBuyFeeIsAppliedTo == CurrencyType.Bitcoin)
            {
                //The buy exchange applies their fee to btc, lower the sell amount to compensate.
                sellAmount = Decimal.Multiply(tradeAmount, decimal.Subtract(1m, buyExchange.TradeFeeAsDecimal));

                buyCost = Decimal.Multiply(tradeAmount, ask.Price);
            }
            else
            {
                //Buy fee is applied to fiat, so no need to decrease sell amount.
                sellAmount = tradeAmount;

                buyCost = Decimal.Multiply(Decimal.Add(1.0m, buyExchange.TradeFeeAsDecimal), Decimal.Multiply(tradeAmount, ask.Price));
            }

            decimal sellCost = Decimal.Multiply(Decimal.Subtract(1.0m, sellExchange.TradeFeeAsDecimal), Decimal.Multiply(sellAmount, bid.Price));
            decimal profit   = Decimal.Subtract(sellCost, buyCost);

            //Just to weed out arbitration opportunities whose profit is so low that they aren't practical. Note, this isn't the Minimum profit requirement,
            //to return an arbitration opportunity, this limit just keeps the algorithm from adding to an arbitration opportunity trade amounts that don't add
            //at least 0.01 profit to the overall opportunity.
            if (profit > 0.001m)
            {
                if (returnOpportunity == null)
                {
                    returnOpportunity = new ArbitrationOpportunity(buyExchange, sellExchange);
                }

                //Increase the amount of the arbitration opportunity; add the new buy and sell orders to this opportunity
                returnOpportunity.BuyAmount  = Decimal.Add(returnOpportunity.BuyAmount, tradeAmount);
                returnOpportunity.SellAmount = Decimal.Add(returnOpportunity.SellAmount, sellAmount);

                returnOpportunity.AddBuyOrder(new Order(tradeAmount, ask.Price));
                returnOpportunity.AddSellOrder(new Order(sellAmount, bid.Price));

                //Decrement MaxBTC and MaxFiat; since some was used on this iteration, less will be available for use on subsequent iterations
                availableBtc  = Decimal.Subtract(availableBtc, tradeAmount);
                availableFiat = Decimal.Subtract(availableFiat, buyCost);

                return(true);
            }

            return(false);
        }
Пример #7
0
        public static ArbitrationOpportunity CreateArbitrationOpportunity(BaseExchange BuyExchange, BaseExchange SellExchange, int ArbitrationRunId, decimal amount = 0.0m)
        {
            ArbitrationOpportunity returnOpportunity = new ArbitrationOpportunity(BuyExchange, SellExchange);

            returnOpportunity.ArbitrationRunId = ArbitrationRunId;
            returnOpportunity.BuyAmount        = amount;
            returnOpportunity.PersistToDb();

            //If there was a problem saving the opportunity to the db.
            if (returnOpportunity.Id == null)
            {
                throw new Exception();
            }

            return(returnOpportunity);
        }
Пример #8
0
        /// <summary>
        /// Transfers coins between the given exchanges. Coin amounts are not updated.
        /// This method  throws an ArgumentException is Amount is greater than the AvailableBtc of the given origin exchange,
        /// the given exchanges are null, or Amount is less than or equal to 0.
        /// </summary>
        /// <param name="originExchange">The exchange coins will be moved out of.</param>
        /// <param name="destinationExchange">The exchange coins will be sent to.</param>
        /// <param name="amount">The number of bitcoins to be exchanged between the two giving exchanges.</param>
        /// <returns>A  transfer object representing the transfer that took place. This method saves the transfer
        ///     object to the DB before it is returned.</returns>
        public static Transfer OnTimeTransfer_Live(BaseExchange originExchange, BaseExchange destinationExchange, decimal amount, ILog log = null)
        {
            Transfer returnTransfer = ValidateInputsAndBuildTransferObject(originExchange, destinationExchange, amount);

            originExchange.Transfer(amount, destinationExchange.BitcoinDepositAddress);

            //Save the transfer object to the DB before returning
            returnTransfer.PersistToDb();

            //If a log was given, create a log message
            if (log != null)
            {
                log.Info(String.Format(LOG_MESSAGE, returnTransfer.Id.Value, returnTransfer.Amount, returnTransfer.OriginExchange.Name, returnTransfer.DestinationExchange.Name));
            }

            return(returnTransfer);
        }
Пример #9
0
        /// <summary>
        /// Simulates a transfer of btc between the two exchanges. The coin amounts of the two exchanges are updated appropriately.
        /// This method  throws an ArgumentException is Amount is greater than the AvailableBtc of the given origin exchange,
        /// the given exchanges are null, or Amount is less than or equal to 0.
        /// </summary>
        /// <param name="originExchange">The exchange coins will be moved out of.</param>
        /// <param name="destinationExchange">The exchange coins will be sent to.</param>
        /// <param name="amount">The number of bitcoins to be exchanged between the two giving exchanges.</param>
        /// <returns>A  transfer object representing the transfer that took place. This method saves the transfer
        ///     object to the DB before it is returned.</returns>
        public static Transfer OnTimeTransfer_Simulate(BaseExchange originExchange, BaseExchange destinationExchange, decimal amount, ILog log = null)
        {
            Transfer returnTransfer = ValidateInputsAndBuildTransferObject(originExchange, destinationExchange, amount);

            //Simulate the transfer by updatjing the appropriate exchange amounts, making sure to take into account transfer fees
            originExchange.AvailableBtc       = originExchange.AvailableBtc - amount;
            destinationExchange.BTCInTransfer = destinationExchange.BTCInTransfer + amount - originExchange.BtcTransferFee;

            //Save the transfer object to the DB before returning
            returnTransfer.PersistToDb();

            //If a log was given, create a log message
            if (log != null)
            {
                log.Info(String.Format(LOG_MESSAGE, returnTransfer.Id.Value, returnTransfer.Amount, returnTransfer.OriginExchange.Name, returnTransfer.DestinationExchange.Name));
            }

            return(returnTransfer);
        }
Пример #10
0
        private static async Task SendTradeOverviewMessage(INotificationManager notificationManager, IDataStore dataStore)
        {
            var trades = await dataStore.GetActiveTradesAsync();

            if (trades.Count > 0)
            {
                var exchangeOptions = AppSettings.Get <ExchangeOptions>();
                var exchange        = new BaseExchange(exchangeOptions);
                var stringResult    = new StringBuilder();

                foreach (var item in trades)
                {
                    var ticker = await exchange.GetTicker(item.Market);

                    var currentProfit = ((ticker.Bid - item.OpenRate) / item.OpenRate) * 100;
                    stringResult.AppendLine($"#{item.Market}: *{currentProfit:0.00}%* opened {item.OpenDate.Humanize()} at {item.OpenRate:0.00000000} BTC");
                }

                await notificationManager.SendNotification(stringResult.ToString());
            }
        }
Пример #11
0
        private void SendExchangePrices(BaseExchange ex, OrderBookEventArgs args, Instrument instrument)
        {
            if (!ex.ValidOrderPrices(args, instrument))
            {
                return;
            }

            var priceArgs = new ExchangePricesEventArgs
            {
                CreatedAt      = DateTime.UtcNow,
                Timestamp      = args.Timestamp,
                Instrument1    = args.Instrument1,
                Instrument2    = args.Instrument2,
                OrderId        = args.OrderId,
                Exchange       = ex.GetExchangeName(),
                IsOrderDeleted = args.IsOrderDeleted
            };

            Task.Run(() => _dbRepo.SaveOrderBook(priceArgs, args.OrderBook));

            instrument.InitExchangePrice(ex, priceArgs);
            _dbGateway.SendPrices(priceArgs);
        }
Пример #12
0
        private static async Task SendClosedTradesProfitText(INotificationManager notificationManager, IDataStore dataStore)
        {
            var trades = await dataStore.GetAllTradesNotCancelledAsync();

            trades = trades.Where(x => x.CloseDate.HasValue == true).OrderBy(x => x.CloseDate).ToList();

            if (trades.Count > 0)
            {
                var exchangeOptions = AppSettings.Get <ExchangeOptions>();
                var exchange        = new BaseExchange(exchangeOptions);
                var stringResult    = new StringBuilder();
                stringResult.AppendLine("*** Closed Trades Profit ***");

                //foreach (var item in trades)
                //{
                //    stringResult.AppendLine($"#{item.Market}: *{item.CloseProfitPercentage:0.00}%* opened {item.OpenDate.Humanize()} at {item.OpenRate:0.00000000} BTC closed {item.CloseDate.Humanize()} at {item.CloseRate:0.00000000} BTC");
                //}

                stringResult.AppendLine($"*Current profit is {trades.Sum(x => x.CloseProfit):0.00000000} BTC ({(trades.Sum(x => x.CloseProfitPercentage)):0.00}%)*");

                await notificationManager.SendNotification(stringResult.ToString());
            }
        }
Пример #13
0
        private static async Task SendOpenedTradesProfitText(INotificationManager notificationManager, IDataStore dataStore)
        {
            var trades = await dataStore.GetAllTradesNotCancelledAsync();

            trades = trades.Where(x => x.CloseDate.HasValue == false).ToList();

            if (trades.Count > 0)
            {
                var exchangeOptions = AppSettings.Get <ExchangeOptions>();
                var exchange        = new BaseExchange(exchangeOptions);
                var stringResult    = new StringBuilder();
                stringResult.AppendLine("*** Opened Trades Profit ***");

                foreach (var item in trades)
                {
                    var ticker = await exchange.GetTicker(item.Market);

                    var currentProfit = ((ticker.Bid - item.OpenRate) / item.OpenRate) * 100;
                    stringResult.AppendLine($"#{item.Market}: *{currentProfit:0.00}%* opened {item.OpenDate.Humanize()} at {item.OpenRate:0.00000000} BTC");
                }

                await notificationManager.SendNotification(stringResult.ToString());
            }
        }
Пример #14
0
        /// <summary>
        /// Determines if the arbitration is possible with the given buy and sell exchanges. The order book for both exchanges must be ordered (that is,
        /// asks with ascending order price and bids with descending order price) for this method to work properly.
        /// </summary>
        /// <param name="buyExchange">The exchange to buy from.</param>
        /// <param name="sellExchange">The exchange to sell at.</param>
        /// <param name="availableBtc">The amount of BTC available for an aribtration trade.</param>
        /// <param name="availableFiat">The amount of fiat available for an arbitration trade.</param>
        /// <param name="minimumProfit">The minimum profit required for an arbitration opportunity to be considered valid. That is, the minimum profit required
        ///     for an arbitration opportunity to be returned by this method.</param>
        /// <returns>An ArbirationOpportunity object is arbitration between the two given exchanges can occur. Otherwise, returns null.</returns>
        public ArbitrationOpportunity CalculateArbitration(BaseExchange buyExchange, BaseExchange sellExchange, decimal availableBtc, decimal availableFiat, decimal minimumProfit, bool accountForBtcTransferFee)
        {
            ArbitrationOpportunity returnOpportunity = null;

            //These two lists keep track of the asks and bids lists as they are used
            List <Order> runningAskList;
            List <Order> runningBidList;

            //Only need to clone the Asks of the buy exchange (since we aren't selling there don't need the bids), and only need to clone the Bids of the sell
            //exchange (since we aren't buying there don't need the asks)
            if (buyExchange.OrderBook != null && buyExchange.OrderBook.Asks != null && sellExchange.OrderBook != null && sellExchange.OrderBook.Bids != null)
            {
                runningAskList = buyExchange.OrderBook.Asks.Clone();
                runningBidList = sellExchange.OrderBook.Bids.Clone();
            }
            else
            {
                //Defensive code: at this point, both orderbooks and their order lists shouldn't be null. But just in case, return null.
                return(null);
            }

            //Continue to look for aribtration while:
            //  - The next ask has a higher price than the next bid (meaning there is a potential for arbitration)
            //  - There is btc left to use up
            //  - There is fiat left to use. Note, this is limited at 1.00 to prevent any fringe situation where this method finds arbitration with a very small
            //    amount of btc. If there is less than 1.00, just don't bother looking for arbitration as that isn't practical. This would probably be assuaged
            //    by the min profit limit anyways, but just to be safe.
            while (runningBidList.Count > 0 && runningAskList.Count > 0 && runningBidList[0].Price > runningAskList[0].Price && availableBtc > 0 && availableFiat > 1.00m)
            {
                decimal buyAmount;
                Order   bid = runningBidList[0];
                Order   ask = runningAskList[0];

                bool calculateProfitResult;

                //Part of the ask (buy) order has been fulfilled
                if ((buyExchange.CurrencyTypeBuyFeeIsAppliedTo == CurrencyType.Fiat && ask.Amount > bid.Amount) || (buyExchange.CurrencyTypeBuyFeeIsAppliedTo == CurrencyType.Bitcoin && ask.Amount > Decimal.Multiply(bid.Amount, Decimal.Add(1, buyExchange.TradeFeeAsDecimal))))
                {
                    buyAmount             = DetermineBuyTradeAmount(availableBtc, ask, bid, availableFiat, buyExchange.TradeFeeAsDecimal, buyExchange.CurrencyTypeBuyFeeIsAppliedTo, OrderType.Bid);
                    calculateProfitResult = CalculateArbitration(buyAmount, buyExchange, sellExchange, ref returnOpportunity, ask, bid, ref availableBtc, ref availableFiat);

                    if (calculateProfitResult)
                    {
                        ask.Amount = decimal.Subtract(ask.Amount, buyAmount);

                        //If the entire bid order was filled, remove it
                        //*NOTE* Greater than or equal too is needed, because in the case of the buy fee being applied to btc, the buy amount may actually be greater than amount of the sell order
                        if (buyAmount >= bid.Amount)
                        {
                            runningBidList.RemoveAt(0);
                        }
                    }
                }

                //All of the ask (buy) order has been filled
                else if ((buyExchange.CurrencyTypeBuyFeeIsAppliedTo == CurrencyType.Fiat && ask.Amount < bid.Amount) || (buyExchange.CurrencyTypeBuyFeeIsAppliedTo == CurrencyType.Bitcoin && ask.Amount < Decimal.Multiply(bid.Amount, Decimal.Add(1, buyExchange.TradeFeeAsDecimal))))
                {
                    buyAmount             = DetermineBuyTradeAmount(availableBtc, ask, bid, availableFiat, buyExchange.TradeFeeAsDecimal, buyExchange.CurrencyTypeBuyFeeIsAppliedTo, OrderType.Ask);
                    calculateProfitResult = CalculateArbitration(buyAmount, buyExchange, sellExchange, ref returnOpportunity, ask, bid, ref availableBtc, ref availableFiat);

                    if (calculateProfitResult)
                    {
                        bid.Amount = Decimal.Subtract(bid.Amount, buyAmount);

                        //If the entire ask order was filled, remove it
                        if (buyAmount >= ask.Amount)
                        {
                            runningAskList.RemoveAt(0);
                        }
                    }
                }

                //The ask and buy orders are the same amount so the both get filled
                //WARNING!!!! This block technically isn't right, it very slightly error when buy fee is applied to btc. But, the error is very small, and this is a very, very unlikely case so
                //I'm not doing to do anything about it. To see the error, take test case 18 and add another tier of arbitration opportunity.
                else
                {
                    buyAmount             = DetermineBuyTradeAmount(availableBtc, ask, bid, availableFiat, buyExchange.TradeFeeAsDecimal, buyExchange.CurrencyTypeBuyFeeIsAppliedTo, OrderType.Ask);
                    calculateProfitResult = CalculateArbitration(buyAmount, buyExchange, sellExchange, ref returnOpportunity, ask, bid, ref availableBtc, ref availableFiat);

                    if (calculateProfitResult)
                    {
                        //If both orders were wholly filled, delete them. Note, since this else block is for asks and bids whose amount are the same,
                        //tradeAmount only needs to be checked against one of the orders
                        if (buyAmount >= ask.Amount)
                        {
                            runningBidList.RemoveAt(0);
                            runningAskList.RemoveAt(0);
                        }
                    }
                }

                //If no profit could be found, exit the while loop
                if (!calculateProfitResult)
                {
                    break;
                }
            }

            //An oppportunity was found, now see if it meets the minimum profit requirements
            if (returnOpportunity != null)
            {
                if (returnOpportunity.BuyExchangeOrderBook == null || returnOpportunity.SellExchangeOrderBook == null)
                {
                    //If arbitration can occur, add the order books to returnOpportunity for recordkeeping and trouble shooting
                    returnOpportunity.BuyExchangeOrderBook  = buyExchange.OrderBook;
                    returnOpportunity.SellExchangeOrderBook = sellExchange.OrderBook;
                }

                returnOpportunity.CalculateArbitrationOpportunityCosts();

                //Todo: just increase the buy amount by the transfer fee, don't use this method
                //Arbitration calculation finished, now take into account the transfer trade fee if specified:
                if (accountForBtcTransferFee)
                {
                    //Calculate the average btc cost in fiat
                    decimal averageCost = (returnOpportunity.BuyPrice + returnOpportunity.SellPrice) / 2;

                    //Using the average buy/sell cost, determine if the opportunity is stil profitable after losing that amount of btc in dollars.
                    returnOpportunity.Profit -= returnOpportunity.BuyExchange.BtcTransferFee * averageCost;
                }

                //Now that arbitration has been fully calculated between the two exchange, and the opportunity has the required minimum profit, see if the buy and sell orders are valid:
                if (returnOpportunity.Profit >= minimumProfit && returnOpportunity.BuyExchange.IsOrderCostValidForExchange(returnOpportunity.TotalBuyCost, returnOpportunity.BuyAmount) && returnOpportunity.SellExchange.IsOrderCostValidForExchange(returnOpportunity.TotalSellCost, returnOpportunity.SellAmount))
                {
                    return(returnOpportunity);
                }
            }

            return(null);
        }
Пример #15
0
 /// <summary>
 /// 基础演示
 /// </summary>
 /// <param name="msg"></param>
 /// <returns></returns>
 public Task <JsonResult> SendMessage([FromBody] SendMessageDto dto)
 {
     baseExchange = new BaseExchange();
     baseExchange.SendMQ(dto);
     return(Task.FromResult(Json(true)));
 }
Пример #16
0
 public override void InitExchangePrice(BaseExchange ex, ExchangePricesEventArgs args)
 {
     args.XrpPrice  = new double[] { GetBidOrder(ex).Price, GetAskOrder(ex).Price };
     args.XrpAmount = new double[2][] { GetBidOrder(ex).Amount, GetAskOrder(ex).Amount };
 }
Пример #17
0
 public abstract void InitExchangePrice(BaseExchange ex, ExchangePricesEventArgs arg);
Пример #18
0
 public DataRefresher(ExchangeOptions exchangeOptions)
 {
     _exchangeOptions = exchangeOptions;
     _api             = new BaseExchange(_exchangeOptions);
 }