def calculate_adaptive_channel(am: ArrayManager, n: int, dev: float): """""" ma = am.sma(n) std = am.std(n) boll_up = ma + std * dev boll_down = ma - std * dev kk_up = ma + atr * dev kk_down = ma - atr * dev donchian_up = am.high[-n:].max() donchian_down = am.low[-n:].min() channel_up = max(boll_up, kk_up, donchian_up) channel_down = min(boll_down, kk_down, donchian_down) return channel_up, channel_down
class MaSignal(CtaSignal): """""" def __init__(self, fast_window: int, slow_window: int): """""" super(MaSignal, self).__init__() self.fast_window = fast_window self.slow_window = slow_window self.bg = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.am = ArrayManager() def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" self.am.update_bar(bar) if not self.am.inited: self.set_signal_pos(0) fast_ma = self.am.sma("c", self.fast_window) slow_ma = self.am.sma("c", self.slow_window) if fast_ma > slow_ma: self.set_signal_pos(1) elif fast_ma < slow_ma: self.set_signal_pos(-1) else: self.set_signal_pos(0)
class StatisticalArbitrageStrategy(SpreadStrategyTemplate): """""" author = "用Python的交易员" boll_window = 20 boll_dev = 2 max_pos = 10 payup = 10 interval = 5 spread_pos = 0.0 boll_up = 0.0 boll_down = 0.0 boll_mid = 0.0 parameters = ["boll_window", "boll_dev", "max_pos", "payup", "interval"] variables = ["spread_pos", "boll_up", "boll_down", "boll_mid"] def __init__(self, strategy_engine, strategy_name: str, spread: SpreadData, setting: dict): """""" super().__init__(strategy_engine, strategy_name, spread, setting) self.bg = BarGenerator(self.on_spread_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(1) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") self.put_event() def on_spread_data(self): """ Callback when spread price is updated. """ tick = self.get_spread_tick() self.on_spread_tick(tick) def on_spread_tick(self, tick: TickData): """ Callback when new spread tick data is generated. """ self.bg.update_tick(tick) def on_spread_bar(self, bar: BarData): """ Callback when spread bar data is generated. """ self.stop_all_algos() self.am.update_bar(bar) if not self.am.inited: return self.boll_mid = self.am.sma(self.boll_window) self.boll_up, self.boll_down = self.am.boll(self.boll_window, self.boll_dev) if not self.spread_pos: if bar.close_price >= self.boll_up: self.start_short_algo(bar.close_price - 10, self.max_pos, payup=self.payup, interval=self.interval) elif bar.close_price <= self.boll_down: self.start_long_algo(bar.close_price + 10, self.max_pos, payup=self.payup, interval=self.interval) elif self.spread_pos < 0: if bar.close_price <= self.boll_mid: self.start_long_algo(bar.close_price + 10, abs(self.spread_pos), payup=self.payup, interval=self.interval) else: if bar.close_price >= self.boll_mid: self.start_short_algo(bar.close_price - 10, abs(self.spread_pos), payup=self.payup, interval=self.interval) self.put_event() def on_spread_pos(self): """ Callback when spread position is updated. """ self.spread_pos = self.get_spread_pos() self.put_event() def on_spread_algo(self, algo: SpreadAlgoTemplate): """ Callback when algo status is updated. """ pass def on_order(self, order: OrderData): """ Callback when order status is updated. """ pass def on_trade(self, trade: TradeData): """ Callback when new trade data is received. """ pass def stop_open_algos(self): """""" if self.buy_algoid: self.stop_algo(self.buy_algoid) if self.short_algoid: self.stop_algo(self.short_algoid) def stop_close_algos(self): """""" if self.sell_algoid: self.stop_algo(self.sell_algoid) if self.cover_algoid: self.stop_algo(self.cover_algoid)
class StatisticalArbitrageGridStrategy(SpreadStrategyTemplate): """ 算法逻辑是在统计算法基础上增加加仓位逻辑 """ author = "yunya" boll_window = 60 boll_dev = 4.0 fixed_pos = 10 max_pos = 4 price_proportion = 2.0 pay_up = 5 increase_price = 0.0 # 超价 interval = 5 spread_pos = 0 boll_up = 0 boll_down = 0 boll_mid = 0 grid_count = 0 buy_grid_count = 0 short_grid_count = 0 long_price = 0 short_price = 0 parameters = [ "boll_window", "boll_dev", "fixed_pos", "max_pos", "price_proportion", "pay_up", "interval", "increase_price" ] variables = [ "spread_pos", "boll_up", "boll_down", "boll_mid", "grid_count", "buy_grid_count", "short_grid_count", "long_price", "short_price", ] def __init__(self, strategy_engine, strategy_name: str, spread: SpreadData, setting: dict): """""" super().__init__(strategy_engine, strategy_name, spread, setting) self.bg = BarGenerator(self.on_spread_bar) self.am = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(5) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") self.put_event() def on_spread_data(self): """ Callback when spread price is updated. 收到差价推送后,合成价差TICK数据 """ #这里的价差tick tick = self.get_spread_tick() self.on_spread_tick(tick) def on_spread_tick(self, tick: TickData): """ Callback when new spread tick data is generated. """ self.bg.update_tick(tick) def on_spread_bar(self, bar: BarData): """ Callback when spread bar data is generated. """ # 把老算法先停止, self.stop_all_algos() self.am.update_bar(bar) if not self.am.inited: return self.boll_mid = self.am.sma(self.boll_window) self.boll_up, self.boll_down = self.am.boll(self.boll_window, self.boll_dev) if not self.spread_pos: if bar.close_price >= self.boll_up: self.start_short_algo(bar.close_price - self.increase_price, self.fixed_pos, payup=self.pay_up, interval=self.interval) elif bar.close_price <= self.boll_down: self.start_long_algo(bar.close_price + self.increase_price, self.fixed_pos, payup=self.pay_up, interval=self.interval) elif self.spread_pos < 0: if bar.close_price <= self.boll_mid: self.start_long_algo(bar.close_price + self.increase_price, abs(self.spread_pos), payup=self.pay_up, interval=self.interval) self.buy_grid_count = 0 else: # 加仓 grid_count = self.buy_grid_count < self.max_pos bar_change = bar.close_price > self.long_price * ( 1 + self.price_proportion / 1000) if grid_count and bar_change: if bar.close_price >= self.boll_up: self.start_short_algo(bar.close_price - self.increase_price, self.fixed_pos, payup=self.pay_up, interval=self.interval) else: if bar.close_price >= self.boll_mid: self.start_short_algo(bar.close_price - self.increase_price, abs(self.spread_pos), payup=self.pay_up, interval=self.interval) self.short_grid_count = 0 else: # 加仓 grid_count = self.short_grid_count < self.max_pos bar_change = bar.close_price < self.short_price * ( 1 - self.price_proportion / 1000) if grid_count and bar_change: if bar.close_price <= self.boll_down: self.start_long_algo(bar.close_price + self.increase_price, self.fixed_pos, payup=self.pay_up, interval=self.interval) def on_spread_pos(self): """ Callback when spread position is updated. """ self.spread_pos = self.get_spread_pos() self.put_event() def on_spread_algo(self, algo: SpreadAlgoTemplate): """ Callback when algo status is updated. """ pass def on_order(self, order: OrderData): """ Callback when order status is updated. """ if order.status == Status.ALLTRADED: if order.direction == Direction.LONG: self.buy_grid_count += 1 else: self.short_grid_count += 1 def on_trade(self, trade: TradeData): """ Callback when new trade data is received. """ if trade.direction == Direction.LONG: self.long_price = trade.price else: self.short_price = trade.price
class StatisticalArbitrageStrategy(SpreadStrategyTemplate): """""" author = "用Python的交易员" open_window = 1 boll_window = 40 boll_dev = 4.9 fixed_pos = 10 payup = 10.0 increase_price = 0.0 # 超价 interval = 5 spread_pos = 0.0 boll_up = 0.0 boll_down = 0.0 boll_mid = 0.0 parameters = [ "boll_window", "boll_dev", "fixed_pos", "payup", "interval", "increase_price" ] variables = ["spread_pos", "boll_up", "boll_down", "boll_mid"] def __init__(self, strategy_engine, strategy_name: str, spread: SpreadData, setting: dict): """""" super().__init__(strategy_engine, strategy_name, spread, setting) self.bg = BarGenerator(self.on_open_spread_bar, self.open_window, self.on_open_spread_bar) self.am = ArrayManager() self.spread_pos = 0.0 self.boll_up = 0.0 self.boll_down = 0.0 self.boll_mid = 0.0 def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") self.put_event() def on_spread_data(self): """ Callback when spread price is updated. 收到差价推送后,合成价差TICK数据 """ #这里的价差tick tick = self.get_spread_tick() self.on_spread_tick(tick) def on_spread_tick(self, tick: TickData): """ Callback when new spread tick data is generated. """ self.bg.update_tick(tick) def on_spread_bar(self, bar: BarData): """ Callback when new spread bar data is generated. """ self.bg.update_bar(bar) def on_open_spread_bar(self, bar: BarData): """ Callback when spread bar data is generated. 目前的策略逻辑: 1、当价差价格大于布林上轨,以当前收盘加低10的价格下单(以市价下单保证成交),当价格跌破中轨时平仓 (做空) 2、当价差价格小于布林下轨,以当前收盘价加10的价格下单,当价格高于中轨时平仓 (做多) 策略优化方向: 1、把目前在分钟价差K线逻辑移到 tick逻辑中实盘,增加细腻度 2、仓位分为四次加减仓,第一次上穿时,开一份,第二次上穿的价格要高于第一次一定比较时,开第二份,一直到满四份。 (这两个参数,一个是份数,一个是跨度(格距)),目的解决如果出现单边短时趋势抗单时爆仓(最后都会回归中轨) 3、回到中轨全部平仓位 """ # 把老算法先停止, self.stop_all_algos() self.am.update_bar(bar) if not self.am.inited: return self.boll_mid = self.am.sma(self.boll_window) self.boll_up, self.boll_down = self.am.boll(self.boll_window, self.boll_dev) if not self.spread_pos: if bar.close_price >= self.boll_up: self.start_short_algo(bar.close_price - self.increase_price, self.fixed_pos, payup=self.payup, interval=self.interval) elif bar.close_price <= self.boll_down: self.start_long_algo(bar.close_price + self.increase_price, self.fixed_pos, payup=self.payup, interval=self.interval) elif self.spread_pos < 0: if bar.close_price <= self.boll_mid: self.start_long_algo(bar.close_price + self.increase_price, abs(self.spread_pos), payup=self.payup, interval=self.interval) else: if bar.close_price >= self.boll_mid: self.start_short_algo(bar.close_price - self.increase_price, abs(self.spread_pos), payup=self.payup, interval=self.interval) self.put_event() def on_spread_pos(self): """ Callback when spread position is updated. """ self.spread_pos = self.get_spread_pos() self.put_event() def on_spread_algo(self, algo: SpreadAlgoTemplate): """ Callback when algo status is updated. """ pass def on_order(self, order: OrderData): """ Callback when order status is updated. """ pass def on_trade(self, trade: TradeData): """ Callback when new trade data is received. """ pass
class MultiTimeframeStrategy(CtaTemplate): """""" author = "中科云集" rsi_signal = 20 rsi_window = 14 fast_window = 5 slow_window = 20 fixed_size = 1 rsi_value = 0 rsi_long = 0 rsi_short = 0 fast_ma = 0 slow_ma = 0 ma_trend = 0 parameters = [ "rsi_signal", "rsi_window", "fast_window", "slow_window", "fixed_size" ] variables = [ "rsi_value", "rsi_long", "rsi_short", "fast_ma", "slow_ma", "ma_trend" ] def __init__(self, cta_engine, strategy_name, vt_symbol, setting): """""" super(MultiTimeframeStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) self.rsi_long = 50 + self.rsi_signal self.rsi_short = 50 - self.rsi_signal self.bg5 = BarGenerator(self.on_bar, 5, self.on_5min_bar) self.am5 = ArrayManager() self.bg15 = BarGenerator(self.on_bar, 15, self.on_15min_bar) self.am15 = ArrayManager() def on_init(self): """ Callback when strategy is inited. """ self.write_log("策略初始化") self.load_bar(10) def on_start(self): """ Callback when strategy is started. """ self.write_log("策略启动") def on_stop(self): """ Callback when strategy is stopped. """ self.write_log("策略停止") def on_tick(self, tick: TickData): """ Callback of new tick data update. """ self.bg5.update_tick(tick) def on_bar(self, bar: BarData): """ Callback of new bar data update. """ self.bg5.update_bar(bar) self.bg15.update_bar(bar) def on_5min_bar(self, bar: BarData): """""" self.cancel_all() self.am5.update_bar(bar) if not self.am5.inited: return if not self.ma_trend: return self.rsi_value = self.am5.rsi(self.rsi_window) if self.pos == 0: if self.ma_trend > 0 and self.rsi_value >= self.rsi_long: self.buy(bar.close_price + 5, self.fixed_size) elif self.ma_trend < 0 and self.rsi_value <= self.rsi_short: self.short(bar.close_price - 5, self.fixed_size) elif self.pos > 0: if self.ma_trend < 0 or self.rsi_value < 50: self.sell(bar.close_price - 5, abs(self.pos)) elif self.pos < 0: if self.ma_trend > 0 or self.rsi_value > 50: self.cover(bar.close_price + 5, abs(self.pos)) self.put_event() def on_15min_bar(self, bar: BarData): """""" self.am15.update_bar(bar) if not self.am15.inited: return self.fast_ma = self.am15.sma("c", self.fast_window) self.slow_ma = self.am15.sma("c", self.slow_window) if self.fast_ma > self.slow_ma: self.ma_trend = 1 else: self.ma_trend = -1 def on_order(self, order: OrderData): """ Callback of new order data update. """ pass def on_trade(self, trade: TradeData): """ Callback of new trade data update. """ self.put_event() def on_stop_order(self, stop_order: StopOrder): """ Callback of stop order update. """ pass