
这是一个基于一目均衡移动平均线的趋势追踪策略。它融合了均线、川Fusion一目均衡移动平均线及精准入场出场机制,旨在提高盈利率。
该策略主要通过计算最后一个交易日的收盘价及用户定义的输入参数,构建出一目均衡移动平均线。当价格上涨突破均线时,做多;当价格下跌突破均线时,做空。并设定止损止盈价格,在达到条件时止损或止盈。
同时,该策略增加了一目均衡移动平均线颜色判定的云确认机制。只有当一目均衡移动平均线颜色为绿色时才做多,颜色为红色时才做空,这可以过滤掉部分不精准的信号,提高策略获利概率。
该策略最大的优势在于结合了均线和一目均衡移动平均线两个指标的优点,既考虑了价格平均线的整体走势,又关注最后一个交易日收盘价的分量变动。此外,云确认机制也可避免交易假信号,从而提高策略稳定性。
在参数优化方面,止损止盈设置也让该策略风险可控。最后,一目均衡移动平均线作为较新的技术指标,许多人还不熟悉,这为该策略应用带来先发优势。
该策略最大的风险在于一目均衡移动平均线本身的不稳定性。作为新的指标,它的长期有效性和 parameter 优化空间都有待商榷。如果模型假设失效,则会产生大量错误信号。
此外,任何追踪趋势的策略都面临着趋势反转的风险。当价格突破均线但很快调头时,该策略就会遭遇较大亏损。所以,止损点的设置十分关键。
该策略可通过以下方式获得进一步优化:
对一目均衡移动平均线的 length 参数进行优化,找到最佳平衡点。
测试不同的止损止盈参数设置,确定最优参数组合。过大的止盈幅度会限制收益上限,过小的止损幅度则风险过大。
增加其他技术指标判断,例如 MACD、KD 等,形成多指标共识,进一步避免错误信号。
对不同品种、周期进行回测,确定最佳策略适用场景。
考虑加入机器学习模型,实现参数的动态优化和策略的自适应调整。
本策略整合均线和一目均衡移动平均线的优势,设置合理的止损止盈,并增加云确认机制,可有效追踪趋势,控制风险。该策略可广泛应用于股指、外汇、商品及加密货币等品种,是一套值得推荐的量化策略。
/*backtest
start: 2022-11-17 00:00:00
end: 2023-11-23 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
strategy("Ichimoku Backtester with TP and SL", overlay=true,
currency = currency.USD, default_qty_type = strategy.percent_of_equity,
default_qty_value = 95)
//@version=4
//Inputs
ts_bars = input(9, minval=1, title="Tenkan-Sen Bars")
ks_bars = input(26, minval=1, title="Kijun-Sen Bars")
ssb_bars = input(52, minval=1, title="Senkou-Span B Bars")
cs_offset = input(26, minval=1, title="Chikou-Span Offset")
ss_offset = input(26, minval=1, title="Senkou-Span Offset")
long_entry = input(true, title="Long Entry")
short_entry = input(true, title="Short Entry")
wait_for_cloud = input(true, title="Wait for Cloud Confirmation")
use_short_stop_loss = input(true, title="Use Short Stop Loss")
short_stop_loss = input(title="Short Stop Loss (%)", type=input.float, minval=0.0, step=0.1,
defval=5) * 0.01
use_long_stop_loss = input(true, title="Use Long Stop Loss")
long_stop_loss = input(title="Long Stop Loss (%)", type=input.float, minval=0.0, step=0.1,
defval=5) * 0.01
use_short_take_profit = input(true, title="Use Short Take Profit")
short_take_profit = input(title="Short Take Profit (%)", type=input.float, minval=0.0, step=0.1,
defval = 20) * .01
use_long_take_profit = input(true, title="Use Long Take Profit")
long_take_profit = input(title="Long Take Profit (%)", type=input.float, minval=0.0, step=0.1,
defval = 20) * .01
// === INPUT SHOW PLOT ===
showDate = input(defval = false, title = "Show Date Range", type = input.bool)
// === INPUT BACKTEST RANGE ===
fromMonth = input(defval = 1, title = "From Month", type = input.integer, minval = 1, maxval = 12)
fromDay = input(defval = 1, title = "From Day", type = input.integer, minval = 1, maxval = 31)
fromYear = input(defval = 2020, title = "From Year", type = input.integer, minval = 1970)
thruMonth = input(defval = 1, title = "Thru Month", type = input.integer, minval = 1, maxval = 12)
thruDay = input(defval = 1, title = "Thru Day", type = input.integer, minval = 1, maxval = 31)
thruYear = input(defval = 2112, title = "Thru Year", type = input.integer, minval = 1970)
// === FUNCTION EXAMPLE ===
start = timestamp(fromYear, fromMonth, fromDay, 00, 00) // backtest start window
finish = timestamp(thruYear, thruMonth, thruDay, 23, 59) // backtest finish window
window() => time >= start and time <= finish ? true : false // create function "within window of time"
middle(len) => avg(lowest(len), highest(len))
// Ichimoku Components
tenkan = middle(ts_bars)
kijun = middle(ks_bars)
senkouA = avg(tenkan, kijun)
senkouB = middle(ssb_bars)
bgcolor(color = showDate and window() ? color.gray : na, transp = 90) // plot within time window
// Plot Ichimoku Kinko Hyo
plot(tenkan, color=#0496ff, title="Tenkan-Sen")
plot(kijun, color=#991515, title="Kijun-Sen")
plot(close, offset=-cs_offset+1, color=#459915, title="Chikou-Span")
sa=plot(senkouA, offset=ss_offset-1, color=color.green, title="Senkou-Span A")
sb=plot(senkouB, offset=ss_offset-1, color=color.red, title="Senkou-Span B")
fill(sa, sb, color = senkouA > senkouB ? color.green : color.red, title="Cloud color")
ss_high = max(senkouA[ss_offset-1], senkouB[ss_offset-1])
ss_low = min(senkouA[ss_offset-1], senkouB[ss_offset-1])
// Entry/Exit Signals
tk_cross_bull = tenkan > kijun
tk_cross_bear = tenkan < kijun
cs_cross_bull = mom(close, cs_offset-1) > 0
cs_cross_bear = mom(close, cs_offset-1) < 0
price_above_kumo = close > ss_high
price_below_kumo = close < ss_low
senkou_green = senkouA > senkouB ? true : false
bullish = tk_cross_bull and cs_cross_bull and price_above_kumo
bearish = tk_cross_bear and cs_cross_bear and price_below_kumo
if (wait_for_cloud)
bullish := bullish and senkou_green
bearish := bearish and not senkou_green
longStopPrice = strategy.position_avg_price * (1 - long_stop_loss)
shortStopPrice = strategy.position_avg_price * (1 + short_stop_loss)
longLimitPrice = strategy.position_avg_price * (1 + long_take_profit)
shortLimitPrice = strategy.position_avg_price * (1 - short_take_profit)
in_long = false
in_long := in_long[1]
open_long = bullish and not in_long
open_short = bearish and in_long
if (open_long)
in_long := true
if (open_short)
in_long := false
strategy.entry("Long", strategy.long, when=open_long and long_entry and (showDate ? window() : true))
strategy.entry("Short", strategy.short ,when=open_short and short_entry and (showDate ? window() : true))
if (strategy.position_size > 0.0)
if (use_long_stop_loss and not use_long_take_profit)
strategy.exit("Long", stop = longStopPrice)
if (use_long_take_profit and not use_long_stop_loss)
strategy.exit("Long", limit = longLimitPrice)
if (use_long_take_profit and use_long_stop_loss)
strategy.exit("Long", stop = longStopPrice, limit=longLimitPrice)
if (strategy.position_size < 0.0)
if (use_short_stop_loss and not use_short_take_profit)
strategy.exit("Short", stop = shortStopPrice)
if (use_short_take_profit and not use_short_stop_loss)
strategy.exit("Short", limit = shortLimitPrice)
if (use_short_take_profit and use_short_stop_loss)
strategy.exit("Short", stop = shortStopPrice, limit = shortLimitPrice)
strategy.close("Long", when=bearish and not short_entry and (showDate ? window() : true))
strategy.close("Short", when=bullish and not long_entry and (showDate ? window() : true))