//+------------------------------------------------------------------+
//|                                            CrossMA_Tester_v2.mq4 |
//|                                Copyright © 2008, TrendLaboratory |
//|            http://finance.groups.yahoo.com/group/TrendLaboratory |
//|                                   E-mail: igorad2003@yahoo.co.uk |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, TrendLaboratory"
#property link      "http://finance.groups.yahoo.com/group/TrendLaboratory"

#property indicator_separate_window
#property indicator_buffers 5
#property indicator_color1 Lime
#property indicator_color2 OrangeRed
#property indicator_color3 Yellow
#property indicator_color4 SkyBlue
#property indicator_color5 OrangeRed
#property indicator_width1 1
#property indicator_width2 1
#property indicator_width3 1
#property indicator_width4 1
#property indicator_width5 1
#property indicator_style3 2
//---- input parameters
extern int        Price       =     0; //Applied Price
extern int        Fast        =    10; //Fast MA Period 
extern int        Slow        =    20; //Slow MA Period  
extern int        FastMode    =     0; //Fast MA's Method
extern int        SlowMode    =     0; //Slow MA's Method
extern int        UseSpread   =     1;
extern int        UseDate     =     1; 
extern datetime   StartDate   =     D'2008.01.01 00:00';

//---- indicator buffers
double Equity[];
double Balance[];
double Unreal[];
double UpSignal[];
double DnSignal[];
double trend[];
double PosPrice[];


int wins, losses;
bool Up=false, Dn=false;
string short_name,setup;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
{
   
//---- indicator line
   IndicatorBuffers(7);
   SetIndexBuffer(0,Equity);
   SetIndexBuffer(1,Balance);
   SetIndexBuffer(2,Unreal);
   SetIndexBuffer(3,UpSignal);
   SetIndexBuffer(4,DnSignal);
   SetIndexBuffer(5,trend);
   SetIndexBuffer(6,PosPrice);
   
   SetIndexStyle(0,DRAW_LINE);
   SetIndexStyle(1,DRAW_LINE);
   SetIndexStyle(2,DRAW_LINE);
   SetIndexStyle(3,DRAW_ARROW);
   SetIndexStyle(4,DRAW_ARROW);
   SetIndexArrow(3,214);
   SetIndexArrow(4,214);
   
//---- name for DataWindow and indicator subwindow label
   short_name="CrossMA_Tester("+Price+","+Fast+","+Slow+","+FastMode+","+SlowMode+","+UseSpread+","+UseDate+","+TimeToStr(StartDate)+")";
   IndicatorShortName(short_name);
   SetIndexLabel(0,"Equity");
   SetIndexLabel(1,"Balance");
   SetIndexLabel(2,"Unrealized profit");
   SetIndexLabel(3,"UpSignal");
   SetIndexLabel(4,"DnSignal");
//----
   SetIndexDrawBegin(0,Fast+Slow);
   SetIndexDrawBegin(1,Fast+Slow);
   SetIndexDrawBegin(2,Fast+Slow);
   SetIndexDrawBegin(3,Fast+Slow);
   SetIndexDrawBegin(4,Fast+Slow);
//----
   setup = StringConcatenate(Price,Fast,Slow,FastMode,SlowMode,UseSpread,UseDate,StartDate," ");
   return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
{
//----
   ObjDel();
//----
   return(0);
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int start()
  {
   
   int shift,limit, counted_bars=IndicatorCounted();
   
   
   if ( counted_bars > 0 )  limit=Bars-counted_bars-1;
   if ( counted_bars < 0 )  return(0);
   if ( counted_bars ==0 )  limit=Bars-1; 
   	
	if (counted_bars < 1)
   { 
      for(int i=1;i<Fast+Slow-1;i++)
      { 
      Equity[Bars-i]=0;
      UpSignal[Bars-i]=0;
      DnSignal[Bars-i]=0;
      PosPrice[Bars-i]=Open[Bars-i];
      Balance[Bars-i]=0;
      Unreal[Bars-i]=0;
      trend[Bars-i]=0;
      }
   }   
	
	if(UseSpread == 1) int spread = MarketInfo(Symbol(),MODE_SPREAD);
	else spread = 0;
	
	for(shift=limit;shift>=0;shift--) 
   {	
      if ( UseDate==0 || (UseDate > 0 && Time[shift] >= StartDate))
      {     
      double fast0 = iCustom(NULL,0,"AllAverages_v2.2",0,Price,Fast,0,FastMode,0,0,shift+1);
      double fast1 = iCustom(NULL,0,"AllAverages_v2.2",0,Price,Fast,0,FastMode,0,0,shift+2);
   
      double slow0 = iCustom(NULL,0,"AllAverages_v2.2",0,Price,Slow,0,SlowMode,0,0,shift+1);
      double slow1 = iCustom(NULL,0,"AllAverages_v2.2",0,Price,Slow,0,SlowMode,0,0,shift+2);
      
      Balance[shift] = Balance[shift+1];   
      PosPrice[shift] = PosPrice[shift+1];
      trend[shift]=trend[shift+1];
   
      if (fast0 > slow0 && fast1 < slow1 && trend[shift+1] <= 0) trend[shift] =  1;
      else
      if (fast0 < slow0 && fast1 > slow1 && trend[shift+1] >= 0) trend[shift] = -1;
      //else 
      //trend[shift] = 0;
      	   
      
      if(trend[shift+1] != trend[shift+0])
      {
      PosPrice[shift] = Open[shift];
         if( trend[shift+0] > 0) Balance[shift] = Balance[shift+1] + (PosPrice[shift+1] - PosPrice[shift])/Point - spread; 
         else
         if( trend[shift+0] < 0) Balance[shift] = Balance[shift+1] + (PosPrice[shift] - PosPrice[shift+1])/Point - spread;   
      if (trend[shift+1] == 0) Balance[shift]=0; 
      } 
         if ( trend[shift] >0 ) 
         {
         Equity[shift] = Balance[shift] + (Close[shift] - PosPrice[shift])/Point - spread;
         Unreal[shift] = Balance[shift] + (High[shift] - PosPrice[shift])/Point - spread;   
            if(trend[shift+1] != trend[shift]) 
            {
            UpSignal[shift] = Balance[shift]; 
               if(!Up)
               {   
               if(Balance[shift] >= Balance[shift+1]) wins += 1;
               else if(Balance[shift+1] != EMPTY_VALUE) losses +=1;
            
               Up=true;Dn=false;
               }
            } 
            else  
            UpSignal[shift] = EMPTY_VALUE;
         DnSignal[shift] = EMPTY_VALUE;
         }
         else
         if ( trend[shift] <0 ) 
         {
         Equity[shift] = Balance[shift] + (PosPrice[shift] - Close[shift])/Point - spread; 
         Unreal[shift] = Balance[shift] + (PosPrice[shift] - Low[shift])/Point - spread; 
	         if(trend[shift+1] != trend[shift]) 
	         {
	         DnSignal[shift] = Balance[shift];
               if(!Dn)
               {   
	            if(Balance[shift] >= Balance[shift+1]) wins += 1;
               else if(Balance[shift+1] != EMPTY_VALUE) losses +=1;
	           	           
	            Up=false;Dn=true;
	            }  
	         }
	         else 
            DnSignal[shift] = EMPTY_VALUE;
         UpSignal[shift] = EMPTY_VALUE;
	      }
      }
      else
      {UpSignal[shift]=EMPTY_VALUE; DnSignal[shift]=EMPTY_VALUE;Equity[shift]=EMPTY_VALUE;
       Balance[shift]=EMPTY_VALUE; PosPrice[shift]=Open[shift]; trend[shift]=0;}
   }

   ObjectCreate("CT"+setup, OBJ_LABEL, WindowFind(short_name), 0, 0);
   ObjectSetText("CT"+setup," Wins = "+wins+" Losses = "+losses,8, "Arial Bold", Silver);
   ObjectSet("CT"+setup, OBJPROP_CORNER, 0);
   ObjectSet("CT"+setup, OBJPROP_XDISTANCE, 510);
   ObjectSet("CT"+setup, OBJPROP_YDISTANCE, 3);
//----	
   return(0);	
}

bool ObjDel()
{
   int _GetLastError = 0;
     
   while(ObjFind("CT"+setup,0,0) > 0)
   {
      int obtotal = ObjectsTotal();
      //Print("ob=",obtotal);
      for (int i = 0; i < obtotal;i++)
      {
      //Print("Name=",ObjectName(i)," Find=",StringFind(ObjectName(i),"LTZZdn"+setup,0));
         if (StringFind(ObjectName(i),"CT"+setup,0) >= 0)
         {
            if (!ObjectDelete(ObjectName(i)))
            {
            _GetLastError = GetLastError();
            Print( "ObjectDelete( \"",ObjectName(i),"\" ) - Error #", _GetLastError );
            }
         }
      }
   }      
      
   if(_GetLastError > 0) return(false);
   else
   return (true);
}
//-----
int ObjFind(string name,int start, int num)
{
   int cnt = 0;
   
   for (int i = 0; i < ObjectsTotal();i++)
      if (StringFind(ObjectName(i),name,start) == num) cnt+=1;
   
   return(cnt);
}         