//+------------------------------------------------------------------+
//|                                                 FBCI EA Beta.mq4 |
//|                                    Copyright © 2009, MastermindG |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net/"

// magic number
extern int Magic =  12345;
extern bool TradeOnlyBreakouts = true; //Will only trade breakouts ignoring signals with no valid retracement
extern double MinimumPips = 0;  //Desired pip retrieval for retracement, 0 to disable
extern double TakeProfit = 0; //Desired pip retrieval when trending, 0 to disable, if disabled exiting will need to be done manually
extern double TrailingStop = 15; //0 to disable, if disabled stepping will not function
extern double TrailingStopStep2 = 10; //Next available trailing stop
extern double TrailingStopStep3 = 10; //Next available trailing stop
extern double TrailingStopStep4 = 10; //Next available trailing stop
extern double Lots = 0; //Desired Lot Size, if 0 lots will be determined by 1% of Avaialable Margin

#include <stdlib.mqh>
#include <WinUser32.mqh>

string ReadCommentfromFile()
{
   string textfile=StringConcatenate(Symbol(),"_comment.txt");
   int handle=FileOpen(textfile,FILE_READ|FILE_WRITE);
   if(handle>0)
      {
         return(FileReadString(handle));
         FileClose(handle);
      }
   else
      {
         return("nofile");
      }
}

string ReadCommentfromIndicator()
{
      //Comment is written with current symbol, checking here
      string fbcibuild=StringConcatenate(Symbol(),"_SFBInd_FractalComment2");
      string fbciComment=ObjectDescription(fbcibuild);
      return(fbciComment);
}

int WriteCommenttoFile()
{
   string commentfile=StringConcatenate(Symbol(),"_comment.txt");
   logstuff(commentfile,ReadCommentfromIndicator(),0);
}

int WriteSignaltoFile()
{
   string newsignal=StringConcatenate(Symbol(),"_signals.txt");
   logstuff(newsignal,ReadCommentfromIndicator(),1);
}

string GetOrderType()
{    
   //Extracting Order Type Element from Comment
   string fbciComment=ReadCommentfromIndicator();
   string fbciordersub=StringSubstr(fbciComment, 0, 4);
   string fbciorder=StringTrimRight(fbciordersub);
   return(fbciorder);      
}

int GetOrderTime()
{
   //Extracting Time Element from Comment
   string fbciComment=ReadCommentfromIndicator();
   int fbcilength=StringLen(fbciComment);
   string fbcitimesub=StringSubstr(fbciComment,fbcilength - 16,0);
   string fbcitimetxt=StringTrimLeft(fbcitimesub);
   //Convert Time to Seconds since 1970
   int fbcitime=StrToTime(fbcitimetxt);

   //string fbcitimetxt="2009.04.10 12:45";
}

string logstuff(string textfile, string sometext, int seek)
{
         int logging=FileOpen(textfile,FILE_READ|FILE_WRITE);
         if(logging>0)
            {
               if(seek>0)
                  {
                     FileSeek(logging,0,SEEK_END);
                  }
               FileWrite(logging,sometext);
               FileClose(logging);
               logging=0;
               return(0);
            }
         else
            {
               Print("Error opening file..",textfile,GetLastError());
               return(1);
            }
}

double CalculateLots(int Lots)
{
double Margin;
Margin = AccountFreeMargin( ) ;
double Hasil;
double MLots ;
Hasil = Margin/10000;
MLots = MathFloor(Hasil);
//Seeing Max Lots of 50 for IBFX Mini
if(Lots==0)
   {
      return(MLots);
   }
if(Lots!=0)
   {
      return(Lots);
   }
}

int GetOrdersCount(int Type = -1)
{
   int count = 0;
   
   for(int i = 0; i < OrdersTotal(); i++)
   {
      // already closed
      if(OrderSelect(i, SELECT_BY_POS) == false) continue;
      // not current symbol
      if(OrderSymbol() != Symbol()) continue;
      
      if(OrderType() == Type || Type == -1)
      {
         count++;
      }
   }
   return (count);
}

int ReturnFirstTicket(int Magic)
{
// Takes an input of MagicNumber

int icnt, itotal, iTicket;

itotal=OrdersTotal();

   for(icnt=0;icnt<itotal;icnt++) 
     {                               // order loop boundary
      OrderSelect(icnt, SELECT_BY_POS, MODE_TRADES);
      
       // check for opened position, symbol & MagicNumber
      if(OrderType()<=OP_SELL && OrderSymbol()==Symbol()  && OrderMagicNumber()==Magic)  // Open orders for pair on chart and the right Magic Number
        {     
         iTicket = OrderTicket();
         break;
        }
        

     }  // order loop boundary

return(iTicket);
     
}

double GetSL()
{
   double SMA50;
   SMA50=iMA(NULL,0,50,0,MODE_SMA,PRICE_CLOSE,0);
   double SMA50normal=NormalizeDouble(SMA50,4);         
   return(SMA50normal);
}

int wherami(double SMA50normal)
{
   if(Bid>SMA50normal)
      {
         return(1);
      }
    else
      {
         return(2);
      }
}

double CheckDigits()
{
   if (Digits>3)
      {
         return(0.0001);
      }
   else 
      {
         return(0.01);
      }
}
int CheckBars()
{    
  double bar0=Close[0]-Open[0];
  double bar1=Close[1]-Open[1];
    
  if(bar0>0 && bar1>0)
   {
      return(2);
   }
  if(bar0<0 && bar1<0)
   {
      return(1);
   }
}

double StripExtras(string text)
{
   int length=StringLen(text) - 1;
   string search1="0";
   string search2=".";
   while(length>=0)
      {
         int index=StringFind(text,search1,0);
         int index2=StringFind(text,search2,0);
         text=StringSetChar(text,index,32);
         text=StringSetChar(text,index2,32);
         length--;
      }
   return(StrToDouble(text));
}

double FibRetracement(int trend)
{
   //Go back max of 8 bars for min/max
   double sellmin,                              // Minimal price
          buymax;                              // Maximal price

   int Quant_Bars=8;
   string numberofbarstotest=StringConcatenate("Number of bars to test ",Quant_Bars);
   
   int Ind_max =ArrayMaximum(High,Quant_Bars,1);// Bar index of max. price 
   int Ind_min =ArrayMinimum(Low, Quant_Bars,1);// Bar index of min. price 
   buymax=High[Ind_max];                       // Desired max. price
   sellmin=Low[Ind_min];                        // Desired min. price
   if(trend==1)
      {
         //subtract bar price from current price and get pips
         double bdifference=StripExtras(buymax - Ask);
         if(Ask>=buymax)
            {
               return (0);
            }
         else
            {
               //Restrict Retracement to atleast 5 pips
               if(bdifference>=MinimumPips)
                  {
                     return (bdifference);
                  }
               else
                  {
                     return (0);
                  }
            }
      }
   if(trend==2)
      {
         double sdifference=StripExtras(Bid - sellmin);
         if(Bid<=sellmin)
            {
               return (0);
            }
         else
            {
               //Restrict Retracement to atleast 5 pips
               if(sdifference>=MinimumPips)
                  {
                     return (sdifference);
                  }
               else
                  {
                     return(0);
                  }
            }
      }
   //return (0);
}

int CheckTime()
{
   //Have to go through this junk because strtime uses local time and not server time
   int y=Year();
   int M=Month();
   int d=Day();
   int h=Hour();
   int m=Minute();
   if(M<10)
      {
         string N="0"+M;
         M=StrToInteger(N);
      }
   if(d<10)
      {
         string e="0"+d;
         d=StrToInteger(e);
      }
   if(m<10)
      {
         string n="0"+m;
         m=StrToInteger(n);
      }
   //Convert Time to Seconds since 1970 - 2009.04.06 1:05
   string times=StringConcatenate(y,".",M,".",d," ",h,":",m);
   int brokerseconds=StrToTime(times);
   //Compensate for FBCI Time Difference
   int fbcithreshold=brokerseconds - 1200;
   return (fbcithreshold);
}

void fbuy (double MLots)
{   
   double MyPoint = CheckDigits();
   int bticket=OrderSend(Symbol(),OP_BUY,MLots,Ask,3,0,TakeProfit*MyPoint,ReadCommentfromIndicator(),Magic,0,Green);
        if(bticket<1)
            {
               int error=GetLastError();
               Print("Error = ",ErrorDescription(error));
               return;
            }
           OrderPrint(); 
   return(0);  
 }
 
void fsell (double MLots)
{  
   double MyPoint = CheckDigits();
   int sticket=OrderSend(Symbol(),OP_SELL,MLots,Bid,3,0,TakeProfit*MyPoint,ReadCommentfromIndicator(),Magic,0,Red);
      if(sticket<1)
            {
               int error=GetLastError();
               Print("Error = ",ErrorDescription(error));
               return;
            }
           OrderPrint(); 
   return(0);
 }

//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+

int start()
  {
//----
string logfile=StringConcatenate(Symbol(),"_logging.txt");
double MyPoint = CheckDigits();

WriteCommenttoFile();

if(CalculateLots(Lots)>50)
   {
      Print("Lots is above 50, Broker may not accept order");
   }  

if (GetOrdersCount() == 0)
{
   if(ReadCommentfromFile()!=ReadCommentfromIndicator())
      {
         WriteSignaltoFile();
         string initiallog=StringConcatenate(GetOrderType(),GetOrderTime(),CalculateLots(Lots),CheckTime(),GetSL(),Bid);
         logstuff(logfile,initiallog,1);
         logstuff(logfile," ",1);
         if(GetOrderTime()>=CheckTime())
            {
               logstuff(logfile,"Time is OK",1);
               if (GetOrderType()=="BUY")
                  {
                     logstuff(logfile,"Buy Order Set..",1);
                     logstuff(logfile," ",1);
                     if(TradeOnlyBreakouts==true)
                        {
                           if(FibRetracement(1)>0)
                              {
                                 if(wherami(GetSL())==1)
                                    {
                                       logstuff(logfile,"Buy Order Placed",1);
                                       logstuff(logfile," ",1);
                                       fbuy(CalculateLots(Lots));
                                    }
                              }
                           else
                              {
                                 return(0);
                              }
                        }
                     else
                        {
                           if(wherami(GetSL())==1)
                              {
                                 logstuff(logfile,"Buy Order Placed",1);
                                 logstuff(logfile," ",1);
                                 fbuy(CalculateLots(Lots));
                              }
                        }  
                  }
               if (GetOrderType()=="SELL")
                  {
                     logstuff(logfile,"Sell Order Set..",1);
                     logstuff(logfile," ",1);
                     if(TradeOnlyBreakouts==true)
                        {
                           if(FibRetracement(2)>0)
                              {
                                 if(wherami(GetSL())==2)
                                    {
                                       logstuff(logfile,"Sell Order Placed",1);
                                       logstuff(logfile," ",1);
                                       fsell(CalculateLots(Lots));
                                    }
                              }
                           else
                              {
                                 return(0);
                              }
                        }
                     else
                        {
                           if(wherami(GetSL())==2)
                              {
                                 logstuff(logfile,"Sell Order Placed",1);
                                 logstuff(logfile," ",1);
                                 fbuy(CalculateLots(Lots));
                              }
                        }  
                  }
            }
      }
}
if (GetOrdersCount()>0)
{
   int ticket=ReturnFirstTicket(Magic);
   OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES);
   if(OrderType()==OP_BUY)
      {
         if(Bid<GetSL() && Close[1]<GetSL())
            {
               if(CheckBars()==1)
                  {
                     OrderClose(ticket,CalculateLots(Lots),Bid,3,Blue);
                  }
            }
         //Check to see if there is room for retracment, if not it is a trending market and trailingstop will be used if enabled
         if(FibRetracement(1)==0)
            {
               //Check to see if Trailing Stop Method has been enabled
               if(TrailingStop>0)
                  {
                     if(Bid-OrderOpenPrice()>MyPoint*TrailingStop && Bid-OrderOpenPrice()<MyPoint*(TrailingStop + TrailingStopStep2))
                        {
                           OrderModify(ticket,OrderOpenPrice(),Bid-MyPoint*TrailingStop,OrderTakeProfit(),0,Green);
                           return(0);
                        }
                     if(Bid-OrderOpenPrice()>MyPoint*(TrailingStop + TrailingStopStep2) && Bid-OrderOpenPrice()<MyPoint*(TrailingStopStep2 + TrailingStopStep3))
                        {
                           OrderModify(ticket,OrderOpenPrice(),Bid-MyPoint*(TrailingStop + TrailingStopStep2),OrderTakeProfit(),0,Green);
                           return(0);
                        }
                     if(Bid-OrderOpenPrice()>MyPoint*(TrailingStopStep2 + TrailingStopStep3) && Bid-OrderOpenPrice()<MyPoint*(TrailingStopStep3 + TrailingStopStep4))
                        {
                           OrderModify(ticket,OrderOpenPrice(),Bid-MyPoint*(TrailingStopStep2 + TrailingStopStep3),OrderTakeProfit(),0,Green);
                           return(0);
                        }
                     if(Bid-OrderOpenPrice()>MyPoint*(TrailingStopStep3 + TrailingStopStep4))
                        {
                           OrderModify(ticket,OrderOpenPrice(),Bid-MyPoint*(TrailingStopStep3 + TrailingStopStep4),OrderTakeProfit(),0,Green);
                           return(0);
                        }
                  }
               else
                  {
                  //Nothing needs to be done, TakeProfit will be assigned if enabled, TrailingStop is disabled and no retracement
                  //Order will need to closed manually if TakeProfit is not enabled                     
                     return(0);
                  }
            }
         else
            {
               if(Bid-OrderOpenPrice()>MyPoint*FibRetracement(1) && Bid-OrderOpenPrice()<MyPoint*MathRound(FibRetracement(1)*1.618))                   
                  {
                     OrderModify(ticket,OrderOpenPrice(),Bid-MyPoint*FibRetracement(1),OrderTakeProfit(),0,Green);
                     return(0);
                  }
               if(Bid-OrderOpenPrice()>MyPoint*MathRound(FibRetracement(1)*1.618) && Bid-OrderOpenPrice()<MyPoint*MathRound(FibRetracement(1)*2.618))                   
                  {
                     OrderModify(ticket,OrderOpenPrice(),Bid-MyPoint*MathRound(FibRetracement(1)*1.618),OrderTakeProfit(),0,Green);
                     return(0);
                  }
               if(Bid-OrderOpenPrice()>MyPoint*MathRound(FibRetracement(1)*2.618) && Bid-OrderOpenPrice()<MyPoint*MathRound(FibRetracement(1)*4.236))                   
                  {
                     OrderModify(ticket,OrderOpenPrice(),Bid-MyPoint*MathRound(FibRetracement(1)*2.618),OrderTakeProfit(),0,Green);
                     return(0);
                  }
               if(Bid-OrderOpenPrice()>MyPoint*MathRound(FibRetracement(1)*4.236))                   
                  {
                     OrderModify(ticket,OrderOpenPrice(),Bid-MyPoint*MathRound(FibRetracement(1)*4.236),OrderTakeProfit(),0,Green);
                     return(0);
                  }
            }                   
      }         
   if(OrderType()==OP_SELL)
      {
         if(Ask>GetSL() && Close[1]>GetSL())
           {
               if(CheckBars()==1)
                  {
                     OrderClose(ticket,CalculateLots(Lots),Ask,3,Blue);
                  }
            }
         //Check to see if there is room for retracment, if not it is a trending market and trailingstop will be used if enabled
         if(FibRetracement(2)==0)
            
            //Check to see if Trailing Stop Method has been enabled
            if(TrailingStop>0)
               {
                  if(OrderOpenPrice()-Ask<MyPoint*TrailingStop && OrderOpenPrice()-Ask>MyPoint*(TrailingStop + TrailingStopStep2))
                     {
                        OrderModify(ticket,OrderOpenPrice(),Ask+MyPoint*TrailingStop,OrderTakeProfit(),0,Red);
                        return(0);
                     }
                  if(OrderOpenPrice()-Ask<MyPoint*(TrailingStop + TrailingStopStep2) && OrderOpenPrice()-Ask>MyPoint*(TrailingStopStep2 + TrailingStopStep3))
                     {
                        OrderModify(ticket,OrderOpenPrice(),Ask+MyPoint*(TrailingStop + TrailingStopStep2),OrderTakeProfit(),0,Red);
                        return(0);
                     }
                  if(OrderOpenPrice()-Ask<MyPoint*(TrailingStopStep2 + TrailingStopStep3) && OrderOpenPrice()-Ask>MyPoint*(TrailingStopStep3 + TrailingStopStep4))
                     {
                        OrderModify(ticket,OrderOpenPrice(),Ask+MyPoint*(TrailingStopStep2 + TrailingStopStep3),OrderTakeProfit(),0,Red);
                        return(0);
                     }
                  if(OrderOpenPrice()-Ask<MyPoint*(TrailingStopStep3 + TrailingStopStep4))
                     {
                        OrderModify(ticket,OrderOpenPrice(),Ask+MyPoint*(TrailingStopStep3 + TrailingStopStep4),OrderTakeProfit(),0,Red);
                        return(0);
                     }
               }
            else
               {
                  //Nothing needs to be done, TakeProfit will be assigned if enabled, TrailingStop is disabled and no retracement
                  //Order will need to closed manually if TakeProfit is not enabled
                  return(0);
               }
         else
            {
               if(OrderOpenPrice()-Ask<MyPoint*FibRetracement(2) && OrderOpenPrice()-Ask>MyPoint*MathRound(FibRetracement(2)*1.618))                   
                  {
                     OrderModify(ticket,OrderOpenPrice(),Ask+MyPoint*FibRetracement(2),OrderTakeProfit(),0,Red);
                     return(0);
                  }
               if(OrderOpenPrice()-Ask<MyPoint*MathRound(FibRetracement(2)*1.618) && OrderOpenPrice()-Ask>MyPoint*MathRound(FibRetracement(2)*2.618))                   
                  {
                     OrderModify(ticket,OrderOpenPrice(),Ask+MyPoint*MathRound(FibRetracement(2)*1.618),OrderTakeProfit(),0,Red);
                     return(0);
                  }
               if(OrderOpenPrice()-Ask<MyPoint*MathRound(FibRetracement(2)*2.618) && OrderOpenPrice()-Ask>MyPoint*MathRound(FibRetracement(2)*4.236))                   
                  {
                     OrderModify(ticket,OrderOpenPrice(),Ask+MyPoint*MathRound(FibRetracement(2)*2.618),OrderTakeProfit(),0,Red);
                     return(0);
                  }
               if(OrderOpenPrice()-Ask<MyPoint*MathRound(FibRetracement(2)*4.236))                   
                  {
                     OrderModify(ticket,OrderOpenPrice(),Ask+MyPoint*MathRound(FibRetracement(2)*4.236),OrderTakeProfit(),0,Red);
                     return(0);
                  }
            }
      }
 }   
          
return(0);
  }
//+------------------------------------------------------------------+