Random Trading

//+------------------------------------------------------------------+//|                                                       Random.mq4 |//|                                                             amba |//|                                                       2009-12-07 |//+------------------------------------------------------------------+   /*  Простой скрипт для иллюстрации виртуальной мультивалютной торговли. Запускаем его на любой валюте.      При этом торговля будет вестить по  валютам, указанным в массиве. Требуется наличие котировок по выбранным инструментам периода текущего графика. Рекомендую М15. */#property copyright "amba"#property link      "http://www.mql4.com/ru/users/Amba"#property show_inputs   extern datetime date.start=D'2009.11.01'; extern datetime date.end= D'2009.12.01'; extern double SL = 0.50; extern double TP = 0.50; extern bool IsPercent = true;   #include <ArrayVO.mq4>   int MagicNum=0;   datetime LastDT=0;   // торгуемые инструментыstring symb[]={ "USDJPY","EURUSD", "EURGBP"};//, "GBPUSD", "USDCHF"};};//   //+------------------------------------------------------------------+//| expert initialization function                                   |//+------------------------------------------------------------------+int init(){     MagicNum=GetTickCount();     MathSrand(GetTickCount());     return(0); }   //+------------------------------------------------------------------+//| expert deinitialization function                                 |//+------------------------------------------------------------------+int deinit(){     // закрытие всех открытых     v.CloseAllOrders();     // вывод массивов в CSV.      // %METATRADER_FOLDER%\experts\files\deb.Random.hist.csv содержит историю торговли     // %METATRADER_FOLDER%\experts\files\deb.Random.trade.csv если всё закрыли как положено - он пуст       DebugPrintArrays("Random");     return(0); }//+------------------------------------------------------------------+//| expert start function                                            |//+------------------------------------------------------------------+int start(){     int _per=Period()*60;     datetime dt=date.start-_per;     while(date.end>dt)     {         dt+=_per;         // Отобразим ход выполнения          string cmnt = StringConcatenate("Current: ",TimeToStr(dt,TIME_DATE),"\nIn trade: ",v.OrdersTotal(),"\nIn hist: ",v.OrdersHistoryTotal());         Comment(cmnt);         // пересчет массива открытых ордеров на каждом баре         RecalcTradeArray(dt);              if(v.OrdersTotal()>0) continue;         // случайным образом выбираем направление торговли Бай/Селл         int op=MathRound(MathRand()/32767.0);         int op1=1-op;           // сигнал, противоположный выбранному              // случайным образом выбираем инструмент из числа предопределенных         int isymb = MathRound((ArraySize(symb)-1)*MathRand()/32767.0);         string sy = symb[isymb];              double pp,sl,tp;   // Цены открытия, стоп-лосс и тэйк-профит              Print("Operation: ", op, " symbol ",sy);              // определяем смещение бара         int sh=iBarShift(sy,0,dt,true);         // Если бар не нашли - продолжим         if(sh<0)              continue;           int spread=MarketInfo(sy,MODE_SPREAD);         double _point=MarketInfo(sy,MODE_POINT);              // считаем цену открытия бара ценой открытия ордера         pp=iOpen(sy,0,sh)+spread*op1*_point;                  if(IsPercent)         {             sl=pp * (1 - IIF(op==OP_BUY,1,-1) * SL/100);             tp=pp * (1 + IIF(op==OP_BUY,1,-1) * TP/100) ;         }          else         {             sl=pp-IIF(op==OP_BUY,1,-1)* SL *_point;             tp=pp+IIF(op==OP_BUY,1,-1)* TP *_point;         }              // установка "текущего времени" для эмуляции сделок         SetCurrentDateTime(dt);                  v.SetOrder(sy, op, 0.1,pp,sl ,tp, MagicNum, dt+86400, StringConcatenate("Params",csv.dem,SL,csv.dem,TP));                 }        return(0); }   //+------------------------------------------------------------------+

//+------------------------------------------------------------------+//|                                                      ArrayVO.mq4 |//|                                                             amba |//|                                                       2009-12-12 |//|                                                        ver. 1.03 |//| Библиотека предназначена для ведения виртуальной торговли.       |//|                                                                  |//| Реализована замена стандартных функций по работе с ордерами      |//| Order*() на  аналогичные v.Order*().                             |//|                                                                  |//| Реализованы функции загрузки/выгрузки массивов ордеров в бинарном|//| и текстовом виде.                                                |//|                                                                  |//| В библиотеке использованы незначительно модифицированные функции |//| (автор Ким Игорь В. aka KimIV,  http://www.kimiv.ru) по работе с |//| ордерами, а также идея работы с массивом номеров предварительно  |//|отфильтрованных ордеров (автора не знаю, но тоже очень благодарен)|                                                                 |//|                                                                  |//|                                                                  |//+------------------------------------------------------------------+#property copyright "amba"#property link      "http://www.mql4.com/ru/users/Amba"//#property library#include <stdlib.mqh>   //количество колонок в массивах ордеров#define MAX_FIELDS 17                      // массивы ордеров действующих и закрытых//      значения типа doubledouble  aHistory[][MAX_FIELDS],         aTrade[][MAX_FIELDS];          //      названия символов и комментарии к ордерамstring  aHistory.strings[][2],         aTrade.strings[][2];          //      счетчики количества ордеровint aHistory.cnt = 0,     aTrade.cnt = 0;   datetime aTrade.CurrentDT=0;          // константы номеров колонок массивов//      стандартные параметры ордеров#define PROP.Ticket     0#define PROP.OpenDT     1#define PROP.Type       2#define PROP.Lots       3#define PROP.OpenPrice  4#define PROP.SL         5#define PROP.TP         6#define PROP.Magic      7#define PROP.ExpDT      8#define PROP.ClosePrice 9#define PROP.CloseDT    10#define PROP.Profit     11          // в валюте//      дополнительные параметры ордеров#define PROP.LastRecalcDT   12      // дата/время последнего пересчета ордера#define PROP.AccBalance     13      // в валюте#define PROP.AccEquity      14      // в валюте#define PROP.MaxDD          15      // в пунктах#define PROP.MaxProfit      16      // в пунктах// константы номеров колонок строковых массивов#define PROP.Symbol      0#define PROP.Comment     1            int    Slippage      = 5;           // Проскальзывание цены - рудимент от реальной торговли   string csv.dem = ",";               // CSV разделитель   int aTrade.p=-1;                    // указатель позиции в массиве текущих ордеровint aHistory.p=-1;                  // указатель позиции в массиве закрытых ордеровint who.selected=0;                 // селектор вида массива {MODE_TRADES|MODE_HISTORY} int next_t=0;                       // счетчик генератора номеров ордеров   bool aTrade.CalcBalance = false;    // Флаг расчета баланса и эквити       //+------------------------------------------------------------------+//|          Группа функций по работе с ордерами                     |//+------------------------------------------------------------------+   // константы определяют использование различных ГРУПП операций ордеров:#define TICKET_ORD -3   // отложенные ордера - OP_BUYLIMIT OP_SELLLIMIT OP_BUYSTOP OP_SELLSTOP#define TICKET_POS -2   // открытые позиции  - OP_BUY OP_SELL#define TICKET_ALL -1   // любой ордер   //+------------------------------------------------------------------+//| Проверяет соответствие текущего выбранного ордера указанным в    |//| параметрах условиям                                              |//| Возвращаемые значения: true|false (соответствует|нет)            |//| Параметры:                                                       |//|   (дефолтные значения означают отсутствие условий по данному     |//|    признаку)                                                     |//|   sy - название символа                                          |//|        (напр. "EURUSD", или "0" - текущий, "" - любой)           |//|   op - тип ордера                                                |//|     op={[OP_BUY..OP_SELLSTOP]|TICKET_POS|TICKET_ORD|TICKET_ALL}  |//|   mn - Magic Number                                              |//|   ot - время открытия. Будут выбраны ордера с временем открытия, |//|        меньшим или равным указанному                             |//|                                                                  |//| Используется в функциях перебора, фильтрации ордеров             |//+------------------------------------------------------------------+bool v.IsOrderFor(string sy="", int op=-1, int mn=-1, datetime ot=0){    int ty=v.OrderType();    if (sy=="0") sy=Symbol();    if ((v.OrderSymbol()==sy || sy=="")     && (ty==op || op==TICKET_ALL || (op==TICKET_POS && ty>=0 && ty<2) || (op==TICKET_ORD && ty>1 && ty<6) ) )         if (mn<0 || v.OrderMagicNumber()==mn)           if (ot<=v.OrderOpenTime())             return(true);    return(false); }   //+------------------------------------------------------------------+//| По заданным условиям проверяет - есть ли хотя бы один ордер, со- |//| ответствующий условиям поиска                                    |//| Возвращаемые значения: true|false (есть|нет)                     |//| Параметры:  см. описание IsOrderFor()                            |//|                                                                  |//+------------------------------------------------------------------+bool v.ExistOrders(string sy="", int op=-1, int mn=-1, datetime ot=0){   int i, k=v.OrdersTotal(), c=0;     for (i=0; i<k; i++)      if (v.OrderSelect(i, SELECT_BY_POS, MODE_TRADES)==true)        if(v.IsOrderFor(sy,op,mn,ot))           return(true);   return(false); }   //+------------------------------------------------------------------+//| По заданным условиям подсчитывает - сколько ордеров соответствует|//| условиям поиска                                                  |//| Возвращаемые значения: количество ордеров                        |//| Параметры:  см. описание IsOrderFor()                            |//|                                                                  |//+------------------------------------------------------------------+int v.CountAllOrders(string sy="", int op=-1, int mn=-1, datetime ot=0){   int i, k=v.OrdersTotal(), c=0;     for (i=0; i<k; i++)      if (v.OrderSelect(i, SELECT_BY_POS, MODE_TRADES)==true)        if(v.IsOrderFor(sy,op,mn,ot)==true)           c++;   return(c); }   //+------------------------------------------------------------------+//| По заданным условиям ищет ордера и заполняет переданный массив   |//| номерами найденных ордеров                                       |//| Возвращаемые значения: количество ордеров                        |//| Параметры:                                                       |//|     Ticket - одномерный массив, заполняется номерами ордеров     | //|     остальные параметры см. описание IsOrderFor()                |//|                                                                  |//+------------------------------------------------------------------+int v.CreateTicketArray(int& Ticket[], string sy="", int op=-1, int mn=-1, datetime ot=0){     int total=v.OrdersTotal(), i, c=0; if (total<=0) return (0);     for(i=0;i<total;i++)       if(v.OrderSelect(i, SELECT_BY_POS)==true)         if(v.IsOrderFor(sy,op,mn,ot)==true) {ArrayResize(Ticket,c+1);Ticket[c] = v.OrderTicket(); c++; }     return (c); }   //+------------------------------------------------------------------+//| По заданным условиям ищет ордера и закрывает/удаляет их.         |//| Цена закрытия - Close на баре даты последнего пересчета ордера.  |//| Сначала закрываются профитные сделки, потом - все остальные.     |//| Возвращаемые значения: нет                                       |//| Параметры: см. описание IsOrderFor()                             |//|                                                                  |//+------------------------------------------------------------------+void v.CloseAllOrders(string sy="", int op=-1, int mn=-1, datetime ot=0){     int i, total = v.OrdersTotal();    if (total<=0) return;     int Ticket[];     total = v.CreateTicketArray(Ticket, sy, op, mn, ot);     if (total<=0) return; //Заглушка          string sym;     double point;     int spread;     // Закрываем только профитные сделки     for (i=0; i<total; i++)         {             if(v.OrderSelect(Ticket[i], SELECT_BY_TICKET) && who.selected == MODE_TRADES && v.OrderProfit()>0)         {             int ty=v.OrderType();             if(ty<2)             {                 sym     = v.OrderSymbol();                 point   = MarketInfo(sym, MODE_POINT);                 spread  = MarketInfo(sym,MODE_SPREAD);                 aTrade.CurrentDT=GetDoublePropArray(PROP.LastRecalcDT);                 double p=iClose(v.OrderSymbol(),0,iBarShift(v.OrderSymbol(),0,GetDoublePropArray(PROP.LastRecalcDT)));                 if(ty==OP_BUY)                     v.OrderClose(Ticket[i], v.OrderLots(), p, 3 );                  else if(ty==OP_SELL)                     v.OrderClose(Ticket[i], v.OrderLots(), p + point*spread, 3 );              } else v.OrderDelete(Ticket[i]);         }     }     // ... а теперь все остальные     for (i=0; i<total; i++)         {             if(v.OrderSelect(Ticket[i], SELECT_BY_TICKET) && who.selected == MODE_TRADES)             {             ty=v.OrderType();             if(ty<2)             {                 sym     = v.OrderSymbol();                 point   = MarketInfo(sym, MODE_POINT);                 spread  = MarketInfo(sym,MODE_SPREAD);                 aTrade.CurrentDT=GetDoublePropArray(PROP.LastRecalcDT);                 p=iClose(v.OrderSymbol(),0,iBarShift(v.OrderSymbol(),0,GetDoublePropArray(PROP.LastRecalcDT)));                 if(ty==OP_BUY)                     v.OrderClose(Ticket[i], v.OrderLots(),  p, 3);                  else if(ty==OP_SELL)                     v.OrderClose(Ticket[i], v.OrderLots(),  p + point*spread, 3);              } else v.OrderDelete(Ticket[i]);         }     }             return; }     //+----------------------------------------------------------------------------+//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |//+----------------------------------------------------------------------------+//|  Версия   : 01.09.2005                                                     |//|  Описание : Возвращает наименование торговой операции                      |//+----------------------------------------------------------------------------+//|  Параметры:                                                                |//|    op - идентификатор торговой операции                                    |//+----------------------------------------------------------------------------+string GetNameOP(int op) {   switch (op) {     case OP_BUY      : return("Buy");     case OP_SELL     : return("Sell");     case OP_BUYLIMIT : return("Buy Limit");     case OP_SELLLIMIT: return("Sell Limit");     case OP_BUYSTOP  : return("Buy Stop");     case OP_SELLSTOP : return("Sell Stop");     default          : return("Unknown Operation");   }}   //+----------------------------------------------------------------------------+//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |//+----------------------------------------------------------------------------+//|  Версия   : 01.09.2005                                                     |//|  Описание : Возвращает наименование таймфрейма                             |//+----------------------------------------------------------------------------+//|  Параметры:                                                                |//|    TimeFrame - таймфрейм (количество секунд)      (0 - текущий ТФ)         |//+----------------------------------------------------------------------------+string GetNameTF(int TimeFrame=0) {   if (TimeFrame==0) TimeFrame=Period();   switch (TimeFrame) {     case PERIOD_M1:  return("M1");     case PERIOD_M5:  return("M5");     case PERIOD_M15: return("M15");     case PERIOD_M30: return("M30");     case PERIOD_H1:  return("H1");     case PERIOD_H4:  return("H4");     case PERIOD_D1:  return("Daily");     case PERIOD_W1:  return("Weekly");     case PERIOD_MN1: return("Monthly");     default:             return("UnknownPeriod");   }}   //+----------------------------------------------------------------------------+//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |//+----------------------------------------------------------------------------+//|  Версия   : 01.09.2005                                                     |//|  Описание : Вывод сообщения в коммент и в журнал                           |//+----------------------------------------------------------------------------+//|  Параметры:                                                                |//|    m - текст сообщения                                                     |//+----------------------------------------------------------------------------+void Message(string m) {   Comment(m);   if (StringLen(m)>0) Print(m); }   //+----------------------------------------------------------------------------+//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |//+----------------------------------------------------------------------------+//|  Версия   : 13.03.2008                                                     |//|  Описание : Установка ордера.                                              |//+----------------------------------------------------------------------------+//|  Параметры:                                                                |//|    sy - наименование инструмента   (NULL или "" - текущий символ)          |//|    op - операция                                                           |//|    ll - лот                                                                |//|    pp - цена                                                               |//|    sl - уровень стоп                                                       |//|    tp - уровень тейк                                                       |//|    mn - Magic Number                                                       |//|    ex - Срок истечения                                                     |//+----------------------------------------------------------------------------+int v.SetOrder(string sy, int op, double ll, double pp,               double sl=0, double tp=0, int mn=0, datetime ex=0, string lsComm="") {   datetime ot;   double   pa, pb, mp;   int      err, it, ticket, msl;   if(lsComm=="")   lsComm=WindowExpertName()+" "+GetNameTF(Period());   if (sy=="" || sy=="0") sy=Symbol();   msl=MarketInfo(sy, MODE_STOPLEVEL);      int dg = MarketInfo(sy, MODE_DIGITS);   pp=NormalizeDouble(pp, dg);   sl=NormalizeDouble(sl, dg);   tp=NormalizeDouble(tp, dg);      if (ex>0 && ex<aTrade.CurrentDT) ex=0;     ticket=v.OrderSend(sy, op, ll, pp, Slippage, sl, tp, lsComm, mn, ex,0);     //Print(GetLastError());     if (ticket>0) {       return(ticket);     }      return(0); }   //+----------------------------------------------------------------------------+//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |//+----------------------------------------------------------------------------+//|  Версия   : 28.11.2006                                                     |//|  Описание : Модификация одного предварительно выбранного ордера.           |//+----------------------------------------------------------------------------+//|  Параметры:                                                                |//|    pp - цена установки ордера                                              |//|    sl - ценовой уровень стопа                                              |//|    tp - ценовой уровень тейка                                              |//|    od - Срок истечения                                                     |//|    cl - цвет значка модификации                                            |//+----------------------------------------------------------------------------+void v.ModifyOrder(double pp=-1, double sl=0, double tp=0, datetime od = 0, color cl=CLR_NONE) {   bool   fm;   double op, pa, pb, os, ot;   int    dg=MarketInfo(OrderSymbol(), MODE_DIGITS), er, it;     if (pp<=0) pp=v.OrderOpenPrice();   if (sl<0 ) sl=v.OrderStopLoss();   if (tp<0 ) tp=v.OrderTakeProfit();      pp=NormalizeDouble(pp, dg);   sl=NormalizeDouble(sl, dg);   tp=NormalizeDouble(tp, dg);   op=NormalizeDouble(v.OrderOpenPrice() , dg);   os=NormalizeDouble(v.OrderStopLoss()  , dg);   ot=NormalizeDouble(v.OrderTakeProfit(), dg);   if(od==0) od=v.OrderExpiration();     if (pp!=op || sl!=os || tp!=ot) {     RefreshRates();     fm=v.OrderModify(OrderTicket(), pp, sl, tp, od, cl);     if (fm) {     }    }}   //+------------------------------------------------------------------+//| Группа функций-эмуляторов  Order*() => v.Order*()                |//| По всем функциям с префиксом v. - см. справку по MQL4            |//+------------------------------------------------------------------+   int         v.OrdersTotal( )        {   return(ArrayRange(aTrade,0));}int         v.OrdersHistoryTotal( ) {   return(aHistory.cnt);}bool        v.OrderSelect( int index, int select, int pool=MODE_TRADES)  {     who.selected=pool;     aTrade.p=-1;     aHistory.p=-1;     int i = 0;     if(select==SELECT_BY_POS)     {         if(pool==MODE_TRADES)         {             if(index>=0&&index<v.OrdersTotal())                 {aTrade.p=index;        return(true);}         } else {//MODE_HISTORY             if(index>=0&&index<v.OrdersHistoryTotal())                 {aHistory.p=index;      return(true);}         }     } else {//SELECT_BY_TICKET            for(i=0;i<v.OrdersTotal();i++)             if(NormalizeDouble(aTrade[i,0],0)==index)             {                 who.selected=MODE_TRADES;                  aTrade.p=i;                           return(true);             }         for(i=0;i<v.OrdersHistoryTotal();i++)             if(NormalizeDouble(aHistory[i,0],0)==index)              {                 who.selected=MODE_HISTORY;                  aHistory.p=i;                           return(true);             }     }          return(false); }   int         v.OrderSend( string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, string comment="", int magic=0, datetime expiration=0, color arrow_color=CLR_NONE)  {     int total=v.OrdersTotal();     int nt=NextTicket();     //datetime d1=IIF(aTrade.CurrentDT==0,TimeCurrent(),aTrade.CurrentDT);     ArrayResize(aTrade,total+1);     ArrayResize(aTrade.strings,total+1);     aTrade.strings[total,PROP.Symbol]=symbol;     aTrade.strings[total,PROP.Comment]=comment;     aTrade[total,PROP.Ticket]=nt;     aTrade[total,PROP.OpenDT]=aTrade.CurrentDT;     aTrade[total,PROP.Type]=cmd;     aTrade[total,PROP.Lots]=volume;     aTrade[total,PROP.OpenPrice]=price;     aTrade[total,PROP.SL]=stoploss;     aTrade[total,PROP.TP]=takeprofit;     aTrade[total,PROP.Magic]=magic;     aTrade[total,PROP.ExpDT]=expiration;     aTrade[total,PROP.LastRecalcDT]=aTrade.CurrentDT;     //if(cmd==OP_BUY||cmd==OP_BUYSTOP||cmd==OP_BUYLIMIT)     {         //aTrade[total,PROP.MaxDD]=price;         //aTrade[total,PROP.MaxProfit]=price;     }     //aTrade.CurrentDT=0;     _Print("Array send "+nt);     return(nt); }   bool        v.OrderClose( int ticket, double lots, double price, int slippage, color Color=CLR_NONE){     _Print("Closing "+ticket);     double point   = MarketInfo(v.OrderSymbol(), MODE_POINT);     if(v.OrderSelect(ticket,SELECT_BY_TICKET) && who.selected == MODE_TRADES)     {         SetDoublePropArray(PROP.CloseDT,aTrade.CurrentDT);         //aTrade.CurrentDT=0;         SetDoublePropArray(PROP.ClosePrice, price);         int ty=v.OrderType();         if(ty==OP_BUY)         {             SetDoublePropArray(PROP.Profit, CalcOrderProfit(price, aTrade.CurrentDT));//(price-v.OrderOpenPrice())/point);         } else if(ty==OP_SELL)         {             SetDoublePropArray(PROP.Profit, CalcOrderProfit(price, aTrade.CurrentDT));//(-price+v.OrderOpenPrice())/point);         } else {             v.OrderDelete( ticket );             return(true);         }         //SetDoublePropArray(PROP.Profit, price);         int newsize=v.OrdersHistoryTotal()+1;         ArrayResize_aHistory(newsize);         ArrayCopy(aHistory,aTrade,(newsize-1)*MAX_FIELDS,aTrade.p*MAX_FIELDS,MAX_FIELDS);         ArrayCopy(aHistory.strings,aTrade.strings,(newsize-1)*2,aTrade.p*2,2);                  if(aTrade.CalcBalance)         {             double AB = v.OrderProfit();             if(newsize>1)                 AB += aHistory[newsize-2][PROP.AccBalance];             aHistory[newsize-1][PROP.AccBalance] = AB;              v.OrderDelete( ticket );             aHistory[newsize-1][PROP.AccEquity] = v.AccountEquity();          } else {             v.OrderDelete( ticket );         }                  return(true);     } else         return(false); }   bool        v.OrderDelete( int ticket, color arrow_color=CLR_NONE)  {     if(v.OrderSelect(ticket,SELECT_BY_TICKET) && who.selected == MODE_TRADES)     {         SetDoublePropArray(PROP.CloseDT,aTrade.CurrentDT);         double a[][MAX_FIELDS];         string as[][2];         int oldsize=v.OrdersTotal();         int newsize=oldsize-1;                  ArrayResize(a, newsize);         ArrayResize(as, newsize);                  if(newsize==0)         {             ArrayResize(aTrade,newsize);              ArrayResize(aTrade.strings,newsize);              aTrade.p=-1;             return(true);         }                  if(aTrade.p==0)         {             ArrayCopy(a,aTrade,0,1*MAX_FIELDS,newsize*MAX_FIELDS);             ArrayCopy(as,aTrade.strings,0,1*2,newsize*2);         }         else if(aTrade.p==newsize)         {             ArrayCopy(a,aTrade,0,0,newsize*MAX_FIELDS);             ArrayCopy(as,aTrade.strings,0,0,newsize*2);         }         else         {             ArrayCopy(a,aTrade,0,0,aTrade.p*MAX_FIELDS);             ArrayCopy(as,aTrade.strings,0,0,aTrade.p*2);             ArrayCopy(a,aTrade,aTrade.p*MAX_FIELDS,(aTrade.p+1)*MAX_FIELDS,(newsize-aTrade.p)*MAX_FIELDS);             ArrayCopy(as,aTrade.strings,aTrade.p*2,(aTrade.p+1)*2,(newsize-aTrade.p)*2);         }                  ArrayResize(aTrade,newsize);         ArrayResize(aTrade.strings,newsize);         ArrayCopy(aTrade,a);         ArrayCopy(aTrade.strings,as);         aTrade.p=-1;                  return(true);     } else         return(false); }   bool        v.OrderModify( int ticket, double price, double stoploss, double takeprofit, datetime expiration, color arrow_color=CLR_NONE) {}int         v.OrderTicket( )        {    return(GetDoublePropArray(PROP.Ticket));}datetime    v.OrderOpenTime( )      {    return(GetDoublePropArray(PROP.OpenDT));}int         v.OrderType( )          {    return(GetDoublePropArray(PROP.Type));}double      v.OrderLots( )          {    return(GetDoublePropArray(PROP.Lots));}double      v.OrderOpenPrice( )     {    return(GetDoublePropArray(PROP.OpenPrice));}double      v.OrderStopLoss( )      {    return(GetDoublePropArray(PROP.SL));}double      v.OrderTakeProfit( )    {    return(GetDoublePropArray(PROP.TP));}int         v.OrderMagicNumber( )   {    return(GetDoublePropArray(PROP.Magic));}datetime    v.OrderExpiration( )    {    return(GetDoublePropArray(PROP.ExpDT));}double      v.OrderClosePrice( )    {    return(GetDoublePropArray(PROP.ClosePrice));}datetime    v.OrderCloseTime( )     {    return(GetDoublePropArray(PROP.CloseDT));}double      v.OrderProfit( )        {    return(GetDoublePropArray(PROP.Profit));}string      v.OrderSymbol( )        {    return(GetStringPropArray(PROP.Symbol));}string      v.OrderComment( )       {    return(GetStringPropArray(PROP.Comment));}   double      v.AccountBalance( ){     double ret = 0;     if(aTrade.CalcBalance && aHistory.cnt>0)         ret = aHistory[aHistory.cnt-1][PROP.AccBalance];     return (ret); }   double      v.AccountEquity( ){     double ret = v.AccountBalance();     if(aTrade.CalcBalance && aTrade.cnt>0)         for(int i = 0; i<v.OrdersTotal();i++)             if(v.OrderSelect(i, SELECT_BY_POS, MODE_TRADES))                 ret += v.OrderProfit();     return (ret); }         //+------------------------------------------------------------------+//|                Группа служебных функций.                         |//+------------------------------------------------------------------+   //+------------------------------------------------------------------+//| Включает/выключает режим расчета баланса и эквити.               |//| Возвращает значение флага до вызова метода.                      |//|                                                                  |//+------------------------------------------------------------------+bool CalcBalance(bool newval){     bool old = aTrade.CalcBalance;     aTrade.CalcBalance = newval;     return(old); }   //+------------------------------------------------------------------+//| Для увеличения быстродействия при работе с большим количеством   |//| ордеров массив для хранения OrdersHistory  увеличиваем по 100    |//| элементов за раз.                                                |//|                                                                  |//+------------------------------------------------------------------+void ArrayResize_aHistory(int newsize){     int size=ArrayRange(aHistory,0);     bool need=false;          while(newsize>size)     {         size+=100;         need=true;     }          if(need)     {         ArrayResize(aHistory,newsize);         ArrayResize(aHistory.strings,newsize);     }           aHistory.cnt=newsize; }    //+------------------------------------------------------------------+//| Генератор уникальных номеров ордеров.                            |//|                                                                  |//+------------------------------------------------------------------+int NextTicket(){     next_t++;     return(next_t); }   //+------------------------------------------------------------------+//| Возращает значение указанного параметра выбранного ордера.       |//|                                                                  |//+------------------------------------------------------------------+double GetDoublePropArray( int col){     if(who.selected==MODE_TRADES && aTrade.p>=0)         return(aTrade[aTrade.p,col]);     if(who.selected==MODE_HISTORY && aHistory.p>=0)         return(aHistory[aHistory.p,col]);     return(-1); }   string GetStringPropArray( int col){     //Print(aTrade.p);     if(who.selected==MODE_TRADES && aTrade.p>=0)         return(aTrade.strings[aTrade.p,col]);     if(who.selected==MODE_HISTORY && aHistory.p>=0)         return(aHistory.strings[aHistory.p,col]);     return("err"); }   //+------------------------------------------------------------------+//| Устанавливает значение указанного параметра выбранного ордера.   |//|                                                                  |//+------------------------------------------------------------------+bool SetDoublePropArray( int col, double d){     //_Print(StringConcatenate(who.selected,p,aTrade.p));     if(who.selected==MODE_TRADES && aTrade.p>=0)     {         aTrade[aTrade.p,col]=d;         return(true);     }     return(false); }   bool SetStringPropArray( int col, string s){     if(who.selected==MODE_TRADES && aTrade.p>=0)     {         aTrade.strings[aTrade.p,col]=s;         return(true);     }     return(false); }   //+------------------------------------------------------------------+//| Устанавливает "текущее время" для эмуляции сделок.               |//| Вызывается в основном коде, например на каждом новом баре.       |//+------------------------------------------------------------------+void SetCurrentDateTime(datetime dt){     aTrade.CurrentDT = dt; }   //+------------------------------------------------------------------+//| Пересчитывает массив открытых ордеров .                          |//| Вызывается в основном коде, например на каждом новом баре.       |//| Параметр: номер бара, на котором пересчет прекращается.          |//|                                                                  |//+------------------------------------------------------------------+void RecalcTradeArray(datetime dt=0){     int Ticket[];     int K=v.CreateTicketArray(Ticket);     //_Print("trades = "+K);     for (int i=0;i<K;i++)     {         if(v.OrderSelect(Ticket[i],SELECT_BY_TICKET))             RecalcOrder(dt);     }      }   //+------------------------------------------------------------------+//| Пересчитывает выбранный ордер.                                   |//| Параметр: номер бара, на котором пересчет прекращается. У каждого|//| ордера есть служебный параметр - дата последнего пересчета. Для  |//| выбранного ордера последовательно обсчитываются все бары от бара |//| последнего пересчета до бара указанного в параметре. При пересче-| //| проверяются условия на открытие отложенных, закрытие открытых по |//| SL и TP, истечение срока жизни (работает в т.ч. и для уже откры- |//| тых позиций, не только отложенников). Вычисляются максимальные   |//| просадка и возможная прибыль за время жизни позиции              |//|                                                                  |//+------------------------------------------------------------------+bool RecalcOrder(datetime dt=0){     string sy=v.OrderSymbol( );     double point   = MarketInfo(sy, MODE_POINT);     int spread     = MarketInfo(sy,MODE_SPREAD);     int dg         = MarketInfo(sy,MODE_DIGITS);     double sp = NormalizeDouble(spread*point,dg);     int ty=v.OrderType();     int s0=iBarShift(sy,0,GetDoublePropArray(PROP.LastRecalcDT));     int sh=0;     if(dt>0) sh=iBarShift(sy,0,dt,true);     if(sh<0) return;          _Print("Recalc "+v.OrderTicket()+" "+sy+" "+s0);          for(int i=s0;i>=sh;i--)     {         double              high    = NormalizeDouble( iHigh(sy,0,i), dg),              low     = NormalizeDouble(  iLow(sy,0,i), dg),             close   = NormalizeDouble(iClose(sy,0,i), dg);         double op=GetDoublePropArray(PROP.OpenPrice);         double sl=GetDoublePropArray(PROP.SL);         double tp=GetDoublePropArray(PROP.TP);         datetime curdt = iTime(sy,0,i);         bool res=SetDoublePropArray(PROP.LastRecalcDT, curdt);         datetime exp=GetDoublePropArray(PROP.ExpDT);         aTrade.CurrentDT=curdt;         _Print("last recalc "+res);                  if((ty==OP_BUYSTOP||ty==OP_BUYLIMIT) && op>=low+sp && op<=high+sp)         {             SetDoublePropArray(PROP.OpenDT,curdt);             ty=OP_BUY;             SetDoublePropArray(PROP.Type,ty);         }                  if(ty==OP_BUY)          {             SetDoublePropArray(PROP.Profit,CalcOrderProfit(close, aTrade.CurrentDT));             //if(sl==0)                 SetDoublePropArray(PROP.MaxDD,MathMin(GetDoublePropArray(PROP.MaxDD),(low-op)/point));             //if(tp==0)                 SetDoublePropArray(PROP.MaxProfit,MathMax(GetDoublePropArray(PROP.MaxProfit),(high-op)/point));             if(sl>0 && sl>=low)                 {v.OrderClose(GetDoublePropArray(PROP.Ticket),v.OrderLots(),sl,2);  break;}             else if(tp>0 && tp<=high)                 {v.OrderClose(GetDoublePropArray(PROP.Ticket),v.OrderLots(),tp,2);  break;}         }                  if((ty==OP_SELLSTOP||ty==OP_SELLLIMIT) && op>=low && op<=high)         {             SetDoublePropArray(PROP.OpenDT,curdt);             ty=OP_SELL;             SetDoublePropArray(PROP.Type,ty);         }                  if(ty==OP_SELL)          {             SetDoublePropArray(PROP.Profit,CalcOrderProfit((close+sp), aTrade.CurrentDT));             //if(sl==0)                 SetDoublePropArray(PROP.MaxDD,MathMin(GetDoublePropArray(PROP.MaxDD),(op-(high+sp))/point));             //if(tp==0)                 SetDoublePropArray(PROP.MaxProfit,MathMax(GetDoublePropArray(PROP.MaxProfit),(op-(low+sp))/point));             if(sl>0 && sl<=high+sp)                 {v.OrderClose(GetDoublePropArray(PROP.Ticket),v.OrderLots(),sl,2);  break;}             else if(tp>0 && tp>=low+sp)                 {v.OrderClose(GetDoublePropArray(PROP.Ticket),v.OrderLots(),tp,2);  break;}         }                  if(exp>0 && exp<=aTrade.CurrentDT)             {v.OrderClose(GetDoublePropArray(PROP.Ticket),v.OrderLots(),close,2);  break;}     }          return(true); }   //+------------------------------------------------------------------+//| Вычисляет стоимость сделки в валюте депозита                     |//| Параметры:                                                       |//|     price  текущая цена для расчета                              |//|     dt     опорная дата/время для расчета кросс-курса            |//|                                                                  |//+------------------------------------------------------------------+   double CalcOrderProfit(double price, datetime dt){     string sy   = v.OrderSymbol();     double lots = v.OrderLots();     int op      = v.OrderType();     double LS   = MarketInfo(sy, MODE_LOTSIZE);     double OrdProf    = lots * LS * (price - v.OrderOpenPrice()) * IIF(op==OP_BUY,1,-1);     string FirstPart  = StringSubstr(sy, 0, 3);     string SecondPart = StringSubstr(sy, 3, 3);     string DepoCurr   = AccountCurrency();          if( SecondPart == DepoCurr )          { /**/ }      else if( FirstPart == DepoCurr )          {OrdProf /= price;}      else      {         if(MarketInfo( DepoCurr + SecondPart, MODE_BID ) > 0)             sy = DepoCurr + SecondPart;         else             sy = SecondPart + DepoCurr;                  int sh = iBarShift(sy, 0, dt, true);         if(sh < 0)         {             sh = iBarShift(sy, 0, dt, false);             Print("Error! No history for "+sy+" at "+TimeToStr(dt)+". Trying at "+TimeToStr(iTime(sy,0,sh)));             price=iClose(sy, 0, sh);             //return(-1);         } else {             price=iClose(sy, 0, sh);         }                  FirstPart  = StringSubstr(sy, 0, 3);         SecondPart = StringSubstr(sy, 3, 3);         if( SecondPart == DepoCurr )              OrdProf *= price;          else if( FirstPart == DepoCurr )              OrdProf /= price;      }       OrdProf = NormalizeDouble(OrdProf, 2) ;     return(OrdProf); }   //+------------------------------------------------------------------+//| Сохраняет массивы ордеров в бинарном формате.                    |//| Параметр: имя группы служебных файлов.                           |//| На выходе 4 файла:                                               |//|      "bin."+fn+".hist"                                           |//|      "bin."+fn+".histstring"                                     |//|      "bin."+fn+".trade"                                          |//|      "bin."+fn+".tradestring"                                    |//| Может применяться для промежуточного сохранения результатов, а   |//| также для сохранения результатов между сеансами.                 | //|                                                                  |//+------------------------------------------------------------------+void SaveArrays(string fn){     int h=FileOpen("bin."+fn+".hist",FILE_WRITE|FILE_BIN);     FileWriteArray(h,aHistory,0,ArraySize(aHistory));     FileClose(h);          h=FileOpen("bin."+fn+".histstring",FILE_WRITE|FILE_BIN);     FileWriteArray(h,aHistory.strings,0,ArraySize(aHistory.strings));     FileClose(h);          h=FileOpen("bin."+fn+".trade",FILE_WRITE|FILE_BIN);     FileWriteArray(h,aTrade,0,ArraySize(aTrade));     FileClose(h);          h=FileOpen("bin."+fn+".tradestring",FILE_WRITE|FILE_BIN);     FileWriteArray(h,aTrade.strings,0,ArraySize(aTrade.strings));     FileClose(h); }   //+------------------------------------------------------------------+//| Загружает массивы ордеров из бинарных файлов                     |//| Параметр: имя группы служебных файлов.                           |//| На входе 4 файла:                                                |//|      "bin."+fn+".hist"                                           |//|      "bin."+fn+".histstring"                                     |//|      "bin."+fn+".trade"                                          |//|      "bin."+fn+".tradestring"                                    |//|                                                                  |//+------------------------------------------------------------------+void LoadArrays(string fn){     int h=FileOpen("bin."+fn+".hist",FILE_READ|FILE_BIN);     int h1=FileOpen("bin."+fn+".histstring",FILE_READ|FILE_BIN);     double a[MAX_FIELDS];     int k=v.OrdersHistoryTotal();          while((!FileIsEnding(h))&&(!FileIsEnding(h)))     {         ArrayResize(aHistory,(k+1));         ArrayResize(aHistory.strings,(k+1));         FileReadArray(h,aHistory,k*MAX_FIELDS,MAX_FIELDS);         FileReadArray(h1,aHistory.strings,k*2,2);         aHistory.cnt++;         k++;     }          if(k>0)     {         aHistory.cnt--;         ArrayResize(aHistory,(k-1));         ArrayResize(aHistory.strings,(k-1));     }          FileClose(h);     FileClose(h1);               h=FileOpen("bin."+fn+".trade",FILE_READ|FILE_BIN);     h1=FileOpen("bin."+fn+".tradestring",FILE_READ|FILE_BIN);     k=v.OrdersTotal();          while((!FileIsEnding(h))&&(!FileIsEnding(h)))     {         ArrayResize(aTrade,(k+1));         ArrayResize(aTrade.strings,(k+1));         FileReadArray(h,aTrade,k*MAX_FIELDS,MAX_FIELDS);         FileReadArray(h1,aTrade.strings,k*2,2);         k++;     }          if(k>0)     {         ArrayResize(aTrade,(k-1));         ArrayResize(aTrade.strings,(k-1));     }          FileClose(h);     FileClose(h1);          for(k=0;k<v.OrdersHistoryTotal();k++)         next_t=MathMax(next_t,aHistory[k,0]);     for(k=0;k<v.OrdersTotal();k++)         next_t=MathMax(next_t,aTrade[k,0]); }   //+------------------------------------------------------------------+//| Выводит массивы ордеров в читабельном формате                    |//| Параметр: имя группы служебных файлов.                           |//| На выходе 2 файла:                                               |//|      "deb."+fn+".hist.csv"                                       |//|      "deb."+fn+".trade.csv"                                      |//| применяется для контроля работы, а также для дальнейшего анализа |//| сделок, например, в Excel                                        |//|                                                                  |//+------------------------------------------------------------------+void DebugPrintArrays(string fn){     string s="", p="";     int i,j;     int h=FileOpen("deb."+fn+".hist.csv",FILE_WRITE|FILE_CSV,csv.dem);     FileWrite(h,"Ticket","OpenDT","Type","Lots","OpenPrice","SL","TP","Magic","ExpDT","ClosePrice","CloseDT",     "Profit","LastRecalcDT","AccBalance","AccEquity","MaxDD","MaxProfit","Symbol","Comment");          for(i=0;i<v.OrdersHistoryTotal();i++)     {         s="";         for(j=0;j<MAX_FIELDS;j++)         {             if(j==PROP.OpenDT||j==PROP.ExpDT||j==PROP.CloseDT||j==PROP.LastRecalcDT)                 p=TimeToStr(aHistory[i,j],TIME_DATE|TIME_MINUTES|TIME_SECONDS);             else if(j==PROP.Ticket||j==PROP.Type||j==PROP.Magic)                 p=DoubleToStr(aHistory[i,j],0);             else                 p=DoubleToStr(aHistory[i,j],4);             s=s+p+csv.dem;         }         s=s+aHistory.strings[i,0]+csv.dem+aHistory.strings[i,1];         FileWrite(h,s);     }          FileClose(h);          h=FileOpen("deb."+fn+".trade.csv",FILE_WRITE|FILE_CSV,csv.dem);     FileWrite(h,"Ticket","OpenDT","Type","Lots","OpenPrice","SL","TP","Magic","ExpDT","ClosePrice","CloseDT",     "Profit","LastRecalcDT","AccBalance","AccEquity","MaxDD","MaxProfit","Symbol","Comment");     datetime d=0;          for(i=0;i<v.OrdersTotal();i++)     {         s="";         for(j=0;j<MAX_FIELDS;j++)         {             if(j==PROP.OpenDT||j==PROP.ExpDT||j==PROP.CloseDT||j==PROP.LastRecalcDT)                 p=TimeToStr(aTrade[i,j],TIME_DATE|TIME_MINUTES|TIME_SECONDS);             else if(j==PROP.Ticket||j==PROP.Type||j==PROP.Magic)                 p=DoubleToStr(aTrade[i,j],0);             else                 p=DoubleToStr(aTrade[i,j],4);             s=s+p+csv.dem;         }         s=s+aTrade.strings[i,0]+csv.dem+aTrade.strings[i,1];         FileWrite(h,s);     }          FileClose(h);      }   //+------------------------------------------------------------------+//| Вывод отладочной информации в лог-файл                           |//| Параметр: строка для записи в файл                               |//|                                                                  |//+------------------------------------------------------------------+void _Print(string s){/*   int fh=FileOpen("vo.log",FILE_WRITE|FILE_READ);    FileSeek(fh, 0, SEEK_END);    FileWrite(fh,TimeToStr(TimeCurrent())," ",s);     FileClose(fh);*/}   //*************************************** // string sIIF(bool cr, string r1, string r2){    if(cr)       return(r1);    else         return(r2); }   double IIF(bool cr, double r1, double r2){    if(cr)       return(r1);    else         return(r2); } // //***************************************