Esempio n. 1
0
class Single_bar:
    """
    用来生成单品种的K线
    
    """
    def __init__(self, strategy: StrategyTemplate, vt_symbol: str):
        """"""
        # 和portfolio的接口
        self.portfolio = strategy
        self.vt_symbol = vt_symbol

        # 需要合成的K线周期设置
        self.bar_interval = self.portfolio.bar_interval
        self.bar_frequency = self.portfolio.bar_frequency

        # K线合成工具和储存容器
        self.bg = BarGenerator(self.on_bar, self.bar_interval,
                               self.on_5min_bar, self.bar_frequency)
        self.am = ArrayManager()

        # K线合成计数
        self.bar_count = 0

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_5min_bar(self, bar: BarData):
        """"""
        self.bar_count += 1
        self.am.update_bar(bar)
Esempio n. 2
0
def draw_his(zscore_data, test_data):
    # RSRS标准分分布
    am = ArrayManager(200, zscore_data, 18)

    rsrs = []
    for bar in test_data:
        am.update_bar(bar)
        rsrs.append(am.rsrs_std())

    ser = pd.Series(rsrs)
    ser.hist(bins=50, color='b', edgecolor='gray', alpha=0.7, grid=False)
    plt.show()
Esempio n. 3
0
class MaSignal(CtaSignal):
    """"""
    def __init__(self, fast_window: int, slow_window: int):
        """"""
        super(MaSignal, self).__init__()

        self.fast_window = fast_window
        self.slow_window = slow_window

        self.bg = BarGenerator(self.on_bar, 5, self.on_5min_bar)
        self.am = ArrayManager()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_5min_bar(self, bar: BarData):
        """"""
        self.am.update_bar(bar)
        if not self.am.inited:
            self.set_signal_pos(0)

        fast_ma = self.am.sma("c", self.fast_window)
        slow_ma = self.am.sma("c", self.slow_window)

        if fast_ma > slow_ma:
            self.set_signal_pos(1)
        elif fast_ma < slow_ma:
            self.set_signal_pos(-1)
        else:
            self.set_signal_pos(0)
Esempio n. 4
0
class CciSignal(CtaSignal):
    """"""
    def __init__(self, cci_window: int, cci_level: float):
        """"""
        super(CciSignal, self).__init__()

        self.cci_window = cci_window
        self.cci_level = cci_level
        self.cci_long = self.cci_level
        self.cci_short = -self.cci_level

        self.bg = BarGenerator(self.on_bar)
        self.am = ArrayManager()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.am.update_bar(bar)
        if not self.am.inited:
            self.set_signal_pos(0)

        cci_value = self.am.cci(self.cci_window)

        if cci_value >= self.cci_long:
            self.set_signal_pos(1)
        elif cci_value <= self.cci_short:
            self.set_signal_pos(-1)
        else:
            self.set_signal_pos(0)
class MACDSignal:
    """"""
    def __init__(self, strategy: StrategyTemplate, vt_symbol: str):
        """"""

        self.portfolio = strategy
        self.vt_symbol = vt_symbol

        self.fast_period = self.portfolio.fast_period
        self.slow_period = self.portfolio.slow_period
        self.signal_period = self.portfolio.signal_period
        self.trailing_percent = self.portfolio.trailing_percent
        self.fixed_size = self.portfolio.fixed_size
        self.bar_interval = self.portfolio.bar_interval
        self.bar_frequency = self.portfolio.bar_frequency

        self.macd_value = 0
        self.intra_trade_high = 0
        self.intra_trade_low = 0

        self.bg = BarGenerator(self.on_bar, self.bar_interval,
                               self.on_5min_bar, self.bar_frequency)
        self.am = ArrayManager()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_5min_bar(self, bar: BarData):
        """"""
        self.am.update_bar(bar)

        if not self.am.inited:
            return

        self.portfolio.cancel_all()
        am = self.am
        macd, macd_signal, _ = am.macd(self.fast_period,
                                       self.slow_period,
                                       self.signal_period,
                                       array=True)

        long_trend = (macd[-2] < macd_signal[-2]) and (macd[-1] >
                                                       macd_signal[-1])
        short_trend = (macd[-2] > macd_signal[-2]) and (macd[-1] <
                                                        macd_signal[-1])

        symbol_pos = self.portfolio.get_pos(self.vt_symbol)
        if symbol_pos == 0:
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = bar.low_price

            if long_trend:

                open_order = self.portfolio.buy(self.vt_symbol,
                                                bar.close_price + 5,
                                                self.fixed_size)

            elif short_trend:

                open_order = self.portfolio.short(self.vt_symbol,
                                                  bar.close_price - 5,
                                                  self.fixed_size)

        elif symbol_pos > 0:

            self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
            self.intra_trade_low = bar.low_price

            long_stop = self.intra_trade_high * (1 -
                                                 self.trailing_percent / 100)
            # if bar.close_price <= long_stop:
            #     close_order = self.portfolio.sell(self.vt_symbol, bar.close_price - 5, abs(symbol_pos))
            #     self.limit_orders.append(close_order)
            if short_trend:

                close_order = self.portfolio.sell(self.vt_symbol,
                                                  bar.close_price - 5,
                                                  abs(symbol_pos))

        elif symbol_pos < 0:
            self.intra_trade_low = min(self.intra_trade_low, bar.low_price)
            self.intra_trade_high = bar.high_price

            short_stop = self.intra_trade_low * (1 +
                                                 self.trailing_percent / 100)
            # if bar.close_price >= short_stop:
            #     close_order = self.portfolio.cover(self.vt_symbol, bar.high_price + 5, abs(symbol_pos))
            #     self.limit_orders.append(close_order)
            if long_trend:
                close_order = self.portfolio.cover(self.vt_symbol,
                                                   bar.high_price + 5,
                                                   abs(symbol_pos))
Esempio n. 6
0
class RSICurveItem(ChartItem):
    name = 'rsi'
    plot_name = 'indicator'
    RSI_PARAMS = [6, 12, 24]
    RSI_COLORS = {
        6: pg.mkPen(color=(255, 255, 255), width=PEN_WIDTH),
        12: pg.mkPen(color=(255, 255, 0), width=PEN_WIDTH),
        24: pg.mkPen(color=(218, 112, 214), width=PEN_WIDTH)
    }

    def __init__(self, manager: BarManager):
        """"""
        super().__init__(manager)
        # self.periods = [6, 12, 24]
        self.init_setting()
        self._arrayManager = ArrayManager(150)
        self.rsis = defaultdict(dict)
        self.last_ix = 0
        self.br_max = -np.inf
        self.br_min = np.inf
        self.last_picture = QtGui.QPicture()

    def init_setting(self):
        setting = VISUAL_SETTING.get(self.name, {})
        self.RSI_PARAMS = setting.get('params', self.RSI_PARAMS)
        if 'pen' in setting:
            pen_settings = setting['pen']
            for p in self.RSI_PARAMS:
                self.RSI_COLORS[p] = pg.mkPen(**pen_settings[str(p)])

    def _draw_bar_picture(self, ix: int, bar: BarData) -> QtGui.QPicture:
        """"""
        # Create objects

        if ix <= self.last_ix:
            return self.last_picture

        pre_bar = self._manager.get_bar(ix - 1)

        if not pre_bar:
            return self.last_picture

        rsi_picture = QtGui.QPicture()
        self._arrayManager.update_bar(pre_bar)
        painter = QtGui.QPainter(rsi_picture)

        # Draw volume body
        for p in self.RSI_PARAMS:
            rsi_ = self._arrayManager.rsi(p, True)
            pre_rsi = rsi_[-2]
            rsi = rsi_[-1]
            self.rsis[p][ix - 1] = rsi
            if np.isnan(pre_rsi) or np.isnan(rsi):
                continue

            self.br_max = max(self.br_max, rsi_[-1])
            self.br_min = min(self.br_min, rsi_[-1])

            rsi_sp = QtCore.QPointF(ix - 2, rsi_[-2])
            rsi_ep = QtCore.QPointF(ix - 1, rsi_[-1])
            drawPath(painter, rsi_sp, rsi_ep, self.RSI_COLORS[p])

        # Finish
        painter.end()
        self.last_ix = ix
        self.last_picture = rsi_picture
        return rsi_picture

    def boundingRect(self) -> QtCore.QRectF:
        """"""
        rect = QtCore.QRectF(0, self.br_min, len(self._bar_picutures),
                             self.br_max - self.br_min)
        return rect

    def get_y_range(self,
                    min_ix: int = None,
                    max_ix: int = None) -> Tuple[float, float]:
        """
        Get range of y-axis with given x-axis range.

        If min_ix and max_ix not specified, then return range with whole data set.
        """
        min_ix = 0 if min_ix is None else min_ix
        max_ix = self.last_ix if max_ix is None else max_ix

        min_v = np.inf
        max_v = -np.inf

        p = self.RSI_PARAMS[0]
        for i in range(min_ix, max_ix):
            min_v = min(min_v, self.rsis[p].get(i, min_v),
                        self.rsis[p].get(i, min_v))
            max_v = max(max_v, self.rsis[p].get(i, max_v),
                        self.rsis[p].get(i, max_v))

        return min_v, max_v

    def get_info_text(self, ix: int) -> str:
        """
        Get information text to show by cursor.
        """
        text = '\n'.join(f'rsi{p}: {v.get(ix, np.nan):.2f}'
                         for p, v in self.rsis.items())
        return f"RSI \n{text}"

    def clear_all(self) -> None:
        """
        Clear all data in the item.
        """
        super().clear_all()
        self._arrayManager = ArrayManager(150)
        self.last_ix = 0
        self.last_picture = QtGui.QPicture()
        self.rsis = defaultdict(dict)
        self.br_max = -np.inf
        self.br_min = np.inf
Esempio n. 7
0
class MACurveItem(ChartItem):
    name = 'ma'
    plot_name = 'candle'
    MA_PARAMS = [5, 10, 20, 30, 60]
    MA_COLORS = {
        5: pg.mkPen(color=(255, 255, 255), width=PEN_WIDTH),
        10: pg.mkPen(color=(255, 255, 0), width=PEN_WIDTH),
        20: pg.mkPen(color=(218, 112, 214), width=PEN_WIDTH),
        30: pg.mkPen(color=(0, 255, 0), width=PEN_WIDTH),
        60: pg.mkPen(color=(64, 224, 208), width=PEN_WIDTH)
    }

    def __init__(self, manager: BarManager):
        """"""
        super().__init__(manager)
        # self.periods = [5, 10, 20, 30, 60]
        self.init_setting()
        self._arrayManager = ArrayManager(max(self.MA_PARAMS) + 1)
        self.mas = defaultdict(dict)
        self.last_ix = 0
        self.last_picture = QtGui.QPicture()

    def init_setting(self):
        setting = VISUAL_SETTING.get(self.name, {})
        self.MA_PARAMS = setting.get('params', self.MA_PARAMS)
        if 'pen' in setting:
            pen_settings = setting['pen']
            pen_colors = {}
            for p in self.MA_PARAMS:
                pen_colors[p] = pg.mkPen(**pen_settings[str(p)])
            self.MA_COLORS = pen_colors

    def _draw_bar_picture(self, ix: int, bar: BarData) -> QtGui.QPicture:
        """"""
        # Create objects

        if ix <= self.last_ix:
            return self.last_picture

        pre_bar = self._manager.get_bar(ix - 1)

        if not pre_bar:
            return self.last_picture

        ma_picture = QtGui.QPicture()
        self._arrayManager.update_bar(pre_bar)
        painter = QtGui.QPainter(ma_picture)

        # Draw volume body
        for p in self.MA_PARAMS:
            if self._arrayManager.close[-(p + 1)] == 0:
                self.mas[p][ix - 1] = np.nan
                continue

            sma = self._arrayManager.ma(p, True)
            pre_ma = sma[-2]
            ma = sma[-1]
            self.mas[p][ix - 1] = ma

            sp = QtCore.QPointF(ix - 2, pre_ma)
            ep = QtCore.QPointF(ix - 1, ma)
            drawPath(painter, sp, ep, self.MA_COLORS[p])

        # Finish
        painter.end()
        self.last_ix = ix
        self.last_picture = ma_picture
        return ma_picture

    def boundingRect(self) -> QtCore.QRectF:
        """"""
        min_price, max_price = self._manager.get_price_range()
        rect = QtCore.QRectF(0, min_price, len(self._bar_picutures),
                             max_price - min_price)
        return rect

    def get_y_range(self,
                    min_ix: int = None,
                    max_ix: int = None) -> Tuple[float, float]:
        """
        Get range of y-axis with given x-axis range.

        If min_ix and max_ix not specified, then return range with whole data set.
        """
        min_volume, max_volume = self._manager.get_price_range(min_ix, max_ix)
        return min_volume, max_volume

    def get_info_text(self, ix: int) -> str:
        """
        Get information text to show by cursor.
        """
        text = '\n'.join(f'ma{p}: {v.get(ix, np.nan):.2f}'
                         for p, v in self.mas.items())
        return f"MA \n{text}"

    def clear_all(self) -> None:
        """
        Clear all data in the item.
        """
        super().clear_all()
        self._arrayManager = ArrayManager(max(self.MA_PARAMS) + 1)
        self.mas = defaultdict(dict)
        self.last_ix = 0
        self.last_picture = QtGui.QPicture()
Esempio n. 8
0
class INCItem(ChartItem):
    name = 'inc'
    plot_name = 'indicator'
    INC_PARAMS = [60, 2]
    INC_COLORS = {
        'up': pg.mkPen(color=(0, 0, 255), width=PEN_WIDTH),
        'inc': {
            'up_gte': pg.mkBrush(color=(255, 0, 0)),
            'up_lt': pg.mkBrush(color=(160, 32, 240)),
            'down_gte': pg.mkBrush(color=(0, 255, 0)),
            'down_lt': pg.mkBrush(color=(0, 255, 255))
        },
        'down': pg.mkPen(color=(255, 255, 0), width=PEN_WIDTH)
    }

    def __init__(self, manager: BarManager):
        """"""
        super().__init__(manager)
        self.init_setting()
        self._arrayManager = ArrayManager(150)
        self.last_ix = 0
        self.last_picture = QtGui.QPicture()
        self.incs = defaultdict(dict)
        self.br_max = 0
        self.br_min = 0

    def init_setting(self):
        setting = VISUAL_SETTING.get(self.name, {})
        self.INC_PARAMS = setting.get('params', self.INC_PARAMS)
        if 'pen' in setting:
            pen_settings = setting['pen']
            self.INC_COLORS['up'] = pg.mkPen(**pen_settings['up'])
            self.INC_COLORS['down'] = pg.mkPen(**pen_settings['down'])

        if 'brush' in setting:
            brush_settings = setting['brush']
            self.INC_COLORS['inc'] = {
                'up_gte': pg.mkBrush(**brush_settings['up_gte']),
                'up_lt': pg.mkBrush(**brush_settings['up_lt']),
                'down_gte': pg.mkBrush(**brush_settings['down_gte']),
                'down_lt': pg.mkBrush(**brush_settings['down_lt'])
            }

    def _draw_bar_picture(self, ix: int, bar: BarData) -> QtGui.QPicture:
        """"""
        # Create objects
        if ix <= self.last_ix:
            return self.last_picture

        pre_bar = self._manager.get_bar(ix - 1)

        if not pre_bar:
            return self.last_picture

        inc_picture = QtGui.QPicture()
        self._arrayManager.update_bar(pre_bar)
        painter = QtGui.QPainter(inc_picture)

        inc = self._arrayManager.close - self._arrayManager.open
        std = talib.STDDEV(inc, self.INC_PARAMS[0])
        multiple = inc / std

        # diff, dea, macd = self._arrayManager.macd(*self.MACD_PARAMS, array=True)
        self.br_max = max(self.br_max, std[-1], inc[-1])
        self.br_min = min(self.br_min, -std[-1], inc[-1])
        self.incs['up'][ix - 1] = std[-1]
        self.incs['inc'][ix - 1] = inc[-1]
        self.incs['down'][ix - 1] = -std[-1]
        self.incs['multiple'][ix - 1] = multiple[-1]
        if not (np.isnan(std[-2] * std[-1] * inc[-2] * inc[-1])):
            multiple_bar = QtCore.QRectF(ix - 1 - BAR_WIDTH, 0, BAR_WIDTH * 2,
                                         inc[-1])
            painter.setPen(pg.mkPen(color=(255, 255, 255),
                                    width=PEN_WIDTH / 2))
            if multiple[-1] >= 0:
                ud = 'up'
            else:
                ud = 'down'
            if abs(multiple[-1]) >= self.INC_PARAMS[1]:
                cp = 'gte'
            else:
                cp = 'lt'
            painter.setBrush(self.INC_COLORS['inc'][f'{ud}_{cp}'])
            painter.drawRect(multiple_bar)

            up_sp = QtCore.QPointF(ix - 2, std[-2])
            up_ep = QtCore.QPointF(ix - 1, std[-1])
            drawPath(painter, up_sp, up_ep, self.INC_COLORS['up'])

            down_sp = QtCore.QPointF(ix - 2, -std[-2])
            down_ep = QtCore.QPointF(ix - 1, -std[-1])
            drawPath(painter, down_sp, down_ep, self.INC_COLORS['down'])

        # Finish
        painter.end()
        self.last_ix = ix
        self.last_picture = inc_picture
        return inc_picture

    def boundingRect(self) -> QtCore.QRectF:
        """"""
        rect = QtCore.QRectF(0, self.br_min, len(self._bar_picutures),
                             self.br_max - self.br_min)
        return rect

    def get_y_range(self,
                    min_ix: int = None,
                    max_ix: int = None) -> Tuple[float, float]:
        """
        Get range of y-axis with given x-axis range.

        If min_ix and max_ix not specified, then return range with whole data set.
        """
        min_ix = 0 if min_ix is None else min_ix
        max_ix = self.last_ix if max_ix is None else max_ix

        min_v = 0
        max_v = 0

        for i in range(min_ix, max_ix):
            min_v = min(min_v, self.incs['down'].get(i, min_v),
                        self.incs['inc'].get(i, min_v))
            max_v = max(max_v, self.incs['up'].get(i, max_v),
                        self.incs['inc'].get(i, max_v))

        return min_v, max_v

    def get_info_text(self, ix: int) -> str:
        """
        Get information text to show by cursor.
        """
        return f"INC{self.INC_PARAMS}  UP:{self.incs['up'].get(ix, np.nan):.2f} DOWN:{self.incs['down'].get(ix, np.nan):.2f} INC:{self.incs['inc'].get(ix, np.nan):.2f} MUTIPLE:{self.incs['multiple'].get(ix, np.nan):.2f}"

    def clear_all(self) -> None:
        """
        Clear all data in the item.
        """
        super().clear_all()
        self._arrayManager = ArrayManager(150)
        self.last_ix = 0
        self.last_picture = QtGui.QPicture()
        self.incs = defaultdict(dict)
        self.br_max = 0
        self.br_min = 0
Esempio n. 9
0
class MACDItem(ChartItem):
    name = 'macd'
    plot_name = 'indicator'
    MACD_PARAMS = [12, 26, 9]
    MACD_COLORS = {
        'diff': pg.mkPen(color=(255, 255, 255), width=PEN_WIDTH),
        'dea': pg.mkPen(color=(255, 255, 0), width=PEN_WIDTH),
        'macd': {
            'up': pg.mkBrush(color=(255, 0, 0)),
            'down': pg.mkBrush(color=(0, 255, 50))
        }
    }

    def __init__(self, manager: BarManager):
        """"""
        super().__init__(manager)
        self.init_setting()
        self._arrayManager = ArrayManager(150)
        self.last_ix = 0
        self.last_picture = QtGui.QPicture()
        self.macds = defaultdict(dict)
        self.br_max = 0
        self.br_min = 0

    def init_setting(self):
        setting = VISUAL_SETTING.get(self.name, {})
        self.MACD_PARAMS = setting.get('params', self.MACD_PARAMS)
        if 'pen' in setting:
            pen_settings = setting['pen']
            self.MACD_COLORS['diff'] = pg.mkPen(**pen_settings['diff'])
            self.MACD_COLORS['dea'] = pg.mkPen(**pen_settings['dea'])

        if 'brush' in setting:
            brush_settings = setting['brush']
            self.MACD_COLORS['macd'] = {
                'up': pg.mkBrush(**brush_settings['macd']['up']),
                'down': pg.mkBrush(**brush_settings['macd']['down'])
            }

    def _draw_bar_picture(self, ix: int, bar: BarData) -> QtGui.QPicture:
        """"""
        # Create objects
        if ix <= self.last_ix:
            return self.last_picture

        pre_bar = self._manager.get_bar(ix - 1)

        if not pre_bar:
            return self.last_picture

        macd_picture = QtGui.QPicture()
        self._arrayManager.update_bar(pre_bar)
        painter = QtGui.QPainter(macd_picture)

        diff, dea, macd = self._arrayManager.macd(*self.MACD_PARAMS,
                                                  array=True)
        self.br_max = max(self.br_max, diff[-1], dea[-1], macd[-1])
        self.br_min = min(self.br_min, diff[-1], dea[-1], macd[-1])
        self.macds['diff'][ix - 1] = diff[-1]
        self.macds['dea'][ix - 1] = dea[-1]
        self.macds['macd'][ix - 1] = macd[-1]
        if not (np.isnan(diff[-2]) or np.isnan(dea[-2]) or np.isnan(macd[-1])):
            macd_bar = QtCore.QRectF(ix - 1 - BAR_WIDTH, 0, BAR_WIDTH * 2,
                                     macd[-1])
            painter.setPen(pg.mkPen(color=(255, 255, 255), width=PEN_WIDTH))
            if macd[-1] > 0:
                painter.setBrush(self.MACD_COLORS['macd']['up'])
            else:
                painter.setBrush(self.MACD_COLORS['macd']['down'])
            painter.drawRect(macd_bar)

            diff_sp = QtCore.QPointF(ix - 2, diff[-2])
            diff_ep = QtCore.QPointF(ix - 1, diff[-1])
            drawPath(painter, diff_sp, diff_ep, self.MACD_COLORS['diff'])

            dea_sp = QtCore.QPointF(ix - 2, dea[-2])
            dea_ep = QtCore.QPointF(ix - 1, dea[-1])
            drawPath(painter, dea_sp, dea_ep, self.MACD_COLORS['dea'])

        # Finish
        painter.end()
        self.last_ix = ix
        self.last_picture = macd_picture
        return macd_picture

    def boundingRect(self) -> QtCore.QRectF:
        """"""
        rect = QtCore.QRectF(0, self.br_min, len(self._bar_picutures),
                             self.br_max - self.br_min)
        return rect

    def get_y_range(self,
                    min_ix: int = None,
                    max_ix: int = None) -> Tuple[float, float]:
        """
        Get range of y-axis with given x-axis range.

        If min_ix and max_ix not specified, then return range with whole data set.
        """
        min_ix = 0 if min_ix is None else min_ix
        max_ix = self.last_ix if max_ix is None else max_ix

        min_v = 0
        max_v = 0

        for i in range(min_ix, max_ix):
            min_v = min(min_v, self.macds['diff'].get(i, min_v),
                        self.macds['dea'].get(i, min_v),
                        self.macds['macd'].get(i, min_v))
            max_v = max(max_v, self.macds['diff'].get(i, max_v),
                        self.macds['dea'].get(i, max_v),
                        self.macds['macd'].get(i, max_v))

        return min_v, max_v

    def get_info_text(self, ix: int) -> str:
        """
        Get information text to show by cursor.
        """
        return f"MACD{self.MACD_PARAMS}  DIFF:{self.macds['diff'].get(ix, np.nan):.2f} DEA:{self.macds['dea'].get(ix, np.nan):.2f} MACD:{self.macds['macd'].get(ix, np.nan):.2f}"

    def clear_all(self) -> None:
        """
        Clear all data in the item.
        """
        super().clear_all()
        self._arrayManager = ArrayManager(150)
        self.last_ix = 0
        self.last_picture = QtGui.QPicture()
        self.macds = defaultdict(dict)
        self.br_max = 0
        self.br_min = 0
Esempio n. 10
0
class TurtleSignal:
    """ 用于产生海龟策略交易信号,包括入场,止损,止盈委托价格与目标仓位 """

    def __init__(self, portfolio, vt_symbol,
                 entry_window, exit_window, atr_window,
                 profit_check=False):
        """Constructor, 初始化海龟信号的策略参数(默认不检查上一笔盈亏,默认缓存60根K线)"""
        self.portfolio = portfolio  # 投资组合

        self.vt_symbol = vt_symbol  # 合约代码
        self.entry_window = entry_window  # 入场通道周期数
        self.exit_window = exit_window  # 出场通道周期数
        self.atr_window = atr_window  # 计算ATR周期数
        self.profit_check = profit_check  # 是否检查上一笔盈利

        self.am = ArrayManager(60)  # K线容器

        self.atr_volatility = 0  # ATR波动率
        self.entry_up = 0  # 入场通道
        self.entry_down = 0
        self.exit_up = 0  # 出场通道
        self.exit_down = 0

        self.long_entry1 = 0  # 多头入场位
        self.long_entry2 = 0
        self.long_entry3 = 0
        self.long_entry4 = 0
        self.long_stop = 0  # 多头止损位

        self.short_entry1 = 0  # 空头入场位
        self.short_entry2 = 0
        self.short_entry3 = 0
        self.short_entry4 = 0
        self.short_stop = 0  # 空头止损位

        self.unit = 0  # 信号持仓
        self.result = None  # 当前的交易
        self.result_list = []  # 交易列表
        self.bar = None  # 最新K线

    def on_bar(self, bar):
        """ 缓存足够K线后,开始计算相关技术指标,判断交易信号 """
        self.bar = bar
        self.am.update_bar(bar)
        if not self.am.inited:
            return
        self.generate_signal(bar)
        self.calulate_indicator()

    def generate_signal(self, bar):
        """
        判断交易信号
        要注意在任何一个数据点:buy/sell/short/cover只允许执行一类动作

        负责交易信号的判断,平仓信号与开仓信号是分开的:优先检查平仓,没有仓位或者持有多头仓位的时候,在设置好入场位做多或加仓;
        没有仓位或者持有空头仓位的时候,在设置好入场位做空或者加仓
        """
        # 如果指标尚未初始化,则忽略
        # 在 calculate_indicator里面初始化,初始化的时候,所有long+short 1,2,3,4都计算完成且不会变了。
        if not self.long_entry1:
            return

        # 优先检查平仓
        if self.unit > 0:
            long_exit = max(self.long_stop, self.exit_down)

            if bar.low <= long_exit:
                self.sell(long_exit)
                return
        elif self.unit < 0:
            short_exit = min(self.short_stop, self.exit_up)
            if bar.high >= short_exit:
                self.cover(short_exit)
                return

        # 没有仓位或者持有多头仓位的时候,可以做多(加仓)
        if self.unit >= 0:
            trade = False

            if bar.high >= self.long_entry1 and self.unit < 1:
                self.buy(self.long_entry1, 1)
                trade = True

            if bar.high >= self.long_entry2 and self.unit < 2:
                self.buy(self.long_entry2, 1)
                trade = True

            if bar.high >= self.long_entry3 and self.unit < 3:
                self.buy(self.long_entry3, 1)
                trade = True

            if bar.high >= self.long_entry4 and self.unit < 4:
                self.buy(self.long_entry4, 1)
                trade = True

            if trade:
                return

        # 没有仓位或者持有空头仓位的时候,可以做空(加仓)
        if self.unit <= 0:
            if bar.low <= self.short_entry1 and self.unit > -1:
                self.short(self.short_entry1, 1)

            if bar.low <= self.short_entry2 and self.unit > -2:
                self.short(self.short_entry2, 1)

            if bar.low <= self.short_entry3 and self.unit > -3:
                self.short(self.short_entry3, 1)

            if bar.low <= self.short_entry4 and self.unit > -4:
                self.short(self.short_entry4, 1)

    def calculate_indicator(self):
        """ 计算技术指标
            负责计算指标的产生,包括计算入场和止盈离场的唐奇安通道上下轨,判断到有单位持仓后,
            计算ATR指标并且设定随后8个入场位置(做多4个和做空4个),同时初始化离场价格。
        """
        self.entry_up, self.entry_down = self.am.donchian(self.entry_window)
        self.exit_up, self.exit_down = self.am.donchian(self.exit_window)

        # 有持仓后,ATR波动率和入场位等都不再变化
        if not self.unit:
            self.atr_volatility = self.am.atr(self.atr_window)

            self.long_entry1 = self.entry_up
            self.long_entry2 = self.entry_up + self.atr_volatility * 0.5
            self.long_entry3 = self.entry_up + self.atr_volatility * 1
            self.long_entry4 = self.entry_up + self.atr_volatility * 1.5
            self.long_stop = 0  # 只有等第一笔买入时才能计算

            self.short_entry1 = self.entry_down
            self.short_entry2 = self.entry_down - self.atr_volatility * 0.5
            self.short_entry3 = self.entry_down - self.atr_volatility * 1
            self.short_entry4 = self.entry_down - self.atr_volatility * 1.5
            self.short_stop = 0 # 只有等第一笔卖出时才能计算

    def new_signal(self, direction, offset, price, volume):
        """ 定义海龟投资组合的发单委托,分别是多空方向、开仓平仓、停止单价格、合约手数。 """
        # ??? 最终的交易是在portfolio class 里完成的吗???
        self.portfolio.new_signal(self, direction, offset, price, volume)

    def buy(self, price, volume):
        """ 买入开仓;
            先传入计算好的停止单价格,缓存开仓委托的价格和手数,发出投资组合的多开委托,基于最后一次加仓价格计算止损离场位置。
            关键字:开仓 """
        price = self.calculate_trade_price(Direction.LONG, price)

        self.open(price, volume)
        self.new_signal(Direction.LONG, Offset.OPEN, price, volume)

        # 以最后一次加仓价格,加上两倍N计算止损
        self.long_stop = price - self.atr_volatility * 2

    def sell(self, price, volume):
        """ 卖出平仓;
            先传入计算好的停止单价格,缓存平仓委托的价格,发出投资组合空平的委托
            关键字:平仓 """
        price = self.calculate_trade_price(Direction.SHORT, price)
        volume = abs(self.unit)

        self.close(price)
        self.new_signal(Direction.SHORT, Offset.CLOSE, price, volume)

    def short(self, price, volume):
        """卖出开仓
            先传入计算好的停止单价格,缓存开仓委托的价格和手数,发出投资组合的空开委托,基于最后一次加仓价格计算止损离场位置。
            关键字:开仓 """
        price = self.calculate_trade_price(Direction.SHORT, price)

        self.open(price, -volume)
        self.new_signal(Direction.SHORT, Offset.OPEN, price, volume)

        # 以最后一次加仓价格,加上两倍N计算止损
        self.short_stop = price + self.atr_volatility * 2

    def cover(self, price, volume):
        """买入平仓;
            先传入计算好的停止单价格,缓存平仓委托的价格,发出投资组合多平的委托。
            关键字:平仓 """
        price = self.calculate_trade_price(Direction.LONG, price)
        volume = abs(self.unit)

        self.close(price)
        self.new_signal(Direction.LONG, Offset.CLOSE, price, volume)

    def open(self, price, change):
        """ 开仓
            计算累计开仓手数 / 单位头寸,调用TurtleResult类定义的open函数计算开仓平均成本。"""
        self.unit += change

        if not self.result:
            self.result = TurtleResult()
        self.result.open(price, change)

    def close(self, price):
        """平仓
            调用TurtleResult类定义的close函数计算单笔开平仓交易盈亏。创建列表专门缓存开平仓交易盈亏。"""
        self.unit = 0

        self.result.close(price)
        self.result_list.append(self.result)
        self.result = None

    def get_last_pnl(self):
        """ 获取上一笔交易的盈亏;
            在开平仓交易盈亏列表中获取上一笔交易的盈亏"""
        if not self.result_list:
            return 0

        result = self.result_list[-1]
        return result.pnl

    def calculate_trade_price(self, direction, price):
        """计算成交价格; 设置停止单价格,要求买入时,停止单成交的最优价格不能低于当前K线开盘价;
        卖出时,停止单成交的最优价格不能高于当前K线开盘价"""
        # 买入时,停止单成交的最优价格不能低于当前K线开盘价
        if direction == Direction.LONG:
            # ZL: 如果开盘的时候突破了通道,则只能以开盘的价格来成交
            # 这里关键字是:停止单
            trade_price = max(self.bar.open, price)
        # 卖出时,停止单成交的最优价格不能高于当前K线开盘价
        else:
            trade_price = min(self.bar.open, price)

        return trade_price
class StatisticalArbitrageStrategy(SpreadStrategyTemplate):
    """"""

    author = "用Python的交易员"

    boll_window = 20
    boll_dev = 2
    max_pos = 10
    payup = 10
    interval = 5

    spread_pos = 0.0
    boll_up = 0.0
    boll_down = 0.0
    boll_mid = 0.0

    parameters = ["boll_window", "boll_dev", "max_pos", "payup", "interval"]
    variables = ["spread_pos", "boll_up", "boll_down", "boll_mid"]

    def __init__(self, strategy_engine, strategy_name: str, spread: SpreadData,
                 setting: dict):
        """"""
        super().__init__(strategy_engine, strategy_name, spread, setting)

        self.bg = BarGenerator(self.on_spread_bar)
        self.am = ArrayManager()

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")

        self.load_bar(1)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

        self.put_event()

    def on_spread_data(self):
        """
        Callback when spread price is updated.
        """
        tick = self.get_spread_tick()
        self.on_spread_tick(tick)

    def on_spread_tick(self, tick: TickData):
        """
        Callback when new spread tick data is generated.
        """
        self.bg.update_tick(tick)

    def on_spread_bar(self, bar: BarData):
        """
        Callback when spread bar data is generated.
        """
        self.stop_all_algos()

        self.am.update_bar(bar)
        if not self.am.inited:
            return

        self.boll_mid = self.am.sma(self.boll_window)
        self.boll_up, self.boll_down = self.am.boll(self.boll_window,
                                                    self.boll_dev)

        if not self.spread_pos:
            if bar.close_price >= self.boll_up:
                self.start_short_algo(bar.close_price - 10,
                                      self.max_pos,
                                      payup=self.payup,
                                      interval=self.interval)
            elif bar.close_price <= self.boll_down:
                self.start_long_algo(bar.close_price + 10,
                                     self.max_pos,
                                     payup=self.payup,
                                     interval=self.interval)
        elif self.spread_pos < 0:
            if bar.close_price <= self.boll_mid:
                self.start_long_algo(bar.close_price + 10,
                                     abs(self.spread_pos),
                                     payup=self.payup,
                                     interval=self.interval)
        else:
            if bar.close_price >= self.boll_mid:
                self.start_short_algo(bar.close_price - 10,
                                      abs(self.spread_pos),
                                      payup=self.payup,
                                      interval=self.interval)

        self.put_event()

    def on_spread_pos(self):
        """
        Callback when spread position is updated.
        """
        self.spread_pos = self.get_spread_pos()
        self.put_event()

    def on_spread_algo(self, algo: SpreadAlgoTemplate):
        """
        Callback when algo status is updated.
        """
        pass

    def on_order(self, order: OrderData):
        """
        Callback when order status is updated.
        """
        pass

    def on_trade(self, trade: TradeData):
        """
        Callback when new trade data is received.
        """
        pass

    def stop_open_algos(self):
        """"""
        if self.buy_algoid:
            self.stop_algo(self.buy_algoid)

        if self.short_algoid:
            self.stop_algo(self.short_algoid)

    def stop_close_algos(self):
        """"""
        if self.sell_algoid:
            self.stop_algo(self.sell_algoid)

        if self.cover_algoid:
            self.stop_algo(self.cover_algoid)
Esempio n. 12
0
class StatisticalArbitrageGridStrategy(SpreadStrategyTemplate):
    """
    算法逻辑是在统计算法基础上增加加仓位逻辑
    """

    author = "yunya"

    boll_window = 60
    boll_dev = 4.0
    fixed_pos = 10
    max_pos = 4
    price_proportion = 2.0
    pay_up = 5
    increase_price = 0.0  # 超价
    interval = 5

    spread_pos = 0
    boll_up = 0
    boll_down = 0
    boll_mid = 0
    grid_count = 0
    buy_grid_count = 0
    short_grid_count = 0
    long_price = 0
    short_price = 0

    parameters = [
        "boll_window", "boll_dev", "fixed_pos", "max_pos", "price_proportion",
        "pay_up", "interval", "increase_price"
    ]
    variables = [
        "spread_pos",
        "boll_up",
        "boll_down",
        "boll_mid",
        "grid_count",
        "buy_grid_count",
        "short_grid_count",
        "long_price",
        "short_price",
    ]

    def __init__(self, strategy_engine, strategy_name: str, spread: SpreadData,
                 setting: dict):
        """"""
        super().__init__(strategy_engine, strategy_name, spread, setting)

        self.bg = BarGenerator(self.on_spread_bar)
        self.am = ArrayManager()

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(5)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")
        self.put_event()

    def on_spread_data(self):
        """
        Callback when spread price is updated.
        收到差价推送后,合成价差TICK数据
        """
        #这里的价差tick
        tick = self.get_spread_tick()
        self.on_spread_tick(tick)

    def on_spread_tick(self, tick: TickData):
        """
        Callback when new spread tick data is generated.
        """
        self.bg.update_tick(tick)

    def on_spread_bar(self, bar: BarData):
        """
        Callback when spread bar data is generated.
        """
        # 把老算法先停止,
        self.stop_all_algos()

        self.am.update_bar(bar)
        if not self.am.inited:
            return

        self.boll_mid = self.am.sma(self.boll_window)
        self.boll_up, self.boll_down = self.am.boll(self.boll_window,
                                                    self.boll_dev)

        if not self.spread_pos:
            if bar.close_price >= self.boll_up:
                self.start_short_algo(bar.close_price - self.increase_price,
                                      self.fixed_pos,
                                      payup=self.pay_up,
                                      interval=self.interval)
            elif bar.close_price <= self.boll_down:
                self.start_long_algo(bar.close_price + self.increase_price,
                                     self.fixed_pos,
                                     payup=self.pay_up,
                                     interval=self.interval)
        elif self.spread_pos < 0:
            if bar.close_price <= self.boll_mid:
                self.start_long_algo(bar.close_price + self.increase_price,
                                     abs(self.spread_pos),
                                     payup=self.pay_up,
                                     interval=self.interval)
                self.buy_grid_count = 0
            else:
                # 加仓
                grid_count = self.buy_grid_count < self.max_pos
                bar_change = bar.close_price > self.long_price * (
                    1 + self.price_proportion / 1000)

                if grid_count and bar_change:
                    if bar.close_price >= self.boll_up:
                        self.start_short_algo(bar.close_price -
                                              self.increase_price,
                                              self.fixed_pos,
                                              payup=self.pay_up,
                                              interval=self.interval)
        else:
            if bar.close_price >= self.boll_mid:
                self.start_short_algo(bar.close_price - self.increase_price,
                                      abs(self.spread_pos),
                                      payup=self.pay_up,
                                      interval=self.interval)
                self.short_grid_count = 0
            else:
                # 加仓
                grid_count = self.short_grid_count < self.max_pos
                bar_change = bar.close_price < self.short_price * (
                    1 - self.price_proportion / 1000)
                if grid_count and bar_change:
                    if bar.close_price <= self.boll_down:
                        self.start_long_algo(bar.close_price +
                                             self.increase_price,
                                             self.fixed_pos,
                                             payup=self.pay_up,
                                             interval=self.interval)

    def on_spread_pos(self):
        """
        Callback when spread position is updated.
        """
        self.spread_pos = self.get_spread_pos()
        self.put_event()

    def on_spread_algo(self, algo: SpreadAlgoTemplate):
        """
        Callback when algo status is updated.
        """
        pass

    def on_order(self, order: OrderData):
        """
        Callback when order status is updated.
        """
        if order.status == Status.ALLTRADED:
            if order.direction == Direction.LONG:
                self.buy_grid_count += 1
            else:
                self.short_grid_count += 1

    def on_trade(self, trade: TradeData):
        """
        Callback when new trade data is received.
        """
        if trade.direction == Direction.LONG:
            self.long_price = trade.price
        else:
            self.short_price = trade.price
Esempio n. 13
0
class StatisticalArbitrageStrategy(SpreadStrategyTemplate):
    """"""

    author = "用Python的交易员"

    open_window = 1
    boll_window = 40
    boll_dev = 4.9
    fixed_pos = 10
    payup = 10.0
    increase_price = 0.0  # 超价
    interval = 5

    spread_pos = 0.0
    boll_up = 0.0
    boll_down = 0.0
    boll_mid = 0.0

    parameters = [
        "boll_window", "boll_dev", "fixed_pos", "payup", "interval",
        "increase_price"
    ]
    variables = ["spread_pos", "boll_up", "boll_down", "boll_mid"]

    def __init__(self, strategy_engine, strategy_name: str, spread: SpreadData,
                 setting: dict):
        """"""
        super().__init__(strategy_engine, strategy_name, spread, setting)

        self.bg = BarGenerator(self.on_open_spread_bar, self.open_window,
                               self.on_open_spread_bar)
        self.am = ArrayManager()

        self.spread_pos = 0.0
        self.boll_up = 0.0
        self.boll_down = 0.0
        self.boll_mid = 0.0

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(10)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

        self.put_event()

    def on_spread_data(self):
        """
        Callback when spread price is updated.
        收到差价推送后,合成价差TICK数据
        """
        #这里的价差tick
        tick = self.get_spread_tick()
        self.on_spread_tick(tick)

    def on_spread_tick(self, tick: TickData):
        """
        Callback when new spread tick data is generated.
        """
        self.bg.update_tick(tick)

    def on_spread_bar(self, bar: BarData):
        """
        Callback when new spread bar data is generated.
        """
        self.bg.update_bar(bar)

    def on_open_spread_bar(self, bar: BarData):
        """
        Callback when spread bar data is generated.

        目前的策略逻辑:
        1、当价差价格大于布林上轨,以当前收盘加低10的价格下单(以市价下单保证成交),当价格跌破中轨时平仓 (做空)
        2、当价差价格小于布林下轨,以当前收盘价加10的价格下单,当价格高于中轨时平仓 (做多)

        策略优化方向:
        1、把目前在分钟价差K线逻辑移到 tick逻辑中实盘,增加细腻度
        2、仓位分为四次加减仓,第一次上穿时,开一份,第二次上穿的价格要高于第一次一定比较时,开第二份,一直到满四份。
        (这两个参数,一个是份数,一个是跨度(格距)),目的解决如果出现单边短时趋势抗单时爆仓(最后都会回归中轨)
        3、回到中轨全部平仓位

        """
        # 把老算法先停止,
        self.stop_all_algos()

        self.am.update_bar(bar)

        if not self.am.inited:
            return

        self.boll_mid = self.am.sma(self.boll_window)
        self.boll_up, self.boll_down = self.am.boll(self.boll_window,
                                                    self.boll_dev)

        if not self.spread_pos:
            if bar.close_price >= self.boll_up:
                self.start_short_algo(bar.close_price - self.increase_price,
                                      self.fixed_pos,
                                      payup=self.payup,
                                      interval=self.interval)
            elif bar.close_price <= self.boll_down:
                self.start_long_algo(bar.close_price + self.increase_price,
                                     self.fixed_pos,
                                     payup=self.payup,
                                     interval=self.interval)
        elif self.spread_pos < 0:
            if bar.close_price <= self.boll_mid:
                self.start_long_algo(bar.close_price + self.increase_price,
                                     abs(self.spread_pos),
                                     payup=self.payup,
                                     interval=self.interval)
        else:
            if bar.close_price >= self.boll_mid:
                self.start_short_algo(bar.close_price - self.increase_price,
                                      abs(self.spread_pos),
                                      payup=self.payup,
                                      interval=self.interval)
        self.put_event()

    def on_spread_pos(self):
        """
        Callback when spread position is updated.
        """
        self.spread_pos = self.get_spread_pos()
        self.put_event()

    def on_spread_algo(self, algo: SpreadAlgoTemplate):
        """
        Callback when algo status is updated.
        """
        pass

    def on_order(self, order: OrderData):
        """
        Callback when order status is updated.
        """
        pass

    def on_trade(self, trade: TradeData):
        """
        Callback when new trade data is received.
        """
        pass
Esempio n. 14
0
class MultiTimeframeStrategy(CtaTemplate):
    """"""
    author = "中科云集"

    rsi_signal = 20
    rsi_window = 14
    fast_window = 5
    slow_window = 20
    fixed_size = 1

    rsi_value = 0
    rsi_long = 0
    rsi_short = 0
    fast_ma = 0
    slow_ma = 0
    ma_trend = 0

    parameters = [
        "rsi_signal", "rsi_window", "fast_window", "slow_window", "fixed_size"
    ]

    variables = [
        "rsi_value", "rsi_long", "rsi_short", "fast_ma", "slow_ma", "ma_trend"
    ]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super(MultiTimeframeStrategy, self).__init__(cta_engine, strategy_name,
                                                     vt_symbol, setting)

        self.rsi_long = 50 + self.rsi_signal
        self.rsi_short = 50 - self.rsi_signal

        self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar)
        self.am5 = ArrayManager()

        self.bg15 = BarGenerator(self.on_bar, 15, self.on_15min_bar)
        self.am15 = ArrayManager()

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(10)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg5.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg5.update_bar(bar)
        self.bg15.update_bar(bar)

    def on_5min_bar(self, bar: BarData):
        """"""
        self.cancel_all()

        self.am5.update_bar(bar)
        if not self.am5.inited:
            return

        if not self.ma_trend:
            return

        self.rsi_value = self.am5.rsi(self.rsi_window)

        if self.pos == 0:
            if self.ma_trend > 0 and self.rsi_value >= self.rsi_long:
                self.buy(bar.close_price + 5, self.fixed_size)
            elif self.ma_trend < 0 and self.rsi_value <= self.rsi_short:
                self.short(bar.close_price - 5, self.fixed_size)

        elif self.pos > 0:
            if self.ma_trend < 0 or self.rsi_value < 50:
                self.sell(bar.close_price - 5, abs(self.pos))

        elif self.pos < 0:
            if self.ma_trend > 0 or self.rsi_value > 50:
                self.cover(bar.close_price + 5, abs(self.pos))

        self.put_event()

    def on_15min_bar(self, bar: BarData):
        """"""
        self.am15.update_bar(bar)
        if not self.am15.inited:
            return

        self.fast_ma = self.am15.sma("c", self.fast_window)
        self.slow_ma = self.am15.sma("c", self.slow_window)

        if self.fast_ma > self.slow_ma:
            self.ma_trend = 1
        else:
            self.ma_trend = -1

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        pass

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
Esempio n. 15
0
class TurtleSignal(object):
    """海龟信号"""

    #----------------------------------------------------------------------
    def __init__(self, portfolio, vtSymbol, 
                 entryWindow, exitWindow, atrWindow,
                 profitCheck=False):
        """Constructor"""
        self.portfolio = portfolio      # 投资组合
        
        self.vtSymbol = vtSymbol        # 合约代码
        self.entryWindow = entryWindow  # 入场通道周期数
        self.exitWindow = exitWindow    # 出场通道周期数
        self.atrWindow = atrWindow      # 计算ATR周期数
        self.profitCheck = profitCheck  # 是否检查上一笔盈利
        
        self.am = ArrayManager(60)      # K线容器
        
        self.atrVolatility = 0          # ATR波动率
        self.entryUp = 0                # 入场通道
        self.entryDown = 0
        self.exitUp = 0                 # 出场通道
        self.exitDown = 0
        
        self.longEntry1 = 0             # 多头入场位
        self.longEntry2 = 0
        self.longEntry3 = 0
        self.longEntry4 = 0
        self.longStop = 0               # 多头止损位
        
        self.shortEntry1 = 0            # 空头入场位
        self.shortEntry2 = 0
        self.shortEntry3 = 0
        self.shortEntry4 = 0
        self.shortStop = 0              # 空头止损位
        
        self.unit = 0                   # 信号持仓
        self.result = None              # 当前的交易
        self.resultList = []            # 交易列表
        self.bar = None                 # 最新K线
        
    #----------------------------------------------------------------------
    def onBar(self, bar):
        """"""
        self.bar = bar
        self.am.update_bar(bar)
        if not self.am.inited:
            return
        
        self.generateSignal(bar)
        self.calculateIndicator()
        
    #----------------------------------------------------------------------
    def generateSignal(self, bar):
        """
        判断交易信号
        要注意在任何一个数据点:buy/sell/short/cover只允许执行一类动作
        """
        # 如果指标尚未初始化,则忽略
        if not self.longEntry1:
            return
        
        # 优先检查平仓
        if self.unit > 0:
            longExit = max(self.longStop, self.exitDown)
            
            if bar.low_price <= longExit:
                self.sell(longExit)
                return
        elif self.unit < 0:
            shortExit = min(self.shortStop, self.exitUp)
            if bar.high_price >= shortExit:
                self.cover(shortExit)
                return
        
        # 没有仓位或者持有多头仓位的时候,可以做多(加仓)
        if self.unit >= 0:
            trade = False
            
            if bar.high_price >= self.longEntry1 and self.unit < 1:
                self.buy(self.longEntry1, 1)
                trade = True
            
            if bar.high_price >= self.longEntry2 and self.unit < 2:
                self.buy(self.longEntry2, 1)
                trade = True
            
            if bar.high_price >= self.longEntry3 and self.unit < 3:
                self.buy(self.longEntry3, 1)
                trade = True
            
            if bar.high_price >= self.longEntry4 and self.unit < 4:
                self.buy(self.longEntry4, 1)
                trade = True
            
            if trade:
                return
            
        # 没有仓位或者持有空头仓位的时候,可以做空(加仓)
        if self.unit <= 0:
            if bar.low_price <= self.shortEntry1 and self.unit > -1:
                self.short(self.shortEntry1, 1)
            
            if bar.low_price <= self.shortEntry2 and self.unit > -2:
                self.short(self.shortEntry2, 1)
            
            if bar.low_price <= self.shortEntry3 and self.unit > -3:
                self.short(self.shortEntry3, 1)
            
            if bar.low_price <= self.shortEntry4 and self.unit > -4:
                self.short(self.shortEntry4, 1)
            
    #----------------------------------------------------------------------
    def calculateIndicator(self):
        """计算技术指标"""
        self.entryUp, self.entryDown = self.am.donchian(self.entryWindow)
        self.exitUp, self.exitDown = self.am.donchian(self.exitWindow)
        
        # 有持仓后,ATR波动率和入场位等都不再变化
        if not self.unit:
            self.atrVolatility = self.am.atr(self.atrWindow)
            
            self.longEntry1 = self.entryUp
            self.longEntry2 = self.entryUp + self.atrVolatility * 0.5
            self.longEntry3 = self.entryUp + self.atrVolatility * 1
            self.longEntry4 = self.entryUp + self.atrVolatility * 1.5
            self.longStop = 0
            
            self.shortEntry1 = self.entryDown
            self.shortEntry2 = self.entryDown - self.atrVolatility * 0.5
            self.shortEntry3 = self.entryDown - self.atrVolatility * 1
            self.shortEntry4 = self.entryDown - self.atrVolatility * 1.5
            self.shortStop = 0
        
    #----------------------------------------------------------------------
    def newSignal(self, direction, offset, price, volume):
        """"""
        self.portfolio.newSignal(self, direction, offset, price, volume)
    
    #----------------------------------------------------------------------
    def buy(self, price, volume):
        """买入开仓"""
        price = self.calculateTradePrice(Direction.LONG, price)
        
        self.open(price, volume)
        self.newSignal(Direction.LONG, Offset.OPEN, price, volume)
        
        # 以最后一次加仓价格,加上两倍N计算止损
        self.longStop = price - self.atrVolatility * 2
    
    #----------------------------------------------------------------------
    def sell(self, price):
        """卖出平仓"""
        price = self.calculateTradePrice(Direction.SHORT, price)
        volume = abs(self.unit)
        
        self.close(price)
        self.newSignal(Direction.SHORT, Offset.CLOSE, price, volume)
    
    #----------------------------------------------------------------------
    def short(self, price, volume):
        """卖出开仓"""
        price = self.calculateTradePrice(Direction.SHORT, price)
        
        self.open(price, -volume)
        self.newSignal(Direction.SHORT, Offset.OPEN, price, volume)
        
        # 以最后一次加仓价格,加上两倍N计算止损
        self.shortStop = price + self.atrVolatility * 2
    
    #----------------------------------------------------------------------
    def cover(self, price):
        """买入平仓"""
        price = self.calculateTradePrice(Direction.LONG, price)
        volume = abs(self.unit)
        
        self.close(price)
        self.newSignal(Direction.LONG, Offset.CLOSE, price, volume)

    #----------------------------------------------------------------------
    def open(self, price, change):
        """开仓"""
        self.unit += change 
        
        if not self.result:
            self.result = TurtleResult()
        self.result.open(price, change)
    
    #----------------------------------------------------------------------
    def close(self, price):
        """平仓"""
        self.unit = 0
        
        self.result.close(price)
        self.resultList.append(self.result)
        self.result = None

    #----------------------------------------------------------------------
    def getLastPnl(self):
        """获取上一笔交易的盈亏"""
        if not self.resultList:
            return 0
        
        result = self.resultList[-1]
        return result.pnl
    
    #----------------------------------------------------------------------
    def calculateTradePrice(self, direction, price):
        """计算成交价格"""
        # 买入时,停止单成交的最优价格不能低于当前K线开盘价
        if direction == Direction.LONG:
            tradePrice = max(self.bar.open_price, price)
        # 卖出时,停止单成交的最优价格不能高于当前K线开盘价
        else:
            tradePrice = min(self.bar.open_price, price)
        
        return tradePrice
Esempio n. 16
0
class ExChartWidget(ChartWidget):
    """ 
    基于ChartWidget的K线图表 
    """

    EVENT_CTA_TICK = "eCtaTick"  # hxxjava add
    EVENT_CTA_HISTORY_BAR = "eCtaHistoryBar"  # hxxjava add
    EVENT_CTA_BAR = "eCtaBar"  # hxxjava add
    EVENT_CTA_ORDER = "eCtaOrder"  # hxxjava add
    EVENT_CTA_TRADE = "eCtaTrade"  # hxxjava add

    MIN_BAR_COUNT = 100

    signal_cta_history_bar: QtCore.pyqtSignal = QtCore.pyqtSignal(Event)
    signal_cta_tick: QtCore.pyqtSignal = QtCore.pyqtSignal(Event)
    signal_cta_bar: QtCore.pyqtSignal = QtCore.pyqtSignal(Event)

    def __init__(self,
                 parent: QtWidgets.QWidget = None,
                 event_engine: EventEngine = None,
                 strategy_name: str = ""):
        """ 初始化 """
        super().__init__(parent)
        self.strategy_name = strategy_name
        self.event_engine = event_engine
        self.am = ArrayManager(10000)

        # 创建K线主图及多个绘图部件
        self.add_plot("candle", hide_x_axis=True)
        self.add_item(ExCandleItem, "candle", "candle")
        self.add_item(LineItem, "line", "candle")
        self.add_item(SmaItem, "sma", "candle")
        self.add_item(SarItem, "sar", "candle")
        # self.add_item(OrderItem, "order", "candle")
        # self.add_item(TradeItem, "trade", "candle")

        # 创建成交量附图及绘图部件
        self.add_plot("volume", maximum_height=150)
        self.add_item(VolumeItem, "volume", "volume")

        # 创建RSI附图及绘图部件
        self.add_plot("rsi", maximum_height=150)
        self.add_item(RsiItem, "rsi", "rsi")

        # 创建MACD附图及绘图部件
        self.add_plot("macd", maximum_height=150)
        self.add_item(MacdItem, "macd", "macd")

        # 创建最新价格线、光标
        self.add_last_price_line()
        self.add_cursor()
        self.setWindowTitle(
            f"K线图表")  #——{symbol}.{exchange.value},{interval},{start}-{end}")

        # 委托单列表
        self.orders: List[str, OrderData] = {}
        # 成交单列表
        self.trades: List[str, TradeData] = {}

        # self.register_event()
        # self.event_engine.start()

    def register_event(self) -> None:
        """"""
        if self.event_engine == None:
            return
        self.signal_cta_history_bar.connect(self.process_cta_history_bar)
        self.event_engine.register(self.EVENT_CTA_HISTORY_BAR,
                                   self.signal_cta_history_bar.emit)

        self.signal_cta_tick.connect(self.process_tick_event)
        self.event_engine.register(self.EVENT_CTA_TICK,
                                   self.signal_cta_tick.emit)

        self.signal_cta_bar.connect(self.process_cta_bar)
        self.event_engine.register(self.EVENT_CTA_BAR,
                                   self.signal_cta_bar.emit)

    def process_cta_history_bar(self, event: Event) -> None:
        """ 处理历史K线推送 """
        strategy_name, history_bars = event.data
        if strategy_name == self.strategy_name:
            self.update_history(history_bars)

            # print(f" {strategy_name} got an EVENT_CTA_HISTORY_BAR")

    def process_tick_event(self, event: Event) -> None:
        """ 处理tick数据推送 """
        strategy_name, tick = event.data
        if strategy_name == self.strategy_name:
            if self.last_price_line:
                self.last_price_line.setValue(tick.last_price)
            #print(f" {strategy_name} got an EVENT_CTA_TICK")

    def process_cta_bar(self, event: Event) -> None:
        """ 处理K线数据推送 """

        strategy_name, bar = event.data
        if strategy_name == self.strategy_name:
            self.update_bar(bar)
            # print(f"{strategy_name} got an EVENT_CTA_BAR")

    def add_last_price_line(self):
        """"""
        plot = list(self._plots.values())[0]
        color = (255, 255, 255)

        self.last_price_line = pg.InfiniteLine(angle=0,
                                               movable=False,
                                               label="{value:.1f}",
                                               pen=pg.mkPen(color, width=1),
                                               labelOpts={
                                                   "color": color,
                                                   "position": 1,
                                                   "anchors": [(1, 1), (1, 1)]
                                               })
        self.last_price_line.label.setFont(NORMAL_FONT)
        plot.addItem(self.last_price_line)

    def update_history(self, history: List[BarData]) -> None:
        """
        Update a list of bar data.
        """
        self._manager.update_history(history)
        # Put all new bars into dict
        self.am.__init__(self.am.size)
        for bar in self._manager.get_all_bars():
            self.am.update_bar(bar)

        for item in self._items.values():
            item.update_history(history)

        self._update_plot_limits()

        self.move_to_right()

        self.update_last_price_line(history[-1])

    def update_bar(self, bar: BarData) -> None:
        """
        Update single bar data.
        """
        self._manager.update_bar(bar)
        self.am.update_bar(bar)

        for item in self._items.values():
            item.update_bar(bar)

        self._update_plot_limits()

        if self._right_ix >= (self._manager.get_count() - self._bar_count / 2):
            self.move_to_right()

        self.update_last_price_line(bar)

    def update_last_price_line(self, bar: BarData) -> None:
        """"""
        if self.last_price_line:
            self.last_price_line.setValue(bar.close_price)

    def add_orders(self, orders: List[OrderData]) -> None:
        """ 
        增加委托单列表到委托单绘图部件 
        """
        for order in orders:
            self.orders[order.orderid] = order

        order_item: OrderItem = self.get_item('order')
        if order_item:
            order_item.add_orders(self.orders.values())

    def add_trades(self, trades: List[TradeData]) -> None:
        """ 
        增加成交单列表到委托单绘图部件 
        """
        for trade in trades:
            self.trades[trade.tradeid] = trade

        trade_item: TradeItem = self.get_item('trade')
        if trade_item:
            trade_item.add_trades(self.trades.values())

    def add_item(self, item_class: Type[ChartItem], item_name: str,
                 plot_name: str):
        """
        Add chart item.
        """
        if issubclass(item_class, ExChartItem):
            item = item_class(self._manager, self.am)
        else:
            item = item_class(self._manager)
        self._items[item_name] = item

        plot = self._plots.get(plot_name)
        plot.addItem(item)

        self._item_plot_map[item] = plot

    def clear_all(self) -> None:
        """
        Clear all data.
        """
        self._manager.clear_all()
        self.am.__init__(self.am.size)

        for item in self._items.values():
            item.clear_all()

        if self._cursor:
            self._cursor.clear_all()
Esempio n. 17
0
class TurtleSignalStrategy(CtaTemplate):
    """"""
    author = "中科云集"

    entry_window = 20
    exit_window = 10
    atr_window = 20
    fixed_size = 1

    entry_up = 0
    entry_down = 0
    exit_up = 0
    exit_down = 0
    atr_value = 0

    long_entry = 0
    short_entry = 0
    long_stop = 0
    short_stop = 0

    parameters = ["entry_window", "exit_window", "atr_window", "fixed_size"]
    variables = ["entry_up", "entry_down", "exit_up", "exit_down", "atr_value"]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super(TurtleSignalStrategy, self).__init__(cta_engine, strategy_name,
                                                   vt_symbol, setting)

        self.bg = BarGenerator(self.on_bar)
        self.am = ArrayManager()

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(20)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.cancel_all()

        self.am.update_bar(bar)
        if not self.am.inited:
            return

        self.entry_up, self.entry_down = self.am.donchian(self.entry_window)
        self.exit_up, self.exit_down = self.am.donchian(self.exit_window)

        if not self.pos:
            self.atr_value = self.am.atr(self.atr_window)

            self.long_entry = 0
            self.short_entry = 0
            self.long_stop = 0
            self.short_stop = 0

            self.send_buy_orders(self.entry_up)
            self.send_short_orders(self.entry_down)
        elif self.pos > 0:
            self.send_buy_orders(self.long_entry)

            sell_price = max(self.long_stop, self.exit_down)
            self.sell(sell_price, abs(self.pos), True)

        elif self.pos < 0:
            self.send_short_orders(self.short_entry)

            cover_price = min(self.short_stop, self.exit_up)
            self.cover(cover_price, abs(self.pos), True)

        self.put_event()

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        if trade.direction == Direction.LONG:
            self.long_entry = trade.price
            self.long_stop = self.long_entry - 2 * self.atr_value
        else:
            self.short_entry = trade.price
            self.short_stop = self.short_entry + 2 * self.atr_value

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        pass

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass

    def send_buy_orders(self, price):
        """"""
        t = self.pos / self.fixed_size

        if t < 1:
            self.buy(price, self.fixed_size, True)

        if t < 2:
            self.buy(price + self.atr_value * 0.5, self.fixed_size, True)

        if t < 3:
            self.buy(price + self.atr_value, self.fixed_size, True)

        if t < 4:
            self.buy(price + self.atr_value * 1.5, self.fixed_size, True)

    def send_short_orders(self, price):
        """"""
        t = self.pos / self.fixed_size

        if t > -1:
            self.short(price, self.fixed_size, True)

        if t > -2:
            self.short(price - self.atr_value * 0.5, self.fixed_size, True)

        if t > -3:
            self.short(price - self.atr_value, self.fixed_size, True)

        if t > -4:
            self.short(price - self.atr_value * 1.5, self.fixed_size, True)
Esempio n. 18
0
    def show(self):
        bars = self.barDatas
        if (bars[0].datetime > bars[-1].datetime):
            bars = bars.__reversed__()

        data = []
        index = []
        am = ArrayManager(self.window_size * 2)

        ### 初始化columns
        columns = ['Open', 'High', 'Low', 'Close', "Volume"]

        if self.open_boll:
            columns.append("boll_up")
            columns.append("boll_down")
        if (self.open_obv):
            columns.append("obv")
        if (self.open_rsi):
            columns.append("rsi")

        for bar in bars:
            index.append(bar.datetime)
            list = [
                bar.open_price, bar.high_price, bar.low_price, bar.close_price,
                bar.volume
            ]
            am.update_bar(bar)

            #添加布林指标数据
            if self.open_boll:
                if am.count >= self.window_size:
                    up, down = am.boll(self.window_size, 3.4)
                    list.append(up)
                    list.append(down)
                else:
                    list.append(bar.close_price)
                    list.append(bar.close_price)

            if self.open_obv:
                if am.count >= self.window_size:
                    obv = am.obv(self.window_size)
                    list.append(obv)
                else:
                    list.append(bar.volume)

            if self.open_rsi:
                if am.count >= self.window_size:
                    rsi = am.rsi(self.window_size)
                    list.append(rsi)
                else:
                    list.append(50)

            data.append(list)

        trades = pd.DataFrame(data, index=index, columns=columns)

        apds = []

        # 添加布林指标数据
        if self.open_boll:
            apds.append(
                mpf.make_addplot(trades['boll_up'], linestyle='dashdot'))
            apds.append(
                mpf.make_addplot(trades['boll_down'], linestyle='dashdot'))

        if self.open_obv:
            apds.append(
                mpf.make_addplot(trades['obv'],
                                 panel='lower',
                                 color='g',
                                 secondary_y=True))
        if self.open_rsi:
            apds.append(
                mpf.make_addplot(trades['rsi'],
                                 panel='lower',
                                 color='b',
                                 secondary_y=True))

        mpf.plot(trades,
                 type='candle',
                 volume=True,
                 mav=(5),
                 figscale=1.3,
                 style='yahoo',
                 addplot=apds)
Esempio n. 19
0
class Renko(object):
    """
    renko砖型图模块
    """
    def __init__(
        self,
        jump_price,
        symbol=None,
        exchange=None,
        gateway_name=None,
        chart=None,
        on_bar_callback=None,
    ):
        self.jump_price = jump_price
        self.symbol = symbol
        self.exchange = exchange
        self.gateway_name = gateway_name

        self.bar = None
        self.bars = ArrayManager(30)

        self.up = None
        self.down = None
        self.datetime = None
        self.volume = None

        self.KLine_chart_dict = chart
        self.on_bar_callback = on_bar_callback

    def update_tick(self, tick: TickData):
        pre_price = tick.last_price

        if self.up is None:
            self.up = pre_price
            self.down = pre_price
            self.datetime = tick.datetime
            self.volume = tick.volume

            self.bar = BarData(
                symbol=tick.symbol,
                exchange=tick.exchange,
                datetime=tick.datetime,
                gateway_name=tick.gateway_name,
                open_price=pre_price,
                high_price=pre_price,
                low_price=pre_price,
                close_price=pre_price,
            )

        self.update_pre_price(pre_price)
        self.datetime = tick.datetime
        self.volume += tick.volume

    def update_bar(self, bar: BarData):
        pre_price = bar.close_price
        if self.up is None:
            self.up = pre_price
            self.down = pre_price
            self.datetime = bar.datetime
            self.volume = bar.volume

            self.bar = BarData(
                symbol=bar.symbol,
                exchange=bar.exchange,
                datetime=bar.datetime,
                gateway_name=bar.gateway_name,
                open_price=pre_price,
                high_price=pre_price,
                low_price=pre_price,
                close_price=pre_price,
            )

        self.update_pre_price(pre_price)
        self.datetime = bar.datetime
        self.volume += bar.volume

    def update_pre_price(self, pre_price):
        if pre_price >= self.up + self.jump_price:
            self.down = self.up
            self.up += self.jump_price
            self.add_bar(True)

            self.init_bar(self.up)
            if pre_price > self.up:
                self.update_pre_price(pre_price)

        elif pre_price <= self.down - self.jump_price:
            self.up = self.down
            self.down -= self.jump_price
            self.add_bar(False)

            self.init_bar(self.down)
            if pre_price < self.down:
                self.update_pre_price(pre_price)

        else:
            self.bar.high_price = max(self.bar.high_price, pre_price)
            self.bar.low_price = min(self.bar.low_price, pre_price)

    def add_bar(self, up_or_down):
        """
        :param up_or_down: True:up, False:down
        """
        if up_or_down:
            self.bar.close_price = self.up
            self.bar.open_price = self.down
        else:
            self.bar.close_price = self.down
            self.bar.open_price = self.up

        self.bar.volume = self.volume
        self.bars.update_bar(self.bar)
        if self.on_bar_callback:
            self.on_bar_callback(self.bar)

        self.volume = 0
        self.bar.datetime = self.datetime

        if self.KLine_chart_dict is not None:
            self.KLine_chart_dict.update_bar(self.bar)

    def init_bar(self, pre_price):
        self.bar.high_price = pre_price
        self.bar.low_price = pre_price

    def save_data_to_csv(self):
        pass
class TredningFollowingSignal:
    """"""
    def __init__(self, strategy: StrategyTemplate, vt_symbol: str):
        """"""

        self.portfolio = strategy
        self.vt_symbol = vt_symbol

        self.atr_window = self.portfolio.atr_window
        self.atr_ma_window = self.portfolio.atr_ma_window
        self.rsi_window = self.portfolio.rsi_window
        self.rsi_entry = self.portfolio.rsi_entry
        self.trailing_percent = self.portfolio.trailing_percent
        self.fixed_size = self.portfolio.fixed_size

        self.atr_value = 0
        self.atr_ma = 0
        self.rsi_value = 0
        self.rsi_buy = 50 + self.rsi_entry
        self.rsi_sell = 50 - self.rsi_entry
        self.intra_trade_high = 0
        self.intra_trade_low = 0

        self.limit_orders = []
        self.bg = BarGenerator(self.on_bar, 5, self.on_5min_bar)
        self.am = ArrayManager()

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)

    def on_5min_bar(self, bar: BarData):
        """"""
        self.am.update_bar(bar)

        if not self.am.inited:
            return

        self.portfolio.cancel_all()
        am = self.am
        atr_array = am.atr(self.atr_window, array=True)
        self.atr_value = atr_array[-1]
        self.atr_ma = atr_array[-self.atr_ma_window:].mean()
        self.rsi_value = am.rsi(self.rsi_window)

        symbol_pos = self.portfolio.get_pos(self.vt_symbol)
        if symbol_pos == 0:
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = bar.low_price

            if self.atr_value > self.atr_ma:
                if self.rsi_value > self.rsi_buy:
                    open_order = self.portfolio.buy(self.vt_symbol,
                                                    bar.close_price + 5,
                                                    self.fixed_size)
                    self.limit_orders.append(open_order)
                elif self.rsi_value < self.rsi_sell:
                    open_order = self.portfolio.short(self.vt_symbol,
                                                      bar.close_price - 5,
                                                      self.fixed_size)
        elif symbol_pos > 0:
            self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
            self.intra_trade_low = bar.low_price

            long_stop = self.intra_trade_high * (1 -
                                                 self.trailing_percent / 100)
            if bar.close_price <= long_stop:
                close_order = self.portfolio.sell(self.vt_symbol,
                                                  bar.close_price - 5,
                                                  abs(symbol_pos))
                self.limit_orders.append(close_order)
        elif symbol_pos < 0:
            self.intra_trade_low = min(self.intra_trade_low, bar.low_price)
            self.intra_trade_high = bar.high_price

            short_stop = self.intra_trade_low * (1 +
                                                 self.trailing_percent / 100)
            if bar.close_price >= short_stop:
                close_order = self.portfolio.cover(self.vt_symbol,
                                                   bar.high_price + 5,
                                                   abs(symbol_pos))
                self.limit_orders.append(close_order)