Example #1
0
 def notify(self):
     if self._notify:
         logger.debug('{}, {}, {}, {} @ {}, lots: {}, execute: {}'.format(
             self.order_event.date, self.order_event.instrument,
             self.order_event.order_type, self.order_event.status,
             self.order_event.price, self.order_event.lots,
             self.order_event.execute_type))
Example #2
0
 def start(self):
     self.notify()
     if self.check_before():
         self.change_status('SUBMITTED')
         self.notify()
     else:
         logger.debug('现金不够,本次交易取消')
Example #3
0
 def next(self):
     # if not self.skipped:
     #     self.skipped = True
     #     return
     self.__update_bar()
     market_event = Context().MarketEvent
     events.put(market_event(self))
     logger.debug('---------------------feedbase.next--------------------')
Example #4
0
 def simple_moving_average(self, period, index=-1):
     close = self.get_preload(period, index, 'close')
     logger.debug('---close in sma---: {}'.format(close))
     sma_close = talib.SMA(close, period)  # 返回array,period个数前计算会得到nan,需处理
     if np.isnan(sma_close[index]):
         raise Warning
     else:
         return sma_close[index]
Example #5
0
 def __combine_all_feed(self):
     """只运行一次,创建一个空Bar,然后将所有feed都整合到一起"""
     self.bar = Bar('')
     self.bar._initialize()
     for feed in self.feed_list:
         logger.debug('feed.bar.total_dict in main: {}'.format(
             feed.bar.total_dict))
         self.bar._combine_all_feed(feed.bar.total_dict)
Example #6
0
 def __set_date(self):
     """将输入的日期转换成datetime对象"""
     if self.startdate:
         # logger.debug('self.startdate: {}'.format(self.startdate))  # 转换前
         self.startdate = datetime.strptime(self.startdate, "%Y-%m-%d")
         logger.debug('self.startdate: {}'.format(self.startdate))  # 转换后
     if self.enddate:
         # logger.debug('self.enddate: {}'.format(self.enddate))  # 转换前
         self.enddate = datetime.strptime(self.enddate, "%Y-%m-%d")
         logger.debug("self.enddate: {}".format(self.enddate))  # 转换后
Example #7
0
 def test_get_trade_bars(self):
     op = analysis._true_func
     lenth_bar1 = analysis._get_trade_bars(ohlc_data, trade_log, op)
     self.assertEquals(lenth_bar1, [19, 9, 3, 2, 8, 5])
     logger.info('trade_log: ', trade_log)
     trade_log1 = trade_log.drop([0, 1]).reset_index(drop=True)
     logger.debug('----------------------------------')
     logger.debug('trade_log: ', trade_log1)
     lenth_bar2 = analysis._get_trade_bars(ohlc_data, trade_log1, op)
     self.assertEquals(lenth_bar2, [9, 3, 2, 8, 5])
Example #8
0
        def _update():
            bar = next(self._iteration_buffer)  # 每次读取一组数据
            logger.debug('bar: {}'.format(bar))
            bar['time'] = self.__set_bar_date(bar)

            for i in bar:
                try:
                    bar[i] = float(bar[i])
                except ValueError:
                    pass
            return bar
Example #9
0
 def update_cash(self, fill_event):
     """
     更新现金,现金 = 资产余额 - 本次已缴纳的保证金
     """
     cur_equity = self.equity[-1]
     # total_margin = self.margin.total()
     margin = self.margin[-1]
     # cash = cur_equity - total_margin
     cash = cur_equity - margin
     logger.debug('fill_event.date, cash: {} {}'.format(fill_event.date, cash))
     logger.debug('cash in date: {} {}'.format(cash, fill_event.date))
     self.cash.add(fill_event.date, cash)
Example #10
0
 def get_basic_data(self, period, ohlc='close'):
     """
     获取基础的数据,如 open, high, low, close 等,
     最后取得一个列表,长度为period,
     period为 1 表示当前bar的数据
     """
     if len(self.bar_list) < period:
         raise IndexError
     data_list = self.bar_list[-period:]
     logger.debug('len(data_list): {}'.format(len(data_list)))
     data = [i[ohlc] for i in data_list]
     return np.array(data)
Example #11
0
 def __update_time_index(self):
     """每次更新行情后,根据新行情更新仓位、现金、保证金等账户基本信息"""
     self.fill.update_time_index(self.feed_list)
     logger.debug('len(self.feed_list) in main: {}'.format(
         len(self.feed_list)))
     logger.debug('self.feed_list in main: {}'.format(self.feed_list))
     date_dict = {}
     if len(self.feed_list) > 1:
         for index, feed in enumerate(self.feed_list):
             date_dict[str(index)] = feed.cur_bar.cur_date
             if self.feed_list.count(feed) > 1:
                 raise SyntaxError('行情中出现了相同的日期,数据有误')
Example #12
0
 def set_dataseries_instrument(self, instrument):
     self.position.set_instrument(instrument)
     self.margin.set_instrument(instrument)
     self.commission.set_instrument(instrument)
     self.long_commission.set_instrument(instrument)
     self.short_commission.set_instrument(instrument)
     self.avg_price.set_instrument(instrument)
     self.realized_gain_and_loss.set_instrument(instrument)
     self.long_realized_gain_and_loss.set_instrument(instrument)
     self.short_realized_gain_and_loss.set_instrument(instrument)
     logger.debug('realized_gain_and_loss in set_dataseries_instrument: {}'.format(self.realized_gain_and_loss.list))
     self.unrealized_gain_and_loss.set_instrument(instrument)
Example #13
0
 def __init__(self, feed):
     self.type = 'Market'
     self.feed = feed
     self.instrument = feed.instrument
     self.cur_bar = feed.cur_bar
     self.bar = feed.bar
     # logger.debug('self.bar.open[:] in event: {}'.format(self.bar.open[:]))
     self.per_comm = feed.per_comm
     self.per_margin = feed.per_margin
     self.units = feed.units
     self.execute_mode = feed.execute_mode
     self.slippage = feed.slippage
     logger.debug('---slippage in event---:{}'.format(self.slippage))
Example #14
0
 def update_position(self, fill_event):
     """
     更新仓位
     如果最后一个仓位的执行类型为LIMIT或STOP,仓位不变,更新时间;
     否则,仓位更新,加上变更量,并更新时间
     """
     last_position = self.position[-1]
     if fill_event.execute_type in ['LIMIT', 'STOP']:
         position = last_position
     else:
         position = int(last_position + fill_event.lots * fill_event.direction)
     logger.debug('position in date: {} {}'.format(position, fill_event.date))
     self.position.add(fill_event.date, position)
Example #15
0
    def add_new_bar(self, new_bar):
        """不断更新当前行情数据"""

        bar_date = datetime.strptime(new_bar['time'], '%Y/%m/%d')
        logger.debug('---bar_date in barbase---: {}'.format(bar_date))
        # bar_list_length = len(self._cur_bar_list)
        logger.debug('self._cur_bar_list in barbase: {}'.format(
            self._cur_bar_list))
        # if bar_list_length == 2:
        #     # self._cur_bar_list.pop(0)
        #     self._cur_bar_list = []
        # elif bar_list_length == 1:
        #     if new_bar['time'] == self._cur_bar_list[0]['time']:
        #         self._cur_bar_list = []
        # self._cur_bar_list.append(new_bar)
        self._cur_bar_list[0] = new_bar
Example #16
0
 def get_ready(self):
     """准备数据,设置参数"""
     feed_list = self.context.feed_list
     strategy_list = self.context.strategy
     portfolio = Portfolio
     self.set_backtest(feed_list, strategy_list, portfolio)
     commission = self.context.commission
     margin = self.context.margin
     units = self.context.units
     lots = self.context.lots
     slippage = self.context.slippage
     logger.debug('---slippage in main---:{}'.format(slippage))
     instrument = self.context.instrument
     self.set_commission(commission, margin, units, lots, slippage,
                         instrument)
     self.set_cash(self.context.initial_cash)
Example #17
0
def dict_to_table(result_dict):
    # 计算传入字典的key的长度的最大值作为key展示列的宽度
    col_width_keys = max([len(key) for key in result_dict.keys()])
    # 计算传入字典的value的长度的最大值作为value展示列的宽度
    col_width_values = max([len(str(value)) for value in result_dict.values()])
    # 列表的头部和尾部用#---#展示
    header_footer = ('#--' + (col_width_keys + col_width_values + 2) * '-' +
                     '#')
    data_list = []
    for key, value in result_dict.items():
        data_list.append('| ' + '.......'.join([
            '{:{}}'.format(key, col_width_keys), '{:{}}'.format(
                value, col_width_values)
        ]) + ' \n')

    table_str = '{}\n{}{}'.format(header_footer, ''.join(data_list),
                                  header_footer)
    logger.debug('table_str: {}'.format(table_str))
    return table_str
Example #18
0
 def max_high(self, period: int, index=0):
     """
     获取 period 个周期内的最高价,
     1 表示当前周期,2 表示上一周期到当前周期,类推,
     index 为 0 表示 period - 1 日前到当日的最高价,即 period 个周期内的最高价,
     index 为 1 表示 period 日前到昨日的最高价,也是 period 个周期内的最高价,
     index 是为比较函数 cross_up 和 cross_down 设置的
     """
     logger.debug('period, index : {} {}'.format(period, index))
     if index not in [0, 1]:
         logger.warning(
             'index must be 0 or 1, please choose the right index')
         logger.info('index set to 0 by default')
         index = 0
     if not index:
         high = self.get_basic_data(period, ohlc='high')
     if index == 1:
         high = self.get_basic_data(period + 1, ohlc='high')[:-1]
     return max(high)
Example #19
0
    def preload(self):
        self.set_iteration_buffer(self.load_data())

        def _update():
            bar = next(self._iteration_buffer)  # 每次读取一组数据
            logger.debug('bar: {}'.format(bar))
            bar['time'] = self.__set_bar_date(bar)

            for i in bar:
                try:
                    bar[i] = float(bar[i])
                except ValueError:
                    pass
            return bar

        try:
            bar = _update()
            self.preload_bar_list.append(bar)  # 添加第一个数据
            self.preload_bar_list.append(bar)  # 添加第一个数据
            logger.debug('barr: {}'.format(bar))
            new_bar_date = datetime.strptime(bar['time'],
                                             self.date_format)
            if self.startdate:
                while new_bar_date < self.startdate:
                    bar = _update()
                    self.preload_bar_list.append(bar)
                # else:
                    # self.preload_bar_list.pop(-1)  # 经过验证bug检查的,最后删除掉一个重复(暂未证实)

            elif self.startdate is None:
                pass
            else:
                raise SyntaxError("语法错误")

        except IndexError:
            pass

        except StopIteration:
            logger.debug("不可能的")

        self.preload_bar_list.reverse()
Example #20
0
    def __initialization(self):
        """对所有 feed 和 fill 内各项数据进行初始化"""
        logger.debug('feed_list in main initialization: {}'.format(
            self.feed_list))
        for feed in self.feed_list:
            feed.load_once()
            instrument = feed.instrument
            self.fill.position.initialize(instrument, 0)
            self.fill.margin.initialize(instrument, 0)
            self.fill.commission.initialize(instrument, 0)
            self.fill.long_commission.initialize(instrument, 0)
            self.fill.short_commission.initialize(instrument, 0)
            self.fill.avg_price.initialize(instrument, 0)
            self.fill.unrealized_gain_and_loss.initialize(instrument, 0)
            self.fill.realized_gain_and_loss.initialize(instrument, 0)
            self.fill.long_realized_gain_and_loss.initialize(instrument, 0)
            self.fill.short_realized_gain_and_loss.initialize(instrument, 0)
        self.fill.cash.initialize('all', self.fill.initial_cash)
        self.fill.equity.initialize('all', self.fill.initial_cash)

        self.__combine_all_feed()
Example #21
0
    def update_avg_price(self, fill_event):
        """
        更新均价
        """
        avg_price = self.avg_price[-1]
        last = self.position[-2]  # 上一个仓位
        cur = self.position[-1]  # 刚刚更新的仓位

        if cur == 0:  # 平仓了,
            avg_price = 0
        else:  # 未平仓
            if fill_event.execute_type in ['LIMIT', 'STOP']:
                pass
            # 上一次仓位为0,本次开仓,均价即为本次执行价
            elif last == 0:
                avg_price = fill_event.price
            # 上一次仓位为多头,即买入了仓位,当最新仓位仍为多头时,均价 = 总成交额 / 最新仓位
            # 当最新仓位为负时,即卖出平仓后又卖出开仓了,均价即为卖出的执行价
            elif last > 0:
                if fill_event.order_type == 'BUY':
                    avg_price = (last * avg_price + fill_event.units * fill_event.price) / cur
                if fill_event.order_type == 'SELL':
                    if cur > 0:
                        avg_price = (last * avg_price - fill_event.units * fill_event.price) / cur
                    elif cur < 0:
                        avg_price = fill_event.price
            # 上一次仓位为空头时,当最新仓位变为多头时,即买入平仓后又买入开仓了,
            # 均价即为买入的执行价;否则,均价 = 总成交额 / 最新仓位
            elif last < 0:
                if fill_event.order_type == 'BUY':
                    if cur > 0:
                        avg_price = fill_event.price
                    elif cur < 0:
                        avg_price = (-last * avg_price - fill_event.units * fill_event.price) / cur
                elif fill_event.order_type == 'SELL':
                    avg_price = (-last * avg_price + fill_event.units * fill_event.price) / cur
        logger.debug('avg_price in date in update_avg_price: {} {}'.format(avg_price, fill_event.date))
        self.avg_price.add(fill_event.date, avg_price)
Example #22
0
 def set_commission(self,
                    commission,
                    margin,
                    units,
                    lots,
                    slippage,
                    instrument=None):
     """
     设置手续费、保证金、合约单位及合约品种等参数
     commission:手续费,0.0003表示每手收取0.03%的手续费
     margin:保证金比例,通常为0.05-0.15
     units:合约单位,一般为吨/手
     lots:下单手数
     """
     for feed in self.feed_list:
         if feed.instrument == instrument or instrument is None:
             feed.set_per_comm(commission)
             feed.set_per_margin(margin)
             feed.set_units(units)
             feed.set_lots(lots)
             feed.set_slippage(slippage)
             logger.debug('---slippage in feed main---:{}'.format(
                 feed.slippage))
Example #23
0
    def __init__(self):
        # 设置默认初始资金,如果用户不更改,则用这个资金进行回测
        self.initial_cash = 100000

        self.position = dataseries.PositionSeries()  # 仓位
        self.margin = dataseries.MarginSeries()  # 保证金
        self.avg_price = dataseries.AvgPriceSeries()  # 均价
        self.commission = dataseries.CommissionSeries()  # 手续费
        self.long_commission = dataseries.LongCommissionSeries()  # 多头手续费
        self.short_commission = dataseries.ShortCommissionSeries()  # 空头手续费
        self.cash = dataseries.CashSeries()  # 现金
        # 平仓盈亏
        self.realized_gain_and_loss = dataseries.RealizedGainAndLossSeries()
        self.long_realized_gain_and_loss = dataseries.LongRealizedGainAndLossSeries()
        self.short_realized_gain_and_loss = dataseries.ShortRealizedGainAndLossSeries()
        logger.debug('realized_gain_and_loss in init: {}'.format(self.realized_gain_and_loss))
        # 浮动盈亏
        self.unrealized_gain_and_loss = dataseries.UnrealizedGainAndLossSeries()
        self.equity = dataseries.EquitySeries()  # 余额

        self._order_list = []
        self._trade_list = []
        self._completed_list = []
Example #24
0
    def __set_order_data(self):
        """初始化各项基本信息,并判断指令种类execute_type"""
        self._instrument = self._order_data.instrument
        self._direction = self._order_data.direction
        self._date = self._order_data.date
        self._lots = self._order_data.lots
        self._price = self._order_data.price
        logger.debug('self._price: {}'.format(self._price))
        self._take_profit = self._order_data.take_profit
        self._stop_loss = self._order_data.stop_loss
        self._trailing_stop = self._order_data.trailing_stop
        self._trailing_stop_calc = self._order_data.trailing_stop_calc

        execute_mode_price = self._order_data.execute_mode_price
        logger.debug('execute_mode_price: {}'.format(execute_mode_price))
        if self._execute_type == 'CLOSE_ALL':
            return
        elif self._price > execute_mode_price:
            self._execute_type = 'STOP' if self._order_type == 'BUY' else 'LIMIT'
        elif self._price < execute_mode_price:
            self._execute_type = 'LIMIT' if self._order_type == 'BUY' else 'STOP'
        elif self._price == execute_mode_price:
            self._execute_type = 'MARKET'
Example #25
0
 def close(self, period=1) -> list:
     """
     close(1)[0] 表示当前周期的close
     close(2)[0] 表示上一周期的close
     """
     close = self.get_basic_data(period, ohlc='close')
     logger.debug('type(close) :{}'.format(type(close)))
     logger.debug('close: {}'.format(close))
     logger.debug('close[0]: {}'.format(close[0]))
     return close
Example #26
0
 def add(self, date, value):
     logger.debug('self.old_date, date in add dataseries: {} {}'.format(
         self.old_date, date))
     if self.old_date != date:
         if self._dict[self._instrument][0]['date'] == 'start':
             self._dict[self._instrument] = []
         self._dict[self._instrument].append({
             'date': date,
             self._name: value
         })
         # logger.debug('self._dict in dataseries: {}'.format(self._dict))
         self.old_date = date
     else:
         logger.debug('self.old_date, date in add dataseries: {} {}'.format(
             self.old_date, date))
         logger.debug('date in dataseries.add: {}'.format(date))
         logger.debug('value in add: {}'.format(value))
         self._dict[self._instrument][-1][self._name] = value
Example #27
0
 def get_re_profit(trade_lots, trade_code):
     """计算平仓盈亏和手续费"""
     if trade_code == 1:  # 做多
         buy_price = f.price  # + 0.2 * 1
         sell_price = i.price  # - 0.2 * 1
     elif trade_code == 0:  # 做空
         buy_price = i.price  # + 0.2 * 1
         sell_price = f.price  # - 0.2 * 1
     # re_profit = np.round((f.price - i.price) * trade_lots * f.units * i.direction, 2)
     re_profit = np.round((sell_price - buy_price) * trade_lots * f.units, 2)
     logger.debug('re_profit: {} {} {} {} {} {}'.format(
         re_profit, f.price, i.price, trade_lots, f.units, i. direction))
     commission_ = np.round(f.units * f.price * f.per_comm * f.lots, 2)  # 平仓手续费
     # 单笔交易的手续费(即开仓手续费和平仓手续费之和)
     commission = commission_ + np.round(i.units * i.price * f.per_comm * i.lots, 2)
     re_profit_list.append(re_profit)
     # 加入累计的盈亏
     # self.realized_gain_and_loss.add(f.date, sum(re_profit_list))
     self.realized_gain_and_loss.add(f.date, re_profit)  # 记录每次盈亏
     logger.debug('---self.realized_gain_and_loss.add---: {} {}'.format(
         self.realized_gain_and_loss.list, self.realized_gain_and_loss.dict))
     if i.direction > 0:  # 多头平仓盈亏(含手续费)
         self.realized_gain_and_loss.long_poisition_re_profit.append(re_profit - commission)
         self.long_realized_gain_and_loss.add(f.date, re_profit - commission)
         self.long_commission.add(f.date, commission)
     else:  # 空头平仓盈亏(含手续费)
         self.realized_gain_and_loss.short_position_re_profit.append(re_profit - commission)
         self.short_realized_gain_and_loss.add(f.date, re_profit - commission)
         self.short_commission.add(f.date, commission)
     logger.debug('self.realized_gain_and_loss in backtestfill: {}'.format(
         self.realized_gain_and_loss))
     logger.debug('self.realized_gain_and_loss.date in backtestfill: {}'.format(
         self.realized_gain_and_loss.date))
     if len(self.realized_gain_and_loss.date) > 1:
         if self.realized_gain_and_loss.date[-2] is f.date:
             new_realized_g_l = (
                 self.realized_gain_and_loss[-1] + self.realized_gain_and_loss[-2])
             # self.realized_gain_and_loss.update_cur(new_realized_g_l)
             self.realized_gain_and_loss.add(date, new_realized_g_l)
             self.realized_gain_and_loss.del_last()
Example #28
0
    def run(self):
        """主循环"""
        self.__initialization()

        while True:
            try:
                event = events.get(False)  # 当 queue 为空时,raise queue.Empty
                logger.debug('events.qsize(): {}'.format(events.qsize()))
            except queue.Empty:
                self.__load_all_feed()  # 加载新行情
                logger.debug('self.__check_backtest_finished(): {}'.format(
                    self.__check_backtest_finished()))
                if not self.__check_backtest_finished():
                    # cur_bar中数据不足两条,不开始计算
                    if len(self.feed_list[-1].cur_bar._cur_bar_list) < 1:
                        # logger.debug('events.qsize(): {}'.format(events.qsize()))
                        continue
                    else:
                        self.__update_time_index()  # 更新基本信息
                        logger.debug(
                            'self.feed_list[-1].cur_bar.cur_date: {}'.format(
                                self.feed_list[-1].cur_bar.cur_date))
                        self.__check_pending_order()  # 检查订单是否成交

            else:
                if event.type == 'Market':
                    self.context.market_event.append(event)
                    self.__pass_to_market(event)  # 传递账户基本信息

                    for strategy in self.strategy_list:
                        strategy(event).run_strategy()

                elif event.type == 'Signal':
                    self.context.signal_event.append(event)
                    self.portfolio.run_portfolio(event)

                elif event.type == 'Order':
                    self.context.order_event.append(event)
                    self.broker.run_broker(event)

                elif event.type == 'Fill':
                    self.context.fill_event.append(event)
                    self.fill.run_fill(event)

                if self.__check_backtest_finished():
                    self.__output_summary()
                    break
Example #29
0
 def update_margin(self, fill_event):
     """
     更新保证金
     根据position确定,多头时保证金为正,空头时保证金为负
     暂时只考虑了期货,以当条bar的收盘价为当日结算价
     当日交易保证金 = 持仓均价 × 当日结束交易后的持仓总量 × 交易保证金比例
     """
     margin = 0
     cur_position = self.position[-1]
     avg_price = self.avg_price[-1]
     if fill_event.execute_type in ['LIMIT', 'STOP']:
         pass
     else:
         cur_close = fill_event.price
         logger.debug('cur_close 结算价 in date:{} in {}'.format(cur_close, fill_event.date))
         logger.debug('fill_event.execute_type in date:{} in {}'.format(fill_event.execute_type, fill_event.date))
         # margin = fill_event.per_margin * (
         #     cur_position * fill_event.mult * cur_close)
         logger.debug('fill_event.per_margin * cur_position * avg_price * fill_event.units: {}, {}, {}, {}'.format(
             fill_event.per_margin, cur_position, avg_price, fill_event.units))
         # 保证金不能为负,用持仓均价计算,不用当日结算价计算,保留两位小数
         margin = np.round(fill_event.per_margin * fill_event.units * avg_price * fill_event.lots, 2)
     logger.debug('margin in date: {} {}'.format(margin, fill_event.date))
     self.margin.add(fill_event.date, margin)
Example #30
0
 def find(self, dic):
     for key, value in dic.items():
         if key is 'func':
             pass
         if key is 'arg':  # value 是一个列表
             # logger.debug('lenth of value: {}'.format(value))
             for i in value:
                 logger.debug('i:', i)
                 if isinstance(i, int) or isinstance(i, float):
                     self._period.append(i)
                     logger.debug('append: {}'.format(i))
                     # continue
                 elif isinstance(i, dict):
                     self.find(i)  # 只要是字典,一定会返回一个值,否则报错
                     # continue
                 else:
                     self._period.append(0)
                     logger.debug('else: {}'.format(i))
     return max(self._period)