
A estratégia usa o EMA de 200 dias para determinar a direção da grande tendência e, em seguida, procura oportunidades de ruptura nos pontos críticos de resistência / suporte.A lógica central é simples e grosseira: o mercado de ativos buscam uma linha de tendência de queda para fazer mais, o mercado de ativos buscam uma linha de tendência de alta para fazer menos.
Os dados falam: a estratégia usa detecção de eixos centrais de 5 + 5 para garantir que o sinal não seja redesenhado. A janela de retrospecção de 20 ciclos limita o alcance dos dados históricos e evita a superação.
O ponto de parada é o ponto mais alto/mais baixo da linha K anterior, com o alvo de parada a três vezes a distância de parada.Isso significa que, mesmo com uma taxa de 30% de sucesso, você ainda é rentável a longo prazo.
Execução específica: após a ruptura de várias cabeças, o stop loss = ante low, o stop stop = preço de entrada + 3 × ((preço de entrada - ante low)). O inverso. O controle de risco é configurado por defeito como 1% do capital da conta, com um intervalo ajustável de 0,1%-10%.
O maior problema com a análise técnica tradicional é que ela é muito subjetiva. Esta estratégia usa um algoritmo para identificar automaticamente os altos e baixos dos pontos-chave:
O resultado é uma imagem totalmente objetiva, sem repetições, e reprodutivel.
Filtragem de primeira camada: tendência de tendência da EMA.O preço faz apenas brechas acima da EMA de 200 dias e apenas brechas abaixo dela. Este truque filtra diretamente 80% das negociações adversas.
Filtragem de segunda camada: validação da eficácia da linha de tendência.O sistema exige que se encontrem dois eixos-chave qualificados para traçar uma linha de tendência. A “linha de tendência” que não é apoiada por dados suficientes é diretamente ignorada.
Efeito de batalha real: diminuição drástica de sinais ineficazes em cidades de turbulência, captura precisa de oportunidades de ruptura em cidades de tendência.
Dois tipos de posições disponíveis:
Fórmula matemática: tamanho da posição = (capital da conta × porcentagem de risco) ÷ distância de parada
Este conjunto de gestão de posições é mais científico do que 90% das estratégias do mercado. Em caso de perda contínua, a perda é automaticamente reduzida e, em caso de lucro, a posição é aumentada gradualmente.
A estratégia não é universal, e as seguintes situações não funcionam bem:
Alerta de sensibilidade de parâmetros:
O melhor cenário:
Recomendações de optimização de parâmetros:
O retorno histórico não representa o lucro futuro. Qualquer estratégia tem a possibilidade de perdas contínuas. Recomenda-se testar o ambiente de simulação e confirmar a compreensão da lógica da estratégia antes de investir no mercado real.
/*backtest
start: 2024-10-29 00:00:00
end: 2025-10-27 08:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"SOL_USDT"}]
*/
//@version=5
strategy("Trendline Breakout Strategy", overlay=true, max_lines_count=500, max_labels_count=500, max_boxes_count=500)
// === INPUTS ===
ema_len = input.int(200, "EMA Length", minval=1, group="Trend Detection")
src = input.source(close, "EMA Source", group="Trend Detection")
lookback = input.int(20, "Lookback Window for Pivots (bars)", minval=5, group="Trend Detection")
left_bars = input.int(5, "Pivot Left Sensitivity (bars)", minval=1, group="Trend Detection")
right_bars = input.int(5, "Pivot Right Sensitivity (bars)", minval=1, group="Trend Detection")
qty_mode = input.string("Risk Percent", "Position Sizing Mode", options=["Risk Percent", "Fixed Contracts"], group="Position Sizing")
risk_pct = input.float(1.0, "Risk % of Equity", minval=0.1, maxval=10.0, step=0.1, group="Position Sizing")
fixed_size = input.int(1, "Fixed Contract Size", minval=1, group="Position Sizing")
show_trendline = input.bool(true, "Show Trendline", group="Visuals")
enable_prints = input.bool(true, "Enable Info Table", group="Visuals")
// === CORE LOGIC ===
// EMA Calculation
ema = ta.ema(src, ema_len)
bias_bull = close > ema
bias_bear = close < ema
// Pivot Detection (confirmed, no repainting)
ph = ta.pivothigh(high, left_bars, right_bars)
pl = ta.pivotlow(low, left_bars, right_bars)
// Arrays to store historical pivots (limited to prevent memory issues)
var array<float> ph_values = array.new<float>()
var array<int> ph_bars = array.new<int>()
var array<float> pl_values = array.new<float>()
var array<int> pl_bars = array.new<int>()
// Update pivot highs array
if not na(ph)
array.push(ph_values, ph)
array.push(ph_bars, bar_index - right_bars)
if array.size(ph_values) > 100
array.shift(ph_values)
array.shift(ph_bars)
// Update pivot lows array
if not na(pl)
array.push(pl_values, pl)
array.push(pl_bars, bar_index - right_bars)
if array.size(pl_values) > 100
array.shift(pl_values)
array.shift(pl_bars)
// Function to find two most recent pivots within lookback
get_two_pivots(arr_vals, arr_bars) =>
int p1_bar = na
float p1_val = na
int p2_bar = na
float p2_val = na
for j = array.size(arr_bars) - 1 to 0
int pb = array.get(arr_bars, j)
if pb < bar_index - lookback
break
if na(p1_bar)
p1_bar := pb
p1_val := array.get(arr_vals, j)
else if na(p2_bar)
p2_bar := pb
p2_val := array.get(arr_vals, j)
break // Only need the two most recent
[p1_bar, p1_val, p2_bar, p2_val]
// Get pivots for bullish bias
int p1h_bar = na
float p1h_val = na
int p2h_bar = na
float p2h_val = na
if bias_bull
[tmp1, tmp2, tmp3, tmp4] = get_two_pivots(ph_values, ph_bars)
p1h_bar := tmp1
p1h_val := tmp2
p2h_bar := tmp3
p2h_val := tmp4
// Get pivots for bearish bias
int p1l_bar = na
float p1l_val = na
int p2l_bar = na
float p2l_val = na
if bias_bear
[tmp5, tmp6, tmp7, tmp8] = get_two_pivots(pl_values, pl_bars)
p1l_bar := tmp5
p1l_val := tmp6
p2l_bar := tmp7
p2l_val := tmp8
// Validate trendlines
bull_valid = bias_bull and not na(p1h_bar) and not na(p2h_bar) and p2h_bar < p1h_bar and p2h_val > p1h_val // Descending: older high > newer high
bear_valid = bias_bear and not na(p1l_bar) and not na(p2l_bar) and p2l_bar < p1l_bar and p2l_val < p1l_val // Ascending: older low < newer low
// Calculate trendline Y at current bar
float bull_y = na
if bull_valid and p1h_bar != p2h_bar
float slope = (p1h_val - p2h_val) / (p1h_bar - p2h_bar)
bull_y := p1h_val + slope * (bar_index - p1h_bar)
float bear_y = na
if bear_valid and p1l_bar != p2l_bar
float slope = (p1l_val - p2l_val) / (p1l_bar - p2l_bar)
bear_y := p1l_val + slope * (bar_index - p1l_bar)
// Breakout conditions (confirmed on close, no repainting)
long_breakout = bull_valid and ta.crossover(close, bull_y)
short_breakout = bear_valid and ta.crossunder(close, bear_y)
// === POSITION SIZING AND ENTRIES ===
var float entry_price = na
var float sl_price = na
var float tp_price = na
if long_breakout and strategy.position_size == 0
entry_price := close
sl_price := low[1]
float risk = entry_price - sl_price
if risk > 0
strategy.entry("Long", strategy.long, qty = qty_mode == "Fixed Contracts" ? float(fixed_size) : (strategy.equity * risk_pct / 100) / risk)
tp_price := sl_price + 3 * risk
strategy.exit("Long Exit", "Long", stop=sl_price, limit=tp_price)
if short_breakout and strategy.position_size == 0
entry_price := close
sl_price := high[1]
float risk = sl_price - entry_price
if risk > 0
strategy.entry("Short", strategy.short, qty = qty_mode == "Fixed Contracts" ? float(fixed_size) : (strategy.equity * risk_pct / 100) / risk)
tp_price := sl_price - 3 * risk
strategy.exit("Short Exit", "Short", stop=sl_price, limit=tp_price)
// === VISUAL LABELS ===
if long_breakout
label.new(bar_index, low, text="Long\nEntry: " + str.tostring(entry_price, "#.##") + "\nSL: " + str.tostring(sl_price, "#.##") + "\nTP: " + str.tostring(tp_price, "#.##") + "\nReason: Trendline Breakout",
style=label.style_label_up, color=color.green, textcolor=color.white, size=size.small)
if short_breakout
label.new(bar_index, high, text="Short\nEntry: " + str.tostring(entry_price, "#.##") + "\nSL: " + str.tostring(sl_price, "#.##") + "\nTP: " + str.tostring(tp_price, "#.##") + "\nReason: Trendline Breakout",
style=label.style_label_down, color=color.red, textcolor=color.white, size=size.small)
// === INFO TABLE ===
if enable_prints and barstate.islast
var table info_table = table.new(position.top_right, 2, 4, bgcolor=color.white, border_width=1)
table.cell(info_table, 0, 0, "Bias", text_color=color.black, bgcolor=color.gray)
table.cell(info_table, 1, 0, bias_bull ? "Bull" : "Bear", text_color=bias_bull ? color.green : color.red)
table.cell(info_table, 0, 1, "Trendline", text_color=color.black, bgcolor=color.gray)
table.cell(info_table, 1, 1, bull_valid or bear_valid ? (bull_valid ? "Descending" : "Ascending") : "None", text_color=color.black)
table.cell(info_table, 0, 2, "Position", text_color=color.black, bgcolor=color.gray)
table.cell(info_table, 1, 2, strategy.position_size > 0 ? "Long" : strategy.position_size < 0 ? "Short" : "Flat", text_color=color.black)
table.cell(info_table, 0, 3, "P&L", text_color=color.black, bgcolor=color.gray)
table.cell(info_table, 1, 3, str.tostring(strategy.netprofit, "#.##"), text_color=strategy.netprofit >= 0 ? color.green : color.red)
// === EMA PLOT ===
plot(ema, "EMA", color=color.blue, linewidth=2)
// === ALERTS ===
alertcondition(long_breakout, title="Long Entry Alert", message="Bullish bias: Price broke above descending trendline. Enter Long.")
alertcondition(short_breakout, title="Short Entry Alert", message="Bearish bias: Price broke below ascending trendline. Enter Short.")
alertcondition(strategy.position_size[1] != 0 and strategy.position_size == 0, title="Exit Alert", message="Position closed at SL or TP.")
// === COMMENTS AND LIMITATIONS ===
// Comments:
// - Pivots are detected using ta.pivothigh/low with user-defined sensitivity to identify "significant" swings.
// - Trendlines are redrawn only when bias is active and valid (two qualifying pivots found).
// - Entries/exits use strategy.entry/exit for backtesting; position size closes opposite trades automatically.
// - No repainting: All pivots require 'right_bars' confirmation; breakouts checked on bar close.
// - Variable names: Descriptive (e.g., p1h_bar for most recent pivot high bar).
//
// Limitations:
// - Trendline uses the two *most recent* pivot highs/lows within lookback; may not always connect the absolute highest/lowest if more pivots exist.
// - Pivot sensitivity (left/right bars) approximates "significant" swings—too low may include noise, too high may miss turns.
// - Only one trendline per bias; does not handle multiple parallel lines or complex channels.
// - Position sizing assumes equity-based risk; in "Fixed Contracts" mode, risk % varies with SL distance.
// - Lookback window limits historical context—short windows may yield few/no valid trendlines on low-volatility periods.
// - Strategy does not filter for overall trend strength beyond EMA bias; add filters (e.g., volume) for production use.