def generate_3mindata(self, am:ArrayManager, bar:BarData):
        offset = -self.offset
        offset_m = int(offset / 2)
        calc_nums = np.array(self.ma_tag[-offset:-1])
        # var_val = np.var(calc_nums)
        std_val = np.std(calc_nums)
        std_val2 = np.std(np.array(self.ma_tag[-10:-1]))
        std_val3 = np.std(np.array(am.range[-30:-10]))
        ma = self.ma_tag[-1]
        
        mean_val = np.mean(calc_nums)
        mean_val2 = np.mean(np.array(self.ma_tag[-5:-1]))
        mean_val3 = np.mean(np.array(self.ma_tag[-20:-1]))
        mean_val4 = np.mean(np.array(self.ma_tag[-30:-5]))
        kdj_val = am.kdj()

        deg1 = calc_regress_deg(am.close[offset : offset_m], False)
        deg2 = calc_regress_deg(am.close[offset_m :], False)
        deg3 = calc_regress_deg(am.close[-10 :], False)
        deg_full = calc_regress_deg(am.close[offset :], False)

        wave = self.wave(am.close[-30:])
        wave_r_sum = np.sum(wave["range"])
        macd=am.macd(20,40, 16)
        calc_data = (dict(
                kdj=[round(kdj_val["k"][-1],2),round(kdj_val["d"][-1],2),round(kdj_val["j"][-1],2)],
                cci_20=am.cci(20),rsi=am.rsi(20),adx=am.adx(20),boll=am.boll(20, 3.4),
                macd=[round(macd[0],2),round(macd[1],2),round(macd[2],2)],
                deg40_20=round(deg1,2), deg20_0=round(deg2,2), deg20_10=round(calc_regress_deg(am.close[-20:-10], False),2), deg10_0=round(deg3,2),
                deg30_15=round(calc_regress_deg(am.close[-30:-15], False),2), deg15_0=round(calc_regress_deg(am.close[-15:], False),2),deg_f=round(deg_full,2),
                atr=round(am.atr(10, length=15), 3), tr=round(am.atr(1, length=2), 3),atr_40=round(am.atr(40, length=42), 3),
                time=bar.datetime, price=bar.close_price, ma=round(ma, 2), 
                std_40=round(std_val, 2),mean40=round(mean_val,2), mean_std=np.mean(self.std_range.data[-5:]),
                std_10=round(std_val2,2), mean30_10=round(mean_val4,2), mean10=round(mean_val2,2),
                vol=am.volume[-1], std_range=self.std_range.data[-1:-5:-1], range=am.range[-1:-5:-1].tolist(),
                range_sum=np.sum(am.range[-5:]), 
                pattern=list(map(lambda x: KLINE_PATTERN_CHINESE[x], self.pattern_record.keys())),
                ma120t=self.ma120_track, 
                ma120t_list=self.ma120_track_list[-1:-10:-1], 
                ma120t_sort=sorted(self.ma120_track_list[-20:-1], key=abs),
                ma120t_sum=np.sum(self.ma120_track_list[-20:-1] + [self.ma120_track]), 
                ma120t_mean=np.mean(self.ma120_track_list[-20:-1] + [self.ma120_track]),
                ma120t_std=np.std(self.ma120_track_list[-20:-1] + [self.ma120_track]),
                ma_info=list(map(lambda x:x["std"], self.ma_info[-1:])),
                wave_cnt=len(wave), wave_r_sum=wave_r_sum, atr_mean=np.mean(am.atr(20, array=True,length=240)[-200:])
                ))

        return calc_data
Ejemplo n.º 2
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)
Ejemplo n.º 3
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)
Ejemplo n.º 4
0
    def generate_data(self, am: ArrayManager, bar: BarData):
        offset = -self.offset
        offset_m = int(offset / 2)

        std_val3 = np.std(np.array(am.range[-30:-10]))

        kdj_val = am.kdj()
        has_kdj_recore = False
        k = kdj_val["k"]
        d = kdj_val["d"]
        j = kdj_val["j"]
        if (k[-1] > 75 and d[-1] > 75 and j[-1] > 75) or \
                (k[-1] < 25 and d[-1] < 25 and j[-1] < 75):
            if (j[-2] < k[-2] or j[-2] < d[-2]) and (j[-1] > k[-1] and j[-1] > d[-1]) \
                    or \
                    (j[-2] > k[-2] or j[-2] > d[-2]) and (j[-1] < k[-1] and j[-1] < d[-1]):
                has_kdj_recore = True
                t = bar.datetime
                self.kdj_record.append(
                    (t.strftime("%H:%M:%S"), round(k[-1], 3), round(d[-1], 3),
                     round(j[-1], 3)))

        deg1 = calc_regress_deg(am.close[offset:offset_m], False)
        deg2 = calc_regress_deg(am.close[offset_m:], False)
        deg3 = calc_regress_deg(am.close[-10:], False)
        deg_full = calc_regress_deg(am.close[offset:], False)

        macd = am.macd(20, 40, 16)

        calc_data = (dict(
            kdj=[
                round(kdj_val["k"][-1], 2),
                round(kdj_val["d"][-1], 2),
                round(kdj_val["j"][-1], 2)
            ],
            cci_20=am.cci(20),
            rsi=am.rsi(20),
            adx=am.adx(20),
            boll=am.boll(20, 3.4),
            macd=[round(macd[0], 2),
                  round(macd[1], 2),
                  round(macd[2], 2)],
            deg40_20=round(deg1, 2),
            deg20_0=round(deg2, 2),
            deg20_10=round(calc_regress_deg(am.close[-20:-10], False), 2),
            deg30_15=round(calc_regress_deg(am.close[-30:-15], False), 2),
            deg15_0=round(calc_regress_deg(am.close[-15:], False), 2),
            deg_f=round(deg_full, 2),
            deg30_10=round(calc_regress_deg(am.close[-30:-10], False), 2),
            deg10_0=round(deg3, 2),
            atr=round(am.atr(10, length=15), 3),
            tr=round(am.atr(1, length=2), 3),
            atr_40=round(am.atr(40, length=42), 3),
            time=bar.datetime,
            price=bar.close_price,
            mean_std=np.mean(self.std_range.data[-5:]),
            vol=am.volume[-1],
            std_range=self.std_range.data[-1:-5:-1],
            range=am.range[-1:-5:-1].tolist(),
            range_sum=np.sum(am.range[-5:]),
            pattern=list(
                map(lambda x: KLINE_PATTERN_CHINESE[x],
                    self.pattern_record.keys())),
            atr_mean=np.mean(am.atr(20, array=True, length=240)[-200:]),
        ))
        if self.ma_info.info.index.size >= 31:
            ma5 = self.ma_info.info[5][-31:]
            x = AnalyseWave(ma5)
            calc_data["ma5_info"] = x.optimize
            ma10 = self.ma_info.info[10][-31:]
            x = AnalyseWave(ma10)
            calc_data["ma10_info"] = x.optimize
        return calc_data
Ejemplo n.º 5
0
class DudlThrustEmaPositionStrategy(CtaTemplate):
    """"""
    author = "yunyu"

    open_window = 5
    xminute_window = 30
    rolling_period = 70
    upper_open = 0.45
    lower_open = 0.45
    cci_length = 5
    ema_length = 60
    position_atr_length = 6
    risk_level = 1000
    # fixed_size = 1

    trading_size = 0
    atr_value = 0
    up = 0
    down = 0
    current_ema = 0
    last_ema = 0
    ema_mid = 0
    ema_new_value = 0
    ema_length_new = 0
    cci_value = 0
    exit_long_nex = 0
    exit_long_last = 0
    exit_short_nex = 0
    exit_short_last = 0
    current_close = 0
    last_close = 0
    front_close = 0
    exit_long = 0
    exit_short = 0

    ask = 0
    bid = 0

    parameters = [
        "open_window", "xminute_window", "rolling_period", "upper_open",
        "lower_open", "cci_length", "ema_length", "position_atr_length",
        "risk_level"
    ]

    variables = [
        "trading_size",
        "up",
        "down",
        "current_ema",
        "last_ema",
        "ema_mid",
        "ema_new_value",
        "ema_length_new",
        "cci_value",
        "exit_long_nex",
        "exit_long_last",
        "exit_short_nex",
        "exit_short_last",
        "current_close",
        "last_close",
        "front_close",
        "exit_long",
        "exit_short",
    ]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)
        self.bg_open = BarGenerator(on_bar=self.on_bar,
                                    window=self.open_window,
                                    on_window_bar=self.on_open_bar)
        self.am_open = ArrayManager()

        self.bg = NewBarGenerator(on_bar=self.on_bar,
                                  window=self.xminute_window,
                                  on_window_bar=self.on_xmin_bar)
        self.am = ArrayManager(self.rolling_period + 50)

    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.bg.update_tick(tick)
        self.ask = tick.ask_price_1  # 卖一价
        self.bid = tick.bid_price_1  # 买一价

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

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

        if not self.am.inited or not self.am_open.inited:
            return

        if self.pos == 0:
            self.cci_value = self.am.cci(self.cci_length)

            # 判断数据是否正常,如果atr 计算结果正常,才计算仓位,避免下单时下出不正常的数量
            self.atr_value = self.am.atr(self.position_atr_length)

            if self.atr_value == 0:
                return

            self.trading_size = max(int(self.risk_level / self.atr_value), 1)

            if self.cci_value > 0:
                self.buy(self.up, self.trading_size, True)

            elif self.cci_value < 0:
                self.short(self.down, self.trading_size, True)

        elif self.pos > 0:
            con1 = bar.close_price < self.current_ema
            con2 = bar.close_price >= self.last_ema
            if con1 and con2:
                self.exit_long_nex = bar.close_price  # 保存当前收盘价

                if self.exit_long_last == 0 or self.exit_long_nex > self.exit_long_last:
                    self.exit_long_last = self.exit_long_nex
                    self.ema_length_new = self.ema_length

                    self.exit_long = self.ema_mid

                else:
                    if bar.close_price > (
                        (self.ema_mid + self.current_ema) / 2):
                        self.exit_long = bar.close_price

                    elif bar.close_price < self.ema_mid:
                        self.exit_long = bar.close_price

                    else:
                        self.exit_long = self.ema_mid
            else:
                self.exit_long = self.ema_mid

            self.sell(self.exit_long, abs(self.pos), True)

        elif self.pos < 0:
            con1 = bar.close_price > self.current_ema
            con2 = bar.close_price <= self.last_ema
            if con1 and con2:
                self.exit_short_nex = bar.close_price
                if self.exit_short_last == 0 or self.exit_short_nex < self.exit_short_last:
                    self.exit_short_last = self.exit_short_nex
                    self.ema_length_new = self.ema_length

                    self.exit_short = self.ema_mid

                else:
                    if bar.close_price < (self.ema_mid + self.current_ema / 2):
                        self.exit_short = bar.close_price

                    elif bar.close_price < self.ema_mid:
                        self.exit_short = bar.close_price

                    else:
                        self.exit_short = self.ema_mid
            else:
                self.exit_short = self.ema_mid

            self.cover(self.exit_short, abs(self.pos), True)

        self.put_event()
        self.sync_data()

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

        if not self.am.inited:
            return

        #  计算海龟 上轨,下轨
        high_max = self.am.high[-self.rolling_period:].max()
        close_min = self.am.close[-self.rolling_period:].min()
        close_max = self.am.close[-self.rolling_period:].max()
        low_min = self.am.low[-self.rolling_period:].min()

        hc = high_max - close_min
        cl = close_max - low_min
        dual = max(hc, cl)

        self.up = self.am.open[-2] + dual * self.upper_open
        self.down = self.am.open[-2] - dual * self.upper_open

        # print(f"up:{self.up},{self.down}")
        self.current_close = self.am.close[-1]
        self.last_close = self.am.close[-2]
        self.front_close = self.am.close[-3]

        if self.pos == 0:
            self.exit_long_nex = 0
            self.exit_long_last = 0
            self.exit_short_nex = 0
            self.exit_short_last = 0
            self.ema_length_new = self.ema_length

        elif self.pos > 0:
            close_long = self.current_close > self.last_close > self.front_close
            if close_long:
                self.ema_length_new -= 1
                self.ema_length_new = max(self.ema_length_new, 5)

        elif self.pos < 0:
            close_short = self.current_close < self.last_close < self.front_close
            if close_short:
                self.ema_length_new -= 1
                self.ema_length_new = max(self.ema_length_new, 5)

        self.ema_mid = self.am.ema(self.ema_length)
        ema_mid_new = self.am.ema(self.ema_length_new, True)

        self.current_ema = ema_mid_new[-1]
        self.last_ema = ema_mid_new[-2]

    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.
        """
        pass

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

    def market_order(self):
        """"""
        pass
        # self.buy(self.last_tick.limit_up, 1)
        # self.write_log("执行市价单测试")

    def limit_order(self):
        """"""
        pass
        # self.buy(self.last_tick.limit_down, 1)
        # self.write_log("执行限价单测试")

    def stop_order(self):
        """"""
        pass
Ejemplo n.º 6
0
class CciSignal(CtaSignal):
    """
    """
    cci_up_array = 0
    cci_dow_array = 0
    cci_value = 0
    cci_up = 0
    cci_down = 0
    cci_ma = 0
    last_cci_value = 0
    current_cci_value = 0
    last_cci_up = 0
    current_cci_up = 0
    last_cci_down = 0
    current_cci_down = 0
    last_cci_ma = 0
    current_cci_ma = 0

    def __init__(self, open_window: int, cci_window: int, cci_level: float):
        """"""
        super().__init__()
        self.open_window = open_window
        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.open_window, self.on_x_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):
        """
        :param bar: 
        :return: 
        """
        self.bg.update_bar(bar)

    def on_x_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)

        # 计算 前一根K线的 cci
        cci_array = talib.CCI(self.am.high[:-1], self.am.low[:-1],
                              self.am.close[:-1], self.cci_window)
        cci_ema = talib.EMA(cci_array, self.cci_window)

        dev_array = abs(
            cci_array[-self.cci_window:] -
            cci_ema[-self.cci_window:]) / cci_ema[-self.cci_window:]
        dev = np.max(dev_array[-self.cci_window:])

        self.cci_up_array = cci_ema[
            -self.cci_window:] + cci_array[-self.cci_window:] * dev
        self.cci_dow_array = cci_ema[
            -self.cci_window:] - cci_array[-self.cci_window:] * dev

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

        self.last_cci_value = self.cci_value[-2]
        self.current_cci_value = self.cci_value[-1]
        self.last_cci_up = self.cci_up_array[-2]
        self.current_cci_up = self.cci_up_array[-1]
        self.last_cci_down = self.cci_dow_array[-2]
        self.current_cci_down = self.cci_dow_array[-1]
        self.last_cci_ma = cci_ema[-2]
        self.current_cci_ma = cci_ema[-1]

        if self.last_cci_value <= self.last_cci_up and self.current_cci_value > self.current_cci_up:
            self.set_signal_pos(1)

        elif self.last_cci_value >= self.last_cci_up and self.current_cci_value < self.current_cci_up:
            self.set_signal_pos(-1)

        cci_sell = self.last_cci_value >= self.last_cci_ma and self.current_cci_value < self.current_cci_ma
        cci_court = self.last_cci_value <= self.last_cci_ma and self.current_cci_value > self.current_cci_ma
        if cci_sell and cci_court:
            self.set_signal_pos(0)
Ejemplo n.º 7
0
class DudlThrustKkStrategy(CtaTemplate):
    """"""
    author = "yunyu"

    xminute_window = 1
    rolling_period = 70
    upper_open = 0.2
    lower_open = 0.2
    cci_window = 30
    keltner_window = 24
    keltner_dev = 1
    fixed_size = 1

    cci_value = 0
    exit_kk_up = 0
    exit_kk_down = 0
    dualthrust_up = 0
    dualthrust_down = 0

    ask = 0
    bid = 0

    parameters = [
        "xminute_window",
        "rolling_period",
        "upper_open",
        "lower_open",
        "cci_window",
        "keltner_window",
        "keltner_dev",
        "fixed_size",
    ]

    variables = [
        "dualthrust_up",
        "dualthrust_down",
        "cci_value",
        "exit_kk_up",
        "exit_kk_down",
    ]

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

        self.bg = NewBarGenerator(on_bar=self.on_bar,
                                  window=self.xminute_window,
                                  on_window_bar=self.on_min_bar,
                                  interval=Interval.MINUTE)
        self.am = 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.bg.update_tick(tick)
        self.ask = tick.ask_price_1  # 卖一价
        self.bid = tick.bid_price_1  # 买一价

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

    def on_min_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.am.update_bar(bar)
        self.cancel_all()
        if not self.am.inited:
            return

        self.dualthrust_up, self.dualthrust_down = self.dualthrust(
            self.am.high, self.am.low, self.am.close, self.am.open,
            self.rolling_period, self.upper_open, self.lower_open)
        self.cci_value = self.am.cci(self.cci_window)
        print(self.cci_value)
        self.keltner_up, self.keltner_down = self.am.keltner(
            self.keltner_window, self.keltner_dev)

        if self.pos == 0:
            if self.cci_value > 0:
                self.buy(self.dualthrust_up, self.fixed_size, True)

            elif self.cci_value < 0:
                self.short(self.dualthrust_down, self.fixed_size, True)

        elif self.pos > 0:
            self.sell(self.exit_kk_down, self.fixed_size, True)

        elif self.pos < 0:
            self.cover(self.exit_kk_up, self.fixed_size, True)

        self.put_event()
        self.sync_data()
        self.put_event()

    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
        # self.put_event()

    def market_order(self):
        """"""
        pass
        # self.buy(self.last_tick.limit_up, 1)
        # self.write_log("执行市价单测试")

    def limit_order(self):
        """"""
        pass
        # self.buy(self.last_tick.limit_down, 1)
        # self.write_log("执行限价单测试")

    def stop_order(self):
        """"""
        pass
        # self.buy(self.last_tick.ask_price_1, 1, True)
        # self.write_log("执行停止单测试")

    def dualthrust(self, high, low, close, open, n, k1, k2):
        """
        :param high:
        :param low:
        :param close:
        :return:
        """
        #计算N日最高价的最高价,收盘价的最高价、最低价,最低价的最低价
        hh = high[-n:].max()
        lc = close[-n:].min()
        hc = close[-n:].max()
        ll = low[-n:].min()

        #计算range,上下轨的距离前一根K线开盘价的距离
        range = max(hh - lc, hc - ll)

        up = open[-2] + k1 * range
        down = open[-2] - k2 * range

        return up, down
Ejemplo n.º 8
0
class MaLevelTrackStrategy(CtaTemplate):
    author = "用Python的交易员"

    ma_level = [5, 10, 20, 30, 120]
    ma_tag = []
    bd = []
    fast_ma0 = 0.0
    fast_ma1 = 0.0

    slow_ma0 = 0.0
    slow_ma1 = 0.0
    request_order = []
    bar_identify = []

    parameters = ["ma_level"]
    variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1"]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super(MaLevelTrackStrategy, self).__init__(cta_engine, strategy_name,
                                                   vt_symbol, setting)
        self.bg = BarGenerator(self.on_bar, 15, self.on_1min_bar)
        self.am = ArrayManager(400)
        self.am3 = ArrayManager(150)
        self.bg3 = BarGenerator(self.on_bar, 3, self.on_3min_bar)
        self.am5 = ArrayManager(120)
        self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar)
        self.order_data = None
        self.positions = Position(self)
        self.std_range = IntervalGen(np.std, 5)
        self.std_range3 = IntervalGen(np.std, 5)
        self.std_range5 = IntervalGen(np.std, 5)
        self.pattern_record = PatternRecord()
        # self.pattern_record.set_expiry([KlinePattern.CDLEVENINGSTAR], 3)
        self.pattern_record.set_expiry(list(KlinePattern), 1)

        five_min_open_5 = partial(self.reverse_shape_strategy,
                                  setting={
                                      "atr": 10,
                                      "atr_valve": 0.8,
                                      "deg1": (10, 5),
                                      "deg2": 5
                                  })
        self.open_strategy = {
            "1": [self.reverse_shape_strategy],
            "5": [five_min_open_5],
        }
        self.offset = 40
        self.ma120_track = None
        self.ma120_track_list = []

    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("策略启动")
        self.put_event()

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

        self.put_event()

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

    def on_3min_bar(self, bar: BarData):
        self.am3.update_bar(bar)
        self.std_range3.update(self.am3.range[-1])
        if not self.am.inited or not self.trading:
            return
        pattern = self.am3.pattern(
            [KlinePattern.CDLEVENINGSTAR, KlinePattern.CDL2CROWS])

        if len(pattern) > 0:
            print(pattern)
            self.pattern_record.add_pattern(pattern)
            # deg = calc_regress_deg(self.am3.close[-20:])

    def wave(self, data, window=0.0002):

        if len(data) <= 0:
            return
        # r = array[::-1]
        result = {"value": [], "range": [], "pos": [], "length": []}
        r = data
        l = len(data) - 1
        now = r[0]
        # v_list.append(now)
        # p_list.append(0)
        pos = 1

        vol = 0
        u_tag = None
        d_tag = None
        end_tag = None
        start_pos = 0
        while pos < l:
            if math.isnan(now):
                now = r[pos]
                pos += 1
                continue
            else:
                start_pos = pos - 1
                break

        while pos < l:

            if now < r[pos]:
                u_tag = pos
                if d_tag:
                    diff = r[start_pos] - r[d_tag]
                    if abs(diff /
                           r[start_pos]) > window and d_tag - start_pos > 1:
                        end_tag = d_tag

            elif now > r[pos]:
                d_tag = pos
                if u_tag:
                    diff = r[start_pos] - r[u_tag]
                    if abs(diff /
                           r[start_pos]) > window and d_tag - start_pos > 1:
                        end_tag = u_tag

            if end_tag is not None:
                result["range"].append(r[end_tag] / r[start_pos] - 1)
                result["length"].append(end_tag - start_pos)
                start_pos = end_tag
                result["value"].append(r[end_tag])
                result["pos"].append(end_tag)
                end_tag = None

            vol += r[pos] - now
            now = r[pos]
            pos += 1
        return pd.DataFrame(result)

    def mode_identify(self, bar: BarData):
        self.bar_identify = []
        hl_scale = round(bar.high_price / bar.low_price - 1, 4)
        if hl_scale > 0.001:
            diff = bar.high_price - bar.low_price
            diff_up = bar.low_price + diff / 2 * 1.20
            diff_down = bar.low_price + diff / 2 * 0.80
            close = bar.close_price
            if bar.open_price < diff_up and bar.open_price > diff_down and \
               bar.close_price < diff_up and bar.close_price > diff_down:
                if bar.close_price > bar.open_price:
                    print("绿十字星", bar.datetime, bar.high_price, bar.low_price,
                          diff, diff_up, diff_down, bar.open_price,
                          bar.close_price)
                else:
                    print("红十字星", bar.datetime, bar.high_price, bar.low_price,
                          diff, diff_up, diff_down, bar.open_price,
                          bar.close_price)

    def on_5min_bar(self, bar: BarData):
        self.std_range5.update(self.am5.range[-1])
        self.am5.update_bar(bar)
        if not self.am.inited or not self.trading:
            return

        self.on_strategy(self.am5, bar, self.open_strategy["5"])
        # pattern_list = [KlinePattern.CDLEVENINGSTAR, KlinePattern.CDL2CROWS, KlinePattern.CDLCONCEALBABYSWALL, KlinePattern.CDLEVENINGDOJISTAR]

    #     pattern = self.am5.pattern(list(KlinePattern))
    #     if len(pattern) > 0:
    #         print(list(map(lambda x: (KLINE_PATTERN_CHINESE[x[0]],x[1]), pattern)))
    #         self.pattern_record.add_pattern(pattern)
    #         deg_full = calc_regress_deg(self.am.close[-40 :], False)
    #         print("deg:",deg_full)

    #     self.pattern_record.update()

    def open_v3(self, am: ArrayManager, bar: BarData):
        std_val2 = np.std(np.array(self.ma_tag[-10:-1]))
        mean_val2 = np.mean(np.array(self.ma_tag[-10:-1]))
        mean = np.mean(np.array(self.ma_tag[-30:-10]))

        if std_val2 < 0.2:
            if mean_val2 > 3:
                if mean_val2 >= (mean + 1):
                    return self.buy(bar.close_price, 1, type=OrderType.MARKET)
            elif mean_val2 < 2:
                if mean_val2 <= (mean - 1):
                    return self.short(bar.close_price,
                                      1,
                                      type=OrderType.MARKET)

    def open_v1(self, am: ArrayManager, bar: BarData):
        offset = -40
        offset_m = int(offset / 2)
        calc_nums = np.array(self.ma_tag[-offset:-1])
        mean_val = np.mean(calc_nums)
        # var_val = np.var(calc_nums)
        std_val = np.std(calc_nums)
        if std_val < 1 and mean_val < 2 and self.ma_tag[-1] >= (mean_val + 2):
            return self.buy(bar.close_price, 1, type=OrderType.MARKET)
        elif std_val < 1 and mean_val > 3 and self.ma_tag[-1] <= (mean_val -
                                                                  2):
            return self.short(bar.close_price, 1, type=OrderType.MARKET)

    def open_v2(self, am: ArrayManager, bar: BarData):
        std_val2 = np.std(np.array(self.ma_tag[-10:-1]))
        mean_val2 = np.mean(np.array(self.ma_tag[-10:-1]))
        mean = np.mean(np.array(self.ma_tag[-30:-10]))

        if std_val2 < 0.2:
            if mean_val2 > 2.5:
                if mean_val2 >= (mean + 1):
                    return self.buy(bar.close_price, 1, type=OrderType.MARKET)
            elif mean_val2 < 2.5:
                if mean_val2 <= (mean - 1):
                    return self.short(bar.close_price,
                                      1,
                                      type=OrderType.MARKET)

    def open2(self, am: ArrayManager, bar: BarData, calc_data):
        deg = calc_data["deg20"]
        ma = self.ma_tag[-1]
        if deg > 0.5 and ma > 3 and self.am5.range[-1] > -0.002:
            return self.buy(bar.close_price, 1, type=OrderType.MARKET)
        elif deg < -0.5 and ma < 2 and self.am5.range[-1] < 0.002:
            return self.short(bar.close_price, 1, type=OrderType.MARKET)

    def open1(self, am: ArrayManager, bar: BarData, calc_data):

        mean = calc_data["mean30_10"]
        mean_val2 = calc_data["mean10"]
        # if std_val2 < 0.2:
        if mean_val2 > 3.5 and mean_val2 >= (mean + 2):
            return self.buy(bar.close_price, 1, type=OrderType.MARKET)
        elif mean_val2 < 1.5 and mean_val2 <= (mean - 2):
            return self.short(bar.close_price, 1, type=OrderType.MARKET)

    # v形反转捕获
    def reverse_shape_strategy(self,
                               am: ArrayManager,
                               bar: BarData,
                               calc_data,
                               setting={
                                   "atr": 40,
                                   "atr_valve": 0.8,
                                   "deg1": (40, 20),
                                   "deg2": (20, 0),
                               }):

        deg1 = calc_data["deg40_20"]
        deg2 = calc_data["deg20_0"]
        kdj = calc_data["kdj"]

        atr = self.am.atr(40)

        if atr < 0.08:
            return

        if deg1 > 0 and deg2 > 0 or \
           deg1 < 0 and deg2 < 0:
            return

        if not (abs(deg1) > 0.15 and abs(deg2) > 0.1 and
                (abs(deg1) + abs(deg2)) > 0.3):
            return

        close = am.close[-40:]
        min_val = np.min(close)
        max_val = np.max(close)
        mid_val = max_val if deg1 > 0 else min_val
        mid_pos = np.where(close == mid_val)[0][0]

        if mid_pos < 10 or mid_pos > 30:
            return

        start_val = np.min(close[:mid_pos]) if deg1 > 0 else np.max(
            close[:mid_pos])
        start_pos = np.where(close == start_val)[0][0]
        l = mid_pos - start_pos

        # pos2 = np.where(close == min_val)[0][0]

        x_fit = reg_util.regress_y_polynomial(close[:mid_pos], zoom=True)
        deg1_remake = calc_regress_deg(x_fit[:abs(mid_pos)], False)
        y_fit = reg_util.regress_y_polynomial(close[mid_pos:], zoom=True)
        deg2_remake = calc_regress_deg(y_fit[:abs(mid_pos)], False)
        print(start_pos, mid_pos, deg1, deg2, deg1_remake, deg2_remake, l,
              start_val, mid_val)
        if deg2 < 0:
            if kdj[0] < 20 and kdj[1] < 10 and kdj[2] < 10:
                # if kdj[2] < 10:
                return self.short(bar.close_price, 1, type=OrderType.MARKET)
        else:
            if kdj[0] > 80 and kdj[1] > 90 and kdj[2] > 90:
                # if kdj[2] > 90:
                return self.buy(bar.close_price, 1, type=OrderType.MARKET)

        # print("找到大v形:", deg1, deg2 )

    def open5(self, am: ArrayManager, bar: BarData, calc_data):

        ma = self.ma_tag[-1]
        mean = calc_data["mean30_10"]
        atr = self.am.atr(10, array=True, length=20)
        tr = self.am.atr(1, array=True, length=11)
        # self.ma120_track
        ma120 = self.am.sma(120)
        # if std_val2 < 0.2:
        mean_std = calc_data["mean_std"]
        if mean_std < 0.8 and tr[-1] > 0.1 and tr[-1] / tr[-10] > 3 and tr[
                -1] / atr[-1] >= 1.7 and tr[-10] / atr[-10] < 1:
            if np.sum(self.am.range[-10:]) > 0 and self.ma120_track > 0:
                return self.buy(bar.close_price, 1, type=OrderType.MARKET)
            elif self.ma120_track < 0:
                return self.short(bar.close_price, 1, type=OrderType.MARKET)

    def open_kline1(self, am: ArrayManager, bar: BarData, calc_data):

        if KlinePattern.CDLEVENINGSTAR not in self.pattern_record:
            return
        # if std_val2 < 0.2:
        deg = calc_regress_deg(self.am.close[-5:], False)
        print("kline_strategy", deg)
        if deg < -0.1:
            return self.short(bar.close_price, 1, type=OrderType.MARKET)

    def generate_data(self, bar: BarData):
        offset = -self.offset
        offset_m = int(offset / 2)
        calc_nums = np.array(self.ma_tag[-offset:-1])
        # var_val = np.var(calc_nums)
        std_val = np.std(calc_nums)
        std_val2 = np.std(np.array(self.ma_tag[-10:-1]))
        std_val3 = np.std(np.array(self.am.range[-30:-10]))
        ma = self.ma_tag[-1]

        mean_val = np.mean(calc_nums)
        mean_val2 = np.mean(np.array(self.ma_tag[-5:-1]))
        mean_val3 = np.mean(np.array(self.ma_tag[-20:-1]))
        mean_val4 = np.mean(np.array(self.ma_tag[-30:-5]))
        kdj_val = self.am.kdj()

        deg1 = calc_regress_deg(self.am.close[offset:offset_m], False)
        deg2 = calc_regress_deg(self.am.close[offset_m:], False)
        deg3 = calc_regress_deg(self.am.close[-10:], False)
        deg_full = calc_regress_deg(self.am.close[offset:], False)

        wave = self.wave(self.am.close[-30:])
        wave_r_sum = np.sum(wave["range"])
        macd = self.am.macd(20, 40, 16)
        calc_data = (dict(
            kdj=[
                round(kdj_val["k"][-1], 2),
                round(kdj_val["d"][-1], 2),
                round(kdj_val["j"][-1], 2)
            ],
            cci_20=self.am.cci(20),
            rsi=self.am.rsi(20),
            adx=self.am.adx(20),
            boll=self.am.boll(20, 3.4),
            macd=[round(macd[0], 2),
                  round(macd[1], 2),
                  round(macd[2], 2)],
            deg40_20=round(deg1, 2),
            deg20_0=round(deg2, 2),
            deg20_10=round(calc_regress_deg(self.am.close[-20:-10], False), 2),
            deg10_0=round(deg3, 2),
            deg30_15=round(calc_regress_deg(self.am.close[-30:-15], False), 2),
            deg15_0=round(calc_regress_deg(self.am.close[-15:], False), 2),
            deg_f=round(deg_full, 2),
            atr=round(self.am.atr(10, length=15), 3),
            tr=round(self.am.atr(1, length=2), 3),
            atr_40=round(self.am.atr(40, length=42), 3),
            time=bar.datetime,
            price=bar.close_price,
            ma=round(ma, 2),
            std_40=round(std_val, 2),
            mean40=round(mean_val, 2),
            mean_std=np.mean(self.std_range.data[-5:]),
            std_10=round(std_val2, 2),
            mean30_10=round(mean_val4, 2),
            mean10=round(mean_val2, 2),
            vol=self.am.volume[-1],
            std_range=self.std_range.data[-1:-5:-1],
            range=self.am.range[-1:-5:-1].tolist(),
            range_sum=np.sum(self.am.range[-5:]),
            pattern=list(
                map(lambda x: KLINE_PATTERN_CHINESE[x],
                    self.pattern_record.keys())),
            ma120t=self.ma120_track,
            ma120t_list=self.ma120_track_list[-1:-10:-1],
            ma120t_sort=sorted(self.ma120_track_list[-20:-1], key=abs),
            ma120t_sum=np.sum(self.ma120_track_list[-20:-1] +
                              [self.ma120_track]),
            ma120t_mean=np.mean(self.ma120_track_list[-20:-1] +
                                [self.ma120_track]),
            ma120t_std=np.std(self.ma120_track_list[-20:-1] +
                              [self.ma120_track]),
            wave_cnt=len(wave),
            wave_r_sum=wave_r_sum,
            atr_mean=np.mean(self.am.atr(20, array=True, length=240)[-200:])))

        return calc_data

    def on_strategy(self, am: ArrayManager, bar: BarData, strategy_list):
        calc_data = self.generate_data(bar)

        order_id = None
        if self.pos == 0:
            for open_strategy in strategy_list:
                if order_id is not None:
                    break
                order_id = open_strategy(am, bar, calc_data)
        else:
            order_id = self.positions.on_strategy(bar, calc_data)

        if order_id is not None:
            offset = -self.offset
            offset_m = int(offset / 2)
            self.tracker["trade_info"].append(
                (self.am.time_array[offset], self.am.time_array[offset_m],
                 bar.datetime, calc_data["deg40_20"], calc_data["deg20_0"]))
            self.request_order.extend(order_id)

        if self.tracker is not None:
            self.tracker["ma_tag_ls"].append(calc_data)

    def on_1min_bar(self, bar: BarData):
        self.am.update_bar(bar)
        am = self.am
        max_len = self.ma_level[-1] + 20
        data = self.am.close[-max_len:-1]
        ma_lvl = []
        for i in self.ma_level:
            ma = self.am.sma(i, True)[-1]
            ma_lvl.append(ma)

        l = len(ma_lvl)
        ma_lvl_tag = []
        now = bar.close_price
        direction = 1 if now > ma_lvl[0] else 0
        ma_lvl_tag.append(direction)
        for i in range(l - 1):
            val = 1 if ma_lvl[i] > ma_lvl[i + 1] else 0
            ma_lvl_tag.append(val)
        bincount_val = np.bincount(np.array(ma_lvl_tag))
        tag_val = 0
        if len(bincount_val) == 2:
            tag_val = bincount_val[1]

        if len(self.ma_tag) < 200:
            self.ma_tag.append(tag_val)
        else:
            self.ma_tag[:-1] = self.ma_tag[1:]
            self.ma_tag[-1] = tag_val
        if self.tracker is not None:
            self.tracker["bar_data"].append(bar)
        self.std_range.update(self.am.range[-1])

        ma120 = self.am.sma(120)

        if bar.close_price >= ma120:
            if self.ma120_track is None:
                self.ma120_track = 1
            elif self.ma120_track > 0:
                self.ma120_track += 1
            else:
                self.ma120_track_list.append(self.ma120_track)
                self.ma120_track = 1
        elif bar.close_price < ma120:
            if self.ma120_track is None:
                self.ma120_track = -1
            elif self.ma120_track < 0:
                self.ma120_track -= 1
            else:
                self.ma120_track_list.append(self.ma120_track)
                self.ma120_track = -1

        if not am.inited or not self.trading:
            return

        self.on_strategy(am, bar, self.open_strategy["1"])
        # median_val = np.median(calc_nums)

        self.put_event()

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

    # def init_order_data(self):
    #     self.order_data = np.array([])

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        print("{}产生了{},价格为{},笔数为{},交易{},pos={}".format(
            order.datetime.strftime("%m/%d %H:%M:%S"),
            order.offset.value + order.direction.value, order.price,
            order.volume, order.status.value, self.pos))

        if order.vt_orderid in self.request_order:
            self.positions.on_order(order)
            if order.status == Status.ALLTRADED or order.status == Status.CANCELLED or order.status == Status.REJECTED:
                self.request_order.remove(order.vt_orderid)
        # if order.status == Status.ALLTRADED or order.status == Status.PARTTRADED:
        #     if order.direction == Direction.LONG:
        #         if self.positions.volumn == 0:
        #             self.positions.close_price = round(order.price * 0.995)
        #         self.positions.volumn += order.volume
        #     elif order.direction == Direction.SHORT:
        #         self.positions.volumn -= order.volume
        #     elif order.direction == Direction.NET:
        #         self.positions.volumn = order.volume

    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
Ejemplo n.º 9
0
class DudlThrust_NewStrategy(CtaTemplate):
    """"""
    author = "yunyu"

    window_min = 15
    rolling_period = 70
    upper_open = 0.5
    lower_open = 0.6
    stop_multiplier = 1.8
    dc_length = 30
    cci_length = 10
    cci_stop = 20
    trailing_tax = 1.8
    fixed_size = 1

    up = 0
    down = 0
    exit_shour = 0
    exit_long = 0
    intra_trade_high = 0
    intra_trade_low = 0
    long_stop = 0
    short_stop = 0
    long_entry = 0
    short_entry = 0
    long_out = 0
    short_out = 0
    cci_value = 0
    ask = 0
    bid = 0

    parameters = [
        "window_min",
        "rolling_period",
        "upper_open",
        "lower_open",
        "stop_multiplier",
        "dc_length",
        "cci_length",
        "cci_stop",
        "trailing_tax",
        "fixed_size",
    ]

    variables = [
        "up", "down", "exit_shour", "exit_long", "intra_trade_high",
        "intra_trade_low", "long_stop", "short_stop", "long_entry",
        "short_entry", "long_out", "short_out", "cci_value"
    ]

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

        self.bg = BarGenerator(on_bar=self.on_bar)
        self.am = ArrayManager(
            (max(self.dc_length, self.rolling_period) + 10) * 60)

        self.bg_xmin = BarGenerator(on_bar=self.on_bar,
                                    window=self.window_min,
                                    on_window_bar=self.on_xmin_bar)
        self.am_xmin = ArrayManager(
            max(self.dc_length, self.rolling_period) + 10)

    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.bg.update_tick(tick)
        self.ask = tick.ask_price_1  # 卖一价
        self.bid = tick.bid_price_1  # 买一价

        self.put_event()

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

        self.exit_shour, self.exit_long = self.am.donchian(self.dc_length * 60)

        if self.pos == 0:
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = bar.low_price

            if self.cci_value > self.cci_stop:
                self.buy(self.up, self.fixed_size, True)

            elif self.cci_value < -self.cci_stop:
                self.short(self.down, self.fixed_size, True)

        elif self.pos > 0:
            self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
            self.intra_trade_low = bar.low_price

            self.long_out = self.intra_trade_high * (1 -
                                                     self.trailing_tax / 100)

            self.long_stop = max(self.long_entry, self.long_out,
                                 self.exit_long)
            self.sell(self.long_stop, abs(self.pos), True)

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

            self.short_out = self.intra_trade_low * (1 +
                                                     self.trailing_tax / 100)

            self.short_stop = min(self.short_entry, self.short_out,
                                  self.exit_shour)
            self.cover(self.short_stop, abs(self.pos), True)

        self.put_event()

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

        if not self.am_xmin.inited:
            return

        self.up, self.down = self.dualthrust(self.am_xmin.high,
                                             self.am_xmin.low,
                                             self.am_xmin.close,
                                             self.am_xmin.open,
                                             self.rolling_period,
                                             self.upper_open, self.lower_open)
        self.cci_value = self.am_xmin.cci(self.cci_length)

        self.atr_value = self.am.atr(16)
        self.put_event()

    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.
        """
        if trade.direction == Direction.LONG:
            long_price = trade.price
            self.long_entry = long_price - self.stop_multiplier * self.atr_value
        else:
            short_price = trade.price
            self.short_entry = short_price + self.stop_multiplier * self.atr_value

        self.put_event()

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

    def market_order(self):
        """"""
        pass
        # self.buy(self.last_tick.limit_up, 1)
        # self.write_log("执行市价单测试")

    def limit_order(self):
        """"""
        pass
        # self.buy(self.last_tick.limit_down, 1)
        # self.write_log("执行限价单测试")

    def stop_order(self):
        """"""
        pass
        # self.buy(self.last_tick.ask_price_1, 1, True)
        # self.write_log("执行停止单测试")

    def dualthrust(self, high, low, close, open, n, k1, k2):
        """
        :param high:
        :param low:
        :param close:
        :return:
        """
        #计算N日最高价的最高价,收盘价的最高价、最低价,最低价的最低价
        hh = high[-n:-1].max()
        lc = close[-n:-1].min()
        hc = close[-n:-1].max()
        ll = low[-n:-1].max()

        #计算range,上下轨的距离前一根K线开盘价的距离
        range = max(hh - lc, hc - ll)

        up = open[-2] + k1 * range
        down = open[-2] - k2 * range

        return up, down
Ejemplo n.º 10
0
    def generate_data(self, am:ArrayManager, bar:BarData):
        offset = -self.offset
        offset_m = int(offset / 2)
        calc_nums = np.array(self.ma_tag[-offset:-1])
        # var_val = np.var(calc_nums)
        std_val = np.std(calc_nums)
        std_val2 = np.std(np.array(self.ma_tag[-10:-1]))
        std_val3 = np.std(np.array(am.range[-30:-10]))
        ma = self.ma_tag[-1]
        
        mean_val = np.mean(calc_nums)
        mean_val2 = np.mean(np.array(self.ma_tag[-5:-1]))
        mean_val3 = np.mean(np.array(self.ma_tag[-20:-1]))
        mean_val4 = np.mean(np.array(self.ma_tag[-30:-5]))
        
        kdj_val = am.kdj()
        has_kdj_recore = False
        k = kdj_val["k"]
        d = kdj_val["d"]
        j = kdj_val["j"]
        if  (k[-1] > 75 and d[-1] > 75 and j[-1] > 75) or \
            (k[-1] < 25 and d[-1] < 25 and j[-1] < 75):
            if (j[-2] < k[-2] or j[-2] < d[-2]) and (j[-1] > k[-1] and j[-1] > d[-1]) \
                or \
            (j[-2] > k[-2] or j[-2] > d[-2]) and (j[-1] < k[-1] and j[-1] < d[-1]):
                has_kdj_recore = True
                t = local_to_eastern(bar.datetime.timestamp())
                self.kdj_record.append((t.strftime("%H:%M:%S"), round(k[-1], 3), round(d[-1], 3), round(j[-1], 3)))

        
        deg1 = calc_regress_deg(am.close[offset : offset_m], False)
        deg2 = calc_regress_deg(am.close[offset_m :], False)
        deg3 = calc_regress_deg(am.close[-10 :], False)
        deg_full = calc_regress_deg(am.close[offset :], False)

        wave = self.wave(am.close[-30:])
        wave_r_sum = np.sum(wave["range"])


        macd=am.macd(20,40, 16)
        calc_data = (dict(
                ma_info=self.ma_info[-1:],
                kdj=[round(kdj_val["k"][-1],2),round(kdj_val["d"][-1],2),round(kdj_val["j"][-1],2)],
                cci_20=am.cci(20),rsi=am.rsi(20),adx=am.adx(20),boll=am.boll(20, 3.4),
                macd=[round(macd[0],2),round(macd[1],2),round(macd[2],2)],
                deg40_20=round(deg1,2), deg20_0=round(deg2,2), deg20_10=round(calc_regress_deg(am.close[-20:-10], False),2), 
                deg30_10=round(calc_regress_deg(am.close[-30:-10], False),2),deg10_0=round(deg3,2),
                deg30_15=round(calc_regress_deg(am.close[-30:-15], False),2), deg15_0=round(calc_regress_deg(am.close[-15:], False),2),deg_f=round(deg_full,2),
                atr=round(am.atr(10, length=15), 3), tr=round(am.atr(1, length=2), 3),atr_40=round(am.atr(40, length=42), 3),
                time=bar.datetime, price=bar.close_price, ma=round(ma, 2), 
                std_40=round(std_val, 2),mean40=round(mean_val,2), mean_std=np.mean(self.std_range.data[-5:]),
                std_10=round(std_val2,2), mean30_10=round(mean_val4,2), mean10=round(mean_val2,2),
                vol=am.volume[-1], std_range=self.std_range.data[-1:-5:-1], range=am.range[-1:-5:-1].tolist(),
                range_sum=np.sum(am.range[-5:]), 
                pattern=list(map(lambda x: KLINE_PATTERN_CHINESE[x], self.pattern_record.keys())),
                ma120t=self.ma120_track, 
                ma120t_list=self.ma120_track_list[-1:-10:-1], 
                ma120t_sort=sorted(self.ma120_track_list[-20:-1], key=abs),
                ma120t_sum=np.sum(self.ma120_track_list[-20:-1] + [self.ma120_track]), 
                ma120t_mean=np.mean(self.ma120_track_list[-20:-1] + [self.ma120_track]),
                ma120t_std=np.std(self.ma120_track_list[-20:-1] + [self.ma120_track]),
                wave_cnt=len(wave), wave_r_sum=wave_r_sum, atr_mean=np.mean(am.atr(20, array=True,length=240)[-200:]),
                kdj_record=self.kdj_record[-10:],
                ))
        if self.ma_info[-1]["ma5"] <= 0.16:
            calc_data["kdj_key"] = True
        return calc_data
Ejemplo n.º 11
0
    def reverse2_strategy(self, am:ArrayManager, bar:BarData, calc_data, setting={"len":40, "atr":40, "atr_valve":0.09, "mid_sign":(10,30)}):
        length = 30
        offset1 = -30
        offset2 = int(-10)
        close = am.close
        deg1 = calc_regress_deg(close[-30:-8], False)
        deg2 = calc_regress_deg(close[-8:], False)
        

        if deg1 > 0 and deg2 > 0 or \
           deg1 < 0 and deg2 < 0:
            return
        
        if not (abs(deg1) > 0.15 and abs(deg2) > 0.15 and (abs(deg1) + abs(deg2)) > 0.35) :
            return

        close = am.close[-length:]
        min_val = np.min(close)
        max_val = np.max(close)
        mid_val =  max_val if deg1 > 0 else min_val
        mid_pos = np.where(close == mid_val)[0][0]

        if mid_pos < setting["mid_sign"][0] or mid_pos > setting["mid_sign"][1]:
            return

        start_val = np.min(close[:mid_pos]) if deg1 > 0 else np.max(close[:mid_pos])
        start_pos = np.where(close == start_val)[0][0]
        l = mid_pos - start_pos

        # pos2 = np.where(close == min_val)[0][0]
        kdj = am.kdj()
        k = kdj["k"][-1]
        d = kdj["d"][-1]
        j = kdj["j"][-1]
        x_fit = reg_util.regress_y_polynomial(close[:mid_pos], zoom=True)
        deg1_remake = calc_regress_deg(x_fit[:abs(mid_pos)], False)
        y_fit = reg_util.regress_y_polynomial(close[mid_pos:], zoom=True)
        deg2_remake = calc_regress_deg(y_fit[:abs(mid_pos)], False)
        # print(start_pos, mid_pos, deg1, deg2, deg1_remake, deg2_remake, l, start_val, mid_val)
        cci = am.cci(20)
        ma60 = am.sma(60)
        if deg2 < 0:
            # if k < 20 and d < 10 and j < 10:
            # if kdj[2] < 10:
            
            if cci < -100 and bar.close_price < ma60:
                if self.pos == 0:
                   calc_data["trade_open"] = "开空,deg={},cci={}".format(deg2, cci)
                   return self.short(bar.close_price, 1, type=OrderType.MARKET)
                elif self.pos > 0:
                   calc_data["trade_close"] = "平多后做空仓,deg={},cci={}".format(deg2, cci)
                   order_id_cover = self.sell(bar.close_price, abs(self.volumn), type=OrderType.MARKET)
                   order_id_buy = self.short(bar.close_price, 1, type=OrderType.MARKET)
                   return order_id_cover.extend(order_id_buy)
        else:
            # if k > 80 and d > 90 and j > 90:
            # if kdj[2] > 90:
            if cci > 100 and bar.close_price > ma60:
                
                if self.pos == 0:
                    calc_data["trade_open"] = "开多,deg={},cci={}".format(deg2, cci)
                    return self.buy(bar.close_price, 1, type=OrderType.MARKET)
                elif self.pos < 0:
                    calc_data["trade_close"] = "平空后多仓,deg={},cci={}".format(deg2, cci)
                    order_id_cover = self.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET)
                    order_id_buy = self.buy(bar.close_price, 1, type=OrderType.MARKET)
                    return order_id_cover.extend(order_id_buy)
Ejemplo n.º 12
0
class MinuteSuperTurtleStrategy(CtaTemplate):
    """
    唐安奇通道策略
    """
    author = "yuya"

    open_window = 15
    entry_window = 28
    exit_window = 7
    atr_window = 4
    cci_window = 10
    risk_level = 0.2

    trading_size = 0
    entry_up = 0
    entry_down = 0
    exit_up = 0
    exit_down = 0
    atr_value = 0
    cci_value = 0

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

    parameters = [
        "open_window", "entry_window", "exit_window", "atr_window",
        "risk_level", "cci_window"
    ]
    variables = [
        "entry_up", "entry_down", "exit_up", "exit_down", "trading_size",
        "atr_value", "cci_value"
    ]

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

        self.bg = BarGenerator(self.on_bar, self.open_window, self.on_hour_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.bg.update_bar(bar)

    def on_hour_bar(self, bar: BarData):
        """"""
        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)
        self.cci_value = self.am.cci(self.cci_window)

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

            if self.atr_value == 0:
                return
            # 反向合约的计算方法,
            atr_risk = talib.ATR(1 / self.am.high, 1 / self.am.low,
                                 1 / self.am.close, self.atr_window)[-1]
            self.trading_size = max(int(self.risk_level / atr_risk), 1)

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

            if self.cci_value > 0:
                self.buy(self.entry_up, self.trading_size, True)

            elif self.cci_value < 0:
                self.short(self.entry_down, self.trading_size, True)

        elif self.pos > 0:
            sell_price = max(self.long_stop, self.exit_down)
            self.sell(sell_price, abs(self.pos), True)

        elif self.pos < 0:
            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

        self.sync_data()

    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
Ejemplo n.º 13
0
class TurtleCCIStrategy(CtaTemplate):
    """基于布林通道的交易策略"""
    className = 'TurtleCCIStrategy'
    author = u'ForwardCapital'

    # 策略参数
    turtleWindow = 20  # 通道窗口数
    trailingPrcnt = 0.4  # 移动止损百分比
    CCIWindow = 14  # 过滤用均线窗口
    ma1Window = 10  # 过滤用均线窗口
    ma2Window = 20  # 过滤用均线窗口
    initDays = 10  # 初始化数据所用的天数
    fixedSize = 1  # 每次交易的数量

    # 策略变量
    periodHigh = 0  # 布林带中轨
    periodLow = 0  # 布林带宽度
    entryUp = 0  # 开仓上轨
    exitUp = 0  # 平仓上轨

    CCIFilter = 0  # 均线过滤
    CCIFilter1 = 0  # 上一期均线

    intraTradeHigh = 0  # 持仓期内的最高点
    intraTradeLow = 0  # 持仓期内的最低点
    longEntry = 0  # 多头开仓
    longExit = 0  # 多头平仓

    orderList = []  # 保存委托代码的列表
    buyOrderID = None
    sellOrderID = None
    shortOrderID = None
    coverOrderID = None

    # 参数列表,保存了参数的名称
    paramList = []

    # 变量列表,保存了变量的名称
    varList = []

    # 同步列表
    syncList = ['pos', 'intraTradeHigh', 'intraTradeLow']

    #----------------------------------------------------------------------
    def __init__(self, ctaEngine, setting):
        """Constructor"""
        super(TurtleCCIStrategy, self).__init__(ctaEngine, setting)

        self.bm = BarGenerator(self.on_bar, 15, self.onFiveBar)
        self.am = ArrayManager()

    #----------------------------------------------------------------------
    def on_init(self):
        """初始化策略(必须由用户继承实现)"""
        self.write_log(u'策略初始化')

        # 载入历史数据,并采用回放计算的方式初始化策略数值
        self.load_bar(self.initDays)

        self.put_event()

    #----------------------------------------------------------------------
    def on_start(self):
        """启动策略(必须由用户继承实现)"""
        self.write_log(u'策略启动')
        self.put_event()

    #----------------------------------------------------------------------
    def on_stop(self):
        """停止策略(必须由用户继承实现)"""
        self.write_log(u'策略停止')
        self.put_event()

    #----------------------------------------------------------------------
    def on_tick(self, tick):
        """收到行情TICK推送(必须由用户继承实现)"""
        self.bm.update_tick(tick)

    #----------------------------------------------------------------------
    def on_bar(self, bar):
        """收到Bar推送(必须由用户继承实现)"""
        self.bm.update_bar(bar)

    #----------------------------------------------------------------------
    def orderIDConvert(self, orderList):
        if not orderList:
            return []
        else:
            return orderList[0]

    #----------------------------------------------------------------------
    def onFiveBar(self, bar, lastTick):
        """收到5分钟K线"""
        # 保存K线数据
        self.am.update_bar(bar)
        if not self.am.inited or not self.trading:
            return

        # 撤销之前发出的尚未成交的委托(包括限价单和停止单)
        print(u'onFiveBar↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓,datetime:%s' % bar.datetime)
        # 计算指标数值
        self.entryUp = max(self.am.high[-self.turtleWindow:])
        self.entryDown = min(self.am.low[-self.turtleWindow:])
        self.entryUp = self.bollMid + self.bollStd * self.entryDev
        self.exitUp = self.bollMid + self.bollStd * self.exitDev

        ma1 = self.am.sma(self.ma1Window, False)
        ma2 = self.am.sma(self.ma2Window, False)
        cci = self.am.cci(self.CCIWindow, True)

        # 判断是否要进行交易
        if not self.buyOrderID or not self.shortOrderID:
            if self.pos == 0:
                # 下开仓单
                if ma1 > ma2:
                    self.buyOrderID = self.buy(self.entryUp, self.fixedSize,
                                               True)
                    self.buyOrderID = self.orderIDConvert(self.buyOrderID)
                    print('None order!!!buyOrderID is : %s ' % self.buyOrderID)
                    if self.buyOrderID:
                        self.orderList.append(self.buyOrderID)
                else:
                    self.shortOrderID = self.short(self.entryDown,
                                                   self.fixedSize, True)
                    self.shortOrderID = self.orderIDConvert(self.shortOrderID)
                    print('None order!!!shortOrderID is : %s ' %
                          self.shortOrderID)
                    if self.shortOrderID:
                        self.orderList.append(self.shortOrderID)

            elif self.pos > 0:
                # 下平仓单
                if cci[-1] < 100 and cci[-2] > 100:
                    # ######此处实盘需要修改发单价格
                    self.sellOrderID = self.sell(bar.low * 0.9, self.fixedSize)
                    self.sellOrderID = self.orderIDConvert(self.sellOrderID)
                    print('order None!!!sellOrderID is : %s ' %
                          self.sellOrderID)
                    if self.sellOrderID:
                        self.orderList.append(self.sellOrderID)
            elif self.pos < 0:
                # 下平仓单
                if cci[-1] > -100 and cci[-2] < -100:
                    # ######此处实盘需要修改发单价格
                    self.coverOrderID = self.cover(bar.high * 0.9,
                                                   self.fixedSize)
                    self.coverOrderID = self.orderIDConvert(self.coverOrderID)
                    print('order None!!!coverOrderID is : %s ' %
                          self.coverOrderID)
                    if self.coverOrderID:
                        self.orderList.append(self.coverOrderID)
        else:
            if self.buyOrderID in self.orderList or self.shortOrderID in self.orderList:
                self.cancel_all()
                # 下开仓单
                if ma1 > ma2:
                    self.buyOrderID = self.buy(self.entryUp, self.fixedSize,
                                               True)
                    self.buyOrderID = self.orderIDConvert(self.buyOrderID)
                    print('buyOrderID is : %s ' % self.buyOrderID)
                    if self.buyOrderID:
                        self.orderList.append(self.buyOrderID)
                else:
                    self.shortOrderID = self.short(self.entryDown,
                                                   self.fixedSize, True)
                    self.shortOrderID = self.orderIDConvert(self.shortOrderID)
                    print('shortOrderID is : %s ' % self.shortOrderID)
                    if self.shortOrderID:
                        self.orderList.append(self.shortOrderID)
            else:
                if self.pos > 0:
                    # 下平仓单
                    if cci[-1] < 100 and cci[-2] > 100:
                        # ######此处实盘需要修改发单价格
                        self.sellOrderID = self.sell(bar.low * 0.9,
                                                     self.fixedSize)
                        self.sellOrderID = self.orderIDConvert(
                            self.sellOrderID)
                        print('order None!!!sellOrderID is : %s ' %
                              self.sellOrderID)
                        if self.sellOrderID:
                            self.orderList.append(self.sellOrderID)
                elif self.pos < 0:
                    # 下平仓单
                    if cci[-1] > -100 and cci[-2] < -100:
                        # ######此处实盘需要修改发单价格
                        self.coverOrderID = self.cover(bar.high * 0.9,
                                                       self.fixedSize)
                        self.coverOrderID = self.orderIDConvert(
                            self.coverOrderID)
                        print('order None!!!coverOrderID is : %s ' %
                              self.coverOrderID)
                        if self.coverOrderID:
                            self.orderList.append(self.coverOrderID)
                elif self.pos == 0:
                    # 下开仓单
                    if ma1 > ma2:
                        self.buyOrderID = self.buy(self.entryUp,
                                                   self.fixedSize, True)
                        self.buyOrderID = self.orderIDConvert(self.buyOrderID)
                        print('buyOrderID is : %s ' % self.buyOrderID)
                        if self.buyOrderID:
                            self.orderList.append(self.buyOrderID)
                    else:
                        self.shortOrderID = self.short(self.entryDown,
                                                       self.fixedSize, True)
                        self.shortOrderID = self.orderIDConvert(
                            self.shortOrderID)
                        print('shortOrderID is : %s ' % self.shortOrderID)
                        if self.shortOrderID:
                            self.orderList.append(self.shortOrderID)

        # 发出状态更新事件
        # self.putEvent()

    #----------------------------------------------------------------------
    def on_order(self, order):
        """收到委托变化推送(必须由用户继承实现)"""
        pass

    #----------------------------------------------------------------------
    def on_trade(self, trade):
        """收到成交推送(必须由用户继承实现)"""
        print(u'成交推送:%s' % trade)
        self.orderList.remove(trade.tradeID)
        # 发出状态更新事件
        # self.putEvent()

    #----------------------------------------------------------------------
    def on_stop_order(self, so):
        """停止单推送"""
        print(u'StopOrder回报,stopOrderID:%s, status:%s' %
              (so.stopOrderID, so.status))
        if so.status == StopOrderStatus.CANCELLED or so.status == StopOrderStatus.TRIGGERED:
            self.orderList.remove(so.stopOrderID)
        pass
class Boll_kk_vix_simple_Strategy(CtaTemplate):
    """
    本策略为反向策略,币本位  Reverse 反向
    """

    author = "yunya"

    open_window = 5
    xminute_window = 15
    com_length = 450
    exit_dc_length = 10
    fast_sma_length = 45
    slow_sma_length = 110
    cci_length = 30
    cci_exit = 26
    sl_multiplier = 8.0
    fixed_size = 1

    bollkk_ema = 0
    bollkk_up = 0
    bollkk_down = 0
    bollkk_width = 0
    cci_vlue = 0
    long_stop = 0
    short_stop = 0
    exit_up = 0
    exit_down = 0
    atr_value = 0
    long_entry = 0
    short_entry = 0
    ma_trend = 0
    exit_dc_long = 0
    exit_dc_short = 0
    intra_trade_high = 0
    intra_trade_low = 0

    parameters = [
        "open_window",
        "xminute_window",
        "com_length",
        "fast_sma_length",
        "slow_sma_length",
        "cci_length",
        "cci_exit",
        "exit_dc_length",
        "sl_multiplier",
        "fixed_size",
    ]

    variables = [
        "bollkk_ema",
        "bollkk_up",
        "bollkk_down",
        "bollkk_width",
        "cci_vlue",
        "long_stop",
        "short_stop",
        "exit_up",
        "exit_down",
        "atr_value",
        "long_entry",
        "short_entry",
        "ma_trend",
    ]

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

        self.bg_xminute = BarGenerator(on_bar=self.on_bar,
                                       window=self.xminute_window,
                                       on_window_bar=self.on_xminute_bar,
                                       interval=Interval.MINUTE)
        self.am_xminute = ArrayManager(self.com_length + 10)
        self.bg = BarGenerator(self.on_bar, self.open_window, self.on_open_bar)
        self.am = 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.bg_xminute.update_tick(tick)

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

    def on_open_bar(self, bar: BarData):
        """
        :param bar:
        :return:
        """
        # 先使用挂单全撤的粗化订单管理
        self.cancel_all()

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

        if self.pos == 0:
            # 根据布林带宽度动态调整仓位大小
            # self.trading_size = max(int(self.risk_level / self.xminute_com_width), 1)
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = bar.low_price
            if self.cci_value > self.cci_exit and self.ma_trend > 0:
                self.buy(self.bollkk_up, self.fixed_size, True)

            elif self.cci_value < -self.cci_exit and self.ma_trend < 0:
                self.short(self.bollkk_down, self.fixed_size, True)

        elif self.pos > 0:
            self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
            self.intra_trade_low = bar.low_price

            exit_long_stop = self.intra_trade_high - self.bollkk_width * self.sl_multiplier
            exit_long_dc = max(exit_long_stop, self.exit_dc_long)
            self.exit_up = max(exit_long_dc, self.long_stop)
            self.sell(self.exit_up, abs(self.pos), True)

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

            exit_short_stop = self.intra_trade_low + self.bollkk_width * self.sl_multiplier
            exit_shout_dc = min(exit_short_stop, self.exit_dc_short)
            self.exit_down = min(exit_shout_dc, self.short_stop)
            self.cover(self.exit_down, abs(self.pos), True)

        self.put_event()
        self.sync_data()

    def on_xminute_bar(self, bar: BarData):
        """
        :param bar:
        :return:
        """
        # x分钟 多策略合合成的通道线
        self.am_xminute.update_bar(bar)

        if not self.am_xminute.inited:
            return

        bollkk_ema_value, self.bollkk_up, self.bollkk_down, = self.boll_kk_combination(
            high=self.am_xminute.high[:-1],
            close=self.am_xminute.close[:-1],
            low=self.am_xminute.low[:-1],
            com_length=self.com_length)

        # 计算开平信号
        self.current_close = self.am_xminute.close[-1]
        self.last_close = self.am_xminute.close[-2]
        self.bollkk_ema = bollkk_ema_value[-1]

        self.bollkk_width = abs(self.bollkk_up - self.bollkk_down)

        self.cci_value = self.am_xminute.cci(self.cci_length)

        self.fast_ma = self.am_xminute.sma(self.fast_sma_length)
        self.slow_ma = self.am_xminute.sma(self.slow_sma_length)

        if self.fast_ma > self.slow_ma:
            self.ma_trend = 1
        else:
            self.ma_trend = -1
        self.atr_value = self.am_xminute.atr(30)
        self.exit_dc_short, self.exit_dc_long = self.am_xminute.donchian(
            self.exit_dc_length)
        self.sync_data()
        self.put_event()

    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.
        """
        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

        self.sync_data()

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

    def boll_kk_combination(self, high, close, low, com_length):
        """
        通过计算收盘价与收盘价均线之间的倍数,来自动调整boll 、kk 的通过宽度
        """

        # 计算组合均线
        bollkk_ema = talib.EMA(close, com_length)

        # 计算自适布林带
        boll_std = talib.STDDEV(close, com_length)
        boll_dev = abs(close - bollkk_ema) / boll_std

        boll_up = bollkk_ema + boll_dev * boll_std
        boll_down = bollkk_ema - boll_dev * boll_std

        # 计算自适肯特通道
        kk_atr = talib.ATR(high, low, close, com_length)
        kk_dev = abs(close - bollkk_ema) / kk_atr

        kk_up = bollkk_ema + kk_atr * kk_dev
        kk_down = bollkk_ema - kk_atr * kk_dev

        bollkk_up = max(boll_up[-1], kk_up[-1])
        bollkk_down = min(boll_down[-1], kk_down[-1])

        return bollkk_ema, bollkk_up, bollkk_down,