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

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

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

        return calc_data
Example #2
0
class AroonAtrStrategy(CtaTemplate):
    """"""

    author = "tonywang_efun"

    fixed_size = 1
    bar_window = 26
    boll_window = 39
    boll_dev = 1.9
    aroon_window = 14
    aroon_long = 50
    aroon_short = 50
    atr_window = 30
    atr_stop_multiplier = 3

    boll_up = 0
    boll_down = 0
    aroon_up = 0
    aroon_down = 0
    intra_trade_high = 0
    intra_trade_low = 0
    long_stop = 0
    short_stop = 0
    atr_value = 0

    parameters = [
        "fixed_size",
        "bar_window",
        "boll_window",
        "boll_dev",
        "aroon_window",
        "aroon_long",
        "aroon_short",
        "atr_window",
        "atr_stop_multiplier"
    ]

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

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

        self.bg = BarGenerator(self.on_bar, self.bar_window, self.on_xmin_bar)
        self.am = ArrayManager()

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

    def on_stop(self):
        """
        Callback when strategy is stopped.
        """
        self.write_log("策略停止")
    
    def on_tick(self, tick: TickData):
        """
        Callback of new tick data update.
        """
        self.bg.update_tick(tick)

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

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

        self.aroon_up, self.aroon_down = self.am.aroon(self.aroon_window)
        self.atr_value = self.am.atr(self.atr_window)
        self.boll_up, self.boll_down = self.am.boll(self.boll_window, self.boll_dev)

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

            if self.aroon_up > self.aroon_down and self.aroon_up > self.aroon_long:
                self.buy(self.boll_up, self.fixed_size, stop=True)

            if self.aroon_down > self.aroon_up and self.aroon_down > self.aroon_short:
                self.short(self.boll_down, self.fixed_size, stop=True)
        
        elif self.pos > 0:
            self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
            self.long_stop = self.intra_trade_high - self.atr_value * self.atr_stop_multiplier
            self.sell(self.long_stop, abs(self.pos), stop=True)
        
        else:
            self.intra_trade_low = min(self.intra_trade_low, bar.low_price)
            self.short_stop = self.intra_trade_low + self.atr_value * self.atr_stop_multiplier
            self.cover(self.short_stop, abs(self.pos), stop=True)
        
        self.put_event()

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        self.put_event()
    
    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        pass
    
    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
Example #3
0
    def generate_data(self, am: ArrayManager, bar: BarData):
        offset = -self.offset
        offset_m = int(offset / 2)

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

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

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

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

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

    # 唐奇安上下轨突破的周期,买入位置
    entry_window = 20
    # 唐奇安通道,卖出位置
    exit_window = 10
    atr_window = 20
    # 乘数,每次下单的单位大小
    fixed_size = 1

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

    # 多头入场价,每次交易后,设置为当前交易价格
    long_entry = 0
    short_entry = 0
    # 多头止损价格
    long_stop = 0
    short_stop = 0

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

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

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

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

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

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

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

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        # 取消之前未成交的单子
        self.cancel_all()

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

        # Only calculates new entry channel when no position holding
        # 没有持仓时才计算入场价
        if not self.pos:
            self.entry_up, self.entry_down = self.am.donchian(
                self.entry_window)

        self.exit_up, self.exit_down = self.am.donchian(self.exit_window)

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

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

            # 下本地止损单,等到突破或者跌破成交
            self.send_buy_orders(self.entry_up)
            self.send_short_orders(self.entry_down)
        elif self.pos > 0:
            # 如果之前有多头突破单成交,下单,根据atr加仓.
            # 不用考虑历史仓位,默认前面都是按照规则正确下单成交的仓位,不考虑未成交情况
            self.send_buy_orders(self.entry_up)

            # 止损价和止盈退出价中的大的一方
            sell_price = max(self.long_stop, self.exit_down)
            # 下多头止盈单
            self.sell(sell_price, abs(self.pos), True)

        elif self.pos < 0:
            # 如果之前有空仓,加仓
            self.send_short_orders(self.entry_down)

            cover_price = min(self.short_stop, self.exit_up)
            # 下空头止盈单
            self.cover(cover_price, abs(self.pos), True)

        self.put_event()

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        print(
            f"海龟交易,{trade.tradeid}, {trade.price}, {trade.direction}, {trade.time}"
        )
        if trade.direction == Direction.LONG:
            self.long_entry = trade.price
            # 修改多头止损价格
            self.long_stop = self.long_entry - 2 * self.atr_value
        else:
            self.short_entry = trade.price
            self.short_stop = self.short_entry + 2 * self.atr_value

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

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

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

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

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

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

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

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

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

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

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

        if t > -4:
            self.short(price - self.atr_value * 1.5, self.fixed_size, True)
Example #5
0
class CincoStrategyHN(CtaTemplate):
    """"""

    author = "Huang Ning"

    boll_window = 42
    boll_dev = 2.0
    trailing_long = 0.65
    trailing_short = 0.7
    atr_window = 10
    risk_level = 100

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

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

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

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

        self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar)
        self.am = ArrayManager()

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

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

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

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

    def on_bar(self, bar: BarData):
        """"""
        self.bg.update_bar(bar)

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

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

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

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

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

            self.buy(self.boll_up, self.trading_size, stop=True)
            self.short(self.boll_down, self.trading_size, stop=True)

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

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

        self.put_event()

    def on_order(self, order: OrderData):
        """"""

    def on_trade(self, trade: TradeData):
        """"""
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """"""
        self.put_event()
Example #6
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
Example #7
0
class PatternScoreStrategy(CtaTemplate):
    author = "用Python的交易员"

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

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

    score = Score()
    count = 0
    interval = 6

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

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

        self.open_strategy = [self.open_kline1]
        self.offset = 40
        self.min = 0
        self.max = 0

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

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

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

        self.put_event()

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

    def on_3min_bar(self, bar: BarData):
        self.am3.update_bar(bar)
        self.std_range3.update(self.am3.range[-1])
        if not self.am.inited or not self.trading:
            return
            # deg = calc_regress_deg(self.am3.close[-20:])

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

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

        return score

    def on_5min_bar(self, bar: BarData):

        self.std_range5.update(self.am5.range[-1])
        self.am5.update_bar(bar)
        if not self.am.inited or not self.trading:
            return
        diff_time = bar.datetime - self.am.time_array[-1]
        if diff_time.total_seconds() > 3600 or self.count > self.interval:
            self.count = 0
            self.score.base = calc_regress_deg(self.am.close[-self.interval:],
                                               False) * 1000
            print("score:", self.score.base, self.min, self.max)
        else:
            self.count += 1

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

        self.pattern_record.update()

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

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

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

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

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

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

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

        calc_data = (dict(kdj=[
            round(kdj_val["k"][-1], 2),
            round(kdj_val["d"][-1], 2),
            round(kdj_val["j"][-1], 2)
        ],
                          deg40_20=round(deg1, 2),
                          deg20=round(deg2, 2),
                          deg10=round(deg3, 2),
                          deg_f=round(deg_full, 2),
                          time=bar.datetime,
                          price=bar.close_price,
                          ma=round(ma, 2),
                          std_40=round(std_val, 2),
                          mean40=round(mean_val, 2),
                          std_10=round(std_val2, 2),
                          mean30_10=round(mean_val4, 2),
                          mean10=round(mean_val2, 2),
                          vol=self.am.volume[-1],
                          std_range=self.std_range.data[-1:-5:-1],
                          range=self.am.range[-1:-5:-1].tolist(),
                          range_sum=np.sum(self.am.range[-5:]),
                          atr=self.am.atr(10),
                          tr=self.am.atr(1, length=2),
                          pattern=list(
                              map(lambda x: KLINE_PATTERN_CHINESE[x],
                                  self.pattern_record.keys()))))

        return calc_data

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

        order_id = None

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

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

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

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg3.update_bar(bar)
        self.bg5.update_bar(bar)
        am = self.am
        self.am.update_bar(bar)
        max_len = self.ma_level[-1] + 20
        data = self.am.close[-max_len:-1]
        ma_lvl = []
        for i in self.ma_level:
            ma = self.am.sma(i, True)[-1]
            ma_lvl.append(ma)

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

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

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

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

        self.put_event()

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

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

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

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

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

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

    fixed_size = 1

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

    long_order_record = []
    short_order_record = []

    rsi_value_l_window = -9999
    rsi_value_s_window = -9999
    atr_value = 0

    position_hold = 0
    long_entered = False
    short_entered = False

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

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

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

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

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

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

        self.atr_profit_exit_recorder = []

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        # 通过设置合成Bar Data的周期可以使得持仓过夜
        elif bar.datetime.time() > self.exit_time:
            if self.pos > 0:
                self.sell(bar.close_price * 0.99, abs(self.pos))
            elif self.pos < 0:
                self.cover(bar.close_price * 1.01, abs(self.pos))

        self.put_event()

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

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

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

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
Example #9
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
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()
Example #11
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
Example #12
0
class TurtleEStrategy(CtaTemplate):
    """"""
    # 改版海龟信号-吊灯止损法出场
    author = "turtle_entry_following_stop"

    entry_window = 50
    exit_window = 20
    atr_window = 20
    # stop_multiple = 10
    fixed_size = 1

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

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

    sl_multiplier = 3
    intra_trade_high = 0
    intra_trade_low = 0
    long_stop = 0
    short_stop = 0

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

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

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

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

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

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

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

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

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

        # Only calculates new entry channel when no position holding

        if not self.pos:
            self.entry_up, self.entry_down = self.am.donchian(
                self.entry_window)
            self.atr_value = self.am.atr(self.atr_window)
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = bar.low_price

            self.send_buy_orders(self.entry_up)
            self.send_short_orders(self.entry_down)
        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_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.stop_multiple * self.atr_value
        # else:
        #     self.short_entry = trade.price
        #     self.short_stop = self.short_entry + self.stop_multiple * self.atr_value

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

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

    def send_buy_orders(self, price):
        """"""
        self.buy(price, self.fixed_size, True)

    def send_short_orders(self, price):
        """"""
        self.short(price, self.fixed_size, True)
Example #13
0
class LifeHunterStrategy(CtaTemplate):
    """"""
    author = "super dino"

    entry_window = 28
    exit_window = 7
    fast_period = 12
    slow_period = 26
    signal_period = 9
    trend_level = 10
    atr_window = 4
    risk_level = 0.2
    trailing_tax = 0.3

    trading_size = 0
    entry_up = 0
    entry_down = 0
    exit_up = 0
    exit_down = 0
    atr_value = 0
    MACD_sign = 0
    signal = 0
    hist = 0
    MACD_trend = 0
    long_entry = 0
    short_entry = 0
    long_stop = 0
    short_stop = 0
    intra_trade_high = 0
    intra_trade_low = 0
    long_out = 0
    short_out = 0

    parameters = [
        "entry_window", "exit_window", "fast_period", "slow_period",
        "signal_period", "trend_level", "atr_window", "risk_level",
        "trailing_tax"
    ]
    variables = [
        "trading_size", "entry_up", "entry_down", "exit_up", "exit_down",
        "atr_value", "MACD_sign", "signal", "hist", "MACD_trend", "long_entry",
        "short_entry", "long_stop", "short_stop", "intra_trade_high",
        "intra_trade_low", "long_out", "short_out"
    ]

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

        self.bg = BarGenerator(self.on_bar, 30, self.on_30min_bar)

        self.am = ArrayManager()
        self.am30 = ArrayManager()

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

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

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

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

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

        self.cancel_all()

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

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

            if self.atr_value == 0:
                return

            atr_risk = talib.ATR(1 / self.am.high, 1 / self.am.low,
                                 1 / self.am.close, self.atr_window)[-1]
            self.trading_size = max(int(self.risk_level / atr_risk), 1)

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

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

            if self.MACD_trend < 0:
                self.short(self.entry_down, self.trading_size, True)

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

        elif self.pos < 0:
            self.intra_trade_low = min(self.intra_trade_low, bar.low_price)
            self.short_out = self.intra_trade_low * \
                (1 + self.trailing_tax / 100)
            cover_price = min(self.short_stop, self.exit_up, self.short_out)
            self.cover(cover_price, abs(self.pos), True)

        if bar.datetime.day == 21:
            print(bar.datetime, self.entry_up, bar.open_price, bar.high_price,
                  bar.low_price, bar.close_price)

        self.put_event()

    def on_30min_bar(self, bar: BarData):
        """"""
        self.am30.update_bar(bar)
        if not self.am30.inited:
            return

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

        if bar.datetime.day == 21:
            print("on 30 min", bar.datetime, self.entry_up)
        self.MACD_sign, self.signal, self.hist = self.am30.macd(
            self.fast_period, self.slow_period, self.signal_period)
        self.MACD_sign = self.signal - self.hist

        if self.MACD_sign > self.trend_level:
            self.MACD_trend = 1
        elif self.MACD_sign < (-self.trend_level):
            self.MACD_trend = -1
        else:
            self.MACD_trend = 0

        self.put_event()

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

        if trade.direction == Direction.LONG:
            self.long_entry = trade.price
            self.long_stop = self.long_entry - 2 * self.atr_value
        else:
            self.short_entry = trade.price
            self.short_stop = self.short_entry + 2 * self.atr_value

        msg = f"新的成交,策略是{self.strategy_name},方向{trade.direction},开平{trade.offset},当前仓位{self.pos}"
        self.send_email(msg)

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

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
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
Example #15
0
class CtaTemplate_6(CtaTemplate_5):
    """
    add bar manager
    """

    className = 'CtaTemplate_6'
    author = u'rxg'

    # 基本变量
    initDays = 20  # 初始化数据所用的天数
    kLineCycle = 6  #Bar line cycle
    KLineSeconds = 60  #生成X秒的K线
    marketTradeValue = 0  #策略的交易市值
    arraySize = 100

    parameters = CtaTemplate_5.parameters + \
                [
                 'className',
                 'author',
                 'kLineCycle',
                 'initDays',
                 'debugMode',
                 'KLineSeconds',
                 'arraySize'
                 ]

    varList = CtaTemplate_5.variables + \
                [
                ]

    #----------------------------------------------------------------------
    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)
        print("-----")
        print(self.kLineCycle)
        self.bm = BarGenerator(self.on_bar, self.kLineCycle,
                               self.onXminBar)  # 创建K线合成器对象

        self.bm.xsec = self.KLineSeconds  #按指定X秒生成K线

        self.am = ArrayManager(size=self.arraySize)
        # self.am = getSharedArrayManager(self.vt_symbol, self.kLineCycle,
        #                                 self.KLineSeconds, self.arraySize)

        self.bm60 = BarGenerator(self.on_bar, 60, self.on60MinBar)
        self.am60 = ArrayManager(size=100)
        # self.am60 = getSharedArrayManager(self.vt_symbol, 60,
        #                                 self.KLineSeconds, 100)

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

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

        if hasattr(self, 'signal'):
            if hasattr(self.signal, 'am'):
                if not self.signal.am.inited:
                    self.write_log(u'%s策略信号加载初始数据不足' % self.strategy_name)
                    print(u'%s策略信号加载初始数据不足 ' % self.strategy_name,
                          self.initDays)

        if not self.am.inited:
            print(u'%s策略加载初始数据不足 ' % self.strategy_name, self.kLineCycle,
                  self.initDays)

        if not self.am60.inited:
            print(u'%s策略加载60 Min Bar 初始数据不足  ' % self.strategy_name,
                  self.initDays)

        self.put_event()

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

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

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

    #----------------------------------------------------------------------
    def on_bar(self, bar: BarData):
        '''处理分钟数据'''
        super(CtaTemplate_6, self).on_bar(bar)
        self.bm.update_bar(bar)
        self.bm60.update_bar(bar)

    #----------------------------------------------------------------------
    def onXminBar(self, bar):
        """收到X分钟K线"""
        # 保存K线数据
        am = self.am
        am.update_bar(bar)
        if not am.inited:
            return

    def on60MinBar(self, bar):
        """收到X分钟K线"""
        self.am60.update_bar(bar)
        if not self.am60.inited:
            return

    #----------------------------------------------------------------------
    def getVolatility(self, volatilityTime=60):
        """收到X分钟K线"""
        # 保存K线数据
        return (self.am.atr(50) / self.lastPrice) * (
            (volatilityTime / self.kLineCycle)**0.5)
Example #16
0
class MaLevelTrackStrategy(CtaTemplate):
    author = "用Python的交易员"

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

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

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

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

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

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

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

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

        self.put_event()

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

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

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

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

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

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

        while pos < l:

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

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

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

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

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

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

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

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

    #     self.pattern_record.update()

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

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

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

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

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

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

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

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

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

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

        atr = self.am.atr(40)

        if atr < 0.08:
            return

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

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

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

        if mid_pos < 10 or mid_pos > 30:
            return

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

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

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

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

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

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

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

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

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

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

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

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

        return calc_data

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

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

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

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

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

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

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

        ma120 = self.am.sma(120)

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

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

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

        self.put_event()

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

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

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

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

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

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
Example #17
0
class TurtleSignalStrategy(CtaTemplate):
    """"""

    author = "用Python的交易员"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        self.put_event()

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

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

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

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

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

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

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

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

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

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

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

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

        if t > -4:
            self.short(price - self.atr_value * 1.5, self.fixed_size, True)
Example #18
0
class Mike_Dc_Strategy(CtaTemplate):
    """"""

    author = "yunya"

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

    ask = 0
    bid = 0

    ema_mid = 0
    ema_hh = 0
    ema_ll = 0

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        elif self.pos > 0:

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

        elif self.pos < 0:

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

        self.sync_data()
        self.put_event()

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

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

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

        self.put_event()

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

    def exchange_load_bar(self,exchange:Exchange):
        """
        如果是火币,ok 交易所,就从数据库获取初始化数据
        """
        if exchange == Exchange.OKEX or exchange == Exchange.HUOBI:
            self.load_bar(days=10,use_database=True)
        else:
            self.load_bar(10)
class ReverseCatchStrategy(CtaTemplate):
    author = "用Python的交易员"

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

    slow_ma0 = 0.0
    slow_ma1 = 0.0
    request_order = []
    bar_identify = []
    volumn = 0
    kdj_record = []
    parameters = ["ma_level"]
    variables = ["fast_ma0", "fast_ma1", "slow_ma0", "slow_ma1"]
    add_pos = False
    safe_price = None
    trend_record = MaTrendRecord

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super(ReverseCatchStrategy, self).__init__(
            cta_engine, strategy_name, vt_symbol, setting
        )
        self.bg = BarGenerator(self.on_bar, 1, self.on_1min_bar)
        self.am = ArrayManager(200)
        self.am3 = ArrayManager(150)
        self.bg3 = BarGenerator(self.on_bar, 3, self.on_3min_bar)
        self.am5 = ArrayManager(120)
        self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar)
        self.order_data = None
        self.positions = CloseoutPosition(self, {"closeout_offset": 0.003})
        self.std_range = IntervalGen(np.std,5)
        self.std_range3 = IntervalGen(np.std,5)        
        self.std_range5 = IntervalGen(np.std,5)
        self.pattern_record = PatternRecord()
        # self.pattern_record.set_expiry([KlinePattern.CDLEVENINGSTAR], 3)
        self.pattern_record.set_expiry(list(KlinePattern), 1)
        self.ma_info = []
        
        five_min_open_5 = partial(self.reverse_shape_strategy, setting={"len":20, "atr":10, "atr_valve":0.8, "mid_sign":(7,14)})
        self.open_strategy = {
            "1":[five_min_open_5],
        }
        self.offset = 40
        self.ma120_track = None
        self.ma120_track_list = []
    def on_init(self):
        """
        Callback when strategy is inited.
        """
        self.write_log("策略初始化")
        self.load_bar(5)

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

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

        self.put_event()

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

    def on_3min_bar(self, bar: BarData):
        self.am3.update_bar(bar)
        self.std_range3.update(self.am3.range[-1])
        if not self.am.inited or not self.trading:
            return   
        pattern = self.am3.pattern([KlinePattern.CDLEVENINGSTAR, KlinePattern.CDL2CROWS])
        
        if len(pattern) > 0:
            print(pattern)
            self.pattern_record.add_pattern(pattern)
            # deg = calc_regress_deg(self.am3.close[-20:])
    
    def wave(self, data, window = 0.0002):

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

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

            while pos < l:

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

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

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

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

    def on_5min_bar(self, bar: BarData):
        self.std_range5.update(self.am5.range[-1])
        self.am5.update_bar(bar)
        if not self.am.inited or not self.trading:
            return   
        
        # self.on_strategy(self.am5, bar, self.open_strategy["5"])
        # pattern_list = [KlinePattern.CDLEVENINGSTAR, KlinePattern.CDL2CROWS, KlinePattern.CDLCONCEALBABYSWALL, KlinePattern.CDLEVENINGDOJISTAR]
    #     pattern = self.am5.pattern(list(KlinePattern))
    #     if len(pattern) > 0:
    #         print(list(map(lambda x: (KLINE_PATTERN_CHINESE[x[0]],x[1]), pattern)))
    #         self.pattern_record.add_pattern(pattern)
    #         deg_full = calc_regress_deg(self.am.close[-40 :], False)
    #         print("deg:",deg_full)
        
    #     self.pattern_record.update()

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

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

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

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

    def ma_trend_strategy(self, am:ArrayManager, bar:BarData, calc_data, setting={"len":40, "atr":40, "atr_valve":0.09, "mid_sign":(10,30)}):
        
        # 60个bar后取消
        if self.trend_record.std_val is not None:
            if len(self.trend_record.close) >= 60:
                self.trend_record.close = []
                self.trend_record.std_val = None
            else:
                self.trend_record.close.append(bar.close_price)
            
            
        # 如果有新的bar,则覆盖
        ma5_std = self.ma_info[-1]["ma5"]
        if ma5_std <= 0.16:
            self.trend_record.close = []
            self.trend_record.std_val = ma5_std
            return
        

        if  self.trend_record.std_val is not None and \
            ma5_std > 0.8:
            y_fit = reg_util.regress_y_polynomial(self.trend_record.close, zoom=True)
            deg = calc_regress_deg(y_fit[:10], False)

            if deg < 0:
                # if k < 20 and d < 10 and j < 10:
                # if kdj[2] < 10:
                if self.pos == 0:
                    calc_data["trade_open"] = "开空,deg={}".format(deg)
                    return self.short(bar.close_price, 1, type=OrderType.MARKET)

            else:
                # if k > 80 and d > 90 and j > 90:
                # if kdj[2] > 90:
                if self.pos == 0:
                    calc_data["trade_open"] = "开多,deg={}".format(deg)
                    return self.buy(bar.close_price, 1, type=OrderType.MARKET)




    # v形反转捕获
    def reverse_shape_strategy(self, am:ArrayManager, bar:BarData, calc_data, setting={"len":40, "atr":40, "atr_valve":0.09, "mid_sign":(10,30)}):
        length = setting["len"]
        offset1 = int(-length)
        offset2 = int(-(length / 2))
        close = am.close
        deg1 = calc_regress_deg(close[offset1:offset2], False)
        deg2 = calc_regress_deg(close[offset2:], False)
        

        atr = self.am.atr(setting["atr"])
        atr_valve = setting["atr_valve"]
        if atr < atr_valve:
            return

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

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

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

        start_val = np.min(close[:mid_pos]) if deg1 > 0 else np.max(close[:mid_pos])
        start_pos = np.where(close == start_val)[0][0]
        l = mid_pos - start_pos
        
        # pos2 = np.where(close == min_val)[0][0]
        kdj = am.kdj()
        k = kdj["k"][-1]
        d = kdj["d"][-1]
        j = kdj["j"][-1]
        x_fit = reg_util.regress_y_polynomial(close[:mid_pos], zoom=True)
        deg1_remake = calc_regress_deg(x_fit[:abs(mid_pos)], False)
        y_fit = reg_util.regress_y_polynomial(close[mid_pos:], zoom=True)
        deg2_remake = calc_regress_deg(y_fit[:abs(mid_pos)], False)
        # print(start_pos, mid_pos, deg1, deg2, deg1_remake, deg2_remake, l, start_val, mid_val)
        cci = am.cci(20)
        ma60 = am.sma(60)
        if deg2 < 0:
            # if k < 20 and d < 10 and j < 10:
            # if kdj[2] < 10:
            
            if cci < -100 and bar.close_price < ma60:
                if self.pos == 0:
                   calc_data["trade_open"] = "开空,deg={},cci={}".format(deg2, cci)
                   return self.short(bar.close_price, 1, type=OrderType.MARKET)
                elif self.pos > 0:
                   order_id_cover = self.sell(bar.close_price, abs(self.volumn), type=OrderType.MARKET)
                   order_id_buy = self.short(bar.close_price, 1, type=OrderType.MARKET)
                   return order_id_cover.extend(order_id_buy)
        else:
            # if k > 80 and d > 90 and j > 90:
            # if kdj[2] > 90:
            if cci > 100 and bar.close_price > ma60:
                
                if self.pos == 0:
                    calc_data["trade_open"] = "开多,deg={},cci={}".format(deg2, cci)
                    return self.buy(bar.close_price, 1, type=OrderType.MARKET)
                elif self.pos < 0:
                    order_id_cover = self.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET)
                    order_id_buy = self.buy(bar.close_price, 1, type=OrderType.MARKET)
                    return order_id_cover.extend(order_id_buy)

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

    def ma120_close(self, am:ArrayManager, bar:BarData, calc_data):
        
        if self.safe_price is None:
            return

        rg = (bar.close_price / self.buy_price) - 1

        close_price = None
        if rg > 0.01 and self.volumn > 0:
            close_price = am.sma(120)
        elif rg < -0.01 and self.volumn < 0:
            close_price = am.sma(120)
            

        for lvl in self.ma_lvl[-1:]:
            # if len(self.order_data) < lvl:
            close_price = am.sma(lvl)
            break
        

        if close_price is None:
            lvl = self.ma_level[-1]
            close_price = am.sma(lvl)

        
        
        if self.volumn < 0:
            if bar.close_price > close_price:
                calc_data["trade_close"] = "平仓:到达MA均线价{}".format(close_price)
                return self.strategy.cover(bar.close_price, abs(self.volumn), type=OrderType.MARKET,
                       extra= { "reason":"平仓:到达MA均线价{}".format(close_price)})
                 
        elif self.volumn > 0:
            if bar.close_price < close_price:
                calc_data["trade_close"] = "平仓:到达MA均线价{}".format(close_price)
                return self.strategy.sell(bar.close_price, abs(self.volumn), type=OrderType.MARKET,
                       extra={"reason": "平仓:到达MA均线价{}".format(close_price)})


    
    def add_position(self, am:ArrayManager, bar:BarData, calc_data, setting={}):

        if self.safe_price is None:
            return

        if not (self.volumn < 0 and bar.close_price < self.safe_price or \
                self.volumn > 0 and bar.close_price > self.safe_price):
            return

        am = self.am
        rg = (bar.close_price / self.trade_price) - 1

        close_price = None
        if rg > 0.01 and self.volumn > 0:
            close_price = am.sma(120)
            if not self.add_pos:
                self.add_pos = True
                return self.strategy.buy(bar.close_price, 50, type=OrderType.MARKET) 
        elif rg < -0.01 and self.volumn < 0:
            close_price = am.sma(120)
            if not self.add_pos:
                self.add_pos = True
                return self.strategy.short(bar.close_price, 50, type=OrderType.MARKET) 

    def reverse2_strategy(self, am:ArrayManager, bar:BarData, calc_data, setting={"len":40, "atr":40, "atr_valve":0.09, "mid_sign":(10,30)}):
        length = 30
        offset1 = -30
        offset2 = int(-10)
        close = am.close
        deg1 = calc_regress_deg(close[-30:-8], False)
        deg2 = calc_regress_deg(close[-8:], False)
        

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

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

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

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

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



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

    def open_kline1(self, am:ArrayManager, bar:BarData, calc_data):
        
        if KlinePattern.CDLEVENINGSTAR not in self.pattern_record:
            return
        # if std_val2 < 0.2: 
        deg = calc_regress_deg(self.am.close[-5:], False)
        print("kline_strategy",deg)
        if deg < -0.1:
            return self.short(bar.close_price, 1, type=OrderType.MARKET)
       
    def generate_data(self, am:ArrayManager, bar:BarData):
        offset = -self.offset
        offset_m = int(offset / 2)
        calc_nums = np.array(self.ma_tag[-offset:-1])
        # var_val = np.var(calc_nums)
        std_val = np.std(calc_nums)
        std_val2 = np.std(np.array(self.ma_tag[-10:-1]))
        std_val3 = np.std(np.array(am.range[-30:-10]))
        ma = self.ma_tag[-1]
        
        mean_val = np.mean(calc_nums)
        mean_val2 = np.mean(np.array(self.ma_tag[-5:-1]))
        mean_val3 = np.mean(np.array(self.ma_tag[-20:-1]))
        mean_val4 = np.mean(np.array(self.ma_tag[-30:-5]))
        
        kdj_val = am.kdj()
        has_kdj_recore = False
        k = kdj_val["k"]
        d = kdj_val["d"]
        j = kdj_val["j"]
        if  (k[-1] > 75 and d[-1] > 75 and j[-1] > 75) or \
            (k[-1] < 25 and d[-1] < 25 and j[-1] < 75):
            if (j[-2] < k[-2] or j[-2] < d[-2]) and (j[-1] > k[-1] and j[-1] > d[-1]) \
                or \
            (j[-2] > k[-2] or j[-2] > d[-2]) and (j[-1] < k[-1] and j[-1] < d[-1]):
                has_kdj_recore = True
                t = local_to_eastern(bar.datetime.timestamp())
                self.kdj_record.append((t.strftime("%H:%M:%S"), round(k[-1], 3), round(d[-1], 3), round(j[-1], 3)))

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

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


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

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

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

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

        return calc_data

    def on_strategy(self, am:ArrayManager, bar: BarData, strategy_list, close_strategy_list, calc_data=None):
        
            
        order_id = None

        for open_strategy in strategy_list:
            if order_id is not None:
                break
            order_id = open_strategy(am, bar, calc_data)

        if order_id is None and self.pos != 0:
            for strategy in close_strategy_list:
                if order_id is not None:
                    break
                order_id = strategy(am, bar, calc_data)

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

    def ma_info_update(self, am:ArrayManager):
        
        ma_info = {}
        ma_data = []
        for i in self.ma_level:
            ma = am.sma(i)
            ma_info[i] = round(ma,2)
            ma_data.append(ma)
        
        data = []
        diff = ma_data[-1]
        for v in ma_data:
            data.append(round(v / diff, 6))

        ma_info["ma5"] = round(np.var(data)*1000000, 8)

        data = []
        diff = ma_data[-3]
        for v in ma_data[:-2]:
            data.append(round(v / diff, 6))

        ma_info["ma3"] = round(np.var(data)*1000000, 8)

        if len(self.ma_info) < 500:
            self.ma_info.append(ma_info)
        else:
            self.ma_info[:-1] = self.ma_info[1:]
            self.ma_info[-1] = ma_info

    
    def on_1min_bar(self, bar: BarData):
        self.am.update_bar(bar)
        am = self.am
        

        max_len = self.ma_level[-1] + 20
        data = self.am.close[-max_len:-1]
        ma_lvl = []
        for i in self.ma_level:
            ma = self.am.sma(i, True)[-1]
            ma_lvl.append(ma)
        
        
        l = len(ma_lvl)
        ma_lvl_tag = []
        now = bar.close_price
        direction = 1 if now > ma_lvl[0] else 0
        ma_lvl_tag.append(direction)
        for i in range(l-1):
            val = 1 if ma_lvl[i] > ma_lvl[i+1] else 0
            ma_lvl_tag.append(val)
        bincount_val = np.bincount(np.array(ma_lvl_tag))
        tag_val = 0
        if len(bincount_val) == 2:
            tag_val = bincount_val[1]

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

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



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

        self.ma_info_update(am)
        calc_data = self.generate_data(am, bar)
        five_min_open_5 = partial(self.reverse_shape_strategy, setting={"len":20, "atr":10, "atr_valve":0.8, "mid_sign":(7,14)})
        open_strategy = [self.reverse_shape_strategy, self.add_position]
        close_strategy = [self.positions.on_bar, self.ma120_close]
        self.on_strategy(am, bar, open_strategy, close_strategy, calc_data)
            # median_val = np.median(calc_nums)
        
        self.put_event()

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

        

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

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


    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        if trade.vt_orderid in self.request_order:
            self.positions.on_trade(trade)
            if self.volumn == 0:
                self.add_pos = False
                
                if trade.direction == Direction.LONG:
                    self.safe_price = trade.price * 1.003
                    self.volumn += trade.volume
                elif trade.direction == Direction.SHORT:
                    self.safe_price = trade.price * 0.997
                    self.volumn -= trade.volume
        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
Example #20
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
    def generate_data(self, am:ArrayManager, bar:BarData):
        offset = -self.offset
        offset_m = int(offset / 2)
        calc_nums = np.array(self.ma_tag[-offset:-1])
        # var_val = np.var(calc_nums)
        std_val = np.std(calc_nums)
        std_val2 = np.std(np.array(self.ma_tag[-10:-1]))
        std_val3 = np.std(np.array(am.range[-30:-10]))
        ma = self.ma_tag[-1]
        
        mean_val = np.mean(calc_nums)
        mean_val2 = np.mean(np.array(self.ma_tag[-5:-1]))
        mean_val3 = np.mean(np.array(self.ma_tag[-20:-1]))
        mean_val4 = np.mean(np.array(self.ma_tag[-30:-5]))
        
        kdj_val = am.kdj()
        has_kdj_recore = False
        k = kdj_val["k"]
        d = kdj_val["d"]
        j = kdj_val["j"]
        if  (k[-1] > 75 and d[-1] > 75 and j[-1] > 75) or \
            (k[-1] < 25 and d[-1] < 25 and j[-1] < 75):
            if (j[-2] < k[-2] or j[-2] < d[-2]) and (j[-1] > k[-1] and j[-1] > d[-1]) \
                or \
            (j[-2] > k[-2] or j[-2] > d[-2]) and (j[-1] < k[-1] and j[-1] < d[-1]):
                has_kdj_recore = True
                t = local_to_eastern(bar.datetime.timestamp())
                self.kdj_record.append((t.strftime("%H:%M:%S"), round(k[-1], 3), round(d[-1], 3), round(j[-1], 3)))

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

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


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

    entry_window = 28
    exit_window = 7
    atr_window = 4
    risk_level = 0.2

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

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

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

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

        self.bg = BarGenerator(self.on_bar,
                               1,
                               self.on_hour_bar,
                               interval=Interval.HOUR)
        self.am = ArrayManager()

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

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

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

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

    def on_bar(self, bar: BarData):
        """"""
        self.bg.update_bar(bar)

    def on_hour_bar(self, bar: BarData):
        """"""

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

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

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

            if self.atr_value == 0:
                return

            atr_risk = talib.ATR(1 / self.am.high, 1 / self.am.low,
                                 1 / self.am.close, self.atr_window)[-1]
            self.trading_size = max(int(self.risk_level / atr_risk), 1)

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

            self.buy(self.entry_up, self.trading_size, True)
            self.short(self.entry_down, self.trading_size, True)

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

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

        self.put_event()

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

        self.sync_data()

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

    def on_stop_order(self, stop_order: StopOrder):
        """
        Callback of stop order update.
        """
        pass
Example #23
0
class TurtleFluidSizeStrategy(CtaTemplate):
    """"""
    # 改版海龟信号-ma出场-rsi过滤-atr浮动手数
    author = "turtle_fluid_size"

    entry_window = 50
    exit_window = 20
    atr_window = 20
    stop_multiple = 10
    long_rsi = 50
    short_rsi = 50
    fixed_size = 1

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

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

    fluid_size = 1
    symbol_size = 1
    risk_percent = 0.002
    risk_capital = 1000000

    parameters = [
        "entry_window", "exit_window", "atr_window", "fixed_size",
        "stop_multiple", "long_rsi", "short_rsi", "symbol_size",
        "risk_percent", "risk_capital"
    ]
    variables = [
        "entry_up", "entry_down", "exit_up", "exit_down", "atr_value",
        "fluid_size"
    ]

    def __init__(self, cta_engine, strategy_name, vt_symbol, setting):
        """"""
        super().__init__(cta_engine, strategy_name, vt_symbol, setting)
        print(self.symbol_size, self.risk_percent, self.risk_capital)

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

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

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

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

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

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

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

        # Only calculates new entry channel when no position holding
        if not self.pos:
            self.entry_up, self.entry_down = self.am.donchian(
                self.entry_window)

        self.exit_up = self.exit_down = self.am.sma(self.exit_window)
        self.rsi_value = self.am.rsi(self.entry_window)

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

            risk_amount = self.risk_capital * self.risk_percent
            atr_amount = self.atr_value * self.symbol_size
            self.fluid_size = round(risk_amount / atr_amount) * self.fixed_size

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

            if self.fluid_size and self.rsi_value > self.long_rsi:
                self.send_buy_orders(self.entry_up)
            if self.fluid_size and self.rsi_value <= self.short_rsi:
                self.send_short_orders(self.entry_down)
        elif self.pos > 0:
            sell_price = max(self.long_stop, self.exit_down)
            self.sell(sell_price, abs(self.pos), True)
        elif self.pos < 0:
            cover_price = min(self.short_stop, self.exit_up)
            self.cover(cover_price, abs(self.pos), True)

        self.put_event()

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

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

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

    def send_buy_orders(self, price):
        """"""
        self.buy(price, self.fluid_size, True)

    def send_short_orders(self, price):
        """"""
        self.short(price, self.fluid_size, True)
class Boll_Kc_Dc_Reverse_Strategy(CtaTemplate):
    """
    本策略为反向策略,币本位  Reverse 反向
    """

    author = "yunya"
    open_window = 2
    xsmall_window = 15
    com_length = 250
    boll_kk_dev = 2.0
    kk_atr_length = 30
    sl_multiplier = 0.5
    risk_level = 10000

    trading_size = 0
    xsmall_up_min = 0
    xsmall_down_min = 0
    xsmall_up_max = 0
    xsmall_down_max = 0
    xsmall_ema_mid = 0
    xsmall_com_width = 0
    long_entry = 0
    short_entry = 0
    long_stop = 0
    short_stop = 0
    exit_up = 0
    exit_down = 0
    atr_value = 0

    intra_trade_high = 0
    intra_trade_low = 0

    parameters = [
        "open_window",
        "xsmall_window",
        "com_length",
        "boll_kk_dev",
        "kk_atr_length",
        "sl_multiplier",
        "risk_level",
    ]
    variables = [
            "trading_size",
            "xsmall_up_min",
            "xsmall_down_min",
            "xsmall_up_max",
            "xsmall_down_max",
            "xsmall_ema_mid",
            "xsmall_com_width",
            "long_entry",
            "short_entry",
            "long_stop",
            "short_stop",
            "exit_up",
            "exit_down",
            "atr_value",
    ]

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

        self.bg_xsmall = BarGenerator(
            on_bar=self.on_bar,
            window=self.xsmall_window,
            on_window_bar=self.on_xsmall_bar,
            interval=Interval.MINUTE
        )
        self.am_xsmall = ArrayManager(self.com_length + 10)
        self.bg = BarGenerator(self.on_bar, self.open_window, self.on_open_bar)
        self.am = ArrayManager()

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

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

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

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

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        self.bg.update_bar(bar)
        self.bg_xsmall.update_bar(bar)
  
    def on_open_bar(self,bar:BarData):
        """
        :param bar:
        :return:
        """
        # 先使用挂单全撤的粗化订单管理
        self.cancel_all()

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

        if self.pos == 0:
            # 根据布林带宽度动态调整仓位大小
            self.trading_size = max(int(self.risk_level / self.xsmall_com_width), 1)
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = bar.low_price

            # 如果价格突破 xsmall_up_min 线时,在xsmall_up_max 价格挂停止单
            if self.am_xsmall.close[-1] >= self.xsmall_up_min and self.am.close[-1] >=self.xsmall_up_min:
                self.buy(self.xsmall_up_max,self.trading_size,True)

            # 如果价格突破 xsmall_down_min 线时,在xsmall_down_max 价格挂停止单
            elif self.am_xsmall.close[-1] <= self.xsmall_down_min and self.am.close[-1] <= self.xsmall_down_min:
                self.short(self.xsmall_down_max,self.trading_size,True)

        elif self.pos > 0:
            # 成交价固定止损位与中轨中最大值为当前止损位
            # self.exit_up = max(self.xsmall_ema_mid,self.long_stop)

            # 成交价回定止损 与最高价回撤一定比例通道宽度值
            self.intra_trade_high = max(self.intra_trade_high,bar.high_price)
            self.intra_trade_low = bar.low_price

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

        elif self.pos < 0:
            # 成交价固定止损位与中轨中最小值为当前止损位
            # self.exit_down = min(self.xsmall_ema_mid,self.short_stop)

            # 成交价回定止损 与最高价回撤一定比例通道宽度值
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = min(self.intra_trade_low,bar.low_price)

            exit_short_stop = self.intra_trade_low - self.xsmall_com_width * self.sl_multiplier
            self.exit_down = min(exit_short_stop,self.short_stop)
            self.cover(self.exit_down,abs(self.pos),True)

        self.sync_data()
        self.put_event()

    def on_xsmall_bar(self, bar: BarData):
        """
        :param bar:
        :return:
        """
        # x分钟 多策略合合成的通道线
        self.am_xsmall.update_bar(bar)
        if not self.am_xsmall.inited :
            return

        self.xsmall_ema_mid,self.xsmall_com_width,self.xsmall_up_min, self.xsmall_down_min,\
        self.xsmall_up_max, self.xsmall_down_max = self.boll_kc_dc_combination(
                                                                        high=self.am_xsmall.high[:-1],
                                                                        low=self.am_xsmall.low[:-1],
                                                                        close=self.am_xsmall.close[:-1],
                                                                        boll_kk_dev=self.boll_kk_dev,
                                                                        kk_atr_length=self.kk_atr_length,
                                                                        com_length=self.com_length
                                                                        )

        # print(f"xsmall: mid:{self.xsmall_ema_mid},width:{self.xsmall_com_width},upmin:{self.xsmall_up_min},\
        #         downmin:{self.xsmall_down_min},upmax:{self.xsmall_up_max},downmax:{self.xsmall_down_max}" + "\n")

        self.atr_value = self.am_xsmall.atr(self.kk_atr_length)

        self.sync_data()
        self.put_event()


    def on_order(self, order: OrderData):
        """
        Callback of new order data update.
        """
        pass
    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        if trade.direction == Direction.LONG:
            self.long_entry = trade.price  # 成交最高价
            self.long_stop = self.long_entry - 2 * self.atr_value
        else:
            self.short_entry = trade.price
            self.short_stop = self.short_entry + 2 * self.atr_value

        self.sync_data()

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

    def boll_kc_dc_combination(self, high, close, low, boll_kk_dev,kk_atr_length,com_length):

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

        # 计算布林带
        boll_std = talib.STDDEV(close, com_length)
        boll_up = ema_com + boll_kk_dev * boll_std
        boll_down = ema_com - boll_kk_dev * boll_std

        # 计算肯特通道
        kc_atr = talib.ATR(high, low, close, kk_atr_length)
        kc_up = ema_com + kc_atr * boll_kk_dev
        kc_dowm = ema_com - kc_atr * boll_kk_dev

        # 计算唐安奇通道
        dc_up = talib.MAX(high, com_length)
        dc_down = talib.MIN(low, com_length)

        # 计算轨道 因kc通道是直接,最小值大概率是直接,所以去除
        pass_up_min = min(dc_up[-1], boll_up[-1])
        pass_down_min = max(dc_down[-1], boll_down[-1])

        pass_up_max = max(kc_up[-1], dc_up[-1], boll_up[-1])
        pass_down_max = min(kc_dowm[-1], dc_down[-1], boll_down[-1])
        ema_mid = ema_com[-1]

        com_width = abs(pass_up_max - pass_down_max)

        return ema_mid, com_width, pass_up_min, pass_down_min, pass_up_max, pass_down_max
Example #25
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
Example #26
0
class RSIStrategy(CtaTemplate):
    """"""

    author = "用Python的交易员"

    no_trade_time_begin1 = time(hour=9, minute=0)
    no_trade_time_end1 = time(hour=9, minute=30)
    no_trade_time_begin2 = time(hour=23, minute=0)
    no_trade_time_end2 = time(hour=23, minute=30)

    load_bar_day = 20

    boll_window = 16
    boll_dev = 2.6
    # cci_window = 10
    atr_window = 30
    # atr_ma_window = 10
    rsi_f_window = 5
    rsi_l_window = 10
    grow_window = 5
    reduce_window = 5
    # rsi_entry = 16
    # ma_window = 5
    sl_multiplier = 7.6
    fixed_size = 1
    db_record = 0
    bar_size = 100

    boll_up = 0
    boll_down = 0
    # cci_value = 0
    atr_value = 0
    # atr_ma = 0

    rsi_f_value = 0
    rsi_l_value = 0
    rsi_max_value = 0
    rsi_min_value = 0
    rsi_f_ma = 0
    rsi_l_ma = 0

    intra_trade_high = 0
    intra_trade_low = 0
    long_stop = 0
    short_stop = 0

    vt_1m_orderids = []
    vt_15m_orderids = []

    parameters = [
        "boll_window", "boll_dev", "atr_window", "rsi_f_window",
        "rsi_l_window", "grow_window", "reduce_window", "sl_multiplier",
        "fixed_size", "bar_size", "db_record"
    ]
    variables = [
        "boll_up", "boll_down", "atr_value", "rsi_f_value", "rsi_l_value",
        "rsi_f_ma", "rsi_l_ma", "rsi_max_value", "rsi_min_value",
        "intra_trade_high", "intra_trade_low", "long_stop", "short_stop"
    ]

    # parameters = ["boll_window", "boll_dev", "cci_window","rsi_window","rsi_entry","ma_window",
    #               "atr_window","atr_ma_window","sl_multiplier", "fixed_size"]
    # variables = ["boll_up", "boll_down", "cci_value", "atr_value","atr_ma","rsi_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)

        #todo,多时间周期,分长短期,判断不同的指标
        self.bg = BarGenerator(self.on_bar, 15, self.on_15min_bar)
        #self.am_1m = ArrayManager()
        self.am_15m = ArrayManager(self.bar_size)

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

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

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

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

    def on_bar(self, bar: BarData):
        """
        Callback of new bar data update.
        """
        # self.cancel_order_list(self.vt_1m_orderids)
        # self.am_1m.update_bar(bar)
        # if not self.am_1m.inited:
        #     return
        # # #todo 1分钟的策略
        #
        # self.boll_up, self.boll_down = self.am_1m.boll(self.boll_window, self.boll_dev)
        # self.atr_value = self.am_1m.atr(self.atr_window)
        # rsi_f_array = self.am_1m.rsi(self.rsi_f_window, array=True)
        # rsi_l_array = self.am_1m.rsi(self.rsi_l_window, array=True)
        # self.rsi_f_value = rsi_f_array[-1]
        # self.rsi_l_value = rsi_l_array[-1]
        #
        # if self.pos == 0:
        #     self.intra_trade_high = bar.high_price
        #     self.intra_trade_low = bar.low_price
        #
        #     # todo,波动不够大,应该过滤
        #     if self.rsi_f_value > self.rsi_l_value and if_keep_grow(self.grow_window, rsi_f_array):
        #         vt_orderids = self.buy(self.boll_up, self.fixed_size, True)
        #         self.vt_1m_orderids.extend(vt_orderids)
        #     elif self.rsi_f_value < self.rsi_l_value and if_keep_reduce(self.reduce_window, rsi_f_array):
        #         vt_orderids = self.short(self.boll_down, self.fixed_size, True)
        #         self.vt_1m_orderids.extend(vt_orderids)
        # # todo,持续范围内小波动,震荡策略
        #
        #
        #
        # elif self.pos > 0:
        #     self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
        #     self.intra_trade_low = bar.low_price
        #     if if_keep_reduce(self.reduce_window, rsi_f_array):  # self.rsi_f_value < self.rsi_l_value and
        #         vt_orderids = self.sell(bar.close_price - 5, abs(self.pos))
        #     else:
        #         self.long_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier
        #         vt_orderids = self.sell(self.long_stop, abs(self.pos), True)
        #     self.vt_1m_orderids.extend(vt_orderids)
        # elif self.pos < 0:
        #     self.intra_trade_high = bar.high_price
        #     self.intra_trade_low = min(self.intra_trade_low, bar.low_price)
        #     if if_keep_grow(self.grow_window, rsi_f_array):  # self.rsi_f_value > self.rsi_l_value and
        #         vt_orderids = self.cover(bar.close_price + 5, abs(self.pos))
        #     else:
        #         self.short_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier
        #         vt_orderids = self.cover(self.short_stop, abs(self.pos), True)
        #     self.vt_1m_orderids.extend(vt_orderids)
        # if self.db_record:
        #     database_manager.save_bar_calc(bar, self.get_variables())
        #
        # self.put_event()

        self.bg.update_bar(bar)

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

        self.boll_up, self.boll_down = self.am_15m.boll(
            self.boll_window, self.boll_dev)
        #self.cci_value = am.cci(self.cci_window)
        self.atr_value = self.am_15m.atr(self.atr_window)
        # atr_array = am.atr(self.atr_window, array=True)
        # self.atr_value = atr_array[-1]
        #self.atr_ma = atr_array[-self.atr_ma_window:].mean()
        rsi_f_array = self.am_15m.rsi(self.rsi_f_window, array=True)
        rsi_l_array = self.am_15m.rsi(self.rsi_l_window, array=True)
        # self.rsi_max_value = rsi_f_array[-self.rsi_f_window:].max()
        # self.rsi_min_value = rsi_f_array[-self.rsi_f_window:].min()
        # self.rsi_f_ma = rsi_f_array[-self.rsi_f_window:].mean()
        # self.rsi_l_ma = rsi_f_array[-self.rsi_f_window:].mean()
        self.rsi_f_value = rsi_f_array[-1]
        self.rsi_l_value = rsi_l_array[-1]

        #self.ma_value = am.sma(self.ma_window)

        # if (bar.datetime.time() >= self.no_trade_time_begin1 and bar.datetime.time() <= self.no_trade_time_end1) \
        #         or (bar.datetime.time() >= self.no_trade_time_begin2 and bar.datetime.time() <= self.no_trade_time_end2):
        #     return

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

            #todo,波动不够大,应该过滤
            #if self.rsi_f_value > 50 and self.rsi_f_value > self.rsi_l_value and if_keep_grow(self.grow_window, rsi_f_array) and self.rsi_f_value < 85: #self.rsi_f_value>=self.rsi_max_value:
            if self.rsi_f_value > self.rsi_l_value:  #and if_keep_grow(self.grow_window, rsi_f_array):
                #self.buy(bar.close_price+5, self.fixed_size)
                vt_orderids = self.buy(self.boll_up, self.fixed_size, True)
                self.vt_15m_orderids.extend(vt_orderids)
            #elif self.rsi_f_value < 50 and self.rsi_f_value < self.rsi_l_value and if_keep_reduce(self.reduce_window, rsi_f_array) and self.rsi_f_value >15: #self.rsi_f_value <=self.rsi_min_value:
            elif self.rsi_f_value < self.rsi_l_value:  # and if_keep_reduce(self.reduce_window, rsi_f_array):
                #self.short(bar.close_price-5, self.fixed_size)
                vt_orderids = self.short(self.boll_down, self.fixed_size, True)
                self.vt_15m_orderids.extend(vt_orderids)
#todo,持续范围内小波动,震荡策略

        elif self.pos > 0:
            self.intra_trade_high = max(self.intra_trade_high, bar.high_price)
            self.intra_trade_low = bar.low_price
            if if_keep_reduce(
                    self.reduce_window,
                    rsi_f_array):  #self.rsi_f_value < self.rsi_l_value and
                vt_orderids = self.sell(bar.close_price - 5, abs(self.pos))
            else:
                self.long_stop = self.intra_trade_high - self.atr_value * self.sl_multiplier
                vt_orderids = self.sell(self.long_stop, abs(self.pos), True)
            self.vt_15m_orderids.extend(vt_orderids)

        elif self.pos < 0:
            self.intra_trade_high = bar.high_price
            self.intra_trade_low = min(self.intra_trade_low, bar.low_price)
            if if_keep_grow(
                    self.grow_window,
                    rsi_f_array):  #self.rsi_f_value > self.rsi_l_value and
                vt_orderids = self.cover(bar.close_price + 5, abs(self.pos))
            else:
                self.short_stop = self.intra_trade_low + self.atr_value * self.sl_multiplier
                vt_orderids = self.cover(self.short_stop, abs(self.pos), True)
            self.vt_15m_orderids.extend(vt_orderids)

        if self.db_record:
            database_manager.save_bar_calc(bar, self.get_variables())

        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.
        """
        #数据库记录成交记录,bar记录,variables值
        if self.db_record:
            database_manager.save_trade_data(trade, self.get_variables())

        self.put_event()

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

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

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

	"""
    author = "yunya"

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

            ema_mid_new = self.am_xminute.sma(self.ema_length_new, True)
            self.current_ema_mid = ema_mid_new[-1]
            self.last_ema_mid = ema_mid_new[-2]
            # 仓位是long 时,如果价格下穿新布林中轨
            con1 = bar.close_price < self.current_ema_mid
            con2 = bar.close_price >= self.last_ema_mid
            if con1 and con2:
                self.exit_long_nex = bar.close_price  # 保存当前收盘价

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

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

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

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

                    else:
                        self.exit_long = self.ema_mid
            # print(f"我是多单,收盘价在两个中轨均值下方,以原中轨挂止损单:{self.exit_long},")
            else:
                self.exit_long = self.ema_mid
            self.long_stop = max(self.exit_long, self.long_stop_trade)
            self.sell(self.long_stop, abs(self.pos), True)

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

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

            # 仓位是short 时,如果价格上穿新布林中轨
            con1 = bar.close_price > self.current_ema_mid
            con2 = bar.close_price <= self.last_ema_mid
            if con1 and con2:
                self.exit_short_nex = bar.close_price
                if self.exit_short_last == 0 or self.exit_short_nex < self.exit_short_last:
                    self.exit_short_last = self.exit_short_nex
                    self.ema_length_new = self.kk_length

                    self.exit_short = self.ema_mid

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

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

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

            self.short_stop = min(self.exit_short, self.short_stop_drade)
            self.cover(self.short_stop, abs(self.pos), True)

        self.sync_data()
        self.put_event()

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

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

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

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

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

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

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

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

        self.sync_data()

    def on_trade(self, trade: TradeData):
        """
        Callback of new trade data update.
        """
        if trade.direction == Direction.LONG:
            self.long_entry = trade.price  # 成交最高价
            self.long_stop_trade = self.long_entry - 2 * self.atr_value
        else:
            self.short_entry = trade.price
            self.short_stop_drade = self.short_entry + 2 * self.atr_value

        self.sync_data()

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

        self.put_event()

    def on_stop_order(self, stop_order: StopOrder):
        """
		Callback of stop order update.
		"""
        self.put_event()
Example #28
0
class TurtleSignalStrategy(CtaTemplate):
    """"""
    author = "backtest example"

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

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

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

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

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

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

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

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

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

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

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

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

        # Only calculates new entry channel when no position holding
        if not self.pos:
            self.entry_up, self.entry_down = self.am.donchian(
                self.entry_window)

        self.exit_up, self.exit_down = self.am.donchian(self.exit_window)

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

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

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

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

        elif self.pos < 0:

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

        self.put_event()

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

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

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

    def send_buy_orders(self, price):
        """"""
        self.buy(price, self.fixed_size, True)

    def send_short_orders(self, price):
        """"""
        self.short(price, self.fixed_size, True)
Example #29
0
class DudlThrust_NewStrategy(CtaTemplate):
    """"""
    author = "yunyu"

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

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

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

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

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

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

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

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

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

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

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

        self.bg.update_tick(tick)
        self.ask = tick.ask_price_1  # 卖一价
        self.bid = tick.bid_price_1  # 买一价

        self.put_event()

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

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

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

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

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

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

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

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

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

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

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

        self.put_event()

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

        if not self.am_xmin.inited:
            return

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

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

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

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

        self.put_event()

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

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

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

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

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

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

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

        return up, down
class TurtleCStrategy(CtaTemplate):
    """"""
    # 反向海龟信号
    author = "turtle_inverse_trade"

    entry_window = 50
    exit_window = 20
    atr_window = 20
    stop_multiple = 2
    fixed_size = 1

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

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

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

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

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

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

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

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

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

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

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

        # Only calculates new entry channel when no position holding
        if not self.pos:
            self.entry_up, self.entry_down = self.am.donchian(
                self.entry_window)

            # self.close_ma = self.am.sma(50)
            # self.entry_up += self.close_ma * 0.002
            # self.entry_down -= self.close_ma * 0.002

        self.exit_up, self.exit_down = self.am.donchian(self.exit_window)

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

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

            self.send_buy_orders(self.entry_up)
            self.send_short_orders(self.entry_down)
        elif self.pos > 0:
            # inverse system
            # 有多头要卖出,等向上再卖出
            self.sell(self.exit_up, abs(self.pos), False)

        elif self.pos < 0:
            # inverse system
            # 有空头要买回,等向下再补回
            self.cover(self.exit_down, abs(self.pos), False)

        self.put_event()

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

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

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

    def send_buy_orders(self, price):
        """"""
        # invere system
        self.short(price, self.fixed_size, False)

    def send_short_orders(self, price):
        """"""
        # inverse system
        self.buy(price, self.fixed_size, False)
class Boll_kk_vix_simple_Strategy(CtaTemplate):
    """
    本策略为反向策略,币本位  Reverse 反向
    """

    author = "yunya"

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

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

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

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

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

        self.bg_xminute = BarGenerator(on_bar=self.on_bar,
                                       window=self.xminute_window,
                                       on_window_bar=self.on_xminute_bar,
                                       interval=Interval.MINUTE)
        self.am_xminute = ArrayManager(self.com_length + 10)
        self.bg = BarGenerator(self.on_bar, self.open_window, self.on_open_bar)
        self.am = ArrayManager()

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

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

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

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

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

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

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

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

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

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

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

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

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

        self.put_event()
        self.sync_data()

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

        if not self.am_xminute.inited:
            return

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

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

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

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

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

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

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

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

        self.sync_data()

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

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

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

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

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

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

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

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

        return bollkk_ema, bollkk_up, bollkk_down,