
Đây là một chiến lược giao dịch định lượng sử dụng đường trung bình di chuyển và chỉ số MACD để thực hiện các hoạt động phá vỡ hai chiều. Nó có đặc điểm hoạt động xuyên thời gian, đó là đánh giá hướng xu hướng trong chu kỳ thời gian dài hơn và tìm kiếm lợi thế trong cơ hội vào trong chu kỳ thời gian ngắn hơn.
Chiến lược này sử dụng 3 đường trung bình SMMA với các độ dài khác nhau và một đường trung bình EMA để xác định xu hướng. Đồng thời, nó kết hợp với chỉ số MACD để xác định xu hướng ngắn hạn và thời gian nhập. Cụ thể, điều kiện mua của nó là: giá vượt qua tất cả đường trung bình và đường trung bình ngắn được kích hoạt trên đường trung bình dài; và điều kiện bán ngược lại, giá vượt qua tất cả đường trung bình và đường trung bình ngắn được kích hoạt dưới đường trung bình dài.
Có thể thấy rằng chiến lược này đồng thời sử dụng moving average để xác định hướng xu hướng trung hạn và dài hạn, và MACD để xác định thời gian chuyển đổi ngắn hạn để nắm bắt thời điểm nhập cảnh thuận lợi. Hoạt động kết hợp đa thời gian này là một tính năng quan trọng của chiến lược.
Ưu điểm của hoạt động xuyên thời gian này là có thể chọn điểm quay vòng ngắn hạn phù hợp trong hướng xu hướng có xác suất cao, do đó có thể nhận được lợi nhuận rủi ro tốt hơn. Cụ thể, có 3 lợi thế chính sau:
3 đường trung bình SMMA cộng với 1 đường trung bình EMA có nhiều sóng, có thể xác định hiệu quả hướng xu hướng trung và dài hạn, tránh hoạt động ngược.
Chỉ số MACD đánh giá điểm đảo chiều ngắn hạn để có được giá nhập cảnh tốt hơn.
Các mối quan hệ thứ tự trung bình di chuyển nghiêm ngặt được sử dụng như một điều kiện lọc, có thể làm giảm khả năng sai lệch.
Những rủi ro chính của chiến lược này là:
Các trung bình di chuyển tự nó có tính chậm trễ và có thể bỏ lỡ cơ hội đảo ngược xu hướng ngắn hạn.
Chỉ số MACD dễ tạo ra các tín hiệu giả, cần kết hợp với bộ lọc giá.
Các phán đoán theo nhiều thời gian làm tăng sự phức tạp của chiến lược, dễ gây ra sự thất bại.
Đối với rủi ro 1 và rủi ro 2, có thể tối ưu hóa bằng cách rút ngắn đúng chu kỳ đường trung bình và chu kỳ tín hiệu, phản ứng nhanh chóng với sự đảo ngược xu hướng ngắn hạn. Đối với rủi ro 3, cần phải thử nghiệm tối ưu hóa cho các giống và chu kỳ khác nhau, để tham số chiến lược phù hợp với đặc điểm của giống.
Chiến lược này có thể được tối ưu hóa từ các khía cạnh sau:
Tối ưu hóa các tham số của đường trung bình di chuyển và MACD để phù hợp nhất với các tính năng khác nhau của chu kỳ và giống. Ví dụ: rút ngắn chiều dài đường trung bình, tăng tham số Signal, v.v.
Thêm chiến lược dừng lỗ, sử dụng ATR hoặc các chỉ số khác để thiết lập dừng di chuyển hợp lý. Điều này có thể cải thiện đáng kể việc kiểm soát rủi ro của chiến lược.
Tìm kiếm các chỉ số hoặc cách lọc tốt hơn để thay thế các tín hiệu MACD. Ví dụ: giới thiệu các chỉ số tỷ lệ dao động, lọc các tín hiệu.
Kiểm tra các mối quan hệ tỷ lệ dừng và mất mát khác nhau để có được một sự kết hợp các tham số tốt hơn so với rủi ro và lợi nhuận.
Nhìn chung, đây là một hệ thống đột phá với tư duy xuyên thời gian độc đáo. Nó sử dụng lợi thế của đường trung bình di chuyển và MACD để thực hiện chiến lược hoạt động phán đoán hợp tác trong nhiều khoảng thời gian. Bằng cách điều chỉnh tối ưu các tham số và điều kiện lọc, chiến lược này có thể trở thành một chương trình giao dịch định lượng rất thực tế.
/*backtest
start: 2023-10-22 00:00:00
end: 2023-11-21 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © SoftKill21
//@version=4
strategy("Koala Script",initial_capital=1000,
commission_type=strategy.commission.cash_per_contract,
commission_value=0.000065,
slippage=3)
fromDay = input(defval = 1, title = "From Day", minval = 1, maxval = 31)
fromMonth = input(defval = 1, title = "From Month", minval = 1, maxval = 12)
fromYear = input(defval = 2000, title = "From Year", minval = 1970)
// To Date Inputs
toDay = input(defval = 1, title = "To Day", minval = 1, maxval = 31)
toMonth = input(defval = 8, title = "To Month", minval = 1, maxval = 12)
toYear = input(defval = 2031, title = "To Year", minval = 1970)
startDate = timestamp(fromYear, fromMonth, fromDay, 00, 00)
finishDate = timestamp(toYear, toMonth, toDay, 00, 00)
len = input(3, minval=1, title="Length")
src = input(hl2, title="Source")
smma = 0.0
sma1 = sma(src, len)
smma := na(smma[1]) ? sma1 : (smma[1] * (len - 1) + src) / len
len2 = input(6, minval=1, title="Length")
src2 = input(hl2, title="Source")
smma2 = 0.0
sma2 = sma(src2, len2)
smma2 := na(smma2[1]) ? sma2 : (smma2[1] * (len2 - 1) + src2) / len2
len3 = input(9, minval=1, title="Length")
src3 = input(hl2, title="Source")
smma3 = 0.0
sma3 = sma(src3, len3)
smma3 := na(smma3[1]) ? sma3 : (smma3[1] * (len3 - 1) + src3) / len3
len4 = input(50, minval=1, title="Length")
src4 = input(close, title="Source")
smma4 = 0.0
sma4 = sma(src4, len4)
smma4 := na(smma4[1]) ? sma4 : (smma4[1] * (len4 - 1) + src4) / len4
len5 = input(200, minval=1, title="Length")
src5 = input(close, title="Source")
out5 = ema(src5, len5)
timeinrange(res, sess) => time(res, sess) != 0
london=timeinrange(timeframe.period, "0300-1045")
londonEntry=timeinrange(timeframe.period, "0300-0845")
time_cond = time >= startDate and time <= finishDate and londonEntry
fast_length = input(title="Fast Length", type=input.integer, defval=12)
slow_length = input(title="Slow Length", type=input.integer, defval=26)
srcc = input(title="Source", type=input.source, defval=close)
signal_length = input(title="Signal Smoothing", type=input.integer, minval = 1, maxval = 50, defval = 9)
sma_source = input(title="Simple MA(Oscillator)", type=input.bool, defval=false)
sma_signal = input(title="Simple MA(Signal Line)", type=input.bool, defval=false)
// Calculating
fast_ma = sma_source ? sma(srcc, fast_length) : ema(srcc, fast_length)
slow_ma = sma_source ? sma(srcc, slow_length) : ema(srcc, slow_length)
macd = fast_ma - slow_ma
signal = sma_signal ? sma(macd, signal_length) : ema(macd, signal_length)
hist = macd - signal
longCond = close > out5 and close > smma4 and close > smma3 and close > smma2 and close > smma and londonEntry and smma > smma2 and smma2>smma3 and smma3>smma4 and smma4>out5
shortCond = close < out5 and close < smma4 and close < smma3 and close < smma2 and close < smma and londonEntry and smma < smma2 and smma2<smma3 and smma3<smma4 and smma4<out5
//longCond2 = crossover(close,out5) and crossover(close,smma4) and crossover(close,smma3) and crossover(close,smma2) and crossover(close,smma) and time_cond
//shortCond2 = crossunder(close,out5) and crossunder(close,smma4) and crossunder(close,smma3) and crossunder(close,smma2) and crossunder(close,smma) and time_cond
length=input(14, title="ATR Length")
mult=input(1.0, title="Percentage Multiplier (for ex., 0.7 = 70%)", step=0.1, minval=0.1, maxval=5.0)
oa=input(false, title="Show actual ATR")
ii=syminfo.pointvalue==0
s=ii?na:oa?atr(length):(syminfo.pointvalue * mult * atr(length))
tp=input(300,title="tp")
sl=input(300,title="sl")
//tp = s*10000
//sl= s*10000
//if(tp>300)
// tp:=300
//if(sl>300)
// sl:=300
//if(sl<150)
// sl:=150
//if(tp<150)
// tp:=150
strategy.initial_capital = 50000
//MONEY MANAGEMENT--------------------------------------------------------------''
balance = strategy.netprofit + strategy.initial_capital //current balance
floating = strategy.openprofit //floating profit/loss
risk = input(3,type=input.float,title="Risk %")/100 //risk % per trade
//Calculate the size of the next trade
temp01 = balance * risk //Risk in USD
temp02 = temp01/sl //Risk in lots
temp03 = temp02*100000 //Convert to contracts
size = temp03 - temp03%1000 //Normalize to 1000s (Trade size)
if(size < 10000)
size := 10000 //Set min. lot size
strategy.entry("long",1,when=longCond )
strategy.exit("closelong","long", profit=tp,loss=sl)
//strategy.close("long",when= crossunder(close[4],smma4) and close[4] > close[3] and close[3]>close[2] and close[2] > close[1] and close[1] > close)
strategy.entry("short",0,when=shortCond )
strategy.exit("closeshort","short", profit=tp,loss=sl)
//strategy.close("short",when= crossover(close[4],smma4) and close[4] < close[3] and close[3]< close[2] and close[2] < close[1] and close[1] < close)
strategy.close_all(when = not london)
maxEntry=input(2,title="max entries")
// strategy.risk.max_intraday_filled_orders(maxEntry)