//+------------------------------------------------------------------+
//|                                        Claudia's Wine Bar EA.mq4 |
//+------------------------------------------------------------------+
// This is an EA; install it in the ..../(MT4)/experts folder

#property copyright "Copyright (c) 2013, David Louisson"
#property link      "http://www.forexfactory.com/hanover"

/*+------------------------------------------------------------------+
Disclaimer and License Agreement
//+------------------------------------------------------------------+

1. The 'VENDOR' (David Louisson, of New Zealand) grants non-exclusive, non-transferable, non-revocable
License to the 'PURCHASER' to use the software and materials for the permitted purpose, for an indefinite period
of time. The Purchaser further agrees that the software and materials are for his/her own personal use only.

2. The Purchaser may not assign nor sublicense the License, nor adapt nor modify the code. The Purchaser may
not reverse engineer, disassemble, or otherwise endeavor to obtain the source code from the object code.

3. The Purchaser is limited to the number of installations as controlled by the software. If the Purchaser wishes
to use the software over this limit, the Vendor reserves the right to charge an additional License/registration fee.

4. The Purchaser must not alter, remove or obscure any trade mark or copyright symbol or legend or other
proprietary mark on the software and the materials.

5. The Purchaser is not permitted to sell, charge, mortgage or otherwise encumber the software and materials in any way.

6. The Purchaser acknowledges that the Vendor gives no guarantee as to the accuracy or completeness of the software
and the materials, or that they are free from error.

7. To the fullest extent permitted by law, the Vendor expressly disclaims all implied warranties and conditions as to
merchantability, fitness or purpose of the software and materials.

8. The Purchaser indemnifies and holds harmless the Vendor and promises to keep the Vendor indemnified against any loss,
claim, action, settlement, award, judgment, expense or damage of whatsoever kind or nature and howsoever arising that
the Vendor might suffer as a result of any inaccuracy of the software and/or the materials including any authorized or
unauthorized use of the software and/or the materials by the Purchaser. The Purchaser further indemnifies and holds
harmless the Vendor for any trading losses, both realized and floating, incurred by the Purchaser.

9. The terms of this Agreement constitute the entire terms of this Agreement and all understandings, prior
representations, arrangements or commitments that are not contained in this Agreement have no effect whatsoever and
do not bind the parties.

//+------------------------------------------------------------------+*/

#include <hanover --- function header (np).mqh>

        string    EAname                       = "CWB1-\x5c";           // hex 5c is backslash
extern  string    RiskPerTrade                 = "1%E";                 // Risk per trade can be fixed number of lots; $ amount; % of (E)quity, (B)alance or (F)ree Margin
extern  string    AllowableOrders              = "BS";                  // include: B = allow buy orders; S = allow sell orders; BS = allow both types
extern  string    DaysToPlaceOrders            = "MonTueWedThuFri";
extern  string    TimesToPlaceOrders           = "";
extern  string    SLmethod                     = "20";                  // nB or nC = use swing hi/lo over last n candles;  0 or blank = no SL;  positive value = SL pips; P=pivot based S1/R1
extern  string    TPmethod                     = "20";                  //                                                  0 or blank = no TP;  positive value = TP pips; P=pivot based S1/R1 
extern  bool      AdjustForSpread              = true;
        string    TrendlineExits               = "";
extern  double    MaxSpreadPips                = 9999;
extern  double    MinSLTPpipsFromEntry         = 5;
extern  double    ProfitPipsForSLtoBE          = 10;                    // negative/zero value = don't move SL to BE; positive value = move SL to BE when order is N pips in profit
extern  double    BEpointPips                  = 0;                     // BE point relative to entry 
extern  string    TrailingSL                   = "0";                   // negative/zero value = don't trail SL; positive value = trail SL N pips behind price
extern  bool      TrailOnlyAfterBEreached      = true;                  // true = trail SL only after BE reached; false = trail SL from outset
extern  string    WeekendCloseProfit           = ""; // "Fri2300";
extern  string    WeekendCloseLoss             = ""; // "Fri2345";
extern  bool      TakeSnapshots                = true;
extern  int       MaxOrdersPerEA               = 1;
extern  int       MagicNumberBuy               = 1001;
extern  int       MagicNumberSell              = 1002;
                                               
        string    EntryCriteria                = "P";
        string    CloseCriteria                = "P";
                                               
extern  string    PivotCalcMethod_SFWTCP       = "S";                   // S=standard (classic); F=fibo-based; W=Woodie's; T=traditional; C=Camarilla; P=PFG
extern  int       StartHourForPivots           = 2;
extern  string    PlotPivotLinesColor          = "Gray";                // PPLC [0] = line color; [1] = days shiftback; [2] = pivot calc type (0=std,1=fibo)
extern  double    ClearancePips                = -9999;
extern  double    TolerancePips                = 0;
extern  double    MinCandleBodyPips            = 2;
extern  double    MaxCandleBodyPips            = 9999;
extern  string    AsianSessionInterval         = "0200,0900";
extern  double    AsianSessionMaxRange         = 9999;
extern  bool      CloseOppositeOrders          = false;        
extern  bool      WholeBodyMustStraddlePP      = false;
        int       MinMinutesBetwSameDirOrders  = 0;
extern  bool      ReverseSignals               = false;        
extern  bool      DisplayComments              = true;
extern  bool      PostDiagnosticInfo           = true;
                                               
extern  int       NumberOfAttempts             = 12;
extern  double    SecondsBetweenAttempts       = 0.5;
extern  color     ArrowColorBuyEntry           = Green;
extern  color     ArrowColorBuyExit            = Green;
extern  color     ArrowColorSellEntry          = Red;
extern  color     ArrowColorSellExit           = Red;

string   ccy, sym, display_string, order_comment, criteria, ordsort[100], RPT[20], TI[20], PPLC[10], ASI[2], TE[20], arr[10], last_dnote;
string   gvname, dfname, dump_string, err_string, orders_before, orders_after, out_text;  // ,open_string, close_string;
int      dig, tmf, h, i, j, k, oper1, oper2, nTI, tbar, ybar, nRPT, err_num, retval, bar, reason, frac[2], nTE;
double   spr, pnt, tickval, bidp, askp, minlot, lswap, sswap, lotstep, SL, TP, entry, vol, OverrideSLpips, OverrideTPpips, NewSL, last_bid;
double   YC, YH, YL, YO, PP, S1, S2, S3, S4, R1, R2, R3, R4, S0.5, S1.5, S2.5, S3.5, R0.5, R1.5, R2.5, R3.5, TrailingSLpips;
bool     Times_reverse, allow_buy, allow_sell, is_entry;
datetime prev_time, ptime, tcurr, etim;

string   optypes[6] = {"BUY","SELL","BUY LIMIT","SELL LIMIT","BUY STOP","SELL STOP"};


//+------------------------------------------------------------------+
int init()  {
//+------------------------------------------------------------------+
  ccy      = Symbol();
  sym      = Symbol();
  tmf      = Period();
  bidp     = MarketInfo(ccy,MODE_BID);
  askp     = MarketInfo(ccy,MODE_ASK);
  pnt      = MarketInfo(ccy,MODE_POINT);
  dig      = MarketInfo(ccy,MODE_DIGITS);
  spr      = MarketInfo(ccy,MODE_SPREAD);
  tickval  = MarketInfo(ccy,MODE_TICKVALUE);
  minlot   = MarketInfo(ccy,MODE_MINLOT);
  lotstep  = MarketInfo(ccy,MODE_LOTSTEP);
  lswap    = MarketInfo(ccy,MODE_SWAPLONG);
  sswap    = MarketInfo(ccy,MODE_SWAPSHORT);
  if (dig == 3 || dig == 5) {
    pnt     *= 10;
    spr     /= 10;
    tickval *= 10;
  }
  prev_time = 0;

  dfname = EAname + "debug_" + Symbol() + DateToStr(TimeCurrent(),"'_'Y-M-D'.txt'");     // debug filename

  Times_reverse = false;
  if (StringFind(TimesToPlaceOrders,"-") >= 0)  {
    Times_reverse = true;
    TimesToPlaceOrders = StringReplace(TimesToPlaceOrders,"-","");
  }  
  nTI = StrToStringArray(TimesToPlaceOrders,TI);

  nRPT = StrToStringArray(RiskPerTrade,RPT);
  
  StrToStringArray(PlotPivotLinesColor,PPLC);
  StrToStringArray(AsianSessionInterval,ASI);

  TrendlineExits = StringUpper(StringTrim(TrendlineExits));
  nTE = StrToStringArray(TrendlineExits,TE,";");

  // Stoploss.....
  if (StringFind(StringUpper(SLmethod),"*") >= 0)  {
    StrToStringArray(SLmethod,arr,"*");
    OverrideSLpips = StrToNumber(arr[0])*iATR(Symbol(),PERIOD_D1,StrToInteger(arr[1]),1) / pnt;             // asterisk: A*B means that SL is A x dailyATR(B)
  }                                                                                                         
  else if (StringFind(StringUpper(SLmethod),"C") >= 0)   OverrideSLpips = -StrToNumber(SLmethod);           // Cn or Bn = set SL outside swing high/low of last n candles
  else if (StringFind(StringUpper(SLmethod),"B") >= 0)   OverrideSLpips = -StrToNumber(SLmethod);           
  else if (StringFind(StringUpper(SLmethod),"P") >= 0)   OverrideSLpips = -1000;                            // P = use S1/R1 pivot level for SL 
  else                                                   OverrideSLpips = StrToNumber(SLmethod);            // else simply set SL = number of pips (0 = no SL) 

  // Take profit.....                                                                                                            
  if (StringFind(StringUpper(TPmethod),"*") >= 0)  {                                                        
    StrToStringArray(TPmethod,arr,"*");                                                                     
    OverrideTPpips = StrToNumber(arr[0])*iATR(Symbol(),PERIOD_D1,StrToInteger(arr[1]),1) / pnt;             // asterisk: A*B means that TP is A x dailyATR(B)
  }                                                                                                         
  else if (StringFind(StringUpper(TPmethod),"P") >= 0)   OverrideTPpips = -1000;                            // P = use S1/R1 pivot level for TP
  else                                                   OverrideTPpips = StrToNumber(TPmethod);            // else simply set TP = number of pips (0 = no TP) 

  // Trailing SL.....                                                                                                            
  if (StringFind(StringUpper(TrailingSL),"*") >= 0)  {                                                      
    StrToStringArray(TrailingSL,arr,"*");                                                                   
    TrailingSLpips = StrToNumber(arr[0])*iATR(Symbol(),PERIOD_D1,StrToInteger(arr[1]),1) / pnt;             // asterisk: A*B means that trailing SL is A x dailyATR(B)
  }                                                                                                         
  else                                                   TrailingSLpips = StrToNumber(TrailingSL);          // else simply set trailing SL = number of pips (0 = no trailing SL) 

  // Initial plot of pivot lines.....
  del_obj();
  plot_obj();
  
  // Initial dump of registers.....
  err_num    = GetLastError();
  err_string = EAname + "  " + Symbol() + "," + TFToStr(Period()) + DateToStr(TimeCurrent(),"' : 'w D n Y H:I:S") + " : Initialization : " + err_msg(err_num);
  out_text   = StringRepeat("=",80) + "\n" + err_string + "\n\n" + ListOrders("OPCD") + "\n\n" + ListObjects() + "\n\n" + DumpVars("init (parameters set)");
  df(out_text);

//  oper2 = CalcValues(2,EntryCriteria,true);
//  oper1 = CalcValues(1,EntryCriteria,true);
  last_dnote = "";
  last_bid   = Bid;
  return(0);
}

//+------------------------------------------------------------------+
int deinit()  {
//+------------------------------------------------------------------+
  del_obj();
  return(0);
}

//+------------------------------------------------------------------+
void del_obj()  {
//+------------------------------------------------------------------+
  int k=0;
  while (k<ObjectsTotal())   {
    string objname = ObjectName(k);
    if (StringSubstr(objname,0,StringLen(EAname)) == EAname)  
      ObjectDelete(objname);
    else
      k++;
  }    
  return(0);
}

//+------------------------------------------------------------------+
int CalcPivots() {
//+------------------------------------------------------------------+
  tcurr = Time[0]-StrToInteger(PPLC[1])*86400;                                                       // PPLC[1] = days shiftback (0=today)
//ptime = StrToTime(TimeToStr(tcurr,TIME_DATE) + NumberToStr(StartHourForPivots,"' 'Z2':00:00'"));   // ptime = time at today's pivot cutoff point
  ptime = 86400*MathInt(tcurr/86400)+StartHourForPivots*3600;
  if (ptime > tcurr)   ptime -= 86400;
  tbar = iBarShift(Symbol(),Period(),ptime,false);                                                   // tbar = bar for ptime; ybar = bar at same time yesterday
  ybar = iBarShift(Symbol(),Period(),Time[tbar]-86400*(1+2*(TimeDayOfWeek(Time[tbar])==1)),false);   // 2*(TimeDayOfWeek(ptime)==1) adjusts for intervening weekend
//  log(tbar,ybar,DateToStr(Time[tbar]),DateToStr(Time[ybar]));
  YO = Open[ybar];   YC = Close[tbar+1];   YH = High[tbar+1];   YL = Low[tbar+1];                    // yesterday's open, close; and start point for calculating high and low
  for (int z=tbar+1; z<=ybar; z++)  {                                                                // find yesterday's highest high and lowest low, for pivot calc
    YH = MathMax(YH,High[z]);
    YL = MathMin(YL,Low[z]);
  }
  switch (StringFind("SFWTCP",StringUpper(StringSubstr(PivotCalcMethod_SFWTCP,0,1))))   {
    case 1  : PP=(YH+YL+YC)/3;    S1=PP-(YH-YL)*0.382;  R1=PP+(YH-YL)*0.382;  S2=PP-(YH-YL)*0.618; R2=PP+(YH-YL)*0.618; S3=PP-(YH-YL);       R3=PP+(YH-YL);       S4=-999999;          R4=-999999;          break;  // F=fibo
    case 2  : PP=(YH+YL+YO+YO)/4; S1=2*PP-YH;           R1=2*PP-YL;           S2=PP-(YH-YL);       R2=PP+(YH-YL);       S3=YL-2*(YH-PP);     R3=YH+2*(PP-YL);     S4=PP-3*(YH-YL);     R4=PP+3*(YH-YL);     break;  // W=Woodie
    case 3  : PP=(YH+YL+YC)/3;    S1=2*PP-YH;           R1=2*PP-YL;           S2=PP+S1-R1;         R2=PP+R1-S1;         S3=PP-R2+S1;         R3=PP-S1+R2;         S4=-999999;          R4=-999999;          break;  // T=traditional
    case 4  : PP=YC;              S1=YC-(YH-YL)*1.1/12; R1=YC+(YH-YL)*1.1/12; S2=YC-(YH-YL)*1.1/6; R2=YC+(YH-YL)*1.1/6; S3=YC-(YH-YL)*1.1/4; R3=YC+(YH-YL)*1.1/4; S4=YC-(YH-YL)*1.1/2; R4=YC+(YH-YL)*1.1/4; break;  // C=Camarilla
    case 5  : PP=(YH+YL+YC)/3;    S2=PP-(YH-YL);        R2=PP+(YH-YL);        S1=(PP+S2)/2;        R1=(PP+R2)/2;        S3=-999999;          R3=-999999;          S4=-999999;          R4=-999999;          break;  // P=PFG
    default : PP=(YH+YL+YC)/3;    S1=2*PP-YH;           R1=2*PP-YL;           S2=PP-(YH-YL);       R2=PP+(YH-YL);       S3=PP-2*(YH-YL);     R3=PP+2*(YH-YL);     S4=PP-3*(YH-YL);     R4=PP+3*(YH-YL);     break;  // S=standard (classic)
  } 
  if (IsAlpha(PivotCalcMethod_SFWTCP,"1."))  { PP = StrToNumber(PivotCalcMethod_SFWTCP);  S1 = PP-20*pnt;  R1 = PP+20*pnt;  S2 = PP-40*pnt;  R2 = PP+40*pnt;  S3 = PP-60*pnt;  R3 = PP+60*pnt;  S4 = PP-80*pnt;  R4 = PP+80*pnt; }  
  S0.5=(PP+S1)/2;   S1.5=(S1+S2)/2;   S2.5=(S2+S3)/2;   S3.5=(S3+S4)/2;
  R0.5=(PP+R1)/2;   R1.5=(R1+R2)/2;   R2.5=(R2+R3)/2;   R3.5=(R3+R4)/2;
  return(0);
}

//+------------------------------------------------------------------+
int plot_obj()  {
//+------------------------------------------------------------------+
  CalcPivots();
  if (PPLC[0] > "")   {  
    color colr = StrToColor(PPLC[0]);   // pivot line color
    PlotVL (EAname+"VY", true, 0, Time[ybar], colr, 1, STYLE_DOT,   false, 0);      // Plot vertical line
    PlotVL (EAname+"VT", true, 0, Time[tbar], colr, 2, STYLE_SOLID, false, 0);      // Plot vertical line

    PlotTL (EAname+"YC", true, 0, Time[ybar], YC, Time[tbar], YC, colr, 1, STYLE_DOT, false, false, 0);        // Plot trendline
    ObjectSetText(EAname+"YC",NumberToStr(YC,"'  close='T3.5"),12);
    PlotTL (EAname+"YH", true, 0, Time[ybar], YH, Time[tbar], YH, colr, 1, STYLE_DOT, false, false, 0);        // Plot trendline
    ObjectSetText(EAname+"YH",NumberToStr(YH,"'  high='T3.5"),12);
    PlotTL (EAname+"YL", true, 0, Time[ybar], YL, Time[tbar], YL, colr, 1, STYLE_DOT, false, false, 0);        // Plot trendline
    ObjectSetText(EAname+"YL",NumberToStr(YL,"'  low='T3.5"),12);

    int ray = 1-(PPLC[1]>"0");   // PPLC[1] = days shiftback
    etim = ifint (tbar<1, Time[0]+60*Period(), MathMin(Time[0],Time[tbar]+86400));
//    log("a",etim,DateToStr(etim),Time[tbar],DateToStr(Time[tbar]));
    for (int zz=0; zz<10; zz++)  {
      if (iBarShift(Symbol(),Period(),etim) >= iBarShift(Symbol(),Period(),Time[tbar]))    etim+=86400;
    }  
//    log("b",etim,DateToStr(etim),Time[tbar],DateToStr(Time[tbar]));
    PlotTL (EAname+"PP", true, 0, Time[tbar], PP, etim, PP, colr, 2, STYLE_SOLID, ray, false, 0);              // Plot trendline
    ObjectSetText(EAname+"PP",NumberToStr(PP,"'  PP='T3.5"),12);
    PlotTL (EAname+"S1", true, 0, Time[tbar], S1, etim, S1, colr, 1, STYLE_DOT,   ray, false, 0);              // Plot trendline
    ObjectSetText(EAname+"S1",NumberToStr(S1,"'  S1='T3.5")+NumberToStr((PP-S1)/pnt,"' = 'TR5.1' pips'"),12);
    PlotTL (EAname+"S2", true, 0, Time[tbar], S2, etim, S2, colr, 1, STYLE_DOT,   ray, false, 0);              // Plot trendline
    ObjectSetText(EAname+"S2",NumberToStr(S2,"'  S2='T3.5")+NumberToStr((PP-S2)/pnt,"' = 'TR5.1' pips'"),12);
    PlotTL (EAname+"S3", true, 0, Time[tbar], S3, etim, S3, colr, 1, STYLE_DOT,   ray, false, 0);              // Plot trendline
    ObjectSetText(EAname+"S3",NumberToStr(S3,"'  S3='T3.5")+NumberToStr((PP-S3)/pnt,"' = 'TR5.1' pips'"),12);
    PlotTL (EAname+"S4", true, 0, Time[tbar], S4, etim, S4, colr, 1, STYLE_DOT,   ray, false, 0);              // Plot trendline
    ObjectSetText(EAname+"S4",NumberToStr(S4,"'  S4='T3.5")+NumberToStr((PP-S4)/pnt,"' = 'TR5.1' pips'"),12);
    PlotTL (EAname+"R1", true, 0, Time[tbar], R1, etim, R1, colr, 1, STYLE_DOT,   ray, false, 0);              // Plot trendline
    ObjectSetText(EAname+"R1",NumberToStr(R1,"'  R1='T3.5")+NumberToStr((R1-PP)/pnt,"' = 'TR5.1' pips'"),12);
    PlotTL (EAname+"R2", true, 0, Time[tbar], R2, etim, R2, colr, 1, STYLE_DOT,   ray, false, 0);              // Plot trendline
    ObjectSetText(EAname+"R2",NumberToStr(R2,"'  R2='T3.5")+NumberToStr((R2-PP)/pnt,"' = 'TR5.1' pips'"),12);
    PlotTL (EAname+"R3", true, 0, Time[tbar], R3, etim, R3, colr, 1, STYLE_DOT,   ray, false, 0);              // Plot trendline
    ObjectSetText(EAname+"R3",NumberToStr(R3,"'  R3='T3.5")+NumberToStr((R3-PP)/pnt,"' = 'TR5.1' pips'"),12);
    PlotTL (EAname+"R4", true, 0, Time[tbar], R4, etim, R4, colr, 1, STYLE_DOT,   ray, false, 0);              // Plot trendline
    ObjectSetText(EAname+"R4",NumberToStr(R4,"'  R4='T3.5")+NumberToStr((R4-PP)/pnt,"' = 'TR5.1' pips'"),12);

    if (StringFind(StringUpper(PivotCalcMethod_SFWTCP),"M")>=0)   {
      PlotTL (EAname+"S0.5", true, 0, Time[tbar], S0.5, etim, S0.5, colr, 1, STYLE_DOT,   ray, false, 0);              // Plot trendline
      ObjectSetText(EAname+"S0.5",NumberToStr(S0.5,"'  S0.5='T3.5")+NumberToStr((PP-S0.5)/pnt,"' = 'TR5.1' pips'"),12);
      PlotTL (EAname+"S1.5", true, 0, Time[tbar], S1.5, etim, S1.5, colr, 1, STYLE_DOT,   ray, false, 0);              // Plot trendline
      ObjectSetText(EAname+"S1.5",NumberToStr(S1.5,"'  S1.5='T3.5")+NumberToStr((PP-S1.5)/pnt,"' = 'TR5.1' pips'"),12);
      PlotTL (EAname+"S2.5", true, 0, Time[tbar], S2.5, etim, S2.5, colr, 1, STYLE_DOT,   ray, false, 0);              // Plot trendline
      ObjectSetText(EAname+"S2.5",NumberToStr(S2.5,"'  S2.5='T3.5")+NumberToStr((PP-S2.5)/pnt,"' = 'TR5.1' pips'"),12);
      PlotTL (EAname+"S3.5", true, 0, Time[tbar], S3.5, etim, S3.5, colr, 1, STYLE_DOT,   ray, false, 0);              // Plot trendline
      ObjectSetText(EAname+"S3.5",NumberToStr(S3.5,"'  S3.5='T3.5")+NumberToStr((PP-S3.5)/pnt,"' = 'TR5.1' pips'"),12);
      PlotTL (EAname+"R0.5", true, 0, Time[tbar], R0.5, etim, R0.5, colr, 1, STYLE_DOT,   ray, false, 0);              // Plot trendline
      ObjectSetText(EAname+"R0.5",NumberToStr(R0.5,"'  R0.5='T3.5")+NumberToStr((R0.5-PP)/pnt,"' = 'TR5.1' pips'"),12);
      PlotTL (EAname+"R1.5", true, 0, Time[tbar], R1.5, etim, R1.5, colr, 1, STYLE_DOT,   ray, false, 0);              // Plot trendline
      ObjectSetText(EAname+"R1.5",NumberToStr(R1.5,"'  R1.5='T3.5")+NumberToStr((R1.5-PP)/pnt,"' = 'TR5.1' pips'"),12);
      PlotTL (EAname+"R2.5", true, 0, Time[tbar], R2.5, etim, R2.5, colr, 1, STYLE_DOT,   ray, false, 0);              // Plot trendline
      ObjectSetText(EAname+"R2.5",NumberToStr(R2.5,"'  R2.5='T3.5")+NumberToStr((R2.5-PP)/pnt,"' = 'TR5.1' pips'"),12);
      PlotTL (EAname+"R3.5", true, 0, Time[tbar], R3.5, etim, R3.5, colr, 1, STYLE_DOT,   ray, false, 0);              // Plot trendline
      ObjectSetText(EAname+"R3.5",NumberToStr(R3.5,"'  R3.5='T3.5")+NumberToStr((R3.5-PP)/pnt,"' = 'TR5.1' pips'"),12);
    }

/*    
    if (PPLC[3] > "")  {
      int FO = StrToInteger(PPLC[3])-StartHourForPivots;
      PlotTL (EAname+"RX", true, 0, Time[tbar]+FO*3600, PP+20*pnt, etim,               PP+20*pnt, colr, 1, STYLE_DASH,   false, false, 0);              // Plot trendline
      PlotTL (EAname+"SX", true, 0, Time[tbar]+FO*3600, PP-20*pnt, etim,               PP-20*pnt, colr, 1, STYLE_DASH,   false, false, 0);              // Plot trendline
      PlotTL (EAname+"VX", true, 0, Time[tbar]+FO*3600, PP-20*pnt, Time[tbar]+FO*3600, PP+20*pnt, colr, 1, STYLE_DASH,   false, false, 0);              // Plot trendline
    }  
*/    
  }  
  return(0);
}

//+------------------------------------------------------------------+
int start()  {
//+------------------------------------------------------------------+
  CalcPivots();
  order_comment = EAname+Symbol();                                              // comment is EAname-symbol, ensures only one open order per pair, at any given time
//open_string  = "";
//close_string = "";
  if (iTime(Symbol(),Period(),0) > prev_time  &&  prev_time > 0)   {            // perform this only on first tick of new candle (on current chart)
    plot_obj();
    err_num    = GetLastError();
    err_string = EAname + "  " + Symbol() + "," + TFToStr(Period()) + DateToStr(TimeCurrent(),"' : 'w D n Y H:I:S") + " : New candle : " + err_msg(err_num);
//    out_text   = StringRepeat("=",80) + "\n" + err_string + "\n\n" + ListOrders("OPCD") + "\n\n" + ListObjects() + "\n\n" + DumpVars("new candle");
    out_text   = StringRepeat("=",80) + "\n" + err_string + "\n\n" + ListOrders("OPCD") + "\n\n" + DumpVars("new candle");
    df(out_text);
    last_dnote = "";                                                            // ensures that the first non-blank note generated in each hour gets output
  }  
  // close order if stipulated CloseCriteria have changed from false to true.....
  if (CloseOppositeOrders)     {
//  bar=2;   is_entry = false;   criteria = AppendIfMissing(StringUpper(CloseCriteria),",");   oper2 = CalcValues();
    bar=1;   is_entry = false;   criteria = AppendIfMissing(StringUpper(CloseCriteria),",");   oper1 = CalcValues();
    if (oper1 < 0)    CloseOrders(order_comment,OP_BUY,"1/1","[opposite]");      // sell signal = close buy order
    if (oper1 > 0)    CloseOrders(order_comment,OP_SELL,"1/1","[opposite]");     // buy signal  = close sell order
  }
  // place new order if stipulated EntryCriteria have changed from false to true.....
//bar=2;   is_entry = true;   criteria = AppendIfMissing(StringUpper(EntryCriteria),",");   oper2 = CalcValues();
  bar=1;   is_entry = true;   criteria = AppendIfMissing(StringUpper(EntryCriteria),",");   oper1 = CalcValues();
//if (oper1 != 0 && oper1 != oper2)    PlaceOrders();  
  if (oper1 != 0)                      PlaceOrders();

  prev_time = iTime(Symbol(),Period(),0);
  
  MoveSLtoBE(order_comment);              // check if SL should be moved to breakeven
  TrailSL(order_comment);                 // check trailing of SL 
  CheckWeekendClose(order_comment);       // check if orders should be closed just prior to the weekend
  CheckTrendlineExits(order_comment);     // check if orders should be fully/partially closed due to price reaching a trendline
  return(0);
}

//+------------------------------------------------------------------+
int Dnote(string note)  {
//+------------------------------------------------------------------+
  if (StringLen(note) > 0 && note != last_dnote)   {
    out_text = "\n**** Note: " + DateToStr(TimeCurrent(),"w D n Y H:I:S': '") + note + "\n";
    df(out_text);
    Print(out_text);
    if (DisplayComments)   Comment(out_text);
  }
  last_dnote = note;
  return(0);
}

//+------------------------------------------------------------------+
int CheckTrendlineExits(string comment)  {
//+------------------------------------------------------------------+
  if (nTE < 1 || StringLen(TrendlineExits) < 1)      return(0);
  for (int q=0; q<ObjectsTotal(); q++)    {
    string objname = ObjectName(q);
    string objdesc = ObjectDescription(objname);
    int    objtype = ObjectType(objname);
    if (objtype != OBJ_TREND && objtype != OBJ_HLINE)     continue;
    if (objtype == OBJ_HLINE)  
      double objprc = ObjectGet(objname,OBJPROP_PRICE1);
    else  
      objprc = ObjectGetValueByShift(objname,0);
    for (int r=0; r<nTE; r++)   {
      StrToStringArray(TE[r],arr,",");
      if (StringFind(objdesc,StringUpper(arr[0])) <= 0)    continue;
      bidp = Bid;
      if ((last_bid<objprc && bidp>=objprc) || (last_bid>objprc && bidp<=objprc))   {
        ObjectDelete(objname);
        err_num = GetLastError();
        if (err_num > 0)  {
          Dnote("Failed to delete object '" + objname + "'; " + err_msg(err_num));
        } else {
          Dnote("Object '" + objname + "' successfully deleted");
          CloseOrders(comment,-1,arr[1],"[trendline]");
  } } } } 
  last_bid = bidp;  
  return(0);
}

//+------------------------------------------------------------------+
int CloseOrders(string comment, int type, string fraction, string close_type)  {
//+------------------------------------------------------------------+
  close_type    = close_type + "[" + fraction + "]";
  orders_before = "\n\nORDERS BEFORE\n=============\n" + ListOrders("OPCD") + "\n\n" + DumpVars("Close Orders [Before]" + close_type);
  for (int i=OrdersTotal()-1; i>=0; i--)  {
    OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
    if (OrderSymbol() != Symbol())     continue;                   // must be for local pair, otherwise ignore
    if (OrderType()   > OP_SELL)       continue;                   // can't close pending orders
    if (type >= 0)
      if (OrderType() != type)         continue;                   // must be same as passed order type (OP_BUY/OP_SELL)
    if (comment > "")
      if (StringFind(StringUpper(OrderComment()),StringUpper(comment)) < 0)  continue;

    for (int attempt=NumberOfAttempts; attempt>=1; attempt--)   {
      askp  = NormalizeDouble(Ask,dig);
      bidp  = NormalizeDouble(Bid,dig);
      StrToIntegerArray(fraction,frac,"/",1);
      double ordvol = OrderLots()*DivZero(frac[0],frac[1]);
      minlot = MarketInfo(OrderSymbol(),MODE_MINLOT);
      if (minlot==1)            ordvol = NormalizeDouble(ordvol,0);
      if (minlot==0.1)          ordvol = NormalizeDouble(ordvol,1);
      if (minlot==0.01)         ordvol = NormalizeDouble(ordvol,2);
      if (frac[0]==frac[1])     ordvol = OrderLots();
      if (OrderType() == OP_SELL)      OrderClose(OrderTicket(),ordvol,askp,99,ArrowColorSellExit);   // close sell order at ask price
      if (OrderType() == OP_BUY)       OrderClose(OrderTicket(),ordvol,bidp,99,ArrowColorBuyExit);    // close buy order at bid price
      err_num = GetLastError(); 
      if (err_num > 0)  {
        if (attempt==1)  {
          string fname = EAname + NumberToStr(OrderTicket(),"T10'—'") + Symbol() + "—" + optypes[type] + "—[ERROR]—close.txt";
          err_string = EAname + "  " + Symbol() + "," + TFToStr(Period()) + DateToStr(TimeCurrent(),"' : 'w D n Y H:I:S") 
               + NumberToStr(OrderTicket(),"' : unable to CLOSE order #'T12' : '") + err_msg(err_num);
          OutputError(fname,err_string);
          if (DisplayComments)     Comment(NumberToStr(OrderTicket(),"'Unable to close order #'T12' : '") + err_msg(err_num));
        }
        Sleep(1000*SecondsBetweenAttempts);
        RefreshRates();
      } else {
        fname = EAname + NumberToStr(OrderTicket(),"T10'—'") + Symbol() + "—" + optypes[OrderType()] + "—close.gif";
        if (TakeSnapshots)    WindowScreenShot(fname,1024,768,-1,3,1);
        fname = EAname + NumberToStr(OrderTicket(),"T10'—'") + Symbol() + "—" + optypes[OrderType()] + "—close.txt";
        h = FileOpen(fname,FILE_WRITE|FILE_BIN);
        if (h>=0) {
          dump_string = DumpVars("Close Orders" + close_type);
          FileWriteString(h,dump_string,StringLen(dump_string));
          FileClose(h);
        }
        if (DisplayComments)     Comment(NumberToStr(OrderTicket(),"'Order# 'T10' successfully closed'"));
        break;  
  } } }

  // Write details to debug.txt file......  
  err_num      = GetLastError();
  orders_after = "\n\nORDERS AFTER\n=============\n" + ListOrders("OPCD") + "\n\n" + DumpVars("Close Orders [After]" + close_type);
  err_string   = EAname + "  " + Symbol() + "," + TFToStr(Period()) + DateToStr(TimeCurrent(),"' : 'w D n Y H:I:S") 
                 + NumberToStr(OrderTicket(),"' : successfully CLOSED order #'T12' : '") + err_msg(err_num);
  out_text     = StringRepeat("=",80) + "\n" + err_string + orders_before + orders_after;
  df(out_text);
  return(0);
}

//+------------------------------------------------------------------+
int PlaceOrders()  {
//+------------------------------------------------------------------+
  if (CountOrders(order_comment,"O") >= MaxOrdersPerEA)  {            // max of 1 open order permitted; if already existing, process no further
    Dnote("Order not placed: CountOrders > MaxOrdersPerEA");
    return(0);
  }

  // Check Asian Session range not greater than specified maximum......
  if (AsianSessionInterval > "")   {
    if (MathMod(StringLen(ASI[0]),2)==1)  ASI[0]="0"+ASI[0];
    datetime asian_open  = StrToTime(TimeToStr(TimeCurrent(),TIME_DATE)+EmbedString(StringRightPad(ASI[0],6,"0")," ##:##:##"));
    if (MathMod(StringLen(ASI[1]),2)==1)  ASI[1]="0"+ASI[1];
    datetime asian_close = StrToTime(TimeToStr(TimeCurrent(),TIME_DATE)+EmbedString(StringRightPad(ASI[1],6,"0")," ##:##:##"))-1;
    if (asian_open > asian_close)   asian_open -= 86400;
    if (TimeCurrent() > asian_close)  {
      int open_bar  = iBarShift(Symbol(),Period(),asian_open,false);
      int close_bar = iBarShift(Symbol(),Period(),asian_close,false);
      double asian_high = High[close_bar];
      double asian_low  = Low[close_bar];
      for (int z=close_bar; z>=open_bar; z++)   {
        asian_high = MathMax(asian_high,High[z]);
        asian_low  = MathMin(asian_low,Low[z]);
      }
      if (asian_high-asian_low > AsianSessionMaxRange*pnt)  {      // Asian range exceeds specified number of pips
        Dnote("Order not placed: Asian range > AsianSessionMaxRange");
        return(0);
  } } }

  // Check that current time is within one of the specified trading intervals (or is not outside any of the specified non-trading intervals) .....  
  if (StringLen(StringTrim(TimesToPlaceOrders)) > 0)   {
    bool inside_times = false;
    string ctime = DateToStr(TimeCurrent(),"HIS");
    for (z=0; z<nTI; z+=2)  {
      string stime = TI[z];
      if (MathMod(StringLen(stime),2)==1)  stime="0"+stime;
      stime = StringRightPad(stime,6,"0");
      string etime = TI[z+1];
      if (MathMod(StringLen(etime),2)==1)  etime="0"+etime;
      etime = StringRightPad(etime,6,"0");
      if (etime>=stime)  {
        if (ctime>=stime && ctime<=etime)     { inside_times = true;   break; }
      } else {
        if (ctime>=stime || ctime<=etime)     { inside_times = true;   break; }
    } }  
    if (!inside_times  && !Times_reverse)  {       // Current time is outside allowed    trading intervals (TimesToPlaceOrders)
      Dnote("Order not placed: Current time outside TimesToPlaceOrders");
      return(0);
    }  
    if ( inside_times  &&  Times_reverse)  {     // Current time is inside  disallowed trading intervals (TimesToPlaceOrders)
      Dnote("Order not placed: Current time inside disallowed TimesToPlaceOrders");
      return(0);
  } } 

  if (oper1 > 0  &&  StringFind(StringUpper(AllowableOrders),"B") < 0)  {     // AllowableOrders must contain 'B', if a buy order is to be placed
    Dnote("Order not placed: Buy order not in AllowableOrders");
    return(0); 
  }  
  if (oper1 < 0  &&  StringFind(StringUpper(AllowableOrders),"S") < 0)  {     // AllowableOrders must contain 'S', if a sell order is to be placed
    Dnote("Order not placed: Sell order not in AllowableOrders");
    return(0); 
  }
      
  if (StringFind(StringUpper(DaysToPlaceOrders),StringUpper(DateToStr(TimeCurrent(),"w"))) < 0)   {       // No trading if DOW not included in DaysToPlaceOrders
    Dnote("Order not placed: Today not in DaysToPlaceOrders");
    return(0); 
  }

  if (StringLen(WeekendCloseProfit)>0
      && StringUpper(StringSubstr(WeekendCloseProfit,0,3))==StringUpper(DateToStr(TimeCurrent(),"w"))
      && StringSubstr(WeekendCloseProfit,3,4)>=DateToStr(TimeCurrent(),"HI"))    {                        // Don't place any more trades after weekend close time
    Dnote("Order not placed: Time is after WeekendCloseProfit");
    return(0); 
  }
 
  if (askp-bidp > MaxSpreadPips*pnt)   {                                                                  // exceeds max spread; trade disallowed
    Dnote("Order not placed: Spread currently > MaxSpreadPips");
    return(0); 
  }

  orders_before = "\n\nORDERS BEFORE\n=============\n" + ListOrders("OPCD") + "\n\n" + DumpVars("Place Orders [Before]");

// All filters/tests passed OK if this point is reached; go ahead and place (market buy/sell) order.......
  int    order_type = (1-oper1)/2;                                                                              // returns 0 (OP_BUY) for oper=1; or 1 (OP_SELL) for oper=-1
  int    riskstep   = CountRecentLosses(order_comment);
  string TradeRisk  = RPT[riskstep];
  // Calc position size (in lots), and store in 'vol'.....
  double vol = 0, AcctFreeMgn = AccountEquity();
  if (StringFind(StringUpper(TradeRisk),"B") >= 0)    AcctFreeMgn = AccountBalance();
  if (StringFind(StringUpper(TradeRisk),"F") >= 0)    AcctFreeMgn = AccountFreeMargin();
  int RiskType = 0;                                                                                                // default to N lots
  if (StringFind(TradeRisk,"%") >= 0 && SL > 0)       RiskType = 1;                                                // N% of account equity
  if (StringFind(TradeRisk,"$") >= 0 && SL > 0)       RiskType = 2;                                                // $N amount
  switch (RiskType)  {
    case 1  : vol = DivZero(AcctFreeMgn*StrToNumber(TradeRisk)/100, MathAbs(entry-SL)/pnt*tickval);    break;      // calc vol = N% of account equity
    case 2  : vol = DivZero(StrToNumber(TradeRisk), MathAbs(entry-SL)/pnt*tickval);                    break;      // calc vol from entered $amount 
    default : vol = StrToNumber(TradeRisk);                                                            break;      // vol is simply no. of lots entered
  } 
  if (lotstep > 0) 
    vol = lotstep * MathInt(vol/lotstep);
  if (lotstep == 0.01)   vol = NormalizeDouble(MathInt(vol,2),2); 
  if (lotstep == 0.1)    vol = NormalizeDouble(MathInt(vol,1),1); 
  if (lotstep == 1)      vol = NormalizeDouble(MathInt(vol,0),0);

  if (vol < minlot)   {
    Dnote(NumberToStr(vol,"'Order not placed: volume of 'TR5.3' lots is less than allowed minimum size'"));
    return(0); 
  }

  // Set arrow color and magic#.....
  int   magic       = 0;
  color arrow_color = CLR_NONE;
  if (order_type == OP_BUY)    { arrow_color = ArrowColorBuyEntry;   magic = MagicNumberBuy;  }
  if (order_type == OP_SELL)   { arrow_color = ArrowColorSellEntry;  magic = MagicNumberSell; }
  
  // Send order to broker.....
  for (int attempt=NumberOfAttempts; attempt>=1; attempt--)   {
    askp = NormalizeDouble(Ask,dig);
    bidp = NormalizeDouble(Bid,dig);
    if (askp-bidp <= MaxSpreadPips*pnt)  {            // check that max allowed spread has not been exceeded
      if (order_type == OP_BUY)    entry = askp;
      if (order_type == OP_SELL)   entry = bidp;
      int tkt = OrderSend(Symbol(),order_type,vol,entry,99,0,0,order_comment,magic,0,arrow_color);
      err_num = GetLastError();
      if (tkt > 0 && err_num < 1)                    // order successfully placed; exit loop and proceed to next step
        break;
    }    
    if (attempt==1)   {                              // all attempts have failed; exit the whole routine without placing the order 
      string fname = EAname + NumberToStr(tkt,"T10'—'") + Symbol() + "—" + optypes[order_type] + "—[ERROR]—open.txt";
      err_string   = EAname + "  " + Symbol() + "," + TFToStr(Period()) + DateToStr(TimeCurrent(),"' : 'w D n Y H:I:S") 
                   + " : Unable to OPEN order  " + err_msg(err_num);
      OutputError(fname,err_string);
      return(0);
    }
    Sleep(1000*SecondsBetweenAttempts);              // pause for X seconds, then refresh rates and try again
    RefreshRates();
  }

  // Set SL/TP as a separate (OrderModify) step......
  SL = NormalizeDouble(SL,dig);
  TP = NormalizeDouble(TP,dig);
  if (SL>0 || TP>0)  {
    for (attempt=NumberOfAttempts; attempt>=1; attempt--)   {
      bool OK = OrderModify(tkt,0,SL,TP,0,arrow_color);
      err_num = GetLastError();
      if (err_num <= 1)                    // order successfully placed; exit loop and proceed to next step
        break;
      if (attempt==1)  {                   // all attempts have failed; exit the whole routine without setting a SL/TP 
        fname      = EAname + NumberToStr(tkt,"T10'—'") + Symbol() + "—" + optypes[order_type] + "—[ERROR]—open.txt";
        err_string = EAname + "  " + Symbol() + "," + TFToStr(Period()) + DateToStr(TimeCurrent(),"' : 'w D n Y H:I:S") 
                   + NumberToStr(OrderTicket(),"' : unable to MODIFY new order #'T12' : '") + err_msg(err_num);
        OutputError(fname,err_string);
        return(0);
      }  
      Sleep(1000*SecondsBetweenAttempts);      // pause for X seconds, then refresh rates and try again
      RefreshRates();
  } }
  
  // Order successfully placed, output details......
  string mask = "TR5." + NumberToStr(dig,"1");
  display_string = NumberToStr(tkt,"'Order# 'T10' placed successfully — '") + StringLower(optypes[order_type]) + NumberToStr(vol,"' 'T5.2' lots'")
                 + StrToStr(TradeRisk,"'; (Trade Risk ='T20')'") + NumberToStr(entry,"'\n    Entry @ '"+mask);
  if (SL>0)     
    display_string = display_string + NumberToStr(SL,"'\n    SL @ '"+mask) + NumberToStr(MathAbs(entry-SL)/pnt,"' = 'TR4.1' pips'")
                   + NumberToStr(MathAbs(entry-SL)/pnt*vol*tickval,"' = $'TR,9.2") + NumberToStr(MathAbs(entry-SL)/pnt*vol*tickval*100/AcctFreeMgn,"' = 'TR5.2'%'");
  if (TP>0)     
    display_string = display_string + NumberToStr(TP,"'\n    TP @ '"+mask) + NumberToStr(MathAbs(entry-TP)/pnt,"' = 'TR4.1' pips'") 
                   + NumberToStr(MathAbs(entry-TP)/pnt*vol*tickval,"' = $'TR,9.2") + NumberToStr(MathAbs(entry-TP)/pnt*vol*tickval*100/AcctFreeMgn,"' = 'TR5.2'%'");
  if (SL*TP>0)  
    display_string = display_string + NumberToStr(MathAbs((entry-TP)/(entry-SL)),"' = 'TR4.2':1 RR'");
  if (DisplayComments)    Comment(display_string);               

  fname = EAname + NumberToStr(tkt,"T10'—'") + Symbol() + "—" + optypes[order_type] + "—open.gif";      // snapshot
  if (TakeSnapshots)    WindowScreenShot(fname,1024,768,-1,3,1);

  fname = EAname + NumberToStr(tkt,"T10'—'") + Symbol() + "—" + optypes[order_type] + "—open.txt";      // logfile
  h = FileOpen(fname,FILE_WRITE|FILE_BIN);
  if (h>=0) {
    dump_string = DumpVars("Place Orders");
    FileWriteString(h,dump_string,StringLen(dump_string));
    FileWriteString(h,"\n\n"+display_string,2+StringLen(display_string));
    FileClose(h);
  }

  // Write details to debug.txt file......  
  err_num      = GetLastError();
  orders_after = "\n\nORDERS AFTER\n=============\n" + ListOrders("OPCD") + "\n\n" + DumpVars("Place Orders [After]");
  err_string   = EAname + "  " + Symbol() + "," + TFToStr(Period()) + DateToStr(TimeCurrent(),"' : 'w D n Y H:I:S") 
                 + NumberToStr(OrderTicket(),"' : successfully OPENED order #'T12' : '") + err_msg(err_num);
  out_text     = StringRepeat("=",80) + "\n" + err_string + orders_before + orders_after + display_string;
  df(out_text);
  return(0);
}

//+------------------------------------------------------------------+
int OutputError (string filename, string err_text)  {
//+------------------------------------------------------------------+
  orders_after = "\n\nORDERS AFTER\n=============\n" + ListOrders("OPCD") + "\n\n" + DumpVars("Place Orders (Output Error) [After]");
  if (DisplayComments)    Comment(err_text);
  out_text = StringRepeat("=",80) + "\n" + err_text + orders_before + orders_after;
  int h = FileOpen(filename,FILE_WRITE|FILE_BIN);
  if (h>=0) {
    FileWriteString(h,out_text,StringLen(out_text));
    FileClose(h);
  }
  df(out_text);  
  return(0);
}

//+------------------------------------------------------------------+
int CountRecentLosses (string comment)  {
//+------------------------------------------------------------------+
// For use if multiple settings (martingale position steps) in RiskPerTrade. 
// Use the returned value element# of the RPT[] array for position size
// Returns 0 if last trade was profit, or number of allowable martingale steps exceeded
  int count=0;
  ArrayInitializeString(ordsort);
  for (int i=OrdersHistoryTotal()-1; i>=0; i--)  {
    OrderSelect(i, SELECT_BY_POS, MODE_HISTORY);
    if (OrderSymbol() != Symbol())             continue;                                    // must be for local pair, otherwise ignore
    if (OrderStatus(OrderTicket()) != "C")     continue;                                    // must be a closed order
    if (comment > "")
      if (StringFind(StringUpper(OrderComment()),StringUpper(comment)) < 0)  continue;      // order comment must contain any specified comment
    ordsort[count] = DateToStr(OrderCloseTime(),"YMDHIS") + NumberToStr(OrderTicket(),"'-'Z12") + ifstr(OrderProfit()>=0,"P","L");
    count++;   
    if (count>=100)   break;
  }
  ShellsortStringArray(ordsort,count+1,true);   // sort in descending CloseTime order
  for (i=0; i<count; i++)   {
    if (StringFind(ordsort[i],"P")>=0)    break;
  }  
  if (i>=nRPT)   i=0;
  return(i);
}

//+------------------------------------------------------------------+
int CountOrders (string comment, string types)  {
//+------------------------------------------------------------------+
// Return count of open orders for this pair (generated by this EA), by checking the comment.......
  types = StringUpper(types);
  int count=0;
  if (StringFind(types,"O") >= 0 || StringFind(types,"P") >= 0)   {
    for (int i=OrdersTotal()-1; i>=0; i--)  {
      OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
      if (OrderSymbol() != Symbol())                            continue;                     // must be for local pair, otherwise ignore
      if (StringFind(types,OrderStatus(OrderTicket())) < 0)     continue;                     // must match one of the specified order types
      if (comment > "")
        if (StringFind(StringUpper(OrderComment()),StringUpper(comment)) < 0)  continue;      // order comment must contain any specified comment
      count++;   
  } }

  if (StringFind(types,"C") >= 0 || StringFind(types,"D") >= 0)   {
    for (i=OrdersHistoryTotal()-1; i>=0; i--)  {
      OrderSelect(i, SELECT_BY_POS, MODE_HISTORY);
      if (OrderSymbol() != Symbol())   continue;                                              // must be for local pair, otherwise ignore
      if (StringFind(types,OrderStatus(OrderTicket())) < 0)     continue;                     // must match one of the specified order types
      if (comment > "")
        if (StringFind(StringUpper(OrderComment()),StringUpper(comment)) < 0)  continue;      // order comment must contain any specified comment
      count++;   
  } }
  
  return(count);
}

//+------------------------------------------------------------------+
int CheckWeekendClose(string comment)  {
//+------------------------------------------------------------------+
  if (StringLen(WeekendCloseProfit)<1 && StringLen(WeekendCloseLoss)<1)    return(0);
  for (int i=OrdersTotal()-1; i>=0; i--)  {
    OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
    if (OrderSymbol() != Symbol())   continue;                   // must be for local pair, otherwise ignore
    if (OrderType() > 1)             continue;                   // must be an open order, hence ignore any pending orders
    if (comment > "")
      if (StringFind(StringUpper(OrderComment()),StringUpper(comment)) < 0)  continue;
    bool close = false;
    if (StringLen(WeekendCloseProfit)>0 && OrderProfit()>=0 
        && StringUpper(StringSubstr(WeekendCloseProfit,0,3))==StringUpper(DateToStr(TimeCurrent(),"w"))
        && StringSubstr(WeekendCloseProfit,3,4)>=DateToStr(TimeCurrent(),"HI"))
      close = true;
    if (StringLen(WeekendCloseLoss)>0
        && StringUpper(StringSubstr(WeekendCloseLoss,0,3))==StringUpper(DateToStr(TimeCurrent(),"w"))
        && StringSubstr(WeekendCloseProfit,3,4)>=DateToStr(TimeCurrent(),"HI"))
      close = true;
    if (close) {     
      orders_before = "\n\nORDERS BEFORE\n=============\n" + ListOrders("OPCD") + "\n\n" + DumpVars("Check Weekend Close [Before]");
      askp = NormalizeDouble(Ask,dig);
      bidp = NormalizeDouble(Bid,dig);
      if (OrderType() == OP_BUY)          OrderClose(OrderTicket(),OrderLots(),bidp,99,ArrowColorBuyExit);
      if (OrderType() == OP_SELL)         OrderClose(OrderTicket(),OrderLots(),askp,99,ArrowColorSellExit);

      // Write details to debug.txt file......  
      err_num      = GetLastError();
      orders_after = "\n\nORDERS AFTER\n=============\n" + ListOrders("OPCD") + "\n\n" + DumpVars("Check Weekend Close [After]");
      err_string   = EAname + "  " + Symbol() + "," + TFToStr(Period()) + DateToStr(TimeCurrent(),"' : 'w D n Y H:I:S"); 
      if (err_num > 0)
        err_string = err_string + NumberToStr(OrderTicket(),"' : failed to CLOSE (weekend test) order #'T12' : '") + err_msg(err_num);
      else
        err_string = err_string + NumberToStr(OrderTicket(),"' : successfully CLOSED (weekend test) order #'T12' : '") + err_msg(err_num);
      out_text = StringRepeat("=",80) + "\n" + err_string + orders_before + orders_after;
      df(out_text);
  } }
  return(0);
}

//+------------------------------------------------------------------+
int MoveSLtoBE(string comment)  {
//+------------------------------------------------------------------+
  if (ProfitPipsForSLtoBE <= 0)   return(0);
  for (int i=OrdersTotal()-1; i>=0; i--)  {
    OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
    if (OrderSymbol() != Symbol())   continue;                   // must be for local pair, otherwise ignore
    if (OrderType() > 1)             continue;                   // must be an open order, hence ignore any pending orders
    if (comment > "")
      if (StringFind(StringUpper(OrderComment()),StringUpper(comment)) < 0)  continue;
    if (OrderType() == OP_BUY   &&  Bid > OrderOpenPrice() + ProfitPipsForSLtoBE*pnt)  {   
      NewSL = OrderOpenPrice()+BEpointPips*pnt;
      if (NewSL > OrderStopLoss())  {
        OrderModify(OrderTicket(),0,NewSL,OrderTakeProfit(),OrderExpiration(),ArrowColorBuyExit);
        Dnote(NumberToStr(NewSL,"'SL moved to 'TR-3.5' (breakeven) on buy order'"));
    } } 
    if (OrderType() == OP_SELL  &&  Ask < OrderOpenPrice() - ProfitPipsForSLtoBE*pnt)  {    
      NewSL = OrderOpenPrice()-BEpointPips*pnt;
      if (NewSL < OrderStopLoss())  {
        OrderModify(OrderTicket(),0,NewSL,OrderTakeProfit(),OrderExpiration(),ArrowColorSellExit);
        Dnote(NumberToStr(NewSL,"'SL moved to 'TR-3.5' (breakeven) on sell order'"));
  } } }
  return(0);
}

//+------------------------------------------------------------------+
int TrailSL(string comment)  {
//+------------------------------------------------------------------+
  if (TrailingSLpips <= 0)   return(0);
  for (int i=OrdersTotal()-1; i>=0; i--)  {
    OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
    if (OrderSymbol() != Symbol())   continue;                   // must be for local pair, otherwise ignore
    if (OrderType() > 1)             continue;                   // must be an open order, hence ignore any pending orders
    if (comment > "")
      if (StringFind(StringUpper(OrderComment()),StringUpper(comment)) < 0)  continue;
    if (OrderType() == OP_BUY)  {
      NewSL = NormalizeDouble(Bid-TrailingSLpips*pnt,dig);
      if (NewSL > OrderStopLoss()  &&  (OrderStopLoss() >= OrderOpenPrice()+BEpointPips*pnt || !TrailOnlyAfterBEreached))  {
        OrderModify(OrderTicket(),0,NewSL,OrderTakeProfit(),OrderExpiration(),ArrowColorBuyExit);
        Dnote(NumberToStr(NewSL,"'SL trailed to 'TR-3.5' (breakeven) on buy order'"));
    } }
    if (OrderType() == OP_SELL)  {
      NewSL = NormalizeDouble(Ask+TrailingSLpips*pnt,dig);
      if (NewSL < OrderStopLoss()  &&  (OrderStopLoss() <= OrderOpenPrice()-BEpointPips*pnt || !TrailOnlyAfterBEreached))  {
        OrderModify(OrderTicket(),0,NewSL,OrderTakeProfit(),OrderExpiration(),ArrowColorSellExit);
        Dnote(NumberToStr(NewSL,"'SL trailed to 'TR-3.5' (breakeven) on sell order'"));
  } } }
  return(0);
}

//+------------------------------------------------------------------+
int CalcValues()  {
//+------------------------------------------------------------------+
// Check entry rules for valid buy/sell signal; calc and return retval (signal polarity), entry, SL, TP; build and output diagnostic string..... 

// Check for valid buy signal.....
  allow_buy = false;
  reason    = -1;
  if (Close[bar]>PP-TolerancePips*pnt && Low[bar]<=PP+TolerancePips*pnt && Close[0]>=PP+Close[bar]*pnt)   {      // candle straddles PP and closes above PP
    allow_buy = true;   
    reason    = 0;
    if (MinCandleBodyPips>0 && Close[bar]-Open[bar]<MinCandleBodyPips*pnt)  {      // needs to be green candle with body > X pips, else buy signal is invalid
      allow_buy = false;
      reason    = 1;
    }  
    if (MaxCandleBodyPips>0 && Close[bar]-Open[bar]>MaxCandleBodyPips*pnt)  {      // if body exceeds max allowable pips, buy signal is invalid
      allow_buy = false;
      reason    = 2;
    }  
    if (WholeBodyMustStraddlePP && Open[bar]>PP+TolerancePips*pnt)  {              // if body fails to straddle PP, then buy signal is invalid
      allow_buy = false;
      reason    = 3;
  } }
  switch (reason)    {
    case  0 : Dnote("Buy order: criteria met");                                                            break;
    case  1 : Dnote("Buy order: criteria failed (not a green candle with body >= MinCandleBodyPips)");     break;
    case  2 : Dnote("Buy order: criteria failed (candle body > MaxCandleBodyPips)");                       break;
    case  3 : Dnote("Buy order: criteria failed (WholeBodyMustStraddlePP)");                               break;
    default :                                                                                              break;
  }  

// Check for valid sell signal.....
  allow_sell = false;
  reason     = -1;
  if (Close[bar]<PP+TolerancePips*pnt && High[bar]>=PP-TolerancePips*pnt && Close[0]<=PP-Close[bar]*pnt)   {      // candle straddles PP and closes below PP
    allow_sell = true;
    reason     = 0;
    if (MinCandleBodyPips>0 && Open[bar]-Close[bar]<MinCandleBodyPips*pnt)  {    // needs to be red candle with body > X pips, else sell signal is invalid
      allow_sell = false;
      reason     = 1;
    }  
    if (MaxCandleBodyPips>0 && Open[bar]-Close[bar]>MaxCandleBodyPips*pnt)  {    // if body exceeds max allowable pips, sell signal is invalid
      allow_sell = false;
      reason     = 2;
    }  
    if (WholeBodyMustStraddlePP && Open[bar]<PP-TolerancePips*pnt)  {            // if body fails to straddle PP, then sell signal is invalid
      allow_sell = false;
      reason     = 3;
  } }  
  switch (reason)    {
    case  0 : Dnote("Sell order: criteria met");                                                           break;
    case  1 : Dnote("Sell order: criteria failed (not a red candle with body >= MinCandleBodyPips)");      break;
    case  2 : Dnote("Sell order: criteria failed (candle body > MaxCandleBodyPips)");                      break;
    case  3 : Dnote("Sell order: criteria failed (WholeBodyMustStraddlePP)");                              break;
    default :                                                                                              break;
  }  

  retval = allow_buy - allow_sell;                                                     // retval = 1 for buy signal; -1 for sell signal; 0 for both or neither (indeterminate)
  if (retval==0)        return(0);                                                     // no point in continuing further
  
  if (ReverseSignals)   retval = -retval;

//  if (is_entry   &&  StringLen(StringTrim(EntryCriteria)) == 0)   retval = 0;        // null EntryCriteria, override (remove) the possibility of opening any trade
//  if (!is_entry  &&  StringLen(StringTrim(CloseCriteria)) == 0)   retval = 0;        // null CloseCriteria, override (remove) the possibility of closing any trade

// Adjust for spread must work as follows:
//    SELL order, entry at BID; if adjust=false, TP/SL at ASK (as per normal); if adjust=true, TP/SL at BID (adjust to make same as entry)
//    BUY  order, entry at ASK; if adjust=false, TP/SL at BID (as per normal); if adjust=true, TP/SL at ASK (adjust to make same as entry)
  entry = 0;
  SL    = 0;
  TP    = 0;
  if (is_entry)   {     // no need to calc entry/SL/TP if the routine was called to check for "exit on opposite criteria" only
    askp  = Ask;
    bidp  = Bid;
    if (retval < 0)   {      // SELL order.....
      entry = bidp;
      if (OverrideSLpips == 0)       SL = 0;                                                          else
      if (OverrideSLpips >  0)       SL = askp + OverrideSLpips*pnt - AdjustForSpread*(askp-bidp);    else
      if (OverrideSLpips == -1000)   SL = R1 + (1-AdjustForSpread)*(askp-bidp);                       else
      {
        SL = 0;
        for (int b=1; b<=-OverrideSLpips; b++)   
          SL = MathMax(SL,iHigh(Symbol(),Period(),b));
        SL += (askp-bidp) + (1-AdjustForSpread)*(askp-bidp);  
      }
      if (SL>0)  SL=MathMax(SL,askp+MinSLTPpipsFromEntry*pnt);
      if (OverrideTPpips == 0)       TP = 0;                                                          else
      if (OverrideTPpips >  0)       TP = askp - OverrideTPpips*pnt - AdjustForSpread*(askp-bidp);    else
      if (OverrideTPpips == -1000)   TP = S1 + (1-AdjustForSpread)*(askp-bidp);                                              
      if (TP>0)  TP=MathMin(TP,bidp-MinSLTPpipsFromEntry*pnt-(askp-bidp));
    }
    if (retval > 0)   {     // BUY order.....
      entry = askp;
      if (OverrideSLpips == 0)       SL = 0;                                                          else
      if (OverrideSLpips >  0)       SL = bidp - OverrideSLpips*pnt + AdjustForSpread*(askp-bidp);    else
      if (OverrideSLpips == -1000)   SL = S1 + AdjustForSpread*(askp-bidp);                           else
      {
        SL = 999999;
        for (b=1; b<=-OverrideSLpips; b++)   
          SL = MathMin(SL,iLow(Symbol(),Period(),b));
        SL -= (askp-bidp) + AdjustForSpread*(askp-bidp);  
      }     
      if (SL>0)  SL=MathMin(SL,bidp-MinSLTPpipsFromEntry*pnt-(askp-bidp));
      if (OverrideTPpips == 0)       TP = 0;                                                          else
      if (OverrideTPpips >  0)       TP = bidp + OverrideTPpips*pnt + AdjustForSpread*(askp-bidp);    else
      if (OverrideTPpips == -1000)   TP = R1 + AdjustForSpread*(askp-bidp);
      if (TP>0)  TP=MathMax(TP,askp+MinSLTPpipsFromEntry*pnt);
  } }
  
/*
  dump_string = DumpVars("Calc Values");
  if (AuditLogging)   {
    log("\n"+dump_string);    
    string fname = EAname + Symbol() + "—AUDIT.txt";
    int h = FileOpen(fname,FILE_READ|FILE_WRITE|FILE_BIN);
    if (h>=0) {
      FileSeek(h,0,SEEK_END);
      FileWriteString(h,"\n\n"+dump_string,2+StringLen(dump_string));
      FileClose(h);
  } }
  
  if (is_entry) 
    open_string  = open_string + "\n" + dump_string; 
  else
    close_string = close_string + "\n" + dump_string; 
*/  
  return(retval);
}

//+------------------------------------------------------------------+
string DumpVars(string breakpoint_id="")   {
//+------------------------------------------------------------------+
  string vars = DateToStr(iTime(Symbol(),Period(),0),                       "'Current candle           ['w D n Y H:I:S']<<=========================================================\n'")
              + DateToStr(prev_time,                                        "'Previous candle          ['w D n Y H:I:S']\n'")
              +                                                              "Is Entry?                [" +BoolToStr(is_entry)+"]\n"
              + NumberToStr(bar,                                            "'Candle#                  ['T-4']\n'")
              + DateToStr(Time[bar],                                        "'Candle Open Time         ['w D n Y H:I:S']\n'")
              + NumberToStr(Open[bar],                                      "'Candle Open              ['R-3.5']\n'") 
              + NumberToStr(High[bar],                                      "'Candle High              ['R-3.5']\n'") 
              + NumberToStr(Low[bar],                                       "'Candle Low               ['R-3.5']\n'") 
              + NumberToStr(Close[bar],                                     "'Candle Close             ['R-3.5']\n'") 
              + NumberToStr(Volume[bar],                                    "'Candle Volume            ['T-12']\n'")
              + StrToStr(criteria,                                          "'Criteria                 ['T80']\n'")
              + NumberToStr(retval,                                         "'OPERATION (retval)       ['T-1']<<------------\n'")
              + NumberToStr(Ask,                                            "'Ask price                ['R-3.5']\n'") 
              + NumberToStr(Bid,                                            "'Bid price                ['R-3.5']\n'") 
              + NumberToStr((Ask-Bid)/pnt,                                  "'Spread                   ['R-5.1']\n'") 
              + NumberToStr(tickval,                                        "'Pip value (tickval)      ['R-3.5']\n'") 
              + StrToStr(breakpoint_id,                                     "'Breakpoint ID            ['T40']<<=====\n\n'")
//------------------------- User parameter settings
              + StrToStr(EAname,                                            "'EAname                   ['T20']\n'")
              + StrToStr(RiskPerTrade,                                      "'RiskPerTrade             ['T40']\n'")
              + StrToStr(AllowableOrders,                                   "'AllowableOrders          ['T20']\n'")
              + StrToStr(DaysToPlaceOrders,                                 "'DaysToPlaceOrders        ['T60']\n'")
              + StrToStr(TimesToPlaceOrders,                                "'TimesToPlaceOrders       ['T60']\n'")
              + StrToStr(SLmethod,                                          "'SLmethod                 ['T20']\n'")
              + StrToStr(TPmethod,                                          "'TPmethod                 ['T20']\n'")
              + StrToStr(TrendlineExits,                                    "'TrendlineExits           ['T60']\n'")
              +                                                              "AdjustForSpread          [" +BoolToStr(AdjustForSpread)+"]\n"
              + NumberToStr(MaxSpreadPips,                                  "'MaxSpreadPips            ['R-3.5']\n'") 
              + NumberToStr(MinSLTPpipsFromEntry,                           "'MinSLTPpipsFromEntry     ['R-3.5']\n'") 
              + NumberToStr(ProfitPipsForSLtoBE,                            "'ProfitForSLtoBE          ['R-3.5']\n'") 
              + NumberToStr(BEpointPips,                                    "'BEpointPips              ['R-3.5']\n'") 
              + StrToStr(TrailingSL,                                        "'TrailingSL               ['T20']\n'")
              +                                                              "TrailOnlyAfterBE         [" +BoolToStr(TrailOnlyAfterBEreached)+"]\n"
              + StrToStr(WeekendCloseProfit,                                "'WeekendCloseProfit       ['T20']\n'")
              + StrToStr(WeekendCloseLoss,                                  "'WeekendCloseLoss         ['T20']\n'")
              +                                                              "TakeSnapshots            [" +BoolToStr(TakeSnapshots)+"]\n"
              + NumberToStr(NumberOfAttempts,                               "'NumberOfAttempts         ['T-6']\n'")
              + NumberToStr(SecondsBetweenAttempts,                         "'SecondsBetweenAttempts   ['R-3.5']\n'")
              + NumberToStr(MaxOrdersPerEA,                                 "'MaxOrdersPerEA           ['T-6']\n'")
              + NumberToStr(MagicNumberBuy,                                 "'MagicNumberBuy           ['T-12']\n'")
              + NumberToStr(MagicNumberSell,                                "'MagicNumberSell          ['T-12']\n'")
              + StrToStr(PivotCalcMethod_SFWTCP,                            "'PivotCalcMethod_SFWTCP   ['T80']\n'")
              + NumberToStr(StartHourForPivots,                             "'StartHourForPivots       ['T-2']\n'")
              + StrToStr(PlotPivotLinesColor,                               "'PlotPivotLinesColor      ['T80']\n'")
              + NumberToStr(ClearancePips,                                  "'ClearancePips            ['R-3.5']\n'") 
              + NumberToStr(TolerancePips,                                  "'TolerancePips            ['R-3.5']\n'") 
              + NumberToStr(MinCandleBodyPips,                              "'MinCandleBodyPips        ['R-3.5']\n'") 
              + NumberToStr(MaxCandleBodyPips,                              "'MaxCandleBodyPips        ['R-3.5']\n'") 
              + StrToStr(AsianSessionInterval,                              "'AsianSessionInterval     ['T20']\n'")
              + NumberToStr(AsianSessionMaxRange,                           "'AsianSessionMaxRange     ['R-3.5']\n'") 
              +                                                              "CloseOppositeOrders      [" +BoolToStr(CloseOppositeOrders)+"]\n"
              +                                                              "WholeBodyMustStraddlePP  [" +BoolToStr(WholeBodyMustStraddlePP)+"]\n"
              + NumberToStr(MinMinutesBetwSameDirOrders,                    "'MinMinutesBetw...Orders  ['T-6']\n'")
              +                                                              "DisplayComments          [" +BoolToStr(DisplayComments)+"]\n"
              +                                                              "ReverseSignals           [" +BoolToStr(ReverseSignals)+"]\n\n"
//------------------------- Program specific variables
              + StrToStr(order_comment,                                     "'order_comment            ['T80']\n'")
              + NumberToStr(OverrideSLpips,                                 "'OverrideSLpips           ['R-6.5']\n'") 
              + NumberToStr(OverrideTPpips,                                 "'OverrideTPpips           ['R-6.5']\n'") 
              + NumberToStr(TrailingSLpips,                                 "'TrailingSLpips           ['R-6.5']\n'") 
              + NumberToStr(PP,                                             "'PP                       ['R-3.5']\n'") 
              + NumberToStr(S1,                                             "'S1                       ['R-3.5']\n'") 
              + NumberToStr(R1,                                             "'R1                       ['R-3.5']\n'") 
              +                                                              "allow_buy                [" +BoolToStr(allow_buy)+"]\n"
              +                                                              "allow_sell               [" +BoolToStr(allow_sell)+"]\n"
              + NumberToStr(entry,                                          "'entry                    ['R-3.5']\n'") 
              + NumberToStr(SL,                                             "'SL                       ['R-3.5']\n'") 
              + NumberToStr(TP,                                             "'TP                       ['R-3.5']\n\n'")
//------------------------- Important program variables
              + StrToStr(ccy,                                               "'ccy                      ['T20']\n'")
              + StrToStr(sym,                                               "'sym                      ['T20']\n'")
              + NumberToStr(tmf,                                            "'tmf                      ['T-8']\n'") 
              + NumberToStr(bidp,                                           "'bidp                     ['R,-6.5']\n'") 
              + NumberToStr(askp,                                           "'askp                     ['R,-6.5']\n'") 
              + NumberToStr(pnt,                                            "'pnt                      ['R,-6.5']\n'") 
              + NumberToStr(dig,                                            "'dig                      ['T-4']\n'") 
              + NumberToStr(spr,                                            "'spr                      ['R,-6.5']\n'") 
              + NumberToStr(tickval,                                        "'tickval                  ['R,-6.5']\n'") 
              + NumberToStr(lswap,                                          "'lswap                    ['R,-6.5']\n'") 
              + NumberToStr(sswap,                                          "'sswap                    ['R,-6.5']\n'") 
              + NumberToStr(minlot,                                         "'minlot                   ['R,-6.5']\n\n'") 
//------------------------- Current order information                                                  
              + NumberToStr(OrderTicket(),                                  "'OrderTicket()            ['T-12']\n'") 
              + StrToStr(optypes[OrderType()],                              "'OrderType()              ['T20']\n'")
              + StrToStr(OrderStatus(OrderTicket()),                        "'OrderStatus(Ticket)      ['T20']\n'")
              + StrToStr(OrderSymbol(),                                     "'OrderSymbol()            ['T20']\n'")
              + NumberToStr(OrderLots(),                                    "'OrderLots()              ['R,-6.5']\n'") 
              + NumberToStr(OrderOpenPrice(),                               "'OrderOpenPrice()         ['R,-6.5']\n'") 
              + DateToStr(OrderOpenTime(),                                  "'OrderOpenTime()          ['w D n Y H:I:S']\n'")
              + NumberToStr(OrderClosePrice(),                              "'OrderClosePrice()        ['R,-6.5']\n'") 
              + DateToStr(OrderCloseTime(),                                 "'OrderCloseTime()         ['w D n Y H:I:S']\n'")
              + NumberToStr(OrderStopLoss(),                                "'OrderStopLoss()          ['R,-6.5']\n'") 
              + NumberToStr(OrderTakeProfit(),                              "'OrderTakeProfit()        ['R,-6.5']\n'") 
              + NumberToStr(OrderProfit(),                                  "'OrderProfit()            ['R,-6.5']\n'") 
              + NumberToStr(OrderCommission(),                              "'OrderCommission()        ['R,-6.5']\n'") 
              + NumberToStr(OrderSwap(),                                    "'OrderSwap()              ['R,-6.5']\n'") 
              + StrToStr(OrderComment(),                                    "'OrderComment()           ['T20']\n'")
              + NumberToStr(OrderMagicNumber(),                             "'OrderMagicNumber()       ['T-12']\n'") 
              + DateToStr(OrderExpiration(),                                "'OrderExpiration()        ['w D n Y H:I:S']\n\n'")
//------------------------- System information
              +                                                              "Chart                    [" + Symbol()+","+TFToStr(Period())+"]\n"              
              + DateToStr(TimeCurrent(),                                    "'MT4 time                 ['w D n Y H:I:S']\n'")
              + DateToStr(TimeLocal(),                                      "'Local time               ['w D n Y H:I:S']\n'")
              + StrToStr(err_msg(GetLastError()),                           "'Last error               ['T80']\n'")
              + DateToStr(MarketInfo(Symbol(),MODE_TIME),                   "'Last tick                ['w D n Y H:I:S']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_HIGH),                 "'High day price           ['T-4.5']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_LOW),                  "'Low day price            ['T-4.5']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_BID),                  "'Bid Price                ['T-4.5']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_ASK),                  "'Ask Price                ['T-4.5']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_SPREAD),               "'Spread (points)          ['T-4.5']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_POINT),                "'Point                    ['T-4.5']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_DIGITS),               "'Digits                   ['T-4']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_STOPLEVEL),            "'Stop Level               ['T-4.5']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_LOTSIZE),              "'Lot Size                 ['T-9.3']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_TICKVALUE),            "'Tick Value (points)      ['T-4.5']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_TICKSIZE),             "'Tick Size                ['T-4.5']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_SWAPLONG),             "'Swap Long                ['T-6.5']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_SWAPSHORT),            "'Swap Short               ['T-6.5']\n'")
              + DateToStr(MarketInfo(Symbol(),MODE_STARTING),               "'Market starting date     ['w D n Y H:I:S']\n'")
              + DateToStr(MarketInfo(Symbol(),MODE_EXPIRATION),             "'Market expiration date   ['w D n Y H:I:S']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_TRADEALLOWED),         "'Trade Allowed            ['T-4']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_MINLOT),               "'Minimum Lots             ['T-9.3']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_LOTSTEP),              "'Lot Step                 ['T-9.3']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_MAXLOT),               "'Maximum Lots             ['T-9.3']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_SWAPTYPE),             "'Swap Type                ['T-4']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_PROFITCALCMODE),       "'Profit calc mode         ['T-4']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_MARGINCALCMODE),       "'Margin calc mode         ['T-4']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_MARGININIT),           "'Init Margin              ['T-9.3']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_MARGINMAINTENANCE),    "'Margin Maint             ['T-9.3']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_MARGINHEDGED),         "'Hedged Margin            ['T-9.3']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_MARGINREQUIRED),       "'Required Margin          ['T-9.3']\n'")
              + NumberToStr(MarketInfo(Symbol(),MODE_FREEZELEVEL),          "'Freeze Level             ['T-4.5']\n\n'")
              + NumberToStr(Bars,                                           "'Bars                     ['T-6']\n'")
              + NumberToStr(IndicatorCounted(),                             "'IndicatorCounted()       ['T-6']\n'")
              + NumberToStr(GetTickCount(),                                 "'GetTickCount()           ['T-12']\n'")
              + NumberToStr(GlobalVariablesTotal(),                         "'GlobalVariablesTotal()   ['T-6']\n'")
              + NumberToStr(OrdersTotal(),                                  "'OrdersTotal()            ['T-6']\n'")
              + NumberToStr(OrdersHistoryTotal(),                           "'OrdersHistoryTotal()     ['T-6']\n'")
              + NumberToStr(ObjectsTotal(),                                 "'ObjectsTotal()           ['T-6']\n'")
              + NumberToStr(WindowsTotal(),                                 "'WindowsTotal()           ['T-6']\n'")
              + NumberToStr(WindowHandle(Symbol(),Period()),                "'WindowHandle()           ['T-12']\n'")
              + NumberToStr(WindowBarsPerChart(),                           "'WindowBarsPerChart()     ['T-6']\n'")
              + NumberToStr(WindowFirstVisibleBar(),                        "'WindowFirstVisibleBar()  ['T-6']\n'")
              + StrToStr(WindowExpertName(),                                "'WindowExpertName()       ['L60']\n'")
              + NumberToStr(WindowPriceMax(),                               "'WindowPriceMax()         ['T-4.5']\n'")
              + NumberToStr(WindowPriceMin(),                               "'WindowPriceMin()         ['T-4.5']\n'")
              + NumberToStr(WindowPriceOnDropped(),                         "'WindowPriceOnDropped()   ['T-4.5']\n'")
              + DateToStr(WindowTimeOnDropped(),                            "'WindowTimeOnDropped()    ['w D n Y H:I:S']\n'")
              + NumberToStr(WindowXOnDropped(),                             "'WindowXOnDropped()       ['T-6']\n'")
              + NumberToStr(WindowYOnDropped(),                             "'WindowYOnDropped()       ['T-6']\n'")
              + StrToStr(TerminalCompany(),                                 "'Terminal Company         ['L60']\n'")
              + StrToStr(TerminalName(),                                    "'Terminal Name            ['L60']\n'")
              + StrToStr(TerminalPath(),                                    "'Terminal Path            ['T256']\n'")
              + StrToStr(AccountCompany(),                                  "'Account Company          ['L60']\n'")
              + StrToStr(AccountServer(),                                   "'Account Server           ['L60']\n'")
              + NumberToStr(AccountNumber(),                                "'Account Number           ['T-8']\n'")
//              + StrToStr(AccountName(),                                     "'Account Name             ['L60']\n'")
              + StrToStr(AccountCurrency(),                                 "'Account Currency         ['L20']\n'")
              + NumberToStr(AccountLeverage(),                              "'Account Leverage         ['T-8']\n'")
              + NumberToStr(AccountBalance(),                               "'Account Balance          ['T-,11.2']\n'")
              + NumberToStr(AccountEquity(),                                "'Account Equity           ['T-,11.2']\n'")
              + NumberToStr(AccountProfit(),                                "'Account Profit           ['T-,11.2']\n'")
              + NumberToStr(AccountCredit(),                                "'Account Credit           ['T-,11.2']\n'")
              + NumberToStr(AccountFreeMargin(),                            "'Account Free Margin      ['T-,11.2']\n'")
              + NumberToStr(AccountFreeMarginMode(),                        "'Account Margin Mode      ['T-4']\n'")
              + NumberToStr(AccountMargin(),                                "'Account Margin           ['T-,11.2']\n'")
              + NumberToStr(AccountStopoutLevel(),                          "'Account Stopout Level    ['T-8']\n'")
              + NumberToStr(AccountStopoutMode(),                           "'Account Stopout Mode     ['T-4']\n'")
              + NumberToStr(IsConnected(),                                  "'Connected                ['T-4']\n'")
              + NumberToStr(IsDemo(),                                       "'Demo                     ['T-4']\n'")
              + NumberToStr(IsDllsAllowed(),                                "'DLLs On                  ['T-4']\n'")
              + NumberToStr(IsExpertEnabled(),                              "'Experts On               ['T-4']\n'")
              + NumberToStr(IsLibrariesAllowed(),                           "'Libraries On             ['T-4']\n'")
              + NumberToStr(IsOptimization(),                               "'Optimization             ['T-4']\n'")
              + NumberToStr(IsStopped(),                                    "'Stopped                  ['T-4']\n'")
              + NumberToStr(IsTesting(),                                    "'Testing                  ['T-4']\n'")
              + NumberToStr(IsTradeAllowed(),                               "'Trade Allowed            ['T-4']\n'")
              + NumberToStr(IsTradeContextBusy(),                           "'Trade Context Busy       ['T-4']\n'")
              + NumberToStr(IsVisualMode(),                                 "'Visual Mode              ['T-4']\n'")
              + NumberToStr(UninitializeReason(),                           "'Uninitialize Reason      ['T-4']\n\n\n'");

  return(vars);
}   

//+------------------------------------------------------------------+
int df(string s1="", string s2="", string s3="", string s4="", string s5="", string s6="", string s7="", string s8="",
          string s9="", string s10="", string s11="", string s12="", string s13="", string s14="", string s15="")     {
//+------------------------------------------------------------------+
// Outputs up to 15 values to the debug file (after creating the file, if it doesn't already exist)
  if (!PostDiagnosticInfo)    return(0);
  string out = StringTrimRight(StringConcatenate(s1, " ", s2, " ", s3, " ", s4, " ", s5, " ", s6, " ", s7, " ", s8, " ", 
                                                 s9, " ", s10, " ", s11, " ", s12, " ", s13, " ", s14, " ", s15));
  int h = FileOpen(dfname,FILE_CSV|FILE_READ|FILE_WRITE,'~');
  FileSeek(h,0,SEEK_END);
  FileWrite(h,out);
  FileClose(h);
  return(0);
}

//+------------------------------------------------------------------+
int ddf(string s1="", string s2="", string s3="", string s4="", string s5="", string s6="", string s7="", string s8="",
           string s9="", string s10="", string s11="", string s12="", string s13="", string s14="", string s15="")     {
//+------------------------------------------------------------------+
// Deletes and re-creates the debug file, and adds up to 15 values to it
  if (!PostDiagnosticInfo)    return(0);
  string out = StringTrimRight(StringConcatenate(s1, " ", s2, " ", s3, " ", s4, " ", s5, " ", s6, " ", s7, " ", s8, " ", 
                                                 s9, " ", s10, " ", s11, " ", s12, " ", s13, " ", s14, " ", s15));
  int h = FileOpen(dfname,FILE_CSV|FILE_WRITE,'~');
  FileWrite(h,out);
  FileClose(h);
  return(0);
}

//+------------------------------------------------------------------+
#include <hanover --- extensible functions (np).mqh>