MT4-LevelStop-Reverse

Download script
Author: Copyright � 2007, Bruce H (brucehvn)
MT4-LevelStop-Reverse

System Overview

The MT4-LevelStop-Reverse script is a technical analysis tool designed to help traders visualize price trends and identify potential reversal points on a chart. It functions by plotting a dynamic "stop line" (a dotted line) that follows the price movement, acting as a boundary for current market momentum. When the price breaks this boundary in a specific way, the system generates visual signals—in the form of up and down arrows—to alert the trader to a possible shift in market direction.

How the Logic Works

The core logic of this script is built around three distinct modes of calculation, allowing users to choose how "sensitive" or "rigid" the stop line should be:

  1. VT Default Optimal Mode: This uses a sophisticated mathematical approach where it calculates market volatility and then smooths that data out over time. It applies a specific multiplier to ensure the stop line stays at an appropriate distance from the price, mimicking a professional trading standard.
  2. ATR Mode (Adjustable): This mode calculates the "Average True Range" (volatility) over a period you define. It multiplies this volatility by a custom factor to determine how far away the stop line should sit. This is ideal for traders who want to customize the distance based on different market conditions.
  3. Fixed Stop Mode: This is the simplest method, where the user manually defines a specific number of pips for the stop line to maintain from the price.

Price Movement and Line Behavior

The script constantly monitors the relationship between the current price and the existing stop line. The logic follows these rules:

  • Trend Following: If the price moves in the direction of the current trend, the stop line adjusts its position to remain at the calculated distance (from the modes mentioned above).
  • Momentum Checks: If the price starts to stall or move against the trend, the line adjusts dynamically to ensure it doesn't "drift" too far away during periods of low activity.
  • Reversal Detection: The script looks for a specific "breakout." If the price closes significantly beyond the current stop line (crossing from one side to the other), the system recognizes this as a reversal signal.

Visual Signals

When the logic detects a confirmed reversal, the script performs two actions:

  • Visual Arrows: It places an Up Arrow (for bullish reversals) or a Down Arrow (for bearish reversals) on the chart at a specific distance from the price candle. These are color-coded to make them easily visible.
  • Line Reset: The script immediately "flips" and recalculates the stop line based on the new direction of the price. This ensures that the indicator is always prepared to track the next potential trend.

Summary for the User

Essentially, this tool acts as a visual "buffer." It filters out minor market noise by creating a protective boundary; only when the price pushes hard enough to break that boundary does the script signal a potential change in direction, helping traders stay on the right side of the market trend.

Indicators Used
Indicator of the average true rangeMoving average indicator
Miscellaneous
Implements a curve of type %1
8 Views
0 Downloads
0 Favorites
MT4-LevelStop-Reverse
//+------------------------------------------------------------------+
//|                                            MT4-LevelStop-Reverse |
//|                             Copyright © 2007, Bruce H (brucehvn) |
//|                                              bhweb@speakeasy.net |
//|                                       http://www.metaquotes.net/ |
//+------------------------------------------------------------------+

/////////////////////////////////////////////////////////////////////
// Version 0.1 Beta
//
// This is a port of the VTTrader VT-LevelStop-Reverse trading system.
// This is ported as an MT4 indicator only and perhaps can be evolved
// into an EA later.
//
// This is a beta version
//
/////////////////////////////////////////////////////////////////////

/*

This is a combination of two VT Trader trading systems.  The first is the default
VT-LevelStop-Reverse and the second is one that was modified to allow customizing
the ATR settings for calculating the stop line.

The default VT version allows you to use two modes, optimized, and manual.
Optimized mode calculates the stop line by using a 14 period EMA smoothed
ATR(14) multiplied by a fixed multiplier of 2.824. In manual mode, you set a
fixed number of pips you want the stop line to be drawn. In my MT4 version,
there are three modes:

1. VT default optimized mode.
2. ATR mode (customizable ATR period and multiplier)
3. Fixed stop mode (customizable fixed stop)

The input parameters are as follows:

* UseVTDefaultOptimal - This mimics the VT optimized mode and ignores the other settings for "UseATRMode", "ATRPeriod", "ATRMultiplier", and "NonATRStopPips".
* UseATRMode - This calculates the stop line based on ATR using customizable period and multiplier.
* NonATRStopPips - If "UseVTDefaultOptimal" and "UseATRMode" are false, then this value is the number of fixed pips to place the stop line.
* ATRPeriod - If "UseATRMode" is true, then this sets the ATR period.
* ATRMultiplier - If "UseATRMode" is true, then the ATR value will be multiplied by this value when calculating the stop line.
* UpArrowColor - The color the Up arrows will display in.
* DnArrowColor - The color the Down arrows will display in.
* ArrowDistance - The number of pips away from the high or low of the bar that the arrow should display.

On the colors tab, only the first color is used. It is the color of the dotted
stop line.

To use this indicator, copy it to your <MetaTrader Folder>\experts\indicators
folder. Then restart MT4. It will appear in the custom indicators list.

This is version Beta 0.1.  As I get feedback, I will release newer versions as needed.
*/


#property copyright "Copyright © 2007, Bruce H (brucehvn)"
#property link      "http: //www.metaquotes.net/"

#property indicator_chart_window
#property indicator_buffers 4
#property indicator_color1 Magenta
#property indicator_style1 STYLE_DOT


//---- input parameters

extern bool UseVTDefaultOptimal = false;
extern bool UseATRMode = true;
extern int NonATRStopPips = 40;
extern int ATRPeriod = 14;
extern double ATRMultiplier = 3.0;
extern color UpArrowColor = DodgerBlue;
extern color DnArrowColor = OrangeRed;
extern int ArrowDistance = 25;

//---- buffers
double TrStopLevel[];
double UpSignal[];
double DnSignal[];
double ATRBuffer[];

//---- variables
int ArrowObjects[50];
int VTDefATRPeriod = 14;
int VTDefSmoothing = 14;
double VTDefATRMultiplier = 2.824;


//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init() {
    string ShortName;
    
    IndicatorBuffers( 4 );
    SetIndexStyle( 0, DRAW_LINE, STYLE_DOT, 1 );
    SetIndexBuffer( 0, TrStopLevel );
    
    SetIndexStyle( 1, DRAW_NONE );
    SetIndexBuffer( 1, UpSignal );
    
    SetIndexStyle( 2, DRAW_NONE );
    SetIndexBuffer( 2, DnSignal );

    SetIndexStyle( 3, DRAW_NONE );
    SetIndexBuffer( 3, ATRBuffer );

    ShortName = "MT4-LevelStop-Reverse( ";
    
    if ( UseVTDefaultOptimal ) {
        ShortName = StringConcatenate( ShortName, "DefVTMode", " )" );
    }
    else {
        if ( UseATRMode ) {
            ShortName = StringConcatenate( ShortName, "ATRMode ", ATRPeriod, ", ", ATRMultiplier, " )" );
        }
        else {
            ShortName = StringConcatenate( ShortName, "Manual Mode Stop = ", NonATRStopPips, " )" );
        }
    }
    
    IndicatorShortName( ShortName );
    SetIndexLabel( 0, ShortName );
    
    for ( int ictr = 0; ictr < 50; ictr++ ) {
        ArrowObjects[ictr] = 0;
    }

    MathSrand( TimeLocal() );
    
    return( 0 );
}

//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                         |
//+------------------------------------------------------------------+
int deinit() {
    int num_elems = ArraySize( ArrowObjects );
    Print( "deinit() - number of objects to delete: ", num_elems );
    for ( int ictr = 0; ictr < num_elems; ictr++ ) {
        if ( ArrowObjects[ ictr ] == 0 ) {
            Print( "ArrowObjects[", ictr, "] is zero" );
            break;
        }
        
        string ObjName = "VTS-" + ArrowObjects[ictr];
        ObjectDelete( ObjName );
    }
    return( 0 );
}



//+------------------------------------------------------------------+
//| Momentum                                                         |
//+------------------------------------------------------------------+
int start() {
    Comment( "\nMT4-LevelStop-Revers Beta v0.9" );
    
    int ictr;
    int counted_bars = IndicatorCounted();
    
    int min_period = 1;
    if ( UseATRMode ) {
        min_period = ATRPeriod;
    }
    
    if ( Bars <= min_period ) {
        return( 0 );
    }
    
    if ( counted_bars < 1 ) {
        for ( ictr = 1; ictr < min_period; ictr++ ) {
            TrStopLevel[ Bars - ictr ] = 0.0;
            UpSignal[ Bars - ictr ] = 0.0;
            DnSignal[ Bars - ictr ] = 0.0;
        }
    }
    
    ictr = Bars - min_period - 1;
    
    if ( counted_bars >= min_period ) {
        ictr = Bars - counted_bars - 1;
    }
    
    int xctr;
    
    for ( xctr = ictr; xctr >= 0; xctr-- ) {
        ATRBuffer[xctr] = iATR( NULL, 0, VTDefATRPeriod, xctr );
    }
    
    for ( xctr = ictr; xctr >= 0; xctr-- ) {
         // Calculate the stop amount
        double DeltaStop = NonATRStopPips * Point;
        
        // VTDefault optimal mode uses the ATR(14) value smoothed with an exponential
        // moving average of 14 periods
        if ( UseVTDefaultOptimal ) {
            double ma_smooth = iMAOnArray( ATRBuffer, 0, VTDefSmoothing, 0, MODE_EMA, xctr );
            DeltaStop = NormalizeDouble( ma_smooth * VTDefATRMultiplier, 4 );
        }
        else {
            if ( UseATRMode ) {
                DeltaStop = NormalizeDouble( iATR( NULL, 0, ATRPeriod, xctr ) * ATRMultiplier, 4 );
            }
        }
        
        // Figure out where the current bar's stop level should be
        double NewStopLevel;
        double PrevStop = TrStopLevel[xctr + 1];
        
        if ( Close[xctr] == PrevStop ) {
            NewStopLevel = PrevStop;
        }
        else {
            if ( Close[xctr + 1] <= PrevStop && Close[xctr] < PrevStop ) {
                NewStopLevel = MathMin( PrevStop, ( Close[xctr] + DeltaStop ) );
            }
            else {
                if ( Close[xctr + 1] >= PrevStop && Close[xctr] > PrevStop ) {
                    NewStopLevel = MathMax( PrevStop, ( Close[xctr] - DeltaStop ) );
                }
                else {
                    if ( Close[xctr] > PrevStop ) {
                        NewStopLevel = Close[xctr] - DeltaStop;
                    }
                    else {
                        NewStopLevel = Close[xctr] + DeltaStop;
                    }
                }
            }
        }
        
        TrStopLevel[xctr] = NewStopLevel;
        
        // Figure out the up/down arrows
        bool Up = false;
        bool Dn = false;
        
        if ( Close[xctr] > TrStopLevel[xctr] && Close[xctr + 1] <= TrStopLevel[xctr + 1] ) {
            Up = true;
            UpSignal[xctr] = Low[xctr] - ( ArrowDistance * Point );
            int next_ind = GetNextObjectIndex();
            int obj_id = MathRand() + 1;
            string ObjName = "VTS-" + obj_id;
            ObjectCreate( ObjName, OBJ_ARROW, 0, Time[xctr], UpSignal[xctr] );
            ObjectSet( ObjName, OBJPROP_COLOR, UpArrowColor );
            ObjectSet( ObjName, OBJPROP_ARROWCODE, 233 );
            ArrowObjects[next_ind] = obj_id;
        }
            
        if ( Close[xctr] < TrStopLevel[xctr] && Close[xctr + 1] >= TrStopLevel[xctr + 1] ) {
            Dn = true;
            DnSignal[xctr] = High[xctr] + ( ArrowDistance * Point );
            next_ind = GetNextObjectIndex();
            obj_id = MathRand() + 1;
            ObjName = "VTS-" + obj_id;
            ObjectCreate( ObjName, OBJ_ARROW, 0, Time[xctr], DnSignal[xctr] );
            ObjectSet( ObjName, OBJPROP_COLOR, DnArrowColor );
            ObjectSet( ObjName, OBJPROP_ARROWCODE, 234 );
            ArrowObjects[next_ind] = obj_id;
        }
        
        // Reverse TrStopLevel According to Up and Down Signals
        if ( Up ) {
            TrStopLevel[xctr] = Close[xctr] - DeltaStop;
        }
        else {
            if ( Dn ) {
                TrStopLevel[xctr] = Close[xctr] + DeltaStop;
            }
        }
    }
        
    return( 0 );
}


//+------------------------------------------------------------------+
//| Gets the next object index so they can be deleted later          |
//+------------------------------------------------------------------+
int GetNextObjectIndex() {
    int retval = 0;
    int arr_size = ArraySize( ArrowObjects );
    int max_elem = arr_size - 1;
    
    if ( ArrowObjects[max_elem] != 0 ) {
        // Resize the array
        ArrayResize( ArrowObjects, arr_size + 10 );
        for ( int xctr = arr_size; xctr < ( arr_size + 10 ); xctr++ ) {
            ArrowObjects[xctr] = 0;
        }
        arr_size += 10;
    }
        
    
    for ( int ictr = 0; ictr < arr_size; ictr++ ) {
        if ( ArrowObjects[ ictr ] == 0 ) {
            retval = ictr;
            break;
        }
    }
    
    return( retval );
}
        

//+------------------------------------------------------------------+

Comments