P6 Released





//Phoenix 6 License information:
//Not Commercial use defined by QPL Open Source License.
//Contact PhoenixFund for Commercial License. Derivative works must also be QPL.
//Unless alternatively licensed by copyright holder, no commercial derivative works may exist.
//+------------------------------------------------------------------+
#property copyright "Copyright PhoenixFund under QPL License. www.bestforextools.com/pf/"

// Constants used in the Signals section

#define Buy                +1
#define Sell               -1
#define None                0

// Constant used in T2_SendTrade for ordersend.

#define Failed             -1

//************* User Variables ******************//
extern string     C_TradeManage              = "===== Trade Management Settings =====";
int        U_maxtrades                = 1;
extern int        P_ConsecSignals            = 10;
bool       U_SignalResetOnBlank        = false;
extern string     U_Trade_CURRENCY           = "USDCHF"; //Currency pair to be traded
extern string     U_Trade_Per             = "M15";  //TimeFrame, use the labels from the MT4 buttons
#define               AcceptSlip                 2
extern int        StaticTP                 = 40;  //Take Profit
extern int        StaticSL                 = 40;  //Stop Loss

extern string     C_Function_Y               = "====== Lotsize Money Management =====";
extern double     U_Lots                     = 1;        //Money management will override setting
double     U_MinLot                   = 0.01;	 //Set to be micro safe by default
extern double     U_MaxLot                   = 90.0;	 //Set to previous max value by default
bool       U_ConfirmSignal1On         = false;  //Will double lotsize if S&R lines near.
extern bool       U_MoneyManage              = true; //Money management for lot sizing
extern double     U_MaxRisk                  = 0.1;     //Percentage of FreeMargin for trade
int        U_DecreaseFactor           = 0;    //6 digit number, 2 digits per subsequent loss 805010= 80% 50% 10%

extern string     C_Function_X1               = "====== Exit Management =====";
extern bool       E_ExitStaticTSOn           = true; //Enable static trailing stops
extern bool       E_ExitParaTSOn             = false; //Enable Parabolic SAR exit - in progress still
extern int        StaticTS                   = 5; //If staticTS is enabled, use this pip value for TS
int         E_MoveTPonTS                =1; //increase Trailing stop by this value in pips each time TS is adjusted. Allows good trades to rise higher
bool        TSConstrictOn               = false; //code currently broken
extern int        E_DelayTS                  = 35; //pips to wait before activating trailing stop
extern int        E_BE_SL                    = 16;  //Pips in profit to enable a Break Even SL
extern int        E_BE_Profit                = 8; //If 0, this sets trade to BE. If a number, this sets the number of pips in profit to lock in
int        E_RecrossMax           =0;      //Not multitrade safe :/ 0 disables setting. Multitrade safe needs an array of ticket numbers?
int recrosscount, bcRecross;
int minStop;                                          //Pulled from broker in init(), minimal TS value

 string     C_Function_X               = "====== Exit Grace Functionality ======";
 int        E_GraceHours         = 0;       //Setting of 0 disables, 24 = 24 hours Daraknor 5.6.6
 int        E_ForceHours         = 0;       //Setting of 0 disables, 48 = 48 hours Darankor 5.6.6
 int        E_GraceTS        = 5;	//Trailing stop in pips to use during Grace Exit: should be small

extern string     C_SignalA                  = "====== Signals Enabled =================";
int        P_signalsRequired          = 3;     //Now calculated on init
extern bool       P_EntrySignal1On           = true; //These settings turn on/off different signals. 
extern bool       P_EntrySignal2On           = true; //  Editing these settings is not necessary or recommended
extern bool       P_EntrySignal3On           = true; //  when Phoenix is being optimized. New strategies require 
extern bool       P_EntrySignal4On           = true; //  changes to the signals that are executed.
extern bool       P_EntrySignal5On           = false;
extern bool       P_EntrySignal6On           = false;

extern bool       P_EntryFilter1On           = true;  //Enabling these settings reduces the number of trades
extern bool       P_EntryFilter2On           = true;
extern bool       P_EntryFilter3On           = true;
extern bool       P_EntryFilter4On           = true;
//extern bool       P_EntryFilter5On           = false;

extern string     C_Signal1                  = "====== Signal 1 Envelope =================";
extern double     P_EnvPerc                  = 0.008;   //Percent 
extern int        P_EnvPer                   = 6;       //Period

extern string     C_Signal2                  = "====== Signal 2 SMA Difference ===========";
extern int        P_SMAPer                   = 5;
extern int        P_SMA2Bars                 = 6;

extern string     C_Signal3                  = "====== Signal 3 OSMA Cross ===============";
extern int        P_OSMAFast                 = 4;
extern int        P_OSMASlow                 = 16;
extern double     P_OSMASignal               = 8;

extern string     C_Signal4                  = "====== Signal 4: Price Divergence ========";
extern int        P_Fast_Per              = 4; 
int        P_Fast_Price               = PRICE_OPEN;
extern int        P_Slow_Per              = 16;
int        P_Slow_Price               = PRICE_OPEN;
extern double     P_DVBuySell                = 1; //only needs 1 decimal at most
extern double     P_DVStayOut                = 8; //only needs 1 decimal at most
double W_DVBuySell;
double W_DVStayOut;

extern string     C_Signal5_6                  = "===== Signal 5 RSI Direction & 6 RSI =====";
extern int        P_RSI_High                 = 80;
extern int        P_RSI_Low                  = 20;
extern int        P_RSI_Per                  = 2;
double W_RSI1, W_RSI2, W_RSI3;   //3 globals saves 6 indicator calls.
int    W_RSIBar, W_ES4_SRBar;
double W_ES4_SR[4]; 

extern string     C_Filter1                  = "====== Filter 1: BBands Channel Detect =====";
extern int        F_ATRShort                    = 5;    //Short term period for consolidation
//int        F_ATRLong                     = 35;   //Long term reference data vs consolidation
                                                 //changed so Long = 7*short
extern double     F_ATR                         = 0.6; //Minimum value to allow trades
                                                 //Code contributed by Wackena
extern string     C_Filter2                  = "====== Filter 2: Allowed Time ==========";
extern double        F_AllAt1                   = 1;    //Defaults will trader 24 hours Mon-Thu
extern double        F_AllTo1                   = 21;   //TODO Support double and min instead of hour int.
extern double        F_AllAt2                   = 24;
extern double        F_AllTo2                   = 24;
extern double        F_SunAt                    = 0;    //Sunday trading is disabled
extern double        F_SunTo                    = 0;
extern double        F_FriAt                    = 0;    //Friday trading ends early
extern double        F_FriTo                    = 16;
extern double        F_MonAt                    = 4;    //Monday without Japanese Open
extern double        F_MonTo                    = 24;
int currentHour; //One global variable saves thousands of CPU cycles.

extern string     C_Filter3_4                = "====== Filter 3&4 Trend ===============";
extern int        U_TrendPer              = 30;
extern int        U_TrendShift               = 5;
extern double     P_TrendStr            = 30;  //Difference in pips between price and MA.

extern string     C_SystemChange             = "====== System Changes =================";
extern bool       U_WriteLog                 = false;
extern bool       U_WriteDebug               = false;
extern string     U_EAComment                = "";
//******************* Global Variables ***************//

#define    MagicNumSet1     101010
int    maxMagic         =  0; //Set size of magic numbers used

bool   Chain2EntryOn    =  false;
bool   W_GreenLight     =  true;
string W_Trade_Per;
int    nDaysSince1970   =  0;
int    LogHandle        = -1;

int    BuySignalCount;
int    SellSignalCount;

 

//----------------------  INIT  --------------------

void init()
  { //Startup Functions, only called once.
    if((Symbol() != U_Trade_CURRENCY) && (Symbol() != U_Trade_CURRENCY+"m"))
      {
        Alert("These settings are designed for "+U_Trade_CURRENCY+
              " only! Change chart or update U_Trade_CURRENCY"    );

        W_GreenLight=false;
      }

    if(U_MaxLot >MarketInfo(Symbol(),MODE_MAXLOT)) U_MaxLot=MarketInfo(Symbol(),MODE_MAXLOT);
    if(U_MinLot >MarketInfo(Symbol(),MODE_MINLOT)) U_MaxLot=MarketInfo(Symbol(),MODE_MINLOT);

    switch(Period())
      {
        case 1:
          W_Trade_Per="M1";     break;
        case 5:
          W_Trade_Per="M5";     break;
        case 15:
          W_Trade_Per="M15";    break;
        case 30:
          W_Trade_Per="M30";    break;
        case 60:
          W_Trade_Per="H1";     break;
        case 240:
          W_Trade_Per="H4";     break;
        case 1440:
          W_Trade_Per="D1";     break;
        case 10080:
          W_Trade_Per="W1";     break;
        case 43200:
          W_Trade_Per="MN";    break;
        default:
          Alert("Your timeframe "+Period()+" was not detected.");
          W_Trade_Per="";
       }

    if(U_Trade_Per != W_Trade_Per)
      {
        Alert("These settings are designed for "+U_Trade_Per+
          " only! Change chart or update U_Trade_Per");
        W_GreenLight=false;
      }   
    //Initial Settings:

//    W_DVBuySell = P_DVBuySell*Point;
//    W_DVStayOut = P_DVStayOut*Point;
    W_DVBuySell = P_DVBuySell;
    W_DVStayOut = P_DVStayOut;
    //TODO starting balance for complex money management.
    P_signalsRequired=P_EntrySignal1On+P_EntrySignal2On+P_EntrySignal3On+P_EntrySignal4On+P_EntrySignal5On+P_EntrySignal6On;

    minStop=MarketInfo(Symbol(),MODE_STOPLEVEL);
    if(E_BE_SL<E_BE_Profit+minStop) 
      E_BE_Profit=E_BE_SL-minStop;
      
    if(F_AllAt1>F_AllTo1) { Alert("F_AllAt1>F_AllTo1"); W_GreenLight = false; }
    if(F_AllAt2>F_AllTo2) { Alert("F_AllAt2>F_AllTo2"); W_GreenLight = false; }
    if(F_AllTo1>F_AllAt2) { Alert("F_AllTo1>=F_AllAt2"); W_GreenLight = false; }
    if(F_SunAt>F_SunTo) { Alert("F_SunAt>F_SunTo"); W_GreenLight = false; }
    if(F_FriAt>F_FriTo) { Alert("F_FriAt>F_FriTo"); W_GreenLight = false; }
    if(F_MonAt>F_MonTo) { Alert("F_MonAt>F_MonTo"); W_GreenLight = false; }
    //F_ATRLong=7*F_ATRShort; //Filter 1, autoconfigure
}
  

//----------------------  START  --------------------

void start()
  {
    if(W_GreenLight == false)
      return(0);
    L1_OpenLogFile("MyLog.txt");
    int ordercount;

    //*************** Detect open trades *********************//
    for (int cticket = 0; cticket < OrdersTotal(); cticket++) 
      {
       if (OrderSelect(cticket, SELECT_BY_POS) == false)
         continue;

       if (OrderSymbol() != Symbol())
         continue;

       if (OrderMagicNumber() >= MagicNumSet1 && OrderMagicNumber() <= MagicNumSet1 + maxMagic)
         {
           X1_ManageExit(OrderTicket());
           ordercount++;

      //  PContour - removed the following lines in favour of condensed order management.
      //     if      (OrderType() == OP_BUY)   X1_ManageExit(OrderTicket()); //Buy
      //     else if (OrderType() == OP_SELL)  X1_ManageExit(OrderTicket()); //Sell
         }
      }
    if ( ordercount < U_maxtrades) A1_OpenTrade_If_Signal();
    L9_FlushLog();
  } //End Start() 

//********************* Check for New Trade *******************//

void A1_OpenTrade_If_Signal()
  { //Check singals and conditions to enter new trade
    int  signalCount;
    bool enableBuy= true;
    bool enableSell=true;

//EntryFilters enable or disable trading, while EntrySignals generate "buy" or "sell"
//EntryFilter should return "false" if trading is still enabled.    
    if (P_EntryFilter1On) //Changed filters to quit ASAP.
      if (Z_F1_BlockTradingFilter1()) return;

    if (P_EntryFilter2On)
      if (Z_F2_BlockTradingFilter2()) return;

    if (P_EntryFilter3On)
      if (Z_F3_BlockTradingFilter3()) { enableBuy=false; BuySignalCount=0; }

    if (P_EntryFilter4On)
      if (Z_F4_BlockTradingFilter4()) { enableSell=false; SellSignalCount=0; }

//    if (P_EntryFilter5On)
//      if (Z_F5_BlockTradingFilter5()) return;

    //Check all the EntrySignals for Buy=1 or Sell=-1 values. See constants at top of file.

    if (P_EntrySignal1On)
      {
        signalCount += Z_S1_EntrySignal1();    
        if(U_WriteDebug) L3_WriteDebug("Signal1 sum: "+signalCount);
      }
    if (P_EntrySignal2On)
      {
        signalCount += Z_S2_EntrySignal2();    
        if(U_WriteDebug) L3_WriteDebug("Signal2 sum: "+signalCount);
      }
    if (P_EntrySignal3On)
      {
        signalCount += Z_S3_EntrySignal3();    
        if(U_WriteDebug) L3_WriteDebug("Signal3 sum: "+signalCount);
      }
    if (P_EntrySignal4On)
      {
        signalCount += Z_S4_EntrySignal4();    
        if(U_WriteDebug) L3_WriteDebug("Signal4 sum: "+signalCount);
      }
    if (P_EntrySignal5On)
      {
        signalCount += Z_S5_EntrySignal5();    
        if(U_WriteDebug) L3_WriteDebug("Signal5 sum: "+signalCount);
      }
    if (P_EntrySignal6On)
      {
        signalCount += Z_S6_EntrySignal6();    
        if(U_WriteDebug) L3_WriteDebug("Signal5 sum: "+signalCount);
      }
    // Counting up the number of buy or sell signals that happen consecutively.  
    if(enableBuy)
      if(signalCount >= P_signalsRequired) 
        { //Check for Buy
          BuySignalCount++;
          SellSignalCount=0;
        }   
    if(enableSell)
      if(signalCount <= (-1)*P_signalsRequired)
        {
          BuySignalCount=0;
          SellSignalCount++;
        }
    if(U_SignalResetOnBlank)
       if(  (signalCount <= (-1)*P_signalsRequired) && (signalCount >= P_signalsRequired))
         {//If neither buy nor sell signal is received
           BuySignalCount =0;
           SellSignalCount=0;
         }
    if(U_WriteLog) L2_WriteLog("signal#:"+signalCount+" P_ConsecSignals:" +P_ConsecSignals+" BuySignalCount:" +BuySignalCount+" SellSignalCount:"+ SellSignalCount);
     // If the BuySignalCount or SellSignalCount exceeds the P_ConsecSignals required
     // then the Buy order or Sell order will be submitted.
    if(P_ConsecSignals <= BuySignalCount)
      {
        A1_1_OrderNewBuy(M1_MM_OptimizeLotSize()*A1_3_EntryConfirmation(OP_BUY));
        BuySignalCount   =0;
        recrosscount=0; //reset recross count for new trade.
      }
    else if(P_ConsecSignals <= SellSignalCount)
      {
        A1_2_OrderNewSell(M1_MM_OptimizeLotSize()*A1_3_EntryConfirmation(OP_SELL));
        SellSignalCount  =0;
        recrosscount=0; //reset recross count for new trade.
      }
  }

  
void A1_1_OrderNewBuy(double lots)  //Trade TP+SL Signals
  { 
    T2_SendTrade(StaticTP, StaticSL, lots, OP_BUY);
  }

void A1_2_OrderNewSell(double lots)   //Trade TP+SL Signals
  { 
    T2_SendTrade(StaticTP, StaticSL, lots, OP_SELL);
  }





double A1_3_EntryConfirmation(int direction)
{ //Gann Style Support and Resist Lines.
   if(!U_ConfirmSignal1On) return (1.0);
   double value=1;
   if(W_ES4_SRBar>iBars(Symbol(),PERIOD_H4))
   {
      W_ES4_SRBar=iBars(Symbol(),PERIOD_H4);
      W_ES4_SR[4]=iHigh(Symbol(),PERIOD_H4,1);
      W_ES4_SR[0]=iLow(Symbol(),PERIOD_H4,1);
      if(W_ES4_SR[4]-W_ES4_SR[0]<(StaticTP+StaticSL)*Point)
      {
         W_ES4_SR[4]=iHigh(Symbol(),PERIOD_D1,1);
         W_ES4_SR[0]=iLow(Symbol(),PERIOD_D1,1);
      }
      W_ES4_SR[3]=(W_ES4_SR[0]+W_ES4_SR[4])*0.75;
      W_ES4_SR[2]=(W_ES4_SR[0]+W_ES4_SR[4])*0.5;
      W_ES4_SR[1]=(W_ES4_SR[0]+W_ES4_SR[4])*0.25;
   }
   int next=ArrayBsearch(W_ES4_SR,Bid);
   if(direction==OP_SELL) 
   {
      if(Bid+StaticSL*Point>W_ES4_SR[next]) value=2;
   }
   if(direction==OP_BUY) 
   {
      if(next !=0)//safe array
      { 
         if(Bid-StaticSL*Point<W_ES4_SR[next-1]) value=2; 
      }
      else value=1;
   }
   return (value);  
}

/*double EntryConfirmation2()
{ //TODO Speed Angle Check
return(1.0);
}
*/

/*double EntryConfirmation3()
{ //TODO 4-7 Rule
return(1.0);
}
*/

//********************* Money Management *****************//

double M1_MM_OptimizeLotSize()
  {
    if(!U_MoneyManage)
      return(U_Lots);

    double lots         =U_Lots;
    int    orders       =HistoryTotal();
    int    i            =orders-1;
    int    trades       =0;
    int    wins         =0;
    int    losses       =0;
    double lotStep=MarketInfo(Symbol(),MODE_LOTSTEP);

    //if(U_WriteLog) L2_WriteLog("ALERT lotstep from broker is "+lotStep);

    //if(lotStep==0) lotStep =.0001; //TODO Safety feature... need to debug this better.

    lots=AccountFreeMargin()*U_MaxRisk/1000.0;
    
    if(U_DecreaseFactor > 256)    //need to check for a real value
      { 
        while (trades< 3 && i > 0)
          {
            if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false)
              {
                if(U_WriteLog) L2_WriteLog("Error in history!");
                break;
              }
            if(OrderSymbol()==Symbol() && OrderType()<=OP_SELL)
              {
                trades++;
                if(OrderProfit()<0) losses++;
                if(OrderProfit()>0) wins++;
              }
            i--;
          }
       if (U_DecreaseFactor > 999999)
         {
           if(U_WriteLog) L2_WriteLog("U_DecreaseFactor too large.  Changed to 902005");
           U_DecreaseFactor = 902005;
         }

       int Loss1_Percentage =  U_DecreaseFactor * 0.0001;
       int Loss2_Percentage = (U_DecreaseFactor - 10000 * Loss1_Percentage) * 0.01;
       int Loss3_Percentage = (U_DecreaseFactor - 10000 * Loss1_Percentage
                                                -   100 * Loss2_Percentage);
                                                
       if(U_WriteLog) L2_WriteLog("Decrease Factors "+Loss1_Percentage+" "+Loss2_Percentage+" "+Loss3_Percentage) ;

//     if (losses==0){ lots=lots*100             *0.01;   }  //This line is just documentation
       if (losses==1){ lots=lots*Loss1_Percentage*0.01;   }
       if (losses==2){ lots=lots*Loss2_Percentage*0.01;   }
       if (losses>=3){ lots=lots*Loss3_Percentage*0.01;   }
       if(U_WriteLog) L2_WriteLog("  losses "+losses+"  lots "+lots);
      }

    if(lots<U_MinLot) { lots=U_MinLot; if(U_WriteLog) L2_WriteLog("lots switched to min "+lots); }
    if(lots>U_MaxLot) { lots=U_MaxLot; if(U_WriteLog) L2_WriteLog("lots switched to max "+lots); }

    lots /=lotStep;
    lots  = NormalizeDouble(lots,0);
    lots *= lotStep;

    return(lots);
  }

int T2_SendTrade(int TP, int SL, double lot, int order, int incMagic = 0)  //Execute Trades
  { 

    double price;
    color  arrow;
    int    ticket;

    string tradecomment= U_EAComment + " P6B T"+ incMagic;

    if (order %2==OP_BUY)
      { //if number is even
        price =  Ask;
        arrow =  Blue;
      }

    if (order %2==OP_SELL)
      { //if number is odd
        price =  Bid;
        SL    = -SL;
        TP    = -TP;
        arrow =  Red;
      }
  //ticket = OrderSend(Symbol(),OP_BUY,1,Ask,3,Ask-25*Point,Ask+25*Point,"My order #2",16384,0,Green);
    ticket = OrderSend( Symbol(),
                        order,
                        lot,
                        price,
                        AcceptSlip,
                        price-SL*Point,
                        price+TP*Point,
                        tradecomment,
                        MagicNumSet1 + incMagic,
                        0, 
                        arrow );

    if (ticket != Failed)
      {
        if(U_WriteLog) L2_WriteLog("Success:"+ticket+" "+Symbol()+" order:"+order+" lot:"+lot+" price:"+price+" SL:"+(price-SL*Point)+" TP:"+(price+TP*Point));
        return (ticket); //TODO use ticket number somehow
      } 
    else
      {
        int error=GetLastError();
        if(U_WriteLog) L2_WriteLog("Error:"+error+" "+Symbol()+" order:"+order+" lot:"+lot+" price:"+price+" SL:"+(price-SL*Point)+" TP:"+(price+TP*Point));

    if(error==129 || error==130 || error==135 || error==138)
          { //Handle a few errors we know about, usually price movement. TODO make this configurable.
            RefreshRates();

            ticket = OrderSend( Symbol(), 
                                order, 
                                lot, 
                                price, 
                                AcceptSlip,
                                price - SL * Point,
                                price + TP * Point, 
                                tradecomment,
                                MagicNumSet1 + incMagic,
                                0, 
                                arrow );

            if (ticket != Failed) 
              return (ticket); //TODO use ticket number somehow
            else 
              if(U_WriteLog) L2_WriteLog("Error: Order send failed twice. Quitting."+ GetLastError());
          }
    if(error==4 || error==136 || error==137 ||error==146)
          { //Busy Errors, sleep a little then retry
            Sleep(2000);
            RefreshRates();
            ticket = OrderSend( Symbol(), 
                                order, 
                                lot, 
                                price, 
                                AcceptSlip,
                                price - SL * Point,
                                price + TP * Point, 
                                tradecomment,
                                MagicNumSet1 + incMagic,
                                0, 
                                arrow );

            if (ticket != Failed) 
              return (ticket); //TODO use ticket number somehow
            else 
              if(U_WriteLog) L2_WriteLog("Error: Order send failed twice. Quitting."+ GetLastError());
          }
      }
  }
  
//**********  Exit Strategies & Trailing Stops **********************************//
void X1_ManageExit(int myticket)
{ //Contains all of the exit strategies and trade management routines. Listed in priority.
    minStop=MarketInfo(Symbol(),MODE_STOPLEVEL); //updated every tick in case of news SL movement
  
    if(E_GraceHours !=0 ||E_ForceHours !=0) 
      X1_ForceClose_or_GraceModify(myticket);
  
    if(E_RecrossMax!=0)
      {
        double price;
          if (OrderType() == OP_BUY)   price=Bid;
          if (OrderType() == OP_SELL)  price=Ask;
          if(Bars>bcRecross)
            { //Bar hasn't been counted yet
              if(OrderOpenPrice()>price-1 && OrderOpenPrice()<price+1)
                {
                  recrosscount++;
                  bcRecross=Bars;

                  if (recrosscount>=E_RecrossMax)
                     if(!OrderClose(myticket,OrderLots(),price,AcceptSlip,Red)) 
                       L4_WriteError();
                }
              }
    
      }
  //TODO StealthExit  
  if(E_BE_SL!=0)
  {  //    BreakEven SL @target
    if(E_BE_SL<E_BE_Profit+minStop) E_BE_Profit=E_BE_SL-minStop; //keeps trade safe all of the time
    if(Bid-OrderOpenPrice()>Point*E_BE_Profit && (OrderStopLoss()< OrderOpenPrice()+E_BE_Profit*Point))
    {
      if (OrderType() == OP_BUY)
        X9_ModifySL(OrderOpenPrice()+E_BE_Profit*Point,myticket); 
      if (OrderType() == OP_SELL)
        X9_ModifySL(OrderOpenPrice()-E_BE_Profit*Point,myticket); 
    } 
  }
  if (E_ExitParaTSOn) 
  {
    double paraSAR=iSAR(NULL,0,0.02,0.2,1);
  //      if(U_WriteDebug) L3_WriteDebug("ParaTS: "+paraSAR+" TP"+OrderTakeProfit()+" SL"+OrderStopLoss()+" Bid"+Bid);
    if(OrderType() == OP_BUY)
      if(paraSAR<Bid && OrderProfit()>0) 
        OrderClose(OrderTicket(),OrderLots(),Bid,AcceptSlip,Red);
        //X9_ModifyTrailingStop(myticket,minStop,0);
    if(OrderType() == OP_SELL)
      if(paraSAR>Ask && OrderProfit()>0) 
        OrderClose(OrderTicket(),OrderLots(),Ask,AcceptSlip,Red);
  } 
  else if (E_ExitStaticTSOn) 
  {
    X9_ModifyTrailingStop(myticket,StaticTS,E_DelayTS);
  }
}


void X1_ForceClose_or_GraceModify(int ticket)   //contrib by HerbertH in original Phoenix 2007 thread.
  {  
    int    PerForce = E_ForceHours*3600;
    int    PerGrace = E_GraceHours*3600;
    double newSL       =0;

    OrderSelect(ticket, SELECT_BY_POS, MODE_TRADES); //TODO verify this line is redundant and unnecessary

    if (PerForce!=0)
      {
      if((OrderOpenTime() + PerForce) < Time[0])
         {
         if(OrderType() == OP_BUY)  OrderClose(OrderTicket(),OrderLots(),Bid,3,Red); //3 points slippage allowed?
         if(OrderType() == OP_SELL) OrderClose(OrderTicket(),OrderLots(),Ask,3,Red);
         }
      }

    if(PerGrace!=0)
      {
        if(OrderOpenTime() + PerGrace < Time[0])
          {
            X9_ModifyTrailingStop(ticket, E_GraceTS,-1000);  // -1000=No profit delay on TS with PerGrace
          }
      }
   }

void X9_ModifyTrailingStop(int ticket, int tsvalue, int delayts)
  {
    double slvalue;
    if(tsvalue>=minStop) //check minimal value allowed by broker
      {        //TODO decrease tsvalue to make constricting difference between TP and SL.
        if(TSConstrictOn)
        { //Code currently broken
          if(OrderProfit()>0)
            tsvalue=((OrderTakeProfit()-OrderStopLoss())/Point)*0.5;
          if(tsvalue<minStop)
            tsvalue=minStop;
        }
      } 
    else 
      { //Set safe value
        tsvalue=minStop;
      }
    if(U_WriteDebug) L3_WriteDebug("EXIT:TS ticket:"+ticket+" tsvalue:"+tsvalue+" delayts:"+delayts);

    if      (OrderType() == OP_BUY)
      {
        slvalue=Bid-(Point*tsvalue);
        if (OrderStopLoss() < slvalue && OrderOpenPrice()+Point*delayts<Bid+tsvalue*Point)
        {
          //if(U_WriteDebug) L3_WriteDebug("OrderSL:" +OrderStopLoss()+ " slvalue:"+ slvalue);
          if(!X9_ModifySL(slvalue,ticket))
          {
            L4_WriteError();
            L3_WriteDebug("ERROR OrderSL:" +OrderStopLoss()+ " slvalue:"+ slvalue);
          }
        }
      } 
    else if (OrderType() == OP_SELL)
      {
        slvalue=Ask+(Point*tsvalue);
        if (OrderStopLoss() > slvalue && OrderOpenPrice()-Point*delayts>Ask-tsvalue*Point)
        {
          //if(U_WriteDebug) L3_WriteDebug("OrderSL:" +OrderStopLoss()+ " slvalue:"+ slvalue);
          if(!X9_ModifySL(slvalue,ticket))
          {
            L4_WriteError();
            L3_WriteDebug("ERROR OrderSL:" +OrderStopLoss()+ " slvalue:"+ slvalue);
          }
        }
      }
  }

bool X9_ModifySL(double sl, int ticket)
  {
    double MoveTP;
    if(E_MoveTPonTS !=0)
    {
      if (OrderType() == OP_SELL) 
      {
        MoveTP=E_MoveTPonTS*(-1)*Point;
        if(Ask-OrderTakeProfit()+MoveTP<minStop*Point) 
          MoveTP=minStop*Point*(-1) -OrderTakeProfit(); //Set the new distance to minimum safe point, -OTP() cancels OTP()
      }
      else 
      {
        MoveTP=E_MoveTPonTS*Point;
        if(OrderTakeProfit()-Bid+MoveTP<minStop*Point) 
          MoveTP=minStop*Point -OrderTakeProfit();  //Set the new distance to minimum safe point, -OTP() cancels OTP()
      }
    }
    
    if(U_WriteDebug) L3_WriteDebug("MODIFY Ticket:"+ticket+" OpenPrice:"+OrderOpenPrice()+" SL:"+sl+" TP:"+(OrderTakeProfit()+MoveTP*Point));
    if(OrderModify ( ticket, OrderOpenPrice(), sl,
                      OrderTakeProfit()+MoveTP,
                      0, Red) ==(-1)) 
        return(false);
    else return(true);
  }


//********************** SIGNALS *********************//
int Z_S1_EntrySignal1()
  { //Envelope Filter
    int Signal=None;

    double HighEnvelope1 = iEnvelopes(NULL,0,P_EnvPer,MODE_SMA,0,PRICE_CLOSE,P_EnvPerc,MODE_UPPER,1);
    double LowEnvelope1  = iEnvelopes(NULL,0,P_EnvPer,MODE_SMA,0,PRICE_CLOSE,P_EnvPerc,MODE_LOWER,1);
    double CloseBar1     = iClose(NULL,0,1);

    if(CloseBar1 > HighEnvelope1) {Signal=Sell;}
    if(CloseBar1 < LowEnvelope1)  {Signal=Buy; }

    if(U_WriteDebug) L3_WriteDebug("Signal 1 "+Signal+" HighEnv:"+HighEnvelope1+" LowEnv:"+LowEnvelope1+" Close:"+CloseBar1);

    return (Signal);
  }

int Z_S2_EntrySignal2()
  { //SMA Difference
    int Signal=None;

    double SMA1=iMA(NULL,0,P_SMAPer,0,MODE_SMA,PRICE_CLOSE,1);
    double SMA2=iMA(NULL,0,P_SMAPer,0,MODE_SMA,PRICE_CLOSE,P_SMA2Bars);

    if (SMA2>SMA1 ) Signal=Buy;
    else            Signal=Sell;

    if(U_WriteDebug) L3_WriteDebug("Signal2 "+Signal+" SMA Diff:"+(SMA2-SMA1)+" SMA2:"+SMA2+" SMA1:"+SMA1);

    return (Signal);
  }


int Z_S3_EntrySignal3()
  { //OSMA Cross
    int Signal=None;

    double OsMABar2=iOsMA(NULL,0,P_OSMAFast,P_OSMASlow,P_OSMASignal,PRICE_CLOSE,2);
    double OsMABar1=iOsMA(NULL,0,P_OSMAFast,P_OSMASlow,P_OSMASignal,PRICE_CLOSE,1);

    if (OsMABar2>OsMABar1) Signal=Buy;
    else                   Signal=Sell;

    if(U_WriteDebug) L3_WriteDebug("Signal3 "+Signal+" OsMA Diff:"+(OsMABar2-OsMABar1)+" OsMABar2:"+OsMABar2+" OsMABar1:"+OsMABar1);

    return (Signal);
  }

int Z_S4_EntrySignal4()
  { //Divergence Trading Signal
    int Signal;  
    double diverge = ZZ_F1_Divergence(P_Fast_Per, P_Slow_Per, P_Fast_Price, P_Slow_Price,0);
    if(diverge >= W_DVBuySell && diverge <= W_DVStayOut) Signal=Buy;
    else if(diverge <= (W_DVBuySell*(-1)) && diverge >= (W_DVStayOut*(-1))) Signal=Sell;
    if(U_WriteDebug) L3_WriteDebug("Signal4 "+Signal+" diverge:"+diverge+" W_DVBuySell:"+W_DVBuySell+" W_DVStayOut:"+W_DVStayOut);
    return (Signal);  
  }

int Z_S5_EntrySignal5()
  { 
   int value=0;
   if(W_RSIBar<Bars)
   {  //This should be based on bars, reduces check to once every bar.
      W_RSIBar=Bars;
      W_RSI3=W_RSI2; //This reduces computation to 1/3
      W_RSI2=W_RSI1;
      W_RSI1 = iRSI(NULL, Period(), P_RSI_Per, PRICE_CLOSE, 1);
   }
   if (W_RSI1 < P_RSI_High)      //Save CPU cycles with quick filters
    { if(W_RSI2 < W_RSI1 && W_RSI3 < W_RSI2) value=Buy; } 
   else if (W_RSI1 > P_RSI_Low)  //only one set needs to be checked, and not always.  
      if(W_RSI2 > W_RSI1 && W_RSI3 > W_RSI2) value=Sell;
   if(U_WriteDebug) L3_WriteDebug("SignalRSI: "+value+" W_RSI1:"+W_RSI1+" W_RSI2:"+W_RSI2+" W_RSI3:"+W_RSI3);
   return(value);
  }
  
int Z_S6_EntrySignal6()
  { 
   int value=0;
   double w_RSI = iRSI(NULL, Period(), P_RSI_Per, PRICE_CLOSE, 1);
   if (w_RSI < P_RSI_High)      //Save CPU cycles with quick filters
      value=Buy;
   else if (w_RSI > P_RSI_Low)  //only one set needs to be checked, and not always.  
      value=Sell;
   if(U_WriteDebug) L3_WriteDebug("SignalRSI: "+value+" w_RSI:"+w_RSI);
   return(value);
  }
  
bool Z_F1_BlockTradingFilter1()
{   //Original code Contributed by Wackena
  bool BlockTrade=false;  //trade by default
  double w_ATR;
  double dAtrShort = iATR(NULL, 0, F_ATRShort, 0);
  //double dAtrLong = iATR(NULL, 0, F_ATRLong, 0);
  //if(dAtrLong != 0) w_ATR = dAtrShort / dAtrLong; 
  //if(w_ATR<F_ATR)BlockTrade=true;
  if(dAtrShort<F_ATR)BlockTrade=true;
  return (BlockTrade); 
}

bool Z_F2_BlockTradingFilter2()   
  { //Time Expiry
    bool BlockTrade=true;  //only trade during permitted hours
    
//    if(TimeHour(TimeCurrent())!=currentHour)
//    {
      currentHour=TimeHour(TimeCurrent());    //one global variable saves thousands of CPU cycles

      if(TimeDayOfWeek(Time[0])==0)  //Sunday
        {
          if(currentHour>=F_SunAt && currentHour<F_SunTo)    BlockTrade=false;
        }
      else if(TimeDayOfWeek(Time[0])==5)  //Friday
        {
          //if(U_WriteDebug) L3_WriteDebug("Today is Friday:"+currentHour);
          if(currentHour>=F_FriAt && currentHour<F_FriTo)    BlockTrade=false;
        }
      else if(TimeDayOfWeek(Time[0])==1)  //Monday
        {
          //if(U_WriteDebug) L3_WriteDebug("Today is Friday:"+currentHour);
          if(currentHour>=F_MonAt && currentHour<F_MonTo)    BlockTrade=false;
        }
      else if((currentHour>=F_AllAt1 && currentHour<F_AllTo1) ||
      (currentHour>=F_AllAt2 && currentHour<F_AllTo2)) BlockTrade=false;
//    }
    return (BlockTrade);
  }
  
bool Z_F3_BlockTradingFilter3()   //if BUY Signal, check buy trend. True = quit.
  {
    bool BlockTrade=false;
  
    double TrendB=iMA(NULL,0,U_TrendPer,U_TrendShift,MODE_LWMA,PRICE_MEDIAN,0)-High[1];

    if(P_TrendStr*Point<TrendB)
      {
        BlockTrade=true;
        if(U_WriteDebug) L3_WriteDebug("EntryFilter3 TrendMA:"+TrendB+" Buy="+BlockTrade+" Buy Allowed");
      }
    else
      { 
        if(U_WriteDebug) L3_WriteDebug("EntryFilter3 TrendMA:"+TrendB+" Buy="+BlockTrade+" Buy DisAllowed");
      }

    return(BlockTrade);
  }
  
bool Z_F4_BlockTradingFilter4()
  {
    //if SELL Signal, check sell trend
    //Currently assuming that rising and falling trends have similar properties.
    bool BlockTrade=false;
    
    double TrendS=Low[1]-iMA(NULL,0,U_TrendPer,U_TrendShift,MODE_LWMA,PRICE_MEDIAN,0);
    
    if(P_TrendStr*Point<TrendS) 
      {
        BlockTrade=true;
        if(U_WriteDebug) L3_WriteDebug("EntryFilter4 TrendMA:"+TrendS+" Sell="+BlockTrade+" Sell DisAllowed");
      }
    else
      {
        if(U_WriteDebug) L3_WriteDebug("EntryFilter4 TrendMA:"+TrendS+" Sell="+BlockTrade+" Sell Allowed");
      }

    return(BlockTrade);
  }

//bool Z_F5_BlockTradingFilter5()   //TODO S&R
//  { 
//    return (false);  //trade by default
//  }

//********************** Signal Functions ******************//

double ZZ_F1_Divergence(int F_Per, int S_Per, int F_Price, int S_Price, int mypos)
  {
    int i;
    double maF2 = iMA(Symbol(), 0, F_Per, 0, MODE_SMA, F_Price, mypos + 1);
    double maS2 = iMA(Symbol(), 0, S_Per, 0, MODE_SMA, S_Price, mypos + 1);

    return((maF2-maS2)/Point);
  }

//*********************** LOGGING **************************//
void L1_OpenLogFile(string strName)
  {
    if (!U_WriteLog && !U_WriteDebug)
      return;

    if (TimeCurrent() / (60 * 60 * 24) > nDaysSince1970 || LogHandle <= 0) 
      { //Pick a new filename and open it.
        if (LogHandle > 0) 
          FileClose(LogHandle);

        string            strMonthPad = "" ;
        if (Month() < 10) strMonthPad = "0";

        string            strDayPad   = "" ;
        if (Day()   < 10) strDayPad   = "0";

        string strFilename = StringConcatenate(strName, "_", Year(),
                                               strMonthPad, Month(),
                                               strDayPad,     Day(), "_log.txt");

        LogHandle =FileOpen(strFilename, FILE_CSV | FILE_READ | FILE_WRITE);

        nDaysSince1970 = TimeCurrent() / (60 * 60 * 24);
      }

    FileFlush(LogHandle);
    FileSeek(LogHandle, 0, SEEK_END);
  }


void L2_WriteLog(string msg)
  {
    if (!U_WriteLog) return;
    if (LogHandle <= 0)   return;

    msg = TimeToStr(TimeCurrent(), TIME_DATE | TIME_MINUTES | TIME_SECONDS) + " " + msg;
    FileWrite(LogHandle, msg);
  }

void L3_WriteDebug(string msg)  //Signal Debugging, rarely called
  {
//    if (!U_WriteDebug) return;
    if (LogHandle <= 0)       return;

    msg = TimeToStr(TimeCurrent(), TIME_DATE | TIME_MINUTES | TIME_SECONDS) + " " + msg;
    FileWrite(LogHandle, msg);
  }

void L4_WriteError()
  {
    if (!U_WriteLog) return;
    if (LogHandle <= 0)   return;

    string msg="Error:"+ GetLastError()+" OrderType:"+OrderType()+" Ticket:"+OrderTicket();

    msg = TimeToStr(TimeCurrent(), TIME_DATE | TIME_MINUTES | TIME_SECONDS) + " " + msg;
    FileWrite(LogHandle, msg);
  }

void L9_FlushLog()
  {
    if (!U_WriteLog) return;

    FileFlush(LogHandle);
  }

//End Of File



Sample





Analysis



Market Information Used:

Series array that contains the highest prices of each bar
Series array that contains the lowest prices of each bar
Series array that contains open time of each bar
Series array that contains close prices for each bar


Indicator Curves created:


Indicators Used:

Parabolic Stop and Reverse system
Envelopes indicator
Moving average indicator
Moving Average of Oscillator
Relative strength index
Indicator of the average true range


Custom Indicators Used:

Order Management characteristics:
Checks for the total of open orders

It Closes Orders by itself

Other Features:

It issuies visual alerts to the screen
Uses files from the file system
It writes information to file