Перейти к содержимому

Theme© by Fisana
 

Фотография

  • Авторизуйтесь для ответа в теме
Сообщений в теме: 34

#16 Olej

Olej

    Почётный житель форума

  • Свой человек
  • PipPipPipPipPipPipPipPipPipPip
  • 411 сообщений

Отправлено 22 February 2011 - 03:38

Обсуждалось где-то в этом разделе.

Вот это место попалось:
http://fxgeneral.com...p?showtopic=998
Можно ещё там уточниться.

 
 

#17 Olej

Olej

    Почётный житель форума

  • Свой человек
  • PipPipPipPipPipPipPipPipPipPip
  • 411 сообщений

Отправлено 28 February 2011 - 01:12

Ещё недокументированная возможность ... но теперь уже в форме вопроса:

1. в MQL4 нет никакой возможности определять функции с переменным числом параметров, такие, как Print() или Аlert() (я правильно понимаю? ... можно, пожалуй, написать нужную функцию на С и откомпилировать её в DLL, и потом подключить эту DLL, но это уже совсем отдельный вопрос).
Но есть возможность определять функцию с значениями аргументов вызова по умолчанию, и если удачно выбрать порядок параметров в описании функции, то это можно использовать, в ограниченной мере, как переменное (не указываемое) число параметров.
Вот как-то так:
 void func( int p1, int p2 = 0, int p3 = 0, int p4 = 0 ) {
 ...
 }
 ...
 // вызовы:
    func( 2 );
    func( 2, 3 );
    func( 2, 3, 4 );

2. но это всё хорошо, пока мы эту функцию записываем в текст программы-советника (всё в одном файле)...
Но функций много, и отладившись с func() мы решаем её перенести в ex4 библиотеку, в простейшем виде:
- в файл lib.mq4 помещаем (здесь записывать умалчиваемые значения бессмысленно):
 void func( int p1, int p2, int p3, int p4 ) {
  ...
  }
- в начало файла советника впишем (описание функции):
 #import "lib.ex4"
 void func( int p1, int p2 = 0, int p3 = 0, int p4 = 0 );
 #import
- в точке вызова:
    func( 2 );
- и вот тут-то нарываемся на ошибку ("неправильное число параметров функции").

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

#18 Olej

Olej

    Почётный житель форума

  • Свой человек
  • PipPipPipPipPipPipPipPipPipPip
  • 411 сообщений

Отправлено 28 February 2011 - 02:44

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


На этот вопрос можно ответить...

Но вот вопрос! Если задаётся позиция i в списке ордеров, то этот список, естественно, упорядочен по какому-то признаку... достаточно естественно, чтобы это было время закрытия-удаления - OrderCloseTime()...

Вот и вопрос: по какому признаку упорядоченными будут "вываливаться" ордера в показанном цикле? Если по времени закрытия, то в возрастающем или убывающем порядке? какой будет получен при i==0 : самый старый или самый последний?


Вот такой примерно функцией заполняем массив истории закрытых ордеров (типа того, что показывалось в "полезные функции", но модернизировано и упрощено):
int HistoryOrdersList( double &order[][], int iMagic ) {
   string sSymbol = Symbol();
   int k = OrdersHistoryTotal(), cnt = 0;
   ArrayResize( order, k );
   for( int i = 0; i < k; i++ ) {
      if( OrderSelect( i, SELECT_BY_POS, MODE_HISTORY ) ) {
         if( OrderSymbol() != sSymbol ) continue;
         if( iMagic != 0 && OrderMagicNumber() != iMagic ) continue;
         if( OrderCloseTime() == 0 ) continue;
         if( OrderType() != OP_BUY && OrderType() != OP_SELL ) continue;
         order[ cnt ][ 0 ] = OrderTicket();
...
         order[ cnt ][ 4 ] = OrderOpenTime();
         order[ cnt ][ 5 ] = OrderCloseTime();
         cnt++;               
      }
   }
   ArrayResize( order, cnt ); 
   return ( cnt );
}

Вызов настолько понятен, что я не буду писать... А вот убедительный результат 3-х ордеров : открываются они последовательно, а закрываются в обратном порядке:

2011.02.28 01:31:36 2011.02.25 22:59 h1 EURUSD,H1: 2010.02.19 08:00:00 ... 2010.02.25 03:00:00
2011.02.28 01:31:36 2011.02.25 22:59 h1 EURUSD,H1: 2010.02.22 05:00:00 ... 2010.02.24 07:00:00
2011.02.28 01:31:36 2011.02.25 22:59 h1 EURUSD,H1: 2010.02.23 01:00:00 ... 2010.02.23 11:00:00


Всё ОК! :
1. ордера истории упорядочены, как и должно быть, по времени закрытия!
2. выдаваемые по возрастанию i от 0... - в порядке возрастания времени: от более старых к последним...
3. конечно, при обратном пробеге i можно выбрать в обратном (убывающем) порядке.

#19 Olej

Olej

    Почётный житель форума

  • Свой человек
  • PipPipPipPipPipPipPipPipPipPip
  • 411 сообщений

Отправлено 28 February 2011 - 21:11

В продолжение вчерашенего сообщения...

Если не ошибаюсь, то порядок сортировки ордеров в истории счета задает сам пользователь (вкладка история счета, если кликнуть например на "тип" - ордера будут отсортированы по типу).


Порядок сортировки на вкладке MT4 - да, управляется пользователем.
Но порядок, в котором из списка ордеров их выгребает библиотечная функция OrderSelect() не может зависить, и не зависит от визуальных настроек MT4.

Лучше, на мой взгляд, занести ордера в массив и сортировать как удобно (по времени открытия/закрытия), по крайней мере я так делаю обычно. Это надежнее, чем зависеть от каких-либо других факторов.


Нет. Определённо не лучше.
Если мне для каких-то целей понадобится один, самый последний, закрытый ордер, то мне (зная порядок сортировки!) остаточно 1 раз выполнить вызов:
  OrderSelect( 0, SELECT_BY_POS, MODE_HISTORY )
А если нужен самый старый закрытый ордер, то:
   OrderSelect( OrdersHistoryTotal() -1, SELECT_BY_POS, MODE_HISTORY )
Вместо того, чтобы перелопачивать всю историю из N ордеров, и вы бирать из неё единственный меня интересующий.

А теперь представьте, что нужно обеспечить цель (что я и делаю):
- на сигнал открытия каждого нового ордера я хочу разгрести историю уже закрытых ... чтобы определиться с размером будущего лота...
- а истории у меня - 280 закрытых ордеров (это из реального тестера взятого наугад)...
- для анализ на открытие 281-го ордера мне нужно: перелопатить и выбрать 280 предыдущих...
- ... потом их пересортировать, а сортировка, как хорошо известно из теории алгоритмов (если это не рекурсивное разделение-слияние) требует N**2 шагов, т.е. + ещё 280*280 операций сравнений и перестановок...

И это всё - вместо того, чтобы мен просто последовательно вызвать OrderSelect() 3, 5 или 10 раз.

#20 Olej

Olej

    Почётный житель форума

  • Свой человек
  • PipPipPipPipPipPipPipPipPipPip
  • 411 сообщений

Отправлено 28 February 2011 - 21:21

В продолжение вчерашенего сообщения...


И ещё раз, чтоб закончить с этим окончательно ... и чтоб не возникал вопрос "откуда ты это знаешь?"...
Вот такой код простейшего тестового советника:
   #include <mmlib.mqh>         
   #define Magic 77777777
   
   int nBars = 0, nStart;
   int aOpen[]  = {  10,  30,  50,  70,  90 },
       aClose[] = { 200, 180, 160, 140, 120 },
       aPrint[] = { 100, 220 },
       aTick[];
   //---------------------------------------------------------------------
   void init() {
      ArrayResize( aTick, ArraySize( aOpen ) );
      ArrayInitialize( aTick, 0 );   
   }
   //---------------------------------------------------------------------
   int start() {
      if( nBars == 0 ) nStart = Bars;
      if( nBars == Bars ) return;
      else nBars = Bars;                             // начался новый бар ...
      int i, nDelay = Bars - nStart;
      for( i = 0; i < ArraySize( aOpen ); i++ ) {
         if( aOpen[ i ] == nDelay ) {
            aTick[ i ] = OrderSend( Symbol(), OP_SELL, 1, 
                                    NormalizeDouble( Bid, Digits ), 3, 0, 0,
                                    "", Magic );
            Print( "bar:", nDelay, " открытие #", aTick[ i ] );
         }
         if( aClose[ i ] == nDelay ) {
            bool Ansv;
            if( aTick[ i ] > 0 ) {
               Ansv = OrderSelect( aTick[ i ], SELECT_BY_TICKET);
               Ansv = OrderClose( aTick[ i ], OrderLots(), NormalizeDouble( Ask, Digits ), 3 );
               Print( "bar:", nDelay, " закрытие #", aTick[ i ] );
               aTick[ i ] = 0;
            }
         }
      }
      for( i = 0; i < ArraySize( aPrint ); i++ ) {
         double ord[][ Parm_Number ];
         if( aPrint[ i ] != nDelay ) continue;
         int n, j;
         n = ActiveOrdersList( ord, 0, Magic );      
         Print( "открытых ордеров в работе : ", n );
         for( j = 0; j < n; j++ ) 
            Print( "#", ord[ j ][ Parm_Ticket ], " : ",
                   TimeToStr( ord[ j ][ Parm_OpenTime ], TIME_DATE | TIME_SECONDS ) );
         n = HistoryOrdersList( ord, 0, Magic );
         Print( "закрытых ордеров в истории : ", n );   
         for( j = 0; j < n; j++ ) 
            Print( "#", ord[ j ][ Parm_Ticket ], " : ",
                   TimeToStr( ord[ j ][ Parm_OpenTime ], TIME_DATE | TIME_SECONDS ), " ... ",
                   TimeToStr( ord[ j ][ Parm_CloseTime ], TIME_DATE | TIME_SECONDS ) );
      }
   }
   //---------------------------------------------------------------------
Сами функции получения как закрытых, так и текущих активных ордеров - вот они:
  #define Parm_Number     7
  #define Parm_Ticket     0
  #define Parm_Type       1
  #define Parm_Lots       2
  #define Parm_OpenPrice  3
  #define Parm_ClosePrice 4
  #define Parm_OpenTime   5
  #define Parm_CloseTime  6
  #define Parm_Profit     7
  
  void SetParam( double& order[][], int n ) {
     order[ n ][ Parm_Ticket ] = OrderTicket();
     order[ n ][ Parm_Type ] = OrderType();
     order[ n ][ Parm_Lots ] = OrderLots();
     order[ n ][ Parm_OpenPrice ] = OrderOpenPrice();
     order[ n ][ Parm_ClosePrice ] = OrderClosePrice();
     order[ n ][ Parm_OpenTime ] = OrderOpenTime();
     order[ n ][ Parm_CloseTime ] = OrderCloseTime();
     order[ n ][ Parm_Profit ] = OrderProfit();
  }
  
  int HistoryOrdersList( double& order[][ Parm_Number ], int iNum, int iMagic  ) {
     string sSymbol = Symbol();
     int total = OrdersHistoryTotal(), cnt = 0;
     ArrayResize( order, total );
     for( int i = 0; i < total; i++ ) {
        if( OrderSelect( i, SELECT_BY_POS, MODE_HISTORY ) == false ) continue;
        if( OrderSymbol() != sSymbol ) continue;
        if( iMagic != 0 && OrderMagicNumber() != iMagic ) continue;
        if( OrderCloseTime() == 0 ) continue;
        if( OrderType() != OP_BUY && OrderType() != OP_SELL ) continue;
        SetParam( order, cnt );
        cnt++;
        if( iNum != 0 && cnt == iNum ) break;
     }
     ArrayResize( order, cnt ); 
     return (cnt);
  }
  
  int ActiveOrdersList( double& order[][ Parm_Number ], int iNum, int iMagic  ) {
     string sSymbol = Symbol();
     int total = OrdersTotal(), cnt = 0;
     ArrayResize( order, total );
     for( int i = 0; i < total; i++ ) {
        if( OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) == false ) continue;
        if( OrderSymbol() != sSymbol ) continue;
        if( iMagic != 0 && OrderMagicNumber() != iMagic ) continue;
        if( OrderCloseTime() != 0 ) continue;
        if( OrderType() != OP_BUY && OrderType() != OP_SELL ) continue;
        SetParam( order, cnt );
        cnt++;
        if( iNum != 0 && cnt == iNum ) break;
     }
     ArrayResize( order, cnt ); 
     return (cnt);
  }

P.S. у меня нет всего в одном файле - функции выкинуты в библиотеку + там много ещё чего... поэтому не обессудьте, что код выкидываю в тему - файл не могу прикрепить ... чего нет - того нет :)

Результат тестера (в "Журнал") будет что-то типа такого:

2011.02.28 17:05:28 2010.02.22 04:00 h1 EURUSD,H1: #1 : 2010.02.09 08:00:00 ... 2010.02.19 07:00:00
2011.02.28 17:05:28 2010.02.22 04:00 h1 EURUSD,H1: #2 : 2010.02.10 04:00:00 ... 2010.02.18 11:00:00
2011.02.28 17:05:28 2010.02.22 04:00 h1 EURUSD,H1: #3 : 2010.02.11 00:00:00 ... 2010.02.17 15:00:00
2011.02.28 17:05:28 2010.02.22 04:00 h1 EURUSD,H1: #4 : 2010.02.11 20:00:00 ... 2010.02.16 19:00:00
2011.02.28 17:05:28 2010.02.22 04:00 h1 EURUSD,H1: #5 : 2010.02.12 16:00:00 ... 2010.02.15 23:00:00
...
2011.02.28 17:05:28 2010.02.15 03:00 h1 EURUSD,H1: #5 : 2010.02.12 16:00:00
2011.02.28 17:05:28 2010.02.15 03:00 h1 EURUSD,H1: #4 : 2010.02.11 20:00:00
2011.02.28 17:05:28 2010.02.15 03:00 h1 EURUSD,H1: #3 : 2010.02.11 00:00:00
2011.02.28 17:05:28 2010.02.15 03:00 h1 EURUSD,H1: #2 : 2010.02.10 04:00:00
2011.02.28 17:05:28 2010.02.15 03:00 h1 EURUSD,H1: #1 : 2010.02.09 08:00:00
...


1. Список открытых ордеров (MODE_TRADES) упорядочен (от индекса 0 и далее) в порядке убывания даты-времени открытия (0 - самый последний).
1. Список закрытых ордеров (MODE_HISTORY) упорядочен (от индекса 0 и далее) в порядке убывания даты-времени закрытия (0 - самый последний) - времена открытия их при этом могут "рассыпаться" в произвольном порядке.

Думаю, что теперь этот вопрос - исчерпывающе ясен.

#21 Olej

Olej

    Почётный житель форума

  • Свой человек
  • PipPipPipPipPipPipPipPipPipPip
  • 411 сообщений

Отправлено 01 March 2011 - 11:42

1. Список открытых ордеров (MODE_TRADES) упорядочен (от индекса 0 и далее) в порядке убывания даты-времени открытия (0 - самый последний).
1. Список закрытых ордеров (MODE_HISTORY) упорядочен (от индекса 0 и далее) в порядке убывания даты-времени закрытия (0 - самый последний) - времена открытия их при этом могут "рассыпаться" в произвольном порядке.

Думаю, что теперь этот вопрос - исчерпывающе ясен.


Во здесь я маху дал! ;)
Да это и по результатам показанных тестов видно - всё, так как и сказано, только списки и открытых и закрытых ордеров - упорядочены по возрастанию даты!


OrderSelect( 0, SELECT_BY_POS, MODE_HISTORY )
- будут возвращать самый старый ордер, и при повторных вызовах будет всегда константой, а:

OrderSelect( OrdersHistoryTotal() -1, SELECT_BY_POS, MODE_HISTORY )
- будет возвращать самый последний ордер, и при повторных вызовах будет (может) обновляться (если между вызовами были операции с ордерами).

#22 Olej

Olej

    Почётный житель форума

  • Свой человек
  • PipPipPipPipPipPipPipPipPipPip
  • 411 сообщений

Отправлено 08 March 2011 - 01:39

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

В архиве 5 файлов mq4 ... покомпилируете сами, кому интересно станет ;)

P.S. архив .tar.gz - раскрывайте WinRAR.

Прикрепленные файлы



#23 Olej

Olej

    Почётный житель форума

  • Свой человек
  • PipPipPipPipPipPipPipPipPipPip
  • 411 сообщений

Отправлено 14 March 2011 - 00:59

Сегодня вышел 68-й выпуск журнала:
_http://www.fortrader.ru/

Там по материалам этой я описал ... как промежуточный итог:

ВАШИ НЕДОКУМЕНТИРОВАННЫЕ ВОЗМОЖНОСТИ ПРИ НАПИСАНИИ СОВЕТНИКОВ НА MQL4


  • Alen_T это нравится

#24 Olej

Olej

    Почётный житель форума

  • Свой человек
  • PipPipPipPipPipPipPipPipPipPip
  • 411 сообщений

Отправлено 28 March 2011 - 09:55

О-о-о-очень ;) интересную возможность для программирования советников подсказали вот здесь:
Запуск/остановка советника
- возможность управлять работой советника по ходу его работы!

Хотя это не возможность MQL4 получается, а возможность клиент-серверной организации работы с ДЦ... Применить этот трюк можно в самых разнообразных целях! а выглядит он в 2-х словах так:

1. работает советник на какой-то паре ... долго работает...
2. входим в другое окно этой же валютной пары (а можно даже с другого MT4 и другого компьютера)...
3. и открываем (вручную!) отложенный ордер лимит или стор, с каким-то зарезервированным заранее MAGIC или с коментарием строго оговоренным... ордер открываем с "дикими" параметрами, который никогда не сработает...
4. советник в цикле start() очередном просматривает открытые ордера ... видит "меченный" (по MAGIC или COMMENT), и понимает, что это ему "письмо" ... ордер этот он при этом удаляет...
5. ... и советник выполняет то, что ему положено по данному "письму".

#25 valenok_2003

valenok_2003

    Выпустил первую очередь

  • Пользователи
  • PipPipPip
  • 11 сообщений

Отправлено 31 March 2011 - 14:47

О-о-о-очень ;) интересную возможность для программирования советников подсказали вот здесь:
Запуск/остановка советника
5. ... и советник выполняет то, что ему положено по данному "письму".


А зачем так напрягаться? Письмо советнику можно отправить с помощью глобальных переманных. Я в BlueDream так и делаю.
<link rel="StyleSheet" href="http://www.onix-trad.../informers.css" type="text/css">
<div style="width:350px">
<div>
<a href="http://www.onix-trad...stat&xid=37518" title="FOREX MONITORING"><img src="http://www.onix-trad...rbar/16055.gif" width="350" height="20" border="0" alt="FOREX MONITORING"><br></a>
</div>


#26 Olej

Olej

    Почётный житель форума

  • Свой человек
  • PipPipPipPipPipPipPipPipPipPip
  • 411 сообщений

Отправлено 31 March 2011 - 14:59

А зачем так напрягаться? Письмо советнику можно отправить с помощью глобальных переманных. Я в BlueDream так и делаю.


Ну а с другого компьютера за 15 км. - вы тоже отошлёте письмо "с помощью глобальных переменных"(с) ? :no:

Тут как-раз интерес способа выплывает из-за клиент-серверности работы терминалов MT4, и того, что роботом можно управлять (вообще-то неограниченно сложно) через сигналы, доставляемые ему с сервера.

#27 Alen_T

Alen_T

    Есть ещё порох в пороховницах

  • Специалист
  • PipPipPipPipPipPipPipPipPipPipPipPip
  • 874 сообщений

Отправлено 31 March 2011 - 15:08

Ну а с другого компьютера за 15 км. - вы тоже отошлёте письмо "с помощью глобальных переменных"(с) ? :no:

Тут как-раз интерес способа выплывает из-за клиент-серверности работы терминалов MT4, и того, что роботом можно управлять (вообще-то неограниченно сложно) через сигналы, доставляемые ему с сервера.


Откуда узнал что именно за 15 км...:hmmm:
А с коммуникатора - 750 км.
А использовал я это потому что поставил не обкатанный советник.
Для хорошего советника это не требуется - он же автомат.
Ты это, заходи, если что...(С)

#28 Olej

Olej

    Почётный житель форума

  • Свой человек
  • PipPipPipPipPipPipPipPipPipPip
  • 411 сообщений

Отправлено 31 March 2011 - 17:22

Для хорошего советника это не требуется - он же автомат.

И для хорошего может пригодиться.
Это ж тема "неописанные возможности"? - и вот есть такая возможность, а кто её и куда потом прилепит - это его вопросы...

#29 erch

erch

    Выпустил первую очередь

  • Пользователи
  • PipPipPip
  • 21 сообщений

Отправлено 01 April 2011 - 05:56

А зачем так напрягаться? Письмо советнику можно отправить с помощью глобальных переманных. Я в BlueDream так и делаю.


Это что ДЦ может рулить BlueDream?

#30 Michelangelo®

Michelangelo®

    МОРДЕ-РАПТОР

  • Профи
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1003 сообщений

Отправлено 01 April 2011 - 08:02

О-о-о-очень ;) интересную возможность для программирования советников подсказали вот здесь:
Запуск/остановка советника
- возможность управлять работой советника по ходу его работы!

Хотя это не возможность MQL4 получается, а возможность клиент-серверной организации работы с ДЦ... Применить этот трюк можно в самых разнообразных целях! а выглядит он в 2-х словах так:

1. работает советник на какой-то паре ... долго работает...
2. входим в другое окно этой же валютной пары (а можно даже с другого MT4 и другого компьютера)...
3. и открываем (вручную!) отложенный ордер лимит или стор, с каким-то зарезервированным заранее MAGIC или с коментарием строго оговоренным... ордер открываем с "дикими" параметрами, который никогда не сработает...
4. советник в цикле start() очередном просматривает открытые ордера ... видит "меченный" (по MAGIC или COMMENT), и понимает, что это ему "письмо" ... ордер этот он при этом удаляет...
5. ... и советник выполняет то, что ему положено по данному "письму".

мне интересно как именно в ручную можно в ордере магик проставить? комментарий пожалуйста, а магик то как? а если советник не использует комментарии т.е. игнорирует их, а обработка идет по магику и символу... тут придется сначала читать открытые ордера, а затем писать робота с тем же магиком... имхо заморочка лишняя... :)



Изображение
Возможно все! ...что ниже скорости света!
Невозможное делаю сразу! Чудо требует незначительной подготовки...
Пришел, увидел, нафлудил...

Изображение



Copyright © 2024 Your Company Name