def test_no_like_for_like(self): """Test that it is not possible to deposit, withdraw, buy, or pay with the BagFIFO base currency. Note: testing against both the new CurrencyTypeException and also ValueError This is in case a future change modifies the order in which arguments are checked in any of these functions, which is not critical in some cases. The point is that none of these should succeed if the BagFIFO base currency (fiat) is used in any transaction instead of expected crypto """ # Note: 'usd' will be converted to uppercase in the constructor bagfifo = bags.BagFIFO('usd', self.rel) assert bagfifo.currency == 'USD' # Should not be able to buy with self.subTest(method="buy_with_base_currency"): with self.assertRaises((bags.CurrencyTypeException, ValueError)): bagfifo.buy_with_base_currency(self.rng[0], 10, 'usd', 10, 'Coinbase') # Should not be able to pay with self.subTest(method="pay"): with self.assertRaises((bags.CurrencyTypeException, ValueError)): bagfifo.pay(self.rng[3], 'usd', '1', 'Coinbase')
def test_trading_profits_with_fees(self): # Add handler to the logger (uncomment this to enable output) #self.logger.addHandler(self.handler) budget=1000 # List of fee percentages to be tested: fee_p = [D('0.00025'), D(1)/D(3), D(2)/D(3)] days = [self.rng[0], self.rng[2], self.rng[4]] currlist = ['BTC', 'XMR', 'EUR'] for fee in fee_p: for trade_to_fee in range(len(currlist)): for i in range(2): feelist = [(0, '')] * len(currlist) feelist[trade_to_fee] = (fee, currlist[trade_to_fee - i]) self.logger.info("Testing fee list %s" % feelist) self.logger.info("Working with new empty BagFIFO object") bagfifo = bags.BagFIFO('EUR', self.rel) # Make up and process some trades: proceeds = self.trading_set( bagfifo, budget=budget, currency='EUR', dayslist=days, currlist=currlist, feelist=feelist) # check correct profit: self.assertEqual( proceeds - budget, bagfifo.profit[str(self.rng[0].year)]) # check that bagfifo is empty and cleaned up: self.assertFalse(bagfifo.totals) self.assertFalse(bagfifo.bags) self.assertFalse(bagfifo.in_transit)
def test_bag_cost_after_trading_with_fees(self): # Add handler to the logger (uncomment this to enable output) #self.logger.addHandler(self.handler) budget=1000 # List of fee percentages to be tested: fee_p = [0, D('0.00025'), D(1)/D(3), D(2)/D(3)] days = [self.rng[0], self.rng[2]] currlist = ['BTC', 'XMR'] for fee in fee_p: for fee_cur in currlist: bagfifo = bags.BagFIFO('EUR', self.rel) self.logger.info("Working with new empty BagFIFO object") # Make up and process some trades: self.trading_set( bagfifo, budget=budget, currency='EUR', dayslist=days, currlist=currlist, feelist=[(0, ''), (fee, fee_cur)]) self.assertEqual( bagfifo.bags[''][-1].cost, budget + bagfifo.profit[str(self.rng[0].year)])
def test_trading_profits_no_fees(self): # Add handler to the logger (uncomment this to enable output) #self.logger.addHandler(self.handler) bagfifo = bags.BagFIFO('EUR', self.rel) budget=1000 # Make up and process some trades: proceeds = self.trading_set( bagfifo, budget=budget, currency='EUR', dayslist=[self.rng[0], self.rng[2], self.rng[4]], currlist=['BTC', 'XMR', 'EUR'], feelist=[(0, ''), (0, ''), (0, '')]) # check correct profit: self.assertEqual( proceeds - budget, bagfifo.profit[str(self.rng[0].year)]) # check that bagfifo is empty and cleaned up: self.assertFalse(bagfifo.totals) self.assertFalse(bagfifo.bags) self.assertFalse(bagfifo.in_transit)
def test_saving_loading(self): # Add handler to the logger (uncomment this to enable output) #self.logger.addHandler(self.handler) bagfifo = bags.BagFIFO('EUR', self.rel) # Make up some transactions: budget = 1000 day1 = self.rng[0] day2 = self.rng[2] day3 = self.rng[4] btc = self.rel.get_rate(day1, 'EUR', 'BTC') * budget t1 = trades.Trade('Buy', day1, 'BTC', btc, 'EUR', budget) # also include withdrawal and deposit: t2 = trades.Trade('Withdraw', day1, '', 0, 'BTC', btc / 3) t3 = trades.Trade('Deposit', day2, 'BTC', btc / 3, '', 0) xmr = self.rel.get_rate(day2, 'BTC', 'XMR') * btc t4 = trades.Trade( 'Trade', day2, 'XMR', xmr, 'BTC', btc, 'XMR', '0') proceeds = self.rel.get_rate(day3, 'XMR', 'EUR') * xmr t5 = trades.Trade( 'Trade', day3, 'EUR', proceeds, 'XMR', xmr, '', '0') # Only process first two transactions, so we have a bag in # bagfifo.bags and one in bagfifo.in_transit to save: for t in [t1, t2]: bagfifo.process_trade(t) self.log_bags(bagfifo) self.logger.info("Profit so far: %.2f %s\n", bagfifo.profit[str(day1.year)], bagfifo.currency) # save state outfile = StringIO() bagfifo.save(outfile) # create new BagFIFO and restore state: bf2 = bags.BagFIFO('EUR', self.rel) outfile.seek(0) bf2.load(outfile) # skip bf2.bags, bf2.in_transit and bf2.report, since the bags # and the report are new objects: excl = ['bags', 'in_transit', 'report'] self.assertDictEqual( {k:v for k, v in bagfifo.__dict__.items() if k not in excl}, {k:v for k, v in bf2.__dict__.items() if k not in excl}) # But the bags' contents must be equal: for ex in bagfifo.bags: for i, b in enumerate(bagfifo.bags[ex]): self.assertDictEqual(b.__dict__, bf2.bags[ex][i].__dict__) for cur in bagfifo.in_transit: for i, b in enumerate(bagfifo.in_transit[cur]): self.assertDictEqual( b.__dict__, bf2.in_transit[cur][i].__dict__) # We did not pay anything yet, thus, the report should be empty: self.assertListEqual(bagfifo.report.data, bf2.report.data) self.assertListEqual(bf2.report.data, []) # process the rest of the transactions: for t in [t3, t4, t5]: bagfifo.process_trade(t) bf2.process_trade(t) self.log_bags(bagfifo) self.logger.info("Profit so far: %.2f %s\n", bagfifo.profit[str(day3.year)], bagfifo.currency) # Now, bags lists should be empty, but we still need to # check the report manually: self.assertDictEqual( {k:v for k, v in bagfifo.__dict__.items() if k != 'report'}, {k:v for k, v in bf2.__dict__.items() if k != 'report'}) self.assertListEqual(bagfifo.report.data, bf2.report.data)