Exemple #1
0
 def update_bars(self):
     """get data from exchange"""
     if len(self.bars) < 10:
         self.bars = self.exchange.get_bars(self.settings.MINUTES_PER_BAR,
                                            0)
     else:
         new_bars = self.exchange.recent_bars(self.settings.MINUTES_PER_BAR,
                                              0)
         for b in reversed(new_bars):
             if b.tstamp < self.bars[0].tstamp:
                 continue
             elif b.tstamp == self.bars[0].tstamp:
                 # merge?
                 if b.subbars[-1].tstamp == self.bars[0].subbars[-1].tstamp:
                     b.bot_data = self.bars[
                         0].bot_data  # merge bot data to not loose it
                     self.bars[0] = b
                 else:
                     # merge!
                     first = self.bars[0].subbars[-1]
                     newBar = Bar(tstamp=b.tstamp,
                                  open=first.open,
                                  high=first.high,
                                  low=first.low,
                                  close=first.close,
                                  volume=first.volume,
                                  subbars=[first])
                     for sub in reversed(self.bars[0].subbars[:-1]):
                         if sub.tstamp < b.subbars[-1].tstamp:
                             newBar.add_subbar(sub)
                         else:
                             break
                     for sub in reversed(b.subbars):
                         if sub.tstamp > newBar.subbars[0].tstamp:
                             newBar.add_subbar(sub)
                         else:
                             continue
                     newBar.bot_data = self.bars[
                         0].bot_data  # merge bot data to not loose it
                     self.bars[0] = newBar
             else:  # b.tstamp > self.bars[0].tstamp
                 self.bars.insert(0, b)
     del self.bars[400:]
     for bar in self.bars[3:]:
         # remove minute data from older bars
         bar.subbars = []
Exemple #2
0
    def run(self):
        self.reset()
        self.logger.info("starting backtest with " + str(len(self.bars)) +
                         " bars and " + str(self.account.equity) + " equity")
        for i in range(self.bot.min_bars_needed(), len(self.bars)):
            if i == len(self.bars) - 1 or i < self.bot.min_bars_needed():
                continue  # ignore last bar and first x

            # slice bars. TODO: also slice intrabar to simulate tick
            self.current_bars = self.bars[-(i + 1):]
            # add one bar with 1 tick on open to show to bot that the old one is closed
            next_bar = self.bars[-i - 2]
            forming_bar = Bar(tstamp=next_bar.tstamp,
                              open=next_bar.open,
                              high=next_bar.open,
                              low=next_bar.open,
                              close=next_bar.open,
                              volume=0,
                              subbars=[])
            self.current_bars.insert(0, forming_bar)
            self.current_bars[0].did_change = True
            self.current_bars[1].did_change = True

            self.do_funding()
            # self.bot.on_tick(self.current_bars, self.account)
            for subbar in reversed(next_bar.subbars):
                # check open orders & update account
                self.handle_open_orders(subbar)
                open = len(self.account.open_orders)
                forming_bar.add_subbar(subbar)
                self.bot.on_tick(self.current_bars, self.account)
                if open != len(self.account.open_orders):
                    self.handle_open_orders(subbar)  # got new ones
                self.current_bars[1].did_change = False

            next_bar.bot_data = forming_bar.bot_data
            for b in self.current_bars:
                if b.did_change:
                    b.did_change = False
                else:
                    break  # no need to go further

        if self.account.open_position.quantity != 0:
            self.send_order(
                Order(orderId="endOfTest",
                      amount=-self.account.open_position.quantity))
            self.handle_open_orders(self.bars[0].subbars[-1])

        if len(self.bot.position_history) > 0:
            daysInPos = 0
            maxDays = 0
            minDays = self.bot.position_history[0].daysInPos() if len(
                self.bot.position_history) > 0 else 0
            for pos in self.bot.position_history:
                if pos.status != PositionStatus.CLOSED:
                    continue
                if pos.exit_tstamp is None:
                    pos.exit_tstamp = self.bars[0].tstamp
                daysInPos += pos.daysInPos()
                maxDays = max(maxDays, pos.daysInPos())
                minDays = min(minDays, pos.daysInPos())
            daysInPos /= len(self.bot.position_history)

            profit = self.account.equity - self.initialEquity
            uw_updates_per_day = 1440  # every minute
            total_days = (self.bars[0].tstamp -
                          self.bars[-1].tstamp) / (60 * 60 * 24)
            rel = profit / (self.maxDD if self.maxDD > 0 else 1)
            rel_per_year = rel / (total_days / 365)
            self.logger.info(
                "finished | closed pos: " +
                str(len(self.bot.position_history)) + " | open pos: " +
                str(len(self.bot.open_positions)) + " | profit: " +
                ("%.2f" % (100 * profit / self.initialEquity)) + " | HH: " +
                ("%.2f" % (100 * (self.hh / self.initialEquity - 1))) +
                " | maxDD: " + ("%.2f" %
                                (100 * self.maxDD / self.initialEquity)) +
                " | maxExp: " + ("%.2f" %
                                 (self.maxExposure / self.initialEquity)) +
                " | rel: " + ("%.2f" % (rel_per_year)) + " | UW days: " +
                ("%.1f" % (self.max_underwater / uw_updates_per_day)) +
                " | pos days: " + ("%.1f/%.1f/%.1f" %
                                   (minDays, daysInPos, maxDays)))
        else:
            self.logger.info("finished with no trades")

        #self.write_results_to_files()
        return self