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
def show(self): bars = self.barDatas if (bars[0].datetime > bars[-1].datetime): bars = bars.__reversed__() data = [] index = [] am = ArrayManager(self.window_size * 2) ### 初始化columns columns = ['Open', 'High', 'Low', 'Close', "Volume"] if self.open_boll: columns.append("boll_up") columns.append("boll_down") if (self.open_obv): columns.append("obv") if (self.open_rsi): columns.append("rsi") for bar in bars: index.append(bar.datetime) list = [ bar.open_price, bar.high_price, bar.low_price, bar.close_price, bar.volume ] am.update_bar(bar) #添加布林指标数据 if self.open_boll: if am.count >= self.window_size: up, down = am.boll(self.window_size, 3.4) list.append(up) list.append(down) else: list.append(bar.close_price) list.append(bar.close_price) if self.open_obv: if am.count >= self.window_size: obv = am.obv(self.window_size) list.append(obv) else: list.append(bar.volume) if self.open_rsi: if am.count >= self.window_size: rsi = am.rsi(self.window_size) list.append(rsi) else: list.append(50) data.append(list) trades = pd.DataFrame(data, index=index, columns=columns) apds = [] # 添加布林指标数据 if self.open_boll: apds.append( mpf.make_addplot(trades['boll_up'], linestyle='dashdot')) apds.append( mpf.make_addplot(trades['boll_down'], linestyle='dashdot')) if self.open_obv: apds.append( mpf.make_addplot(trades['obv'], panel='lower', color='g', secondary_y=True)) if self.open_rsi: apds.append( mpf.make_addplot(trades['rsi'], panel='lower', color='b', secondary_y=True)) mpf.plot(trades, type='candle', volume=True, mav=(5), figscale=1.3, style='yahoo', addplot=apds)
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