Chiến lược nắm bắt đường trung bình động kép

Tác giả:ChaoZhang, Ngày: 2023-12-13 15:28:50
Tags:

img

Tổng quan

Chiến lược này sử dụng hai đường trung bình động để xác định hướng xu hướng thị trường kết hợp với Bollinger Bands để xác định các điều kiện mua quá mức và bán quá mức, để đạt được mua thấp và bán cao để lấy lợi nhuận.

Chiến lược logic

Chiến lược này sử dụng các đường trung bình động kép để xác định hướng thị trường tổng thể, trong khi dựa vào Bollinger Bands cho các tín hiệu nhập cảnh cụ thể.

Quy tắc trung bình di chuyển kép quy định tính toán đường trung bình di chuyển theo cấp số nhân ngắn hạn và dài hạn, với đường ngắn hạn vượt qua đường dài hạn lên cho thấy tín hiệu mua; đường ngắn hạn đi xuống qua dài hạn tạo thành tín hiệu bán.

Chỉ số Bollinger Bands xác định giá có bị mua quá mức hay bán quá mức. Dải giữa của Bollinger Bands là đường trung bình động của giá đóng cửa n giai đoạn, trong khi chiều rộng dải đại diện cho độ lệch chuẩn của đường trung bình động trong n giai đoạn trước. Giá gần dải trên cho thấy tình trạng mua quá mức và những người gần dải dưới tạo thành tình huống bán quá mức.

Các quy tắc chiến lược được xác định như sau: Khi đường trung bình ngắn vượt qua đường trung bình dài tăng cộng với giá đóng cửa xuyên qua dải trên Bollinger, đi dài. Khi đường ngắn vượt qua đường dài giảm cộng với giá đóng cửa giảm xuống dưới dải dưới Bollinger, đi ngắn.

Stop loss sau khi mua mua được đặt ở mức thấp nhất trong n ngày qua, trong khi take profit được đặt ở mức 1,6 lần giá nhập cảnh.

Ngoài ra, chiến lược xem xét chỉ số xu hướng EMA để tránh sự đảo ngược xu hướng.

Phân tích lợi thế

  1. Sử dụng hai đường trung bình động để xác định hướng tổng thể kết hợp với Bollinger Bands để làm nổi bật các điểm đầu vào cụ thể đại diện cho một sự pha trộn chỉ số hợp lý;
  2. Việc áp dụng mức thấp nhất trong n ngày như là lệnh dừng lỗ cho các giao dịch dài và mức cao nhất trong n ngày như là lệnh dừng lỗ cho các giao dịch ngắn giúp giảm thiểu khả năng lệnh dừng được thực hiện;
  3. Đặt mục tiêu lợi nhuận ở mức gấp 1,6 lần giá nhập cảnh giúp thu được lợi nhuận đầy đủ;
  4. Xem xét chỉ số xu hướng EMA giúp tránh giao dịch chống lại xu hướng chính, giảm lỗ hệ thống.

Phân tích rủi ro

  1. Tối ưu hóa không phù hợp các thông số Bollinger Bands có thể dẫn đến giao dịch quá thường xuyên hoặc tín hiệu không đủ;
  2. Các điểm dừng lỗ quá lỏng dẫn đến tổn thất lớn hơn;
  3. Các hạn chế lợi nhuận quá chặt chẽ sẽ làm mất đi lợi nhuận lớn hơn.

Để giải quyết các rủi ro trên, tối ưu hóa sự kết hợp của các tham số Bollinger và kiểm tra các ngưỡng dừng lỗ / thu lợi nhuận khác nhau để chọn các cài đặt tối ưu.

Hướng tối ưu hóa

  1. Tối ưu hóa các thông số đầu vào Bollinger Bands để xác định kết hợp lý tưởng;
  2. Kiểm tra các tham số tăng stop loss khác nhau để giảm khả năng stop được chạy;
  3. Kiểm tra các giá trị nhân lợi nhuận để nắm bắt lợi nhuận lớn nhất có thể.

Kết luận

Chiến lược này đã hoạt động đáng tin cậy trong các bài kiểm tra ngược bằng cách xác nhận xu hướng tổng thể bằng cách sử dụng đường trung bình động kép và dựa trên các băng tần Bollinger cho các tín hiệu đầu vào cụ thể. Các cải tiến hiệu suất bổ sung có thể được dự đoán thông qua tối ưu hóa tham số liên tục và sửa đổi quy tắc. Cơ chế dừng lỗ / lấy lợi nhuận cũng có thể chuyển sang các hệ thống khác để thích nghi.


/*backtest
start: 2023-12-05 00:00:00
end: 2023-12-06 22:00:00
period: 15m
basePeriod: 5m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

// This close code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © AugustoErni

//@version=5
strategy('Bollinger Bands Modified (Stormer)', overlay=true)

bbL                   = input.int(20, title='BB Length/Comprimento da Banda de Bollinger', minval=1, step=1, tooltip='Calculate the length of bollinger bands./Calcula o comprimento das bandas de bollinger.')
mult                  = input.float(0.38, title='BB Standard Deviation/Desvio Padrão da Banda de Bollinger', minval=0.01, step=0.01, tooltip='Calculate the standard deviation of bollinger bands./Calcula o desvio padrão das bandas de bollinger.')
emaL                  = input.int(80, title='EMA Length/Comprimento da Média Móvel Exponencial', minval=1, step=1, tooltip='Calculate the length of EMA./Calcula o comprimento da EMA.')
highestHighL          = input.int(7, title='Highest High Length/Comprimento da Alta Maior', minval=1, step=1, tooltip='Fetches the highest high candle from length input. Use to set stop loss for short position./Obtém a vela de maior alta com base na medida fornecida. Usa para definir o stop loss para uma posição curta.')
lowestLowL            = input.int(7, title='Lowest Low Length/Comprimento da Baixa Menor', minval=1, step=1, tooltip='Fetches the lowest low candle from length input. Use to set stop loss for long position./Obter a vela de menor baixa com base na medida fornecida. Usa para definir o stop loss para uma posição longa.')
targetFactor          = input.float(1.6, title='Target Take Profit/Objetivo de Lucro Alvo', minval=0.1, step=0.1, tooltip='Calculate the take profit factor when entry position./Calcula o fator do alvo lucro ao entrar na posição.')
emaTrend              = input.bool(true, title='Check Trend EMA/Verificar Tendência da Média Móvel Exponencial', tooltip='Use EMA as trend verify for opening position./Usa a EMA como verificação de tendência para abrir posição.')
crossoverCheck        = input.bool(false, title='Add Another Crossover Check/Adicionar Mais uma Verificação de Cruzamento Superior', tooltip='This option is to add one more veryfication attempt to check if price is crossover upper bollinger band./Esta opção é para adicionar uma verificação adicional para avaliar se o preço cruza a banda superior da banda de bollinger.')
crossunderCheck       = input.bool(false, title='Add Another Crossunder Check/Adicionar Mais uma Verificação de Cruzamento Inferior', tooltip='This option is to add one more veryfication attempt to check if price is crossunder lower bollinger band./Esta opção é para adicionar uma verificação adicional para avaliar se o preço cruza a banda inferior da banda de bollinger.')
insideBarPatternCheck = input.bool(true, title='Show Inside Bar Pattern/Mostrar Padrão de Inside Bar', tooltip='This option is to show possible inside bar pattern./Esta opção é para mostrar um possível padrão de inside bar.')

[middle, upper, lower] = ta.bb(close, bbL, mult)
ema                    = ta.ema(close, emaL)
highestHigh            = ta.highest(high, highestHighL)
lowestLow              = ta.lowest(low, lowestLowL)
isCrossover            = ta.crossover(close, upper) ? 1 : 0
isCrossunder           = ta.crossunder(close, lower) ? 1 : 0

isPrevBarHighGreaterCurBarHigh = high[1] > high ? 1 : 0
isPrevBarLowLesserCurBarLow    = low[1] < low ? 1 : 0
isInsideBar                    = isPrevBarHighGreaterCurBarHigh and isPrevBarLowLesserCurBarLow ? 1 : 0

isBarLong  = ((close - open) > 0) ? 1 : 0
isBarShort = ((close - open) < 0) ? 1 : 0

isLongCross  = crossoverCheck ? ((isBarLong and not isBarShort) and (open < upper and close > upper)) ? 1 : 0 : isCrossover ? 1 : 0
isShortCross = crossunderCheck ? ((isBarShort and not isBarLong) and (close < lower and open > lower)) ? 1 : 0 : isCrossunder ? 1 : 0

isCandleAboveEma = close > ema ? 1 : 0
isCandleBelowEma = close < ema ? 1 : 0

isLongCondition  = emaTrend ? isLongCross and isCandleAboveEma ? 1 : 0 : isLongCross
isShortCondition = emaTrend ? isShortCross and isCandleBelowEma ? 1 : 0 : isShortCross

isPositionNone  = strategy.position_size == 0 ? 1 : 0
isPositionLong  = strategy.position_size > 0 ? 1 : 0
isPositionShort = strategy.position_size < 0 ? 1 : 0

var float enterLong     = 0.0
var float stopLossLong  = 0.0
var float targetLong    = 0.0
var float enterShort    = 0.0
var float stopLossShort = 0.0
var float targetShort   = 0.0
var bool isLongEntry    = false
var bool isShortEntry   = false

if (isPositionNone)
    isLongEntry   := false
    isShortEntry  := false
    enterLong     := 0.0
    stopLossLong  := 0.0
    targetLong    := 0.0
    enterShort    := 0.0
    stopLossShort := 0.0
    targetShort   := 0.0
if (isPositionShort or isPositionNone)
    isLongEntry  := false
    enterLong    := 0.0
    stopLossLong := 0.0
    targetLong   := 0.0
if (isPositionLong or isPositionNone)
    isShortEntry  := false
    enterShort    := 0.0
    stopLossShort := 0.0
    targetShort   := 0.0
if (isPositionLong and isLongEntry)
    isLongEntry   := true
    isShortEntry  := false
    enterShort    := 0.0
    stopLossShort := 0.0
    targetShort   := 0.0
if (isPositionShort and isShortEntry)
    isShortEntry := true
    isLongEntry  := false
    enterLong    := 0.0
    stopLossLong := 0.0
    targetLong   := 0.0

if (isLongCondition and not isLongEntry)
    isLongEntry  := true
    enterLong    := close
    stopLossLong := lowestLow
    targetLong   := (enterLong + (math.abs(enterLong - stopLossLong) * targetFactor))
    alertMessage = '{ "side/lado": "buy", "entry/entrada": ' + str.tostring(enterLong) + ', "stop": ' + str.tostring(stopLossLong) + ', "target/alvo": ' + str.tostring(targetLong) + ' }'
    alert(alertMessage)
    strategy.entry('Long', strategy.long)
    strategy.exit('Exit Long', 'Long', stop=stopLossLong, limit=targetLong)

if (isShortCondition and not isShortEntry)
    isShortEntry  := true
    enterShort    := close
    stopLossShort := highestHigh
    targetShort   := (enterShort - (math.abs(enterShort - stopLossShort) * targetFactor))
    alertMessage = '{ "side/lado": "sell", "entry/entrada": ' + str.tostring(enterShort) + ', "stop": ' + str.tostring(stopLossShort) + ', "target/alvo": ' + str.tostring(targetShort) + ' }'
    alert(alertMessage)
    strategy.entry('Short', strategy.short)
    strategy.exit('Exit Short', 'Short', stop=stopLossShort, limit=targetShort)

plot(upper, title='Upper Band', color=color.blue)
plot(middle, title='Middle Band', color=color.gray)
plot(lower, title='Lower Band', color=color.blue)
plot(ema, title='EMA', color=color.white)

barcolor(insideBarPatternCheck and isInsideBar and isBarLong ? color.lime : insideBarPatternCheck and isInsideBar and isBarShort ? color.maroon : na, title='Inside Bar Color in Long Bar Long and in Short Bar Short/Cor do Inside Bar em Barra Longa Longa e em Barra Curta Curta')

tablePosition    = position.bottom_right
tableColumns     = 2
tableRows        = 5
tableFrameWidth  = 1
tableBorderColor = color.gray
tableBorderWidth = 1

tableInfoTrade = table.new(position=tablePosition, columns=tableColumns, rows=tableRows, frame_width=tableFrameWidth, border_color=tableBorderColor, border_width=tableBorderWidth)

table.cell(table_id=tableInfoTrade, column=0, row=0)
table.cell(table_id=tableInfoTrade, column=1, row=0)

table.cell(table_id=tableInfoTrade, column=0, row=1, text='Entry Side/Lado da Entrada', text_color=color.white)
table.cell(table_id=tableInfoTrade, column=0, row=2, text=isLongEntry ? 'LONG' : isShortEntry ? 'SHORT' : 'NONE/NENHUM', text_color=color.yellow)

table.cell(table_id=tableInfoTrade, column=1, row=1, text='Entry Price/Preço da Entrada', text_color=color.white)
table.cell(table_id=tableInfoTrade, column=1, row=2, text=isLongEntry ? str.tostring(enterLong) : isShortEntry ? str.tostring(enterShort) : 'NONE/NENHUM', text_color=color.blue)

table.cell(table_id=tableInfoTrade, column=0, row=3, text='Take Profit Price/Preço Alvo Lucro', text_color=color.white)
table.cell(table_id=tableInfoTrade, column=0, row=4, text=isLongEntry ? str.tostring(targetLong) : isShortEntry ? str.tostring(targetShort) : 'NONE/NENHUM', text_color=color.green)

table.cell(table_id=tableInfoTrade, column=1, row=3, text='Stop Loss Price/Preço Stop Loss', text_color=color.white)
table.cell(table_id=tableInfoTrade, column=1, row=4, text=isLongEntry ? str.tostring(stopLossLong) : isShortEntry ? str.tostring(stopLossShort) : 'NONE/NENHUM', text_color=color.red)

Thêm nữa