public void CalculateArbitrationTests_12() { ArbitrationHunter hunter = new ArbitrationHunter(null); Kraken kraken = new Kraken(); ArbitrationOpportunity opportunity; Bitstamp bitstamp = new Bitstamp(); OrderBook askBook = new OrderBook(); OrderBook bidBook = new OrderBook(); kraken.OrderBook = askBook; bitstamp.OrderBook = bidBook; //Test case 12: Part of ask order is fulfilled, not profitable after taking into account transfer fee //IMPORTANT NOTE! This test assumes Kraken has a trade fee of 0.0005, if that changes, this test *MIGHT* fail! kraken.TradeFee = 0.0m; bitstamp.TradeFee = 0.0m; askBook.Asks.Add(new Order(1.1m, 400.0m)); askBook.Asks.Add(new Order(0.8m, 402.0m)); askBook.Asks.Add(new Order(1.0m, 410.0m)); bidBook.Bids.Add(new Order(0.6m, 400.25m)); bidBook.Bids.Add(new Order(1.0m, 399m)); bidBook.Bids.Add(new Order(2.8m, 398m)); opportunity = hunter.CalculateArbitration(kraken, bitstamp, 99m, 999999m, 0.01m, true); //Make sure opportunity was not found, as it is not profitable when taking into account transfer fee Assert.IsTrue(opportunity == null); //Calculate arbitration again, but this time, don't take into account the transfer fee. An opportunity should be found this time. opportunity = hunter.CalculateArbitration(kraken, bitstamp, 99m, 999999m, 0.01m, false); Assert.IsTrue(opportunity != null); }
public void BitstampGetOpenOrdersTest() { Bitstamp bitstamp = new Bitstamp(FiatType.Usd); //If there is any problem connecting to the exchange, this will throw an error. bitstamp.GetAllOpenOrders(); }
public void GetTotalBalances() { ItBit itbit = new ItBit(); Anx anx = new Anx(); Bitstamp bitstamp = new Bitstamp(); Kraken kraken = new Kraken(); //Btce btce = new Btce(); Bitfinex bitfinex = new Bitfinex(); itbit.UpdateBalances(); anx.UpdateBalances(); bitstamp.UpdateBalances(); bitfinex.UpdateBalances(); //TODO: Fix these! Should be calls to UpdateTotalBalances! kraken.UpdateBalances(); //btce.UpdateBalances(); Decimal itBitBtcAmount = itbit.TotalBtc; Decimal itBitFiatAmount = itbit.TotalFiat; Decimal anxBtcAmount = anx.TotalBtc; Decimal anxFiatAmount = anx.TotalFiat; Decimal bitstampBtcAmount = bitstamp.TotalBtc; Decimal bitstampFiatoAmount = bitstamp.TotalFiat; Decimal bitfinexBtcAmount = bitfinex.TotalBtc; Decimal bitfinexFiatAmount = bitfinex.TotalFiat; //TODO Fix these! They should be the total amounts! Decimal krakenBtcAmount = kraken.AvailableBtc; Decimal krakenEurAmount = kraken.AvailableFiat; //Decimal btceBtcAmount = btce.AvailableBtc; //Decimal btceEuroAmount = btce.AvailableFiat; }
public void BitstampGetUsdEurConversionRateTest() { Bitstamp bitstamp = new Bitstamp(); decimal conversionRate = bitstamp.GetUsdEurConversionRate(); //As long as this returned a number, the call to the api was successful Assert.IsTrue(conversionRate > 0); }
public void BitstampAccountInformationUpdateTest() { Bitstamp bitstamp = new Bitstamp(); //If there is any problem connecting to the exchange, this will throw an error. bitstamp.UpdateAccountInformation(); //Only need to ensure UpdateAccountInformation updates trade fee, as btc and fiat balances are allowed to be zero. Assert.IsTrue(bitstamp.TradeFee > 0.0m); }
public void BitstampAvailableBalanceUpdateTest() { Bitstamp bitstamp = new Bitstamp(FiatType.Usd); //If there is any problem connecting to the exchange, this will throw an error. bitstamp.UpdateBalances(); //Only need to ensure UpdateBalances updates trade fee, as btc and fiat balances are allowed to be zero. Assert.IsTrue(bitstamp.TradeFee > 0.0m); }
public void BitstampUpdateOrderBookTest() { Bitstamp bitstamp = new Bitstamp(); //If there is any problem connecting to the exchange, this will throw an error. bitstamp.UpdateOrderBook(1); //This assumes that the exchange has at least 1 order on each side. Technically this can give a false negative, but it's unlikely. Assert.IsTrue(bitstamp.OrderBook.Asks.Count == 1); Assert.IsTrue(bitstamp.OrderBook.Bids.Count == 1); }
public void BitstampBuyCostRoundTest() { Bitstamp bitstamp = new Bitstamp(FiatType.Usd); //Need to set the trade fee for this test to work bitstamp.TradeFee = 0.25m; Assert.IsTrue(bitstamp.ApplyFeeToBuyCost(20.09m) == 20.15m); Assert.IsTrue(bitstamp.ApplyFeeToBuyCost(90.95m) == 91.18m); //Buy 0.02 @ 395.65 = 7.91 //Fee price = 7.91 * 0.0025 = 0.019775 = 0.02 //Total cost = 7.91 + 0.02 = 7.93 Assert.IsTrue(bitstamp.ApplyFeeToBuyCost(Decimal.Multiply(395.65m, 0.02m)) == 7.93m); }
public void TransferInsertTest() { BaseExchange sellExchange = new Kraken(); BaseExchange buyExchange = new Bitstamp(); int MaxId = 0; sellExchange.AvailableBtc = 1.0234234234m; buyExchange.AvailableBtc = 2.4534534m; decimal transferAmount = 0.6319841998m; //First need to create an arbitration run and opportunity ArbitrationRun testRun = TestsHelper.CreateArbitrationRun(); ArbitrationOpportunity testOpportunity = TestsHelper.CreateArbitrationOpportunity(buyExchange, sellExchange, testRun.Id.Value); //Before the test can continue, ensure the arbitraiton opportunity was properly inserted Assert.IsTrue(testOpportunity.Id != null); Transfer testTransfer = new Transfer(buyExchange, sellExchange, transferAmount); //Get the max id from TRANSFER table Object result = DatabaseManager.ExecuteQuery("select MaxId = max(id) from TRANSFER").Rows[0]["MaxId"]; if (result != DBNull.Value) { MaxId = (int)result; } //Now save the TRANSFER to the db testTransfer.PersistToDb(); //Select the transfer from the db result = DatabaseManager.ExecuteQuery(string.Format("select id from TRANSFER where id = {0} AND ORIGIN_EXCHANGE = '{1}' and DESTINATION_EXCHANGE = '{2}' AND AMOUNT = {3}", testTransfer.Id, buyExchange.Name, sellExchange.Name, transferAmount)).Rows[0][0]; //Clean up before testing result if (result != DBNull.Value) { //Remove the test transfer DatabaseManager.ExecuteNonQuery(String.Format("delete from TRANSFER where id = {0}", testTransfer.Id)); } TestsHelper.DeleteArbitrationTrade(testOpportunity.Id.Value); TestsHelper.DeleteArbitrationRun(testRun.Id.Value); //The above query should return the transfer that was created. Assert.IsTrue(result != DBNull.Value); }
public void BitstampSellCostRoundTest() { Bitstamp bitstamp = new Bitstamp(FiatType.Usd); //Need to set the trade fee for this test to work bitstamp.TradeFee = 0.25m; Assert.IsTrue(bitstamp.ApplyFeeToSellCost(20.09m) == 20.03m); Assert.IsTrue(bitstamp.ApplyFeeToSellCost(90.95m) == 90.72m); //Sell 0.04831514 @ 415.5 = 20.07494067 = 20.07 //Fee price = 20.07 * 0.0025 = 0.050175 = 0.06 //Total cost = 20.07 - 0.06 = 20.01 Assert.IsTrue(bitstamp.ApplyFeeToSellCost(Decimal.Multiply(0.04831514m, 415.5m)) == 20.01m); //Sell 0.05513812 @ 365 = 20.1254138 = 20.13 //Fee price = 20.13 * 0.0025 = 0.050325 = 0.06 //Total cost = 20.13 - 0.06 = 20.07 Assert.IsTrue(bitstamp.ApplyFeeToSellCost(Decimal.Multiply(0.05513812m, 365.0m)) == 20.07m); }
public void CalculateArbitrationTests_11() { ArbitrationHunter hunter = new ArbitrationHunter(null); Kraken kraken = new Kraken(); ArbitrationOpportunity opportunity; Bitstamp bitstamp = new Bitstamp(); OrderBook askBook = new OrderBook(); OrderBook bidBook = new OrderBook(); kraken.OrderBook = askBook; bitstamp.OrderBook = bidBook; //Test case 11: Part of ask order is fulfilled, taking into account transfer fee //IMPORTANT NOTE! This test assumes Kraken has a transfer fee of 0.0005, if that changes, this test will fail! kraken.TradeFee = 0.0m; bitstamp.TradeFee = 0.0m; askBook.Asks.Add(new Order(1.1m, 400.0m)); askBook.Asks.Add(new Order(0.8m, 402.0m)); askBook.Asks.Add(new Order(1.0m, 410.0m)); bidBook.Bids.Add(new Order(0.6m, 401.0m)); bidBook.Bids.Add(new Order(1.0m, 399m)); bidBook.Bids.Add(new Order(2.8m, 398m)); opportunity = hunter.CalculateArbitration(kraken, bitstamp, 99m, 999999m, 0.01m, true); //Make sure opportunity was found correctly Assert.IsTrue(opportunity != null); Assert.IsTrue(opportunity.BuyExchange == kraken); Assert.IsTrue(opportunity.SellExchange == bitstamp); Assert.IsTrue(opportunity.BuyAmount == 0.6m); Assert.IsTrue(opportunity.SellAmount == 0.6m); Assert.IsTrue(opportunity.Profit == 0.39975m); Assert.IsTrue(opportunity.BuyPrice == 400m); Assert.IsTrue(opportunity.SellPrice == 401m); Assert.IsTrue(opportunity.TotalBuyCost == 240m); Assert.IsTrue(opportunity.TotalSellCost == 240.60m); }
public void CalculateArbitrationTests_01() { ArbitrationHunter hunter = new ArbitrationHunter(null); Kraken kraken = new Kraken(); ArbitrationOpportunity opportunity; Bitstamp bitstamp = new Bitstamp(); OrderBook askBook = new OrderBook(); OrderBook bidBook = new OrderBook(); kraken.OrderBook = askBook; bitstamp.OrderBook = bidBook; //Test case 1: Part of ask order is fulfilled, no trade fees to account for kraken.TradeFee = 0.0m; bitstamp.TradeFee = 0.0m; askBook.Asks.Add(new Order(1.1m, 400.0m)); askBook.Asks.Add(new Order(0.8m, 402.0m)); askBook.Asks.Add(new Order(1.0m, 410.0m)); bidBook.Bids.Add(new Order(0.6m, 401.0m)); bidBook.Bids.Add(new Order(1.0m, 399m)); bidBook.Bids.Add(new Order(2.8m, 398m)); opportunity = hunter.CalculateArbitration(kraken, bitstamp, 99m, 999999m, 0.58m, false); //Make sure opportunity was found correctly Assert.IsTrue(opportunity != null); Assert.IsTrue(opportunity.BuyExchange == kraken); Assert.IsTrue(opportunity.SellExchange == bitstamp); Assert.IsTrue(opportunity.BuyAmount == 0.6m); Assert.IsTrue(opportunity.SellAmount == 0.6m); Assert.IsTrue(opportunity.Profit == 0.6m); Assert.IsTrue(opportunity.BuyPrice == 400m); Assert.IsTrue(opportunity.SellPrice == 401m); Assert.IsTrue(opportunity.TotalBuyCost == 240m); Assert.IsTrue(opportunity.TotalSellCost == 240.60m); }
public void BitstampBuySellQueryDeleteTest() { Bitstamp bitstamp = new Bitstamp(FiatType.Usd); string buyOrderId; string sellorderId; //First, insert a buy and sell order. If there are any errors with either of these operations, //an exception will be thrown. //This is the lowest possible buy order you can put in bitstamp buyOrderId = bitstamp.Buy(1, 5.00m); //Set the sell price at an absurdely high value so the sell order doesn't actully get executed. sellorderId = bitstamp.Sell(bitstamp.MinimumBitcoinOrderAmount, 99999m); //Both orders should still be open Assert.IsFalse(bitstamp.IsOrderFulfilled(buyOrderId)); Assert.IsFalse(bitstamp.IsOrderFulfilled(sellorderId)); //Now delete both orders. If there are any errors with either of these operations, //an exception will be thrown. bitstamp.DeleteOrder(buyOrderId); bitstamp.DeleteOrder(sellorderId); }
private static void PopulateExchanges(string securityJsonFilename) { m_security = new ApiSecurity(securityJsonFilename); foreach (var exch in m_security.ApiKeys.Keys) { var c = m_security.ApiKeys[exch]; //Console.WriteLine("{0} '{1}' '{2}'", exch, c.ApiKey, c.ApiSecret); } ApiCredentials creds; /*creds = m_security.ApiKeys["B2C2"]; // BINANCE * b2c2 = B2C2.Create(creds); * Exchanges[CryptoExch.B2C2] = b2c2;*/ creds = m_security.ApiKeys["BINANCE"]; // BINANCE binance = Binance.Create(creds); Exchanges[CryptoExch.BINANCE] = binance; creds = m_security.ApiKeys["BITFINEX"]; // BITFINEX bitfinex = Bitfinex.Create(creds); Exchanges[CryptoExch.BITFINEX] = bitfinex; creds = m_security.ApiKeys["BITFLYER"]; // BITFLYER bitflyer = BitFlyer.Create(creds); Exchanges[CryptoExch.BITFLYER] = bitflyer; creds = m_security.ApiKeys["BITSTAMP"]; // BITSTAMP bitstamp = Bitstamp.Create(creds, "client_id"); Exchanges[CryptoExch.BITSTAMP] = bitstamp; creds = m_security.ApiKeys["BITTREX"]; // BITTREX bittrex = Bittrex.Create(creds); Exchanges[CryptoExch.BITTREX] = bittrex; creds = m_security.ApiKeys["GDAX"]; // GDAX gdax = GDAX.Create(creds, "mickey+mouse"); Exchanges[CryptoExch.GDAX] = gdax; creds = m_security.ApiKeys["HITBTC"]; // HITBTC hitbtc = HitBTC.Create(creds); Exchanges[CryptoExch.HITBTC] = hitbtc; creds = m_security.ApiKeys["ITBIT"]; // ITBIT itbit = ItBit.Create(creds); Exchanges[CryptoExch.ITBIT] = itbit; creds = m_security.ApiKeys["KRAKEN"]; // KRAKEN kraken = Kraken.Create(creds); Exchanges[CryptoExch.KRAKEN] = kraken; creds = m_security.ApiKeys["POLONIEX"]; // POLONIEX poloniex = Poloniex.Create(creds); Exchanges[CryptoExch.POLONIEX] = poloniex; /*creds = m_security.ApiKeys["BLEUTRADE"]; // BLEUTRADE * bleutrade = Bleutrade.Create(creds); * Exchanges[CryptoExch.BLEUTRADE] = bleutrade; * * creds = m_security.ApiKeys["BLINKTRADE"]; // BLINKTRADE * blinktrade = BlinkTrade.Create(creds); * Exchanges[CryptoExch.BLINKTRADE] = blinktrade;*/ gemini = Gemini.Instance; Exchanges[CryptoExch.GEMINI] = Gemini.Instance; // For each exchange, subscribe to the various events foreach (var exchange in Exchanges.Values) { exchange.UpdateOrderBookEvent += Exchanges_UpdateOrderBookEvent; exchange.UpdateOrdersEvent += Exchanges_UpdateOrdersEvent; exchange.UpdateTickerEvent += Exchanges_UpdateTickerEvent; /*var ws = exchange as IExchangeWebSocket; * if (ws != null) * ws.StartWebSocket(null);*/ } /*Exchanges[CryptoExch.VAULTORO] = Vaultoro.Instance; * Exchanges[CryptoExch.CHANGELLY] = Changelly.Instance; * Exchanges[CryptoExch.BITHUMB] = Bithumb.Instance; * Exchanges[CryptoExch.BITMEX] = BitMEX.Instance; * Exchanges[CryptoExch.BITSQUARE] = Bitsquare.Instance; * Exchanges[CryptoExch.BTCC] = BTCC.Instance; * //Exchanges[CryptoExch.BTER] = BTER.Instance; * Exchanges[CryptoExch.CEX] = Cex.Instance; * //Exchanges[CryptoExch.COINIGY] = Coinigy.Instance; * Exchanges[CryptoExch.COINONE] = Coinone.Instance; * Exchanges[CryptoExch.GATEIO] = GateIO.Instance; * Exchanges[CryptoExch.HUOBI] = Huobi.Instance; * Exchanges[CryptoExch.KORBIT] = Korbit.Instance; * Exchanges[CryptoExch.KUCOIN] = Kucoin.Instance; * Exchanges[CryptoExch.OKCOIN] = OkCoin.Instance; * Exchanges[CryptoExch.OKEX] = OKEx.Instance; * Exchanges[CryptoExch.WEX] = Wex.Instance; * Exchanges[CryptoExch.XCRYPTO] = XCrypto.Instance;*/ }
public async Task <ITickers> GetTicker([FromBody] CompositeStockExchangeObject compositeStockExchangeObject) { decimal exchangeRate = compositeStockExchangeObject.ExchangeRate; Common.StockExchange.Types.StockExchange selectedStockExchange = compositeStockExchangeObject.StockExchange; string selectedPairs = compositeStockExchangeObject.SelectedPairs; IStockExchanges stockExchanges; switch (selectedStockExchange) { case Common.StockExchange.Types.StockExchange.Binance: stockExchanges = new Binance(); return(await stockExchanges.GetTickers(selectedPairs, exchangeRate)); case Common.StockExchange.Types.StockExchange.Bitfinex: stockExchanges = new Bitfinex(); return(await stockExchanges.GetTickers(selectedPairs, exchangeRate)); case Common.StockExchange.Types.StockExchange.Bitmex: stockExchanges = new Bitmex(); return(await stockExchanges.GetTickers(selectedPairs, exchangeRate)); case Common.StockExchange.Types.StockExchange.Bitstamp: stockExchanges = new Bitstamp(); return(await stockExchanges.GetTickers(selectedPairs, exchangeRate)); case Common.StockExchange.Types.StockExchange.Bittrex: stockExchanges = new Bittrex(); return(await stockExchanges.GetTickers(selectedPairs, exchangeRate)); case Common.StockExchange.Types.StockExchange.Cex: stockExchanges = new Cex(); return(await stockExchanges.GetTickers(selectedPairs, exchangeRate)); case Common.StockExchange.Types.StockExchange.Exmo: stockExchanges = new Exmo(); return(await stockExchanges.GetTickers(selectedPairs, exchangeRate)); case Common.StockExchange.Types.StockExchange.Gdax: stockExchanges = new Gdax(); return(await stockExchanges.GetTickers(selectedPairs, exchangeRate)); case Common.StockExchange.Types.StockExchange.Gemini: stockExchanges = new Gemini(); return(await stockExchanges.GetTickers(selectedPairs, exchangeRate)); case Common.StockExchange.Types.StockExchange.Kraken: stockExchanges = new Kraken(); return(await stockExchanges.GetTickers(selectedPairs, exchangeRate)); case Common.StockExchange.Types.StockExchange.Poloniex: stockExchanges = new Poloniex(); return(await stockExchanges.GetTickers(selectedPairs, exchangeRate)); case Common.StockExchange.Types.StockExchange.QuadrigaCx: stockExchanges = new QuadrigaCx(); return(await stockExchanges.GetTickers(selectedPairs, exchangeRate)); default: throw new NullStockExchangeException("Invalid StockExchange Selection"); } }
public void OpportunityListValidatesProperly() { int requiredRoundsForValidarion = 3; Anx anx = new Anx(); Bitstamp bitstamp = new Bitstamp(); Kraken kraken = new Kraken(); ItBit itBit = new ItBit(); List <ArbitrationOpportunity> opportunityList = new List <ArbitrationOpportunity>(); List <ArbitrationOpportunity> validatedList; List <BaseExchange> exchangeList = new List <BaseExchange>(); exchangeList.Add(anx); exchangeList.Add(bitstamp); exchangeList.Add(kraken); exchangeList.Add(itBit); OpportunityValidator opportunityValidator = new OpportunityValidator(requiredRoundsForValidarion, exchangeList); //Build of a list of opportunities: ArbitrationOpportunity krakenItBitopportunity = new ArbitrationOpportunity(kraken, itBit) { Profit = 2.23m }; ArbitrationOpportunity krakenBitstampopportunity = new ArbitrationOpportunity(kraken, bitstamp) { Profit = 0.50m }; ArbitrationOpportunity anxItBitopportunity = new ArbitrationOpportunity(anx, itBit) { Profit = 2.01m }; ArbitrationOpportunity anxItBitopportunity2 = new ArbitrationOpportunity(anx, itBit) { Profit = 1.98m }; ArbitrationOpportunity anxItBitopportunity3 = new ArbitrationOpportunity(anx, itBit) { Profit = 0.27m }; opportunityList.Add(krakenItBitopportunity); opportunityList.Add(krakenBitstampopportunity); opportunityList.Add(anxItBitopportunity); //Round one: validatedList = opportunityValidator.ValidateOpportunities(opportunityList); Assert.IsTrue(validatedList.Count == 0); //Round two: opportunityList.Remove(krakenBitstampopportunity); validatedList = opportunityValidator.ValidateOpportunities(opportunityList); Assert.IsTrue(validatedList.Count == 0); //Round three: An oppportunity between Anx and ItBit has survived until now (alebit with a different profit) //Add the Kraken - Bitstamp opportunity. //Remove Krakken - ItBit opportunity; it only lasts two rounds. opportunityList.Add(krakenBitstampopportunity); opportunityList.Remove(krakenItBitopportunity); //Remove the Anx - ItBit opportunity, than add another opportunity with those exchanges but a less profit opportunityList.Remove(anxItBitopportunity); opportunityList.Add(anxItBitopportunity2); validatedList = opportunityValidator.ValidateOpportunities(opportunityList); Assert.IsTrue(validatedList.Count == 1); Assert.IsTrue(validatedList[0].Profit == 1.98m); //Round 4: anxItBitopportunity should still be in the returned list //Remove the Anx - ItBit opportunity, than add another opportunity with those exchanges but a less profit opportunityList.Remove(anxItBitopportunity); opportunityList.Add(anxItBitopportunity3); validatedList = opportunityValidator.ValidateOpportunities(opportunityList); Assert.IsTrue(validatedList.Count == 1); Assert.IsTrue(validatedList[0].Profit == 0.27m); //Round 5: anxItBitopportunity should still be in the returned list, krakenBitstampopportunity should have been added validatedList = opportunityValidator.ValidateOpportunities(opportunityList); Assert.IsTrue(validatedList.Count == 2); Assert.IsTrue(validatedList[0].Profit == 0.50m); Assert.IsTrue(validatedList[1].Profit == 0.27m); }
public void OpportunityProfitValidatesProperly() { int requiredRoundsForValidarion = 3; Anx anx = new Anx(); Bitstamp bitstamp = new Bitstamp(); Kraken kraken = new Kraken(); ItBit itBit = new ItBit(); List <BaseExchange> exchangeList = new List <BaseExchange>(); decimal amount = 0.2m; decimal buyPrice = 150m; decimal totalBuyCost = 30m; decimal sellPrice = 200m; decimal totalSellCost = 40m; decimal profit = 10m; exchangeList.Add(anx); exchangeList.Add(bitstamp); exchangeList.Add(kraken); exchangeList.Add(itBit); OpportunityValidator opportunityValidator = new OpportunityValidator(requiredRoundsForValidarion, exchangeList); //Note, can use a fake run id here because the trade is never persisted to the db. ArbitrationOpportunity testOpportunity = new ArbitrationOpportunity(anx, bitstamp, amount, buyPrice, totalBuyCost, sellPrice, totalSellCost, profit, 1); //First, set the balances for all the exchanges. anx.AvailableFiat = 100m; anx.AvailableBtc = 100m; bitstamp.AvailableFiat = 100m; bitstamp.AvailableBtc = 100m; kraken.AvailableFiat = 100m; kraken.AvailableBtc = 100m; itBit.AvailableFiat = 100m; itBit.AvailableBtc = 100m; //Scenario 1; happy path. Buy and selling works as expected. //Prep the validator opportunityValidator.SetFiatAndBitcoinBalanceBeforeArbitrationTrade(); //Simulate the trade going through anx.AvailableFiat -= totalBuyCost; anx.AvailableBtc += amount; bitstamp.AvailableFiat += totalSellCost; bitstamp.AvailableBtc -= amount; //If there was as error, this will throw it. opportunityValidator.ValidateExchangeBalancesAfterTrade(testOpportunity); //Scenario 2: Buy never happens. Validator should throw an error bool errorThrown = false; anx.AvailableFiat = 100m; anx.AvailableBtc = 100m; bitstamp.AvailableFiat = 100m; bitstamp.AvailableBtc = 100m; kraken.AvailableFiat = 100m; kraken.AvailableBtc = 100m; itBit.AvailableFiat = 100m; itBit.AvailableBtc = 100m; //Prep the validator opportunityValidator.SetFiatAndBitcoinBalanceBeforeArbitrationTrade(); //Simulate the trade going through, but buy never happens. This should cause the validator to throw an error. bitstamp.AvailableFiat += totalSellCost; bitstamp.AvailableBtc -= amount; try { opportunityValidator.ValidateExchangeBalancesAfterTrade(testOpportunity); } catch (Exception e) { errorThrown = true; } Assert.IsTrue(errorThrown); }
public void PersistArbitrationOpportunity() { //Arbitraty test values decimal buyAmount = 351.654316m; decimal sellAmount = 351.654316m; decimal buyPrice = 409.21m; decimal sellPrice = 410.87m; decimal totalBuyCost = 1201.14m; decimal totalSellCost = 1301.54m; decimal profit = totalSellCost - totalBuyCost; string buyOrderId = "Abc-123"; string sellOrderId = "123-Abc"; DateTime executionDateTime = DateTime.Now; Bitstamp buyExchange = new Bitstamp(); Btce sellExchange = new Btce(); ArbitrationRun testRun = null; ArbitrationRun updateTestRun = null; ArbitrationOpportunity testArbitrationTrade = null; try { testRun = TestsHelper.CreateArbitrationRun(); updateTestRun = TestsHelper.CreateArbitrationRun(); testArbitrationTrade = new ArbitrationOpportunity(buyExchange, sellExchange); testArbitrationTrade.BuyAmount = buyAmount; testArbitrationTrade.SellAmount = sellAmount; testArbitrationTrade.ArbitrationRunId = testRun.Id.Value; testArbitrationTrade.BuyPrice = buyPrice; testArbitrationTrade.ExecutionDateTime = executionDateTime; testArbitrationTrade.Profit = profit; testArbitrationTrade.SellPrice = sellPrice; testArbitrationTrade.TotalBuyCost = totalBuyCost; testArbitrationTrade.TotalSellCost = totalSellCost; testArbitrationTrade.BuyOrderId = buyOrderId; testArbitrationTrade.SellOrderId = sellOrderId; //Now that the arbitration trade has been set up, save it to the db. testArbitrationTrade.PersistToDb(); //Ensure an id was set after the initial insert Assert.IsTrue(testArbitrationTrade.Id != null); string insertFetchSql = string.Format("" + "select " + " ID, " + " CREATE_DATETIME, " + " LAST_MODIFIED_DATETIME " + "from " + " ARBITRATION_TRADE " + "where " + " ID = {0} AND " + " BUY_AMOUNT = {1} AND " + " BUY_PRICE = {2} AND " + " SELL_PRICE = {3} AND" + " TOTAL_BUY_COST = {4} AND " + " TOTAL_SELL_COST = {5} AND " + " PROFIT = {6} AND " + " EXECUTION_DATETIME = '{7}' AND " + " SELL_EXCHANGE = '{8}' AND " + " BUY_EXCHANGE = '{9}' AND " + " BUY_ORDER_ID = '{10}' AND " + " SELL_ORDER_ID = '{11}' AND " + " ARBITRATION_RUN_ID = {12} AND " + " SELL_AMOUNT = {13}", testArbitrationTrade.Id.Value, buyAmount, buyPrice, sellPrice, totalBuyCost, totalSellCost, profit, executionDateTime.ToString("yyy-MM-dd HH:mm:ss"), sellExchange.Name, buyExchange.Name, buyOrderId, sellOrderId, testRun.Id.Value, sellAmount); //Ensure all the values were properly inserted. DataTable result = DatabaseManager.ExecuteQuery(insertFetchSql); Assert.IsTrue(result != null && Convert.ToInt32(result.Rows[0]["ID"]) == testArbitrationTrade.Id.Value); //Create some bogus dates for CREATE_DATETIME and LAST_MODIFIED_DATETIME DateTime createDateTime = new DateTime(2014, 1, 1, 13, 25, 05); DateTime lastModifiedDateTime = new DateTime(2014, 1, 1, 13, 25, 05); //In order to test that CREATE_DATETIME and LAST_MODIFIED_DATETIME behave properly on updates, need to put some bogus data in there: DatabaseManager.ExecuteNonQuery(string.Format("update ARBITRATION_TRADE set CREATE_DATETIME = '{0}', LAST_MODIFIED_DATETIME = '{1}' where ID = {2}", createDateTime.ToString("yyy-MM-dd HH:mm:ss"), lastModifiedDateTime.ToString("yyy-MM-dd HH:mm:ss"), testArbitrationTrade.Id.Value)); //Update properties with arbitraty test values. buyAmount = 103264798.175785743216m; sellAmount = 103264798.175785743216m; buyPrice = 1.02m; sellPrice = 10.02m; totalBuyCost = 2.01m; totalSellCost = 18.01m; profit = totalSellCost - totalBuyCost; executionDateTime = DateTime.Now; buyOrderId = "Choctaw-47"; sellOrderId = "Apache-48"; //Update arbitration trade to have new values testArbitrationTrade.BuyAmount = buyAmount; testArbitrationTrade.SellAmount = sellAmount; testArbitrationTrade.ArbitrationRunId = updateTestRun.Id.Value; testArbitrationTrade.BuyPrice = buyPrice; testArbitrationTrade.ExecutionDateTime = executionDateTime; testArbitrationTrade.Profit = profit; testArbitrationTrade.SellPrice = sellPrice; testArbitrationTrade.TotalBuyCost = totalBuyCost; testArbitrationTrade.TotalSellCost = totalSellCost; testArbitrationTrade.BuyOrderId = buyOrderId; testArbitrationTrade.SellOrderId = sellOrderId; testArbitrationTrade.PersistToDb(); string updateFetchSql = string.Format("" + "select " + " ID, " + " CREATE_DATETIME, " + " LAST_MODIFIED_DATETIME " + "from " + " ARBITRATION_TRADE " + "where " + " ID = {0} AND " + " BUY_AMOUNT = {1} AND " + " BUY_PRICE = {2} AND " + " SELL_PRICE = {3} AND" + " TOTAL_BUY_COST = {4} AND " + " TOTAL_SELL_COST = {5} AND " + " PROFIT = {6} AND " + " EXECUTION_DATETIME = '{7}' AND " + " SELL_EXCHANGE = '{8}' AND " + " BUY_EXCHANGE = '{9}' AND " + " BUY_ORDER_ID = '{10}' AND " + " SELL_ORDER_ID = '{11}' AND " + " ARBITRATION_RUN_ID = {12} AND " + " SELL_AMOUNT = {13}", testArbitrationTrade.Id.Value, buyAmount, buyPrice, sellPrice, totalBuyCost, totalSellCost, profit, executionDateTime.ToString("yyy-MM-dd HH:mm:ss"), sellExchange.Name, buyExchange.Name, buyOrderId, sellOrderId, updateTestRun.Id.Value, sellAmount); result = DatabaseManager.ExecuteQuery(updateFetchSql); //Ensure a record was found with all the updated values Assert.IsTrue(result != null); //Ensure the CREATE_DATETIME is the same, but the LAST_MODIFIED_DATETIME is different Assert.IsTrue(createDateTime == (DateTime)result.Rows[0]["CREATE_DATETIME"]); Assert.IsTrue(lastModifiedDateTime != (DateTime)result.Rows[0]["LAST_MODIFIED_DATETIME"]); } finally { //Remove test data from the database if (testArbitrationTrade.Id != null) { TestsHelper.DeleteArbitrationTrade(testArbitrationTrade.Id.Value); } if (testRun.Id != null) { TestsHelper.DeleteArbitrationRun(testRun.Id.Value); } if (updateTestRun.Id != null) { TestsHelper.DeleteArbitrationRun(updateTestRun.Id.Value); } } }
public void NotEnoughtBtcExceptionAreSwallowedCorrectly() { ArbitrationRun testRun = null; ArbitrationOpportunity opportunity1 = null; ArbitrationOpportunity opportunity2 = null; ArbitrationOpportunity opportunity3 = null; try { //Set up a test run testRun = TestsHelper.CreateArbitrationRun(); //Set up the buy and sell exchanges. Bitstamp bitstamp = new Bitstamp(); Kraken kraken = new Kraken(); List <BaseExchange> exchangeList = new List <BaseExchange>(); exchangeList.Add(bitstamp); exchangeList.Add(kraken); bitstamp.AvailableBtc = 0.2m; bitstamp.AvailableFiat = 100m; kraken.AvailableBtc = 0.2m; kraken.AvailableFiat = 30m; //Initial trad; bitstamp will need to transfer 0.1 btc to kraken for this. It will be found in the rollup later. //Bitstamp now has 0.4 btc. opportunity1 = TestsHelper.CreateArbitrationOpportunity(bitstamp, kraken, testRun.Id.Value, 0.1m); //Made up numbers; they don't really matter for this test opportunity1.TotalBuyCost = 10m; opportunity1.TotalSellCost = 10m; bitstamp.SimulatedBuy(opportunity1.BuyAmount, opportunity1.TotalBuyCost); kraken.SimulatedSell(opportunity1.BuyAmount, opportunity1.TotalSellCost); Assert.IsTrue(bitstamp.AvailableBtc == 0.3m); //Now a couple a trade where btc is sold off at Bitstamp; enough to make the rollup transfer fail //Bitstamp now has 0.1 opportunity2 = TestsHelper.CreateArbitrationOpportunity(kraken, bitstamp, testRun.Id.Value, 0.3m); //Made up numbers; they don't really matter for this test opportunity2.TotalBuyCost = 30m; opportunity2.TotalSellCost = 30m; kraken.SimulatedBuy(opportunity2.BuyAmount, opportunity2.TotalBuyCost); bitstamp.SimulatedSell(opportunity2.BuyAmount, opportunity2.TotalSellCost); Assert.IsTrue(bitstamp.AvailableBtc == 0.0m); //Now assume this trigger a transfer, so lets say 0.5btc is in transfer to bitstamp from kraken bitstamp.BTCInTransfer = 0.5m; //Now another buy at bitstamp; this will trigger a transfer rollup from bitstamp to kraken opportunity3 = TestsHelper.CreateArbitrationOpportunity(bitstamp, kraken, testRun.Id.Value, 0.15m); //Made up numbers; they don't really matter for this test opportunity3.TotalBuyCost = 15m; opportunity3.TotalSellCost = 15m; bitstamp.SimulatedBuy(opportunity3.BuyAmount, opportunity3.TotalBuyCost); kraken.SimulatedSell(opportunity3.BuyAmount, opportunity3.TotalSellCost); Assert.IsTrue(bitstamp.AvailableBtc == 0.15m); //This should detect a transfer, but not actually create it List <Transfer> transferFound = TransferManager.DetectAndExecuteRollupTransfers_Simulate(3, testRun.Id.Value, exchangeList); Assert.IsTrue(transferFound == null); //Erase btc in transfer and look for transfers again, this time the TransferManager should throw an exception because //a bad transfer has been found (it's amount is > bitstamp total btc) bool errorFound = false; bitstamp.BTCInTransfer = 0m; try { TransferManager.DetectAndExecuteRollupTransfers_Simulate(2, testRun.Id.Value, exchangeList); } catch (NotEnoughBtcException e) { errorFound = true; } Assert.IsTrue(errorFound, "TransferManager did not throw NotEnoughBtcException."); } //Clean up test data finally { if (opportunity1 != null) { TestsHelper.DeleteArbitrationTrade(opportunity1.Id.Value); } if (opportunity2 != null) { TestsHelper.DeleteArbitrationTrade(opportunity2.Id.Value); } if (opportunity3 != null) { TestsHelper.DeleteArbitrationTrade(opportunity3.Id.Value); } if (testRun != null) { TestsHelper.DeleteArbitrationTrade(testRun.Id.Value); } } }