//+------------------------------------------------------------------+
//|                                                 eramax_remon.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "eramax"
#property link      "eramax.org"
#property version   "1.00"
#property strict
input double Risk = 1;
input double ProfitRatio = 1;
input int Step = 15;
double minLot,maxLot;
double profit_amount;
int     Magic       = 1558;
int     Slippage    = 5;
double lot = 0.1;
double currentAsk = 0;
/*struct Trade
{
   double lotsize;    
   double openPrice;  
   int ticket;
   int Type;  
};*/
  
int OnInit()
  {
      minLot = MarketInfo(Symbol(),MODE_MINLOT);
      maxLot = MarketInfo(Symbol(),MODE_MAXLOT);
      CalcLot();
      profit_amount = ProfitRatio*AccountBalance()/100;
      return(INIT_SUCCEEDED);
  }

void OnDeinit(const int reason){  }
  
void OnTick()
{
    CloseControl();
    PrintData2();
    Print(trade_count + "   " + AccountEquity());
    if(trade_count == 0)//------ New Start
    {
       addTrade(lot);
       HalfProfit = 0;
    }
    if( NormalizeDouble(currentAsk + Step*Point,Digits()) == Ask || NormalizeDouble(currentAsk - Step*Point,Digits()) == Ask )
    {
       addTrade(lot);
    }   
    
   
   
}
void addTrade(double lt)
{     
    lot = NormalizeDouble(lt,2);
    if(!buyFound && OrderSend(Symbol(),OP_BUY,lot,NormalizeDouble(Ask,Digits()),Slippage,0,0,"eramax",Magic,0,clrGreen)<0)
        Print(" Error open Buy N ",GetLastError());
    else currentAsk = Ask;
    if(!sellFound &&  OrderSend(Symbol(),OP_SELL,lot,NormalizeDouble(Bid,Digits()),Slippage,0,0,"eramax",Magic,0,clrGreen)<0)
        Print(" Error open Sell N ",GetLastError());      
}

double Prof=0;
int trade_count = 0;
double highestProfitTradeb = 0 , highestLossTradeb = 0, highestProfitTrades = 0 , highestLossTrades = 0;
bool buyFound = false,sellFound = false;
double bTrades[200][2];
double sTrades[200][2];
void OrderControl(bool closeAll=false )
{
    trade_count = 0; buyFound = false; sellFound = false; Prof=0;
    ArrayInitialize(bTrades,0);
    ArrayInitialize(sTrades,0);
    for (int i=0; i<OrdersTotal(); i++) 
    {
        if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) 
        {
            if (OrderMagicNumber() == Magic && OrderSymbol() == Symbol()) 
            {
                switch(OrderType())
                {
                  case OP_BUY       : 
                    if(closeAll) OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), 5, Red );
                    if( OrderOpenPrice() == Ask) buyFound = true;
                    bTrades[i][0] = OrderProfit();
                    bTrades[i][1] = OrderTicket();
                    break;
                  case OP_SELL      : 
                    if(closeAll) OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), 5, Red );
                    if( OrderOpenPrice() == Bid) sellFound = true;
                    sTrades[i][0] = OrderProfit();
                    sTrades[i][1] = OrderTicket();                    
                    break;
                  case OP_BUYLIMIT  :
                  case OP_BUYSTOP   :
                  case OP_SELLLIMIT :
                  case OP_SELLSTOP  : 
                    if(closeAll) OrderDelete( OrderTicket() );
                }
                //if( OrderProfit() > highestProfitTrade) { highestProfitTrade = OrderProfit(); highestPTicket = OrderTicket(); }
                //if( OrderProfit() < highestLossTrade) { highestLossTrade = OrderProfit(); highestLTicket = OrderTicket(); }                
                Prof = Prof + OrderProfit();
                trade_count++;
            }
        } 
    } 
    if(closeAll){ trade_count = 0; highestProfitTradeb = 0 ; highestLossTradeb = 0; highestProfitTrades = 0 ; highestLossTrades = 0; buyFound = false; sellFound = false; Prof=0; } 
    else
    {   ArraySort(bTrades,WHOLE_ARRAY,0,MODE_ASCEND);
        ArraySort(sTrades,WHOLE_ARRAY,0,MODE_ASCEND);
    } 
}
double CloseArrayb[200];
double CloseArrays[200];
double HalfProfit;
void CloseControl()
{
    OrderControl(false);
    if( NormalizeDouble(currentAsk + Step*Point,Digits()) == Ask || NormalizeDouble(currentAsk - Step*Point,Digits()) == Ask )
    {
        if(bTrades[0][0] > sTrades[0][0]) { CheckBuys(); CheckSells(); }
        else { CheckSells(); CheckBuys(); }
    } 
    if( Prof >= profit_amount )
    {
        OrderControl(true);
        Sleep(1000);
    } 
}
void CheckBuys()
{
    ArrayInitialize(CloseArrayb,0);
    double sumb = 0;
    if( bTrades[0][0] < 0 )
        {
            highestLossTradeb = bTrades[0][0]; 
            CloseArrayb[0]    = bTrades[0][1];                       
            int i = 200;
            do
            {
                if( sumb + HalfProfit >= highestLossTradeb )
                {
                    //----- We will close All trades which has profit is above or equal to highestLossTrade;
                    Print("Closing b");
                    for(int j=0;j<200;j++)
                    {
                         if(CloseArrayb[j] > 0 ) CloseOrder(CloseArrayb[j]);
                    }
                    double tmp = (sumb - highestLossTradeb );
                    if(tmp > 0) HalfProfit += tmp/2;
                    else HalfProfit -= tmp;
                    break;
                        
                }else
                {
                    i--;
                    sumb += bTrades[i][0];
                    CloseArrayb[200-i] = bTrades[i][1];
                }
            }while(i > 0);
        }    
}
void CheckSells()
{
    ArrayInitialize(CloseArrays,0);
    double sums = 0;
    if( sTrades[0][0] < 0 )
        {
            highestLossTrades = sTrades[0][0]; 
            CloseArrays[0]    = sTrades[0][1];     
            int i = 200;
            do
            {
                if( sums + HalfProfit >= highestLossTrades )
                {
                    //----- We will close All trades which has profit is above or equal to highestLossTrade;
                    Print("Closing s");
                    for(int j=0;j<200;j++)
                    {
                         if(CloseArrays[j] > 0 ) CloseOrder(CloseArrays[j]);
                    }
                    double tmp = (sums - highestLossTradeb );
                    if(tmp > 0) HalfProfit += tmp/2;
                    else HalfProfit -= tmp;
                    break;
                        
                }else
                {
                    i--;
                    sums += sTrades[i][0];
                    CloseArrays[200-i] = sTrades[i][1];
                }
            }while(i > 0);
        }    
    
}
void CloseOrder(int ticket)
{
    if (OrderSelect(ticket, SELECT_BY_POS, MODE_TRADES))
    {
        Print("Closing : ");
        OrderPrint();
        switch(OrderType())
        {
            case OP_BUY : OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), 5, Red ); break;
            case OP_SELL: OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), 5, Red ); break;
        }
    }
}
void addPending(double lot, double step)
{
    if(OrderSend(Symbol(),OP_BUYSTOP,lot,NormalizeDouble(1.3372,Digits()),Slippage,0,0,"eramax",Magic,0,clrGreen)<0)
        Print(" Error open BuyLimit N ",GetLastError());
    if(OrderSend(Symbol(),OP_SELLLIMIT,lot,NormalizeDouble(1.3372,Digits()),Slippage,0,0,"eramax",Magic,0,clrGreen)<0)
        Print(" Error open SELLSTOP N ",GetLastError());        
}
void PrintData()
{
    string txt ="Balance : " + DoubleToStr(AccountBalance(),0) + "\nEquity : " + DoubleToStr(AccountEquity(),0) +
    "\nFreeMargin : " + DoubleToStr(AccountFreeMargin(),0) + "\nProfit : " + DoubleToStr(AccountProfit(),0) + "\nLeverage : " +
     DoubleToStr(AccountLeverage(),0) + "\nMin Lot : " + minLot + "\nMax Lot : " + maxLot 
     + "\n100K Margin : " + DoubleToStr(MarketInfo(Symbol(),MODE_MARGINREQUIRED),0);       
    Comment(txt);  
}
void PrintData2()
{
    string txt = "\nFreeMargin : " + DoubleToStr(AccountFreeMargin(),0) + "\nProfit : " + DoubleToStr(Prof,0) + "\nLeverage : " +
     DoubleToStr(AccountLeverage(),0) + "\nMin Lot : " + minLot + "\nMax Lot : " + maxLot 
     + "\n100K Margin : " + DoubleToStr(MarketInfo(Symbol(),MODE_MARGINREQUIRED),0);       
    Comment(txt);  
}
double CalcLot()
{
   return NormalizeDouble(AccountEquity()*Risk/10000,2);
}  
