
Đây là một chiến lược theo dõi xu hướng dựa trên đường trung bình di chuyển cân bằng một lần. Nó kết hợp đường trung bình, đường trung bình di chuyển cân bằng một lần và cơ chế xuất cảnh chính xác để tăng tỷ lệ lợi nhuận.
Chiến lược này chủ yếu xây dựng một đường trung bình di chuyển cân bằng bằng mắt bằng cách tính toán giá đóng cửa vào ngày giao dịch cuối cùng và các tham số đầu vào được xác định bởi người dùng. Khi giá tăng vượt qua đường trung bình, hãy làm nhiều hơn; Khi giá giảm vượt qua đường trung bình, hãy bỏ đi.
Trong khi đó, chiến lược này đã thêm một cơ chế xác nhận đám mây để xác định màu trung bình chuyển động cân bằng một lần. Chỉ làm nhiều khi màu trung bình chuyển động cân bằng một lần là màu xanh lá cây và trống khi màu đỏ, điều này có thể lọc ra một số tín hiệu không chính xác, cải thiện khả năng chiến lược có lợi nhuận.
Ưu điểm lớn nhất của chiến lược này là kết hợp lợi thế của hai chỉ số đường trung bình và đường trung bình di chuyển cân bằng, xem xét cả xu hướng tổng thể của đường trung bình giá cả và chú ý đến sự thay đổi phần trăm của giá đóng cửa vào ngày giao dịch cuối cùng. Ngoài ra, cơ chế xác nhận đám mây cũng có thể tránh tín hiệu giao dịch giả, do đó tăng sự ổn định của chiến lược.
Trong việc tối ưu hóa các tham số, thiết lập dừng lỗ cũng giúp kiểm soát rủi ro của chiến lược này. Cuối cùng, các chỉ số kỹ thuật mới, nhiều người chưa quen thuộc với các chỉ số chuyển động trung bình cân bằng, mang lại lợi thế cho việc áp dụng chiến lược.
Rủi ro lớn nhất của chiến lược này nằm ở sự không ổn định của bản thân đường trung bình di chuyển cân bằng. Là một chỉ số mới, hiệu quả lâu dài của nó và không gian tối ưu hóa tham số vẫn còn được thảo luận. Nếu mô hình giả định không hiệu quả, sẽ tạo ra một số lượng lớn tín hiệu sai.
Ngoài ra, bất kỳ chiến lược theo dõi xu hướng nào cũng có nguy cơ đảo ngược xu hướng. Chiến lược này sẽ bị mất nhiều khi giá vượt qua đường trung bình nhưng nhanh chóng điều chỉnh. Vì vậy, thiết lập điểm dừng là rất quan trọng.
Chiến lược này có thể được tối ưu hóa thêm bằng cách:
Tối ưu hóa tham số length của trung bình di chuyển cân bằng một lần để tìm điểm cân bằng tốt nhất.
Kiểm tra các thiết lập tham số dừng lỗ khác nhau để xác định sự kết hợp tham số tối ưu. Mức dừng quá lớn sẽ giới hạn mức lợi nhuận, và mức dừng lỗ quá nhỏ có nguy cơ quá lớn.
Thêm các chỉ số kỹ thuật khác, chẳng hạn như MACD, KD, v.v., để tạo ra sự đồng thuận đa chỉ số, tránh thêm tín hiệu sai.
Phân tích lại các giống và chu kỳ khác nhau để xác định các tình huống chiến lược tốt nhất.
Xem xét thêm mô hình học máy để thực hiện tối ưu hóa động của tham số và điều chỉnh tùy chỉnh của chiến lược.
Chiến lược này tích hợp các lợi thế của đường trung bình và đường trung bình di chuyển cân bằng, thiết lập các điểm dừng lỗ hợp lý và thêm các cơ chế xác nhận đám mây, có thể theo dõi xu hướng hiệu quả, kiểm soát rủi ro. Chiến lược này có thể được áp dụng rộng rãi cho các giống như chỉ số cổ phiếu, ngoại hối, hàng hóa và tiền điện tử, là một bộ chiến lược định lượng đáng được đề xuất.
/*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))