//+------------------------------------------------------------------+
//|                                                      Starter.mq4 |
//|                      Copyright © 2005, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"
//#include <Tracert.mqh>
extern double  Lots              = 0.1;
extern double  MaximumRisk       = 0.03;
extern double  DecreaseFactor    = 3;
extern int     Stop              = 10;
extern int     SL                = 0;     //Для "эстетов" из форуму StopLoss
//extern double Lots = 4;
//Параметры Laguerre
extern double  GammaP            = 0.7;   //Некая "Гамма" из параметров "Laguerre"
extern double  StopL             = 0.1;   //"Порог" "Laguerre" для закрытия позиции
extern int     ShftL             = 0;     //Бар, на котором рассчитывается "Laguerre"
//Параметры CCI
extern int     CCIperiod         = 14;    //Собственно период CCI
extern int     TypeCCI           = 0;     //"Ценовые константы" для расчтеиа CCI 0-Close, 1-Open, 2-High, 3-Low, 4-Median, 5-Typical, 6-WEIGHTED
extern int     DAlpha            = 0;     //Дельта CCI - "порог изменения скорости CCI" в процентах
extern int     CCILevel          = 100;   //Классически - уровень, который должна пересечь CCI, чтобы дать сигнал. Классика +/-100, 0, в оригиналбном starter'е +/-5. Я закомментировал, т.к.....
extern int     ShftA1            = 0;     //Бар для расчета "текущей" CCI
extern int     ShftA2            = 1;     //Бар для расчета "предыдущей" CCI
//Параметры MA
extern double  MAPeriod          = 120;   //Собственно период MA
extern int     TypeMA            = 0;     //"Ценовые константы" для расчтеиа MA 0-Close, 1-Open, 2-High, 3-Low, 4-Median, 5-Typical, 6-WEIGHTED
extern int     ShftMA            = 0;     //Бар для расчета "текущей" MA (Бар для "предыдущей" MA = ShftMA+1 (в отличии от CCI))
extern double  DeltaMA           = 0.1;   //Дельта MA ("текущего" и "предыдущего" бара) в "пипсах" :)
//MagicNubber
extern int     MagicNumber       = 20051016; //Я всегда выношу всегда, чтобы можно было, НАПРИМЕР, торговать на одной паре с разными параметрами :)

int handle;
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//---- 
   handle = FileOpen("StarterDebug.csv",  FILE_CSV | FILE_WRITE);
   FileWrite(handle, "Time[0]", "TradeType", "Laguerre", "MA", "MA1", "DMA", "Alpha1", "Alpha2", "DAlpha");
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//---- 
   FileClose(handle);  
//----
   return(0);
  }
 
//+------------------------------------------------------------------+
//| Calculate optimal lot size                                       |
//+------------------------------------------------------------------+
double LotsOptimized()
  {
   double lot=Lots;
   int    orders=HistoryTotal();     // history orders total
   int    losses=0;                  // number of losses orders without a break
//---- select lot size
   lot=NormalizeDouble(AccountFreeMargin()*MaximumRisk/500,1);
//---- calcuulate number of losses orders without a break
   if(DecreaseFactor>0)
     {
      for(int i=orders-1;i>=0;i--)
        {
         if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false) { Print("Error in history!"); break; }
         if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue;
         //----
         if(OrderProfit()>0) break;
         if(OrderProfit()<0) losses++;
        }
      if(losses>1) lot=NormalizeDouble(lot-lot*losses/DecreaseFactor,1);
     }
//---- return lot size
   if(lot<1) lot=1;
   if(lot>1000) lot=1000;
   return(lot);
  }  
  
double LaGuerre(double gamma, int shift)
{
	double RSI;
	double L0[100];
	double L1[100];
	double L2[100];
	double L3[100];
	double CU, CD;

	for (int i=shift+99; i>=shift; i--)
	{
		L0[i] = (1.0 - gamma)*Close[i] + gamma*L0[i+1];
		L1[i] = -gamma*L0[i] + L0[i+1] + gamma*L1[i+1];
		L2[i] = -gamma*L1[i] + L1[i+1] + gamma*L2[i+1];
		L3[i] = -gamma*L2[i] + L2[i+1] + gamma*L3[i+1];

		CU = 0;
		CD = 0;
		if (L0[i] >= L1[i])  CU = L0[i] - L1[i];
		else 		 		CD = L1[i] - L0[i];
		
		if (L1[i] >= L2[i])  CU = CU + L1[i] - L2[i];
		else 		 		CD = CD + L2[i] - L1[i];
		if (L2[i] >= L3[i])  CU = CU + L2[i] - L3[i];
		else 		 		CD = CD + L3[i] - L2[i];

		if (CU + CD != 0)		RSI = CU / (CU + CD);
	}
   return(RSI);
}  

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   double Laguerre;
   double SLstop;
   double Alpha1, Alpha2;
   double MA, MA1;
   
//+--   double Juice;
   int cnt, ticket, RealTotal, total;
  
//  Laguerre=iCustom(NULL, 0, "Laguerre", 0, 0);
  Laguerre=LaGuerre(GammaP, 0);
  Alpha1=iCCI(NULL, 0, CCIperiod, TypeCCI, ShftA1);
  Alpha2=iCCI(NULL, 0, CCIperiod, TypeCCI, ShftA2);
  MA=iMA(NULL,0,MAPeriod,0,MODE_EMA,TypeMA,ShftMA);
  MA1=iMA(NULL,0,MAPeriod,0,MODE_EMA,TypeMA,ShftMA+1);
//+--  Juice=iCustom(NULL,0,"Juice",0,0);
  
  total=OrdersTotal();
  //Ищем реальное чило трговых ордеров для нашего MagicNumber на нашей паре (чтобы дать торговать себе и другим советникам)
  for (cnt = 0; cnt < total; cnt++)
  {
   OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
   if (OrderMagicNumber() == MagicNumber && OrderSymbol() == Symbol())
    RealTotal = RealTotal + 1;
  }
 
   if(RealTotal<1) 
     {
      // no opened orders identified
      if(AccountFreeMargin()<(1000*Lots))
        {
         Print("We have no money. Free Margin = ", AccountFreeMargin());
         return(0);  
        }
      // check for long position (BUY) possibility
      if(
         //Из "оригинала"
         (Laguerre==0) 
      && //Не просто рост MA, но и минимум некоторую дельту
         (MA-MA1 > DeltaMA * Point) 
      && //Рост CCI
         (Alpha2 < Alpha1) 
      && //Пересечение некоторого уровня +/-100, 0 "Снизу-вверх"
         (Alpha1 > -1 * CCILevel && Alpha2 < -1 * CCILevel)
//      && //В оригинале (если честно - не понял. ИМХО имелось ввиду пересечение (или "подход" к) 0, но, если смотреть отладочный файл, то там ....
//         (Alpha1 < -5)
      && //Рост CCI в % больше порога
         (MathAbs(Alpha1 - Alpha2)/MathMax(MathAbs(Alpha1),MathAbs(Alpha2))*100 > DAlpha)
        ) //+-- && Juice>JuiceLevel)
        {
         FileWrite(handle, "Buy", Time[0], Laguerre, MA, MA1, MA-MA1, Alpha1, Alpha2, MathAbs(Alpha1 - Alpha2)/MathMax(MathAbs(Alpha1),MathAbs(Alpha2))*100 );
         FileFlush(handle);
         //Для "эстетов" StopLoss
         if (SL == 0)
          SLstop = 0;
         else
          SLstop = Ask - SL * Point;
         ticket=OrderSend(Symbol(),OP_BUY,LotsOptimized(),Ask,3,SLstop,0,"starter",MagicNumber,0,Green);
        }
      // check for short position (SELL) possibility
      if(
         //Из "оригинала"
         (Laguerre==1) 
      && //Не просто падение MA, но и минимум некоторую дельту
         (MA-MA1 < -1 * DeltaMA * Point) 
      && //Падение CCI
         (Alpha2 > Alpha1) 
      && //Пересечение некоторого уровня +/-100, 0 "Сверху-вниз"
         (Alpha1 < CCILevel && Alpha2 > CCILevel)
//      && //В оригинале (если честно - не понял. ИМХО имелось ввиду пересечение (или "подход" к) 0, но, если смотреть отладочный файл, то там ....
//         (Alpha1 > 5)
      && //Рост CCI в % больше порога
         (MathAbs(Alpha1 - Alpha2)/MathMax(MathAbs(Alpha1),MathAbs(Alpha2))*100 > DAlpha)
        ) //+-- && Juice>JuiceLevel)
        {
         FileWrite(handle, "Sell", Time[0], Laguerre, MA, MA1, MA-MA1, Alpha1, Alpha2, MathAbs(Alpha1 - Alpha2)/MathMax(MathAbs(Alpha1),MathAbs(Alpha2))*100 );
         FileFlush(handle);
         //Для "эстетов" StopLoss
         if (SL == 0)
          SLstop = 0;
         else
          SLstop = Bid + SL * Point;
         ticket=OrderSend(Symbol(),OP_SELL,LotsOptimized(),Bid,3,SLstop,0,"starter",MagicNumber,0,Red);
        } 
     }
// it is important to enter the market correctly, 
   // but it is more important to exit it correctly...   
   for(cnt=0;cnt<total;cnt++)
     {
      OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);
      if(OrderType()<=OP_SELL &&   // check for opened position 
         OrderSymbol()==Symbol() &&  // check for symbol
         OrderMagicNumber() == MagicNumber)  // check for MagicNumber (Чтобы рулить только своими сделками своего советника)
        {
         if(OrderType()==OP_BUY)   // long position is opened
           {
            // should it be closed?
            if(Laguerre>1-StopL)
                {
                 OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position
                 return(0); // exit
                }
            // check for stop
            if(Stop>0)  
              {                 
               if(Bid-OrderOpenPrice()>Point*Stop)
                 {
                   OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position
                   return(0);
                 }
              }
           }
         else // go to short position
           {
            // should it be closed?
            if(Laguerre<StopL)
              {
               OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // close position
               return(0); // exit
              }
            // check for stop
            if(Stop>0)  
              {                 
               if(OrderOpenPrice()-Ask>Point*Stop)
                 {
                   OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // close position
                   return(0);
                 }
              }
           }
        }
     }
     
   return(0);
  }
// the end.

