Chiến lược này là hệ thống giao dịch theo dõi xu hướng kết hợp đường trung bình động và chỉ báo kỹ thuật kép MACD. Chỉ báo này chủ yếu nắm bắt xu hướng thị trường thông qua giao điểm của đường trung bình động EMA9 và giá, cũng như giao điểm của đường nhanh (DIF) và đường chậm (DEA) trong chỉ báo MACD. Đồng thời, chiến lược này áp dụng phương pháp dừng lỗ thích ứng dựa trên 5 đường K trước đó và sử dụng tỷ lệ rủi ro-lợi nhuận gấp 3,5 lần để đặt mục tiêu lợi nhuận, hình thành nên một hệ thống giao dịch hoàn chỉnh.
Logic cốt lõi của chiến lược được chia thành hai hướng: dài và ngắn:
Chiến lược này xây dựng một hệ thống giao dịch theo dõi xu hướng hoàn chỉnh thông qua việc xác nhận kép các chỉ báo kỹ thuật và quản lý rủi ro chặt chẽ. Mặc dù có mức độ phụ thuộc nhất định vào môi trường thị trường, chiến lược này vẫn chứng tỏ khả năng thích ứng và ổn định tốt thông qua việc tối ưu hóa thông số hợp lý và quản lý rủi ro. Các hướng tối ưu hóa tiếp theo sẽ chủ yếu tập trung vào độ chính xác của việc xác định xu hướng và động lực của quản lý rủi ro để cải thiện hiệu suất chung của chiến lược.
/*backtest
start: 2024-01-17 00:00:00
end: 2025-01-16 00:00:00
period: 2d
basePeriod: 2d
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT","balance":49999}]
*/
// =======================
// @version=6
strategy(title="MACD + EMA9 3 h",
shorttitle="MACD+EMA9+StopTP_5candles",
overlay=true,
initial_capital=100000, // Ajuste conforme desejar
default_qty_type=strategy.percent_of_equity,
default_qty_value=200) // Ajuste % de risco ou quantidade
// ----- Entradas (Inputs) -----
emaLen = input.int(9, "Período da EMA 9", minval=1)
macdFastLen = input.int(12, "Período MACD Rápido", minval=1)
macdSlowLen = input.int(26, "Período MACD Lento", minval=1)
macdSignalLen = input.int(9, "Período MACD Signal", minval=1)
riskMultiplier = input.float(3.5, "Fator de Multiplicação do Risco (TP)")
lookbackCandles = input.int(5, "Quantidade de candles p/ Stop", minval=1)
// ----- Cálculo da EMA -----
ema9 = ta.ema(close, emaLen)
// ----- Cálculo do MACD -----
[macdLine, signalLine, histLine] = ta.macd(close, macdFastLen, macdSlowLen, macdSignalLen)
// DIF cruza DEA para cima ou para baixo
macdCrossover = ta.crossover(macdLine, signalLine) // DIF cruza DEA p/ cima
macdCrossunder = ta.crossunder(macdLine, signalLine) // DIF cruza DEA p/ baixo
// ----- Condições de Compra/Venda -----
// Compra quando:
// 1) Preço cruza EMA9 de baixo pra cima
// 2) MACD cruza a linha de sinal para cima
buySignal = ta.crossover(close, ema9) and macdCrossover
// Venda quando:
// 1) Preço cruza EMA9 de cima pra baixo
// 2) MACD cruza a linha de sinal para baixo
sellSignal = ta.crossunder(close, ema9) and macdCrossunder
// ----- Execução das ordens -----
// Identifica o menor e o maior preço dos últimos 'lookbackCandles' candles.
// A função ta.lowest() e ta.highest() consideram, por padrão, a barra atual também.
// Se você quiser EXCLUIR a barra atual, use low[1] / high[1] dentro do ta.lowest() / ta.highest().
lowestLow5 = ta.lowest(low, lookbackCandles)
highestHigh5= ta.highest(high, lookbackCandles)
// >>> Quando há sinal de COMPRA <<<
if (buySignal)
// Fecha posição vendida, se existir
strategy.close("Sell")
// Entra comprado
strategy.entry("Buy", strategy.long)
// STOP: abaixo do menor preço dos últimos 5 candles
stopPrice = lowestLow5
// Risco = (preço de entrada) - (stop)
// Note que strategy.position_avg_price só fica disponível a partir da barra seguinte.
// Por isso, o exit costuma funcionar corretamente apenas na barra seguinte.
// Para fins de teste, podemos usar 'close' como proxy do "entry" (ou aceitar essa limitação).
// A forma "correta" de usar strategy.position_avg_price seria via calc_on_order_fills = true,
// mas isso pode exigir algumas configurações adicionais.
risk = strategy.position_avg_price - stopPrice
// Take Profit = entrada + 2,5 * risco
takeProfitPrice = strategy.position_avg_price + riskMultiplier * risk
// Registra a saída (stop e alvo) vinculada à posição "Buy"
strategy.exit("Exit Buy", "Buy", stop=stopPrice, limit=takeProfitPrice)
// >>> Quando há sinal de VENDA <<<
if (sellSignal)
// Fecha posição comprada, se existir
strategy.close("Buy")
// Entra vendido
strategy.entry("Sell", strategy.short)
// STOP: acima do maior preço dos últimos 5 candles
stopPrice = highestHigh5
// Risco = (stop) - (preço de entrada)
risk = stopPrice - strategy.position_avg_price
// Take Profit = entrada - 2,5 * risco
takeProfitPrice = strategy.position_avg_price - riskMultiplier * risk
// Registra a saída (stop e alvo) vinculada à posição "Sell"
strategy.exit("Exit Sell", "Sell", stop=stopPrice, limit=takeProfitPrice)
// ----- Plotagens visuais -----
plot(ema9, color=color.orange, linewidth=2, title="EMA 9")
plot(macdLine, color=color.new(color.blue, 0), title="MACD")
plot(signalLine, color=color.new(color.red, 0), title="Signal")
plot(histLine, color=color.new(color.purple, 0), style=plot.style_histogram, title="Histogram")
// Só para auxiliar na visualização, vamos plotar a linha do lowestLow5 e highestHigh5
plot(lowestLow5, color=color.new(color.lime, 70), style=plot.style_line, title="Lowest 5 bars")
plot(highestHigh5, color=color.new(color.fuchsia,70),style=plot.style_line, title="Highest 5 bars")