Dual Thrust Daily Range Breakout Strategy
Summary
This example implements a Dual Thrust breakout strategy for a futures contract. It measures a recent range from the largest of two values: the lookback high minus the lookback closing low, or the lookback closing high minus the lookback low. The strategy places an upper and lower threshold around the current daily open, using separate multipliers for each side.
When the latest price crosses above the upper threshold, the target position becomes long; crossing below the lower threshold sets it short. The thresholds are recalculated when a new daily bar begins or its opening price changes. The example uses a five-day lookback, equal multipliers, and a fixed target of three contracts in either direction. It demonstrates signal and target-position mechanics rather than presenting performance evidence. The source explicitly frames it as a functional example requiring adaptation for live trading; it supplies no backtest, stop-loss rule, or broader risk analysis.
Key ideas
- The strategy derives its breakout range from recent highs, lows, and closing prices.
- It anchors the upper and lower thresholds to the current daily opening price.
- A price move beyond either threshold changes the target position to a fixed long or short size.
- The example recalculates thresholds when the current daily bar opens or a new daily bar appears.
- The document provides implementation logic but no performance evidence or stop-loss method.
Tags
Full text
# dualthrust
# dualthrust
## Source (Apache-2.0)
```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = 'limin'
'''
Dual Thrust策略 (难度:中级)
参考: https://www.shinnytech.com/blog/dual-thrust
注: 该示例策略仅用于功能示范, 实盘时请根据自己的策略/经验进行修改
'''
from tqsdk import TqApi, TqAuth, TargetPosTask
SYMBOL = "DCE.jd2011" # 合约代码
NDAY = 5 # 天数
K1 = 0.2 # 上轨K值
K2 = 0.2 # 下轨K值
api = TqApi(auth=TqAuth("快期账户", "账户密码"))
print("策略开始运行")
quote = api.get_quote(SYMBOL)
klines = api.get_kline_serial(SYMBOL, 24 * 60 * 60) # 86400使用日线
target_pos = TargetPosTask(api, SYMBOL)
def dual_thrust(quote, klines):
current_open = klines.iloc[-1]["open"]
HH = max(klines.high.iloc[-NDAY - 1:-1]) # N日最高价的最高价
HC = max(klines.close.iloc[-NDAY - 1:-1]) # N日收盘价的最高价
LC = min(klines.close.iloc[-NDAY - 1:-1]) # N日收盘价的最低价
LL = min(klines.low.iloc[-NDAY - 1:-1]) # N日最低价的最低价
range = max(HH - LC, HC - LL)
buy_line = current_open + range * K1 # 上轨
sell_line = current_open - range * K2 # 下轨
print("当前开盘价: %f, 上轨: %f, 下轨: %f" % (current_open, buy_line, sell_line))
return buy_line, sell_line
buy_line, sell_line = dual_thrust(quote, klines) # 获取上下轨
while True:
api.wait_update()
if api.is_changing(klines.iloc[-1], ["datetime", "open"]): # 新产生一根日线或开盘价发生变化: 重新计算上下轨
buy_line, sell_line = dual_thrust(quote, klines)
if api.is_changing(quote, "last_price"):
if quote.last_price > buy_line: # 高于上轨
print("高于上轨,目标持仓 多头3手")
target_pos.set_target_volume(3) # 交易
elif quote.last_price < sell_line: # 低于下轨
print("低于下轨,目标持仓 空头3手")
target_pos.set_target_volume(-3) # 交易
else:
print('未穿越上下轨,不调整持仓')
```Shown in full with attribution under the source's licence. Licence: Apache-2.0
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.