Пример #1
0
class BollVix(CtaTemplate):
    """"""
    author = "yunya"

    open_window = 15
    boll_window = 80
    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

    parameters = [
        "open_window",
        "boll_window",
        "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_window * 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

        # 计算布林
        self.boll_calculate()
        if not self.boll_inited:
            return

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

        # 计算数组
        self.boll_mid = boll_mid_array[-2]
        self.boll_up_current = self.up_array[-1]
        self.boll_up_last = self.up_array[-2]
        self.boll_down_current = self.down_array[-1]
        self.boll_down_last = self.down_array[-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(self.boll_up_current, 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(self.boll_down_current, 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)

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

    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_window, True)
        std_array = self.am.std(self.boll_window, True)
        dev = abs(self.am.close[:-1] - sma_array[:-1]) / std_array[:-1]
        dev_max = dev[-self.boll_window:].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
Пример #2
0
class DudlThrustEmaPositionStrategy(CtaTemplate):
    """"""
    author = "yunyu"

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

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

    ask = 0
    bid = 0

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

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

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

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

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

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

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

    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)
        self.ask = tick.ask_price_1  # 卖一价
        self.bid = tick.bid_price_1  # 买一价

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

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

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

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

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

            if self.atr_value == 0:
                return

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

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

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

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

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

                    self.exit_long = self.ema_mid

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

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

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

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

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

                    self.exit_short = self.ema_mid

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

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

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

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

        self.put_event()
        self.sync_data()

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

        if not self.am.inited:
            return

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    def stop_order(self):
        """"""
        pass
Пример #3
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

		# 状态控制初始化
		self.chase_long_trigger = False
		self.chase_sell_trigger = False
		self.chase_short_trigger = False
		self.chase_cover_trigger = False
		self.cancel_status = False
		self.long_trade_volume = 0
		self.short_trade_volume = 0
		self.sell_trade_volume = 0
		self.cover_trade_volume = 0
		self.chase_interval = 10  # 拆单间隔:秒

	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):
		working_order_dict = self.get_position_detail(tick.vt_symbol).active_orders
		# working_order_dict = self.order_dict
		if working_order_dict:
			# 委托完成状态
			order_finished = False
			vt_orderid = list(working_order_dict.items())[0][0]  # 委托单vt_orderid
			working_order = list(working_order_dict.items())[0][1]  # 委托单字典
			# 开平仓追单,部分交易没有平仓指令(Offset.NONE)
			"""获取到未成交委托单后检查未成交委托量>0,tick.datetime - 未成交委托单的datetime>追单间隔(chase_interval),
			同时chase_long_trigger状态未触发和有vt_orderid的判定(之前有收过空vt_orderid,所有要加个过滤),撤销该未成交委托单,
			赋值chase_long_trigger为True.chase_long_trigger为True且没有未成交委托单时执行追单,
			如有未成交委托单则调用cancel_surplus_order取消所有未成交委托单,追单的委托单发送出去后初始化chase_long_trigger.
			其他方向的撤单追单也是一样的流程"""
			if working_order.offset in (Offset.NONE, Offset.OPEN):
				if working_order.direction == Direction.LONG:
					self.long_trade_volume = working_order.untrade
					if (
							tick.datetime - working_order.datetime).seconds > self.chase_interval and self.long_trade_volume > 0 and (
					not self.chase_long_trigger) and vt_orderid:
						# 撤销之前发出的未成交订单
						self.cancel_order(vt_orderid)
						self.chase_long_trigger = True
				elif working_order.direction == Direction.SHORT:
					self.short_trade_volume = working_order.untrade
					if (
							tick.datetime - working_order.datetime).seconds > self.chase_interval and self.short_trade_volume > 0 and (
					not self.chase_short_trigger) and vt_orderid:
						self.cancel_order(vt_orderid)
						self.chase_short_trigger = True
			# 平仓追单
			elif working_order.offset in (Offset.CLOSE, Offset.CLOSETODAY):
				if working_order.direction == Direction.SHORT:
					self.sell_trade_volume = working_order.untrade
					if (
							tick.datetime - working_order.datetime).seconds > self.chase_interval and self.sell_trade_volume > 0 and (
					not self.chase_sell_trigger) and vt_orderid:
						self.cancel_order(vt_orderid)
						self.chase_sell_trigger = True
				if working_order.direction == Direction.LONG:
					self.cover_trade_volume = working_order.untrade
					if (
							tick.datetime - working_order.datetime).seconds > self.chase_interval and self.cover_trade_volume > 0 and (
					not self.chase_cover_trigger) and vt_orderid:
						self.cancel_order(vt_orderid)
						self.chase_cover_trigger = True
		else:
			order_finished = True
			self.cancel_status = False
		if self.chase_long_trigger:
			if order_finished:
				self.buy(tick.ask_price_1, self.long_trade_volume)
				self.chase_long_trigger = False
			else:
				self.cancel_surplus_order(list(working_order_dict))
		elif self.chase_short_trigger:
			if order_finished:
				self.short(tick.bid_price_1, self.short_trade_volume)
				self.chase_short_trigger = False
			else:
				self.cancel_surplus_order(list(working_order_dict))
		elif self.chase_sell_trigger:
			if order_finished:
				self.sell(tick.bid_price_1, self.sell_trade_volume)
				self.chase_sell_trigger = False
			else:
				self.cancel_surplus_order(list(working_order_dict))
		elif self.chase_cover_trigger:
			if order_finished:
				self.cover(tick.ask_price_1, self.cover_trade_volume)
				self.chase_cover_trigger = False
			else:
				self.cancel_surplus_order(list(working_order_dict))

	# ------------------------------------------------------------------------------------
	def cancel_surplus_order(self, orderids: list):
		"""
		撤销剩余活动委托单
		"""
		if not self.cancel_status:
			for vt_orderid in orderids:
				self.cancel_order(vt_orderid)
			self.cancel_status = True

	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
Пример #4
0
class Boll_Control_Proportion_Vix_Width(CtaTemplate):
    """"""
    author = "yunya"

    win_open = 21
    boll_window = 90
    prop = 1.8
    atr_window = 30
    trailing_long = 0.9
    trailing_short = 0.9
    exit_dc_length = 0
    fixed_size = 1

    exit_long = 0
    exit_short = 0
    entry_crossover = 0
    atr_value = 0
    intra_trade_high = 0
    intra_trade_low = 0
    long_stop = 0
    short_stop = 0

    parameters = [
        "win_open",
        "boll_window",
        "prop",
        "trailing_long",
        "trailing_short",
        "fixed_size",
    ]

    variables = [
        "entry_crossover",
        "atr_value",
        "intra_trade_high",
        "intra_trade_low",
        "long_stop",
        "short_stop",
        "exit_long",
        "exit_short",
    ]

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

        self.bg = NewBarGenerator(self.on_bar, self.win_open, self.on_xmin_bar)
        self.am = ArrayManager(self.boll_window + 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

        # Calculate array  计算数组
        self.sma_array = am.sma(self.boll_window, True)
        std_array = 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 + std_array * dev_max
        self.boll_down_array = self.sma_array - std_array * dev_max

        # Get current and last index
        current_sma = self.sma_array[-1]
        last_close = self.am.close[-2]
        currnet_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]
        up_limit = current_sma * (1 + self.prop / 100)
        down_limit = current_sma * (1 - self.prop / 100)

        boll_width = currnet_boll_up - current_boll_down

        self.exit_long, self.exit_short = self.am.donchian(self.exit_dc_length)

        # Get crossover
        if (last_close <= last_boll_up and bar.close_price > currnet_boll_up
                and bar.close_price < up_limit):
            self.entry_crossover = 1
        elif (last_close >= last_boll_down
              and bar.close_price < current_boll_down
              and bar.close_price > down_limit):
            self.entry_crossover = -1

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

            if self.entry_crossover > 0:
                self.buy(up_limit, self.fixed_size, True)

            elif self.entry_crossover < 0:
                self.short(down_limit, 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_stop_high = self.intra_trade_high - boll_width * self.trailing_long

            self.long_stop = max(long_stop_high, self.exit_short)

            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_stop = self.intra_trade_low + boll_width * self.trailing_short
            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.
        """
        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()
        pass
Пример #5
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
Пример #6
0
class AberrationBiasStrategy(CtaTemplate):
    """
    目前使用中轨加速,可以考虑使用另外一根均线来加速,这样可以避免在开仓时被平。
    """
    author = "yunya"

    open_window = 60
    boll_length = 80
    boll_dev = 2.0
    bias = 1.0
    cci_length = 6
    cci_exit = 10.0
    fixed_size = 1

    boll_up = 0
    boll_down = 0
    boll_mid = 0
    boll_mid_new = 0
    boll_mid_array = 0
    bias_value_array = 0
    bias_value = 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",
        "bias",
        "cci_length",
        "cci_exit",
        "fixed_size",
    ]

    variables = [
        "boll_up",
        "boll_down",
        "boll_mid",
        "bias_value",
        "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("策略启动")

    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()

        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_array = am.sma(self.boll_length, True)
        self.boll_mid = self.boll_mid_array[-1]
        self.bias_value_array = (self.am.close -
                                 self.boll_mid_array) / self.boll_mid_array
        self.bias_value = self.bias_value_array[-1]

        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, True)

            if self.cci_value < -self.cci_exit:
                self.short(self.boll_down, self.fixed_size, 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}")

            if self.bias_value > self.bias:
                self.exit_long = max(bar.close_price, self.exit_long)

            self.sell(self.exit_long, abs(self.pos), 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

            if self.bias_value < -self.bias:
                self.exit_short = min(self.exit_short, bar.close_price)

            self.cover(self.exit_short, abs(self.pos), 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
Пример #7
0
class RsiDcVixStrategy(CtaTemplate):
    """
    Rsi 原版逻辑

      Rsi 值 上破临界值 80 时平空做多,下破临界值 20 时平多做空。

    Rsi 策略优化思路:
    一、指标计算方式
        1、计算 N 周期 rsi
        2、计算 N 周期 RSI 的最大值为上轨,最小值为下轨
        3、rsi 上穿上轨,并且 rsi 大于 50 ,做多
        3、rsi 下穿下轨,并且 rsi 小于 50 ,做空

    """

    author = "yunya"

    open_window = 45
    rsi_window = 100
    exit_window = 65
    ema_window = 65
    atr_window = 16
    atr_window_ma = 10
    atr_multiplier = 10.0
    pos_trailing = 3.0
    fixed_size = 1

    exit_up = 0
    exit_down = 0
    atr_value = 0
    atr_value_ma = 0
    long_entry = 0
    short_entry = 0
    long_stop = 0
    short_stop = 0
    long_trade_stop = 0
    short_trade_stop = 0
    intra_trade_high = 0
    intra_trade_low = 0
    rsi_value_current = 0
    rsi_value_last = 0
    rsi_up_current = 0
    rsi_up_last = 0
    rsi_down_current = 0
    rsi_down_last = 0
    exit_long_nex = 0
    exit_long_last = 0
    exit_long = 0
    exit_short_nex = 0
    exit_short_last = 0
    exit_short = 0
    boll_mid = 0
    boll_mid_new = 0
    ema_window_new = 0

    parameters = [
        "open_window",
        "rsi_window",
        "exit_window",
        "ema_window",
        "atr_window",
        "atr_multiplier",
        "pos_trailing",
        "fixed_size",
    ]
    variables = [
        "exit_up",
        "exit_down",
        "atr_value",
        "long_entry",
        "short_entry",
        "long_stop",
        "short_stop",
        "long_trade_stop",
        "short_trade_stop",
        "intra_trade_high",
        "intra_trade_low",
        "rsi_value_current",
        "rsi_value_last",
        "rsi_up_current",
        "rsi_up_last",
        "rsi_down_current",
        "rsi_down_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_15min_bar)
        self.am = ArrayManager(self.rsi_window * 2)

        self.count: int = 0
        self.size: int = 4
        self.rsi_inited: bool = False
        self.rsi_up_array: np.ndarray = np.zeros(self.size)
        self.rsi_down_array: np.ndarray = np.zeros(self.size)

    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 tick data update.
        """
        self.bg.update_bar(bar)

    def on_15min_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

        # 计算 dev_max
        rsi_array = talib.RSI(self.am.close, self.rsi_window)

        if not self.rsi_inited:
            self.count += 1
            if self.count >= self.size:
                self.rsi_inited = True

        # rsi 上下轨容器
        self.rsi_up_array[:-1] = self.rsi_up_array[1:]
        self.rsi_down_array[:-1] = self.rsi_down_array[1:]

        rsi_up = rsi_array[-self.rsi_window:].max()
        rsi_down = rsi_array[-self.rsi_window:].min()

        self.rsi_up_array[-1] = rsi_up
        self.rsi_down_array[-1] = rsi_down

        if not self.rsi_inited:
            return

        rsi_value_array = am.rsi(self.rsi_window, True)

        self.rsi_value_current = rsi_value_array[-1]
        self.rsi_value_last = rsi_value_array[-2]

        # 取前一个值
        self.rsi_up_current = self.rsi_up_array[-2]
        self.rsi_up_last = self.rsi_up_array[-3]
        self.rsi_down_current = self.rsi_down_array[-2]
        self.rsi_down_last = self.rsi_down_array[-3]

        self.exit_up, self.exit_down = self.am.donchian(self.exit_window)
        atr_value_array = am.atr(self.atr_window, True)
        self.atr_value = atr_value_array[-1]
        self.atr_value_ma = atr_value_array[-self.atr_window_ma:].mean()

        self.boll_mid = am.sma(self.ema_window)

        # 没有仓
        if not self.pos:
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = bar.low_price
            rsi_inited_up = self.rsi_value_current > self.rsi_up_current and self.rsi_value_last <= self.rsi_up_last
            rsi_inited_down = self.rsi_value_current < self.rsi_down_current and self.rsi_value_last >= self.rsi_down_last
            atr_inited = self.atr_value > self.atr_window_ma

            self.ema_window_new = self.ema_window

            if rsi_inited_up and atr_inited and self.rsi_value_current > 50:
                self.buy(bar.close_price + 5, self.fixed_size)

            elif rsi_inited_down and atr_inited and self.rsi_value_current < 50:
                self.short(bar.close_price - 5, self.fixed_size)

        # 有多仓
        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_stop = self.intra_trade_high - self.atr_value * self.atr_multiplier

            self.long_stop = max(self.long_stop, self.exit_down)
            self.long_stop = max(self.long_stop, self.long_trade_stop)

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

            if close_long:
                self.ema_window_new -= 1
                self.ema_window_new = max(self.ema_window_new, 10)

            # 计算新的布林带
            self.boll_mid_new = am.sma(self.ema_window_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.ema_window_new = self.ema_window
                    # 下穿新均线,以原布林均线挂出停止单,避免快速下跌而无法止损
                    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

            self.long_stop = max(self.long_stop, 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_stop = self.intra_trade_low + self.atr_value * self.atr_multiplier

            self.short_stop = min(self.short_stop, self.exit_up)
            self.short_stop = min(self.short_stop, self.short_trade_stop)

            close_short = am.close[-1] < am.close[-2] < am.close[-3]
            if close_short:
                self.ema_window_new -= 1
                self.ema_window_new = max(self.ema_window_new, 10)

            # 计算新的布林带
            self.boll_mid_new = am.sma(self.ema_window_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.ema_window_new = self.ema_window

                    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.short_stop = min(self.short_stop, self.exit_short)

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

        self.put_event()
        self.sync_data()

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

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        if trade.direction == Direction.LONG:
            self.long_entry = trade.price  # 成交最高价
            self.long_trade_stop = self.long_entry * (1 -
                                                      self.pos_trailing / 100)
        else:
            self.short_entry = trade.price
            self.short_trade_stop = self.short_entry * (
                1 + self.pos_trailing / 100)
        self.put_event()
        self.sync_data()
Пример #8
0
class EmaDifferenceStrategy(CtaTemplate):
    """
    策略逻辑:
        1、计算两条不同周期均线的差离值,差离值二次求均值。
        2、当差离值大于零做多,小于零做空。
        3、成交价格回撤 2% 固定止损,当利润达到 5% 时,止损位移动到成本价。



        1、计算四条差离值线,并求30周期ema 如果所有差离线全部在零线附近(-0.1,+0.1),
        2、如果所有线上穿大周期开多,所有线下穿大周期开空。
        3、引入打分系统,各个指标计算,每个值为正向一分,分数达到N值开多,小于-N 开空。 小于N-时减部分仓位。
        4、判断各线之间上穿和下穿来打分,短周期上穿长周期加1分,短周期下穿长周期减1分,长周期是否拐头,拐头向上加一分,向下减一分。
    """
    author = "yunya"

    open_window = 15
    fastest_length = 10  # 最快
    fast_length = 30  # 快
    slow_length = 60  # 慢
    slowest_length = 120  # 最慢
    extremely_slow_length = 180  # 特慢
    diff_ema_length = 30  # 差离ema
    diff_deviate = 0.2  # 零轴的偏离最
    fixed_size = 1

    fast_ema = 0  # 差离均值
    slow_ema = 0
    slowest_ema = 0
    extremely_slow_ema = 0

    fast_diff_deviate = 0  # 差离线与零轴的位置
    slow_diff_deviate = 0
    slowest_diff_deviate = 0
    extremely_slow_diff_deviate = 0

    fast_slow_to = 0  # 判断上穿,下穿,上穿1 下穿-1
    fast_slowest_to = 0
    fast_extremely_slow_to = 0

    slow_slowest_to = 0
    slow_extremely_to = 0
    slowest_extremely_to = 0

    parameters = []

    variables = []

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

    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()
        am = self.am
        am.update_bar(bar)
        if not am.inited:
            return

        # 计算ema
        fastest_value = am.ema(self.fastest_length, True)
        fast_value = am.ema(self.fast_length, True)
        slow_value = am.ema(self.slow_length, True)
        slowest_value = am.ema(self.slowest_length, True)
        extremely_slow_value = am.ema(self.extremely_slow_length, True)

        # 计算差离值
        fastest_fast_diff = fastest_value - fast_value
        fast_slow_diff = fast_value - slow_value
        slow_slowest_diff = slow_value - slowest_value
        slowest_extremely_slow_diff = slow_value - extremely_slow_value

        # 计算差离均值
        self.fast_ema = talib.EMA(fastest_fast_diff, self.diff_ema_length)
        self.slow_ema = talib.EMA(fast_slow_diff, self.diff_ema_length)
        self.slowest_ema = talib.EMA(slow_slowest_diff, self.diff_ema_length)
        self.extremely_slow_ema = talib.EMA(slowest_extremely_slow_diff,
                                            self.diff_ema_length)

        # 判断差离线与零轴的位置(在零轴附近)
        self.fast_diff_deviate = self.on_diff_range(self.fast_ema,
                                                    self.diff_deviate)
        self.slow_diff_deviate = self.on_diff_range(self.slow_ema,
                                                    self.diff_deviate)
        self.slowest_diff_deviate = self.on_diff_range(self.slowest_ema,
                                                       self.diff_deviate)
        self.extremely_slow_diff_deviate = self.on_diff_range(
            self.extremely_slow_ema, self.diff_deviate)

        # 判断差离线交叉情况(上穿,下穿)
        self.fast_slow_to = self.on_diff_to_up_down(self.fast_ema,
                                                    self.slow_ema)
        self.fast_slowest_to = self.on_diff_to_up_down(self.fast_ema,
                                                       self.slowest_ema)
        self.fast_extremely_slow_to = self.on_diff_to_up_down(
            self.fast_ema, self.extremely_slow_ema)
        self.slow_slowest_to = self.on_diff_to_up_down(self.slow_ema,
                                                       self.slowest_ema)
        self.slow_extremely_to = self.on_diff_to_up_down(
            self.slow_ema, self.extremely_slow_ema)
        self.slowest_extremely_to = self.on_diff_to_up_down(
            self.slowest_ema, self.extremely_slow_ema)

        # 如果没有仓位,两条布林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, True)

            if self.cci_value < -self.cci_exit:
                self.short(self.boll_down, self.fixed_size, 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, 10)

            # 计算新的布林带
            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), 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, 10)

            # 计算新的布林带
            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), 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

    def on_diff_range(self, diff_array, diff_deviate):
        """
        判断 diff 是否在一定范围内
        :param diff_array:
        :param range:
        :return:
        """

        for i in range(1, 6, 1):

            diff_up = diff_array[-i] > -diff_deviate
            diff_down = diff_array[-i] < diff_deviate

            if diff_up and diff_down:
                diff_range = True
            else:
                diff_range = False
            return diff_range

    def on_diff_to_up_down(self, fastdiffema, slowdiffema):
        """
        差离线上穿、下穿
        :param diff_ema:
        :return:
        """
        current_fast_diff = fastdiffema[-1]
        last_fast_diff = fastdiffema[-2]
        current_slow_diff = slowdiffema[-1]
        last_slow_diff = slowdiffema[-2]
        to_up_down = 0

        if current_fast_diff > current_slow_diff and last_fast_diff <= last_slow_diff:
            to_up_down = 1
        elif current_fast_diff < current_slow_diff and last_fast_diff >= last_slow_diff:
            to_up_down = -1
        else:
            to_up_down = 0

        return to_up_down
Пример #9
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 MacdRsibollDcMinuteStrategy(CtaTemplate):
	"""
	策略逻辑:
	一、、过虑信号  (小时周期)
	1、使用macd 快慢线交叉来判断多空大方向。
	2、使用rsiboll来判断信号强弱

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

	三、止损
	1、使用固定止损
	2、dc 移动止损
	3、布林宽度比例
	三个止损相结合的方式
	"""
	author = "yunya"

	max_window = 45
	min_window = 15
	open_window = 5
	fast_macd = 12
	slow_macd = 26
	signal_macd = 9
	macd_trend_level = 1.0
	rsi_length = 15
	boll_length = 20
	boll_dev = 2.0
	dc_length = 20
	atr_window = 30
	trailing_tax = 2.0
	risk_level = 1

	exit_down = 0
	exit_up = 0
	macd = 0
	macd_entry = 0
	rsi_entry = 0
	intra_trade_high = 0
	intra_trade_low = 0
	long_stop = 0
	short_stop = 0
	atr_value = 0

	parameters = [
		"max_window",
		"min_window",
		"open_window",
		"fast_macd",
		"slow_macd",
		"signal_macd",
		"macd_trend_level",
		"boll_length",
		"boll_dev",
		"rsi_length",
		"dc_length",
		"atr_window",
		"trailing_tax",
		"risk_level",
	]

	variables = [
		"exit_down",
		"exit_up",
		"macd",
		"macd_entry",
		"rsi_entry",
		"intra_trade_high",
		"intra_trade_low",
		"long_stop",
		"short_stop",
		"atr_value",
	]

	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_xhour = NewBarGenerator(
			on_bar=self.on_bar,
			window=self.max_window,
			on_window_bar=self.on_xhour_bar,
			interval=Interval.MINUTE   # 由小时修改到分钟级
		)
		self.am_hour = ArrayManager(self.boll_length + 100)

		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.boll_length + 100)

		self.bg_open = NewBarGenerator(
			on_bar=self.on_bar,
			window=self.open_window,
			on_window_bar=self.on_5min_bar
		)
		self.am_open = ArrayManager(self.dc_length * int(self.min_window / self.open_window) + 30)

	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_open.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_xhour.update_bar(bar)
		self.bg_xminute.update_bar(bar)
		self.bg_open.update_bar(bar)

	def on_5min_bar(self, bar: BarData):

		self.cancel_all()
		self.am_open.update_bar(bar)

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

		#
		self.exit_up, self.exit_down = self.am_open.donchian(
			self.dc_length * int(self.min_window / self.open_window))

		if not self.pos:

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

			if self.macd_entry > 0 and self.rsi_entry > 0:
				self.buy(self.boll_up, self.trading_size, True)
			# print(bar.datetime, self.boll_up, self.trading_size)
			# print(bar.datetime, self.entry_up, self.trading_size, bar)

			if self.macd_entry < 0 and self.rsi_entry < 0:
				self.short(self.boll_down, 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)

		elif self.pos < 0:
			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(short_low, abs(self.pos), True)

		self.put_event()

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

		rsi_array = talib.RSI(self.am_xminute.close[:-1], self.rsi_length)
		ema_array = talib.EMA(self.am_xminute.close, self.rsi_length)

		dev_array = abs(self.am_xminute.close[:-1] - ema_array[:-1]) / rsi_array

		rsi_up_array = rsi_array + rsi_array * dev_array
		rsi_dow_array = rsi_array - rsi_array * dev_array

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

		current_rsi_up = rsi_up_array[-1]
		current_rsi_down = rsi_dow_array[-1]
		current_rsi_value = self.rsi_value[-1]

		if current_rsi_value > current_rsi_up:
			self.rsi_entry = 1
		elif current_rsi_value < current_rsi_down:
			self.rsi_entry = -1
		else:
			self.rsi_entry = 0

		self.boll_up, self.boll_down = self.am_xminute.boll(self.boll_length, self.boll_dev)

	def on_xhour_bar(self, bar: BarData):
		""""""
		am_hour = self.am_hour
		am_hour.update_bar(bar)

		if not am_hour.inited:
			return
		macd_signal, signal, hist = self.am_hour.macd(
			self.fast_macd,
			self.slow_macd,
			self.signal_macd
		)
		self.macd = signal - hist

		if self.macd > self.macd_trend_level:
			self.macd_entry = 1

		elif self.macd < (-self.macd_trend_level):
			self.macd_entry = -1
		else:
			self.macd_entry = 0

		# 动态调整仓位
		if not self.pos:
			self.atr_value = self.am_hour.atr(self.atr_window)

			if self.atr_value == 0:  # 保证仓位值是有效的
				return
			# 正向合约
			atr_risk = self.am_hour.atr(self.atr_window)
			self.trading_size = max(int(self.risk_level / atr_risk), 1)

		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()
Пример #11
0
class EmaDifferenceStrategy(CtaTemplate):
    """
    策略逻辑:
        1、计算两条不同周期均线的差离值,差离值二次求均值。
        2、当差离值大于零做多,小于零做空。
        3、成交价格回撤 2% 固定止损,当利润达到 5% 时,止损位移动到成本价。
    """
    author = "yunya"

    open_window = 15
    express_length = 30  # 特快
    fast_length = 60  # 快
    slow_length = 150  # 慢
    diff_ema_length = 30  # 差离ema
    atr_length = 6
    atr_multiple = 2.0  # 成交价 2倍ATR为固定止损位
    entry_mulitple = 5.0  # 当前价格超过成交价的5%时,止损价为成交价
    pay_up = 5
    fixed_size = 1

    current_express_fast_diff = 0
    last_express_fast_diff = 0
    current_fast_slow_diff = 0
    last_fast_slow_diff = 0
    current_express_fast_ema = 0
    last_express_fast_ema = 0
    current_fast_slow_ema = 0
    last_fast_slow_ema = 0
    express_fast_inited = 0
    fast_slow_inited = 0
    price_tick = 0
    atr_value = 0
    long_entry = 0
    long_stop = 0
    short_entry = 0
    short_stop = 0
    exit_long = 0
    exit_short = 0

    parameters = [
        "open_window",
        "express_length",
        "fast_length",
        "slow_length",
        "diff_ema_length",
        "atr_length",
        "atr_multiple",
        "entry_mulitple",
        "pay_up",
        "fixed_size",
    ]

    variables = [
        "current_express_fast_diff",
        "last_express_fast_diff",
        "current_fast_slow_diff",
        "last_fast_slow_diff",
        "current_express_fast_ema",
        "last_express_fast_ema",
        "current_fast_slow_ema",
        "last_fast_slow_ema",
        "express_fast_inited",
        "fast_slow_inited",
        "price_tick",
        "atr_value",
        "long_entry",
        "long_stop",
        "short_entry",
        "short_stop",
        "exit_long",
        "exit_short",
    ]

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

        self.bg = NewBarGenerator(self.on_bar, self.open_window,
                                  self.on_xmin_bar)
        self.am = ArrayManager(int(self.slow_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("策略启动")

    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()
        am = self.am
        am.update_bar(bar)
        if not am.inited:
            return

        # 计算ema
        express_value = am.ema(self.express_length, True)
        fast_value = am.ema(self.fast_length, True)
        slow_value = am.ema(self.slow_length, True)

        # 计算差离值
        express_fast_diff = express_value - fast_value
        fast_slow_diff = fast_value - slow_value

        # 计算差离均值
        express_fast_ema = talib.EMA(express_fast_diff, self.diff_ema_length)
        fast_slow_ema = talib.EMA(fast_slow_diff, self.diff_ema_length)
        # print(f"express_fast_ema: {express_fast_ema[-10:]}" + "\n")
        # print(f"fast_slow_ema: {fast_slow_ema[-10:]}" + "\n")

        # 判断差离线交叉情况(上穿,下穿)
        self.current_express_fast_diff = express_fast_diff[-1]
        self.last_express_fast_diff = express_fast_diff[-2]
        self.current_fast_slow_diff = fast_slow_diff[-1]
        self.last_fast_slow_diff = fast_slow_diff[-2]

        self.current_express_fast_ema = express_fast_ema[-1]
        self.last_express_fast_ema = express_fast_ema[-2]
        self.current_fast_slow_ema = fast_slow_ema[-1]
        self.last_fast_slow_ema = fast_slow_ema[-2]

        # 计算上穿,下穿零轴
        if self.current_express_fast_ema > 0 and self.last_express_fast_ema <= 0:
            self.express_fast_inited = 1

        elif self.current_express_fast_ema < 0 and self.last_express_fast_ema >= 0:
            self.express_fast_inited = -1
        else:
            self.express_fast_inited = 0
        print(f"特慢:{self.express_fast_inited}" + "\n")
        if self.current_fast_slow_ema > 0 and self.last_fast_slow_ema <= 0:
            self.fast_slow_inited = 1

        elif self.current_fast_slow_ema < 0 and self.last_fast_slow_ema >= 0:
            self.fast_slow_inited = -1
        else:
            self.fast_slow_inited = 0

        # 如果没有仓位,两条布林window一样
        if self.pos == 0:
            # 判断是回测,还是实盘
            engine_type = self.get_engine_type()
            if engine_type == EngineType.BACKTESTING:
                long_price = bar.close_price - 10
                short_price = bar.close_price + 10
            else:
                self.price_tick = self.get_pricetick()
                long_price = bar.close_price - self.price_tick * self.pay_up
                short_price = bar.close_price + self.price_tick * self.pay_up

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

            if self.fast_slow_inited > 0:
                self.buy(long_price, self.fixed_size)

            elif self.fast_slow_inited < 0:
                self.short(short_price, self.fixed_size)

        elif self.pos > 0:
            long_stop_entry = bar.close_price * (1 - self.entry_mulitple / 100)
            self.exit_long = max(self.long_stop, long_stop_entry)

            if self.express_fast_inited < 0:
                # self.exit_long = bar.close_price - self.price_tick * self.pay_up
                self.exit_long = bar.close_price - 10

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

        elif self.pos < 0:
            short_stop_entry = bar.close_price * (1 +
                                                  self.entry_mulitple / 100)
            self.exit_short = min(self.short_stop, short_stop_entry)

            if self.express_fast_inited > 0:
                # self.exit_short = bar.close_price + self.price_tick * self.pay_up
                self.exit_short = bar.close_price + 10
            self.cover(self.exit_short, abs(self.pos), 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.
        """
        if trade.direction == Direction.LONG:
            self.long_entry = trade.price  # 成交最高价
            self.long_stop = self.long_entry - self.atr_multiple * self.atr_value
        else:
            self.short_entry = trade.price
            self.short_stop = self.short_entry + self.atr_multiple * self.atr_value

        self.sync_data()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        self.put_event()
        pass
Пример #12
0
class AtrStop_Dc_Strategy(CtaTemplate):
    """"""
    author = "yunya"

    atrstop_window = 46
    open_window = 5
    distance_line = 2.0
    nloss_singnal = 2.7
    dc_length = 50
    fixd_size = 1
    atr_window = 30

    atr_entry = 0
    current_atr_stop = 0.0
    last_atr_stop = 0.0
    nloss_array = 0.0
    exit_short = 0
    exit_long = 0

    ask = 0
    bid = 0
    atr_value = 0

    parameters = [
            "atrstop_window",
            "open_window",
            "nloss_singnal",
            "dc_length",
            "distance_line",
            "fixd_size",
            "atr_window"
    ]

    variables = [
        "current_atr_stop",
        "last_atr_stop",
        "exit_short",
        "exit_long",
        "atr_entry",
    ]

    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
        )
        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()

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

    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.atr_value = self.am_5min.atr(self.atr_window)

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

            up_limit = self.current_atr_stop * (1 + self.distance_line / 100)
            down_limit = self.current_atr_stop * (1 - self.distance_line / 100)

            if self.atr_entry > 0 and bar.close_price < up_limit:
                self.buy(self.current_atr_stop, self.fixd_size, True)

            elif self.atr_entry < 0 and bar.close_price > down_limit:
                self.short(self.current_atr_stop, self.fixd_size, True)

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

        elif self.pos < 0:
            self.cover(self.exit_short, 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.ema_array = am_xmin.ema(3, array=True)
        self.nloss_array = am_xmin.atr(16, array=True) * self.nloss_singnal

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

        # 初始化
        if self.atr_stop_array[-3] == 0:
            return

        self.current_atr_stop = self.atr_stop_array[-1]
        self.last_atr_stop = self.atr_stop_array[-2]
        current_ema = self.ema_array[-1]
        last_ema = self.ema_array[-2]

        if last_ema <= self.last_atr_stop and current_ema > self.current_atr_stop:
            self.atr_entry = 1
        elif last_ema >= self.last_atr_stop and current_ema < self.current_atr_stop:
            self.atr_entry = -1

        self.exit_short,self.exit_long = self.am_xmin.donchian(self.dc_length)
        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
Пример #13
0
class RisBollStrategy(CtaTemplate):
    """
    目前使用中轨加速,可以考虑使用另外一根均线来加速,这样可以避免在开仓时被平。
    """
    author = "yunya"

    open_window = 15
    boll_length = 80
    boll_dev = 2.0
    rsi_window = 12
    rsi_entry = 19
    atr_window = 16
    long_trailing = 4.0
    short_trailing = 4.0
    fixed_size = 1

    rsi_long = 0
    rsi_short = 0
    rsi_value = 0
    atr_value = 0
    boll_up = 0
    boll_down = 0
    boll_mid = 0
    boll_mid_new = 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
    long_stop_trade = 0
    short_stop_trade = 0
    trade_price_long = 0
    trade_price_short = 0

    parameters = [
                "open_window",
                "boll_length",
                "boll_dev",
                "rsi_window",
                "rsi_entry",
                "atr_window",
                "long_trailing",
                "short_trailing",
                "fixed_size",
                ]

    variables = [
            "rsi_long",
            "rsi_short",
            "rsi_value",
            "atr_value",
            "boll_up",
            "boll_down",
            "boll_mid",
            "boll_mid_new",
            "exit_long",
            "exit_short",
            "boll_length_new",
            "exit_long_nex",
            "exit_long_last",
            "exit_short_nex",
            "exit_short_last",
            "long_stop_trade",
            "short_stop_trade",
            "trade_price_long",
            "trade_price_short",
                ]

    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.rsi_long = 50 + self.rsi_entry
        self.rsi_short = 50 - self.rsi_entry

        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()

        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.rsi_value = am.rsi(self.rsi_window)

        # 如果没有仓位,两条布林window一样
        if self.pos == 0:
            self.atr_value = am.atr(self.atr_window)
            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.rsi_value > self.rsi_long:
                self.buy(self.boll_up, self.fixed_size, True)

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

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

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

            # 计算新的布林带
            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

                else:
                    # 收盘价在两条均线平均价上方,以当前收盘价挂出限价单
                    if self.am.close[-1] > ((self.boll_mid + self.boll_mid_new[-1]) / 2):
                        self.exit_long = bar.close_price

                    elif bar.close_price < self.boll_mid:
                        self.exit_long = bar.close_price
                    else:
                        self.exit_long = self.boll_mid

            else:
                self.exit_long = self.boll_mid

            if bar.close_price < self.trade_price_long * (1 - self.long_trailing / 100):
                exit_long_price = self.trade_price_long * (1 - (self.long_trailing + 1) / 100)
                self.exit_long = max(exit_long_price, self.exit_long)

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

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

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

            # 计算新的布林带
            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

            # 如果 有3%以上的收益,止损价为买入成交价
            if bar.close_price > self.trade_price_short * (1 + self.short_trailing / 100):
                exit_short_price = self.trade_price_short * (1 + (self.short_trailing + 1) / 100)
                self.exit_short = min(exit_short_price, self.exit_short)

            self.exit_short = min(self.exit_short, self.short_stop_trade)
            self.cover(self.exit_short, abs(self.pos), 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.
        """
        if trade.direction == Direction.LONG:
            self.trade_price_long = trade.price  # 成交最高价
            self.long_stop_trade = self.trade_price_long - 2 * self.atr_value
        else:
            self.trade_price_short = trade.price
            self.short_stop_trade = self.trade_price_short + 2 * self.atr_value

        self.sync_data()
        self.put_event()
Пример #14
0
class BollVixJStrategy(CtaTemplate):
    """
一、灵感来源
    我基于动量自适应布林短线策略的原始版本,做了非常小的修改,但回测效果惊人。

    「gcouple.j」动量自适应布林短线策略v1
    https://forum.quantclass.cn/d/1784-gcouplej-btc61eth1481

    1.1 自适应布林的原理:
    对于时间窗口参数是n1, 标准差倍数m的布林策略

    close:每周期收盘价

    ma(n1):时间窗口参数是n1的移动平均值

    std(n1):时间窗口参数是n1的标准差

    突破布林上轨的条件

    close > ma(n1) + m*std(n1)

    即:(close-ma(n1))/std(n1) > m

    突破布林下轨条件

    close < ma(n1) - m*std(n1)

    即:-(close-ma(n1))/std(n1) > m

    将布林突破上下轨的条件合并

    abs((close-ma(n1))/std(n1)) > m

    通过将m转为n的函数达到构建自适应布林的目的,即

    令 m=max(abs((close-ma(n1))/std(n1)))

    此处修改,令m=mean(abs((close-ma(n1))/std(n1)))

    由此,只需一个参数即可完成布林通道的构建。

1.2 对指标构建自适应布林通道
    通过对动量指标构建自适应布林通道,可以得到日内级别短线参数。

二、策略思路
    将
        df['m'] = df['z_score'].rolling(window=n1).max().shift(1)
    改成
        df['m'] = df['z_score'].rolling(window=n1).mean()

三、代码
    3.1、策略代码
        def adaptboll_with_mtm_v2(df, para=[90]):
          n1 = para[0]

          # 计算动量因子
          df['mtm'] = df['close'] / df['close'].shift(n1) - 1
          df['mtm_mean'] = df['mtm'].rolling(window=n1, min_periods=1).mean()


          # 基于价格atr,计算波动率因子wd_atr
          df['c1'] = df['high'] - df['low']
          df['c2'] = abs(df['high'] - df['close'].shift(1))
          df['c3'] = abs(df['low'] - df['close'].shift(1))
          df['tr'] = df[['c1', 'c2', 'c3']].max(axis=1)
          df['atr'] = df['tr'].rolling(window=n1, min_periods=1).mean()
          df['avg_price'] = df['close'].rolling(window=n1, min_periods=1).mean()
          df['wd_atr'] = df['atr'] / df['avg_price']

          # 参考ATR,对MTM指标,计算波动率因子
          df['mtm_l'] = df['low'] / df['low'].shift(n1) - 1
          df['mtm_h'] = df['high'] / df['high'].shift(n1) - 1
          df['mtm_c'] = df['close'] / df['close'].shift(n1) - 1
          df['mtm_c1'] = df['mtm_h'] - df['mtm_l']
          df['mtm_c2'] = abs(df['mtm_h'] - df['mtm_c'].shift(1))
          df['mtm_c3'] = abs(df['mtm_l'] - df['mtm_c'].shift(1))
          df['mtm_tr'] = df[['mtm_c1', 'mtm_c2', 'mtm_c3']].max(axis=1)
          df['mtm_atr'] = df['mtm_tr'].rolling(window=n1, min_periods=1).mean()

          # 参考ATR,对MTM mean指标,计算波动率因子
          df['mtm_l_mean'] = df['mtm_l'].rolling(window=n1, min_periods=1).mean()
          df['mtm_h_mean'] = df['mtm_h'].rolling(window=n1, min_periods=1).mean()
          df['mtm_c_mean'] = df['mtm_c'].rolling(window=n1, min_periods=1).mean()
          df['mtm_c1'] = df['mtm_h_mean'] - df['mtm_l_mean']
          df['mtm_c2'] = abs(df['mtm_h_mean'] - df['mtm_c_mean'].shift(1))
          df['mtm_c3'] = abs(df['mtm_l_mean'] - df['mtm_c_mean'].shift(1))
          df['mtm_tr'] = df[['mtm_c1', 'mtm_c2', 'mtm_c3']].max(axis=1)
          df['mtm_atr_mean'] = df['mtm_tr'].rolling(window=n1, min_periods=1).mean()

          indicator = 'mtm_mean'

          # mtm_mean指标分别乘以三个波动率因子
          df[indicator] = df[indicator] * df['mtm_atr']
          df[indicator] = df[indicator] * df['mtm_atr_mean']
          df[indicator] = df[indicator] * df['wd_atr']

          # 对新策略因子计算自适应布林
          df['median'] = df[indicator].rolling(window=n1).mean()
          df['std'] = df[indicator].rolling(n1, min_periods=1).std(ddof=0)  # ddof代表标准差自由度
          df['z_score'] = abs(df[indicator] - df['median']) / df['std']
          # df['m'] = df['z_score'].rolling(window=n1).max().shift(1)
          df['m'] = df['z_score'].rolling(window=n1).mean()
          df['up'] = df['median'] + df['std'] * df['m']
          df['dn'] = df['median'] - df['std'] * df['m']

          # 突破上轨做多
          condition1 = df[indicator] > df['up']
          condition2 = df[indicator].shift(1) <= df['up'].shift(1)
          condition = condition1 & condition2
          df.loc[condition, 'signal_long'] = 1

          # 突破下轨做空
          condition1 = df[indicator] < df['dn']
          condition2 = df[indicator].shift(1) >= df['dn'].shift(1)
          condition = condition1 & condition2
          df.loc[condition, 'signal_short'] = -1

          # 均线平仓(多头持仓)
          condition1 = df[indicator] < df['median']
          condition2 = df[indicator].shift(1) >= df['median'].shift(1)
          condition = condition1 & condition2
          df.loc[condition, 'signal_long'] = 0

          # 均线平仓(空头持仓)
          condition1 = df[indicator] > df['median']
          condition2 = df[indicator].shift(1) <= df['median'].shift(1)
          condition = condition1 & condition2
          df.loc[condition, 'signal_short'] = 0



          # ===由signal计算出实际的每天持有仓位
          # signal的计算运用了收盘价,是每根K线收盘之后产生的信号,到第二根开盘的时候才买入,仓位才会改变。
          df['signal_short'].fillna(method='ffill', inplace=True)
          df['signal_long'].fillna(method='ffill', inplace=True)
          df['signal'] = df[['signal_long', 'signal_short']].sum(axis=1)
          df['signal'].fillna(value=0, inplace=True)
          # df['signal'] = df[['signal_long', 'signal_short']].sum(axis=1, min_count=1,
          #                                                        skipna=True)  # 若你的pandas版本是最新的,请使用本行代码代替上面一行
          temp = df[df['signal'].notnull()][['signal']]
          temp = temp[temp['signal'] != temp['signal'].shift(1)]
          df['signal'] = temp['signal']

          df.drop(['signal_long', 'signal_short', 'atr', 'z_score'], axis=1,
                  inplace=True)
          return df

    3.2、策略参数组合
    # 策略参数组合
    def adaptboll_with_mtm_v2_para_list(m_list=range(1, 100, 1)):

        print('参数遍历范围:')
        print('m_list', list(m_list))

        para_list = []

        for m in m_list:
          para = [m]
          para_list.append(para)

        return para_list

    4.2、策略总体评价
        strategy_name	symbol	年化收益回撤比
        adaptboll_with_mtm_v2	BTC	14.415570606108213
        adaptboll_with_mtm_v2	ETH	38.00534253439086


    """

    author = "yunya"

    open_window = 15
    boll_length = 50
    fixed_size = 1

    atr_value = 0
    mtm_ma_current = 0
    mtm_ma_last = 0
    boll_up_current = 0
    boll_up_last = 0
    boll_down_current = 0
    boll_down_last = 0
    boll_mid_current = 0
    boll_mid_last = 0

    bar_length = 8

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

    variables = [
        "atr_value",
        "mtm_ma_current",
        "mtm_ma_last",
        "boll_up_current",
        "boll_up_last",
        "boll_down_current",
        "boll_down_last",
        "boll_mid_current",
        "boll_mid_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) * (self.bar_length * 2))

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

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

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

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

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

    def on_xmin_bar(self, bar: BarData):
        """
        m=mean(abs((close-ma(n1))/std(n1)))
        :param bar:
        :return:
        """
        self.cancel_all()

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

        # 计算动量因子 MTM
        mtm_array = radio_array(am.close, self.boll_length, self.bar_length)
        mtm_ma = talib.MA(mtm_array, self.boll_length)

        # 计算atr 相对emaatr的波动率 计算波动率因子wd_atr
        atr_array = am.atr(self.boll_length, array=True)
        self.atr_value = atr_array[-1]

        atr_ma = talib.MA(atr_array, self.boll_length)
        wd_atr = atr_array / atr_ma

        # 参考ATR,对MTM指标,计算波动率因子
        mtm_high = radio_array(am.high, self.boll_length, self.bar_length)
        mtm_low = radio_array(am.low, self.boll_length, self.bar_length)
        mtm_close = radio_array(am.close, self.boll_length, self.bar_length)

        mtm_atr_array = talib.ATR(mtm_high, mtm_low, mtm_close,
                                  self.boll_length)
        mtm_atr_ma = talib.MA(mtm_atr_array, self.boll_length)

        # 参考ATR,对MTM mean指标,计算波动率因子
        mtm_high_mean = talib.MA(mtm_high, self.boll_length)
        mtm_low_mean = talib.MA(mtm_low, self.boll_length)
        mtm_close_mean = talib.MA(mtm_close, self.boll_length)

        mtm_atr_mean_array = talib.ATR(mtm_high_mean, mtm_low_mean,
                                       mtm_close_mean, self.boll_length)
        mtm_atr_meam_ma = talib.MA(mtm_atr_mean_array, self.boll_length)

        # mtm_mean指标分别乘以三个波动率

        mtm_ma = mtm_ma * wd_atr[-self.boll_length * self.bar_length:]
        mtm_ma = mtm_ma * mtm_atr_ma[-self.boll_length * self.bar_length:]
        mtm_ma = mtm_ma * mtm_atr_meam_ma[-self.boll_length * self.bar_length:]

        mtm_meam = talib.MA(mtm_ma, self.boll_length)
        mtm_std = talib.STDDEV(mtm_meam, self.boll_length)

        mtm_dev = abs(mtm_ma - mtm_meam) / mtm_std
        mtm_dev_me = talib.MA(mtm_dev, self.boll_length)

        boll_up = mtm_meam + mtm_std * mtm_dev_me
        boll_down = mtm_meam - mtm_std * mtm_dev_me

        # 值
        self.mtm_ma_current = mtm_ma[-1]
        self.mtm_ma_last = mtm_ma[-2]
        self.boll_up_current = boll_up[-1]
        self.boll_up_last = boll_up[-2]
        self.boll_down_current = boll_down[-1]
        self.boll_down_last = boll_down[-2]
        self.boll_mid_current = mtm_meam[-1]
        self.boll_mid_last = mtm_meam[-2]

        # 如果没有仓位,两条布林window一样
        if self.pos == 0:
            if self.mtm_ma_current > self.boll_up_current and self.mtm_ma_last <= self.boll_up_last:
                self.buy(bar.close_price, self.fixed_size)

            elif self.mtm_ma_current < self.boll_down_current and self.mtm_ma_last >= self.boll_down_last:
                self.short(bar.close_price, self.fixed_size)

        elif self.pos > 0:
            if self.mtm_ma_current < self.boll_mid_current and self.mtm_ma_last >= self.boll_mid_last:
                self.sell(bar.close_price, abs(self.pos))  # 要优化

        elif self.pos < 0:
            if self.mtm_ma_current > self.boll_mid_current and self.mtm_ma_last <= self.boll_mid_last:
                self.cover(bar.close_price, abs(self.pos))

        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.
        """
        pass
Пример #15
0
class BollBbWidthtrategy(CtaTemplate):
    """
    布林带策略优化:
        1、计算布林极限指标  BB = (收盘价 - 布林下轨)/(上轨 - 下轩)  区间:0-1
        2、计算布林宽度指标 width = (上轨 - 下轨) / 中轨  区间: 
    """
    author = "yunya"

    open_window = 36
    boll_length = 24
    prop = 1.8
    atr_window = 30
    sl_multiplier = 0.2
    dc_length = 20
    fixed_size = 1

    entry_crossover = 0
    atr_value = 0
    intra_trade_high = 0
    intra_trade_low = 0
    long_stop_trade = 0
    short_stop_trade = 0
    long_stop = 0
    short_stop = 0
    exit_short = 0
    exit_long = 0
    entry_ema = 0

    parameters = [
        "open_window",
        "boll_length",
        "dc_length",
        "sl_multiplier",
        "prop",
        "fixed_size",
    ]

    variables = ["entry_crossover", "long_stop", "short_stop"]

    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

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

        # Get current and last index
        current_sma = self.sma_array[-1]
        last_sma = self.sma_array[-2]
        last_close = self.am.close[-2]
        currnet_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]
        up_limit = current_sma * (1 + self.prop / 100)
        down_limit = current_sma * (1 - self.prop / 100)

        boll_width = currnet_boll_up - current_boll_down

        # Get crossover
        if (last_close <= last_boll_up
                and currnet_boll_up < bar.close_price < up_limit):
            self.entry_crossover = 1
        elif (last_close >= last_boll_down
              and current_boll_down > bar.close_price > down_limit):
            self.entry_crossover = -1

        if (last_close <= last_sma and bar.close_price > current_sma):
            self.entry_ema = -1
        elif (last_close >= last_sma and bar.close_price < current_sma):
            self.entry_ema = 1
        else:
            self.entry_ema = 0

        self.atr_value = am.atr(self.atr_window)
        self.exit_short, self.exit_long = self.am.donchian(self.dc_length)

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

            if self.entry_crossover > 0:
                self.buy(up_limit, self.fixed_size, True)

            elif self.entry_crossover < 0:
                self.short(down_limit, self.fixed_size, True)

        elif self.pos > 0:
            if self.entry_ema > 0:
                self.sell((bar.close_price - 5), abs(self.pos))

            # 最高价回撤比例、固定止损、唐安奇下轨中的最大值为止损位
            self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
            self.intra_trade_low = bar.low_price

            long_stop_high = self.intra_trade_high - boll_width * self.sl_multiplier
            long_high_trade = max(long_stop_high, self.long_stop_trade)
            self.long_stop = max(self.exit_long, long_high_trade)

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

        elif self.pos < 0:
            if self.entry_ema < 0:
                self.cover((bar.close_price + 5), abs(self.pos))
            else:
                # 最低价回撤比例、固定止损、唐安奇上轨中的最小值为止损位
                self.intra_trade_high = bar.high_price
                self.intra_trade_low = min(self.intra_trade_low, bar.low_price)

                short_stop_low = self.intra_trade_low + boll_width * self.sl_multiplier
                short_low_trade = min(short_stop_low, self.short_stop_trade)
                self.short_stop = min(short_low_trade, self.exit_short)

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

        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 == 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_trade = self.short_entry + 2 * self.atr_value

        self.sync_data()
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        self.put_event()
        pass
Пример #16
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()
Пример #17
0
class BollStdvix(CtaTemplate):
    """"""
    author = "yunya"

    win_open = 15
    boll_window = 80
    atr_window = 30
    rsi_window = 16
    rsi_entry = 19
    atr_multiple = 2.1
    fixed_size = 1

    rsi_value = 0
    rsi_long = 0
    rsi_short = 0

    entry_rsi = 0
    entry_crossover = 0
    atr_value = 0
    intra_trade_high = 0
    intra_trade_low = 0
    long_entry = 0
    short_entry = 0
    long_stop = 0
    short_stop = 0
    current_sma = 0
    sma_array = 0
    boll_up_array = 0
    boll_down_array = 0
    trade_price_long = 0
    long_stop_trade = 0
    trade_price_short = 0
    short_stop_trade = 0

    parameters = [
            "win_open",
            "boll_window",
            "atr_window",
            "rsi_window",
            "rsi_entry",
            "atr_multiple",
            "fixed_size",
    ]

    variables = [
            "entry_crossover",
            "entry_rsi",
            "atr_value",
            "long_entry",
            "short_entry",
            "long_stop",
            "short_stop"
    ]

    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.win_open, self.on_xmin_bar)
        self.am = ArrayManager(self.boll_window + 100)

    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.rsi_long = 50 + self.rsi_entry
        self.rsi_short = 50 - self.rsi_entry
        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

        # Calculate array  计算数组
        self.rsi_value = am.rsi(self.rsi_window, True)
        self.sma_array = am.sma(self.boll_window, True)
        std_array = am.std(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 + std_array * dev_max
        self.boll_down_array = self.sma_array - std_array * dev_max

        # Get current and last index
        last_rsi_value = self.rsi_value[-2]
        current_rsi_value = self.rsi_value[-1]

        self.current_sma = self.sma_array[-1]
        last_close = self.am.close[-2]
        self.current_boll_up = self.boll_up_array[-1]
        last_boll_up = self.boll_up_array[-2]
        self.current_boll_down = self.boll_down_array[-1]
        last_boll_down = self.boll_down_array[-2]

        # Get crossover
        if current_rsi_value > self.rsi_short > last_rsi_value:
            self.entry_rsi = 1
        elif current_rsi_value < self.rsi_long < last_rsi_value:
            self.entry_rsi = -1
        else:
            self.entry_rsi = 0

        if bar.close_price > self.current_boll_up and last_close <= last_boll_up:
            self.entry_crossover = 1

        elif bar.close_price < self.current_boll_down and last_close >= last_boll_down:
            self.entry_crossover = -1
        else:
            self.entry_crossover = 0

        if not self.pos:
            self.atr_value = am.atr(self.atr_window)
            # 进出场逻辑,可以优化
            if self.entry_crossover > 0:
                self.long_entry = max(self.current_boll_up,bar.close_price)
                self.buy(self.long_entry, self.fixed_size)

            elif self.entry_crossover < 0:
                self.short_entry = min(self.current_boll_down,bar.close_price)
                self.short(self.short_entry, self.fixed_size)

        elif self.pos > 0:

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

        elif self.pos < 0:
            self.short_stop = min(self.short_stop_trade, self.current_sma)
            self.cover(self.short_stop, abs(self.pos), True)

        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 == Direction.LONG:
            self.trade_price_long = trade.price  # 成交最高价
            self.long_stop_trade = self.trade_price_long - self.atr_multiple * self.atr_value

        else:
            self.trade_price_short = trade.price
            self.short_stop_trade = self.trade_price_short + self.atr_multiple * self.atr_value

        self.sync_data()
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        self.put_event()
        pass
Пример #18
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
Пример #19
0
class RsiAdaptStrategy(CtaTemplate):
    """
	策略逻辑:
	一、、过虑信号  (小时周期)
	使用rsiboll来判断信号强弱

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

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

	"""
    author = "yunya"

    min_window = 15
    open_window = 5
    rsi_length = 15
    boll_length = 80
    boll_dev = 2.0
    trading_size = 1

    rsi_value = 0
    rsi_up = 0
    rsi_dow = 0
    rsi_entry = 0
    boll_up = 0
    boll_down = 0
    boll_mid = 0
    boll_length_new = 0
    current_boll_mid = 0
    last_boll_mid = 0
    current_close = 0
    last_close = 0
    front_close = 0
    exit_long = 0
    exit_short = 0
    exit_long_nex = 0
    exit_long_last = 0
    exit_short_nex = 0
    exit_short_last = 0

    parameters = [
        "min_window",
        "open_window",
        "rsi_length",
        "boll_length",
        "boll_dev",
        "trading_size",
    ]

    variables = [
        "rsi_value",
        "rsi_up",
        "rsi_dow",
        "rsi_entry",
        "boll_up",
        "boll_down",
        "boll_mid",
        "boll_length_new",
        "current_boll_mid",
        "last_boll_mid",
        "current_close",
        "last_close",
        "front_close",
        "exit_long",
        "exit_short",
        "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.atr_stop_array = np.zeros(10)

        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.boll_length + 100)

        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(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_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

        if not self.pos:
            if self.rsi_entry > 0:
                self.buy(self.boll_up, self.trading_size, True)
            # print(bar.datetime, self.boll_up, self.trading_size)
            # print(bar.datetime, self.entry_up, self.trading_size, bar)

            elif self.rsi_entry < 0:
                self.short(self.boll_down, self.trading_size, True)

        elif self.pos > 0:
            # 仓位是long 时,如果价格下穿新布林中轨
            con1 = bar.close_price < self.current_boll_mid
            con2 = bar.close_price >= self.last_boll_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.boll_length_new = self.boll_length

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

                else:
                    # 收盘价在两条均线平均价上方,以当前收盘价挂出限价单
                    if bar.close_price > (
                        (self.boll_mid + self.current_boll_mid) / 2):
                        self.exit_long = bar.close_price

                    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
            self.sell(self.exit_long, abs(self.pos), True)

        elif self.pos < 0:
            # 仓位是short 时,如果价格上穿新布林中轨
            con1 = bar.close_price > self.current_boll_mid
            con2 = bar.close_price <= self.last_boll_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.boll_length_new = self.boll_length

                    self.exit_short = self.boll_mid

                else:
                    if bar.close_price < (self.boll_mid +
                                          self.current_boll_mid / 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), 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

        rsi_array = talib.RSI(self.am_xminute.close[:-1], self.rsi_length)
        ema_array = talib.EMA(self.am_xminute.close, self.rsi_length)

        dev_array = abs(self.am_xminute.close[:-1] -
                        ema_array[:-1]) / rsi_array

        rsi_up_array = rsi_array + rsi_array * dev_array
        rsi_dow_array = rsi_array - rsi_array * dev_array

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

        current_rsi_up = rsi_up_array[-1]
        current_rsi_down = rsi_dow_array[-1]

        if self.rsi_value > current_rsi_up:
            self.rsi_entry = 1
        elif self.rsi_value < current_rsi_down:
            self.rsi_entry = -1

        self.boll_up, self.boll_down = self.am_xminute.boll(
            self.boll_length, self.boll_dev)
        self.boll_mid = self.am_xminute.sma(self.boll_length)

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

        if self.pos == 0:
            self.exit_long_nex = 0
            self.exit_long_last = 0
            self.exit_short_nex = 0
            self.exit_short_last = 0
            self.boll_length_new = self.boll_length

        elif self.pos > 0:
            # 上涨或下跌时,布林中轨均值减1
            close_long = self.current_close > self.last_close > self.front_close
            if close_long:
                self.boll_length_new -= 1
                self.boll_length_new = max(self.boll_length_new, 5)

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

        boll_mid_new = self.am_xminute.sma(self.boll_length_new, True)
        self.current_boll_mid = boll_mid_new[-1]
        self.last_boll_mid = boll_mid_new[-2]

        self.sync_data()

    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()
Пример #20
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()
Пример #21
0
class Boll_Std_vix(CtaTemplate):
    """"""
    author = "yunya"

    win_open = 15
    boll_window = 80
    atr_window = 30
    sl_multiplier = 10.0
    fixed_size = 1

    entry_crossover = 0
    atr_value = 0
    intra_trade_high = 0
    intra_trade_low = 0
    long_stop = 0
    short_stop = 0

    parameters = [
        "win_open",
        "boll_window",
        "sl_multiplier",
        "fixed_size",
    ]

    variables = [
        "entry_crossover", "atr_value", "intra_trade_high", "intra_trade_low",
        "long_stop", "short_stop"
    ]

    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.win_open, self.on_xmin_bar)
        self.am = ArrayManager(self.boll_window + 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

        # Calculate array  计算数组
        self.sma_array = am.sma(self.boll_window, True)
        std_array = am.std(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 + std_array * dev_max
        self.boll_down_array = self.sma_array - std_array * dev_max

        # Get current and last index
        current_sma = self.sma_array[-1]
        last_sma = self.sma_array[-2]
        last_close = self.am.close[-2]
        currnet_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 (bar.close_price > currnet_boll_up and last_close <= last_boll_up):
            self.entry_crossover = 1

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

        self.atr_value = am.atr(self.atr_window)

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

            if self.entry_crossover > 0:
                self.buy(bar.close_price, self.fixed_size, True)

            elif self.entry_crossover < 0:
                self.short(bar.close_price, 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_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier
            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_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier
            self.cover(self.short_stop, abs(self.pos), True)

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

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        self.put_event()
        pass
class AtrStopRsiDcStrategy(CtaTemplate):
    """"""
    author = "yunya"

    hour_window = 1
    minute_window = 50
    open_window = 5
    rsi_length = 15
    distance_line = 2.0
    nloss_singnal = 3.1
    exit_dc_length = 30
    sl_multiplier = 8.0

    fixd_size = 1
    atr_window = 30

    exit_dowm = 0
    exit_up = 0
    atr_entry = 0
    rsi_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
    ask = 0
    bid = 0
    atr_value = 0

    parameters = [
        "hour_window", "minute_window", "open_window", "nloss_singnal",
        "rsi_length", "exit_dc_length", "sl_multiplier", "distance_line",
        "fixd_size", "atr_window"
    ]

    variables = [
        "current_atr_stop", "last_atr_stop", "long_stop", "short_stop",
        "atr_entry", "atr_value", "ask", "bid"
    ]

    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_xhour = NewBarGenerator(on_bar=self.on_bar,
                                        window=self.hour_window,
                                        on_window_bar=self.on_xhour_bar,
                                        interval=Interval.HOUR)
        self.am_hour = ArrayManager()

        self.bg_xminute = NewBarGenerator(on_bar=self.on_bar,
                                          window=self.minute_window,
                                          on_window_bar=self.on_xminute_bar)
        self.am_xminute = ArrayManager()

        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(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_open.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_xhour.update_bar(bar)
        self.bg_xminute.update_bar(bar)
        self.bg_open.update_bar(bar)

    def on_5min_bar(self, bar: BarData):

        self.cancel_all()
        self.am_open.update_bar(bar)

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

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

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

            up_limit = self.current_atr_stop * (1 + self.distance_line / 100)
            down_limit = self.current_atr_stop * (1 - self.distance_line / 100)

            if self.atr_entry > 0 and self.rsi_entry > 0 and bar.close_price < up_limit:

                self.buy(up_limit, self.fixd_size, True)

            elif self.atr_entry < 0 and self.rsi_entry < 0 and bar.close_price > down_limit:
                self.short(down_limit, self.fixd_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_stop_high = self.intra_trade_high - self.atr_value * self.sl_multiplier

            self.long_stop = max(self.exit_up, long_stop_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)
            short_stop_low = self.intra_trade_low + self.atr_value * self.sl_multiplier

            self.short_stop = min(self.exit_dowm, short_stop_low)
            self.cover(self.short_stop, abs(self.pos), True)

        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

        rsi_array = talib.RSI(self.am_xminute.close[:-1], self.rsi_length)
        ema_array = talib.EMA(self.am_xminute.close, self.rsi_length)

        dev_array = abs(self.am_xminute.close[:-1] -
                        ema_array[:-1]) / rsi_array

        rsi_up_array = rsi_array + rsi_array * dev_array
        rsi_dow_array = rsi_array - rsi_array * dev_array

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

        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]
        current_rsi_value = self.rsi_value[-1]
        last_rsi_value = self.rsi_value[-2]

        if (current_rsi_value > current_rsi_up) and (last_rsi_value <=
                                                     last_rsi_up):
            self.rsi_entry = 1
        elif (current_rsi_value < current_rsi_down) and (last_rsi_value >=
                                                         last_rsi_down):
            self.rsi_entry = -1
        else:
            self.rsi_entry = 0
        # print(self.rsi_entry)

        self.exit_dowm, self.exit_up = self.am_xminute.donchian(
            self.exit_dc_length)

    def on_xhour_bar(self, bar: BarData):
        """"""
        am_hour = self.am_hour
        am_hour.update_bar(bar)

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

        if not am_hour.inited:
            return

        # 计算轨道线 nloss
        self.ema_array = am_hour.ema(3, array=True)
        self.nloss_array = am_hour.atr(16, array=True) * self.nloss_singnal

        # 计算轨道线
        self.atr_stop_array = self.atrstop(am_hour.close, self.atr_stop_array,
                                           self.nloss_array)
        # print(self.atr_stop_array)
        # 初始化
        if self.atr_stop_array[-3] == 0:
            return

        self.current_atr_stop = self.atr_stop_array[-1]
        self.last_atr_stop = self.atr_stop_array[-2]
        current_ema = self.ema_array[-1]
        last_ema = self.ema_array[-2]

        if current_ema > self.current_atr_stop and last_ema <= self.last_atr_stop:
            self.atr_entry = 1
        elif current_ema < self.current_atr_stop and last_ema >= self.last_atr_stop:
            self.atr_entry = -1

        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