Example #1
0
    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()
Example #2
0
    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()
Example #3
0
    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()
Example #4
0
    def __init__(self, rsi_window: int, rsi_level: float):
        """Constructor"""
        super(RsiSignal, self).__init__()

        self.rsi_window = rsi_window
        self.rsi_level = rsi_level
        self.rsi_long = 50 + self.rsi_level
        self.rsi_short = 50 - self.rsi_level

        self.bg = BarGenerator(self.on_bar)
        self.am = ArrayManager()
Example #5
0
    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()
Example #6
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(self.fast_window)
        slow_ma = self.am.sma(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)
Example #7
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)
Example #8
0
class MarketStationary(CtaTemplate):
    """"""
    author = ""

    stationary_threshold = 4 / 1000

    market_open_time = time(hour=9, minute=30)
    start_record_time_m = time(hour=9, minute=30)
    start_trade_time_m = time(hour=10, minute=20)
    exit_time_m = time(hour=11, minute=30)
    start_trade_time_a = time(hour=13, minute=33)
    exit_time_a = time(hour=14, minute=55)

    fixed_size = 1
    pct_array_m = []
    pct_array_a = []
    open_price = 0
    draw_back_mean_m = 0
    draw_back_inverse_mean_m = 0
    draw_back_inverse_mean_a = 0
    stationary_value_m = 0
    draw_back_mean_a = 0
    draw_back_inverse_a = 0
    stationary_value_m = 0
    stationary_value_a = 0
    exit_loss = 5 / 1000
    bar_num = 0

    long_order_record_m = []
    short_order_record_m = []
    long_order_record_a = []
    short_order_record_a = []


    trend_bool_m = False
    trend_bool_a = False
    first_time_m = True
    first_time_a = True


    parameters = ['stationary_threshold']
    variables = ['stationary_value_m', 'stationary_value_a', 'trend_bool']

    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.am = ArrayManager(size=300)

        self.long_order_record_m = []
        self.short_order_record_m = []
        self.long_order_record_a = []
        self.short_order_record_a = []
        self.pct_array_m = []
        self.pct_array_a = []
    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)

    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

        am = self.am

        if bar.datetime.time() == self.market_open_time:
            self.open_price = bar.close_price
        if bar.datetime.time() == self.start_trade_time_m:
            self.bar_num = 0
        elif bar.datetime.time() < self.start_trade_time_a:
            self.bar_num += 1
        elif bar.datetime.time() >= self.exit_time_a:
            self.bar_num = 0

        if self.open_price > 0:

            if bar.datetime.time() == self.start_trade_time_m:

                price_array = am.close[-self.bar_num:]
                draw_back_record = []
                draw_back_inverse_record = []
                for ind in range(self.bar_num):
                    if ind < self.bar_num-1:

                        self.pct_array_m = (price_array-price_array[ind])/price_array[ind]
                        print(self.pct_array_m)
                        draw_back = max(self.pct_array_m[ind+1:])
                        draw_back_inverse = -min(self.pct_array_m[ind+1:])
                        draw_back_record.append(draw_back)
                        draw_back_inverse_record.append(draw_back_inverse)


                self.draw_back_mean_m = np.mean(draw_back_record)
                self.draw_back_inverse_mean_m = np.mean(draw_back_inverse_record)
                self.stationary_value_m = np.min([self.draw_back_mean_m, self.draw_back_inverse_mean_m])

                if self.stationary_value_m < self.stationary_threshold:
                    self.trend_bool_m = True

            elif bar.datetime.time() < self.exit_time_m:
                if self.trend_bool_m:
                    if self.pos == 0 and self.first_time_m:
                        if bar.close_price > self.open_price:
                            self.buy(bar.close_price + 5, self.fixed_size)
                            self.long_order_record_m.append(bar.close_price + 5)
                        elif bar.close_price < self.open_price:
                            self.short(bar.close_price - 5, self.fixed_size)
                            self.short_order_record_m.append(bar.close_price - 5)

                    elif self.pos > 0:
                        self.first_time_m = False
                        buy_order_price = self.long_order_record_m[-1]
                        if bar.close_price <= buy_order_price * (1 - self.exit_loss):
                            self.sell(bar.close_price * 0.99, abs(self.pos))

                    elif self.pos < 0:
                        self.first_time_m = False
                        sell_order_price = self.short_order_record_m[-1]
                        if bar.close_price >= sell_order_price * (1 + self.exit_loss):
                            self.cover(bar.close_price * 1.01, abs(self.pos))

            elif self.exit_time_m <= bar.datetime.time() < self.start_trade_time_a:
                if self.pos > 0:
                    self.sell(bar.close_price * 0.99, abs(self.pos))
                elif self.pos < 0:
                    self.cover(bar.close_price * 1.01, abs(self.pos))
                self.trend_bool_m = False
                self.first_time_m = True
            elif bar.datetime.time() == self.start_trade_time_a:
                price_array = am.close[-self.bar_num:]
                draw_back_record = []
                draw_back_inverse_record = []
                for ind in range(self.bar_num):
                    if ind < self.bar_num-1:
                        self.pct_array_a = (price_array-price_array[ind])/price_array[ind]
                        draw_back = max(self.pct_array_a[ind+1:])
                        draw_back_inverse = -min(self.pct_array_a[ind+1:])
                        draw_back_record.append(draw_back)
                        draw_back_inverse_record.append(draw_back_inverse)

                self.draw_back_mean_a = np.mean(draw_back_record)
                self.draw_back_inverse_mean_a = np.mean(draw_back_inverse_record)
                self.stationary_value_a = np.min([self.draw_back_mean_a, self.draw_back_inverse_mean_a])
                if self.stationary_value_a < self.stationary_threshold:
                    self.trend_bool_a = True
            elif self.start_trade_time_a <= bar.datetime.time() < self.exit_time_a:
                if self.trend_bool_a:
                    if self.pos == 0 and self.first_time_a:
                        if bar.close_price > self.open_price:
                            self.buy(bar.close_price + 5, self.fixed_size)
                            self.long_order_record_a.append(bar.close_price + 5)
                        elif bar.close_price < self.open_price:
                            self.short(bar.close_price - 5, self.fixed_size)
                            self.short_order_record_a.append(bar.close_price - 5)

                    elif self.pos > 0:
                        self.first_time_a = False
                        buy_order_price = self.long_order_record_a[-1]
                        if bar.close_price <= buy_order_price * (1 - self.exit_loss):
                            self.sell(bar.close_price * 0.99, abs(self.pos))

                    elif self.pos < 0:
                        self.first_time_a = False
                        sell_order_price = self.short_order_record_a[-1]
                        if bar.close_price >= sell_order_price * (1 + self.exit_loss):
                            self.cover(bar.close_price * 1.01, abs(self.pos))
            elif bar.datetime.time() >= self.exit_time_a:
                if self.pos > 0:
                    self.sell(bar.close_price * 0.99, abs(self.pos))
                elif self.pos < 0:
                    self.cover(bar.close_price * 1.01, abs(self.pos))
                self.trend_bool_a = False
                self.first_time_a = True
                self.open_price = 0
        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
Example #9
0
class CincoAtrStrategy(CtaTemplate):
    """"""

    author = "tonywang_efun"

    fixed_size = 1
    bar_window = 26
    boll_window = 39
    boll_dev = 1.9
    rsi_window = 10
    rsi_long = 74
    rsi_short = 37
    atr_window = 30
    atr_stop_multiplier = 1.5

    boll_up = 0
    boll_down = 0
    rsi_value = 0
    trading_size = 0
    intra_trade_high = 0
    intra_trade_low = 0
    long_stop = 0
    short_stop = 0
    atr_value = 0

    parameters = [
        "fixed_size", "bar_window", "boll_window", "boll_dev", "rsi_window",
        "rsi_long", "rsi_short", "atr_window", "atr_stop_multiplier"
    ]

    variables = [
        "boll_up", "boll_down", "rsi_value", "atr_value", "intra_trade_high",
        "intra_trade_low", "long_stop", "short_stop"
    ]

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

        self.bg = BarGenerator(self.on_bar, self.bar_window, self.on_xmin_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.update_tick(tick)

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

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

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

        self.rsi_value = self.am.rsi(self.rsi_window)
        self.atr_value = self.am.atr(self.atr_window)
        self.boll_up, self.boll_down = self.am.boll(self.boll_window,
                                                    self.boll_dev)

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

            if self.rsi_value >= self.rsi_long:
                self.buy(self.boll_up, self.fixed_size, stop=True)

            if self.rsi_value <= self.rsi_short:
                self.short(self.boll_down, self.fixed_size, stop=True)

        elif self.pos > 0:
            self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
            self.long_stop = self.intra_trade_high - self.atr_value * self.atr_stop_multiplier
            self.sell(self.long_stop, abs(self.pos), stop=True)

        else:
            self.intra_trade_low = min(self.intra_trade_low, bar.low_price)
            self.short_stop = self.intra_trade_low + self.atr_value * self.atr_stop_multiplier
            self.cover(self.short_stop, abs(self.pos), stop=True)

        self.put_event()

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

    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
Example #10
0
class FbbStrategy(CtaTemplate):
    """"""

    author = "feng.shao"

    boll_window = 20  #
    boll_dev = 2.0  #
    boll_bw_limit = 0.01
    fixed_size: float = 0.2  # 单笔buy 暂时固定为总资产的 千分之 1~4  (风险随之增加)
    limit_amt = 10.0  # 最小交易资金10 USDT -binance

    #BB
    boll_up = 0
    boll_down = 0
    boll_mid = 0
    boll_pb = 0
    boll_bw = 0

    #kdj

    k = 0
    d = 0
    j = 0

    last_boll_pb = 0

    parameters = [
        "boll_window",
        "boll_dev",
        # "boll_dev_2",
        # "boll_pb_sal",
        "boll_bw_limit",
        "fixed_size"
    ]
    variables = [
        # "boll_up",
        # "boll_down",
        # "boll_mid",
        "boll_pb",
        # "boll_bw",
        # "boll_up_2",
        # "boll_down_2",
        # "boll_mid_2",
        # "boll_pb_2",
        # "boll_bw_2",
    ]

    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, 15, self.on_mins_bar)
        self.am = ArrayManager()

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

    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_mins_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.cancel_all()

        am = self.am
        am.update_bar(bar)

        if not am.inited:
            return

        # start
        self.get_boll(bar)
        self.get_kdj()

        print(
            str(self.k) + "  -  " + str(self.d) + "  -  " + str(self.j) +
            "  -  " + bar.datetime.strftime("%Y-%m-%d %H:%M:%S"))

        # 低于 boll_down 并且width 不小于limit 买入
        if self.boll_pb <= 0 and self.boll_bw > self.boll_bw_limit:
            self.buy(bar.close_price,
                     self.check_minimum_size(bar.close_price, self.fixed_size),
                     False)

        if self.pos > 0:
            # 上穿 up 卖出信号
            if self.last_boll_pb < 1 <= self.boll_pb and self.boll_bw < self.boll_bw_limit:
                self.sell(bar.close_price, self.pos, False)
            # 未达up 而下穿 mid 卖出
            if self.last_boll_pb > 0.5 >= self.boll_pb and self.boll_bw < self.boll_bw_limit:
                self.sell(bar.close_price, self.pos, False)
            # down 下方 ,width 很小 卖出
            if self.boll_pb <= 0 and self.boll_bw <= self.boll_bw_limit:
                self.sell(bar.close_price, self.pos, False)

        self.last_boll_pb = self.boll_pb

        #     self.short(bar.close_price, self.fixed_size, False)

        #     self.cover(bar.close_price, self.pos, False)

        self.put_event()

    def check_minimum_size(self, price: float, order_size) -> float:
        min_size = self.size_by_limit_amt(self.limit_amt, price)
        return max(order_size, min_size)

    def kdj_signal(self):
        if self.d <= self.k < 20:
            return True

    def get_boll(self, bar: BarData):
        self.boll_up, self.boll_mid, self.boll_down = self.am.boll(
            self.boll_window, self.boll_dev)
        self.boll_pb = self.percentbeta(bar.close_price, self.boll_up,
                                        self.boll_down)
        self.boll_bw = self.bandwidth(self.boll_up, self.boll_mid,
                                      self.boll_down)

    def get_kdj(self):
        self.k, self.d, self.j = self.am.kdj()

    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

    def percentbeta(self, close: float, up: float, low: float) -> float:
        """
        %b of boll
        """
        pb = (close - low) / (up - low)

        return pb

    def bandwidth(self, up: float, mid: float, low: float) -> float:
        """
        bandwidth of boll
        """
        bw = (up - low) / mid

        return bw

    def size_by_limit_amt(self, limit_amt: float, price: float) -> float:

        return math.ceil(limit_amt / price * 1000000) / 1000000
Example #11
0
 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.am = ArrayManager()
Example #12
0
class DoubleDayM30M1Strategy(CtaTemplate):
    """
    使用1m线合成 日线、30分钟、1分钟三种数据,并根据各自ma叠加进行卖卖的策略
    """
    author = "fsksf"
    window_mn = 30  # n分钟线
    fast_window_day = 3
    fast_window_m30 = 3
    fast_window_m1 = 3
    slow_window_day = 5
    slow_window_m30 = 5
    slow_window_m1 = 5

    fast_ma_day = 0.0
    fast_ma_m30 = 0.0
    fast_ma_m1 = 0.0

    slow_ma_day = 0.0
    slow_ma_m30 = 0.0
    slow_ma_m1 = 0.0

    parameters = [
        "fast_window_day", "fast_window_m30", "fast_window_m1",
        "slow_window_day", "slow_window_m30", "slow_window_m1", "window_mn"
    ]
    variables = [
        "fast_ma_day", "slow_ma_day", "fast_ma_m30", "slow_ma_m30",
        "fast_ma_m1", "slow_ma_m1"
    ]

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

        self.day_bar_gen = BarGenerator(lambda x: None,
                                        interval=Interval.DAILY,
                                        window=1,
                                        on_window_bar=self.on_day_bar)
        self.m30_bar_gen = BarGenerator(self.on_bar,
                                        interval=Interval.MINUTE,
                                        window=self.window_mn,
                                        on_window_bar=self.on_m30_bar)
        self.day_am = ArrayManager(size=self.slow_window_day + 1)
        self.m30_am = ArrayManager(size=self.slow_window_m30 + 1)
        self.m1_am = ArrayManager(size=self.slow_window_m1 + 1)

    def on_m30_bar(self, bar):
        self.m30_am.update_bar(bar)

    def on_day_bar(self, bar):
        print(bar.__dict__)
        self.day_am.update_bar(bar)

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

    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.m30_bar_gen.update_tick(tick)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        # if self.cta_engine.gateway_name == "BACKTESTING":
        # update window
        self.m30_bar_gen.update_bar(bar)
        self.day_bar_gen.update_bar(bar)
        self.m1_am.update_bar(bar)
        if not (self.day_am.inited and self.m30_am.inited
                and self.m1_am.inited):
            return

        # 最后一个bar实时更新的,计算ma后删除
        # self.day_am.update_bar(self.day_bar_gen.last_bar)
        fast_ma_day = self.day_am.sma(self.fast_window_day, array=True)
        slow_ma_day = self.day_am.sma(self.slow_window_day, array=True)

        # self.m30_am.update_bar(self.m30_bar_gen.last_bar)
        fast_ma_m30 = self.m30_am.sma(self.fast_window_m30, array=True)
        slow_ma_m30 = self.m30_am.sma(self.slow_window_m30, array=True)

        fast_ma_m1 = self.m1_am.sma(self.fast_window_m1, array=True)
        slow_ma_m1 = self.m1_am.sma(self.slow_window_m1, array=True)

        self.fast_ma_day = fast_ma_day[-1]
        self.fast_ma_m30 = fast_ma_m30[-1]
        self.fast_ma_m1 = fast_ma_m1[-1]

        self.slow_ma_day = slow_ma_day[-1]
        self.slow_ma_m30 = slow_ma_m30[-1]
        self.slow_ma_m1 = slow_ma_m1[-1]

        cross_over = fast_ma_day[-2] < slow_ma_day[-2] and fast_ma_day[-1] > slow_ma_day[-1] and \
            fast_ma_m30[-2] < slow_ma_m30[-2] and fast_ma_m30[-1] > slow_ma_m30[-1] and \
            fast_ma_m1[-2] < slow_ma_m1[-2] and fast_ma_m1[-1] > slow_ma_m1[-1]
        cross_below = fast_ma_day[-2] > slow_ma_day[-2] and fast_ma_day[-1] < slow_ma_day[-1] and \
            fast_ma_m30[-2] > slow_ma_m30[-2] and fast_ma_m30[-1] < slow_ma_m30[-1] and \
            fast_ma_m1[-2] > slow_ma_m1[-2] and fast_ma_m1[-1] < slow_ma_m1[-1]

        if cross_over:
            self.write_log(f'触发买入:{str(bar.datetime)}')
            # print(f'触发买入:{str(bar.datetime)}')
            self.write_log(
                f'day: ma_fast: {fast_ma_day[-2:]}, slow: {slow_ma_day[-2:]} close_price: {self.day_am.close_array}'
            )
            self.write_log(
                f'30m: ma_fast: {fast_ma_m30[-2:]}, slow: {slow_ma_m30[-2:]} close_price: {self.m30_am.close_array}'
            )
            self.write_log(
                f'1m: ma_fast: {fast_ma_m1[-2:]}, slow: {slow_ma_m1[-2:]} close_price: {self.m1_am.close_array}'
            )
            if self.pos == 0:
                self.buy(bar.close_price, 1)
            elif self.pos < 0:
                self.cover(bar.close_price, 1)
                self.buy(bar.close_price, 1)

        elif cross_below:
            if self.pos == 0:
                self.short(bar.close_price, 1)
            elif self.pos > 0:
                self.sell(bar.close_price, 1)
                self.short(bar.close_price, 1)

        # self.day_am.remove_last_bar()
        # self.m30_am.remove_last_bar()

        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
Example #13
0
class CuatroStrategy(CtaTemplate):
    """"""
    author = "vn_trader"

    boll_window = 20
    boll_dev = 1.8
    rsi_window = 14
    rsi_signal = 19
    fast_window = 4
    slow_window = 26
    trailing_long = 0.5
    trailing_short = 0.3
    fixed_size = 1

    boll_up = 0
    boll_down = 0
    rsi_value = 0
    rsi_long = 0
    rsi_short = 0
    fast_ma = 0
    slow_ma = 0
    ma_trend = 0
    intra_trade_high = 0
    intra_trade_low = 0
    long_stop = 0
    short_stop = 0

    parameters = [
        "boll_window", "boll_dev", "rsi_window", "rsi_signal", "fast_window",
        "slow_window", "trailing_long", "trailing_short", "fixed_size"
    ]

    variables = [
        "boll_up", "boll_down", "rsi_value", "rsi_long", "rsi_short",
        "fast_ma", "slow_ma", "ma_trend", "intra_trade_high",
        "intra_trade_low", "long_stop", "short_stop"
    ]

    def __init__(
        self,
        cta_engine,
        strategy_name: str,
        vt_symbol: str,
        setting: dict,
    ):
        """"""
        super().__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.bg15 = BarGenerator(self.on_bar, 15, self.on_15min_bar)

        self.am5 = ArrayManager()
        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 or not self.am15.inited:
            return

        self.boll_up, self.boll_down = self.am5.boll(self.boll_window,
                                                     self.boll_dev)
        self.rsi_value = self.am5.rsi(self.rsi_window)
        boll_width = self.boll_up - self.boll_down

        # No position
        if self.pos == 0:
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = bar.low_price
            self.long_stop = 0
            self.short_stop = 0

            if self.ma_trend > 0 and self.rsi_value >= self.rsi_long:
                self.buy(self.boll_up, self.fixed_size, stop=True)

            if self.ma_trend < 0 and self.rsi_value <= self.rsi_short:
                self.short(self.boll_down, self.fixed_size, stop=True)

        # Long position
        elif self.pos > 0:
            self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
            self.long_stop = (self.intra_trade_high -
                              self.trailing_long * boll_width)
            self.sell(self.long_stop, abs(self.pos), stop=True)

        # Short position
        else:
            self.intra_trade_low = min(self.intra_trade_low, bar.low_price)
            self.short_stop = (self.intra_trade_low +
                               self.trailing_short * boll_width)
            self.cover(self.short, abs(self.pos), stop=True)

        self.put_event()

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

        self.fast_ma = self.am15.sma(self.fast_window)
        self.slow_ma = self.am15.sma(self.slow_window)

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

        self.put_event()

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

    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
Example #14
0
class BollVix(CtaTemplate):
    """"""
    author = "yunya"

    open_window = 15
    boll_length = 530
    fixed_size = 1

    boll_mid_current = 0
    boll_mid_last = 0
    boll_up_current = 0
    boll_up_last = 0
    boll_down_current = 0
    boll_down_last = 0
    target_pos = 0
    pos_inited = 0
    boll_mid = 0

    # 画图专用
    time_list = []
    open_list = []
    high_list = []
    low_list = []
    close_list = []
    volume_list = []
    up_list = []
    down_list = []
    mid_list = []
    mid_new_list = []
    bias_value_list = []
    bias_list = []
    singnal_plot = []
    singnal_list = None
    singnal = None

    plot_echarts = {}

    parameters = [
        "open_window",
        "boll_length",
        "fixed_size",
    ]

    variables = [
        "boll_mid_current", "boll_mid_last", "boll_up_current", "boll_up_last",
        "boll_down_current", "boll_down_last", "pos_inited", "target_pos"
    ]

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

        self.bg = NewBarGenerator(self.on_bar,
                                  self.open_window,
                                  self.on_minute_bar,
                                  interval=Interval.MINUTE)
        self.am = ArrayManager(self.boll_length * 2)

        self.up_array: np.ndarray = np.zeros(5)
        self.down_array: np.ndarray = np.zeros(5)
        self.boll_inited = False
        self.boll_count = 0

        self.engine_type = self.get_engine_type()
        self.vt_orderids = []
        self.order_price = 0

        self.pos_inited = 0

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

    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)

        # 只有实盘交易才使用BestLimit算法
        if self.engine_type != EngineType.LIVE:
            return

        #  当前没有仓位
        order_volume_open = self.target_pos - self.pos

        if not order_volume_open:
            return

        if order_volume_open > 0:
            if not self.vt_orderids:
                self.order_price = tick.bid_price_1
                vt_orderids = self.buy(self.order_price,
                                       abs(order_volume_open))
                self.vt_orderids.extend(vt_orderids)
            elif self.order_price != tick.bid_price_1:
                for vt_orderid in self.vt_orderids:
                    self.cancel_order(vt_orderid)

        elif order_volume_open < 0:
            if not self.vt_orderids:
                self.order_price = tick.ask_price_1
                vt_orderids = self.short(self.order_price,
                                         abs(order_volume_open))
                self.vt_orderids.extend(vt_orderids)
            elif self.order_price != tick.ask_price_1:
                for vt_orderid in self.vt_orderids:
                    self.cancel_order(vt_orderid)

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

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

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

        # 计算布林
        sma_array = self.am.sma(self.boll_length, True)
        std_array = self.am.std(self.boll_length, True)
        dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1]
        dev_max = dev[-self.boll_length:].max()
        up = sma_array + std_array * dev_max
        down = sma_array - std_array * dev_max

        boll_mid_array = self.am.sma(self.boll_length, True)

        # 计算数组
        self.boll_mid = boll_mid_array[-2]
        self.boll_up_current = up[-1]
        self.boll_up_last = up[-2]
        self.boll_down_current = down[-1]
        self.boll_down_last = down[-2]

        if not self.pos:
            self.pos_inited = 0

            if self.am.close[-1] > self.boll_up_current and self.am.close[
                    -2] <= self.boll_up_last:

                if self.engine_type == EngineType.BACKTESTING:
                    self.buy(bar.close_price, self.fixed_size)
                else:
                    self.target_pos = self.fixed_size
                    print("没有仓位,我开多")

            elif self.am.close[-1] < self.boll_down_current and self.am.close[
                    -2] >= self.boll_down_last:

                if self.engine_type == EngineType.BACKTESTING:
                    self.short(bar.close_price, self.fixed_size)
                else:
                    self.target_pos = -self.fixed_size
                    print("没有仓位,我开空")

        elif self.pos > 0:
            self.sell(self.boll_mid, abs(self.pos), True)

        elif self.pos < 0:
            self.cover(self.boll_mid, abs(self.pos), True)

        # 画图专用
        if self.singnal != self.singnal_list:
            plot = self.singnal
        else:
            plot = None

        self.time_list.append(bar.datetime)
        self.open_list.append(bar.open_price)
        self.high_list.append(bar.high_price)
        self.low_list.append(bar.low_price)
        self.close_list.append(bar.close_price)
        self.volume_list.append(bar.volume)
        self.up_list.append(self.boll_up_current)
        self.down_list.append(self.boll_down_current)
        self.mid_list.append(self.boll_mid)
        self.singnal_plot.append(plot)

        self.plot_echarts = {
            "datetime": self.time_list,
            "open": self.open_list,
            "high": self.high_list,
            "low": self.low_list,
            "close": self.close_list,
            "volume": self.low_list,
            "boll_up": self.up_list,
            "boll_down": self.down_list,
            "boll_mid": self.mid_list,
            "signal": self.singnal_plot
        }
        self.singnal_list = self.singnal

        self.put_event()

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

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        if trade.direction.value == Direction.LONG.value:
            if trade.offset.value == Offset.OPEN.value:
                self.singnal = 1

            elif trade.offset.value == Offset.CLOSE.value:
                self.singnal = 0

            else:
                self.singnal = None

        elif trade.direction.value == Direction.SHORT.value:
            if trade.offset.value == Offset.OPEN.value:
                self.singnal = -1

            elif trade.offset.value == Offset.CLOSE.value:
                self.singnal = 0

            else:
                self.singnal = None

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

    def boll_calculate(self):
        """
        计算布林
        :return:
        """

        if not self.boll_inited:
            self.boll_count += 1
            if self.boll_count >= 6:
                self.boll_inited = True

        self.up_array[:-1] = self.up_array[1:]
        self.down_array[:-1] = self.down_array[1:]

        sma_array = self.am.sma(self.boll_length, True)
        std_array = self.am.std(self.boll_length, True)
        dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1]
        dev_max = dev[-self.boll_length:].max()
        up = sma_array[-1] + std_array[-1] * dev_max
        down = sma_array[-1] - std_array[-1] * dev_max

        self.up_array[-1] = up
        self.down_array[-1] = down
Example #15
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
Example #16
0
class CincoStrategy(CtaTemplate):
    """"""

    author = "vnpy"

    boll_window = 42
    boll_dev = 2.2
    trailing_long = 0.65
    trailing_short = 0.65
    atr_window = 4
    risk_level = 300

    boll_up = 0
    boll_down = 0
    trading_size = 0
    intra_trade_high = 0
    intra_trade_low = 0
    long_stop = 0
    short_stop = 0
    atr_value = 0

    parameters = [
        "boll_window",
        "boll_dev",
        "trailing_long",
        "trailing_short",
        "atr_window",
        "risk_level"
    ]

    variables = [
        "boll_up",
        "boll_down",
        "trading_size",
        "intra_trade_high",
        "intra_trade_low",
        "long_stop",
        "short_stop",
        "atr_value"
    ]

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

        self.bg = BarGenerator(self.on_bar, 15, self.on_15min_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.update_tick(tick)

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

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

        self.boll_up, self.boll_down = self.am.boll(self.boll_window, self.boll_dev)
        boll_width = self.boll_up - self.boll_down

        if not self.pos:
            self.atr_value = self.am.atr(self.atr_window)
            self.trading_size = int(self.risk_level / self.atr_value)

            self.intra_trade_high = bar.high_price
            self.intra_trade_low = bar.low_price
            self.long_stop = 0
            self.short_stop = 0

            self.buy(self.boll_up, self.trading_size, stop=True)
            self.short(self.boll_down, self.trading_size, stop=True)
        
        elif self.pos > 0:
            self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
            self.long_stop = self.intra_trade_high - self.trailing_long * boll_width
            self.sell(self.long_stop, abs(self.pos), stop=True)
        
        else:
            self.intra_trade_low = min(self.intra_trade_low, bar.low_price)
            self.short_stop = self.intra_trade_low + self.trailing_short * boll_width
            self.cover(self.short_stop, abs(self.pos), stop=True)
        
        self.put_event()

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        self.put_event()
    
    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
Example #17
0
    def __init__(self, strategy, KCircle=1):
        """Constructor"""
        super(TripleMaCrossSignal, self).__init__(strategy)

        self.bg = BarGenerator(self.onBar, KCircle, self.onXminBar)
        self.am = ArrayManager(size=100)
Example #18
0
class TripleMaSignal(CtaSignalPatch):
    """TripleMaSignal"""

    # 策略参数
    # 三均线长度设置
    maWindow1 = 10
    maWindow2 = 30
    maWindow3 = 90

    # ma最新值
    ma1 = 0
    ma2 = 0
    ma3 = 0

    #----------------------------------------------------------------------
    def __init__(self, strategy, KCircle=1):
        """Constructor"""
        super(TripleMaSignal, self).__init__(strategy)

        self.bg = BarGenerator(self.onBar, KCircle, self.onXminBar)
        self.am = ArrayManager(size=100)

    #----------------------------------------------------------------------
    def onBar(self, bar):
        """K线更新"""
        self.bg.update_bar(bar)

    #----------------------------------------------------------------------
    def onXminBar(self, bar=BarData):
        """X Min Bar"""

        # 保存K线数据
        am = self.am
        am.update_bar(bar)
        if not am.inited:
            self.set_signal_pos(0)
            return

        if self.trading:
            self.updateSignal()

    #----------------------------------------------------------------------
    def updateSignal(self):
        """X Min Bar"""
        self.set_signal_pos(self.getSignal())
        pass

    #----------------------------------------------------------------------
    def getSignal(self):
        """生成信号"""

        ma1Array = self.am.sma(self.maWindow1, True)
        self.ma10 = ma1Array[-2]
        self.ma1 = ma1Array[-1]

        self.ma2 = self.am.sma(self.maWindow2, False)
        self.ma3 = self.am.sma(self.maWindow3, False)

        # 开多,上穿
        if self.ma1 > self.ma2 > self.ma3:
            return 1
        # 开空,下穿
        elif self.ma1 < self.ma2 < self.ma3:
            return -1

        return 0
Example #19
0
class EmaStrategy(CtaTemplate):
    author = "CHENG LI"

    trade_money = 1000000
    fixed_size = 1
    bars = []
    # exit_time = time(hour=14, minute=55)

    # for EMA algorithm
    fast_window = 12
    slow_window = 48
    fast_ema0 = 0.0
    fast_ema1 = 0.0
    slow_ema0 = 0.0
    slow_ema1 = 0.0

    # 菲阿里四价:昨日高点、昨日低点、昨天收盘、今天开盘
    yesterday_high = 0.0
    yesterday_low = 0.0
    yesterday_close = 0.0
    today_open = 0.0

    short_stop_loss = 0.0
    long_stop_loss = 0.0

    parameters = ["fast_window", "slow_window", "trade_money"]
    variables = [
        "fast_ema0", "fast_ema1", "slow_ema0", "slow_ema1", "yesterday_high",
        "yesterday_low", "yesterday_close", "today_open", "short_stop_loss",
        "long_stop_loss"
    ]

    def __init__(self, cta_engine: Any, strategy_name: str, vt_symbol: str,
                 setting: dict):
        super(EmaStrategy, self).__init__(cta_engine, strategy_name, vt_symbol,
                                          setting)

        self.bg_hour = BarGenerator(self.on_bar,
                                    window=1,
                                    on_window_bar=self.on_hour_bar,
                                    interval=Interval.HOUR)
        self.bg_day = BarGenerator(self.on_bar,
                                   window=24,
                                   on_window_bar=self.on_day_bar,
                                   interval=Interval.HOUR)

        self.am_hour = ArrayManager(100)
        self.am_day = ArrayManager(2)

        self.bars = []

    def on_init(self):
        print("on init")
        self.load_bar(10)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        print("on_start strategy")

    def on_tick(self, tick: TickData):

        self.bg_hour.update_tick(tick)
        self.bg_day.update_tick(tick)

    def on_bar(self, bar: BarData):

        self.bg_hour.update_bar(bar)
        self.bg_day.update_bar(bar)

    def on_day_bar(self, bar: BarData):
        """
        菲阿里四价算法实现
        """
        # bar 初始化
        self.cancel_all()
        am = self.am_day
        am.update_bar(bar)
        if not am.inited:
            self.bars.append(bar)
            return

        self.bars.append(bar)
        if len(self.bars) <= 2:
            return
        else:
            self.bars.pop(0)
        last_bar = self.bars[-2]

        # compute 4 different prices from data
        self.yesterday_high = last_bar.high_price
        self.yesterday_low = last_bar.low_price
        self.yesterday_close = last_bar.close_price
        self.today_open = bar.open_price

        # 设置多头止损
        if self.today_open / self.yesterday_high > 1.005:  # 如果当天开盘价大于昨天最高价
            self.long_stop_loss = self.yesterday_high
        elif self.today_open / self.yesterday_high < 0.995:  # 如果当天开盘价小于昨天最高价
            self.long_stop_loss = self.today_open
        else:  # 如果当天开盘价接近于昨天最高价
            self.long_stop_loss = (self.yesterday_high +
                                   self.yesterday_low) / 2  # 设置多头止损为昨天中间价

        # 设置空头止损
        if self.today_open / self.yesterday_low < 0.995:  # 如果当天开盘价小于昨天最低价
            self.short_stop_loss = self.yesterday_low
        elif self.today_open / self.yesterday_low > 1.005:  # 如果当天开盘价大于昨天最低价
            self.short_stop_loss = self.today_open
        else:  # 如果当天开盘价接近于昨天最低价
            self.short_stop_loss = (self.yesterday_high +
                                    self.yesterday_low) / 2

        self.put_event()

    def on_hour_bar(self, bar: BarData):

        # 确保day bar初始化
        self.am_hour.update_bar(bar)
        if not self.am_hour.inited:
            return
        self.am_day.update_bar(bar)
        if not self.am_day.inited:
            return

        # compute exp. moving average
        fast_ema = self.am_hour.ema(self.fast_window, array=True)
        self.fast_ema0 = fast_ema[-1]  # at T
        self.fast_ema1 = fast_ema[-2]  # at T-1

        slow_ema = self.am_hour.ema(self.slow_window, array=True)
        self.slow_ema0 = slow_ema[-1]
        self.slow_ema1 = slow_ema[-2]

        # identify trend: 1:bullish, -1:bearish, 0:sideways
        if self.fast_ema0 > self.slow_ema0 and self.fast_ema1 < self.slow_ema1:
            trend_status = 1
        elif self.fast_ema0 < self.slow_ema0 and self.fast_ema1 > self.slow_ema1:
            trend_status = -1
        else:
            trend_status = 0

        self.fixed_size = 0.1 * self.trade_money / bar.close_price
        # if bar.datetime.time() < self.exit_time:
        if self.pos == 0:  # 没有仓位
            if trend_status == 1:
                if bar.close_price > self.yesterday_high:
                    self.buy(bar.close_price * 1.005, self.fixed_size)  # 做多
            elif trend_status == -1:
                if bar.close_price < self.yesterday_low:
                    self.short(bar.close_price * 0.995, self.fixed_size)  # 做空

        elif self.pos > 0:  # 有多头仓位
            if bar.close_price < self.long_stop_loss:  # 如果当前价格小于多头止损线
                if trend_status == -1:
                    self.sell(bar.close_price * 0.995,
                              abs(self.pos))  # 先平多头仓位,再反手开空
                    self.short(bar.close_price * 0.995, self.fixed_size)  # 做空
                else:
                    self.sell(bar.close_price * 0.995, abs(self.pos))  # 止
            else:
                # 继续做多
                if trend_status == 1:
                    if bar.close_price > self.yesterday_high:
                        self.buy(bar.close_price * 1.005,
                                 self.fixed_size)  # 做多

        elif self.pos < 0:  # 有空头的仓位
            if bar.close_price > self.short_stop_loss:  # 如果当前价格大于空头止损线
                if trend_status == 1:
                    self.cover(bar.close_price * 1.005,
                               abs(self.pos))  # 先平空头仓位, 然后反手开多
                    self.buy(bar.close_price * 1.005,
                             self.fixed_size)  # 做多按照开仓的资金来计算
                else:
                    self.cover(bar.close_price * 1.005, abs(self.pos))
            else:
                # 继续做空
                if trend_status == -1:
                    if bar.close_price < self.yesterday_low:
                        self.short(bar.close_price * 0.995, self.fixed_size)

        self.put_event()

    def on_trade(self, trade: TradeData):
        pass

    def on_order(self, order: OrderData):
        pass

    def on_stop_order(self, stop_order: StopOrder):
        pass
Example #20
0
class RsiAdaptStrategy(CtaTemplate):
    """
	策略逻辑:
	一、、过虑信号  (小时周期)
	使用rsiboll来判断信号强弱

	二、开单信号 (分钟周期)
	1、使用布林上下轨作为开单条件

	三、止损
	使用动态布林中轨止损

	"""
    author = "yunya"

    min_window = 45
    open_window = 15
    rsi_length = 23
    kk_length = 80
    kk_dev = 2.0
    trading_size = 1
    atr_length = 30

    rsi_entry = 0
    kk_up = 0
    kk_down = 0
    long_stop = 0
    short_stop = 0
    rsi_value = 0
    rsi_up = 0
    rsi_dow = 0
    ema_mid = 0
    ema_length_new = 0
    current_ema_mid = 0
    last_ema_mid = 0
    current_close = 0
    last_close = 0
    front_close = 0
    exit_long = 0
    exit_short = 0
    long_entry = 0
    short_entry = 0
    long_stop_trade = 0
    short_stop_drade = 0
    exit_long_nex = 0
    exit_long_last = 0
    exit_short_nex = 0
    exit_short_last = 0
    atr_value = 0

    parameters = [
        "open_window",
        "min_window",
        "rsi_length",
        "kk_length",
        "kk_dev",
        "trading_size",
        "atr_length",
    ]

    variables = [
        "rsi_entry",
        "long_stop",
        "short_stop",
        "rsi_value",
        "rsi_up",
        "rsi_dow",
        "ema_mid",
        "ema_length_new",
        "current_ema_mid",
        "last_ema_mid",
        "current_close",
        "last_close",
        "front_close",
        "exit_long",
        "exit_short",
        "long_entry",
        "short_entry",
        "long_stop_trade",
        "short_stop_drade",
        "exit_long_nex",
        "exit_long_last",
        "exit_short_nex",
        "exit_short_last",
    ]

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

        self.bg_xminute = NewBarGenerator(on_bar=self.on_bar,
                                          window=self.min_window,
                                          on_window_bar=self.on_xminute_bar)
        self.am_xminute = ArrayManager(self.kk_length * 2 + 10)

        self.bg_open = NewBarGenerator(on_bar=self.on_bar,
                                       window=self.open_window,
                                       on_window_bar=self.on_5min_bar)
        self.am_open = ArrayManager()

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

    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_open.update_tick(tick)

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

    def on_5min_bar(self, bar: BarData):
        """
		:param bar: 
		:type bar: 
		:return: 
		:rtype: 
		"""
        self.cancel_all()
        self.am_open.update_bar(bar)

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

        ema_mid_array = self.am_open.ema(self.kk_length, True)
        atr = self.am_open.atr(self.kk_length, True)
        kk_up_array = ema_mid_array + atr * self.kk_dev
        kk_down_array = ema_mid_array - atr * self.kk_dev

        self.ema_mid = ema_mid_array[-1]
        self.kk_up = kk_up_array[-1]
        self.kk_down = kk_down_array[-1]

        self.current_close = self.am_open.close[-1]
        self.last_close = self.am_open.close[-2]
        self.front_close = self.am_open.close[-3]

        if not self.pos:
            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.kk_length

            self.atr_value = self.am_open.atr(self.atr_length)

            if self.rsi_entry > 0:
                self.buy(self.kk_up, self.trading_size, True)
                self.write_log(
                    f"下多单:{bar.datetime}, {self.kk_up}, {self.trading_size}")

            elif self.rsi_entry < 0:
                self.short(self.kk_down, self.trading_size, True)
                self.write_log(
                    f"下多单:{bar.datetime}, {self.kk_down}, {self.trading_size}")

        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)

            ema_mid_new = self.am_xminute.sma(self.ema_length_new, True)
            self.current_ema_mid = ema_mid_new[-1]
            self.last_ema_mid = ema_mid_new[-2]
            # 仓位是long 时,如果价格下穿新布林中轨
            con1 = bar.close_price < self.current_ema_mid
            con2 = bar.close_price >= self.last_ema_mid
            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.kk_length

                    # 下穿新均线,以原布林均线挂出停止单,避免快速下跌而无法止损
                    self.exit_long = self.ema_mid

                else:
                    # 收盘价在两条均线平均价上方,以当前收盘价挂出限价单
                    if bar.close_price > (
                        (self.ema_mid + self.current_ema_mid) / 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
            # print(f"我是多单,收盘价在两个中轨均值下方,以原中轨挂止损单:{self.exit_long},")
            else:
                self.exit_long = self.ema_mid
            self.long_stop = max(self.exit_long, self.long_stop_trade)
            self.sell(self.long_stop, abs(self.pos), True)

        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)

            ema_mid_new = self.am_xminute.sma(self.ema_length_new, True)
            self.current_ema_mid = ema_mid_new[-1]
            self.last_ema_mid = ema_mid_new[-2]

            # 仓位是short 时,如果价格上穿新布林中轨
            con1 = bar.close_price > self.current_ema_mid
            con2 = bar.close_price <= self.last_ema_mid
            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.kk_length

                    self.exit_short = self.ema_mid

                else:
                    if bar.close_price < (self.ema_mid +
                                          self.current_ema_mid / 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.short_stop = min(self.exit_short, self.short_stop_drade)
            self.cover(self.short_stop, abs(self.pos), True)

        self.sync_data()
        self.put_event()

    def on_xminute_bar(self, bar: BarData):
        """
		:param bar:
		:return:
		"""
        self.am_xminute.update_bar(bar)
        if not self.am_xminute.inited:
            return

        ema_array = talib.EMA(self.am_xminute.close, self.rsi_length)
        std_array = talib.EMA(self.am_xminute.close, self.rsi_length)

        dev_array = abs(self.am_xminute.close[:-1] -
                        ema_array[:-1]) / std_array[:-1]
        dev_max = max(dev_array[-self.rsi_length:])

        rsi_array = talib.RSI(self.am_xminute.close[:-1], self.rsi_length)
        rsi_up_array = rsi_array + rsi_array * dev_max
        rsi_dow_array = rsi_array - rsi_array * dev_max

        rsi_value_array = self.am_xminute.rsi(self.rsi_length, True)
        self.rsi_up = rsi_up_array[-1]
        self.rsi_dow = rsi_dow_array[-1]

        self.rsi_value = rsi_value_array[-1]
        current_rsi = rsi_value_array[-1]
        last_rsi = rsi_value_array[-2]
        current_rsi_up = rsi_up_array[-1]
        last_rsi_up = rsi_up_array[-2]
        current_rsi_down = rsi_dow_array[-1]
        last_rsi_down = rsi_dow_array[-2]

        con1 = current_rsi > current_rsi_up
        con2 = last_rsi <= last_rsi_up
        con3 = current_rsi < current_rsi_down
        con4 = last_rsi >= last_rsi_down

        if con1 > con2:
            self.rsi_entry = 1
        elif con3 and con4:
            self.rsi_entry = -1

        self.sync_data()

    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_trade = self.long_entry - 2 * self.atr_value
        else:
            self.short_entry = trade.price
            self.short_stop_drade = self.short_entry + 2 * self.atr_value

        self.sync_data()

    def on_order(self, order: OrderData):
        """
		订单更新回调
		Callback of new order data update.
		"""

        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
		Callback of stop order update.
		"""
        self.put_event()
Example #21
0
class GridStockCtaStrategy(CtaTemplate):
    """
    策略逻辑:
        1、网格数量: 21  ,网格总限量资金: 3000
        2、网格操作区间: 10%
        3、网格跟踪指标 : 首次成交价格
        4、网格上限: 网格跟踪指标 * (1 + 网格操作区间)
        5、网格下限: 网格跟踪指标 * ( 1 - 网格操作区间)
        6、网格步进 :( 网格上限 - 网格下限 ) / 网格数量
        7、仓位单元 : 网格总限量 / 网格数量
        8、网格启动、停止开关:振幅超过百分比例,网格暂时停止,等待8小时后重新启动
    """
    author = "yunya"

    open_window = 2
    xminute_window = 5
    xhour_window = 1
    position_proportion = 1.0  # 每次加仓比例
    grid_amount = 20  # 网格最大量
    grid_usdt_size = 20  # 首次使用多少USDT购买币
    grid_usdt_capital = 200  # 网格最多使用的资金量USDT
    grid_buy_price = 1.0  # 网格距离
    grid_sell_price = 1.0
    pay_up = 2  # 偏移pricetick
    buy_callback = 0.5  # 买入回调幅度
    sell_callback = 0.5  # 卖出回调幅度
    sleep_switch = False  # 睡眠开关,默认关
    grid_amplitude = 5.0  # 振幅超过比例停止策略8小时
    stop_time = 8  # 策略暂停时间

    price_change = 0  # 网格基准线(每次成交价)
    current_volume = 0  # 当前下单币的数量
    target_pos = 0
    buy_benchmark = 0
    sell_benchmark = 0
    buy_price = 0  # 买入成交价
    sell_price = 0  # 平仓成交价
    grid_usdt_volume = 0
    cumulative_usdt_volume = 0  # 累计使用金额
    grid_count = 0  # 网格次数
    intra_trade_high = 0  # 最高价
    trade_high = 0
    intra_trade_low = 0  # 最低价
    trade_low = 0
    amplitude = 0  # 振幅
    tick_price = 0
    time_stop = 0  # 计算得到的重新启动时间
    buy_fixed_size = 0
    sell_fixed_size = 0
    len_tick_decimal = 0  # 获取当前币种盘口最小下单量
    amplitude_inited = False  # 振幅标签
    first_time_inited = False  # 判断是否是首次启动,如果是首次启动,清空初始化数据
    min_volume = 0
    buy_tick = 0
    short_tick = 0

    parameters = [
        "open_window",
        "xminute_window",
        "xhour_window",
        "position_proportion",
        "grid_amount",
        "grid_usdt_size",
        "grid_usdt_capital",
        "grid_buy_price",
        "grid_sell_price",
        "pay_up",
        "buy_callback",
        "sell_callback",
        "sleep_switch",
        "grid_amplitude",
        "stop_time",
    ]

    variables = [
        "price_change", "current_volume", "buy_benchmark", "sell_benchmark",
        "grid_usdt_volume", "cumulative_usdt_volume", "grid_count",
        "amplitude", "amplitude_inited", "first_time_inited", "min_volume"
    ]

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

        self.exchangematerial = ExchangeMaterial.OKEX_MATERIAL
        self.bg_open = BarGenerator(self.on_bar, self.open_window,
                                    self.on_open_bar)
        self.am_open = ArrayManager()

        self.bg_minute = BarGenerator(self.on_bar, self.xminute_window,
                                      self.on_mintue_bar)
        self.am_minute = ArrayManager()

        self.bg_xhour = BarGenerator(self.on_bar, self.xhour_window,
                                     self.on_xhour_bar, Interval.HOUR)
        self.am_xhour = ArrayManager()

        # 计算每次使用资金量
        self.cumulative_usdt_volume = 0
        self.target_pos = 0
        self.grid_usdt_volume = 0
        self.amplitude = 0
        self.tick_price = 0
        self.engine_type = self.get_engine_type()  # 测试还是实盘
        self.vt_orderids = []

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        contract = self.cta_engine.main_engine.get_contract(self.vt_symbol)
        self.min_volume = contract.min_volume
        self.len_tick_decimal = len(str(self.min_volume).split(".")[1])
        self.load_bar(1)

    def on_start(self):
        """
        Callback when strategy is started.
        """
        self.write_log("策略启动")
        if not self.first_time_inited:
            self.grid_count = 0
            self.current_volume = 0
            self.cumulative_usdt_volume = 0
            self.first_time_inited = True
        self.amplitude_inited = False

    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_open.update_tick(tick)
        self.buy_tick = tick.bid_price_1
        self.short_tick = tick.ask_price_1

    def on_bar(self, bar: BarData):
        """"""
        self.bg_open.update_bar(bar)
        self.bg_minute.update_bar(bar)
        self.bg_xhour.update_bar(bar)

    def on_open_bar(self, bar: BarData):
        """"""
        self.am_open.update_bar(bar)

        if not self.am_open.inited:
            return

        self.cancel_all()
        # 判断 休眠时间
        if self.amplitude_inited:
            if bar.datetime > self.time_stop:
                self.amplitude_inited = False
            return

        # 根据网格次数加仓 , 根据USDT量和价格计算出可购买的币数量
        if self.position_proportion > 0 and self.grid_count > 0:
            self.grid_usdt_volume = self.grid_usdt_size * (
                1 + (self.position_proportion / 100) * self.grid_count)
        else:
            self.grid_usdt_volume = self.grid_usdt_size
        self.current_volume = self.grid_usdt_volume / bar.close_price

        if not self.pos or self.pos < self.min_volume:
            """
            1、如果空仓,以当前价格买入一份做为底仓
            2、总网格次数减一
            """
            self.buy_price = bar.close_price - self.tick_price * self.pay_up
            # 取四舍五入
            self.current_volume = float(
                format(self.current_volume, f".{self.len_tick_decimal}f"))
            USDT = bar.close_price * self.min_volume

            if self.current_volume < self.min_volume:
                msg = f"当前下单小于:{self.vt_symbol} 最小下单最,请重新设置最小下单量!最下小量为:{self.min_volume},需要约:{USDT}枚USDT"
                self.write_log(msg)
                return

            vt_orderid = self.buy(self.buy_price,
                                  self.current_volume,
                                  order_type=OrderType.MakerPostOnly)
            # 把挂单信息添加到列表末尾
            self.vt_orderids.extend(vt_orderid)

            self.intra_trade_high = bar.high_price
            self.intra_trade_low = bar.low_price

            # 清空
            self.cumulative_usdt_volume = 0
            self.grid_count = 0
            self.current_volume = 0

        else:
            if bar.close_price < self.buy_benchmark:
                """
                当前收盘价低于下个网格买入价格时,判断买入时机:
                1、价格在上次买入后,中间没有卖出的过程,
                2、
                """
                if self.cumulative_usdt_volume < self.grid_usdt_capital:
                    """
                    买在最低位
                    """
                    self.intra_trade_high = bar.high_price
                    self.intra_trade_low = min(self.intra_trade_low,
                                               bar.low_price)
                    self.trade_low = self.intra_trade_low * (
                        1 + self.buy_callback / 100)

                    if self.trade_low < self.buy_benchmark:
                        self.buy_price = self.trade_low
                    else:
                        self.buy_price = self.buy_benchmark
                    # 取四舍五入
                    self.current_volume = float(
                        format(self.current_volume,
                               f".{self.len_tick_decimal}f"))
                    vt_orderid = self.buy(self.buy_price,
                                          self.current_volume,
                                          order_type=OrderType.MakerPostOnly)
                    self.vt_orderids.extend(vt_orderid)

            elif bar.close_price > self.sell_benchmark:
                if self.pos > 0:
                    """
                    卖在最高位
                    """
                    self.intra_trade_high = max(self.intra_trade_high,
                                                bar.high_price)
                    self.intra_trade_low = bar.low_price
                    self.trade_high = self.intra_trade_high * (
                        1 - self.sell_callback / 100)

                    if self.trade_high > self.sell_benchmark:
                        self.sell_price = self.trade_high
                    else:
                        self.sell_price = self.sell_benchmark

                    # 判断 如果理论(不含手续费)self.pos 比交易所成交反馈回来的量小时,使用交易所反馈回来的量下单,同时把理论值设置为零
                    if self.pos > self.current_volume * 1.2:
                        self.sell_fixed_size = self.current_volume
                    else:
                        self.sell_fixed_size = self.pos

                    vt_orderid = self.sell(self.sell_price,
                                           abs(self.sell_fixed_size),
                                           order_type=OrderType.MakerPostOnly)
                    self.vt_orderids.extend(vt_orderid)

        # 更新图形界面
        self.put_event()

    def on_mintue_bar(self, bar: BarData):
        """
        :return:
        """
        self.am_minute.update_bar(bar)

        if not self.am_minute.inited:
            return
        # 计算振幅
        if self.sleep_switch:
            self.amplitude = (bar.high_price - bar.low_price) / bar.high_price

            # 如果振幅超过指定值,策略撤掉所有挂单,并且进入休眠状态
            if self.amplitude > self.grid_amplitude / 100:
                self.amplitude_inited = True
                self.time_stop = bar.datetime + datetime.timedelta(
                    hours=self.stop_time)
                time_stop = self.time_stop.replace(tzinfo=UTC_TZ)
                self.write_log(
                    f"当前市场波动较大,"
                    f"振幅为:{self.amplitude},超过设置值,策略进入休眠,"
                    f"休眠到:{time_stop.strftime('%Y-%m-%d %H:%M:%S')}时重新启动策略")

    def on_xhour_bar(self, bar: BarData):
        """
        :return:
        """
        self.am_xhour.update_bar(bar)

        if not self.am_xhour.inited:
            return
        pass

    def on_order(self, order: OrderData):
        """
        判断是否完全成交,如果成交获取成交数量,计数器加减
        移除成交、拒绝、撤单的订单号
        """
        if order.vt_orderid in self.vt_orderids:
            if order.status == Status.ALLTRADED:
                if order.direction == Direction.LONG:
                    self.target_pos = order.traded
                    self.grid_count += 1
                    self.cumulative_usdt_volume += self.grid_usdt_volume
                    # 买入时,实际得到币量为总买量减手续费
                    msg = f"开仓,成交量为:{self.target_pos}"
                    self.write_log(msg)
                    self.target_pos = 0
                else:
                    self.target_pos = -order.traded
                    self.grid_count -= 1
                    self.cumulative_usdt_volume -= self.grid_usdt_volume
                    msg = f"平仓,成交量为:{self.target_pos}"
                    self.write_log(msg)
                    self.target_pos = 0

            if not order.is_active():
                self.vt_orderids.remove(order.vt_orderid)
        self.sync_data()

    def on_trade(self, trade: TradeData):
        """
        获取交易价格做为基准线
        """
        if trade.direction == Direction.LONG:
            self.price_change = trade.price  # 成交最高价
            msg = f"开仓,成交价格为:{self.price_change}"
            self.write_log(msg)
        else:
            self.price_change = trade.price
            msg = f"平仓,成交价格为:{self.price_change}"
            self.write_log(msg)
        # 计算当前网格买入价格和卖出价格
        self.buy_benchmark = self.price_change * (1 -
                                                  self.grid_buy_price / 100)
        self.sell_benchmark = self.price_change * (1 +
                                                   self.grid_sell_price / 100)
        msg = f"下个网格加仓价格线为:{self.buy_benchmark},平仓位价格线为: {self.sell_benchmark}"
        self.write_log(msg)

        self.sync_data()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
Example #22
0
class MultiTimeframeStrategy(CtaTemplate):
    """"""
    author = "用Python的交易员"

    rsi_signal = 20
    rsi_window = 14
    fast_window = 5
    slow_window = 20
    fixed_size = 1
    # 5min级bar下限价单时的加点,应该为最小变动价的整数倍
    bar_add = 2

    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","bar_add"]

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

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

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

        # 维护两组bg/am,对应不同时间周期
        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 + self.bar_add, self.fixed_size)
            elif self.ma_trend < 0 and self.rsi_value <= self.rsi_short:
                self.short(bar.close_price - self.bar_add, self.fixed_size)

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

        elif self.pos < 0:
            if self.ma_trend > 0 or self.rsi_value > 50:
                self.cover(bar.close_price + self.bar_add, 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(self.fast_window)
        self.slow_ma = self.am15.sma(self.slow_window)

        # 根据15min级的MA设置方向
        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
Example #23
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
Example #24
0
class Mike_Dc_Strategy(CtaTemplate):
    """"""

    author = "yunya"

    exchange : Exchange = ""
    mike_window = 1
    mike_length = 30
    dc_length = 10
    kk_length = 20
    kk_dev = 2.0
    sl_trade = 2
    fixed_size = 1

    ask = 0
    bid = 0

    ema_mid = 0
    ema_hh = 0
    ema_ll = 0

    ema_wr = 0  #初级压力线
    ema_mr = 0  #中级压力线
    ema_sr = 0  #高级压力线

    ema_ws = 0  #初级支撑线
    ema_ms = 0  #中级支撑线
    ema_ss = 0  #高级支撑线

    dc_up = 0
    dc_down = 0
    kk_up = 0
    kk_down = 0

    atr_value = 0
    long_stop = 0
    short_stop = 0
    long_stop_trade = 0
    short_stop_trade = 0
    long_enrty = 0
    short_enrty = 0
    ema_entry_crossover = 0
    boll_entry_crossover = 0
    boll_width = 0


    parameters = [
                    "exchange",
                    "mike_window",
                    "mike_length",
                    "dc_length",
                    "kk_length",
                    "kk_dev",
                    "sl_trade",
                    "fixed_size",
                    ]

    variables = [
                    "long_stop",
                    "short_stop",
                    "ema_entry_crossover",
                    "boll_entry_crossover",
                    "boll_width",
                    "ema_mid",
                    "ema_hh",
                    "ema_ll",
                    "ema_wr",
                    "ema_mr",
                    "ema_sr",
                    "ema_ws",
                    "ema_ms",
                    "ema_ss",
                    ]

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

        self.bg_xhour = BarGenerator(
                                on_bar=self.on_bar,
                                window=self.mike_window,
                                on_window_bar=self.on_hour_bar,
                                interval=Interval.HOUR
                            )
        self.am_xhour = ArrayManager(max(self.dc_length ,self.kk_length) + 10)

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

    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_xhour.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_xhour.update_bar(bar)

    def on_hour_bar(self, bar: BarData):
        """
        计算 mike 指标线
        :param_xhour bar:
        :return:
        """

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

        # 计算mike压力支撑线
        ema_array = (self.am_xhour.close[:-1] + self.am_xhour.high[:-1] + self.am_xhour.low[:-1]) / 3
        self.ema_mid = ema_array[-1]
        self.ema_hh = self.am_xhour.high[-self.mike_length:-1].max()
        self.ema_ll = self.am_xhour.low[-self.mike_length:-1].min()

        self.ema_wr = self.ema_mid + (self.ema_mid - self.ema_ll)
        self.ema_mr = self.ema_mid + (self.ema_hh - self.ema_ll)
        self.ema_sr = 2 * self.ema_hh - self.ema_ll

        self.ema_ws = self.ema_mid - (self.ema_hh - self.ema_mid)
        self.ema_ms = self.ema_mid - (self.ema_hh - self.ema_ll)
        self.ema_ss = 2 * self.ema_ll - self.ema_hh

        if (self.am_xhour.close[-1] > self.ema_sr) or (self.ema_ms < self.am_xhour.close[-1] < self.ema_ws):
            self.ema_entry_crossover = 1

        elif (self.am_xhour.close[-1] < self.ema_ss) or (self.ema_mr > self.am_xhour.close[-1] > self.ema_wr):
            self.ema_entry_crossover = -1

        self.kk_up,self.kk_down = self.am_xhour.keltner(self.kk_length,self.kk_dev)

        self.dc_up,self.dc_down = self.am_xhour.donchian(self.dc_length)

        if self.pos == 0:
            self.atr_value = self.am_xhour.atr(30)

            if self.ema_entry_crossover > 0 :
                self.buy(self.kk_up, self.fixed_size,True)
                print(self.kk_up)

            elif self.ema_entry_crossover < 0 :
                self.short(self.kk_down, self.fixed_size,True)

        elif self.pos > 0:

            self.long_stop = max(self.dc_down,self.long_stop_trade)
            self.sell(self.long_stop, abs(self.pos), True)

        elif self.pos < 0:

            self.short_stop = min(self.dc_up,self.short_stop_trade)
            self.cover(self.short_stop, abs(self.pos), True)

        self.sync_data()
        self.put_event()

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

        # self.write_log(f"on_order: status:{order.status}, orderid: {order.vt_orderid}, offset:{order.offset}, price:{order.price}, volume:{order.volume}, traded: {order.traded}")
        # self.put_event()

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        # if trade.direction == Direction.LONG:
        #     self.long_enrty = trade.price
        #     self.long_stop_trade = self.long_enrty - 2 * self.atr_value
        #
        # else:
        #     self.short_enrty = trade.price
        #     self.short_stop_trade = self.short_enrty + 2 * self.atr_value

        self.put_event()

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

    def exchange_load_bar(self,exchange:Exchange):
        """
        如果是火币,ok 交易所,就从数据库获取初始化数据
        """
        if exchange == Exchange.OKEX or exchange == Exchange.HUOBI:
            self.load_bar(days=10,use_database=True)
        else:
            self.load_bar(10)
    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, 1, self.on_15min_bar,interval=Interval.HOUR)
        self.am = ArrayManager()
Example #26
0
class MacdBollDcStrategy(CtaTemplate):
    """"""

    author = "云崖"

    open_window = 2
    xminute_window = 15
    xhour_window = 1
    fast_length = 14
    show_length = 28
    boll_length = 20
    boll_dev = 2.0
    dc_length = 30
    trailing_tax = 2.0
    fixed_size = 1

    macd_inited = 0
    boll_up = 0
    boll_down = 0
    dc_up = 0
    dc_down = 0
    exit_long = 0
    exit_short = 0
    long_stop = 0
    short_stop = 0

    intra_trade_high = 0
    intra_trade_low = 0

    parameters = [
        "open_window",
        "xminute_window",
        "xhour_window",
        "fast_length",
        "show_length",
        "boll_length",
        "boll_dev",
        "dc_length",
        "trailing_tax",
        "fixed_size",
    ]

    variables = [
        "macd_inited",
        "boll_up",
        "boll_down",
        "dc_up",
        "dc_down",
        "exit_long",
        "exit_short",
        "long_stop",
        "short_stop",
    ]

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

        self.bg_open = NewBarGenerator(self.on_bar, self.open_window,
                                       self.on_open_bar)
        self.am_open = ArrayManager()

        self.bg_xminute = NewBarGenerator(self.on_bar, self.xminute_window,
                                          self.on_xminute_bar)
        self.am_xminute = ArrayManager(150)

        self.bg_xhour = NewBarGenerator(self.on_bar,
                                        self.xhour_window,
                                        self.on_xhour_bar,
                                        interval=Interval.HOUR)
        self.am_xhour = 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)
        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_xhour.update_bar(bar)
        self.bg_xminute.update_bar(bar)
        self.bg_open.update_bar(bar)

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

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

            return

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

            self.long_stop = 0
            self.short_stop = 0

            if self.macd_inited > 0:
                self.buy(self.boll_up, self.fixed_size, True)

            elif self.macd_inited < 0:
                self.short(self.boll_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

            long_high = self.intra_trade_high * (1 - self.trailing_tax / 100)
            self.long_stop = max(self.exit_long, long_high)

            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)

            stop_low = self.intra_trade_low * (1 + self.trailing_tax / 100)
            self.short_stop = min(self.exit_short, stop_low)

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

        self.put_event()

    def on_xminute_bar(self, bar: BarData):
        """"""
        self.am_xminute.update_bar(bar)
        if not self.am_xminute.inited:
            return

        self.boll_up, self.boll_down = self.am_xminute.boll(
            self.boll_length, self.boll_dev)
        self.exit_short, self.exit_long = self.am_xminute.donchian(
            self.dc_length)

    def on_xhour_bar(self, bar: BarData):
        """
        :param bar:
        :type bar:
        :return:
        :rtype:
        """
        self.am_xhour.update_bar(bar)
        if self.am_xhour.inited:
            return
        fast_ema_value = self.am_xhour.ema(self.fast_length, True)
        show_ema_value = self.am_xhour.ema(self.show_length, True)
        diff = fast_ema_value - show_ema_value
        macd_diff = (fast_ema_value - show_ema_value) / show_ema_value * 100

        if diff[-2] > macd_diff[-2]:
            self.macd_inited = 1

        elif diff[-2] < macd_diff[-2]:
            self.macd_inited = -1

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

    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.
        """
        self.put_event()
Example #27
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)
Example #28
0
class PatternScoreStrategy(CtaTemplate):
    author = "用Python的交易员"

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

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

    score = Score()
    count = 0
    interval = 6

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

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super(PatternScoreStrategy, self).__init__(cta_engine, strategy_name,
                                                   vt_symbol, setting)
        self.bg = BarGenerator(self.on_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)

        self.open_strategy = [self.open_kline1]
        self.offset = 40
        self.min = 0
        self.max = 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("策略启动")
        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
            # deg = calc_regress_deg(self.am3.close[-20:])

    def calc_score(self):
        score = 0
        score += self.score.base

        for item in self.pattern_record.values():
            score += item["value"]

        return score

    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
        diff_time = bar.datetime - self.am.time_array[-1]
        if diff_time.total_seconds() > 3600 or self.count > self.interval:
            self.count = 0
            self.score.base = calc_regress_deg(self.am.close[-self.interval:],
                                               False) * 1000
            print("score:", self.score.base, self.min, self.max)
        else:
            self.count += 1

        # 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_kline1(self, bar: BarData, calc_data):

        score = self.calc_score()
        if score < self.min:
            self.min = score
        if score > self.max:
            self.max = score

        if abs(calc_data["range_sum"]) < 0.001 or abs(score) < 300:
            return

        # if std_val2 < 0.2:
        if score > 0 and calc_data["range_sum"] > 0:
            return self.buy(bar.close_price,
                            1,
                            type=OrderType.MARKET,
                            extra={
                                "reason":
                                "开多,score={}, rang_sum={}".format(
                                    score, calc_data["range_sum"])
                            })
        if score < 0 and calc_data["range_sum"] < 0:
            return self.short(bar.close_price,
                              1,
                              type=OrderType.MARKET,
                              extra={
                                  "reason":
                                  "开多,score={}, rang_sum={}".format(
                                      score, calc_data["range_sum"])
                              })

    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)

        calc_data = (dict(kdj=[
            round(kdj_val["k"][-1], 2),
            round(kdj_val["d"][-1], 2),
            round(kdj_val["j"][-1], 2)
        ],
                          deg40_20=round(deg1, 2),
                          deg20=round(deg2, 2),
                          deg10=round(deg3, 2),
                          deg_f=round(deg_full, 2),
                          time=bar.datetime,
                          price=bar.close_price,
                          ma=round(ma, 2),
                          std_40=round(std_val, 2),
                          mean40=round(mean_val, 2),
                          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:]),
                          atr=self.am.atr(10),
                          tr=self.am.atr(1, length=2),
                          pattern=list(
                              map(lambda x: KLINE_PATTERN_CHINESE[x],
                                  self.pattern_record.keys()))))

        return calc_data

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

        order_id = None

        if self.pos == 0:
            for open_strategy in self.open_strategy:
                if order_id is not None:
                    break
                order_id = open_strategy(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"]))
            self.request_order.extend(order_id)

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

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg3.update_bar(bar)
        self.bg5.update_bar(bar)
        am = self.am
        self.am.update_bar(bar)
        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])

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

        self.on_strategy(bar)
        # median_val = np.median(calc_nums)

        self.put_event()

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

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

        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
Example #29
0
class TrendModelStrategy(CtaTemplate):
    """"""

    author = "yiran"

    fixed_size = 1

    fast_ma_macd = 9
    slow_ma_macd = 26
    signal_macd = 4
    true_range_window = 4
    true_range_influence_multiplier = 0.5

    cross_over_record_max_num = 50
    cross_over_slice_window = 4
    trail_bar_window = 6

    bar_num = 0
    bar_num_after_crossover = 0

    mdif = 0
    cross_above_0 = False
    cross_under_0 = False
    cross_over_record_array = np.zeros(shape=(4, cross_over_record_max_num))
    cross_over_slice_window_highest = 0
    cross_over_slice_window_lowest = 0
    last_cross_over_interval = 0
    last_cross_over_side = 0

    long_open_stop_order_price = 0
    long_close_stop_order_price = 0
    short_open_stop_order_price = 0
    short_close_stop_order_price = 0

    parameters = [
        'fast_ma_macd', 'slow_ma_macd', 'signal_macd', 'true_range_window',
        'cross_over_record_max_num', 'true_range_influence_multiplier',
        'cross_over_slice_window', 'trail_bar_window'
    ]

    variables = [
        'bar_num', 'bar_num_after_crossover', 'mdif', 'cross_above_0',
        'cross_under_0'
        'cross_over_slice_window_highest', 'cross_over_slice_window_lowest',
        'last_cross_over_interval', 'long_open_stop_order_price',
        'lass_cross_over_side', 'short_open_stop_order_price',
        'short_close_stop_order_price'
    ]

    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.am = ArrayManager()
        self.bars = []

    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)

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.cancel_all()
        self.am.update_bar(bar)
        self.bar_num += 1
        if not self.am.inited:
            return

        am = self.am
        self.mdif, signal, hist = am.macd(self.fast_ma_macd,
                                          self.slow_ma_macd,
                                          self.signal_macd,
                                          array=True)
        self.long_close_stop_order_price = am.low[-self.trail_bar_window:].min(
        )
        self.short_close_stop_order_price = am.high[-self.
                                                    trail_bar_window:].max()

        if self.mdif[-2] < 0 < self.mdif[-1]:
            self.cross_above_0 = True
        elif self.mdif[-2] > 0 > self.mdif[-1]:
            self.cross_under_0 = True

        if self.cross_under_0 or self.cross_above_0:
            # bar_num
            self.cross_over_record_array[
                0, :-1] = self.cross_over_record_array[0, 1:]
            # high
            self.cross_over_record_array[
                1, :-1] = self.cross_over_record_array[1, 1:]
            # low
            self.cross_over_record_array[
                2, :-1] = self.cross_over_record_array[2, 1:]
            # cross_over_side
            self.cross_over_record_array[
                3, :-1] = self.cross_over_record_array[3, 1:]

            self.cross_over_record_array[0, -1] = self.bar_num
            self.cross_over_record_array[1, -1] = am.high[-1]
            self.cross_over_record_array[2, -1] = am.low[-1]
            if self.cross_above_0:
                side = 1
            elif self.cross_under_0:
                side = -1
            self.cross_over_record_array[3, -1] = side
            self.cross_above_0, self.cross_under_0 = False, False

        self.cross_over_slice_window_highest = np.max(
            self.cross_over_record_array[1, -self.cross_over_slice_window:])
        self.cross_over_slice_window_lowest = np.min(
            self.cross_over_record_array[2, -self.cross_over_slice_window:])
        self.last_cross_over_interval = self.bar_num - \
            self.cross_over_record_array[0, -1]
        self.last_cross_over_side = self.cross_over_record_array[3, -1]
        true_range_influence = np.mean(
            am.trange(array=True)
            [-self.true_range_window:]) * self.true_range_influence_multiplier
        self.long_open_stop_order_price = self.cross_over_slice_window_highest + \
            true_range_influence
        self.short_open_stop_order_price = self.cross_over_slice_window_lowest + \
            true_range_influence

        if self.pos == 0:
            if self.last_cross_over_interval <= self.cross_over_record_max_num:
                if self.last_cross_over_side == 1:
                    self.buy(self.long_open_stop_order_price,
                             self.fixed_size,
                             stop=True)
                if self.last_cross_over_side == -1:
                    self.short(self.short_close_stop_order_price,
                               self.fixed_size,
                               stop=True)
        elif self.pos > 0:
            self.sell(self.long_close_stop_order_price, self.pos, stop=True)
        elif self.pos < 0:
            self.cover(self.short_close_stop_order_price,
                       np.abs(self.pos),
                       stop=True)

        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
Example #30
0
class BollVixSignal(CtaSignal):
    """
    布林 vix
    """
    sma_array = 0
    boll_up_array = 0
    boll_down_array = 0
    entry_crossover = 0
    atr_value = 0
    intra_trade_high = 0
    intra_trade_low = 0
    long_stop = 0
    short_stop = 0

    def __init__(self, open_window, boll_window: int):
        """"""
        super().__init__()
        self.open_window = open_window
        self.boll_window = boll_window

        self.bg = BarGenerator(self.on_bar, self.open_window, self.on_xmin_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_xmin_bar(self, bar: BarData):
        """"""
        self.am.update_bar(bar)
        if not self.am.inited:
            self.set_signal_pos(0)

        # Calculate array  计算数组
        self.sma_array = self.am.sma(self.boll_window, True)
        std_array = self.am.sma(self.boll_window, True)
        dev = abs(self.am.close[:-1] - self.sma_array[:-1]) / std_array[:-1]
        dev_max = dev[-self.boll_window:].max()
        self.boll_up_array = self.sma_array[:-1] + std_array[:-1] * dev_max
        self.boll_down_array = self.sma_array[:-1] - std_array[:-1] * dev_max

        # Get current and last index
        last_sma = self.sma_array[-2]
        current_sma = self.sma_array[-1]
        last_close = self.am.close[-2]
        current_boll_up = self.boll_up_array[-1]
        last_boll_up = self.boll_up_array[-2]
        current_boll_down = self.boll_down_array[-1]
        last_boll_down = self.boll_down_array[-2]

        # Get crossover
        if last_close <= last_boll_up and current_boll_up < bar.close_price:
            self.set_signal_pos(1)

        elif last_close >= last_boll_down and current_boll_down > bar.close_price:
            self.set_signal_pos(-1)

        exit_long = last_close >= last_sma and current_sma > bar.close_price
        exit_short = last_close <= last_sma and current_sma < bar.close_price

        if exit_long and exit_short:
            self.set_signal_pos(0)
Example #31
0
class AberrationStrategy(CtaTemplate):
    """"""
    author = "yunya"

    open_window = 15
    boll_length = 80
    boll_dev = 2.0
    cci_length = 6
    cci_exit = 10.0
    fixed_size = 1

    boll_up = 0
    boll_down = 0
    boll_mid = 0
    boll_mid_new = 0
    cci_value = 0
    exit_long = 0
    exit_short = 0
    boll_length_new = 0
    exit_long_nex = 0
    exit_long_last = 0
    exit_short_nex = 0
    exit_short_last = 0

    parameters = [
        "open_window",
        "boll_length",
        "boll_dev",
        "cci_length",
        "cci_exit",
        "fixed_size",
    ]

    variables = [
        "boll_up",
        "boll_down",
        "boll_mid",
        "cci_value",
        "exit_long",
        "exit_short",
        "boll_length_new",
        "exit_long_nex",
        "exit_long_last",
        "exit_short_nex",
        "exit_short_last",
    ]

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

        self.bg = NewBarGenerator(self.on_bar, self.open_window,
                                  self.on_xmin_bar)
        self.am = ArrayManager(int(self.boll_length) + 100)

    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)

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

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

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

        # 计算原布林带
        self.boll_up, self.boll_down = self.am.boll(self.boll_length,
                                                    self.boll_dev)
        self.boll_mid = am.sma(self.boll_length)
        self.cci_value = am.cci(self.cci_length)

        # 如果没有仓位,两条布林window一样
        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.boll_length_new = self.boll_length

            if self.cci_value > self.cci_exit:
                self.buy(self.boll_up, self.fixed_size, stop=True)

            if self.cci_value < -self.cci_exit:
                self.short(self.boll_down, self.fixed_size, stop=True)

        elif self.pos > 0:
            # 上涨或下跌时,布林中轨均值减1
            close_long = am.close[-1] > am.close[-2] > am.close[-3]

            if close_long:
                self.boll_length_new -= 1
                self.boll_length_new = max(self.boll_length_new, 20)

            # 计算新的布林带
            self.boll_mid_new = am.sma(self.boll_length_new, True)

            # 仓位是long 时,如果价格上穿新布林中轨
            con1 = am.close[-1] < self.boll_mid_new[-1]
            con2 = am.close[-2] >= self.boll_mid_new[-2]

            if con1 and con2:
                self.exit_long_nex = am.close[-1]  # 保存当前收盘价
                if self.exit_long_nex > self.exit_long_last or self.exit_long_last == 0:
                    self.exit_long_last = self.exit_long_nex
                    self.boll_length_new = self.boll_length
                    # 下穿新均线,以原布林均线挂出停止单,避免快速下跌而无法止损
                    self.exit_long = self.boll_mid
                    # print(f"我是多单,exitlast:{self.exit_short_last},重置布林中轨参数,止损挂{self.exit_long}:")
                else:
                    # 收盘价在两条均线平均价上方,以当前收盘价挂出限价单
                    if self.am.close[-1] > (
                        (self.boll_mid + self.boll_mid_new[-1]) / 2):
                        self.exit_long = bar.close_price
                        # print(f"我是多单,收盘价在两个中轨均值上方,以收盘价挂止损单:{self.exit_long}")
                    elif bar.close_price < self.boll_mid:
                        self.exit_long = bar.close_price
                    else:
                        self.exit_long = self.boll_mid
                        # print(f"我是多单,收盘价在两个中轨均值下方,以原中轨挂止损单:{self.exit_long},")
            else:
                self.exit_long = self.boll_mid
                # print(f"我是多单,收盘价在新中轨上方,以原中轨挂止损单:{self.exit_long}")

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

        elif self.pos < 0:
            close_short = am.close[-1] < am.close[-2] < am.close[-3]

            if close_short:
                self.boll_length_new -= 1
                self.boll_length_new = max(self.boll_length_new, 20)

            # 计算新的布林带
            self.boll_mid_new = am.sma(self.boll_length_new, True)

            # 仓位是short 时,如果价格上穿新布林中轨
            con3 = am.close[-1] > self.boll_mid_new[-1]
            con4 = am.close[-2] <= self.boll_mid_new[-2]

            if con3 and con4:
                self.exit_short_nex = am.close[-1]
                if self.exit_short_nex < self.exit_short_last or self.exit_short_last == 0:
                    self.exit_short_last = self.exit_short_nex
                    self.boll_length_new = self.boll_length

                    self.exit_short = self.boll_mid
                else:
                    if self.am.close[-1] < (self.boll_mid +
                                            self.boll_mid_new[-1] / 2):
                        self.exit_short = bar.close_price

                    elif bar.close_price > self.boll_mid:
                        self.exit_short = bar.close_price

                    else:
                        self.exit_short = self.boll_mid

            else:
                self.exit_short = self.boll_mid

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

        self.put_event()
        self.sync_data()

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

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

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        self.put_event()
        pass
Example #32
0
class MultiTimeframeStrategy(CtaTemplate):
    """"""
    author = '用Python的交易员'

    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(self.fast_window)
        self.slow_ma = self.am15.sma(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
Example #33
0
class GridStockCtaStrategy(CtaTemplate):
    """
    期货网格策略逻辑:
        1、支持正向合约和反向合约交易逻辑(设置正向和反向标记来转换)
        2、网格格数设置50格,多空各25格(参数)
        3、网格总限量资金: 3000USDT 或 合约张数
        4、网格操作区间: 10%

        3、网格跟踪指标 : 首次成交价格
        4、网格上限: 网格跟踪指标 * (1 + 网格操作区间)
        5、网格下限: 网格跟踪指标 * ( 1 - 网格操作区间)
        6、网格步进 :( 网格上限 - 网格下限 ) / 网格数量
        7、仓位单元 : 网格总限量 / 网格数量
        8、网格启动、停止开关:振幅超过百分比例,网格暂时停止,等待8小时后重新启动

    """
    author = "yunya"

    open_window = 2
    xminute_window = 5
    xhour_window = 1
    position_proportion = 1  # 每次加仓比例
    grid_amount = 20  # 网格最大量
    grid_usdt_size = 10  # 首次使用多少USDT购买币
    grid_usdt_capital = 1000  # 网格最多使用的资金量USDT
    grid_buy_price = 0.2  # 网格距离
    grid_sell_price = 0.25
    pay_up = 2  # 偏移pricetick
    buy_callback = 2  # 买入回调幅度
    sell_callback = 2  # 卖出回调幅度
    grid_amplitude = 5  # 振幅超过比例停止策略8小时
    stop_time = 8  # 策略暂停时间

    # active_orderids = set()  # 保存不重复的订单号
    price_change = 0  # 网格基准线(每次成交价)
    current_grid = 0
    max_target = 0  # 当前网格最大最
    current_volume = 0  # 当前下单币的数量
    buy_benchmark = 0
    sell_benchmark = 0
    buy_price = 0  # 买入成交价
    sell_price = 0  # 平仓成交价
    grid_usdt_volume = 0
    cumulative_usdt_volume = 0  # 累计使用金额
    grid_count = 0  # 网格次数
    intra_trade_high = 0  # 最高价
    trade_high = 0
    last_trade_high = 0
    intra_trade_low = 0  # 最低价
    trade_low = 0
    last_trade_low = 0
    amplitude = 0  # 振幅
    tick_price = 0
    amplitude_inited = False  # 振幅标签
    time_stop = 0  # 计算得到的重新启动时间

    parameters = [
        "open_window",
        "xminute_window",
        "xhour_window",
        "position_proportion",
        "grid_amount",
        "grid_usdt_size",
        "grid_usdt_capital",
        "grid_buy_price",
        "grid_sell_price",
        "pay_up",
        "buy_callback",
        "sell_callback",
        "grid_amplitude",
        "stop_time",
    ]

    variables = [
        "price_change",
        "current_grid",
        "max_target",
        "current_volume",
        "buy_benchmark",
        "sell_benchmark",
        "buy_price",
        "sell_price",
        "grid_usdt_volume",
        "cumulative_usdt_volume",
        "grid_count",
        "intra_trade_high",
        "trade_high",
        "last_trade_high",
        "intra_trade_low",
        "trade_low",
        "last_trade_low",
        "amplitude",
        "tick_price",
        "amplitude_inited",
        "time_stop",
    ]

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

        self.bg_open = BarGenerator(self.on_bar, self.open_window,
                                    self.on_open_bar)
        self.am_open = ArrayManager()

        self.bg_minute = BarGenerator(self.on_bar, self.xminute_window,
                                      self.on_mintue_bar)
        self.am_minute = ArrayManager()

        self.bg_xhour = BarGenerator(self.on_bar, self.xhour_window,
                                     self.on_xhour_bar, Interval.HOUR)
        self.am_xhour = ArrayManager()

        # 计算每次使用资金量
        self.cumulative_usdt_volume = 0
        self.grid_usdt_volume = 0
        self.amplitude = 0
        self.tick_price = 0
        # self.active_orderids = set()

    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_open.update_tick(tick)

    def on_bar(self, bar: BarData):
        """"""
        self.bg_open.update_bar(bar)
        self.bg_minute.update_bar(bar)
        self.bg_xhour.update_bar(bar)

    def on_open_bar(self, bar: BarData):
        """"""
        self.am_open.update_bar(bar)

        if not self.am_open.inited:
            return

        self.cancel_all()

        # 判断 休眠时间
        if self.amplitude_inited:
            if bar.datetime > self.time_stop:
                self.amplitude_inited = False
            return

        # 根据网格次数加仓 , 根据USDT量和价格计算出可购买的币数量
        if self.position_proportion > 0 or self.grid_count > 0:
            self.grid_usdt_volume = self.grid_usdt_size * (
                1 + (self.position_proportion / 100) * self.grid_count)
        else:
            self.grid_usdt_volume = self.grid_usdt_size

        self.current_volume = self.grid_usdt_volume / bar.close_price

        self.write_log(
            f"使用 {self.grid_usdt_volume} 枚USDT,可购买 {self.current_volume} 枚币")

        self.tick_price = self.get_pricetick()
        if not self.pos:
            """
            1、如果空仓,以当前价格买入一份做为底仓
            2、总网格次数减一
            """
            msg = f"tick_price:{self.tick_price}"
            self.write_log(msg=msg)

            buy_price = bar.close_price - self.tick_price * self.pay_up
            self.buy(buy_price, self.current_volume)

            self.intra_trade_high = bar.high_price
            self.intra_trade_low = bar.low_price

            self.grid_count += 1
            self.cumulative_usdt_volume += self.grid_usdt_volume

        else:
            if bar.close_price < self.buy_benchmark:
                """
                当前收盘价低于下个网格买入价格时,判断买入时机:
                1、价格在上次买入后,中间没有卖出的过程,
                2、
                """
                if self.cumulative_usdt_volume < self.grid_usdt_capital:
                    """
                    买在最低位
                    """
                    self.intra_trade_high = bar.high_price
                    self.intra_trade_low = min(self.intra_trade_low,
                                               bar.low_price)
                    self.trade_low = self.intra_trade_low * (
                        1 + self.buy_callback / 100)

                    if self.trade_low <= self.buy_benchmark:
                        if self.last_trade_low > 0:
                            self.last_trade_low = min(self.trade_low,
                                                      self.last_trade_low)
                        else:
                            self.last_trade_low = self.trade_low

                    if bar.close_price <= self.last_trade_low:
                        self.buy_price = self.last_trade_low
                    else:
                        self.buy_price = bar.close_price + self.tick_price * self.pay_up  # 加价保证成交

                    self.buy(self.buy_price, self.current_volume)
                    self.grid_count += 1
                    self.cumulative_usdt_volume += self.grid_usdt_volume
                    self.last_trade_low = self.trade_low

            elif bar.close_price > self.sell_benchmark:
                if self.pos > 0:
                    """
                    卖在最高位
                    """
                    self.intra_trade_high = max(self.intra_trade_high,
                                                bar.high_price)
                    self.intra_trade_low = bar.low_price
                    self.trade_high = self.intra_trade_high * (
                        1 - self.sell_callback / 100)

                    if self.trade_high >= self.sell_benchmark:
                        if self.last_trade_high > 0:
                            self.last_trade_high = max(self.trade_high,
                                                       self.last_trade_high)
                        else:
                            self.last_trade_high = self.trade_high

                    if bar.close_price >= self.last_trade_high:
                        self.sell_price = self.last_trade_high
                    else:
                        self.sell_price = bar.close_price - self.tick_price * self.pay_up

                    # 判断 最后一次全部卖完
                    if self.pos > self.current_volume * 1.2:
                        self.cover(self.sell_price, abs(self.current_volume))
                        self.grid_count -= 1
                        self.cumulative_usdt_volume -= self.grid_usdt_volume
                    else:
                        self.cover(self.sell_price, abs(self.pos))
                        self.grid_count -= 1
                        self.cumulative_usdt_volume -= self.grid_usdt_volume
        # 更新图形界面
        self.put_event()

    def on_mintue_bar(self, bar: BarData):
        """
        :return:
        """
        self.am_minute.update_bar(bar)

        if not self.am_minute.inited:
            return
        # 计算振幅
        self.amplitude = (bar.high_price - bar.low_price) / bar.high_price

        # 如果振幅超过指定值,策略撤掉所有挂单,并且进入休眠状态
        if self.amplitude > self.grid_amplitude / 100:
            self.amplitude_inited = True
            self.time_stop = bar.datetime + datetime.timedelta(
                hours=self.stop_time)
            self.write_log(
                f"当前市场波动较大,"
                f"振幅为:{self.amplitude},超过设置值,策略进入休眠,"
                f"休眠到:{self.time_stop.strftime('%Y-%m-%d %H:%M:%S')}时重新启动策略")

    def on_xhour_bar(self, bar: BarData):
        """
        :return:
        """
        self.am_xhour.update_bar(bar)

        if not self.am_xhour.inited:
            return
        pass

    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        pass
        # # 保存活动委托的委托号
        # if order.is_active():
        #     self.active_orderids.add(order.vt_orderid)
        # # 移除已结束(撤单、全成)委托的委托号
        # elif order.vt_orderid in self.active_orderids:
        #     self.active_orderids.remove(order.vt_orderid)
        #
        # self.put_event()

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        if trade.direction == Direction.LONG:
            self.price_change = trade.price  # 成交最高价
        else:
            self.price_change = trade.price

        # 计算当前网格买入价格和卖出价格
        self.buy_benchmark = self.price_change * (1 - self.grid_buy_price)
        self.sell_benchmark = self.price_change * (1 + self.grid_sell_price)

        self.sync_data()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
Example #34
0
class ZZ500Strategy(CtaTemplate):
    # 参考文档: https://www.doc88.com/p-5748746646083.html
    # TODO: 对参数调优之后再做指标共振平滑处理看效果如何
    author = "digu"

    score_bull = 4  # 各指标得分和,超过阈值之后才发出买入信号
    score_bear = 3  # 各指标得分和,低于阈值之后才发出卖出信号

    pct_cnt_low = 30  # 上涨股票占比
    pct_cnt_high = 90

    pct_ma60_low = 40
    pct_ma60_high = 90

    cnt_8ma_low = 3
    cnt_8ma_high = 5
    ds_tushare = DataServiceTushare()

    c1 = 0
    c2 = 0
    c3 = 0
    c4 = 0
    c5 = 0
    c6 = 0
    parameters = [
        "score_bull", "score_bear", "pct_cnt_low", "pct_cnt_high",
        "pct_ma60_low", "pct_ma60_high", "cnt_8ma_low", "cnt_8ma_high"
    ]
    variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1"]

    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.am = ArrayManager(size=500)
        self.lst_turnover_rate_f = list()  # 保存zz500的历史流通盘换手率
        self.deque_quantile_20 = deque()
        self.pct_cnt_score_pre = 0  # 保存前一天的上涨股占比得分
        self.cnt_8ma_score_pre = 0  # 保存前一天的8ma得分
        self.ma_bull_score_pre = 0  # 保存前一天的均线多空得分
        self.rsi_score_pre = 0  # 保存前一天的rsi得分
        self.turnover_rate_f_score_pre = 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("策略启动")
        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)

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

        # TODO 获取zz500的相关信息
        info_zz500 = self.ds_tushare.get_zz500(
            '000905_SH', time_to_str(bar.datetime, '%Y%m%d'))
        if info_zz500 is None:
            LOG.info('zz500 None date: %s' %
                     time_to_str(bar.datetime, '%Y%m%d'))
            return
        self.lst_turnover_rate_f.append(info_zz500['turnover_rate_f'])
        arr_turnover_rate_f = np.array(self.lst_turnover_rate_f)
        arr_turnover_rate_f.sort()
        idx_turnover_rate_f = np.argwhere(
            arr_turnover_rate_f > info_zz500['turnover_rate_f'] - 0.0000001)[0]
        quantile_turnover_rate_f = idx_turnover_rate_f / arr_turnover_rate_f.size
        if len(self.deque_quantile_20) < 20:
            self.deque_quantile_20.append(quantile_turnover_rate_f)
        else:
            self.deque_quantile_20.popleft()
            self.deque_quantile_20.append(quantile_turnover_rate_f)

        am = self.am
        am.update_bar(bar)
        if not am.inited:
            return
        # 判断当日上涨股票数目比例
        pct_cnt = (info_zz500['stk_cnt_up'] * 100.0) / (
            info_zz500['stk_cnt_up'] + info_zz500['stk_cnt_down'])
        if pct_cnt > self.pct_cnt_high:
            pct_cnt_score = 1
        elif pct_cnt < self.pct_cnt_low:
            pct_cnt_score = 0
        else:
            pct_cnt_score = self.pct_cnt_score_pre
        self.pct_cnt_score_pre = pct_cnt_score

        # 判断大于ma60强势股票数目比例
        pct_ma60 = (info_zz500['stk_cnt_ma60_up'] * 100.0) / (
            info_zz500['stk_cnt_ma60_up'] + info_zz500['stk_cnt_ma60_down'])
        if pct_ma60 < self.pct_ma60_low or pct_ma60 > self.pct_ma60_high:
            pct_ma60_score = 0
        else:
            pct_ma60_score = 1

        # 判断8ma指标
        cnt_ma = 0
        cnt_ma = cnt_ma + 1 if info_zz500['close'] > info_zz500[
            'ma_5'] else cnt_ma
        cnt_ma = cnt_ma + 1 if info_zz500['close'] > info_zz500[
            'ma_10'] else cnt_ma
        cnt_ma = cnt_ma + 1 if info_zz500['close'] > info_zz500[
            'ma_20'] else cnt_ma
        cnt_ma = cnt_ma + 1 if info_zz500['close'] > info_zz500[
            'ma_30'] else cnt_ma
        cnt_ma = cnt_ma + 1 if info_zz500['close'] > info_zz500[
            'ma_60'] else cnt_ma
        cnt_ma = cnt_ma + 1 if info_zz500['close'] > info_zz500[
            'ma_120'] else cnt_ma
        cnt_ma = cnt_ma + 1 if info_zz500['close'] > info_zz500[
            'ma_250'] else cnt_ma
        cnt_ma = cnt_ma + 1 if info_zz500['close'] > info_zz500[
            'ma_500'] else cnt_ma
        if cnt_ma > self.cnt_8ma_high:
            cnt_8ma_score = 1
        elif cnt_ma < self.cnt_8ma_low:
            cnt_8ma_score = 0
        else:
            cnt_8ma_score = self.cnt_8ma_score_pre
        self.cnt_8ma_score_pre = cnt_8ma_score

        # 判断均线多空排列指标
        if info_zz500['ma_30'] > info_zz500['ma_20'] and info_zz500[
                'ma_20'] > info_zz500['ma_10']:
            ma_bull_score = 0
        elif info_zz500['ma_10'] > info_zz500['ma_20'] and info_zz500[
                'ma_20'] > info_zz500['ma_30']:
            ma_bull_score = 1
        else:
            ma_bull_score = self.ma_bull_score_pre
        self.ma_bull_score_pre = ma_bull_score

        # 判断平滑相对强弱指标MA(RSI(20), 20)
        arr_rsi_20 = self.am.rsi(20, array=True)[-20:]
        rsi_20_mean = np.mean(arr_rsi_20)
        rsi_20_std = np.std(arr_rsi_20)
        if arr_rsi_20[-1] > rsi_20_mean + rsi_20_std:
            rsi_score = 1
        elif arr_rsi_20[-1] < rsi_20_mean - rsi_20_std:
            rsi_score = 0
        else:
            rsi_score = self.rsi_score_pre
        self.rsi_score_pre = rsi_score

        # 判断A股换手率指标(历史分位数q)得分
        quantile_20_mean = np.mean(np.array(self.deque_quantile_20))
        quantile_20_std = np.std(np.array(self.deque_quantile_20))
        if quantile_turnover_rate_f > quantile_20_mean + quantile_20_std:
            turnover_rate_f_score = 1
        elif quantile_turnover_rate_f < quantile_20_mean - quantile_20_std:
            turnover_rate_f_score = 0
        else:
            turnover_rate_f_score = self.turnover_rate_f_score_pre
        self.turnover_rate_f_score_pre = turnover_rate_f_score

        ZZ500Strategy.c1 += pct_cnt_score
        ZZ500Strategy.c2 += pct_ma60_score
        ZZ500Strategy.c3 += cnt_8ma_score
        ZZ500Strategy.c4 += ma_bull_score
        ZZ500Strategy.c5 += rsi_score
        ZZ500Strategy.c6 += turnover_rate_f_score
        score = pct_cnt_score + pct_ma60_score + cnt_8ma_score + ma_bull_score + rsi_score + turnover_rate_f_score

        flag_buy = True if score > self.score_bull else False
        flag_sell = True if score < self.score_bear else False
        if flag_buy:
            if self.pos == 0:
                self.cancel_all()
                self.buy(bar.close_price, 1)
                # self.buy(bar.close_price, 1, True)
        elif flag_sell:
            if self.pos > 0:
                self.cancel_all()
                self.sell(bar.close_price, 1)
                # self.sell(bar.close_price, 1, True)

        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
Example #35
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
Example #36
0
class MultiTimeframeStrategyHNTest(CtaTemplate):
    """"""
    author = "Huang Ning"

    bar_window1 = 5
    bar_window2 = 15
    rsi_signal = 20
    rsi_window = 14
    fast_window = 12
    slow_window = 20
    fixed_size = 1
    pricetick_multiplier1 = 0.2
    pricetick_multiplier2 = 0

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

    parameters = [
        "bar_window1", "bar_window2", "rsi_signal", "rsi_window",
        "fast_window", "slow_window", "fixed_size", "pricetick_multiplier1",
        "pricetick_multiplier2"
    ]

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

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

        self.pricetick = self.get_pricetick()

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

        self.bg1 = XminBarGenerator(self.on_bar, self.bar_window1,
                                    self.on_Xmin1_bar)
        self.am1 = ArrayManager()

        self.bg2 = XminBarGenerator(self.on_bar, self.bar_window2,
                                    self.on_Xmin2_bar)
        self.am2 = ArrayManager()

        self.buy_vt_orderids = []
        self.sell_vt_orderids = []
        self.short_vt_orderids = []
        self.cover_vt_orderids = []

        self.buy_price = 0
        self.sell_price = 0
        self.short_price = 0
        self.cover_price = 0

    def on_init(self):
        """"""
        self.write_log("策略初始化")
        self.load_bar(10)

    def on_start(self):
        """"""
        self.write_log("策略启动")

    def on_stop(self):
        """"""
        self.write_log("策略停止")

    def on_tick(self, tick: TickData):
        """"""
        self.bg1.update_tick(tick)

    def on_bar(self, bar: BarData):
        """"""
        # 注意:不同周期K线合成的顺序对结果是有影响的
        self.bg1.update_bar(bar)
        self.bg2.update_bar(bar)

        if self.buy_vt_orderids:
            for vt_orderid in self.buy_vt_orderids:
                self.cancel_order(vt_orderid)
            self.buy_vt_orderids = self.buy(
                bar.close_price + self.pricetick * self.pricetick_multilplier2,
                self.fixed_size, True)

        elif self.sell_vt_orderids:
            for vt_orderid in self.sell_vt_orderids:
                self.cancel_order(vt_orderid)
            self.sell_vt_orderids = self.sell(
                bar.close_price - self.pricetick * self.pricetick_multilplier2,
                self.fixed_size, True)

        elif self.short_vt_orderids:
            for vt_orderid in self.short_vt_orderids:
                self.cancel_order(vt_orderid)
            self.short_vt_orderids = self.short(
                bar.close_price - self.pricetick * self.pricetick_multilplier2,
                self.fixed_size, True)

        elif self.cover_vt_orderids:
            for vt_orderid in self.cover_vt_orderids:
                self.cancel_order(vt_orderid)
            self.cover_vt_orderids = self.cover(
                bar.close_price + self.pricetick * self.pricetick_multilplier2,
                self.fixed_size, True)

    def on_Xmin1_bar(self, bar: BarData):
        """"""
        self.am1.update_bar(bar)
        if not self.am1.inited:
            return

        if not self.ma_trend:
            return

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

        if self.pos == 0:
            self.buy_price = bar.close_price + self.pricetick * self.pricetick_multiplier1
            self.sell_price = 0
            self.short_price = bar.close_price - self.pricetick * self.pricetick_multiplier1
            self.cover_price = 0

        elif self.pos > 0:
            self.buy_price = 0
            self.sell_price = bar.close_price - self.pricetick * self.pricetick_multiplier1
            self.short_price = 0
            self.cover_price = 0

        else:
            self.buy_price = 0
            self.sell_price = 0
            self.short_price = 0
            self.cover_price = bar.close_price + self.pricetick * self.pricetick_multiplier1

        if self.pos == 0:
            if not self.buy_vt_orderids:
                if self.ma_trend > 0 and self.rsi_value >= self.rsi_long:
                    self.buy(self.buy_price, self.fixed_size, True)
                    self.buy_price = 0
            else:
                for vt_orderid in self.buy_vt_orderids:
                    self.cancel_order(vt_orderid)

            if not self.short_vt_orderids:
                if self.ma_trend < 0 and self.rsi_value <= self.rsi_short:
                    self.short(self.short_price, self.fixed_size, True)
                    self.short_price = 0
            else:
                for vt_orderid in self.short_vt_orderids:
                    self.cancel_order(vt_orderid)

        elif self.pos > 0:
            if not self.sell_vt_orderids:
                if self.ma_trend < 0 or self.rsi_value < 50:
                    self.sell(self.sell_price, abs(self.pos), True)
                    self.sell_price = 0
            else:
                for vt_orderid in self.sell_vt_orderids:
                    self.cancel_order(vt_orderid)

        else:
            if not self.cover_vt_orderids:
                if self.ma_trend > 0 or self.rsi_value > 50:
                    self.cover(self.cover_price, abs(self.pos), True)
                    self.cover_price = 0
            else:
                for vt_orderid in self.cover_vt_orderids:
                    self.cancel_order(vt_orderid)

    def on_Xmin2_bar(self, bar: BarData):
        """"""
        self.am2.update_bar(bar)
        if not self.am2.inited:
            return

        self.fast_ma = self.am2.sma(self.fast_window)
        self.slow_ma = self.am2.sma(self.slow_window)

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

    def on_stop_order(self, stop_order: StopOrder):
        """"""
        if stop_order.status == StopOrderStatus.WAITING:
            return

        for buf_orderids in [
                self.buy_vt_orderids, self.sell_vt_orderids,
                self.short_vt_orderids, self.cover_vt_orderids
        ]:
            if stop_order.stop_orderid in buf_orderids:
                buf_orderids.remove(stop_order.stop_orderid)
Example #37
0
class AtrStop_Ut(CtaTemplate):
    """"""
    author = "yunya"

    atrstop_window = 46
    open_window = 5
    nloss_singnal = 2.7
    trailing_tax = 2.0
    risk_level = 5000
    exit_dc_length = 50
    atr_length = 30

    atrstop_entry = 0
    current_atr_stop = 0.0
    last_atr_stop = 0.0
    intra_trade_high = 0
    intra_trade_low = 0
    nloss_array = 0.0
    long_stop = 0
    short_stop = 0
    trading_size = 0
    exit_down = 0
    exit_up = 0
    ask = 0
    bid = 0
    atr_value = 0
    count = 0

    parameters = [
        "atrstop_window", "open_window", "nloss_singnal", "trailing_tax",
        "risk_level", "exit_dc_length", "atr_length"
    ]

    variables = [
        "atrstop_entry",
        "current_atr_stop",
        "last_atr_stop",
        "intra_trade_high",
        "intra_trade_low",
        "long_stop",
        "short_stop",
        "exit_down",
        "exit_up",
        "trading_size",
    ]

    def __init__(
        self,
        cta_engine: Any,
        strategy_name: str,
        vt_symbol: str,
        setting: dict,
    ):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)
        self.atr_stop_array = np.zeros(10)

        self.bg_xmin = NewBarGenerator(self.on_bar,
                                       window=self.atrstop_window,
                                       on_window_bar=self.on_xmin_bar,
                                       interval=Interval.MINUTE)
        self.am_xmin = ArrayManager()

        self.bg_5min = BarGenerator(self.on_bar,
                                    window=self.open_window,
                                    on_window_bar=self.on_5min_bar)
        self.am_5min = ArrayManager(self.exit_dc_length *
                                    int(self.atr_length / self.open_window) +
                                    10)

        self.inited_atr_stop = False

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

    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_5min.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.bg_5min.update_bar(bar)

    def on_5min_bar(self, bar: BarData):

        self.cancel_all()
        self.am_5min.update_bar(bar)

        if not self.am_5min.inited or not self.am_xmin.inited:
            return
        if self.atr_stop_array[-3] == 0:
            return

        self.exit_up, self.exit_down = self.am_5min.donchian(
            self.exit_dc_length * int(self.atr_length / self.open_window))

        # print(f"dc上轨:{self.exit_up},下轨:{self.exit_down}")

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

            if self.atrstop_entry > 0:
                self.buy(self.current_atr_stop, self.trading_size, True)

            elif self.atrstop_entry < 0:
                self.short(self.current_atr_stop, self.trading_size, True)

        elif self.pos > 0:
            self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
            long_high = self.intra_trade_high * \
                            (1 - self.trailing_tax / 100)
            self.long_stop = max(self.exit_down, long_high)
            self.sell(self.long_stop, abs(self.pos), True)

        else:
            self.intra_trade_low = min(self.intra_trade_low, bar.low_price)
            short_low = self.intra_trade_low * \
                             (1 + self.trailing_tax / 100)
            self.short_stop = min(self.exit_up, short_low)
            self.cover(self.short_stop, abs(self.pos), True)

        self.put_event()

    def on_xmin_bar(self, bar: BarData):
        """"""
        am_xmin = self.am_xmin
        am_xmin.update_bar(bar)

        self.atr_stop_array[:-1] = self.atr_stop_array[1:]

        if not am_xmin.inited:
            return

        # 计算轨道线 nloss
        self.nloss_array = am_xmin.atr(30, array=True) * self.nloss_singnal

        # 计算轨道线
        self.atr_stop_array = self.atrstop(am_xmin.close, self.atr_stop_array,
                                           self.nloss_array)

        # 初始化 atr_stop_array 保证前三个有值
        if self.count < 4:
            self.count += 1
            return

        self.current_atr_stop = self.atr_stop_array[-1]
        self.last_atr_stop = self.atr_stop_array[-2]
        current_bar = self.am_xmin.close[-1]

        if self.current_atr_stop > self.last_atr_stop and current_bar > self.current_atr_stop:
            self.atrstop_entry = 1
        elif self.current_atr_stop < self.last_atr_stop and current_bar < self.current_atr_stop:
            self.atrstop_entry = -1
        else:
            self.atrstop_entry = 0

        if self.pos == 0:
            self.atr_value = self.am_xmin.atr(self.atr_length)
            self.trading_size = max(int(self.risk_level / self.atr_value), 1)

        self.sync_data()
        self.put_event()

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

    def on_order(self, order: OrderData):
        """
        订单更新回调
        Callback of new order data update.
        """

        self.put_event()

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

    def atrstop(self, close, atrstop, nlossatr):

        # 计算轨道线
        if (close[-1] > atrstop[-2]) and (close[-2] > atrstop[-2]):
            atrstop[-1] = max(atrstop[-2], close[-1] - nlossatr[-1])

        elif (close[-1] < atrstop[-2]) and (close[-2] < atrstop[-2]):
            atrstop[-1] = min(atrstop[-2], close[-1] + nlossatr[-1])

        elif (close[-1] > atrstop[-2]):
            atrstop[-1] = (close[-1] - nlossatr[-1])

        else:
            atrstop[-1] = (close[-1] + nlossatr[-1])

        return atrstop
class DoubleRsiAtr(CtaTemplate):
    """"""
    author = "yiran"

    s_window = 5
    l_window = 15
    atr_window = 20
    atr_multiplier = 0.05
    rsi_window = 11
    long_threshold_l_window = 50
    long_threshold_s_window = 80
    exit_return = 0.02
    exit_loss = 0.02
    exit_return_soft_long = -0.1
    exit_loss_soft_long = -0.2
    exit_return_soft_short = 0.2
    exit_loss_soft_short = 0.1

    fixed_size = 1

    start_time = time(hour=10)
    exit_time = time(hour=14, minute=55)

    long_order_record = []
    short_order_record = []

    rsi_value_l_window = -9999
    rsi_value_s_window = -9999
    atr_value = 0

    position_hold = 0
    long_entered = False
    short_entered = False

    parameters = [
        's_window', 'l_window', 'atr_window', 'atr_multiplier',
        'exit_return_soft_long', 'exit_loss_soft_long', "rsi_window",
        'exit_return_soft_short', 'exit_loss_soft_short',
        "long_threshold_l_window", "long_threshold_s_window", 'exit_return',
        'exit_loss', "fixed_size"
    ]

    variables = ["rsi_value_l_window ", "rsi_value_s_window", "ma_trend"]

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

        self.rsi_long_l = self.long_threshold_l_window
        self.rsi_long_s = self.long_threshold_s_window
        self.rsi_short_l = 100 - self.long_threshold_l_window
        self.rsi_short_s = 100 - self.long_threshold_s_window

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

        self.bg15 = BarGenerator(self.on_bar, self.l_window, self.on_15min_bar)
        self.am15 = ArrayManager()
        self.long_order_record = []
        self.short_order_record = []
        self.atr_value_array = np.array([])

        self.atr_profit_exit_recorder = []

    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

        self.rsi_value_s_window = self.am5.rsi(self.rsi_window)
        self.atr_value = self.am5.atr(self.atr_window)

        if self.long_threshold_l_window != -9999:
            self.long_entered = (self.rsi_value_s_window >
                                 self.rsi_long_s) and (self.rsi_value_l_window
                                                       > self.rsi_long_l)
            self.short_entered = (
                self.rsi_value_s_window < self.rsi_short_s) and (
                    self.rsi_value_l_window < self.rsi_short_l)
        else:
            return

        if self.start_time <= bar.datetime.time() < self.exit_time:
            if self.pos == 0:
                self.position_hold = 0
                if self.long_entered:
                    self.buy(bar.close_price + 5, self.fixed_size)
                    self.long_order_record.append(bar.close_price + 5)
                elif self.short_entered:
                    self.short(bar.close_price - 5, self.fixed_size)
                    self.short_order_record.append(bar.close_price - 5)
            elif self.pos > 0:
                self.position_hold += 1
                buy_order_price = self.long_order_record[-1]
                initial_profit_exit_price = buy_order_price * (
                    1 + self.exit_return)
                # 波动变大+持仓周期变长,会使得止盈的点上移
                moving_profit_exit_price = buy_order_price * (
                    1 + self.exit_return_soft_long
                ) + self.atr_value * self.atr_multiplier * self.position_hold

                initial_loss_exit_price = buy_order_price * (1 -
                                                             self.exit_loss)
                # 波动变大+持仓周期变长,会使得止损的点上移
                moving_loss_exit_price = buy_order_price * (
                    1 + self.exit_loss_soft_long
                ) + self.atr_value * self.atr_multiplier * self.position_hold
                if initial_profit_exit_price < moving_profit_exit_price:
                    self.atr_profit_exit_recorder.append((1, bar.datetime))
                else:
                    self.atr_profit_exit_recorder.append((0, bar.datetime))

                if bar.close_price >= max(initial_profit_exit_price,
                                          moving_profit_exit_price):
                    self.sell(bar.close_price * 0.99, abs(self.pos))
                elif bar.close_price <= max(initial_loss_exit_price,
                                            moving_loss_exit_price):
                    self.sell(bar.close_price * 0.99, abs(self.pos))

            elif self.pos < 0:
                self.position_hold += 1
                sell_order_price = self.short_order_record[-1]
                #初始的盈利要求比较低即空头平仓的价格比较高
                initial_profit_exit_price = sell_order_price * (
                    1 - self.exit_return)
                # 随着持仓时间推移和波动率变大,对应盈利方向上的头寸止盈要求变高,即空头平仓价格下移
                moving_profit_exit_price = sell_order_price * (
                    1 + self.exit_return_soft_short
                ) - self.atr_value * self.atr_multiplier * self.position_hold
                initial_loss_exit_price = sell_order_price * (1 +
                                                              self.exit_loss)
                # 随着持仓时间推移和波动率变大,对应亏损方向上的头寸的平仓价格上升,即空头平仓价格上升
                moving_loss_exit_price = sell_order_price * (
                    1 + self.exit_loss_soft_short
                ) - self.atr_value * self.atr_multiplier * self.position_hold

                if bar.close_price >= min(initial_loss_exit_price,
                                          moving_loss_exit_price):
                    self.cover(bar.close_price * 1.01, abs(self.pos))
                elif bar.close_price <= min(initial_profit_exit_price,
                                            moving_profit_exit_price):
                    self.cover(bar.close_price * 1.01, abs(self.pos))

        # 通过设置合成Bar Data的周期可以使得持仓过夜
        elif bar.datetime.time() > self.exit_time:
            if self.pos > 0:
                self.sell(bar.close_price * 0.99, abs(self.pos))
            elif self.pos < 0:
                self.cover(bar.close_price * 1.01, 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.rsi_value_l_window = self.am15.rsi(self.rsi_window)

    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
Example #39
0
class TurtleSignalStrategy(CtaTemplate):
    """"""

    author = "用Python的交易员"

    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)