Chiến lược đảo ngược trung bình động kép

Tác giả:ChaoZhang, Ngày: 2023-11-17 16:56:24
Tags:

img

Tổng quan

Chiến lược đảo ngược trung bình động kép là một chiến lược giao dịch đảo ngược trung bình ngắn hạn điển hình. Chiến lược tạo ra tín hiệu giao dịch bằng hai đường trung bình động với các thiết lập tham số khác nhau. Nó nhằm mục đích kiếm lợi nhuận khi sự đảo ngược xu hướng xảy ra.

Chiến lược logic

Chiến lược này sử dụng hai đường trung bình động để tạo ra tín hiệu giao dịch. Mở MA đầu tiên được sử dụng để xác định hướng xu hướng. Mở MA thứ hai được sử dụng để tạo ra tín hiệu giao dịch.

Khi maopening tăng, nó chỉ ra thị trường hiện tại đang trong xu hướng tăng. Khi maopening giảm, nó chỉ ra thị trường hiện tại đang trong xu hướng giảm. maclosing được nhân với một hệ số lớn hơn 1 để làm cho nó nhạy cảm hơn để tạo ra các tín hiệu đảo ngược sớm.

Cụ thể, khi maopening tăng và maclosing vượt qua dưới maopening, nó cho thấy một sự đảo ngược xu hướng. Chiến lược sẽ mở vị trí ngắn. Khi maopening giảm và maclosing vượt qua trên maopening, nó cho thấy một sự đảo ngược xu hướng. Chiến lược sẽ mở vị trí dài.

Các thông số của chiến lược bao gồm loại MA, độ dài, nguồn dữ liệu vv. Hiệu suất giao dịch có thể được tối ưu hóa bằng cách điều chỉnh các thông số này.

Phân tích lợi thế

Những lợi thế chính của Chiến lược đảo ngược hai MA là:

  1. Lượng rút ngắn, phù hợp với giao dịch ngắn hạn.

  2. Dễ dàng thực hiện và dễ hiểu.

  3. Rất dễ cấu hình với nhiều thông số điều chỉnh. Các thông số của hai MAs và hệ số có thể được tối ưu hóa.

  4. Dễ dàng tự động hóa với luồng logic rõ ràng.

  5. Rủi ro có thể kiểm soát được với cơ chế dừng lỗ.

Phân tích rủi ro

Ngoài ra còn có một số rủi ro của chiến lược:

  1. Sự chậm trễ của các tín hiệu giao thoa MA. Các MAs chính nó tụt lại phía sau giá. Sự giao thoa có thể xảy ra sau khi xu hướng đã đảo ngược trong một thời gian.

  2. Rủi ro của các giao dịch whipsaw. xu hướng đảo ngược có thể nhanh chóng đảo ngược lại, gây ra tổn thất liên tiếp.

  3. Mặc dù dừng lỗ hạn chế lỗ duy nhất, nhưng dừng lỗ liên tục vẫn có thể dẫn đến giảm lớn.

  4. Rủi ro quá phù hợp: Tối ưu hóa tham số quá mức có thể dẫn đến quá phù hợp và hiệu suất kém trong giao dịch trực tiếp.

Các giải pháp bao gồm:

  1. Tối ưu hóa các thông số để tìm ra các MAs nhanh hơn.

  2. Thêm các bộ lọc, như chỉ số khối lượng và biến động, để tránh giao dịch whipsaw.

  3. Điều chỉnh vị trí dừng lỗ để giảm xác suất dừng lỗ liên tiếp.

  4. Kiểm tra độ bền của các bộ tham số để đánh giá rủi ro quá cố.

Hướng dẫn cải thiện

Chiến lược có thể được tối ưu hóa thêm trong các khía cạnh sau:

  1. Kiểm tra các loại MAs khác nhau để tìm những loại nhạy cảm hơn, như KAMA, ZLEMA v.v.

  2. Tối ưu hóa độ dài MA để tìm sự kết hợp tối ưu. Thông thường thời gian ngắn hơn có hiệu suất tốt hơn.

  3. Kiểm tra các nguồn dữ liệu khác nhau, chẳng hạn như giá gần, giá trung bình, giá điển hình v.v.

  4. Thêm bộ lọc xu hướng để tránh các tín hiệu đảo ngược không phù hợp, như kênh Donchian.

  5. Thêm các chỉ số khác để xác nhận, như MACD, OBV vv

  6. Cải thiện các cơ chế quản lý rủi ro, chẳng hạn như di chuyển dừng lỗ, lỗ tài khoản tối đa vv

  7. Tối ưu hóa danh mục đầu tư để tìm ra phân bổ tài sản tối ưu.

  8. Kiểm tra độ bền của các thông số để đánh giá rủi ro quá phù hợp.

Kết luận

Phản hồi MA kép là một chiến lược giao dịch ngắn hạn đơn giản và thực tế. Nó phù hợp để nắm bắt các sự đảo ngược ngắn hạn với giao dịch định lượng. Tuy nhiên, có những rủi ro như trượt và giao dịch chích. Chiến lược có thể được cải thiện bằng cách tối ưu hóa các tham số, thêm bộ lọc, tăng cường kiểm soát rủi ro vv để phát triển một chiến lược ổn định và hiệu quả với hiệu suất giao dịch thực sự tốt.


/*backtest
start: 2023-10-17 00:00:00
end: 2023-11-16 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
strategy(title = "hamster-bot MRS 2", overlay = true, default_qty_type = strategy.percent_of_equity, initial_capital = 100, default_qty_value = 100, pyramiding = 9, commission_value = 0.045, backtest_fill_limits_assumption = 1)
info_options = "Options"

on_close = input(false, title = "Entry on close", inline=info_options, group=info_options)
OFFS = input.int(0, minval = 0, maxval = 1, title = "| Offset View", inline=info_options, group=info_options)
trade_offset = input.int(0, minval = 0, maxval = 1, title = "Trade", inline=info_options, group=info_options)
use_kalman_filter = input.bool(false, title="Use Kalman filter", group=info_options)

//MA Opening
info_opening = "MA Opening"
maopeningtyp = input.string("SMA", title="Type", options=["SMA", "EMA", "TEMA", "DEMA", "ZLEMA", "WMA", "Hma", "Thma", "Ehma", "H", "L", "DMA"], title = "", inline=info_opening, group=info_opening)
maopeningsrc = input.source(ohlc4, title = "", inline=info_opening, group=info_opening)
maopeninglen = input.int(3, minval = 1, maxval = 200, title = "", inline=info_opening, group=info_opening)

//MA Closing
info_closing = "MA Closing"
maclosingtyp = input.string("SMA", title="Type", options=["SMA", "EMA", "TEMA", "DEMA", "ZLEMA", "WMA", "Hma", "Thma", "Ehma", "H", "L", "DMA"], title = "", inline=info_closing, group=info_closing)
maclosingsrc = input.source(ohlc4, title = "", inline=info_closing, group=info_closing)
maclosinglen = input.int(3, minval = 1, maxval = 200, title = "", inline=info_closing, group=info_closing)
maclosingmul = input.float(1, step = 0.005, title = "mul", inline=info_closing, group=info_closing)

long1on    = input(true, title = "", inline = "long1")
long1shift = input.float(0.96, step = 0.005, title = "Long", inline = "long1")
long1lot   = input.int(10, minval = 0, maxval = 10000, step = 10, title = "Lot 1", inline = "long1")
short1on    = input(true, title = "", inline = "short1")
short1shift = input.float(1.04, step = 0.005, title = "short", inline = "short1")
short1lot   = input.int(10, minval = 0, maxval = 10000, step = 10, title = "Lot 1", inline = "short1")
startTime = input(timestamp("01 Jan 2010 00:00 +0000"), "Start date", inline = "period")
finalTime = input(timestamp("31 Dec 2030 23:59 +0000"), "Final date", inline = "period")

HMA(_src, _length) =>  ta.wma(2 * ta.wma(_src, _length / 2) - ta.wma(_src, _length), math.round(math.sqrt(_length)))
EHMA(_src, _length) =>  ta.ema(2 * ta.ema(_src, _length / 2) - ta.ema(_src, _length), math.round(math.sqrt(_length)))
THMA(_src, _length) =>  ta.wma(ta.wma(_src,_length / 3) * 3 - ta.wma(_src, _length / 2) - ta.wma(_src, _length), _length)
tema(sec, length)=>
    tema1= ta.ema(sec, length)
    tema2= ta.ema(tema1, length)
    tema3= ta.ema(tema2, length)
    tema_r = 3*tema1-3*tema2+tema3
donchian(len) => math.avg(ta.lowest(len), ta.highest(len))
ATR_func(_src, _len)=>
    atrLow = low - ta.atr(_len)
    trailAtrLow = atrLow
    trailAtrLow := na(trailAtrLow[1]) ? trailAtrLow : atrLow >= trailAtrLow[1] ? atrLow : trailAtrLow[1]
    supportHit = _src <= trailAtrLow
    trailAtrLow := supportHit ? atrLow : trailAtrLow
    trailAtrLow
f_dema(src, len)=>
    EMA1 = ta.ema(src, len)
    EMA2 = ta.ema(EMA1, len)
    DEMA = (2*EMA1)-EMA2
f_zlema(src, period) =>
    lag = math.round((period - 1) / 2)
    ema_data = src + (src - src[lag])
    zl= ta.ema(ema_data, period)
f_kalman_filter(src) =>
    float value1= na
    float value2 = na
    value1 := 0.2 * (src - src[1]) + 0.8 * nz(value1[1])
    value2 := 0.1 * (ta.tr) + 0.8 * nz(value2[1])
    lambda = math.abs(value1 / value2)
    alpha = (-math.pow(lambda, 2) + math.sqrt(math.pow(lambda, 4) + 16 * math.pow(lambda, 2)))/8
    value3 = float(na)
    value3 := alpha * src + (1 - alpha) * nz(value3[1])
//SWITCH
ma_func(modeSwitch, src, len, use_k_f=true) =>
      modeSwitch == "SMA"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.sma(src, len))  : ta.sma(src, len) :
      modeSwitch == "RMA"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.rma(src, len))  : ta.rma(src, len) :
      modeSwitch == "EMA"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.ema(src, len))  : ta.ema(src, len) :
      modeSwitch == "TEMA"  ? use_kalman_filter and use_k_f ? f_kalman_filter(tema(src, len))    : tema(src, len):
      modeSwitch == "DEMA"  ? use_kalman_filter and use_k_f ? f_kalman_filter(f_dema(src, len))  : f_dema(src, len):
      modeSwitch == "ZLEMA" ? use_kalman_filter and use_k_f ? f_kalman_filter(f_zlema(src, len)) : f_zlema(src, len):
      modeSwitch == "WMA"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.wma(src, len))  : ta.wma(src, len):
      modeSwitch == "VWMA"  ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.vwma(src, len)) : ta.vwma(src, len):
      modeSwitch == "Hma"   ? use_kalman_filter and use_k_f ? f_kalman_filter(HMA(src, len))     : HMA(src, len):
      modeSwitch == "Ehma"  ? use_kalman_filter and use_k_f ? f_kalman_filter(EHMA(src, len))    : EHMA(src, len):
      modeSwitch == "Thma"  ? use_kalman_filter and use_k_f ? f_kalman_filter(THMA(src, len/2))  : THMA(src, len/2):
      modeSwitch == "ATR"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ATR_func(src, len)): ATR_func(src, len) :
      modeSwitch == "L"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.lowest(len)): ta.lowest(len) :
      modeSwitch == "H"   ? use_kalman_filter and use_k_f ? f_kalman_filter(ta.highest(len)): ta.highest(len) :
      modeSwitch == "DMA"   ? donchian(len) : na

//Var
sum = 0.0
maopening = 0.0
maclosing = 0.0
os = maopeningsrc
cs = maclosingsrc
pos = strategy.position_size
p = 0.0
p := pos == 0 ? (strategy.equity / 100) / close : p[1]
truetime = true
loss = 0.0
maxloss = 0.0
equity = 0.0

//MA Opening
maopening := ma_func(maopeningtyp, maopeningsrc, maopeninglen)

//MA Closing
maclosing := ma_func(maclosingtyp, maclosingsrc, maclosinglen) * maclosingmul

long1 = long1on == false ? 0 : long1shift == 0 ? 0 : long1lot == 0 ? 0 : maopening == 0 ? 0 : maopening * long1shift
short1 = short1on == false ? 0 : short1shift == 0 ? 0 : short1lot == 0 ? 0 : maopening == 0 ? 0 : maopening * short1shift
//Colors
maopeningcol = maopening == 0 ? na : color.blue
maclosingcol = maclosing == 0 ? na : color.fuchsia
long1col = long1 == 0 ? na : color.green
short1col = short1 == 0 ? na : color.red
//Lines
plot(maopening, offset = OFFS, color = maopeningcol)
plot(maclosing, offset = OFFS, color = maclosingcol)
long1line = long1 == 0 ? close : long1
short1line = short1 == 0 ? close : short1
plot(long1line, offset = OFFS, color = long1col)
plot(short1line, offset = OFFS, color = short1col)

//Lots
lotlong1 = p * long1lot
lotshort1 = p * short1lot

//Entry
if maopening > 0 and maclosing > 0 and truetime
    //Long
    sum := 0
    strategy.entry("L", strategy.long, lotlong1, limit = on_close ? na : long1, when = long1 > 0 and pos <= sum and (on_close ? close <= long1[trade_offset] : true))
    sum := lotlong1

    //Short
    sum := 0
    pos := -1 * pos
    strategy.entry("S", strategy.short, lotshort1, limit = on_close ? na : short1, when = short1 > 0 and pos <= sum and (on_close ? close >= short1[trade_offset] : true))
    sum := lotshort1

strategy.exit("Exit", na, limit = maclosing)
if time > finalTime
    strategy.close_all()

Thêm nữa