Скачать MetaTrader 5
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Используй MQL5 Cloud Network. Тестируй роботов с гиперскоростью!
zevs37
17
zevs37 2012.03.28 14:25 
Приветствую Всех!!! В массивах совсем пока не силен поэтому прошу помощи.
В процесе написания советника потребовалось запоминать промежуточные данные на основании которых принимаются торговые решения.(А,B,C... время выставления ордера)
Ордера идентифицировать собираюсь по магику (каждый ордер свой уникальный магик).
В момент инициализации советник загружает резервную копию масива,

и в процесе работы сохраняет резервную копию. Советник с явным контролем открытия бара, поэтому диск запросами не перегрузит.

Куски кода для работы смассивами и файлами взяты отсюда https://forum.mql4.com/ru/28948#256425 (резервное копирование. Спасибо Integer'у!!!)

и отсюда https://www.mql5.com/ru/articles/1390

Задача описана в конце кода. Помогите !!! под номерами 1-4 ( void ZapOrdMas() ) .

double Massiv[101][15]; // Обьявляем массив -= Massiv =- Основной массив
// 1й индекс = порядковый номер ордера в этом массиве
// [0][1]  MagicNumber         !!! самый Новый магик  !!! (глобальный магик, требуется для резервного копирования)
// [][1] курс откр. ордера   (абсолютное знач. курса)
// [][2] StopLoss ордера     (абсолютное знач. курса)
// [][3] TakeProfit ордера   (абсолютное знач. курса)
// [][4] номер ордера         ticket   
// [][5] колич. лотов ордера (абсолютное знач. курса)
// [][6] тип ордера 0=B,1=S,2=BL,3=SL,4=BS,5=SS  Если ордер закрыт то +10
// [][7] Магическое число ордера  MagicNumber
// [][8] = A;          // Цена A  
// [][9] = B;          // Цена B
// [][10] = Razmer;    // Размер АB
// [][11] = Time[] ;  // Время  АB
//--------------------------------------------------------------------

// тралим и пр...
//+ Ля-ля-ля... Жу-жу-жу..  получаем  A, B, Razmer....(здесь расположена сама торговая система)
//+ условия выполнены: MagicNumber+1, открываем ордер. --- получаем ticket ордера.
// ZapOrdMas();

void ZapOrdMas()
 {
// if (Massiv[0][1]<MagicNumber) Massiv[0][1]=MagicNumber ; //сохраняем самый свежий магик
// (1й индекс = порядковый номер ордера в этом массиве)
// 1. Сортируем массив по  типу ордера [][6] <= 10. У кого тип больше либо равен 10 в конец массива (закрытые ордера)
// 2. В первой части массива (открытые ордера) ищем самый маленький MagicNumber (Massiv[][7])
// 3. Сортирум вторую часть массива (закрытые ордера у которых тип [][6]<=10) по магику и удал. с самыми старыми магиками.)
// 4. пишем данные нового ордера и A, B, Razmer... в массив.
 FilesWrite(); // Сохраняем массив в Файл.(Взято отсюда https://forum.mql4.com/ru/28948#256425 Спасибо Integer'у!!!)
 }
Sergey Guliaev
2302
Sergey Guliaev 2012.03.28 17:12  
zevs37:
Ордера идентифицировать собираюсь по магику (каждый ордер свой уникальный магик).

Зачем каждому свой магик? Или я что-то не догоняю или обсуждать пока что нечего.

OrderSend()
Основная функция, используемая для открытия позиции или установки отложенного ордера.
Возвращает номер тикета, который назначен ордеру торговым сервером или -1 в случае неудачи.
TarasBY
1743
TarasBY 2012.03.28 17:19  
zevs37: Ордера идентифицировать собираюсь по магику (каждый ордер свой уникальный магик).

Уникальный номер у каждого ордера - это его OrderTicket() и манипуляции с уникальным Магиком вызывают непонятки... :(

Ваша сверхзадача неясна, а точнее не ясен её смысл.

zevs37
17
zevs37 2012.03.28 18:21  
TarasBY:

Уникальный номер у каждого ордера - это его OrderTicket() и манипуляции с уникальным Магиком вызывают непонятки... :(

Ваша сверхзадача неясна, а точнее не ясен её смысл.


На NDD отложка может открываться частями и закрываться тоже частями может, при этом тикет меняется. (Alpari)

Соответственно ордер теряет свою уникальность. Мне нужно точно знать почему и когда ордер открылся (отложка) для того чтобы в динамике пересчитывать каждому ордеру TP, SL или просто закрывать потому что цена пошла не по моему ожидаемому сценарию.
В Massiv помимо параметров ордера еще сохраняется и информация Почему и Когда, взятая из блока принятия решений.

Ниже Цитата: Источник https://www.mql5.com/ru/articles/1390

Прежде, чем перейти к примеру обработки событий, необходимо напомнить, что существуют специфические ситуации, при которых интуитивно ожидаемый порядок событий не соблюдается.

Во-первых, есть некоторые дилеры (например, банки со своей спецификой учёта), которые в конце торгового дня принудительно закрывают все открытые ордера и тут же, в начале следующего дня, открывают такие же ордера, но по курсу, отличающемуся от текущего на несколько десятых пункта. Этими долями пункта в экономику ордера закладывается своп. Сам своп в терминале всегда отражается нулевым. C точки зрения экономики дилеры ничего не нарушают. Нам в этой ситуации важно то, что вновь открываемым ордерам присваиваются новые номера, никак не связанные с предыдущими.

Во-вторых, частичное закрытие отдельно взятого ордера (у всех дилеров) осуществляется как бы в два этапа. На первом этапе ордер закрывается полностью, а на втором - открывается новый ордер уменьшенной стоимости, но уже с новым номером. При этом номер исходного ордера прописывается в комментарий нового ордера.

В-третьих, аналогичная специфика возникает и при закрытии одного ордера за счёт другого, если эти ордера имеют разную стоимость. Фактически в этом случае повторяется ситуация частичного закрытия одного из ордеров.

А вот еще информация к размышлению: тикеты размножаются... (Обратите внимание на обьемы позиций !!!)

Советник выставляет отложенный ордер

2012.03.19 19:28:50 open #1323587278 buy limit 0.80 XAUUSD at 1651.05 tp: 1656.05 ok

После этого в отчете видно 2 открытых ордера с разным объемом в сумме равным 0.8

Ticket Open Time Type Size Item Price S / L T / P Close Time Price Commission Taxes Swap Profit
1323587278 2012.03.20 10:11 buy 0.01 xauusd 1651.05 0.00 1656.05 2012.03.20 17:01 1656.05 -0.10 0.00 0.00 5.00
1323621997 2012.03.20 10:11 buy 0.79 xauusd 1651.05 0.00 1656.05 2012.03.20 17:01 1656.05 -7.90 0.00 0.00 395.00
Sergey Guliaev
2302
Sergey Guliaev 2012.03.29 01:38  

Я думаю, что для получения ответов, вам лучше разбить свой вопрос на меньшие и более конкретные части.

С вашей постановкой вопроса ответа вы вряд ли дождётесь.

// 1. Сортируем массив по типу ордера [][6] <= 10. У кого тип больше либо равен 10 в конец массива (закрытые ордера)

здесь проблема в массиве или в способе сортировки?

// 2. В первой части массива (открытые ордера) ищем самый маленький MagicNumber (Massiv[][7])

затруднения вызывает массив или сам поиск? и что значит " В первой части массива "?

// 3. Сортирум вторую часть массива (закрытые ордера у которых тип [][6]<=10) по магику и удал. с самыми старыми магиками.)

смотри п.п 1 и п.п 2

// 4. пишем данные нового ордера и A, B, Razmer... в массив.

на какое место, а оно у вас есть свободное?

Мне кажется, что ваша схема на данный момент неработоспособна. Выделите каждый пункт в отдельную функцию и с ним работайте.

Или может смысл вашего вопроса в технологии передачи массива в функцию?

Sergey Guliaev
2302
Sergey Guliaev 2012.03.29 02:11  

Массив, это просто таблица для хранения данных, в вашем случае размер таблицы 101Х15.

Для сортировки:

1.счётчик=0; (указатель индекса элемента массива same номера строки таблицы)

2. Возмите данные из ячейки с номером= счётчик;

3. Сравните со всеми ячейками подряд до первого меньшего.

- Если не нашли меньшего поместите данные в ячейку под номером =счётчик (значение из этой ячейки сохранить на освободившееся место), счётчик++

- Если нашли меньшее, Возьмите меньшее перейдите к п 3.

zevs37
17
zevs37 2012.03.29 06:54  
valenok2003:

Массив, это просто таблица для хранения данных, в вашем случае размер таблицы 101Х15.

Для сортировки:

1.счётчик=0; (указатель индекса элемента массива same номера строки таблицы)

2. Возмите данные из ячейки с номером= счётчик;

3. Сравните со всеми ячейками подряд до первого меньшего.

- Если не нашли меньшего поместите данные в ячейку под номером =счётчик (значение из этой ячейки сохранить на освободившееся место), счётчик++

- Если нашли меньшее, Возьмите меньшее перейдите к п 3.


Я на рынке уже не новичек. MQL тоже вроде как освоил, но с массивами я пока впадаю в ступор (документацию трудно понять). Поэтому и прошу помощи у профи.
Попробую обьяснить задачу иначе. Имеем массив в котором будет храниться информация об ордерах открытых и закрытых и их параметрах + переменные.
функция должна удалить старые закрытые ордера и занести новый ордер в массив.(Интересуют примеры кода, я практик с теорией у меня туго.)
Должно получиться так:
пор.номер/магик/тип ордера/
1 // 56 // 0
2 // 34 // 1 // у этого ордера самый маленький магик(34)из открытых ордеров
3 // 63 // 4
4 // 51 // 4
5 // 68 // 14
6 // 29 // 10 // Этот нужно удалить 29<34 магик
7 // 37 // 12
8 // 31 // 11 // Этот нужно удалить 31<34 магик
9 ....
с 1 по 4 ордера открыты. тип ордера <10 (тип ордера меняется в другом блоке сравнения ордеров.Если ордер закрывается или удаляется к типу ордера +10)
самый маленький магик(34) у 2 ордера
c 5 по 8 ордеры закрыты. тип ордера =>10
у ордеров 6 и 8 магик меньше 34 и они уже закрыты(тип =>10). их нужно удалить.
(Наверно сортируем)
ПИШЕМ новый ордер в массив.
Уходим...
Пожалуйсто напишите пример кода...
Sergey Guliaev
2302
Sergey Guliaev 2012.03.29 08:53  

Вот пример кода из моего советника.

//+-------
//+------------------------------------------------------------------+
//|   valenok2003@mail.ru                                   19.02.2012
//+------------------------------------------------------------------+
//| lock_buy() локирование длинных позиций
//+------------------------------------------------------------------+
bool lock_buy(){  
   string _Function = "lock_buy():";
//-----------------
   int _Cnt = 0;
   int _Ticket, _Record_Num;
   double _Lot_Base_Order;
   bool _RET = true;
   bool _SUCCES_SET_LOCK = true;
//---- проверка внешних сигналов управляющих локами ------------------
   if(GlobalVariableGet(GV_Ignore_Lock_BUY)  == YES) return(true);
//--------------------------------------------------------------------
   // необходимо локировать ордера на каждом тике, так как локи могут закрываться, например, по outloss
   for(int _i = OrdersTotal()-1; _i >= 0; _i--)  {  
      // берём очередной ордер
      OrderSelect(_i, SELECT_BY_POS, MODE_TRADES);
      if(OrderSymbol() == Symbol() && OrderType() == OP_BUY && check_magic(OrderMagicNumber(), _Function)) { 
         _Lot_Base_Order = OrderLots();      // запоминаем лот базового ордера
         bool _EXIST_RECORD_BASE_ORDER = false;
//-----------------
         // ищем запись об ордере в массиве
         for(int _n = 0; _n < MAX_ORDERS; _n++){
            // если запись о базовом существует 
            if(Buy_Base_Tickets[_n] == OrderTicket()) {
               _EXIST_RECORD_BASE_ORDER = true;
               _Record_Num = _n;
               break;
            }
         }
         // если нет записи о базовом ордере создаём её на первом свободном месте
         if(!_EXIST_RECORD_BASE_ORDER) {
            for(_n = 0; _n < MAX_ORDERS; _n++){
               if(Buy_Base_Tickets[_n] == 0) {
                  Buy_Base_Tickets[_n] = OrderTicket(); 
                  Buy_Lock_Tickets[_n] = 0;
                  _Record_Num = _n;
                  break;
               }
            } 
         }
//-----------------
         // если существует соответствующая базовому запись о локирующем ордере
         if(Buy_Lock_Tickets[_Record_Num] != 0) {   
            // и сам локирущий существует
            if(OrderSelect(Buy_Lock_Tickets[_Record_Num], SELECT_BY_TICKET)) {
               // и он ещё не закрыт 
               if(OrderCloseTime() <= 0) {
                  // и соответствует лоту базового 
                  // то переходим к следующему базовому ордеру
                  if(_Lot_Base_Order == OrderLots())continue; 
               }
            }
         }
//-----------------
         // если доехали до сюда то лока не существует
         Buy_Lock_Tickets[_Record_Num] = 0;
//-----------------
         bool _SUCCES = false;
         // ищем ордер оппозит среди локов с лотом равным лоту базового
         for(int _z = OrdersTotal()-1; _z >= 0; _z--)  {
            OrderSelect(_z, SELECT_BY_POS, MODE_TRADES);
            // если нашли подходящий ордер
            if(OrderSymbol() == Symbol() && OrderType() == OP_SELL && _Lot_Base_Order == OrderLots() && OrderMagicNumber() == Lock_Magic) { 
               bool _BUSY_ORDER_LOCK = false;
               bool _GO_NEXT_BASE = false;
               // проверка - не учтён ли он в другой паре
               for(_n = 0; _n < MAX_ORDERS; _n++){
                  if(Buy_Lock_Tickets[_n] == OrderTicket()) {
                     if(_n == _Record_Num) {
                        _GO_NEXT_BASE = true;
                        _SUCCES = true;
                        break;
                     }
                     if(Buy_Base_Tickets[_n] != 0) {
                        _BUSY_ORDER_LOCK = true;
                        break;
                     }
                  }
               }
               // если используется в разрабатываемой паре, переходим к следующему базовому
               if(_GO_NEXT_BASE) break;
               // если он занят (учтён в другой паре) переходим к следующему локу 
               if(_BUSY_ORDER_LOCK) continue; 
               // если свободен
               else {
                  // ставим его в пару базовому ордеру
                  Buy_Lock_Tickets[_Record_Num] = OrderTicket();
                  _SUCCES = true;
               }
            }
         }   
         // если не нашли подходящий локовый ордер - открываем новый
         if(!_SUCCES) {
            _Ticket = open_order_sell(_Lot_Base_Order,"Lock for "+Buy_Base_Tickets[_Record_Num]+" Mgc="+Lock_Magic, Lock_Magic);
            if(_Ticket > 0) {
               Buy_Lock_Tickets[_Record_Num] = _Ticket;
            }
            else _SUCCES_SET_LOCK = false;                     
         }
      }
   }
   //if(_SUCCES_SET_LOCK) output_mov_string("локи для BUY установлены",Clr_Report);
//-----------------
   return(_SUCCES_SET_LOCK);
}
//+------------------------------------------------------------------+
//+-------

Только я работаю не с одним массивом размерностью (MAX_ORDERS х N), а создаю N массивов размерностью (MAX_ORDERS х 1), тогда я имею возможность каждому массиву приписать мнемоническое имя, что в дальнейшем облегчет мне понимание кода. Рзбираться и запоминать в какой ячейке какие данные записаны будет сложнее, чем, например, иметь массивы Tickets[ MAX_ORDERS ], Magic[ MAX_ORDERS ], OpenPrice[ MAX_ORDERS ];

Но ещё раз хочу вам повторить - учет ордеров уже существует в терминале и намного выгоднее ИМХО использовать уже существующие функции терминала, потому что вы хотите дублировать работу, которая уже проделана за вас. Вы всегда можете извлечь любую информацию о любом ордере как из открытых так и из истории.

ЗЫ. Критики моего кода щас найдутся - не обращайте внимания.

ЗЫ.ЗЫ Обратите внимание, я в массиве храню только тикеты для возможности учета локирующих ордеров, все же прочие данные добываются из терминала.

/
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий