Пример #1
0
 def __init__(self, prices_file, balance, strategy):
     """
     :param prices_file: The file that has the pair prices.
     :param balance: The initial balance to start with.
     :param strategy: The instance of the strategy to backtest (subclass of AbstractStrategy)
     """
     self.prices_file = prices_file
     self.account = Account(balance)
     self.strategy = strategy
Пример #2
0
 def test_create_trade(self):
     account = Account(100)
     trade_id, trade = account.open_trade(('a', 'b'), 1, Trade.TYPE_BUY, 60, 2, 0.5)
     self.assertEqual(40, account.balance)
     self.assertEqual(1, len(account.trades_list))
     self.assertIn(trade, account.trades_list)
     self.assertEqual(1, trade_id)
     self.assertEqual(('a', 'b'), trade.pair)
     self.assertEqual(1, trade.price)
     self.assertEqual(60, trade.amount)
     self.assertEqual(2, trade.take_profit_price)
     self.assertEqual(0.5, trade.stop_loss_price)
Пример #3
0
class Backtest:
    def __init__(self, prices_file, balance, strategy):
        """
        :param prices_file: The file that has the pair prices.
        :param balance: The initial balance to start with.
        :param strategy: The instance of the strategy to backtest (subclass of AbstractStrategy)
        """
        self._prices_file = prices_file
        self._account = Account(balance)
        self._strategy = strategy

    @property
    def account(self):
        return self._account

    @staticmethod
    def parse_entry(entry):
        parts = entry.strip().split(';')
        timestamp = parts[0]
        values = [0] * (len(parts) - 1)
        for i in range(1, len(parts)):
            values[i - 1] = float(parts[i])
        return timestamp, values

    def start(self):
        """Starts the replay of historical data against the user-defined strategy"""

        pairs = cfg.pairs()
        with open(self._prices_file) as file:
            while True:
                current_line = file.readline()
                if not current_line:
                    break

                timestamp, prices = self.__class__.parse_entry(current_line)
                if len(prices) != len(pairs):
                    raise RuntimeError(
                        'The number of prices in this entry ({}) does not match the number of pairs'
                        .format(timestamp))

                prices_dict = {pairs[i]: prices[i] for i in range(len(pairs))}

                results = self._account.auto_close_trades(prices_dict)
                for trade_id, outcome in results:
                    logging.debug('{} Closed t{} with {}'.format(
                        timestamp, trade_id, outcome))

                self._strategy.execute(self._account, timestamp, prices_dict)

        logging.info('Result: %s' %
                     self._account.net_balance_summary(prices_dict))
Пример #4
0
 def test_close_trade(self):
     account = Account(100)
     account.open_trade(('a', 'b'), 1, Trade.TYPE_BUY, 60)
     self.assertEqual(40, account.balance)
     self.assertEqual(Account.OUTCOME_LOSS, account.close_trade(1, 0.5))
     self.assertEqual(70, account.balance)
     account.open_trade(('a', 'b'), 2, Trade.TYPE_SELL, 50)
     self.assertEqual(20, account.balance)
     self.assertEqual(Account.OUTCOME_PROFIT, account.close_trade(2, 1))
     self.assertEqual(120, account.balance)
Пример #5
0
 def test_net_balance_summary(self):
     account = Account(100)
     account.open_trade(('a', 'b'), 1, Trade.TYPE_BUY, 40)
     account.open_trade(('c', 'd'), 1, Trade.TYPE_SELL, 40)
     self.assertEqual('90 units - trades [open [1, 2], 2 total, 0 wins, 0 losses]',
                      account.net_balance_summary({('a', 'b'): 1.25, ('c', 'd'): 2}))
     self.assertEqual('80 units - trades [open [1, 2], 2 total, 0 wins, 0 losses]',
                      account.net_balance_summary({('a', 'b'): 0.5, ('c', 'd'): 1}))
     account.close_trade(2, 4)
     self.assertEqual('70 units - trades [open [1], 2 total, 0 wins, 1 losses]',
                      account.net_balance_summary({('a', 'b'): 1}))
     account.close_trade(1, 1.5)
     self.assertEqual('90 units - trades [open [], 2 total, 1 wins, 1 losses]',
                      account.net_balance_summary({}))
Пример #6
0
 def test_auto_close_trade(self):
     account = Account(100)
     account.open_trade(('a', 'b'), 1, Trade.TYPE_BUY, 30)
     account.open_trade(('a', 'b'), 1, Trade.TYPE_BUY, 30, 1.25, 0.75)
     account.open_trade(('c', 'd'), 1, Trade.TYPE_SELL, 30, 0.5, 1.5)
     self.assertEqual([], account.auto_close_trades({('a', 'b'): 1, ('c', 'd'): 1}))
     self.assertEqual(3, len(account.trades_list))
     self.assertEqual([], account.auto_close_trades({('a', 'b'): 1.2, ('c', 'd'): 0.7}))
     self.assertEqual(3, len(account.trades_list))
     self.assertEqual([(2, 'profit'), (3, 'loss')], account.auto_close_trades({('a', 'b'): 1.3, ('c', 'd'): 1.75}))
     self.assertEqual(1, len(account.trades_list))
Пример #7
0
 def test_not_enough_balance(self):
     account = Account(100)
     with self.assertRaises(RuntimeError):
         account.open_trade(('a', 'b'), 1, Trade.TYPE_BUY, 200)
     self.assertEqual(100, account.balance)
     self.assertEqual(0, len(account.trades_list))