Merge pull request #1811 from 1122455801/algo_trade_0608

[Mod] algo_trader.md
This commit is contained in:
vn.py 2019-06-08 21:22:11 +08:00 committed by GitHub
commit e5108bdf61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -9,7 +9,7 @@
- engine定义了算法引擎其中包括引擎初始化、保存/移除/加载算法配置、启动算法、停止算法、订阅行情、挂撤单等。 - engine定义了算法引擎其中包括引擎初始化、保存/移除/加载算法配置、启动算法、停止算法、订阅行情、挂撤单等。
- template定义了交易算法模板具体的算法示例如冰山算法都需要继承于该模板。 - template定义了交易算法模板具体的算法示例如冰山算法都需要继承于该模板。
- algos官方提供的交易算法示例,包括:冰山算法、狙击手算法、时间加权平均算法、条件委托、最优限价 - algos具体的交易算法示例。用户基于算法模板和官方提供是算法示例,可以自己搭建新的算法
- ui基于PyQt5的GUI图形应用。 - ui基于PyQt5的GUI图形应用。
![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/algo_trader/algo_trader_document.png) ![](https://vnpy-community.oss-cn-shanghai.aliyuncs.com/forum_experience/yazhang/algo_trader/algo_trader_document.png)
@ -83,6 +83,37 @@
## 算法示例 ## 算法示例
### 直接委托算法
直接发出新的委托(限价单、停止单、市价单)
```
def on_tick(self, tick: TickData):
""""""
if not self.vt_orderid:
if self.direction == Direction.LONG:
self.vt_orderid = self.buy(
self.vt_symbol,
self.price,
self.volume,
self.order_type,
self.offset
)
else:
self.vt_orderid = self.sell(
self.vt_symbol,
self.price,
self.volume,
self.order_type,
self.offset
)
self.put_variables_event()
```
 
### 时间加权平均算法 ### 时间加权平均算法
- 将委托数量平均分布在某个时间区域内; - 将委托数量平均分布在某个时间区域内;
@ -319,3 +350,160 @@
offset=self.offset offset=self.offset
) )
``` ```
 
### 网格算法
- 每隔一段时间检查委托情况,若有委托则先清空。
- 基于用户设置的价格步进(即网格)计算目标距离,目标距离=(目标价格- 当前价格)/价格步进,故当前价格低于目标价格,目标距离为正,方向为买入;当前价格高于目标价格,目标距离为负,方向为卖出。(高抛低吸概念)
- 计算目标仓位,目标仓位= 取整后的目标距离 * 委托数量步进。注意卖卖方向取整的方式是不同的买入方向要向下取整math.floor()如目标距离为1.6取1卖出方向要向上取整如目标距离为-1.6,取-1。
- 计算具体委托仓位:若目标买入仓位大于当前仓位,执行买入操作;若目标卖出仓位低于当前仓位,执行卖出操作。
- 为了能够快速成交买入情况是基于ask price计算卖出情况是基于bid price计算。
```
def on_timer(self):
""""""
if not self.last_tick:
return
self.timer_count += 1
if self.timer_count < self.interval:
self.put_variables_event()
return
self.timer_count = 0
if self.vt_orderid:
self.cancel_all()
# Calculate target volume to buy
target_buy_distance = (self.price - self.last_tick.ask_price_1) / self.step_price
target_buy_position = math.floor(target_buy_distance) * self.step_volume
target_buy_volume = target_buy_position - self.last_pos
# Buy when price dropping
if target_buy_volume > 0:
self.vt_orderid = self.buy(
self.vt_symbol,
self.last_tick.ask_price_1,
min(target_buy_volume, self.last_tick.ask_volume_1)
)
# Calculate target volume to sell
target_sell_distance = (self.price - self.last_tick.bid_price_1) / self.step_price
target_sell_position = math.ceil(target_sell_distance) * self.step_volume
target_sell_volume = self.last_pos - target_sell_position
# Sell when price rising
if target_sell_volume > 0:
self.vt_orderid = self.sell(
self.vt_symbol,
self.last_tick.bid_price_1,
min(target_sell_volume, self.last_tick.bid_volume_1)
)
```
&nbsp;
### 套利算法
- 每隔一段时间检查委托情况,若有委托则先清空;若主动腿还持有净持仓,通过被动腿成交来对冲。
- 计算价差spread_bid_price 和 spread_ask_price, 以及对应的委托数量
- 卖出情况主动腿价格相对被动腿上涨其价差spread_bid_price大于spread_up时触发买入信号
- 买入情况主动腿价格相对被动腿下跌其价差spread_ask_price小于 - spread_down(spread_down默认设置为正数)时,触发卖出信号
- 在买卖信号判断加入最大持仓的限制其作用是避免持仓过多导致保证金不足或者直接被交易所惩罚性强平而且随着价差持续波动主动腿持仓可以从0 -> 10 -> 0 -> -10 -> 0,从而实现平仓获利离场。
```
def on_timer(self):
""""""
self.timer_count += 1
if self.timer_count < self.interval:
self.put_variables_event()
return
self.timer_count = 0
if self.active_vt_orderid or self.passive_vt_orderid:
self.cancel_all()
return
if self.net_pos:
self.hedge()
return
active_tick = self.get_tick(self.active_vt_symbol)
passive_tick = self.get_tick(self.passive_vt_symbol)
if not active_tick or not passive_tick:
return
# Calculate spread
spread_bid_price = active_tick.bid_price_1 - passive_tick.ask_price_1
spread_ask_price = active_tick.ask_price_1 - passive_tick.bid_price_1
spread_bid_volume = min(active_tick.bid_volume_1, passive_tick.ask_volume_1)
spread_ask_volume = min(active_tick.ask_volume_1, passive_tick.bid_volume_1)
# Sell condition
if spread_bid_price > self.spread_up:
if self.acum_pos <= -self.max_pos:
return
else:
self.active_vt_orderid = self.sell(
self.active_vt_symbol,
active_tick.bid_price_1,
spread_bid_volume
)
# Buy condition
elif spread_ask_price < -self.spread_down:
if self.acum_pos >= self.max_pos:
return
else:
self.active_vt_orderid = self.buy(
self.active_vt_symbol,
active_tick.ask_price_1,
spread_ask_volume
)
self.put_variables_event()
def hedge(self):
""""""
tick = self.get_tick(self.passive_vt_symbol)
volume = abs(self.net_pos)
if self.net_pos > 0:
self.passive_vt_orderid = self.sell(
self.passive_vt_symbol,
tick.bid_price_5,
volume
)
elif self.net_pos < 0:
self.passive_vt_orderid = self.buy(
self.passive_vt_symbol,
tick.ask_price_5,
volume
)
def on_trade(self, trade: TradeData):
""""""
# Update net position volume
if trade.direction == Direction.LONG:
self.net_pos += trade.volume
else:
self.net_pos -= trade.volume
# Update active symbol position
if trade.vt_symbol == self.active_vt_symbol:
if trade.direction == Direction.LONG:
self.acum_pos += trade.volume
else:
self.acum_pos -= trade.volume
# Hedge if active symbol traded
if trade.vt_symbol == self.active_vt_symbol:
self.hedge()
self.put_variables_event()
```