算法示例

直接委托算法

直接发出新的委托(限价单、停止单、市价单)

  1. def on_tick(self, tick: TickData):
  2. """"""
  3. if not self.vt_orderid:
  4. if self.direction == Direction.LONG:
  5. self.vt_orderid = self.buy(
  6. self.vt_symbol,
  7. self.price,
  8. self.volume,
  9. self.order_type,
  10. self.offset
  11. )
  12.  
  13. else:
  14. self.vt_orderid = self.sell(
  15. self.vt_symbol,
  16. self.price,
  17. self.volume,
  18. self.order_type,
  19. self.offset
  20. )
  21. self.put_variables_event()

时间加权平均算法

  • 将委托数量平均分布在某个时间区域内;

  • 每隔一段时间用指定的价格挂出买单(或者卖单)。

  • 买入情况:买一价低于目标价格时,发出委托,委托数量在剩余委托量与委托分割量中取最小值。

  • 卖出情况:卖一价高于目标价格时,发出委托,委托数量在剩余委托量与委托分割量中取最小值。

  1. def on_timer(self):
  2. """"""
  3. self.timer_count += 1
  4. self.total_count += 1
  5. self.put_variables_event()
  6.  
  7. if self.total_count >= self.time:
  8. self.write_log("执行时间已结束,停止算法")
  9. self.stop()
  10. return
  11.  
  12. if self.timer_count < self.interval:
  13. return
  14. self.timer_count = 0
  15.  
  16. tick = self.get_tick(self.vt_symbol)
  17. if not tick:
  18. return
  19.  
  20. self.cancel_all()
  21.  
  22. left_volume = self.volume - self.traded
  23. order_volume = min(self.order_volume, left_volume)
  24.  
  25. if self.direction == Direction.LONG:
  26. if tick.ask_price_1 <= self.price:
  27. self.buy(self.vt_symbol, self.price,
  28. order_volume, offset=self.offset)
  29. else:
  30. if tick.bid_price_1 >= self.price:
  31. self.sell(self.vt_symbol, self.price,
  32. order_volume, offset=self.offset)

冰山算法

  • 在某个价位挂单,但是只挂一部分,直到全部成交。

  • 买入情况:先检查撤单:最新Tick卖一价低于目标价格,执行撤单;若无活动委托,发出委托:委托数量在剩余委托量与挂出委托量中取最小值。

  • 卖出情况:先检查撤单:最新Tick买一价高于目标价格,执行撤单;若无活动委托,发出委托:委托数量在剩余委托量与挂出委托量中取最小值。

  1. def on_timer(self):
  2. """"""
  3. self.timer_count += 1
  4.  
  5. if self.timer_count < self.interval:
  6. self.put_variables_event()
  7. return
  8.  
  9. self.timer_count = 0
  10.  
  11. contract = self.get_contract(self.vt_symbol)
  12. if not contract:
  13. return
  14.  
  15. # If order already finished, just send new order
  16. if not self.vt_orderid:
  17. order_volume = self.volume - self.traded
  18. order_volume = min(order_volume, self.display_volume)
  19.  
  20. if self.direction == Direction.LONG:
  21. self.vt_orderid = self.buy(
  22. self.vt_symbol,
  23. self.price,
  24. order_volume,
  25. offset=self.offset
  26. )
  27. else:
  28. self.vt_orderid = self.sell(
  29. self.vt_symbol,
  30. self.price,
  31. order_volume,
  32. offset=self.offset
  33. )
  34. # Otherwise check for cancel
  35. else:
  36. if self.direction == Direction.LONG:
  37. if self.last_tick.ask_price_1 <= self.price:
  38. self.cancel_order(self.vt_orderid)
  39. self.vt_orderid = ""
  40. self.write_log(u"最新Tick卖一价,低于买入委托价格,之前委托可能丢失,强制撤单")
  41. else:
  42. if self.last_tick.bid_price_1 >= self.price:
  43. self.cancel_order(self.vt_orderid)
  44. self.vt_orderid = ""
  45. self.write_log(u"最新Tick买一价,高于卖出委托价格,之前委托可能丢失,强制撤单")
  46.  
  47. self.put_variables_event()

狙击手算法

  • 监控最新tick推送的行情,发现好的价格立刻报价成交。

  • 买入情况:最新Tick卖一价低于目标价格时,发出委托,委托数量在剩余委托量与卖一量中取最小值。

  • 卖出情况:最新Tick买一价高于目标价格时,发出委托,委托数量在剩余委托量与买一量中取最小值。

  1. def on_tick(self, tick: TickData):
  2. """"""
  3. if self.vt_orderid:
  4. self.cancel_all()
  5. return
  6.  
  7. if self.direction == Direction.LONG:
  8. if tick.ask_price_1 <= self.price:
  9. order_volume = self.volume - self.traded
  10. order_volume = min(order_volume, tick.ask_volume_1)
  11.  
  12. self.vt_orderid = self.buy(
  13. self.vt_symbol,
  14. self.price,
  15. order_volume,
  16. offset=self.offset
  17. )
  18. else:
  19. if tick.bid_price_1 >= self.price:
  20. order_volume = self.volume - self.traded
  21. order_volume = min(order_volume, tick.bid_volume_1)
  22.  
  23. self.vt_orderid = self.sell(
  24. self.vt_symbol,
  25. self.price,
  26. order_volume,
  27. offset=self.offset
  28. )
  29.  
  30. self.put_variables_event()

条件委托算法

  • 监控最新tick推送的行情,发现行情突破立刻报价成交。

  • 买入情况:Tick最新价高于目标价格时,发出委托,委托价为目标价格加上超价。

  • 卖出情况:Tick最新价低于目标价格时,发出委托,委托价为目标价格减去超价。

  1. def on_tick(self, tick: TickData):
  2. """"""
  3. if self.vt_orderid:
  4. return
  5.  
  6. if self.direction == Direction.LONG:
  7. if tick.last_price >= self.stop_price:
  8. price = self.stop_price + self.price_add
  9.  
  10. if tick.limit_up:
  11. price = min(price, tick.limit_up)
  12.  
  13. self.vt_orderid = self.buy(
  14. self.vt_symbol,
  15. price,
  16. self.volume,
  17. offset=self.offset
  18. )
  19. self.write_log(f"停止单已触发,代码:{self.vt_symbol},方向:{self.direction}, 价格:{self.stop_price},数量:{self.volume},开平:{self.offset}")
  20.  
  21. else:
  22. if tick.last_price <= self.stop_price:
  23. price = self.stop_price - self.price_add
  24.  
  25. if tick.limit_down:
  26. price = max(price, tick.limit_down)
  27.  
  28. self.vt_orderid = self.buy(
  29. self.vt_symbol,
  30. price,
  31. self.volume,
  32. offset=self.offset
  33. )
  34. self.write_log(f"停止单已触发,代码:{self.vt_symbol},方向:{self.direction}, 价格:{self.stop_price},数量:{self.volume},开平:{self.offset}")
  35.  
  36. self.put_variables_event()

最优限价算法

  • 监控最新tick推送的行情,发现好的价格立刻报价成交。

  • 买入情况:先检查撤单:最新Tick买一价不等于目标价格时,执行撤单;若无活动委托,发出委托:委托价格为最新Tick买一价,委托数量为剩余委托量。

  • 卖出情况:先检查撤单:最新Tick买一价不等于目标价格时,执行撤单;若无活动委托,发出委托:委托价格为最新Tick卖一价,委托数量为剩余委托量。

  1. def on_tick(self, tick: TickData):
  2. """"""
  3. self.last_tick = tick
  4.  
  5. if self.direction == Direction.LONG:
  6. if not self.vt_orderid:
  7. self.buy_best_limit()
  8. elif self.order_price != self.last_tick.bid_price_1:
  9. self.cancel_all()
  10. else:
  11. if not self.vt_orderid:
  12. self.sell_best_limit()
  13. elif self.order_price != self.last_tick.ask_price_1:
  14. self.cancel_all()
  15.  
  16. self.put_variables_event()
  17.  
  18. def buy_best_limit(self):
  19. """"""
  20. order_volume = self.volume - self.traded
  21. self.order_price = self.last_tick.bid_price_1
  22. self.vt_orderid = self.buy(
  23. self.vt_symbol,
  24. self.order_price,
  25. order_volume,
  26. offset=self.offset
  27. )
  28.  
  29. def sell_best_limit(self):
  30. """"""
  31. order_volume = self.volume - self.traded
  32. self.order_price = self.last_tick.ask_price_1
  33. self.vt_orderid = self.sell(
  34. self.vt_symbol,
  35. self.order_price,
  36. order_volume,
  37. offset=self.offset
  38. )

网格算法

  • 每隔一段时间检查委托情况,若有委托则先清空。

  • 基于用户设置的价格步进(即网格)计算目标距离,目标距离=(目标价格- 当前价格)/价格步进,故当前价格低于目标价格,目标距离为正,方向为买入;当前价格高于目标价格,目标距离为负,方向为卖出。(高抛低吸概念)

  • 计算目标仓位,目标仓位= 取整后的目标距离 * 委托数量步进。注意卖卖方向取整的方式是不同的:买入方向要向下取整math.floor(),如目标距离为1.6,取1;卖出方向要向上取整,如目标距离为-1.6,取-1。

  • 计算具体委托仓位:若目标买入仓位大于当前仓位,执行买入操作;若目标卖出仓位低于当前仓位,执行卖出操作。

  • 为了能够快速成交,买入情况是基于ask price计算,卖出情况是基于bid price计算。

  1. def on_timer(self):
  2. """"""
  3. if not self.last_tick:
  4. return
  5.  
  6. self.timer_count += 1
  7. if self.timer_count < self.interval:
  8. self.put_variables_event()
  9. return
  10. self.timer_count = 0
  11.  
  12. if self.vt_orderid:
  13. self.cancel_all()
  14.  
  15. # Calculate target volume to buy
  16. target_buy_distance = (self.price - self.last_tick.ask_price_1) / self.step_price
  17. target_buy_position = math.floor(target_buy_distance) * self.step_volume
  18. target_buy_volume = target_buy_position - self.last_pos
  19.  
  20. # Buy when price dropping
  21. if target_buy_volume > 0:
  22. self.vt_orderid = self.buy(
  23. self.vt_symbol,
  24. self.last_tick.ask_price_1,
  25. min(target_buy_volume, self.last_tick.ask_volume_1)
  26. )
  27.  
  28. # Calculate target volume to sell
  29. target_sell_distance = (self.price - self.last_tick.bid_price_1) / self.step_price
  30. target_sell_position = math.ceil(target_sell_distance) * self.step_volume
  31. target_sell_volume = self.last_pos - target_sell_position
  32.  
  33. # Sell when price rising
  34. if target_sell_volume > 0:
  35. self.vt_orderid = self.sell(
  36. self.vt_symbol,
  37. self.last_tick.bid_price_1,
  38. min(target_sell_volume, self.last_tick.bid_volume_1)
  39. )

套利算法

  • 每隔一段时间检查委托情况,若有委托则先清空;若主动腿还持有净持仓,通过被动腿成交来对冲。

  • 计算价差spread_bid_price 和 spread_ask_price, 以及对应的委托数量

  • 卖出情况:主动腿价格相对被动腿上涨,其价差spread_bid_price大于spread_up时,触发买入信号

  • 买入情况:主动腿价格相对被动腿下跌,其价差spread_ask_price小于 - spread_down(spread_down默认设置为正数)时,触发卖出信号

  • 在买卖信号判断加入最大持仓的限制,其作用是避免持仓过多导致保证金不足或者直接被交易所惩罚性强平;而且随着价差持续波动,主动腿持仓可以从0 -> 10 -> 0 -> -10 -> 0,从而实现平仓获利离场。

  1. def on_timer(self):
  2. """"""
  3. self.timer_count += 1
  4. if self.timer_count < self.interval:
  5. self.put_variables_event()
  6. return
  7. self.timer_count = 0
  8.  
  9. if self.active_vt_orderid or self.passive_vt_orderid:
  10. self.cancel_all()
  11. return
  12.  
  13. if self.net_pos:
  14. self.hedge()
  15. return
  16.  
  17. active_tick = self.get_tick(self.active_vt_symbol)
  18. passive_tick = self.get_tick(self.passive_vt_symbol)
  19. if not active_tick or not passive_tick:
  20. return
  21.  
  22. # Calculate spread
  23. spread_bid_price = active_tick.bid_price_1 - passive_tick.ask_price_1
  24. spread_ask_price = active_tick.ask_price_1 - passive_tick.bid_price_1
  25.  
  26. spread_bid_volume = min(active_tick.bid_volume_1, passive_tick.ask_volume_1)
  27. spread_ask_volume = min(active_tick.ask_volume_1, passive_tick.bid_volume_1)
  28.  
  29. # Sell condition
  30. if spread_bid_price > self.spread_up:
  31. if self.acum_pos <= -self.max_pos:
  32. return
  33. else:
  34. self.active_vt_orderid = self.sell(
  35. self.active_vt_symbol,
  36. active_tick.bid_price_1,
  37. spread_bid_volume
  38. )
  39.  
  40. # Buy condition
  41. elif spread_ask_price < -self.spread_down:
  42. if self.acum_pos >= self.max_pos:
  43. return
  44. else:
  45. self.active_vt_orderid = self.buy(
  46. self.active_vt_symbol,
  47. active_tick.ask_price_1,
  48. spread_ask_volume
  49. )
  50. self.put_variables_event()
  51.  
  52. def hedge(self):
  53. """"""
  54. tick = self.get_tick(self.passive_vt_symbol)
  55. volume = abs(self.net_pos)
  56.  
  57. if self.net_pos > 0:
  58. self.passive_vt_orderid = self.sell(
  59. self.passive_vt_symbol,
  60. tick.bid_price_5,
  61. volume
  62. )
  63. elif self.net_pos < 0:
  64. self.passive_vt_orderid = self.buy(
  65. self.passive_vt_symbol,
  66. tick.ask_price_5,
  67. volume
  68. )
  69.  
  70. def on_trade(self, trade: TradeData):
  71. """"""
  72. # Update net position volume
  73. if trade.direction == Direction.LONG:
  74. self.net_pos += trade.volume
  75. else:
  76. self.net_pos -= trade.volume
  77.  
  78. # Update active symbol position
  79. if trade.vt_symbol == self.active_vt_symbol:
  80. if trade.direction == Direction.LONG:
  81. self.acum_pos += trade.volume
  82. else:
  83. self.acum_pos -= trade.volume
  84.  
  85. # Hedge if active symbol traded
  86. if trade.vt_symbol == self.active_vt_symbol:
  87. self.hedge()
  88.  
  89. self.put_variables_event()