tvpinescript

open
close

Final 15 Strategy: A Comprehensive Trading System Combining Adaptive Indicators

January 21, 2025 | by admin

bandicam 2025-01-21 14-08-04-656

Successful trading requires a strategic approach that leverages multiple market indicators for precise entry and exit decisions. Final 15, a Pine Script-based strategy, offers traders a robust trading system incorporating advanced indicators such as cRSI, HTF MESA MA, ALMA, and MACD, along with built-in risk management features. This strategy aims to help traders capitalize on market movements effectively while minimizing risk.

However, it’s essential to remember that no trading indicator guarantees profits. Final 15 should be used as a guide within a well-structured trading plan that includes risk management and proper market analysis.

Key Features of the Script:

  1. Comprehensive Indicator Integration:
    • Combines multiple indicators, including:
      • cRSI (Cumulative RSI) for trend confirmation.
      • HTF MESA MA (Adaptive Moving Average) for high-timeframe trend filtering.
      • ALMA (Arnaud Legoux Moving Average) for smooth trend tracking.
      • MACD for momentum analysis and trend validation.
  2. Automated Trade Execution:
    • Implements an automated trading strategy using percentage-based position sizing, ensuring consistent risk allocation.
    • Includes configurable commission settings to simulate real trading conditions.
  3. Advanced Stop-Loss and Take-Profit Mechanism:
    • Customizable stop-loss (SL) and take-profit (TP) percentages, allowing traders to adapt risk-reward ratios to market conditions.
    • Automatic trailing features based on ATR and MESA pivots.
  4. Multi-Timeframe Analysis (MTF):
    • Supports trading decisions based on higher timeframes, improving accuracy by filtering noise from lower timeframes.
    • The HTF MESA MA component allows trend alignment across multiple timeframes.
  5. Market Structure Recognition:
    • Identifies key pivot highs and lows using MESA pivots, offering a dynamic support/resistance system.
    • Plots potential breakout and reversal zones based on historical price action.
  6. Zigzag and Reversal Detection:
    • Uses a zigzag pattern algorithm to identify key swing points and potential reversal areas.
    • Provides visual alerts for bullish and bearish reversals.
  7. Dynamic Trend Filtering with ALMA and MACD:
    • Filters false signals by aligning trades with trend direction confirmed by ALMA and MACD.
    • Avoids trading against the primary market trend.
  8. Chandelier Exit Integration:
    • Incorporates the Chandelier Exit system for dynamic stop placement.
    • Can be used as an additional filter for trade entries and exits.
  9. Real-Time Alerts and Notifications:
    • Alerts for buy and sell signals, as well as stop-loss triggers, ensuring traders never miss an opportunity.
    • Push notifications for mobile trading convenience.
  10. User-Friendly Customization:
  • Easily adjustable input parameters such as trade direction, timeframe, ATR settings, and commission values.
  • Clean visual representation with trend color coding.

Recommended Usage:

  1. Scalping:
    • Best suited for 5-minute to 15-minute charts.
    • Use with ALMA and MACD filters for quick in-and-out trades.
  2. Day Trading:
    • Effective on 30-minute to 1-hour charts.
    • Combines MESA pivots and cRSI to find optimal entry points.
  3. Swing Trading:
    • Recommended for 4-hour to daily charts.
    • HTF MESA and Chandelier Exit help manage longer-term trades with precise stop levels.
  4. Risk Management Strategy:
    • Leverage ATR-based stop-loss levels to avoid unnecessary risk.
    • Utilize take-profit levels to lock in gains and avoid emotional decision-making.

Script Evaluation:

  • Functionality: 4.8/5
    A well-designed trading strategy with advanced indicator integration and automated execution.
  • Ease of Use: 4.3/5
    The script includes extensive customization options, making it versatile but requiring some learning for beginners.
  • Accuracy: 4.6/5
    Offers reliable trade signals when applied with trend-following principles and proper risk management.
  • Repainting Analysis:
    This script does not repaint.
    All calculations are based on confirmed bar data, ensuring accuracy during live trading and backtesting.
  • Optimal Timeframes:
    • Scalping: 5-minute to 15-minute charts.
    • Day Trading: 30-minute to 1-hour charts.
    • Swing Trading: 4-hour to daily charts.
  • Author and Development Quality:
    The script appears well-coded with professional-level logic, although no specific author attribution is provided.
  • Overall Score: 4.7/5
    A highly adaptable tool for traders looking to optimize entries and exits with advanced trend-following and risk management techniques.

// @version=5
strategy(" final 15", shorttitle="final 15 ", overlay=true,  pyramiding = 0, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, commission_type = strategy.commission.percent, commission_value = 0.05, initial_capital = 300)

GROUP_GLOBAL_OPTIONS = "Global Options"
GROUP_TIME_LIMITED_BACKTESTS = "Time-Limit BackTests (0 = disable)"
GROUP_CRSI_OPTIONS = "cRSI Options"
GROUP_HTF_MESA_MA = "HTF Adaptive MESA MA Options"
GROUP_ALMA = "ALMA Trend Direction Options"
GROUP_MACD = "MACD Options"
GROUP_MESA = "MESA Pivots Options"

i_sl_perc = input(4, title="Stop Loss Percentage")
i_tp_perc = input.float(1, title="Take Profit Percentage") // Cambiamos 'var float' a 'input.float' para hacerlo más claro


SLPerc=i_sl_perc

TPPerc = i_tp_perc

i_use_crsi = input.bool( true, "Trade by cRSI", group = GROUP_CRSI_OPTIONS )
i_show_crsi = input.bool( true, "Show cRSI Pivots", group = GROUP_CRSI_OPTIONS )
i_i_len   = input( 21, "cRSI EMA period", group = GROUP_CRSI_OPTIONS )
i_src     = input.source( close, 'cRSI Source',  group = GROUP_CRSI_OPTIONS )
i_trade_trend_direction = input( true, "cRSI trade in trend direction only", group = GROUP_CRSI_OPTIONS )
i_trade_trend_direction_change_percent_cancel = input.float( 3, "cRSI price change (%) to cancel trade in trend direction", group = GROUP_CRSI_OPTIONS )

i_use_htf_mesa = input.bool( true, "Trade by HTF Adaptive MESA MA", group = GROUP_HTF_MESA_MA )
i_show_htf_mesa = input.bool(true, "Show HFT Adaptive MESA MA", group = GROUP_HTF_MESA_MA )
_tf = input.timeframe( '60', "HTF Adaptive MESA MA Resolution", group = GROUP_HTF_MESA_MA )

i_use_alma = input.bool( true, "Trade by ALMA Trend Direction", group = GROUP_ALMA )
i_show_alma = input.bool(true, "Show ALMA", group = GROUP_ALMA )
alma_len = input.int( 50, "Arnaud Legoux MA Length", minval = 1, group = GROUP_ALMA )
alma_offset = input.float( 2, "ALMA Offset", minval = 0.0001, group = GROUP_ALMA )
alma_sigma = input.int( 10, title="ALMA Sigma Value", minval = 1, group = GROUP_ALMA )

i_use_macd = input.bool( true, "Trade by MACD", group = GROUP_MACD )
macd_fast = input.int( 10, "MACD Fast Length", minval = 1, group = GROUP_MACD )
macd_slow = input.int( 25, "MACD Slow Length", minval = 1, group = GROUP_MACD )
macd_smooth = input.int( 10, "MACD Signal Smoothing", minval = 0, group = GROUP_MACD )

i_use_mesa = input.bool( true, "Trade by MESA Pivots", group = GROUP_MESA )
i_show_mesa = input.bool( true, "Show MESA Pivots", group = GROUP_MESA )
offsetNum = input( 0, "MESA offset", group = GROUP_MESA)
pivot_zone_upper = input.float( 0.4, "MESA pivot zone upper", step=0.1, group = GROUP_MESA )
pivot_zone_lower = input.float( -0.4, "MESA pivot zone lower", step=0.1, group = GROUP_MESA )
min_mesa_pivots_gap_minutes = input( 20, "MESA minimum pivots gap (minutes)", group = GROUP_MESA)



inDateRange = true

// Look if the close time of the current bar falls inside the date range

//------------------------------------------------------------------------------
// persisting variables
//------------------------------------------------------------------------------

var cRSI_high_extreme_found = 0.0
var cRSI_high_extreme_valid = true
var cRSI_low_extreme_found = 0.0
var cRSI_low_extreme_valid = true
var last_cRSI_extreme = ""
var last_pivot_ts = time
var last_trade_ts = time
var mesa_ma_trend_direction = ""
var alma_trend_direction = ""
var macd_trend_direction = ""
var min_trade_gap_minutes = 2

//------------------------------------------------------------------------------
// MESA calculations from the MESA indicator
//------------------------------------------------------------------------------
// Basic
//------------------------------------------------------------------------------

DomCycle = 15
RealPart = 0.0
ImagPart = 0.0

for J = 0 to DomCycle - 1
    Weight = (close[J] + close[J] + high[J] + low[J]) * 10000
    if DomCycle != 0
        RealPart := RealPart + math.cos(90 * J / DomCycle) * Weight * 2
        ImagPart := ((ImagPart + math.sin(90 * J / DomCycle) * Weight) + (ImagPart + math.sin(180 * J / DomCycle) * Weight)) / 2

Phase = ((math.atan(ImagPart / RealPart)) - 0.685) * 100

//------------------------------------------------------------------------------
//Pivot
//------------------------------------------------------------------------------

ph_mesa = ta.pivothigh(Phase, 1, 1)
pl_mesa = ta.pivotlow(Phase, 1, 1)

out_zone = Phase[2] < pivot_zone_lower or Phase[2] > pivot_zone_upper

plotshape(i_show_mesa and ph_mesa and out_zone ? ph_mesa : na, title = "Pivot High", color=#f23737, style = shape.circle, location = location.abovebar, offset = -1, size = size.tiny)
plotshape(i_show_mesa and pl_mesa and out_zone ? pl_mesa : na, title = "Pivot Low", color=#169788, style = shape.circle, location = location.belowbar, offset = -1, size = size.tiny)


//------------------------------------------------------------------------------
// MESA adaptive moving average indicator code
//------------------------------------------------------------------------------
tf1 = _tf == '0' ? timeframe.period : _tf
fast = 0.25
slow = 0.05

//Returns scalar difference between current timeframe and requested
ResolutionToMin(tf)=>
    mins = tf=="1M" ? 43830 : tf=="1W" ?   10080: tf=="1D" ?   1440 :tf=="240"?   240 :tf=="180"?   180 :tf=="120"?   120 :tf=="60"?    60  :tf=="45"?    45  :tf=="30"?    30  :tf=="15"?    15  :tf=="5"?     5   :tf=="3"?     3   :tf=="1"?     1   :   -1
    mins
chart_res = ResolutionToMin(timeframe.period)
if(timeframe.isdwm)
    chart_res := ResolutionToMin(str.tostring(timeframe.multiplier) + timeframe.period)
req_res = ResolutionToMin(_tf)
scale = req_res==-1 or chart_res==-1 or chart_res>req_res ? 1 : chart_res/req_res
    
    
//MESA Moving Average`
//Args: src - the series to perform MAMA calculations on
//      fast - limit to the fast moving average calc (default 0.5)
//      slow - limit to the slow moving average calc (default 0.05)
//      hide - for usage with multiple MESA plots. set to True to return [na,na]
//##############################################################################
getMESA(src_in, fast, slow, show) =>
    Price = src_in
    FastLimit = fast
    SlowLimit = slow
    MAMA = src_in
    FAMA = src_in
    PI = 3.14159
    Smooth = 0.0
    Detrender = 0.0
    I1 = 0.0
    Q1 = 0.0
    jI = 0.0
    jQ = 0.0
    I2 = 0.0
    Q2 = 0.0
    Re = 0.0
    Im = 0.0
    Period = 0.0
    SmoothPeriod = 0.0
    Phase = 0.0
    DeltaPhase = 0.0
    alpha = 0.0
    if(na(Price))
        MAMA := MAMA[1]
        FAMA := FAMA[1]
        Smooth := Smooth[1]
        Detrender := Detrender[1]
        I1 := I1[1]
        Q1 := Q1[1]
        I2 := I2[1]
        Q2 := Q2[1]
        Re := Re[1]
        Im := Im[1]
        Period := Period[1]
        SmoothPeriod := SmoothPeriod[1]
        Phase := Phase[1]
        
    if(bar_index > 5 and show and not na(Price))
        Smooth := (4 * Price + 3 * Price[1] + 2 * Price[2] + Price[3]) / 10
        Detrender := (0.0962 * Smooth + 0.5769 * Smooth[2] - 0.5769 * Smooth[4] - 0.0962 * Smooth[6]) * 
           (0.075 * Period[1] + 0.54)
        //Get the Inphase & Quadtrature Components
        Q1 := (0.0962 * Detrender + 0.5769 * Detrender[2] - 0.5769 * Detrender[4] - 
           0.0962 * Detrender[6]) * (0.075 * Period[1] + 0.54)
        I1 := Detrender[3]
        //Advance phase angle by 90 deg
        jI := (0.0962 * I1 + 0.5769 * I1[2] - 0.5769 * I1[4] - 0.0962 * I1[6]) * 
           (0.075 * Period[1] + 0.54)
        jQ := (0.0962 * Q1 + 0.5769 * Q1[2] - 0.5769 * Q1[4] - 0.0962 * Q1[6]) * 
           (0.075 * Period[1] + 0.54)
        //Phasor addition for 3-bar averaging 
        I2 := I1 - jQ
        Q2 := Q1 + jI
        //Smooth the I and Q components before applying the discriminator 
        I2 := 0.2 * I2 + 0.8 * I2[1]
        Q2 := 0.2 * Q2 + 0.8 * Q2[1]
        //Homodyne Discriminator 
        Re := I2 * I2[1] + Q2 * Q2[1]
        Im := I2 * Q2[1] - Q2 * I2[1]
        Re := 0.2 * Re + 0.8 * Re[1]
        Im := 0.2 * Im + 0.8 * Im[1]
        if Im != 0 and Re != 0
            Period := 2 * PI / math.atan(Im / Re)
        Period := Period > 1.5 * Period[1] ? 1.5 * Period[1] : Period
        Period := Period > 50 ? 50 : Period
        Period := Period < 0.67 * Period[1] ? 0.67 * Period[1] : Period
        Period := Period < 6 ? 6 : Period
        Period := 0.2 * Period + 0.8 * Period[1]
        SmoothPeriod := 0.33 * Period + 0.67 * SmoothPeriod[1]
        if I1 != 0
            Phase := 180 / PI * math.atan(Q1 / I1)
        DeltaPhase := Phase[1] - Phase
        if DeltaPhase < 1
            DeltaPhase := 1
        alpha := FastLimit / DeltaPhase
        alpha := alpha < SlowLimit ? SlowLimit : alpha
        alpha := alpha > FastLimit ? FastLimit : alpha
        MAMA := alpha * Price + (1 - alpha) * MAMA[1]
        FAMA := 0.5 * alpha * MAMA + (1 - 0.5 * alpha) * FAMA[1]
    if(not show)
        MAMA := na
        FAMA := na
    [MAMA, FAMA]

[M_1, F_1] = getMESA(close, fast*scale, slow*scale, true)

//Simple function to grab the color of the fill given a Mama / Fama tuple
//Args : mama - the Mesa adaptive moving average
//       fama - the follower moving average (generated by prior)
//##############################################################################
fillColor(mama, fama, show) =>
    color_1 = color.new(color.white, 100)
    ret = show ? mama > fama ? color.red : color.blue : color_1
    ret
//##############################################################################

p_m_1 = plot(M_1, "MAMA on HTF Adaptive MESA", i_show_htf_mesa ? color.maroon : na, 2)
p_f_1 = plot(F_1, "FAMA on HTF Adaptive MESA", i_show_htf_mesa ? color.navy : na, 2)
fill_1 = fillColor(M_1, F_1, i_show_htf_mesa)
fill(p_m_1, p_f_1, fill_1, "Fill1")

if mesa_ma_trend_direction == "" or ta.cross( M_1, F_1 )
    if M_1 > F_1
        mesa_ma_trend_direction := "up"
    else
        mesa_ma_trend_direction := "down"



//------------------------------------------------------------------------------
// ALMA Trend Direction indicator code
//------------------------------------------------------------------------------
trendALMA = ta.alma(close, alma_len, alma_offset, alma_sigma)

if low > trendALMA
    alma_trend_direction := "up"
else
    alma_trend_direction := "down"
    
p0 = plot(i_show_alma ? trendALMA : na, color = color.new( color.black, 100 ))
p1 = plot(i_show_alma ? close : na, color=color.new( color.black, 100 ))
fill(p0, p1, color=low > trendALMA ? color.new( #00ff00, 82) : color.new( #c2185b, 81 ))
    
//------------------------------------------------------------------------------
// MACD
//------------------------------------------------------------------------------
if i_use_macd
    [ macdLine, signalLine, hist ] = ta.macd(close, macd_fast, macd_slow, macd_smooth)
    if macdLine > signalLine
        macd_trend_direction := "up"
    else
        macd_trend_direction := "down"

crsi       = 0.0
vibration  = 10
torque     = 0.618 / (vibration + 1)
phasingLag = (vibration - 1) / 0.618

rsi        = ta.rsi(i_src, i_i_len)
crsi      := torque * (2 * rsi - rsi[phasingLag]) + (1 - torque) * nz(crsi[1])

float osc = crsi
float ph = ta.highestbars(high, i_i_len) == 0 ? osc : na
float pl = ta.lowestbars(low,   i_i_len) == 0 ? osc : na

var int dir = 0
dir := ph and na(pl) ? 1 : pl and na(ph) ? -1 : dir

var max_array_size = 10
var arr_zz         = array.new_float(0)
older_zz           = array.copy(arr_zz)
dirchanged         = ta.change(dir)

add_to_zigzag(_id, float value, int bindex) =>
    array.unshift(_id, bindex)
    array.unshift(_id, value)
    if array.size(_id) > max_array_size
        array.pop(_id)
        array.pop(_id)

update_zigzag(_id, float value, int bindex, int dir) =>
    if array.size(_id) == 0
        add_to_zigzag(_id, value, bindex)
    else
        if dir == 1 and value > array.get(_id, 0) or dir == -1 and value < array.get(_id, 0)
            array.set(_id, 0, value)
            array.set(_id, 1, bindex)
        0.

if ph or pl
    if dirchanged
        add_to_zigzag(arr_zz, dir == 1 ? ph : pl, bar_index)
    else
        update_zigzag(arr_zz, dir == 1 ? ph : pl, bar_index, dir)

if array.size(arr_zz) >= 6
    // Variables
    var label label_zz = na

    // Bools for or
    bool bool_or_1 = array.get(arr_zz, 0) != array.get(older_zz, 0)
    bool bool_or_2 = array.get(arr_zz, 1) != array.get(older_zz, 1)
    
    // Bools for and
    bool bool_n_1 = array.get(arr_zz, 2) == array.get(older_zz, 2)
    bool bool_n_2 = array.get(arr_zz, 3) == array.get(older_zz, 3)
    
    // Bools for more than and less than
    bool bool_0_mt_4 = array.get(arr_zz, 0) > array.get(arr_zz, 4)
    bool bool_0_lt_4 = array.get(arr_zz, 0) < array.get(arr_zz, 4)

    if bool_or_1 or bool_or_2
        if bool_n_1 and bool_n_2
            label.delete(label_zz)
        str_label = dir == 1 ?   bool_0_mt_4 ? '▼'     : '◍' :
                                 bool_0_lt_4 ? '▲'     : '◍'
        col_label = dir == 1 ?   bool_0_mt_4 ? color.red  : color.teal :
                                 bool_0_lt_4 ? color.teal : color.red

        if i_show_crsi
            label_zz := label.new(bar_index, high, text = str_label, color = color.new(color.blue, 100), textcolor = col_label, style=dir == 1 ? label.style_label_down : label.style_label_up )

        if dir == 1
            cRSI_high_extreme_found := close
            cRSI_low_extreme_found := 0.0
            last_cRSI_extreme := "high"
        else
            cRSI_low_extreme_found := close
            cRSI_high_extreme_found := 0.0
            last_cRSI_extreme := "low"

        // if we found a cRSI extreme close any open trades here
        if i_use_crsi and cRSI_high_extreme_found > 0.0
            strategy.close( "Buy", comment = "close buy (cRSI)" )
        if i_use_crsi and cRSI_low_extreme_found > 0.0
            strategy.close( "Sell", comment = "close sell (cRSI)" )


// check that our last found high extreme is not more than i_trade_trend_direction_change_percent_cancel percent lower than our current price
// in which case we'll mark it as invalid, so we can keep on opening buy entries
if i_use_crsi and i_trade_trend_direction and cRSI_high_extreme_found > 0.0
    if cRSI_high_extreme_found != close
        extreme_distance_from_last_point_percent = ( ( cRSI_high_extreme_found - close ) / cRSI_high_extreme_found ) * 100
        cRSI_high_extreme_valid := close < cRSI_high_extreme_found or math.abs( extreme_distance_from_last_point_percent ) < i_trade_trend_direction_change_percent_cancel

    // reset the high extreme to current price if we found out that we're redrawing it further
    if not cRSI_high_extreme_valid
        cRSI_high_extreme_found := close
        cRSI_high_extreme_valid := false
else
    cRSI_high_extreme_valid := true


// check that our last found low extreme is not more than i_trade_trend_direction_change_percent_cancel percent higher than our current price
// in which case we'll mark it as invalid, so we can keep on opening sell entries
if i_use_crsi and i_trade_trend_direction and cRSI_low_extreme_found > 0.0
    if cRSI_low_extreme_found != close
        extreme_distance_from_last_point_percent = ( ( cRSI_low_extreme_found - close ) / cRSI_low_extreme_found ) * 100
        cRSI_low_extreme_valid := close > cRSI_low_extreme_found or math.abs( extreme_distance_from_last_point_percent ) < i_trade_trend_direction_change_percent_cancel

    // reset the high extreme to current price if we found out that we're redrawing it further
    if not cRSI_low_extreme_valid
        cRSI_low_extreme_found := close
        cRSI_low_extreme_valid := false
else
    cRSI_low_extreme_valid := true


//@version=5

// indicator('Chandelier Exit', shorttitle='CEBTC 1h', overlay=true)

ce(length,mult,useClose,tf_ce,sy_ce)=>
    atr = mult * ta.atr(length)

    longStop_ce = (useClose ? ta.highest(close, length) : ta.highest(length)) - atr
    longStopPrev = nz(longStop_ce[1], longStop_ce)

    shortStop_ce = (useClose ? ta.lowest(close, length) : ta.lowest(length)) + atr
    shortStopPrev = nz(shortStop_ce[1], shortStop_ce)

    var int dir_ce_ = 1
    dir_ce_ := close > shortStopPrev ? 1 : close < longStopPrev ? -1 : dir_ce_
    longStop_ce := close[1] > longStopPrev ? math.max(longStop_ce, longStopPrev) : longStop_ce
    shortStop_ce := close[1] < shortStopPrev ? math.min(shortStop_ce, shortStopPrev) : shortStop_ce

    [dir_ce,longStop,shortStop] = request.security(sy_ce,tf_ce,[dir_ce_,longStop_ce,shortStop_ce])
use_ce4 = input(true, "use as Filter for Entry",group = "Chandelier Exit for Another Symbol")
use_ce3 = input(true, "use as Filter for Reversal Entry",group = "Chandelier Exit for Another Symbol")
length = input(title='ATR Period', defval=14,group = "Chandelier Exit for Another Symbol")
mult = input.float(title='ATR Multiplier', step=0.1, defval=2.5,group = "Chandelier Exit for Another Symbol")
// showLabels = input(title='Show Buy/Sell Labels ?', defval=true,group = "Chandelier Exit for Another Symbol")
useClose = input(title='Use Close Price for Extremums ?', defval=true,group = "Chandelier Exit for Another Symbol")
// highlightState = input(title='Highlight State ?', defval=true,group = "Chandelier Exit for Another Symbol")

tf_ce = input.timeframe("60","Chandelier Exit Timeframe",group = "Chandelier Exit for Another Symbol")
sy_ce = input.symbol("BTC1!","Chandelier Exit Symbol",group = "Chandelier Exit for Another Symbol")

[dir_ce,longStop,shortStop] = ce(length,mult,useClose,tf_ce,sy_ce)
use_ce = input(false, "use as Filter for Entry",group = "Chandelier Exit")
use_ce1 = input(false, "use as Filter for Reversal Entry",group = "Chandelier Exit")
length_ = input(title='ATR Period', defval=14,group = "Chandelier Exit")
mult_ = input.float(title='ATR Multiplier', step=0.1, defval=2.5,group = "Chandelier Exit")
// showLabels_ = input(title='Show Buy/Sell Labels ?', defval=true,group = "Chandelier Exit")
useClose_ = input(title='Use Close Price for Extremums ?', defval=true,group = "Chandelier Exit")
// highlightState_ = input(title='Highlight State ?', defval=true,group = "Chandelier Exit")

tf_ce_ = input.timeframe("60","Chandelier Exit Timeframe",group = "Chandelier Exit")
sy_ce_ = syminfo.tickerid// input.symbol("BTC1!","Chandelier Exit Symbol",group = "Chandelier Exit")

[dir_ce_,longStop_,shortStop_] = ce(length_,mult_,useClose_,tf_ce_,sy_ce_)



// MESA pivot high was found
if ( not i_use_mesa or ( ph_mesa and out_zone ) ? ph_mesa : na )
    // close trade if a cRSI extreme was previously found, otherwise let the cRSI close the trade once it gets there
    if not i_use_crsi or ( cRSI_high_extreme_found > 0.0 and cRSI_high_extreme_valid )
        strategy.close( "Buy", comment = "close buy (" + ( i_use_mesa ? "MESA" : i_use_crsi ? "cRSI" : i_use_htf_mesa ? "HTF MESA" : "unknown" ) + ")" )
        // open a counter-strategy, if:
        //   1) we're not too close to the last trade's TS
        //   2) we're in the correct cRSI trend (if enabled)
        //   3) we're in the correct MESA HTF MA trend (if enabled)
        //   4) we're in the correct ALMA trend (if enabled)
        //   5) we're in the correct MACD trend (if enabled)
        if ( inDateRange and ( ( time - last_trade_ts ) / 1000 >= ( 60 * min_trade_gap_minutes ) ) and ( not i_use_crsi or last_cRSI_extreme == "high" ) and ( not i_use_mesa or ( i_use_mesa and ( time - last_pivot_ts ) / 1000 >= ( 60 * min_mesa_pivots_gap_minutes ) ) ) and ( not i_use_crsi or not i_trade_trend_direction or last_cRSI_extreme == "high" ) and ( not i_use_htf_mesa or mesa_ma_trend_direction == "down" ) and ( not i_use_alma or alma_trend_direction == "down" ) and ( not i_use_macd or macd_trend_direction == "down" ) and ( strategy.opentrades == 0 or strategy.opentrades.entry_id( strategy.opentrades - 1 ) != "Sell" ) )  and (use_ce ? dir_ce_==-1 : true)  and (use_ce4?dir_ce==-1:true)
            stopPrice = close + ( ( SLPerc / 100 ) * close )
            takeProfitPrice = close - ((i_tp_perc / 100) * close) // Nuevo cálculo del Take Profit

            strategy.entry( "Sell", strategy.short, comment = "Sell (SL = " + str.tostring( stopPrice ) + ")" )
            //strategy.exit( "Sell", stop = stopPrice, comment = "closed by SL " + str.tostring(SLPerc) + "%" )
            strategy.exit("Sell", stop=stopPrice, limit=takeProfitPrice, comment="SL " + str.tostring(SLPerc) + "%, TP " + str.tostring(i_tp_perc) + "%") // Línea corregida, orden de salida con Stop Loss y Take Profit

            cRSI_low_extreme_found := 0.0
            last_trade_ts := time
    last_pivot_ts := time

// MESA pivot low was found
if ( not i_use_mesa or ( pl_mesa and out_zone ) ? pl_mesa : na )
    // close trade if a cRSI extreme was previously found, otherwise let the cRSI close the trade once it gets there
    if not i_use_crsi or ( cRSI_low_extreme_found > 0.0 and cRSI_low_extreme_valid )
        strategy.close( "Sell", comment = "close sell (" + ( i_use_mesa ? "MESA" : i_use_crsi ? "cRSI" : i_use_htf_mesa ? "HTF MESA" : "unknown" ) + ")" )
        // open a counter-strategy, if:
        //   1) we're not too close to the last trade's TS
        //   2) we're in the correct cRSI trend (if enabled)
        //   3) we're in the correct MESA HTF MA trend (if enabled)
        //   4) we're in the correct ALMA trend (if enabled)
        //   5) we're in the correct MACD trend (if enabled)
        if ( inDateRange and ( ( time - last_trade_ts ) / 1000 >= ( 60 * min_trade_gap_minutes ) ) and ( not i_use_crsi or last_cRSI_extreme == "low" ) and ( not i_use_mesa or ( i_use_mesa and ( time - last_pivot_ts ) / 1000 >= ( 60 * min_mesa_pivots_gap_minutes ) ) ) and ( not i_use_crsi or not i_trade_trend_direction or last_cRSI_extreme == "low"  ) and ( not i_use_htf_mesa or mesa_ma_trend_direction == "up" ) and ( not i_use_alma or alma_trend_direction == "up" ) and ( not i_use_macd or macd_trend_direction == "down" )  and ( strategy.opentrades == 0 or strategy.opentrades.entry_id( strategy.opentrades - 1 ) != "Buy" ) ) and (use_ce ? dir_ce_==1 : true)  and (use_ce4?dir_ce==1:true)
            stopPrice = close - ( ( SLPerc / 100 ) * close )
            // strategy.entry("Buy", strategy.long, comment = "close: " + str.tostring(close) + ", sl: " + str.tostring(stopPrice) )
            strategy.entry( "Buy", strategy.long, comment = "Buy" )
            strategy.exit( "Buy", stop = stopPrice, comment = "closed by SL " + str.tostring(SLPerc) + "%" )
            cRSI_high_extreme_found := 0.0
            last_trade_ts := time
    last_pivot_ts := time




// Exit open market position when date range ends
if (not inDateRange)
    strategy.close_all()


use_strategy = input(true, "Used Reverse")
 

// Establecer precio de entrada original de la operación que dio perdida
entry_price = strategy.closedtrades.entry_price(strategy.closedtrades - 1)  
// Look if the strategy closed a trade
tradeClosed = strategy.closedtrades > strategy.closedtrades[1]

last_trade_profit = strategy.closedtrades.profit(strategy.closedtrades - 1)

// When the strategy closed a trade whose entry contains 'SMA',
// draw a label with that entry's result on the chart
is_pos_closed = (strategy.position_size[1] != 0 and strategy.position_size == 0) or ((strategy.position_size[1] * strategy.position_size) < 0)
is_long = strategy.position_size > 0
is_short = strategy.position_size < 0
was_long = is_pos_closed and is_long[1]
was_short = is_pos_closed and is_short[1]


var color longColor = color.green
var color shortColor = color.red

// buySignal = dir_ce == 1 and dir_ce[1]==-1
// sellSignal = dir_ce == -1 and dir_ce[1]==1
// longFillColor = highlightState ? dir_ce==1 ? longColor : na : na
// shortFillColor = highlightState ? dir_ce==-1 ? shortColor : na : na
// changeCond = dir_ce != dir_ce[1]


// buySignal_ = dir_ce_ == 1 and dir_ce_[1]==-1
// sellSignal_ = dir_ce_ == -1 and dir_ce_[1]==1
// longFillColor_ = highlightState_ ? dir_ce_==1 ? longColor : na : na
// shortFillColor_ = highlightState_ ? dir_ce_==-1 ? shortColor : na : na
// changeCond_ = dir_ce_ != dir_ce_[1]

longStopPlot = plot(dir_ce_==1 ? longStop_ : na, title='Long Stop', style=plot.style_linebr, linewidth=2, color=color.new(longColor, 0))
// //plotshape(buySignal ? longStop : na, title="Long Stop Start", location=location.absolute, style=shape.circle, size=size.tiny, color=longColor, transp=0)
plotshape(dir_ce==1, title='Buy Trend in Another Chart', text='', location=location.bottom, style=shape.circle, size=size.tiny, color=color.new(longColor, 0), textcolor=color.new(color.white, 0))

shortStopPlot = plot(dir_ce_==1 ? na : shortStop_, title='Short Stop', style=plot.style_linebr, linewidth=2, color=color.new(shortColor, 0))
// plotshape(sellSignal ? shortStop : na, title='Short Stop Start', location=location.absolute, style=shape.circle, size=size.tiny, color=color.new(shortColor, 0))
plotshape(dir_ce==-1, title="Sell Trend in Another Chart", text="", location=location.bottom, style=shape.circle, size=size.tiny, color=shortColor, textcolor=color.white)

// midPricePlot = plot(ohlc4, title='', style=plot.style_circles, linewidth=0, display=display.none, editable=false)

// fill(midPricePlot, longStopPlot, title='Long State Filling', color=color.new(longFillColor, transp=90))
// fill(midPricePlot, shortStopPlot, title='Short State Filling', color=color.new(shortFillColor, transp=90))

// alertcondition(changeCond, title='Alert: CE dir_ceection Change', message='Chandelier Exit has changed dir_ceection!')
// alertcondition(buySignal, title='Alert: CE Buy', message='Chandelier Exit Buy!')
// alertcondition(sellSignal, title='Alert: CE Sell', message='Chandelier Exit Sell!')


sl = input(27, "Stoploss %", group="SL")/100
tp = input(9, "Take Profit %", group="TP/SL")/100

var lsl = 0.0
var ssl = 0.0
var ltp = 0.0
var stp = 0.0

if tradeClosed  and  last_trade_profit < -0.25  and was_short and (use_ce3?dir_ce==-1:true)  and (use_ce1 ? dir_ce_==-1 : true) and use_strategy
    labelText = str.format("SHORTLOSER: {0}",
         strategy.closedtrades.profit(strategy.closedtrades - 1))    
    label.new(bar_index, high, labelText, color=color.black, 
         textcolor=color.white)
    strategy.entry("SHORTLOSER", strategy.short)
    ssl := close+(close*sl)
    stp := entry_price-(entry_price*tp)
    strategy.exit("SHORTLOSER", stop=ssl ,limit=stp)
    
if tradeClosed  and  last_trade_profit < -0.25  and was_long and (use_ce3?dir_ce==1:true)  and (use_ce1 ? dir_ce_==1 : true) and use_strategy
    labelText = str.format("LONGLOSER: {0}",
         strategy.closedtrades.profit(strategy.closedtrades - 1))    
    label.new(bar_index, high, labelText, color=color.black, 
         textcolor=color.white)
    lsl := close-(close*sl)
    ltp := entry_price+(entry_price*tp)
    strategy.entry("LONGLOSER", strategy.long)
    strategy.exit("LONGLOSER",stop=lsl, limit=ltp)  

How to Apply Pine Script in TradingView:

  1. Open TradingView and log in.
  2. Navigate to the Pine Script Editor at the bottom of the screen.
  3. Copy and paste the provided script code.
  4. Click Save, then name the script (e.g., “Final 15 Strategy”).
  5. Click Add to Chart to apply it.
  6. Customize parameters to align with your trading strategy.

Additional Trading Tips:

  • Combine with Volume Analysis:
    Use this strategy alongside volume-based indicators such as OBV or VWAP to confirm trade entries.
  • Backtest Thoroughly:
    Conduct extensive backtesting with different settings to understand the performance across various market conditions.
  • Avoid Over-Optimization:
    Focus on realistic parameter settings that align with current market conditions instead of curve-fitting past data.

Final Thoughts:

The Final 15 Strategy is a versatile trading tool that integrates multiple indicators to provide comprehensive market analysis. Its ability to analyze trends, manage risk, and execute trades makes it suitable for traders across different timeframes.

However, always remember that no strategy guarantees success, and trading should be approached with proper risk management and a disciplined mindset.

RELATED POSTS

View all

view all

You cannot copy content of this page