//+------------------------------------------------------------------+
//
//+------------------------------------------------------------------+
#property link      "http://www.forexfactory.com/" 
#property version   "1.00"
#property description "[ Idea Of remon78eg , Remon Reffat , the_programmer_eg@yahoo.com ]"
#property description "Programmers: (Other Programmer) & (remon78eg = Remon Reffat)"
#property strict
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum Trade
  {
   Only_BUY,   // Only BUY
   Only_SELL,  // Only SELL
   Only_All    // BUY and SELL
  };
enum LOTS_TYPE
  {
   FixedLot,     // Fixed Lot
   IncreasingLot // Increasing Lot
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
input  bool      CanRestart     = true;//Can Restart After Win
input  Trade     TypeOrders     = Only_All;
input  LOTS_TYPE LotsType       = IncreasingLot;
input  double    LOT            = 0.01;  // Lot
extern double    LotBalance     = 0.0;   // LotBalance (If 0.0 = No Money Management)
input  double    MinProfit_     = 00.00; // Minimal Profit $ Close Loss Deals
input  double    AMinProfit_    = 50.00; // Minimal Profit $ Close All Deals
input  int       MinStep        = 100;   // Step order
       int       MinStepPlus    = 0;     // Add minimal step
       bool      UsePartlyClose = true;  // Decrease All Lots After Close
input  int       MAGIC          = 2277;
       int       Slippage       = 3000;
input  double    CLOSE_BY_RATIO = 0.01;//CloseBy Ratio (0.01 to 1.00)
extern double    SingleTradeProfit_=1.0;//Profit $ If Use (Sell/Buy) Only 
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
double LotBuy=0.0;
double LotSel=0.0;
double MinProfit,AMinProfit,SingleTradeProfit;

int OnInit()
  {
  
  //remon78eg code start
   CalcMinProfits();
   if(LotBalance<=0.0){
     LotBuy=LOT;
     LotSel=LOT;
   }else{
     if(OrdersTotals(MAGIC,Symbol(),OP_BUY )==0 || !UsePartlyClose){LotBuy=NormalizeLot(AccountBalance()/LotBalance*LOT,Symbol());}else{LotBuy=GetMinLot(MAGIC,Symbol(),OP_BUY );}
     if(OrdersTotals(MAGIC,Symbol(),OP_SELL)==0 || !UsePartlyClose){LotSel=NormalizeLot(AccountBalance()/LotBalance*LOT,Symbol());}else{LotSel=GetMinLot(MAGIC,Symbol(),OP_SELL);}
   }
  //remon78eg code end
  
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   int b=0,s=0;
   double
   BuyProfit  = 0,
   SellProfit = 0,
   BuyMin     = 0,
   SellMax    = 0,
   BuyMinLot  = 0,
   SellMaxLot = 0,
   BuyLot     = 0,
   SellLot    = 0,
   BuyMax     = 0,
   SellMin    = 0,
   SellTicProfit = 0,
   BuyTicProfit  = 0;
   int
   BuyMaxTic  = 0,
   SellMinTic = 0;
   
   bool CanCloseBy=false;//remon78eg
   if(!CanRestart && OrdersTotals(MAGIC,Symbol(),-1)==0){return;}//remon78eg
   
   for(int i=OrdersTotal()-1; i>=0; i--)
      if(OrderSelect(i,SELECT_BY_POS))
         if(OrderSymbol()==Symbol())
            if(OrderMagicNumber()==MAGIC)
              {
               if(OrderType()==OP_BUY)
                 {
                  b++;
                  if(OrderOpenPrice()<BuyMin || BuyMin==0)
                    {
                     BuyMin=OrderOpenPrice();
                     BuyMinLot=OrderLots();
                    }
                  if(OrderOpenPrice()>BuyMax || BuyMin==0)
                    {
                     BuyMax=OrderOpenPrice();
                     BuyMaxTic=OrderTicket();
                     BuyTicProfit=OrderProfit()+OrderCommission()+OrderSwap();
                    }
                  if(OrderProfit()+OrderCommission()+OrderSwap()>0)BuyProfit+=OrderProfit()+OrderCommission()+OrderSwap();
                 }
               if(OrderType()==OP_SELL)
                 {
                  s++;
                  if(OrderOpenPrice()>SellMax || SellMax==0)
                    {
                     SellMax=OrderOpenPrice();
                     SellMaxLot=OrderLots();
                    }
                  if(OrderOpenPrice()<SellMin || SellMin==0)
                    {
                     SellMin=OrderOpenPrice();
                     SellMinTic=OrderTicket();
                     SellTicProfit=OrderProfit()+OrderCommission()+OrderSwap();
                    }
                  if(OrderProfit()+OrderCommission()+OrderSwap()>0)SellProfit+=OrderProfit()+OrderCommission()+OrderSwap();
                 }
              }
// Summ profit final
   double ProfitBuy=BuyTicProfit+BuyProfit;
   double ProfitSel=SellTicProfit+SellProfit;

   //double  lot=NormalizeDouble(AccountBalance()*Risk/100/MarketInfo(Symbol(),MODE_MARGINREQUIRED),2);
   if(LotsType==FixedLot){
     BuyLot =LotBuy;//remon78eg
     SellLot=LotSel;//remon78eg
   }else{
     BuyLot =iif(b==0,LotBuy,BuyMinLot +LotBuy);//remon78eg
     SellLot=iif(s==0,LotSel,SellMaxLot+LotBuy);//remon78eg
   }

   double BuyDist  = NormalizeDouble(MinStep*Point()+MinStepPlus*Point()*b,Digits());
   double SellDist = NormalizeDouble(MinStep*Point()+MinStepPlus*Point()*s,Digits());


   if(TypeOrders==Only_BUY || TypeOrders==Only_All)
      if((b==0) || (b>0 && (BuyMin-Ask)>=BuyDist))
         if(OrderSend(Symbol(),OP_BUY,NormalizeDouble(BuyLot,2),NormalizeDouble(Ask,Digits()),Slippage,0,0,"My order",MAGIC,0,clrGreen)<0)
            Print(" Error open Buy N ",GetLastError());

   if(TypeOrders==Only_SELL || TypeOrders==Only_All)
      if((s==0) || (s>0 && (Bid-SellMax)>=SellDist))
         if(OrderSend(Symbol(),OP_SELL,NormalizeDouble(SellLot,2),NormalizeDouble(Bid,Digits()),Slippage,0,0,"My order",MAGIC,0,clrGreen)<0)
            Print(" Error open Sell N ",GetLastError());


   //remon78eg code start
   //if(CalcProfits(MAGIC,Symbol(),OP_BUY )>=AMinProfit){CanCloseBy=true;/*CloseAll(MAGIC,Symbol(),OP_BUY );*/}//remon78eg code
   //if(CalcProfits(MAGIC,Symbol(),OP_SELL)>=AMinProfit){CanCloseBy=true;/*CloseAll(MAGIC,Symbol(),OP_SELL);*/}//remon78eg code
   
   if(ProfitBuy+iif(UsePartlyClose,CalcWhatLoss(MAGIC,Symbol(),OP_BUY ,BuyMaxTic ),0.0)>=MinProfit && b>=2){CloseAll(OP_BUY ,BuyMaxTic );iif(UsePartlyClose,0.0,ClosePartly(MAGIC,Symbol(),OP_BUY ));}//remon78eg code
   if(ProfitSel+iif(UsePartlyClose,CalcWhatLoss(MAGIC,Symbol(),OP_SELL,SellMinTic),0.0)>=MinProfit && s>=2){CloseAll(OP_SELL,SellMinTic);iif(UsePartlyClose,0.0,ClosePartly(MAGIC,Symbol(),OP_SELL));}//remon78eg code

   if(LotBalance<=0.0){
     LotBuy=LOT;
     LotSel=LOT;
   }else{
     if(OrdersTotals(MAGIC,Symbol(),OP_BUY )==0 || !UsePartlyClose){LotBuy=NormalizeLot(AccountBalance()/LotBalance*LOT,Symbol());}else{LotBuy=GetMinLot(MAGIC,Symbol(),OP_BUY );}
     if(OrdersTotals(MAGIC,Symbol(),OP_SELL)==0 || !UsePartlyClose){LotSel=NormalizeLot(AccountBalance()/LotBalance*LOT,Symbol());}else{LotSel=GetMinLot(MAGIC,Symbol(),OP_SELL);}
   }
   
   //--------test to close by
   int c1,c2;
   double Ratio,p1,p2;
   c1=OrdersTotals(MAGIC,Symbol(),OP_BUY );
   c2=OrdersTotals(MAGIC,Symbol(),OP_SELL);
   p1=CalcProfits(MAGIC,Symbol(),OP_BUY);
   p2=CalcProfits(MAGIC,Symbol(),OP_SELL);
   if(1==c1 && 1==c2 && p1!=0 && p2!=0 && p1+p2>=AMinProfit){
     Ratio=p1/p2;
     if(Ratio>1){Ratio=1.0/Ratio;}//make it <= 1.0
    if(Ratio>=CLOSE_BY_RATIO){CloseBy(MAGIC,Symbol());}
   }
   //---------
   
   //Sell/Buy Only Profit To Close
   if(1==c1 && p1>=SingleTradeProfit && TypeOrders==Only_BUY){CloseAll(MAGIC,Symbol(),OP_BUY );}
   if(1==c2 && p2>=SingleTradeProfit && TypeOrders==Only_SELL){CloseAll(MAGIC,Symbol(),OP_SELL);}
   
   CalcMinProfits();//MinProfit,AMinProfit Ratio Changed To Lot And Balance
   //remon78eg code end
   
   Comment("AccountProfit:  ",NUM(CalcProfits(MAGIC,Symbol(),-1),2)," / ",AMinProfit,"\n",
      "B= ",NUM(ProfitBuy,2)," ~ ",+NUM(iif(UsePartlyClose,CalcWhatLoss(MAGIC,Symbol(),OP_BUY ,BuyMaxTic),0.0),2),"\n",
      "S= ",NUM(ProfitSel,2)," ~ ",+NUM(iif(UsePartlyClose,CalcWhatLoss(MAGIC,Symbol(),OP_SELL,SellMinTic),0.0),2),"\n",
   "");

}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {

  }
//+------------------------------------------------------------------+
void CloseAll(int aType,int ticket)
  {
   for(int i=OrdersTotal()-1; i>=0; i--)
      if(OrderSelect(i,SELECT_BY_POS))
         if(OrderSymbol()==Symbol())
            if(OrderMagicNumber()==MAGIC)
              {
               if(OrderType()==aType && OrderType()==OP_BUY)
                  if(OrderProfit()+OrderCommission()+OrderSwap()>0 || OrderTicket()==ticket)
                     if(!OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Bid,Digits()),Slippage,clrRed))
                        Print(" OrderClose OP_BUY Error N",GetLastError());

               if(OrderType()==aType && OrderType()==OP_SELL)
                  if(OrderProfit()+OrderCommission()+OrderSwap()>0 || OrderTicket()==ticket)
                     if(!OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Ask,Digits()),Slippage,clrRed))
                        Print(" OrderClose OP_SELL Error N",GetLastError());

              }
  }
//+------------------------------------------------------------------+














//from here:   remon78eg code start
//---------------------------------------------
double iif(bool Test,double TruePart,double FalsePart){if(Test)return TruePart;return FalsePart;}
void CalcMinProfits(){
  double MinLot;
  if(LotBalance<=0.0){
    MinProfit =MinProfit_ ;
    AMinProfit=AMinProfit_;
    SingleTradeProfit=SingleTradeProfit_;
  }else{
    MinLot=iif(LotBuy<LotSel,LotBuy,LotSel);
    MinProfit =MinLot/LOT*MinProfit_ ;
    AMinProfit=MinLot/LOT*AMinProfit_;
    SingleTradeProfit=MinLot/LOT*SingleTradeProfit_;
  }
}

bool CloseAll(int Magic,string deal,int dir){
  int i;
  
  RefreshRates();
  for(i=OrdersTotal()-1;i>=0;i--){
    if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)){Print("Error Select: ",__LINE__);RefreshRates();break;}
    if(OrderSymbol()==deal && (OrderMagicNumber()==Magic || Magic==-1) && (OrderType()==dir || dir==-1)){
      if(OrderType()==OP_BUY ){if(!OrderClose(OrderTicket(),OrderLots(),SymbolInfoDouble(OrderSymbol(), SYMBOL_BID),3000,clrLightGreen)){PlaySound("::error.wav");Print("Canot Close "+OrderSymbol());RefreshRates();break;}}
      if(OrderType()==OP_SELL){if(!OrderClose(OrderTicket(),OrderLots(),SymbolInfoDouble(OrderSymbol(), SYMBOL_ASK),3000,clrLightPink )){PlaySound("::error.wav");Print("Canot Close "+OrderSymbol());RefreshRates();break;}}
    }
  }

  return(true);
}

bool ClosePartly(int Magic,string deal,int dir){
  int i;
  string s="";
  double lot;
  
  RefreshRates();
  for(i=OrdersTotal()-1;i>=0;i--){
    if(IsStopped()){return false;}
    if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)){Print("Error Select: ",__LINE__);RefreshRates();break;}
    //---------------------------------------------------
    if(OrderSymbol()==deal && (OrderMagicNumber()==Magic || Magic==-1) && (OrderType()==dir || dir==-1)){
      lot=iif(OP_BUY==dir,LotBuy,LotSel);
      if(lot>=MarketInfo(deal,MODE_MINLOT) && OrderLots()>lot){
        if(OrderType()==OP_BUY ){if(!OrderClose(OrderTicket(),lot,SymbolInfoDouble(OrderSymbol(), SYMBOL_BID),3000,clrLightGreen)){PlaySound("::error.wav");Print("Canot Close "+OrderSymbol());RefreshRates();break;}}
        if(OrderType()==OP_SELL){if(!OrderClose(OrderTicket(),lot,SymbolInfoDouble(OrderSymbol(), SYMBOL_ASK),3000,clrLightPink )){PlaySound("::error.wav");Print("Canot Close "+OrderSymbol());RefreshRates();break;}}
      }
    }
  }

  return(true);
}
//---------------------------------------------
double CalcWhatLoss(int Magic,string deal,int dir,int Ticket){
  int i;
  double lossBig=0,lossSmall=0;
  double lotMin=0,LotAll=0;
  
  RefreshRates();
  for(i=OrdersTotal()-1;i>=0;i--){
    if(IsStopped()){return false;}
    if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)){Print("Error Select: ",__LINE__);RefreshRates();break;}
    //---------------------------------------------------
    if(OrderSymbol()==deal && (OrderMagicNumber()==Magic || Magic==-1) && OrderType()==dir){
      lossBig=OrderProfit()+OrderCommission()+OrderSwap();
      if(OrderLots()>iif(OP_BUY==dir,LotBuy,LotSel) && lossBig<0 && OrderTicket() !=Ticket){//remove first & last orders & all profit orders
        lotMin=iif(OP_BUY==dir,LotBuy,LotSel);
        LotAll =OrderLots  ();
        //lossSmall+=((lotMin/LotAll)*lossBig);
        lossSmall+=lossBig/(LotAll/lotMin);//ok
        //Print(OrderTicket()," ",(lotMin/LotAll)*lossBig);
        //Print(OrderTicket()," ",lossBig/(LotAll/lotMin));
      }
    }
    //---------------------------------------------------
  }
  //if(0==LotAll){}else{lossSmall=lotSome*lossBig/LotAll;}
  return(lossSmall);
}

double CalcProfits(int Magic,string sym,int Dir){//
  double profitloss=0.0;
  bool Err;
  
  while(true){
    profitloss=0.0;
    Err=false;
    RefreshRates();
    for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)){Err=true;break;}
      if((OrderType()==OP_BUY || OrderType()==OP_SELL)&&(OrderType()==Dir || Dir==-1) && ((OrderMagicNumber()==Magic || Magic==-1) && (OrderSymbol()==sym || sym=="" || sym==NULL))){
        profitloss+=OrderProfit()+OrderCommission()+OrderSwap();
      }
    }
    if(!Err){break;}
  }
  
  return(profitloss);
}

double GetMinLot(int Magic,string sym,int Dir){
  double Min=0.0;
  bool Err;
  
  while(true){
    Min=DBL_MAX;
    Err=false;
    RefreshRates();
    for(int i=OrdersTotal()-1;i>=0;i--){
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)){Err=true;break;}
      if((OrderType()==OP_BUY || OrderType()==OP_SELL)&&(OrderType()==Dir || Dir==-1) && ((OrderMagicNumber()==Magic || Magic==-1) && (OrderSymbol()==sym || sym=="" || sym==NULL))){
        if(OrderLots()<Min){Min=OrderLots();}
      }
    }
    if(!Err){break;}
  }
  
  return(Min);
}

string NUM(double number,int n){
  return(DoubleToStr(number,n));
}

double NormalizeLot(double eLot,string sym){
  double LotNrm,MinLot,LotStp;
  
  MinLot=MarketInfo(sym,MODE_MINLOT);
  LotStp=MarketInfo(sym,MODE_LOTSTEP);
  eLot=(double)NUM(eLot,6);//convert 1.000e-18 to 0.0
  LotNrm=(double)NUM(MathFloor(eLot/LotStp)*LotStp,6);
  if(MathAbs(LotNrm)<MinLot)return 0;
  return(LotNrm);
}

int OrdersTotals(int Magic,string sym,int Direction){
  int x=0,i;
  bool error;
  
  while(true){
    x=0;
    error=false;
    for(i=0;i<OrdersTotal();i++){
      if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)){RefreshRates();error=true;break;}
      if((OrderMagicNumber()==Magic || Magic==-1) && (OrderType()==OP_BUY || OrderType()==OP_SELL)&&(OrderType()==Direction || Direction==-1) && (OrderSymbol()==sym || sym=="" || sym==NULL)){x++;}
    }
    if(!error){break;}
    if(IsStopped()){return -1;};
  }
  return(x);
}

bool CloseBy(int Magic,string sym){//false == fin, true==not yet
  int t1=0,t2=0,err;
  bool r;
  
  for(int i=OrdersTotal()-1;i>=0;i--){
    if(!OrderSelect(i,SELECT_BY_POS,MODE_TRADES)){RefreshRates();return true;}
    if(OrderSymbol()==sym && OrderType()==OP_BUY  && t1==0 && (OrderMagicNumber()==Magic || Magic==-1)){t1=OrderTicket();}
    if(OrderSymbol()==sym && OrderType()==OP_SELL && t2==0 && (OrderMagicNumber()==Magic || Magic==-1)){t2=OrderTicket();}

    if(t1>0 && t2>0){
      r=OrderCloseBy(t1,t2);
      //if(DEALS_SOUND)PlaySound("::coin.wav");//eoo.wav
      err=GetLastError(); 
      if(err!=ERR_NO_ERROR){Print("OrderCloseBy() Error: ");}
      return true;
    }
  }
  return false;
}

//--------------------------------------------------------------
//remon78eg code end

