Strategy · Pine Script v5 · On the chart

ETH Perp Trading Bot V9.7 Strategy Backtest

by xunxuntj

A backtest strategy for an Ethereum perpetual futures bot with two modes: a 30-minute signal confirmed on one hour, or a one-hour signal confirmed on four hours.

View on GitHub

GitHub stars1on the repository
Pine versionv5runs as is
Lines of code372
Settings19inputs
LicenceMIT
Last update3 days ago26 Oct 2026

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new strategy, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart. The trades and results appear in the Strategy Tester tab; adjust the settings with the gear icon.

Source Code

372 lines of Pine Script v5 from archive/v9.7_legacy/eth_perp_v9_7_backtest.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.

eth_perp_v9_7_backtest.pine
//@version=5
strategy("ETH Perp Trading Bot V9.7 Strategy Backtest", overlay=true, initial_capital=10000, default_qty_type=strategy.cash, default_qty_value=100, commission_type=strategy.commission.percent, commission_value=0.04, margin_long=10, margin_short=10, max_boxes_count=500, max_labels_count=500, max_lines_count=500)

// ==========================================
// 1. INPUT PARAMETERS
// ==========================================

gp_mode = "=== Strategy Mode ==="
strat_mode = input.string("30m-1H", "Strategy Mode", options=["30m-1H", "1H-4H"], group=gp_mode, tooltip="Select the timeframe mode. 30m-1H: 30m signal with 1H confirmation (run on 30m chart); 1H-4H: 1H signal with 4H confirmation (run on 1H chart).")

gp_ind = "=== Technical Indicators ==="
st_period = input.int(10, "SuperTrend Period", group=gp_ind, tooltip="Lookback period for ATR in SuperTrend")
st_mult = input.float(3.0, "SuperTrend Multiplier", step=0.1, group=gp_ind, tooltip="ATR multiplier for SuperTrend bands")
dema_period = input.int(200, "DEMA Period", group=gp_ind, tooltip="DEMA length on the higher timeframe")

gp_risk = "=== Sizing & Risk ==="
risk_mode = input.string("percent", "Risk Mode", options=["fixed", "percent"], group=gp_risk, tooltip="fixed: Fixed risk amount in USDT; percent: Risk is % of total equity")
risk_fixed_amount = input.float(10.0, "Fixed Risk Amount (USDT)", group=gp_risk, tooltip="Amount of USDT risked per trade based on stop loss distance")
risk_percent = input.float(2.0, "Percent Risk of Equity (%)", minval=0.1, maxval=100.0, group=gp_risk, tooltip="Risk percentage of total equity per trade") / 100.0
leverage = input.float(10.0, "Leverage", group=gp_risk, tooltip="Leverage used to calculate margin requirement")
lock_profit_buffer = input.float(1.0, "Lock Profit Buffer (R Ratio)", group=gp_risk, tooltip="Minimum guaranteed profit as a ratio of trade risk (R value) once stop loss enters lock phase (e.g. 1.0 means profit = 1 * Risk)")

gp_asset = "=== Asset Details ==="
auto_face_value = input.bool(true, "Auto-detect Face Value", group=gp_asset, tooltip="Detect face value based on symbol base currency (e.g. BTC=0.0001, ETH=0.01, SOL=1.0)")
manual_face_value = input.float(0.01, "Manual Face Value (contracts multiplier)", group=gp_asset, tooltip="If auto-detect is disabled, this multiplier is used for position size calculation")

gp_ctrl = "=== Cooldown & Circuit Breaker ==="
enable_cooldown = input.bool(true, "Enable Cooldown (3 Losses)", group=gp_ctrl, tooltip="Enable 48 hours pause after 3 consecutive losses")
cooldown_hours = input.int(48, "Cooldown Duration (Hours)", group=gp_ctrl)
enable_cb = input.bool(true, "Enable Circuit Breaker", group=gp_ctrl, tooltip="Enable circuit breaker if equity falls below threshold")
cb_equity = input.float(350.0, "Circuit Breaker Equity Threshold", group=gp_ctrl, tooltip="Stop trading if equity is below this amount")

gp_filter = "=== Trend Strength Filter (Auto-Trading) ==="
use_adx = input.bool(true, "Enable ADX Filter", group=gp_filter, tooltip="Turn on to prevent the bot from trading in choppy, sideways markets.")
adx_len = input.int(14, "ADX Length", group=gp_filter)
adx_threshold = input.int(20, "ADX Threshold", group=gp_filter, tooltip="Typical values: 20-25. ADX must be above this to open new positions.")
adx_tf = input.timeframe("30", "ADX Timeframe", options=["30", "60", "240"], group=gp_filter, tooltip="Select ADX calculation timeframe: 30 (30m), 60 (1H), 240 (4H).")

// Timeframe check to ensure backtest is run on the correct chart resolution based on mode
if strat_mode == "30m-1H" and timeframe.period != "30"
    runtime.error("For 30m-1H mode, the strategy must be run on the 30-minute (30m) chart resolution.")
if strat_mode == "1H-4H" and timeframe.period != "60"
    runtime.error("For 1H-4H mode, the strategy must be run on the 1-hour (1H) chart resolution.")

// ==========================================
// 2. AUTO-DETECT CONTRACT FACE VALUE
// ==========================================

get_default_face_value() =>
    syminfo.pointvalue

face_value = auto_face_value ? get_default_face_value() : manual_face_value

// ==========================================
// 3. MULTI-TIMEFRAME INDICATORS
// ==========================================

// Signal Timeframe indicators (evaluated on current chart resolution: 30m for 30m-1H, 1H for 1H-4H)
[st_val_sig, st_dir_sig_raw] = ta.supertrend(st_mult, st_period)
// Map to python-style direction: 1 = green (bullish), -1 = red (bearish)
last_sig_dir = st_dir_sig_raw == -1 ? 1 : -1
last_sig_st = st_val_sig

// Custom Double Exponential Moving Average (DEMA) function (ta.dema is not built-in in Pine Script v5)
dema(src, length) =>
    ema1 = ta.ema(src, length)
    ema2 = ta.ema(ema1, length)
    2 * ema1 - ema2

// Helper function to calculate ADX/DMI
f_adx(len) =>
    [diplus, diminus, adx_val] = ta.dmi(len, len)
    adx_val

// Calculate ADX on the requested timeframe to filter micro-chop
adx_val = request.security(syminfo.tickerid, adx_tf, f_adx(adx_len), barmerge.gaps_off, barmerge.lookahead_off)
// Condition: Is the market trending enough?
adx_is_trending = not use_adx or (adx_val > adx_threshold)

// HTF Timeframe indicators function (evaluated on HTF to avoid lookahead bias)
f_htf_indicators() =>
    [st_val, st_dir_raw] = ta.supertrend(st_mult, st_period)
    dema_val = dema(close, dema_period)
    st_dir = st_dir_raw == -1 ? 1 : -1
    // Use lookahead_off in request.security to retrieve the completed HTF bar values
    [st_val, st_dir, dema_val, close]

// Dynamic HTF period resolution based on strategy mode
htf_period = (strat_mode == "30m-1H") ? "60" : "240"

// Request HTF indicators safely
[htf_st, htf_st_dir, htf_dema, htf_close] = request.security(syminfo.tickerid, htf_period, f_htf_indicators(), barmerge.gaps_off, barmerge.lookahead_off)

// ==========================================
// 4. COOLDOWN & CIRCUIT BREAKER STATE
// ==========================================

var int consecutive_losses = 0
var int cooldown_end_time = 0
var int cb_end_time = 0
var int last_closed_trades_count = 0
var int last_loss_time = 0

// Reset consecutive losses and cooldown end time after cooldown period ends
if cooldown_end_time > 0 and time >= cooldown_end_time
    consecutive_losses := 0
    cooldown_end_time := 0
    last_loss_time := 0

// Scan for closed trades to count consecutive losses and trigger cooldown
if strategy.closedtrades > last_closed_trades_count
    for i = last_closed_trades_count to strategy.closedtrades - 1
        trade_pnl = strategy.closedtrades.profit(i)
        
        // If more than 48 hours have passed since the last loss, reset the counter
        if consecutive_losses > 0 and last_loss_time > 0 and (time - last_loss_time) > 48 * 60 * 60 * 1000
            consecutive_losses := 0
            
        if trade_pnl < 0
            consecutive_losses := consecutive_losses + 1
            last_loss_time := time
        else
            consecutive_losses := 0
            last_loss_time := 0
        
        if enable_cooldown and consecutive_losses >= 3
            cooldown_end_time := time + cooldown_hours * 60 * 60 * 1000
            
    last_closed_trades_count := strategy.closedtrades

equity_val = nz(strategy.equity, 10000.0)

// Circuit Breaker triggers if equity drops below cb_equity (7 days stop)
if enable_cb and equity_val <= cb_equity and nz(strategy.equity[1], 10000.0) > cb_equity
    cb_end_time := time + 7 * 24 * 60 * 60 * 1000

in_cooldown = enable_cooldown and (time < cooldown_end_time)
in_cb = enable_cb and (equity_val <= cb_equity or time < cb_end_time)
can_trade = not (na(in_cooldown) ? false : in_cooldown) and not (na(in_cb) ? false : in_cb)

// ==========================================
// 5. POSITION SIZING & PHASE STATE MACHINE
// ==========================================

var float pos_entry_price = na
var float pos_stop_loss = na
var float pos_initial_30m_st = na
var int pos_phase = 0 // 0: None, 1: Survival, 2: Locked, 3: HTF Track
var float pos_qty = na

calculate_qty(stop_val) =>
    equity_val = nz(strategy.equity, 10000.0)
    sl_dist = math.abs(close - stop_val)
    risk_amt = (risk_mode == "fixed") ? risk_fixed_amount : (equity_val * risk_percent)
    calc_qty = sl_dist > 0 and not na(sl_dist) ? math.floor(risk_amt / (sl_dist * face_value)) : 0.0
    
    // Leverage safety cap: position value cannot exceed (equity * leverage)
    max_qty_leverage = math.floor((equity_val * leverage) / (close * face_value))
    final_qty = na(max_qty_leverage) ? calc_qty : na(calc_qty) ? max_qty_leverage : math.min(calc_qty, max_qty_leverage)
    
    math.max(1.0, na(final_qty) ? 1.0 : final_qty) // Minimum 1 contract

calculate_lock_threshold(entry_val, qty_val, is_long_pos) =>
    equity_val = nz(strategy.equity, 10000.0)
    risk_amt = (risk_mode == "fixed") ? risk_fixed_amount : (equity_val * risk_percent)
    buffer_usdt = risk_amt * lock_profit_buffer
    position_eth = qty_val * face_value
    if position_eth == 0
        entry_val
    else
        if is_long_pos
            entry_val + buffer_usdt / position_eth
        else
            entry_val - buffer_usdt / position_eth

tighten_sl(candidate, current, is_long_pos) =>
    if na(current) or current <= 0
        candidate
    else
        if is_long_pos
            math.max(candidate, current)
        else
            math.min(candidate, current)

// Track position state changes
pos_size = strategy.position_size
prev_pos_size = strategy.position_size[1]

is_new_long = (pos_size > 0 and prev_pos_size <= 0)
is_new_short = (pos_size < 0 and prev_pos_size >= 0)
is_active_pos = (pos_size != 0)

if is_new_long or is_new_short
    pos_entry_price := strategy.position_avg_price
    pos_initial_30m_st := last_sig_st
    pos_stop_loss := last_sig_st
    pos_phase := 1 // Survival
    pos_qty := math.abs(pos_size)
else if not is_active_pos
    pos_entry_price := na
    pos_initial_30m_st := na
    pos_stop_loss := na
    pos_phase := 0
    pos_qty := na

// Update stop loss trailing and stage transitions
if is_active_pos
    is_long_pos = pos_size > 0
    qty_val = pos_qty
    
    survival_to_locked_price = pos_entry_price
    locked_to_hourly_price = calculate_lock_threshold(pos_entry_price, qty_val, is_long_pos)
    
    // Stage 1 Check: Survival Phase
    is_survival = is_long_pos ? (last_sig_st < survival_to_locked_price) : (last_sig_st > survival_to_locked_price)
    
    if is_survival
        pos_phase := 1
        pos_stop_loss := tighten_sl(last_sig_st, pos_stop_loss, is_long_pos)
    else
        // Stage 3 Check: Switch Track (HTF) Phase
        is_htf = is_long_pos ? (htf_st > locked_to_hourly_price) : (htf_st < locked_to_hourly_price)
        if is_htf
            pos_phase := 3
            pos_stop_loss := tighten_sl(htf_st, pos_stop_loss, is_long_pos)
        else
            // Stage 2 Check: Lock Profit Phase
            pos_phase := 2
            candidate_stop = last_sig_st
            if is_long_pos
                if last_sig_st > locked_to_hourly_price
                    candidate_stop := locked_to_hourly_price
            else
                if last_sig_st < locked_to_hourly_price
                    candidate_stop := locked_to_hourly_price
            pos_stop_loss := tighten_sl(candidate_stop, pos_stop_loss, is_long_pos)

// ==========================================
// 6. ENTRY & EXIT TRIGGER LOGIC
// ==========================================

// Entry Conditions
can_long = nz(can_trade, false) and nz(htf_st_dir == 1, false) and nz(htf_close > htf_dema, false) and nz(last_sig_dir == 1, false) and nz(adx_is_trending, false)
can_short = nz(can_trade, false) and nz(htf_st_dir == -1, false) and nz(htf_close < htf_dema, false) and nz(last_sig_dir == -1, false) and nz(adx_is_trending, false)

// Position States
is_flat = strategy.position_size == 0
is_long = strategy.position_size > 0
is_short = strategy.position_size < 0

// Exit Conditions
exit_signal = false
exit_reason = ""

if is_active_pos
    is_long_pos = pos_size > 0
    if is_long_pos
        if pos_phase == 3 and htf_st_dir == -1
            exit_signal := true
            exit_reason := (strat_mode == "30m-1H" ? "1H ST Red" : "4H ST Red")
        else if (pos_phase == 1 or pos_phase == 2) and last_sig_dir == -1
            exit_signal := true
            exit_reason := (strat_mode == "30m-1H" ? "30m ST Red" : "1H ST Red")
    else // Short position
        if pos_phase == 3 and htf_st_dir == 1
            exit_signal := true
            exit_reason := (strat_mode == "30m-1H" ? "1H ST Green" : "4H ST Green")
        else if (pos_phase == 1 or pos_phase == 2) and last_sig_dir == 1
            exit_signal := true
            exit_reason := (strat_mode == "30m-1H" ? "30m ST Green" : "1H ST Green")

// Order execution (includes reversal rules)
if is_flat
    if can_long
        entry_qty = calculate_qty(last_sig_st)
        strategy.entry("Long", strategy.long, qty=entry_qty)
    else if can_short
        entry_qty = calculate_qty(last_sig_st)
        strategy.entry("Short", strategy.short, qty=entry_qty)

else if is_long
    if exit_signal
        if can_short
            reverse_qty = calculate_qty(last_sig_st)
            strategy.entry("Short", strategy.short, qty=reverse_qty, comment="Reverse Short")
        else
            strategy.close("Long", comment=exit_reason)
    else if can_short // Direct reversal
        reverse_qty = calculate_qty(last_sig_st)
        strategy.entry("Short", strategy.short, qty=reverse_qty, comment="Reverse Short")

else if is_short
    if exit_signal
        if can_long
            reverse_qty = calculate_qty(last_sig_st)
            strategy.entry("Long", strategy.long, qty=reverse_qty, comment="Reverse Long")
        else
            strategy.close("Short", comment=exit_reason)
    else if can_long // Direct reversal
        reverse_qty = calculate_qty(last_sig_st)
        strategy.entry("Long", strategy.long, qty=reverse_qty, comment="Reverse Long")

// Trailing / Dynamic Stop Loss order execution
if is_active_pos
    if pos_size > 0
        strategy.exit("SL Long", "Long", stop=pos_stop_loss)
    else
        strategy.exit("SL Short", "Short", stop=pos_stop_loss)

// ==========================================
// 7. CHART VISUALIZATION & HUD PANEL
// ==========================================

// Plot Stop Loss and Entry Prices
plot_entry = plot(pos_entry_price, title="Entry Price", color=color.blue, style=plot.style_linebr, linewidth=1)
plot_sl = plot(pos_stop_loss, title="Stop Loss", color=color.red, style=plot.style_linebr, linewidth=2)

qty_val_plot = is_active_pos ? pos_qty : 0.0
locked_to_hourly_price_plot = is_active_pos ? calculate_lock_threshold(pos_entry_price, qty_val_plot, pos_size > 0) : na
plot_lock = plot(pos_phase >= 2 ? locked_to_hourly_price_plot : na, title="Lock Profit Threshold", color=color.orange, style=plot.style_linebr, linewidth=1)

fill(plot_entry, plot_sl, color=color.new(color.red, 95), title="Risk Band")

// Plot underlying indicators for visual checks
plot(st_val_sig, title="Signal SuperTrend", color=st_dir_sig_raw == -1 ? color.green : color.red, linewidth=1, style=plot.style_line)
plot(htf_dema, title="HTF DEMA", color=color.new(color.blue, 30), linewidth=2)
plot(htf_st, title="HTF SuperTrend", color=htf_st_dir == 1 ? color.new(color.green, 30) : color.new(color.red, 30), linewidth=2)

// Paint background during cooldown / cb
bgcolor(in_cb ? color.new(color.red, 95) : in_cooldown ? color.new(color.orange, 95) : na, title="Trading Restriction Background")

// HUD Table overlay in top-right
var table hud = table.new(position.top_right, 2, 8, bgcolor=color.new(color.black, 30), border_color=color.gray, border_width=1)

if barstate.islast
    table.cell(hud, 0, 0, "V9.7 Metric", text_color=color.white, bgcolor=color.blue, text_size=size.small)
    table.cell(hud, 1, 0, "Current Value", text_color=color.white, bgcolor=color.blue, text_size=size.small)
    
    // Trading status
    status_text = in_cb ? "Circuit Breaker" : in_cooldown ? "Cooldown (48h)" : "Normal"
    status_color = in_cb or in_cooldown ? color.red : color.green
    table.cell(hud, 0, 1, "Trading Status", text_color=color.white, text_size=size.small)
    table.cell(hud, 1, 1, status_text, text_color=status_color, text_size=size.small)
    
    // Phase
    phase_text = pos_phase == 1 ? "1. Survival" : pos_phase == 2 ? "2. Locked" : pos_phase == 3 ? (strat_mode == "30m-1H" ? "3. Hourly" : "3. 4H Track") : "None"
    phase_color = pos_phase == 1 ? color.aqua : pos_phase == 2 ? color.yellow : pos_phase == 3 ? color.purple : color.gray
    table.cell(hud, 0, 2, "Position Phase", text_color=color.white, text_size=size.small)
    table.cell(hud, 1, 2, phase_text, text_color=phase_color, text_size=size.small)
    
    // Size
    pos_eth = is_active_pos ? (pos_qty * face_value) : 0.0
    table.cell(hud, 0, 3, "Position Size (" + syminfo.basecurrency + ")", text_color=color.white, text_size=size.small)
    table.cell(hud, 1, 3, str.tostring(pos_eth) + (pos_size > 0 ? " LONG" : pos_size < 0 ? " SHORT" : ""), text_color=color.white, text_size=size.small)
    
    // Stop loss
    sl_text = is_active_pos ? str.tostring(pos_stop_loss, "#.##") : "N/A"
    table.cell(hud, 0, 4, "Active Stop Loss", text_color=color.white, text_size=size.small)
    table.cell(hud, 1, 4, sl_text, text_color=color.white, text_size=size.small)
    
    // Lock profit threshold
    lock_text = is_active_pos ? str.tostring(locked_to_hourly_price_plot, "#.##") : "N/A"
    table.cell(hud, 0, 5, "Lock profit threshold", text_color=color.white, text_size=size.small)
    table.cell(hud, 1, 5, lock_text, text_color=color.white, text_size=size.small)
    
    // Consecutive losses
    table.cell(hud, 0, 6, "Consecutive Losses", text_color=color.white, text_size=size.small)
    table.cell(hud, 1, 6, str.tostring(consecutive_losses) + " / 3", text_color=consecutive_losses >= 3 ? color.red : color.white, text_size=size.small)
    
    // Face value
    table.cell(hud, 0, 7, "Face Value Unit", text_color=color.white, text_size=size.small)
    table.cell(hud, 1, 7, str.tostring(face_value), text_color=color.white, text_size=size.small)

Overview

ETH Perp Trading Bot V9.7 Strategy Backtest combines a SuperTrend with a DEMA and an optional ADX filter that blocks new entries in choppy markets. Risk is sized from a fixed amount or a percentage of equity with a leverage setting, a lock-profit stage measured in risk multiples, a loss cooldown and an equity circuit breaker.

Details

Published by

xunxuntj on GitHub

Type

Strategy, Pine Script v5

Draws

On the price chart

Category

Trend

Markets

Crypto

Timeframes

M15-H1

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Strategy Modestring30m-1Hstrat_mode
SuperTrend Periodint10st_period
SuperTrend Multiplierfloat3.0st_mult
DEMA Periodint200dema_period
Risk Modestringpercentrisk_mode
Fixed Risk Amount (USDT)float10.0risk_fixed_amount
Percent Risk of Equity (%)float2.0risk_percent
Leveragefloat10.0leverage
Lock Profit Buffer (R Ratio)float1.0lock_profit_buffer
Auto-detect Face Valuebooltrueauto_face_value
Manual Face Value (contracts multiplier)float0.01manual_face_value
Enable Cooldown (3 Losses)booltrueenable_cooldown
Show all 19 settings
SettingTypeDefaultVariable
Cooldown Duration (Hours)int48cooldown_hours
Enable Circuit Breakerbooltrueenable_cb
Circuit Breaker Equity Thresholdfloat350.0cb_equity
Enable ADX Filterbooltrueuse_adx
ADX Lengthint14adx_len
ADX Thresholdint20adx_threshold
ADX Timeframetimeframe30adx_tf
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

Doge SMA

by hackingthemarkets
474 stars

Doge SMA is a long-only moving-average crossover strategy drawn on the price chart. It calculates a fast and a slow simple moving average of close and enters a long position when the fast average crosses above the slow average, but only inside a user-defined s

Strategy v4 TrendMoving averages
Updated 4 years ago · None stated GitHub repository of Doge SMA

This strategy calculates and plots a fast Exponential Moving Average (EMA) and a slow EMA directly on the main price chart. It enters long trades when the fast EMA crosses above the slow EMA and exits when the fast EMA crosses below the slow EMA. Inputs allow

Strategy v6 TrendMoving averages
Updated yesterday · AGPL-3.0 GitHub repository of Forven S01508 — Simple EMA20/50 Cross
330 stars

2 EMA/SMA + RSI Strategy [Alorse] combines three configurable moving averages with a short-period Relative Strength Index filter. It plots fast, slow, and trend moving averages on the price chart. Long entries trigger when the fast moving average is above the

Strategy v4 TrendOscillators & momentum
Updated 2 months ago · None stated GitHub repository of 2 EMA/SMA + RSI Strategy [Alorse]

Acrypto - Weighted Strategy

by AlbertoCuadra
318 stars

This strategy plots on the price chart and opens long or short positions when a weighted score from MACD, Stochastic RSI, RSI, Supertrend and a moving-average crossover exceeds a user-set trigger. Each component has its own weight and candle delay. Entries can

Strategy v5 TrendOscillators & momentum
Updated 3 years ago · Custom licence GitHub repository of Acrypto - Weighted Strategy
285 stars

Mean Reversion Strategy is an overlay strategy that identifies pullbacks using a long-term EMA, RSI, and candlestick patterns. It generates long signals when a bullish engulfing candle forms below the EMA while RSI is oversold, and short signals when a bearish

Strategy v4 Mean reversionCandlestick patterns
Updated 3 years ago · None stated GitHub repository of Mean Reversion Strategy
257 stars

This strategy calculates dynamic support and resistance levels using pivot highs and lows alongside a custom smoothed trend filter and a 3-period EMA. It identifies entry opportunities when price breaks out relative to the trend filter and short-term EMA cross

Strategy v5 TrendSupport & resistance Repaints
Updated 6 weeks ago · None stated GitHub repository of 30s - ES 1m Strategy Candle Bar

More strategys

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers