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 );
}
        

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



Sample





Analysis



Market Information Used:

Series array that contains close prices for each bar
Series array that contains the lowest prices of each bar
Series array that contains open time of each bar
Series array that contains the highest prices of each bar


Indicator Curves created:

Implements a curve of type DRAW_LINE

Implements a curve of type DRAW_NONE

Indicators Used:

Indicator of the average true range
Moving average indicator


Custom Indicators Used:

Order Management characteristics:

Other Features: