双海龟突破策略


创建日期: 2023-11-28 16:25:41 最后修改: 2023-11-28 16:25:41
复制: 0 点击次数: 562
avatar of ChaoZhang ChaoZhang
1
关注
1359
关注者

双海龟突破策略

概述

双海龟突破策略融合了海龟交易法的突破策略和琳达·拉施克的移动止损原理,具有优异的突破性能和严格的风险控制。该策略同时监控价格的上下突破,在突破发生时建立做多或做空头寸,并利用移动止损和移动止盈管理头寸。

策略原理

核心逻辑是在大周期高点上突破小周期高点时做空,在大周期低点下突破小周期低点时做多。建仓后设置移动止损和移动止盈,首先止损确认风险。在持仓数量累积到设置的止盈数量时,在下一个周期取消止损单,然后出半仓并设置移动止损和移动止盈锁定利润并追踪价差。

具体操作步骤是: 1. 计算大周期(20周期)高点prevHigh和小周期(4周期)高点smallPeriodHigh。 2. 当最新K线的high大于prevHigh,并且prevHigh大于smallPeriodHigh时,表明大周期高点突破小周期高点,此时若没有仓位则做空。 3. 建仓后设置移动止损,待仓位反转后取消止损单,防止被止损。 4. 当持仓数量达到设置的移动止盈周期数(当前为0周期)时,在下一个周期出一半仓位,并设置移动止损与移动止盈,追踪价差并锁定利润。 5. 对于低点的突破类似,基于大周期低点和小周期低点的突破关系建立做多头寸。

优势分析

这是一个综合性较强的突破策略,同时具有以下优势: 1. 结合双周期海龟交易法,能够有效识别突破信号。 2. 采用移动止损与移动止盈技术严格控制风险,避免巨亏。 3. 分两次出场,一次止盈出半仓,再通过移动止盈出全仓,锁定利润。 4. 兼顾做多和做空双向操作,符合多空互换的市场特点。 5. 回测效果优异,具有很强的实盘表现能力。

风险分析

主要的风险和应对措施如下: 1. 假突破风险。应适当调整周期参数,确保突破的有效性。 2. 追涨杀跌风险。应结合趋势和形态进行过滤,避免在趋势末期建仓。 3. 止损被冲风险。可适当放宽止损幅度,确保有足够的空间。 4. 移动止损过于灵敏风险。应调整止损后滑点设置,避免无谓止损。

优化方向

该策略还可从以下几个方面进行优化: 1. 增加成交量的突破过滤,确保突破的真实性。 2. 加入趋势判断指标,避免在趋势末期建仓。 3. 结合更多时间周期判断突破时机。 4. 增加机器学习算法,动态优化参数。 5. 组合其他策略,实施统计套利。

总结

双海龟突破策略综合运用双周期技术、突破理论和严格的风险管理手段,在保持高胜率的同时也确保收益的稳定性。该策略模型简单清晰,易于理解与应用,是一款非常出色的量化策略。本策略还具有很大的优化空间,投资者可以在此基础上进行创新,打造更加出色的交易系统。

策略源码
/*backtest
start: 2022-11-21 00:00:00
end: 2023-11-27 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=3
strategy(title = "Turtle soup plus one", shorttitle = "Turtle soup plus one", overlay=true)

bigPeriod = input(20)
smallPeriod = input(4)
takeProfitBars = input(0)
trailingStop = input(5, title = "Trailing stop percentages")
if (strategy.position_size == 0)
    strategy.cancel("Long")
    strategy.cancel("Short")
    strategy.cancel("Stop")



stopLossPrice = 0.1
stopLossPrice := nz(stopLossPrice[1])
takeProfitStarted = false
takeProfitStarted := nz(takeProfitStarted[1])

prevHigh = highest(high, bigPeriod - smallPeriod)[smallPeriod]
smallPeriodHigh = highest(high, smallPeriod - 1)[1]
if (high > prevHigh and prevHigh > smallPeriodHigh and close > prevHigh and strategy.position_size == 0)
    strategy.order("Short", strategy.short, stop = prevHigh)

if strategy.position_size < 0 and strategy.position_size[1] == 0
    stopLossPrice := high[1]
    strategy.order("Stop", strategy.long, qty = -strategy.position_size, stop = stopLossPrice)
    takeProfitStarted := false

if (strategy.position_size < 0 and sum(strategy.position_size, takeProfitBars) == strategy.position_size * takeProfitBars and close < strategy.position_avg_price and not takeProfitStarted)
    takeProfitStarted := true
    strategy.cancel("Stop")
    strategy.order("ExitHalf", strategy.long, qty = ceil(-strategy.position_size / 2), stop = close)
    if (strategy.position_size != -1)
        strategy.exit("ExitFull", "Short", qty = -strategy.position_size - ceil(-strategy.position_size / 2), loss = stopLossPrice, trail_price  = close, trail_offset = -(close - strategy.position_avg_price) * trailingStop / 100 / syminfo.mintick)
        

prevLow = lowest(low, bigPeriod - smallPeriod)[smallPeriod]
smallPeriodLow = lowest(low, smallPeriod - 1)[1]
if (low < prevLow and prevLow < smallPeriodLow and close < prevLow and strategy.position_size == 0)
    strategy.order("Long", strategy.long, stop = prevLow)

if strategy.position_size > 0 and strategy.position_size[1] == 0
    stopLossPrice := low[1]
    strategy.order("Stop", strategy.short, qty = strategy.position_size, stop = stopLossPrice)
    takeProfitStarted := false

if (strategy.position_size > 0 and sum(strategy.position_size, takeProfitBars) == strategy.position_size * takeProfitBars and close > strategy.position_avg_price and not takeProfitStarted)
    takeProfitStarted := true
    strategy.cancel("Stop")
    strategy.order("ExitHalf", strategy.short, qty = ceil(strategy.position_size / 2), stop = close)
    if (strategy.position_size != 1)
        strategy.exit("ExitFull", "Long", qty = strategy.position_size - ceil(strategy.position_size / 2),loss = stopLossPrice, trail_price  = close, trail_offset = (close - strategy.position_avg_price) * trailingStop / 100 / syminfo.mintick)

// === Backtesting Dates ===
testPeriodSwitch = input(false, "Custom Backtesting Dates")
testStartYear = input(2018, "Backtest Start Year")
testStartMonth = input(3, "Backtest Start Month")
testStartDay = input(6, "Backtest Start Day")
testStartHour = input(08, "Backtest Start Hour")
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay,testStartHour,0)
testStopYear = input(2038, "Backtest Stop Year")
testStopMonth = input(12, "Backtest Stop Month")
testStopDay = input(14, "Backtest Stop Day")
testStopHour = input(14, "Backtest Stop Hour")
testPeriodStop = timestamp(testStopYear,testStopMonth,testStopDay,testStopHour,0)
testPeriod() =>
    time >= testPeriodStart and time <= testPeriodStop ? true : false
isPeriod = testPeriodSwitch == true ? testPeriod() : true
// === /END
if not isPeriod
    strategy.cancel_all()
    strategy.close_all()