
A estratégia de rastreamento de tendências de reversão de KDJ é um sistema de negociação quantitativa que combina a dinâmica de reversão e a ideia de rastreamento de tendências. O núcleo da estratégia consiste em capturar o primeiro sinal de reversão do indicador J após a região de extremo (~ 0 ou 100) e, ao mesmo tempo, filtrar a direção da tendência através da linha de equilíbrio EMA676, garantindo que a direção da negociação esteja de acordo com a tendência principal.
A lógica central da estratégia é baseada na característica J-valor do indicador KDJ e, em combinação com a filtragem de tendências, permite uma entrada de precisão. Os princípios específicos são os seguintes:
Identificação de extremos de JA estratégia de monitorar se o valor de J atinge um limite predefinido (default upper bound 100, lower bound 0), que geralmente representa um mercado muito comprado ou muito vendido.
Confirmação de padrões de mudança contínuaA estratégia exige que, após o valor de J atingir o limite, deve haver uma mudança unidirecional de 3 linhas K consecutivas (ascensão ou queda contínua). Este modelo permite confirmar o movimento forte do indicador.
Captura de sinal de retornoA estratégia de monitorar a primeira mudança de sentido inverso, ou seja, a mudança de sentido inverso do valor de J de ascensão contínua para descensão, ou de descensão contínua para ascensão, quando o valor de J completa um movimento unidirecional de 3 linhas K consecutivas.
Filtragem de direção de tendênciaA estratégia usa a linha média do EMA676 como critério para determinar a tendência, considerando apenas os sinais de multiplicação quando o preço está acima da linha média e os sinais de curto prazo quando está abaixo da linha média, garantindo que a direção da negociação esteja de acordo com a tendência geral.
Paragem dinâmicaA estratégia utiliza um stop loss percentual baseado no preço de entrada, com um stop loss de 3% e um stop loss de 2.2%, para uma estrutura de negociação com um risco/ganho maior que 1.
Gestão inteligente de armazénsO sistema fornece um número fixo de contratos e uma porcentagem de risco baseada em dois métodos de cálculo de posições, que ajustam o tamanho da posição de acordo com a dinâmica da abertura de risco de cada transação, otimizando a eficiência do uso de fundos.
Ao analisar o código em profundidade, a estratégia mostra as seguintes vantagens significativas:
O mecanismo de disparo do sinal de precisãoA condição complexa aumenta consideravelmente a confiabilidade do sinal, reduzindo as falsas rupturas, ao exigir que o valor de J não apenas atinja o limite, mas também experimente o movimento unidirecional de 3 linhas K consecutivas, antes de capturar a primeira reversão.
A combinação perfeita de tendência e reversãoA estratégia combina habilmente os dois conceitos de negociação: acompanhamento de tendências (filtragem na direção do EMA676) e negociação de reversão (revolta no valor máximo do J), respeitando a direção da grande tendência e capturando oportunidades de rebote de alta probabilidade na tendência.
Gestão de risco adaptadaO código permite o cálculo de posições dinâmicas baseadas na porcentagem de risco, mantendo a abertura de risco de cada transação consistente e mantendo o controle de risco estável, independentemente da variação da volatilidade do mercado.
Comentário visual claroA estratégia traça no gráfico os sinais de entrada, os pontos de disparo de stop loss e as linhas de preço-chave, permitindo ao comerciante entender intuitivamente a lógica e o resultado da execução de cada transação.
Configuração de parâmetros flexívelO sistema oferece uma grande variedade de parâmetros ajustáveis, incluindo o ciclo de cálculo do KDJ, a duração do EMA, a configuração do limite e a proporção de stop loss, permitindo que a estratégia se adapte a diferentes ambientes de mercado e variedades de negociação.
Mecanismo de alertaO código é projetado para a proximidade de um sinal de aviso prévio, como quando o valor de J está perto da zona de extremo valor ou está prestes a formar um sinal de entrada, pode avisar o comerciante para se preparar, aumentando a eficiência operacional.
Apesar da estratégia ser bem concebida, existem os seguintes riscos potenciais:
Cessação de perdas em situações extremasA solução é introduzir um mecanismo de parada fora de campo, ou considerar o uso de condições dentro do campo.
Risco de atraso na linha médiaA EMA676 tem um atraso significativo como uma média de longo período, e pode dar orientação errada no início de uma mudança de tendência. Recomenda-se a combinação de análise de múltiplos períodos ou a adição de indicadores de confirmação de tendências de curto prazo para otimizar a qualidade do sinal.
Parâmetros de otimização de overfittingOs parâmetros atuais (como o KDJ de 60 ciclos, o máximo de 100⁄0) podem ser obtidos com base na otimização de dados históricos, existindo o risco de superalimento. Recomenda-se a verificação da solidez dos parâmetros por meio de testes de antecipação e testes de diferentes ciclos.
J-valor de cálculo de desvioA estratégia utiliza a função bcwsma, que pode ser usada para calcular o valor do KDJ. Pode haver diferenças com o cálculo do KDJ padrão em diferentes plataformas, o que pode levar à incompatibilidade da detecção com o sinal do disco. A consistência do método de cálculo deve ser confirmada antes do disco.
Riscos de mercado de baixa liquidezEm mercados com menor volume de transações, os pontos de stop-loss podem ser maiores, afetando o desempenho real da estratégia. Recomenda-se a aplicação da estratégia em mercados de alta liquidez ou variedades de negociação mainstream.
Frequência de sinal instávelOs sinais baseados em inversões de extremos podem variar muito em frequência em diferentes ambientes de mercado, resultando em inestabilidade na eficiência do uso de fundos. Pode-se considerar a adição de sinais de negociação auxiliares ou mecanismos de confirmação de múltiplos quadros de tempo para suavizar a frequência de negociação.
As seguintes direções de otimização podem ser consideradas em função das características existentes da estratégia:
Definição de limite dinâmicoA estratégia atual usa limites máximos e mínimos fixos (de 100 e 0) e pode considerar ajustes dinâmicos de limites baseados na flutuação histórica, adaptando-se a diferentes ambientes de flutuação, como, por exemplo, restringir adequadamente os limites em períodos de baixa flutuação e ampliar os limites em períodos de alta flutuação.
Confirmação do Multi-TemposIntrodução de sinais de confirmação de quadros de tempo de nível mais elevado, como, por exemplo, exigir que os valores de J do nível do sol também estejam na região de extremo valor, ou confirmação de consistência de sinais com períodos de 3 minutos e 15 minutos, aumentando a qualidade do sinal.
Mecanismos inteligentes de bloqueioImplementar estratégias de stop-loss dinâmicas, como a liquidação em lotes ou o cálculo de stop-loss com base no ATR (Actualização da Variação da Margem Real), ou o uso de stop-loss de rastreamento para maximizar o lucro de captura de tendências após o lucro atingir um determinado nível.
Filtragem do cenário de mercadoAumentar as condições de filtragem de taxa de flutuação, suspender a negociação em um ambiente de mercado com excesso ou baixa volatilidade, ou ajustar o tamanho da posição para evitar a negociação em um ambiente de mercado que não seja adequado para as características da estratégia.
Classificação de intensidade do sinal: baseado na amplitude de inversão de J, forma de linha K, confirmação de volume de transação e outros fatores, classifique a intensidade do sinal e ajuste o tamanho da posição de acordo com a dinâmica da intensidade do sinal, o sinal forte aumenta a posição e o sinal fraco diminui a posição.
Otimização de aprendizagem de máquinaIntrodução de algoritmos de aprendizado de máquina para otimizar automaticamente os conjuntos de parâmetros, ou extrair características dos sinais históricos, criar modelos de previsão para avaliar a probabilidade de sucesso de cada sinal, melhorar a adaptabilidade e a robustez das estratégias.
A estratégia de rastreamento de tendências de reversão de extremos do KDJ é um sistema de negociação quantitativa bem estruturado e com lógica clara, que controla o risco ao capturar reversões de extremos de indicadores técnicos e combinar filtros de direção de tendência, mantendo uma alta taxa de vitória. A principal vantagem da estratégia reside na precisão de seu mecanismo de acionamento de sinais e na integridade do gerenciamento de risco, adequado para ambientes de mercado onde as tendências são claras, mas flutuantes, a médio e longo prazo.
Do ponto de vista da implementação, a estrutura do código da estratégia é clara, a lógica de cálculo é rigorosa, contém funções completas de gerenciamento de transações, e tem implementações detalhadas desde a geração de sinais, o cálculo de posições até a execução de stop-loss. A estabilidade e adaptabilidade da estratégia devem ser melhoradas através das direções de otimização propostas neste artigo, especialmente o ajuste de parâmetros dinâmicos e a confirmação de sinais multidimensional.
Para os comerciantes, a aplicação desta estratégia deve ter em conta a aplicabilidade dos parâmetros de verificação em diferentes condições de mercado e ajustar o stop loss e o posicionamento de posição de acordo com as preferências de risco pessoais. Ao mesmo tempo, é recomendável a combinação de análise fundamental e análise técnica em quadros de tempo mais elevados para aumentar a abrangência e a precisão das decisões de negociação.
//@version=6
strategy("J值极值趋势跟随策略", overlay = true,
default_qty_type = strategy.percent_of_equity, default_qty_value = 10, // 降低每笔交易的仓位大小
initial_capital = 10000,
margin_long = 20, margin_short = 20) // 设置合理的保证金要求
// === 策略说明:J值极值趋势跟随策略 ===
// 主图:显示J值连续下降后反弹的买点和连续上升后回调的卖点
// 副图:显示J线走势、中轴线、极值区域
// 方向过滤:676均线,价格在上方只做多,下方只做空
// 止盈止损:基于百分比波动,默认1%止盈1%止损
// === 输入参数 ===
lengthK = input.int(60, title = "K period")
lengthD = input.int(3, title = "D period")
smoothK = input.int(3, title = "Smooth K")
emaLength = input.int(576, title = "趋势EMA周期", inline="ema")
extremeHigh = input.float(100, title = "J值极值上限", minval = 80, maxval = 120)
extremeLow = input.float(0, title = "J值极值下限", minval = -20, maxval = 20)
// === 止盈止损参数(改为百分比) ===
takeProfitPercent = input.float(3, title = "止盈百分比", minval = 0.1, step = 0.1)
stopLossPercent = input.float(2.2, title = "止损百分比", minval = 0.1, step = 0.1)
// === 风险控制参数 ===
useFixedPositionSize = input.bool(true, title = "使用固定合约数量")
fixedPositionSize = input.float(1.0, title = "固定合约数量", minval = 0.1, step = 0.1)
riskPerTrade = input.float(1.0, title = "每笔交易风险百分比", minval = 0.1, maxval = 10, step = 0.1)
// === KDJ计算(使用与bitcoinwisdom一致的算法) ===
// 自定义加权移动平均函数(与bitcoinwisdom一致)
bcwsma(s, l, m) =>
var _bcwsma = 0.0
_bcwsma := (m*s + (l-m)*nz(_bcwsma[1])) / l
_bcwsma
highestHigh = ta.highest(high, lengthK)
lowestLow = ta.lowest(low, lengthK)
rsv = (close - lowestLow) / (highestHigh - lowestLow) * 100
K = bcwsma(rsv, smoothK, 1)
D = bcwsma(K, lengthD, 1)
J = 3 * K - 2 * D
// === 676均线方向判断 ===
ema676 = ta.ema(close, emaLength)
trendUp = close > ema676 // 价格在676均线上方
trendDown = close < ema676 // 价格在676均线下方
// === 检测J值连续下降和上升 ===
// 检测连续3根下降:J < J[1] < J[2] < J[3]
jContinuousDown = J < J[1] and J[1] < J[2] and J[2] < J[3]
// 检测连续3根上升:J > J[1] > J[2] > J[3]
jContinuousUp = J > J[1] and J[1] > J[2] and J[2] > J[3]
// === 检测反弹和回调(必须在极值区域内) ===
// 反弹:当前J值上升,且之前连续下降,且J值在极值下限以下
jBounce = J > J[1] and jContinuousDown[1] and J[1] <= extremeLow
// 回调:当前J值下降,且之前连续上升,且J值在极值上限以上
jPullback = J < J[1] and jContinuousUp[1] and J[1] >= extremeHigh
// === 开仓信号(带方向过滤) ===
// 买点:J值连续下降后反弹 + 价格在676均线上方
longEntry = jBounce and trendUp
// 卖点:J值连续上升后回调 + 价格在676均线下方
shortEntry = jPullback and trendDown
// === 记录开仓价格和止盈止损价格 ===
var float entryPrice = na
var float tpPrice = na
var float slPrice = na
// === 计算仓位大小 ===
// 基于风险百分比的仓位计算需要考虑止损百分比
positionSize = useFixedPositionSize ? fixedPositionSize : (strategy.equity * (riskPerTrade / 100)) / (close * stopLossPercent / 100)
// === 止盈止损信号变量 ===
var bool longTakeProfitHit = false
var bool longStopLossHit = false
var bool shortTakeProfitHit = false
var bool shortStopLossHit = false
// === 警报信号指示器 ===
// 多单入场信号将触发
longSignalComing = J <= extremeLow and jContinuousDown and trendUp
// 空单入场信号将触发
shortSignalComing = J >= extremeHigh and jContinuousUp and trendDown
// J值接近极值区域
jNearExtremeLow = J <= extremeLow + 5 and J > extremeLow
jNearExtremeHigh = J >= extremeHigh - 5 and J < extremeHigh
// === 策略执行 ===
if (longEntry and strategy.position_size == 0)
entryPrice := close
// 计算基于百分比的止盈止损价格
tpPrice := entryPrice * (1 + takeProfitPercent / 100)
slPrice := entryPrice * (1 - stopLossPercent / 100)
strategy.entry("多单", strategy.long, qty=positionSize)
// 重置止盈止损信号
longTakeProfitHit := false
longStopLossHit := false
if (shortEntry and strategy.position_size == 0)
entryPrice := close
// 计算基于百分比的止盈止损价格
tpPrice := entryPrice * (1 - takeProfitPercent / 100)
slPrice := entryPrice * (1 + stopLossPercent / 100)
strategy.entry("空单", strategy.short, qty=positionSize)
// 重置止盈止损信号
shortTakeProfitHit := false
shortStopLossHit := false
// === 手动检查止盈止损条件 ===
// 多单止盈止损
longTPHit = strategy.position_size > 0 and high >= tpPrice and not longTakeProfitHit
longSLHit = strategy.position_size > 0 and low <= slPrice and not longStopLossHit
if (longTPHit)
strategy.close("多单", comment="止盈")
longTakeProfitHit := true
if (longSLHit)
strategy.close("多单", comment="止损")
longStopLossHit := true
// 空单止盈止损
shortTPHit = strategy.position_size < 0 and low <= tpPrice and not shortTakeProfitHit
shortSLHit = strategy.position_size < 0 and high >= slPrice and not shortStopLossHit
if (shortTPHit)
strategy.close("空单", comment="止盈")
shortTakeProfitHit := true
if (shortSLHit)
strategy.close("空单", comment="止损")
shortStopLossHit := true
// === 在主图绘制676均线 ===
plot(ema676, title="676 EMA", color=color.blue, linewidth=2)
// === 在主图标注开仓信号 ===
plotshape(longEntry, title="多单入场", location=location.belowbar, color=color.lime, style=shape.triangleup, size=size.small, text="多单", force_overlay=true)
plotshape(shortEntry, title="空单入场", location=location.abovebar, color=color.red, style=shape.triangledown, size=size.small, text="空单", force_overlay=true)
// === 添加止盈止损信号 ===
// 多单止盈信号
plotshape(longTPHit, title="多单止盈", location=location.abovebar,
color=color.green, style=shape.circle, size=size.normal, text="止盈", force_overlay=true)
// 多单止损信号
plotshape(longSLHit, title="多单止损", location=location.abovebar,
color=color.red, style=shape.xcross, size=size.normal, text="止损", force_overlay=true)
// 空单止盈信号
plotshape(shortTPHit, title="空单止盈", location=location.belowbar,
color=color.green, style=shape.circle, size=size.normal, text="止盈", force_overlay=true)
// 空单止损信号
plotshape(shortSLHit, title="空单止损", location=location.belowbar,
color=color.red, style=shape.xcross, size=size.normal, text="止损", force_overlay=true)
// === 绘制止盈止损线 ===
plot(strategy.position_size != 0 ? tpPrice : na, title="止盈", color=color.green, style=plot.style_line, linewidth=1)
plot(strategy.position_size != 0 ? slPrice : na, title="止损", color=color.red, style=plot.style_line, linewidth=1)
plot(strategy.position_size != 0 ? entryPrice : na, title="入场价", color=color.yellow, style=plot.style_line, linewidth=1)
// === 设置警报条件(使用常量字符串) ===
// 基础信号警报
alertcondition(longEntry, title="多单入场信号", message="J值极值策略: 多单入场信号触发")
alertcondition(shortEntry, title="空单入场信号", message="J值极值策略: 空单入场信号触发")
alertcondition(longTPHit, title="多单止盈触发", message="J值极值策略: 多单止盈触发")
alertcondition(longSLHit, title="多单止损触发", message="J值极值策略: 多单止损触发")
alertcondition(shortTPHit, title="空单止盈触发", message="J值极值策略: 空单止盈触发")
alertcondition(shortSLHit, title="空单止损触发", message="J值极值策略: 空单止损触发")
// === 添加交易详情标签 ===
if (longTPHit)
label.new(bar_index, high, text="多单止盈 +" + str.tostring(takeProfitPercent) + "%",
style=label.style_label_down, color=color.green, textcolor=color.white)
if (longSLHit)
label.new(bar_index, low, text="多单止损 -" + str.tostring(stopLossPercent) + "%",
style=label.style_label_up, color=color.red, textcolor=color.white)
if (shortTPHit)
label.new(bar_index, low, text="空单止盈 +" + str.tostring(takeProfitPercent) + "%",
style=label.style_label_up, color=color.green, textcolor=color.white)
if (shortSLHit)
label.new(bar_index, high, text="空单止损 -" + str.tostring(stopLossPercent) + "%",
style=label.style_label_down, color=color.red, textcolor=color.white)