!Report_v3






#property copyright "© RickD 2005-2006"
#property link      "www.e2e-fx.net"
#property show_inputs

//-----

#define template    "[ROOT]\\templates\\report.htm"
#define report      "[ROOT]\\experts\\files\\[ACCOUNT_NUM]rep.htm"

//-----

#import "shell32.dll"
  int ShellExecuteA(int hWnd, int lpVerb, string lpFile, int lpParameters, string lpDirectory, int nCmdShow);

#import "kernel32.dll"
  int GetModuleFileNameA(int hModule, int& buf[], int len);

  int _lcreat(string path, int attr);
  int _lopen(string path, int mode);
  int _lclose(int hFile);  
  int _llseek(int hFile, int offset, int origin);   
  int _lread(int hFile, int buf[], int len);
  int _lwrite(int hFile, string buf, int len);

#import


#define OF_READ             0x00000000
#define OF_WRITE            0x00000001
#define OF_READWRITE        0x00000002

#define HFILE_ERROR         0xFFFFFFFF


#define FILE_BEGIN          0
#define FILE_CURRENT        1
#define FILE_END            2


#define SW_SHOW             5

#define OP_BALANCE          6


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

void init() {
}

void deinit(){
}

void start() {
  int ts1 = GetTickCount();

  string root;
  int res = GetRoot(root);
  if (res == FALSE) return;

  //-----

  string html;
  res = GetTemplate(root, html);
  if (res == FALSE) return;
  
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Validate & Sort
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
  int Tickets[];
  int ticket = -1;
  int ind = 0;

  int cnt = HistoryTotal();
  ArrayResize(Tickets, cnt);
  
  for (int i=0; i<cnt; i++) {
    if (!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;

    ticket = OrderTicket();
    if (Validate(ticket)) {
      Tickets[ind] = ticket;
      ind++;
    }
  }
  
  ArrayResize(Tickets, ind);
  Sort(Tickets);
  
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Head
//------------------------------------------------------------------------------------

  html = str_replace(html, "<!--COMPANY-->", CompanyName());
  html = str_replace(html, "<!--ACC_NUMBER-->", AccountNumber());
  html = str_replace(html, "<!--ACC_NAME-->", AccountName());
  html = str_replace(html, "<!--CURRENCY-->", AccountCurrency());
  html = str_replace(html, "<!--LOCAL_TIME-->", time_format(LocalTime(), "d mon yyyy hh:mm"));

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Body
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  
  string row_tpl = str_substr(html, "<!--CLOSED_POSITIONS[-->", "<!--]CLOSED_POSITIONS-->");
  string section = "<!--CLOSED_POSITIONS[-->" + row_tpl + "<!--]CLOSED_POSITIONS-->";
  
  row_tpl = StringTrimLeft(row_tpl);
  row_tpl = StringTrimRight(row_tpl);
  
  //-----
    
  double depo = 0;
  double comm = 0;
  double swap = 0;
  double profit = 0;
  double initial_deposit = 0;
  
  double gross_profit = 0;
  double gross_loss = 0;
  
  double min_account_balance = 0;
  double max_account_balance = 0;
  double max_dd = 0;
  double max_dd_rel = 0;
  
  int trades_total = 0;
  int trades_short = 0;
  int trades_long = 0;
  int trades_profit = 0;
  int trades_loss = 0;
  
  int ticket0 = -1;
  double largest_profit_trade = 0;
  double largest_loss_trade = 0;
  double avg_profit_trade = 0;
  double avg_loss_trade = 0;
  
  int consecutive_wins_cnt = 0;
  int consecutive_losses_cnt = 0;
  double consecutive_wins_summ = 0;
  double consecutive_losses_summ = 0;
  int max_consecutive_wins_cnt = 0;
  int max_consecutive_losses_cnt = 0;
  double max_consecutive_wins_summ = 0;
  double max_consecutive_losses_summ = 0;
  
  double consecutive_profit_summ = 0;
  double consecutive_loss_summ = 0;
  int consecutive_profit_cnt = 0;
  int consecutive_loss_cnt = 0;
  double max_consecutive_profit_summ = 0;
  double max_consecutive_loss_summ = 0;
  int max_consecutive_profit_cnt = 0;
  int max_consecutive_loss_cnt = 0;

  string row = "";
  string rows[];
  int size = -1;
 
  cnt = ArraySize(Tickets);
  for (i=0; i<cnt; i++) {
    if (!OrderSelect(Tickets[i], SELECT_BY_TICKET, MODE_HISTORY)) continue;
    
    int dig = MarketInfo(OrderSymbol(), MODE_DIGITS);
    if (dig == 0) dig = 4;
  
    row = row_tpl;
    if (i%2 == 1) row = str_replace(row, "bgcolor=#FFFFFF", "bgcolor=#E0E0E0");
    row = str_replace(row, "<!--NUM-->", i+1);

    int type = OrderType();
    
    if (OrderType() == OP_BALANCE) {
      row = str_replace(row, "<!--TICKET-->", OrderTicket());
      row = str_replace(row, "<!--OPEN_TIME-->", TimeToStr(OrderOpenTime()));
      row = str_replace(row, "<!--TYPE-->", OrderTypeToStr(OrderType()));
      row = str_replace(row, "<!--LOTS-->", "");
      row = str_replace(row, "<!--SYMBOL-->", "");
      row = str_replace(row, "<!--OPEN_PRICE-->", "");
      row = str_replace(row, "<!--SL-->", "");
      row = str_replace(row, "<!--TP-->", "");
      row = str_replace(row, "<!--CLOSE_TIME-->", "");
      row = str_replace(row, "<!--CLOSE_PRICE-->", "");
      row = str_replace(row, "<!--COMISSION-->", "");
      row = str_replace(row, "<!--SWAP-->", "");
      row = str_replace(row, "<!--PROFIT-->", number_format(OrderProfit(), 2, ".", " "));
      row = str_replace(row, "<!--COMMENT-->", OrderComment());
      
      row = str_replace(row, "mso-number-format:#\\.##;", "mso-number-format:0\\.00;");
      
      depo += OrderProfit();
      if (i == 0 && OrderProfit() > 0) initial_deposit = OrderProfit();
    }
    else {
      bool cancelled = (type == OP_BUYSTOP || type == OP_SELLSTOP || type == OP_BUYLIMIT || type == OP_SELLLIMIT);

      row = str_replace(row, "<!--TICKET-->", OrderTicket());
      row = str_replace(row, "<!--OPEN_TIME-->", TimeToStr(OrderOpenTime()));
      row = str_replace(row, "<!--TYPE-->", OrderTypeToStr(OrderType()));
      row = str_replace(row, "<!--LOTS-->", DoubleToStr(OrderLots(), 2));
      row = str_replace(row, "<!--SYMBOL-->", OrderSymbol());
      row = str_replace(row, "<!--OPEN_PRICE-->", DoubleToStr(OrderOpenPrice(), dig));
      row = str_replace(row, "<!--SL-->", DoubleToStr(OrderStopLoss(), dig));
      row = str_replace(row, "<!--TP-->", DoubleToStr(OrderTakeProfit(), dig));
      row = str_replace(row, "<!--CLOSE_TIME-->", TimeToStr(OrderOpenTime()));
      row = str_replace(row, "<!--CLOSE_PRICE-->", DoubleToStr(OrderClosePrice(), dig));
      row = str_replace(row, "<!--COMISSION-->", number_format(OrderCommission(), 2, ".", " "));
      row = str_replace(row, "<!--SWAP-->", number_format(OrderSwap(), 2, ".", " "));
      
      if (cancelled) {
        row = str_replace(row, "<!--PROFIT-->", "");
      }
      else {
        row = str_replace(row, "<!--PROFIT-->", number_format(OrderProfit(), 2, ".", " "));
      }
      
      row = str_replace(row, "<!--COMMENT-->", OrderComment());
      
      row = str_replace(row, "mso-number-format:#\\.##;", "mso-number-format:0\\." + str_repeat('0', dig) + ";");

      //-----

      if (!cancelled) {
        comm += OrderCommission();
        swap += OrderSwap();
        profit += OrderProfit();
        
        double order_profit = OrderCommission() + OrderSwap() + OrderProfit();
        
        //-----
        
        if (order_profit > 0) gross_profit += order_profit;
        if (order_profit < 0) gross_loss += order_profit;
        
        double account_balance = gross_profit + gross_loss + depo;
        
        if (ticket0 == -1) {
          min_account_balance = account_balance;
        }
        else {
          min_account_balance = MathMin(min_account_balance, account_balance);
        }
              
        if (account_balance > max_account_balance) {
          max_account_balance = account_balance;
        }
        else {
          if (account_balance > 0 && max_account_balance - account_balance > max_dd) {
            max_dd = max_account_balance - account_balance;
            max_dd_rel = 100*max_dd/max_account_balance;
          }
        }
        
        //-----
      
        trades_total++;
        if (type == OP_BUY) trades_long++;
        if (type == OP_SELL) trades_short++;
        
        if (order_profit < 0) {
          trades_loss++;
          avg_loss_trade += order_profit;
        }
        
        if (order_profit >= 0) {
          trades_profit++;
          avg_profit_trade += order_profit;
        }
   
        if (ticket0 == -1) {
          largest_profit_trade = order_profit;
          largest_loss_trade = order_profit;
        }
        else {        
          if (order_profit > 0) {
            largest_profit_trade = MathMax(largest_profit_trade, order_profit);
          }
          
          if (order_profit < 0) {
            largest_loss_trade = MathMin(largest_loss_trade, order_profit);
          }
        }
        
        //-----
        
        if (order_profit >= 0) {
          consecutive_losses_cnt = 0;
          consecutive_losses_summ = 0;
        
          consecutive_wins_cnt++;
          consecutive_wins_summ += order_profit;
          
          if (consecutive_wins_cnt > max_consecutive_wins_cnt || 
             (consecutive_wins_cnt == max_consecutive_wins_cnt && max_consecutive_wins_summ < consecutive_wins_summ)) {
            max_consecutive_wins_cnt = consecutive_wins_cnt;
            max_consecutive_wins_summ = consecutive_wins_summ;
          }
        }
        
        if (order_profit < 0) {
          consecutive_wins_cnt = 0;
          consecutive_wins_summ = 0;
        
          consecutive_losses_cnt++;
          consecutive_losses_summ += order_profit;
          
          if (consecutive_losses_cnt > max_consecutive_losses_cnt ||
             (consecutive_losses_cnt == max_consecutive_losses_cnt && max_consecutive_losses_summ > consecutive_losses_summ)) {
            max_consecutive_losses_cnt = consecutive_losses_cnt;
            max_consecutive_losses_summ = consecutive_losses_summ;
          }
        }
        
        //-----
        
        if (order_profit >= 0) {
          consecutive_loss_summ = 0;
          consecutive_loss_cnt = 0;

          consecutive_profit_summ += order_profit;        
          consecutive_profit_cnt++;
          
          if (consecutive_profit_summ > max_consecutive_profit_summ) {
            max_consecutive_profit_summ = consecutive_profit_summ;
            max_consecutive_profit_cnt = consecutive_profit_cnt;
          }
        }
        
        if (order_profit < 0) {
          consecutive_profit_summ = 0;
          consecutive_profit_cnt = 0;

          consecutive_loss_summ += order_profit;        
          consecutive_loss_cnt++;
          
          if (consecutive_loss_summ < max_consecutive_loss_summ) {
            max_consecutive_loss_summ = consecutive_loss_summ;
            max_consecutive_loss_cnt = consecutive_loss_cnt;
          }
        }
        
        if (ticket0 == -1) ticket0 = OrderTicket();
     
      } //cancelled      
    }
    
    row = row + "\r\n";

    size = ArraySize(rows);
    ArrayResize(rows, size+1);
    rows[size] = row;
  }
 
  if (trades_profit > 0) avg_profit_trade /= trades_profit;
  if (trades_loss > 0) avg_loss_trade /= trades_loss; 
  
  
//  rows = StringTrimRight(rows);
//  html = str_replace(html, section, rows);

  //-----  

  row_tpl = str_substr(html, "<!--CLOSED_TOTAL[-->", "<!--]CLOSED_TOTAL-->");
  section = "<!--CLOSED_TOTAL[-->" + row_tpl + "<!--]CLOSED_TOTAL-->";
  
  row_tpl = StringTrimLeft(row_tpl);
  row_tpl = StringTrimRight(row_tpl);
  
  row = row_tpl;

  //if (i%2 == 1) row = str_replace(row, "bgcolor=#FFFFFF", "bgcolor=#E0E0E0");
  
  row = str_replace(row, "<!--COMISSION-->", number_format(comm, 2, ".", " "));
  row = str_replace(row, "<!--SWAP-->", number_format(swap, 2, ".", " "));
  row = str_replace(row, "<!--PROFIT-->", number_format(profit, 2, ".", " "));
  
  html = str_replace(html, section, row);
  
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Summary
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

  html = str_replace(html, "<!--DEPOSIT-->", number_format(depo, 2, ".", " "));
  html = str_replace(html, "<!--CLOSED_PL-->", number_format(comm+swap+profit, 2, ".", " "));
  html = str_replace(html, "<!--BALANCE-->", number_format(depo+comm+swap+profit, 2, ".", " "));
  
  double total_net_profit = gross_profit + gross_loss;
  
  html = str_replace(html, "<!--GROSS_PROFIT-->", number_format(gross_profit, 2, ".", " "));
  html = str_replace(html, "<!--GROSS_LOSS-->", number_format(gross_loss, 2, ".", " "));
  html = str_replace(html, "<!--TOTAL_NET_PROFIT-->", number_format(total_net_profit, 2, ".", " "));

  double absolute_dd = 0;
  if (initial_deposit > 0) {
    absolute_dd = initial_deposit - min_account_balance;
    html = str_replace(html, "<!--ABSOLUTE_DRAWDOWN-->", number_format(absolute_dd, 2, ".", " "));
  }
  else {
    html = str_replace(html, "<!--ABSOLUTE_DRAWDOWN-->", "*");
  }  
  
  html = str_replace(html, "<!--MAXIMAL_DRAWDOWN-->", number_format(max_dd, 2, ".", " ") + " (" + number_format(max_dd_rel, 1, ".", " ") + "%)");
  
  double profit_factor = 0;
  if (NormalizeDouble(gross_loss, 2) != 0) {
    profit_factor = MathAbs(gross_profit/gross_loss);
    html = str_replace(html, "<!--PROFIT_FACTOR-->", number_format(profit_factor, 2, ".", " "));
  }
  else {
    html = str_replace(html, "<!--PROFIT_FACTOR-->", "*");
  }
  
  double expected_payoff = 0;
  if (trades_total > 0) expected_payoff = total_net_profit/trades_total;

  html = str_replace(html, "<!--EXPECTED_PAYOFF-->", number_format(expected_payoff, 2, ".", " "));


  double trades_short_rel = 0;
  double trades_long_rel = 0;
  double trades_profit_rel = 0;
  double trades_loss_rel = 0;      

  if (trades_total > 0) {
    trades_short_rel = 100*trades_short/trades_total;
    trades_long_rel = 100*trades_long/trades_total;
    trades_profit_rel = 100*trades_profit/trades_total;
    trades_loss_rel = 100*trades_loss/trades_total;
  }
  
  html = str_replace(html, "<!--TRADES_TOTAL-->", number_format(trades_total, 0, ".", " "));
  html = str_replace(html, "<!--TRADES_SHORT-->", number_format(trades_short, 0, ".", " ") + " (" + DoubleToStr(trades_short_rel, 1) + "%)");
  html = str_replace(html, "<!--TRADES_LONG-->", number_format(trades_long, 0, ".", " ") + " (" + DoubleToStr(trades_long_rel, 1) + "%)");
  html = str_replace(html, "<!--TRADES_PROFIT-->", number_format(trades_profit, 0, ".", " ") + " (" + DoubleToStr(trades_profit_rel, 1) + "%)");
  html = str_replace(html, "<!--TRADES_LOSS-->", number_format(trades_loss, 0, ".", " ") + " (" + DoubleToStr(trades_loss_rel, 1) + "%)");
  
  html = str_replace(html, "<!--LARGET_PROFIT_TRADE-->", number_format(largest_profit_trade, 2, ".", " "));
  html = str_replace(html, "<!--LARGET_LOSS_TRADE-->", number_format(largest_loss_trade, 2, ".", " "));
  html = str_replace(html, "<!--AVERAGE_PROFIT_TRADE-->", number_format(avg_profit_trade, 2, ".", " "));
  html = str_replace(html, "<!--AVERAGE_LOSS_TRADE-->", number_format(avg_loss_trade, 2, ".", " "));

  html = str_replace(html, "<!--MAX_CONS_WINS-->", number_format(max_consecutive_wins_cnt, 0, ".", " ") + " (" + number_format(max_consecutive_wins_summ, 2, ".", " ") + ")");
  html = str_replace(html, "<!--MAX_CONS_LOSSES-->", number_format(max_consecutive_losses_cnt, 0, ".", " ") + " (" + number_format(max_consecutive_losses_summ, 2, ".", " ") + ")");
  html = str_replace(html, "<!--MAX_CONS_PROFIT-->", number_format(max_consecutive_profit_summ, 2, ".", " ") + " (" + number_format(max_consecutive_profit_cnt, 0, ".", " ") + ")");
  html = str_replace(html, "<!--MAX_CONS_LOSS-->", number_format(max_consecutive_loss_summ, 2, ".", " ") + " (" + number_format(max_consecutive_loss_cnt, 0, ".", " ") + ")");
      
  //-----
  
  string html_part1 = str_substr(html, "", "<!--CLOSED_POSITIONS[-->");
  string html_part2 = str_substr(html, "<!--]CLOSED_POSITIONS-->", "");
  
  //-----
   
  WriteRes(root, html_part1, rows, html_part2); 
  
  int ts2 = GetTickCount();
  Print("Run time: ", ts2-ts1, " msec");
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

int GetRoot(string& root) 
{
  int buf[255];
  int res = GetModuleFileNameA(0, buf, 4*255);
  if (res == 0) {
    Alert("GetRoot: GetModuleFileName failed!");
    return (FALSE);
  }

  root = "";
  int ch = -1;
  
  for (int i=0; i<res; i++) {
    if (i%4 == 0) ch = buf[i/4] & 0xFF;
    if (i%4 == 1) ch = (buf[i/4] >> 8) & 0xFF;
    if (i%4 == 2) ch = (buf[i/4] >> 16) & 0xFF;
    if (i%4 == 3) ch = (buf[i/4] >> 24) & 0xFF;

    root = root + CharToStr(ch);
  }
  
  root = str_replace(root, "\\terminal.exe", "");

  return (TRUE);
}

int GetTemplate(string root, string& html) 
{
  string path = str_replace(template, "[ROOT]", root);

  int hFile = _lopen(path, OF_READ);
  if (hFile == HFILE_ERROR) {
    Alert("GetTemplate: _lopen('" + path +"', OF_READ) failed!");  
    return (FALSE);
  }
  
  int size = _llseek(hFile, 0, FILE_END);
  _llseek(hFile, 0, FILE_BEGIN);

  int buf[];
  ArrayResize(buf, size/4 + 1);

  int res = _lread(hFile, buf, size);
  if (res == HFILE_ERROR) {
    Alert("GetTemplate: _lread failed!");
    return (FALSE);
  }

  html = "";  
  int ch = -1;
    
  for (int i=0; i<res; i++) {
    if (i%4 == 0) ch = buf[i/4] & 0xFF;
    if (i%4 == 1) ch = (buf[i/4] >> 8) & 0xFF;
    if (i%4 == 2) ch = (buf[i/4] >> 16) & 0xFF;
    if (i%4 == 3) ch = (buf[i/4] >> 24) & 0xFF;

    html = html + CharToStr(ch);
  }

  _lclose(hFile);

  return (TRUE);
}

void Sort(int& Tickets[]) 
{
  int cnt = ArraySize(Tickets);
  for (int i=0; i < cnt; i++) {
    for (int j=i+1; j < cnt; j++) {
      int res = Compare(Tickets[i], Tickets[j]);

      if (res == -1) {
        int ticket = Tickets[i];
        Tickets[i] = Tickets[j];
        Tickets[j] = ticket;        
      }
    }
  }  
}

int WriteRes(string root, string html_part1, string& rows[], string html_part2)
{
  string path = str_replace(report, "[ROOT]", root);
  path = str_replace(path, "[ACCOUNT_NUM]", AccountNumber());

  int hFile = _lcreat(path, 0);
  if (hFile == HFILE_ERROR) {
    Alert("WriteRes: _lcreat('" + path + "', 0) failed!");
    return (FALSE);
  }
  
  _lwrite(hFile, html_part1, StringLen(html_part1));

  int size = ArraySize(rows);
  for (int i=0; i<size; i++) {
    _lwrite(hFile, rows[i], StringLen(rows[i]));
  }
  
  _lwrite(hFile, html_part2, StringLen(html_part2));
  _lclose(hFile);

  ShellExecuteA(0, 0, path, 0, "", SW_SHOW);  

  return (TRUE);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

string str_replace(string subject, string search, string replace) 
{
  string left_part = "";
  string right_part = "";

  for (;;) {
    int pos = StringFind(subject, search);
    if (pos == -1) break;
    
    left_part = "";
    right_part = "";
    
    if (pos > 0) left_part = StringSubstr(subject, 0, pos);
    if (pos+1 < StringLen(subject)) right_part = StringSubstr(subject, pos+StringLen(search));

    subject = left_part + replace + right_part;
  }

  return (subject);
}

string str_substr(string text, string marker1, string marker2)
{
  int pos = -1;
  int pos2 = -1;
    
  if (marker1 == "") {
    pos = 0;
  } 
  else {
    pos = StringFind(text, marker1, 0);
    if (pos == -1) return ("");
  }
  
  pos += StringLen(marker1);

  if (marker2 == "") {
    pos2 = StringLen(text) - 1;
  } else {
    pos2 = StringFind(text, marker2, pos);
    if (pos2 == -1) return ("");
  }

  string res = StringSubstr(text, pos, pos2-pos);
  return (res);
}

string str_repeat(int char, int cnt)
{
  string res = "";
  for (int i=0; i<cnt; i++) {
    res = res + CharToStr(char);
  }
  
  return (res);
}

string str_if(bool cond, string val1, string val2) 
{
  if (cond) return (val1);
  return (val2);
}

string number_format(double number, int decimals, string dec_point, string thousands_sep)
{
  string str = DoubleToStr(number, decimals);
  string res = "";

  int len = StringLen(str);
  int pos = StringFind(str, dec_point);
  if (pos > 0) {
    len = pos;
    res = StringSubstr(str, pos);
  }
  
  for (int i = len-1; i >= 0; i--) {
    res = StringSubstr(str, i, 1) + res;
    
    if (i > 0 && (len-i)%3 == 0) {
      if (StringSubstr(str, i-1, 1) != "-") res = thousands_sep + res;
    }
  }

  return (res);
}

string time_format(datetime tm, string format) 
{
  string month[12] = {"Jan", "Feb", "March", "April", "May", "June", "July", "Aug",
    "Sept", "Oct", "Nov", "Dec"};
  
  string res = format;  
  res = str_replace(res, "d", TimeDay(tm));
  res = str_replace(res, "mon", month[TimeMonth(tm)-1]);
  res = str_replace(res, "yyyy", TimeYear(tm));
  
  int hh = TimeHour(tm);
  int mm = TimeMinute(tm);
  
  res = str_replace(res, "hh", str_if(hh < 10, "0" + hh, hh));
  res = str_replace(res, "mm", str_if(mm < 10, "0" + mm, mm));

  return (res);
}

string OrderTypeToStr(int type) 
{
  if (type == OP_BUY) return ("buy");
  if (type == OP_SELL) return ("sell");
  if (type == OP_BUYLIMIT) return ("buy limit");
  if (type == OP_SELLLIMIT) return ("sell limit");
  if (type == OP_BUYSTOP) return ("buy stop");
  if (type == OP_SELLSTOP) return ("sell stop");
  if (type == OP_BALANCE) return ("balance");

  return ("?");
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Compare
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

int Compare(int ticket1, int ticket2) 
{
  if (!OrderSelect(ticket1, SELECT_BY_TICKET, MODE_HISTORY)) return (0);
  datetime tm1 = OrderCloseTime();
  double Profit1 = OrderProfit();
  
  if (!OrderSelect(ticket2, SELECT_BY_TICKET, MODE_HISTORY)) return (0);
  datetime tm2 = OrderCloseTime();
  double Profit2 = OrderProfit();
  
  
  if (tm1 < tm2) return (1);
  if (tm1 > tm2) return (-1);

/*
  if (Profit1 > Profit2) return (1);
  if (Profit1 < Profit2) return (-1);
*/  
  return (0);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Validate
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

bool Validate(int ticket) 
{
  if (!OrderSelect(ticket, SELECT_BY_TICKET, MODE_HISTORY)) return (false);
  //if (OrderType() == OP_BALANCE) return (false);

//  if (StringFind(OrderComment(), "[tp]") == -1) return(true);
//  if (OrderOpenTime() < StrToTime("2005.05.27 22.20")) return(false); 
//  if (OrderOpenTime() > StrToTime("2005.06.13 20.00")) return(false); 
//  if (TimeDay(OrderOpenTime()) == 13) return(true);
//  if (OrderProfit() >= 0) return(true);
  
  //if (OrderType() == OP_BUYLIMIT || OrderType() == OP_SELLLIMIT) return (false);
  //return (OrderOpenTime() < StrToTime("2006.01.30 00.00"));
 
  return (true); 
  //return (OrderSymbol() == "NZDUSD");
}








Sample





Analysis



Market Information Used:



Indicator Curves created:


Indicators Used:



Custom Indicators Used:
shell32
kernel32

Order Management characteristics:


Other Features:

It issuies visual alerts to the screen