//+------------------------------------------------------------------+
//|                                            KosVisualBackTest.mq4 |
//|                             Copyright © 2010, zznbrm@hotmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2010, zznbrm@hotmail.com"
#property indicator_chart_window
#property indicator_buffers 2
#property indicator_color1 White

//+------------------------------------------------------------------+
//| Constants                                                        |
//+------------------------------------------------------------------+
#define    cLONG              1
#define    cSHORT             -1
#define    cNONE              0
#define    cOPEN_TRADE_ARROW  1
#define    cCLOSE_TRADE_ARROW 3

//+------------------------------------------------------------------+
//| User Inputs                                                      |
//+------------------------------------------------------------------+
extern string estrDesc0 = "----- Trend Magic settings -----";
extern int eintCCIPeriod = 50;
extern int eintATRPeriod = 5;
extern string estrDesc1 = "----- MACD settings -----";
extern int eintMA1 = 12;
extern int eintMA2 = 26;
extern int eintSignal = 9;

//+------------------------------------------------------------------+
//| Indicator Buffers                                                |
//+------------------------------------------------------------------+
double gadblTM[];
double gadblMacd[];

//+------------------------------------------------------------------+
//| Global Variables                                                 |
//+------------------------------------------------------------------+
bool     gblnHistCompleted = false;
int      gintTradeType = cNONE;
double   gdblEntryPrice = 0.0;
datetime gdtEntryTime = 0;

//*********************************************************************************************
//* STANDARD INDICATOR FUNCTIONS BELOW                                                        *
//*********************************************************************************************
//+------------------------------------------------------------------+
//| init()                                                           |
//+------------------------------------------------------------------+
int init()
{          
   IndicatorShortName( "KosVisualBackTest" );
   IndicatorDigits( Digits );
   IndicatorBuffers( 2 );
      
   SetIndexBuffer( 0, gadblTM ); 
   SetIndexStyle( 0, DRAW_LINE, STYLE_SOLID, 1, White );
   SetIndexLabel( 0, "TrendMagic" );
   
   SetIndexBuffer( 1, gadblMacd ); 
   SetIndexStyle( 1, DRAW_NONE );
   SetIndexLabel( 1, "MACD" );            
   
   return( 0 );
}

//+------------------------------------------------------------------+
//| deinit()                                                         |
//+------------------------------------------------------------------+
int deinit()
{
   ObjectsDeleteAll( 0 );
   return( 0 );
}

//+------------------------------------------------------------------+
//| start()                                                          |
//+------------------------------------------------------------------+
int start()
{     
   if ( gblnHistCompleted )   return( 0 );   
   gblnHistCompleted = true;

   // Populate the TrendMagic buffer
   initialize( Bars - eintCCIPeriod );
   
   // Display trades
   doBacktest( Bars - eintCCIPeriod - 20 );     
       
   return( 0 );
}

//*********************************************************************************************
//* MAIN PROCESSING FUNCTIONS BELOW                                                           *
//*********************************************************************************************
//+------------------------------------------------------------------+
//| initialize                                                       |
//+------------------------------------------------------------------+
void initialize( int intLimit )
{  
   double dblCCI, dblTM, dblMacdMain, dblMacdSig;
   
   for( int inx = intLimit; inx >= 0; inx-- ) 
   {
      // Initialize the Trend Magic buffer
      dblCCI = iCCI( NULL, 0, eintCCIPeriod, PRICE_TYPICAL, inx );
           
      if ( dblCCI >= 0 )   
      {
         dblTM = Low[inx] - iATR( NULL, 0, eintATRPeriod, inx );
         
         if ( dblTM < gadblTM[inx+1] )    dblTM = gadblTM[inx+1];
      }     
      else                  
      {
         dblTM = High[inx] + iATR( NULL, 0, eintATRPeriod, inx ); 
         
         if ( dblTM > gadblTM[inx+1] )    dblTM = gadblTM[inx+1];   
      }  
      
      gadblTM[inx] = dblTM;
      
      // Initialize the MACD buffer
      dblMacdMain = iMACD( NULL, 0, eintMA1, eintMA2, eintSignal, PRICE_CLOSE, MODE_MAIN, inx );
      dblMacdSig = iMACD( NULL, 0, eintMA1, eintMA2, eintSignal, PRICE_CLOSE, MODE_SIGNAL, inx ); 
      
      if ( dblMacdMain >= dblMacdSig )       gadblMacd[inx] = cLONG;
      else                                   gadblMacd[inx] = cSHORT;
   }         
}

//+------------------------------------------------------------------+
//| doBacktest                                                       |
//+------------------------------------------------------------------+
void doBacktest( int intLimit )
{  
   string strDesc;
   
   for( int inx = intLimit; inx >= 0; inx-- ) 
   {        
      if ( gintTradeType == cLONG )
      {
         // Check exit criteria for long trade
         doExitLong( inx );
      }
      else if ( gintTradeType == cSHORT )
      {
         // Check exit criteria for short trade
         doExitShort( inx );
      }      
      
      if ( gintTradeType == cNONE )
      {
         // Check entry criteria for new entries
         doEntry( inx );
      }
   }        
}

//*********************************************************************************************
//* TRADING FUNCTIONS BELOW                                                                   *
//*********************************************************************************************
//+------------------------------------------------------------------+
//| doEntry                                                          |
//+------------------------------------------------------------------+
void doEntry( int intShift )
{  
   string strDesc;
   
   //--------------------------------------------------
   // Check entry criteria for long trade
   //--------------------------------------------------
   // 1) No open trades
   // 2) Current Close > Current Trend Magic
   // 3) Current MACD-Main > Current MACD-Signal
   //-------------------------------------------------- 
   if ( ( Close[intShift] > gadblTM[intShift] ) && ( gadblMacd[intShift] == cLONG ) )
   {
      gintTradeType = cLONG;
      gdblEntryPrice = Close[intShift];
      gdtEntryTime = Time[intShift];
      strDesc = "Open Long @ " + DoubleToStr( gdblEntryPrice, Digits );
      drawArrow( "OLong" + gdtEntryTime, cOPEN_TRADE_ARROW, Blue, gdblEntryPrice, gdtEntryTime, 2, strDesc );
   }
   
   //--------------------------------------------------
   // Check entry criteria for short trade
   //--------------------------------------------------
   // 1) No open trades
   // 2) Current Close < Current Trend Magic
   // 3) Current MACD-Main < Current MACD-Signal
   //--------------------------------------------------
   else if ( ( Close[intShift] < gadblTM[intShift] ) && ( gadblMacd[intShift] == cSHORT ) )
   {
      gintTradeType = cSHORT;
      gdblEntryPrice = Close[intShift];
      gdtEntryTime = Time[intShift];
      strDesc = "Open Short @ " + DoubleToStr( gdblEntryPrice, Digits );
      drawArrow( "OShort" + gdtEntryTime, cOPEN_TRADE_ARROW, Red, gdblEntryPrice, gdtEntryTime, 2, strDesc );
   }
      
   return;      
}

//+------------------------------------------------------------------+
//| doExitLong                                                       |
//+------------------------------------------------------------------+
void doExitLong( int intShift )
{  
   string strDesc;
   
   //--------------------------------------------------
   // Check exit criteria for long trade
   //--------------------------------------------------
   // 1) Current Macd-Main < Current Macd-Signal
   //-------------------------------------------------- 
   if ( gadblMacd[intShift] == cSHORT )
   {
      gintTradeType = cNONE;      
      strDesc = "Close Long @ " + DoubleToStr( Close[intShift], Digits );
      drawArrow( "CLong" + Time[intShift], cCLOSE_TRADE_ARROW, Red, Close[intShift], Time[intShift], 2, strDesc );
      drawTL( "TL" + Time[intShift], Aqua, gdblEntryPrice, gdtEntryTime, Close[intShift], Time[intShift] ); 
      gdblEntryPrice = 0.0;
      gdtEntryTime = 0;
   }   
   
   return;      
}

//+------------------------------------------------------------------+
//| doExitShort                                                      |
//+------------------------------------------------------------------+
void doExitShort( int intShift )
{  
   string strDesc;
   
   //--------------------------------------------------
   // Check exit criteria for short trade
   //--------------------------------------------------
   // 1) Current Macd-Main > Current Macd-Signal
   //-------------------------------------------------- 
   if ( gadblMacd[intShift] == cLONG )
   {
      gintTradeType = cNONE;      
      strDesc = "Close Short @ " + DoubleToStr( Close[intShift], Digits );
      drawArrow( "CShort" + Time[intShift], cCLOSE_TRADE_ARROW, Blue, Close[intShift], Time[intShift], 2, strDesc );
      drawTL( "TL" + Time[intShift], Magenta, gdblEntryPrice, gdtEntryTime, Close[intShift], Time[intShift] ); 
      gdblEntryPrice = 0.0;
      gdtEntryTime = 0;
   }   
   
   return;      
}

//*********************************************************************************************
//* DRAWING FUNCTIONS BELOW                                                                   *
//*********************************************************************************************
//+------------------------------------------------------------------+
//| drawArrow                                                        |
//+------------------------------------------------------------------+
void drawArrow( string strName, int intCode, color clr, double dblPrice,
                datetime dtTime, int intWidth, string strDesc )
{
   if ( ObjectFind( strName ) == -1 )
   {
      ObjectCreate( strName, OBJ_ARROW, 0, dtTime, dblPrice );
      ObjectSet( strName, OBJPROP_ARROWCODE, intCode );
      ObjectSet( strName, OBJPROP_COLOR, clr );
      ObjectSet( strName, OBJPROP_WIDTH, intWidth );
      ObjectSetText( strName, strDesc );
   }
   else
      ObjectMove( strName, 0, dtTime, dblPrice ); 
}

//+------------------------------------------------------------------+
//| drawTL                                                           |
//+------------------------------------------------------------------+
void drawTL( string strName, color clr, double dblPrice1, datetime dtTime1, double dblPrice2, datetime dtTime2 )
{
   if ( ObjectFind( strName ) == -1 )
   {
      ObjectCreate( strName, OBJ_TREND, 0, dtTime1, dblPrice1, dtTime2, dblPrice2 );
      ObjectSet( strName, OBJPROP_COLOR, clr );
      ObjectSet( strName, OBJPROP_WIDTH, 1 );
      ObjectSet( strName, OBJPROP_STYLE, STYLE_DOT );
      ObjectSet( strName, OBJPROP_RAY, false );
   }
   else
   {
      ObjectMove( strName, 0, dtTime1, dblPrice1 ); 
      ObjectMove( strName, 1, dtTime2, dblPrice2 );
   }
}

//*********************************************************************************************
//* UTILITY FUNCTIONS BELOW                                                                   *
//*********************************************************************************************


//*********************************************************************************************
//* DATA FUNCTIONS BELOW                                                                      *
//*********************************************************************************************



      




   
   



