Эмуляция тиков из советника/индикатора - страница 3

 
Meat:

Да уж, непонятно, в чём же дело... Попробуйте тогда так:  в разделе импорта #import "user32.dll"  добавьте функцию:

CallWindowProcA(int lpPrevWndFunc[], int hWnd, int Msg, int wParam, int lParam);

 А в конце функции SetMyTimer добавьте строчку:  CallWindowProcA(code,0,0,0,0); 

И каким нибудь параллельно запущенным индикатором проверьте, генерируется ли тик в этот момент. 

ну вроде что то изменилось, в логе теперь так:
10:42:52 test EURUSD,H1: loaded successfully
10:42:54 test EURUSD,H1: function 'CallWindowProcA' call from dll 'user32.dll' critical error c0000005 at 02C310A8.
10:42:54 test EURUSD,H1: initialize

 

а тики-то где? ;) 

 
Meat:

Zhunko, ну так если у вас всё нестандартное (свой лог, своя реализация индикаторов и т.д.), то к чему тогда вы затеяли весь этот разговор?  Мы тут вообще-то обсуждаем работу конкретно с МТ4, а не со своими собственными разработками.

Я же в первом посте специально указал, что мой код будет полезен именно в том случае, если стоит задача обойтись без сторонних ДЛЛ, т.е. реализовать самодостаточный советник/индикатор, который использует лишь системные библиотеки.  А если вы используете свои собственные разработки, то значит к вам это не относится.

И вообще я не понимаю, зачем "вручную чистить лог после работы", если легче просто не захламлять его. Ведь насколько я понял, вы свои разработки реализуете в ДЛЛ. Тогда что вам мешает установить там такой же таймер, как и я предложил здесь. Только там это займёт всего несколько строчек кода. Но вы почему-то предпочитаете всякие пляски с бубном и чисткой лога.  Как-то не по программистки мыслите...   Мой код вас видите-ли напрягает, а чистить ежеденевно логи вам не лень :) 

Лог у меня забивается только после подкачки истории. Бывает это по средам и субботам. Забыл, что это такое из-за его автоматической чистки.

Автономное обновление графиков давно сделал. Реализовано здесь. Один раз функцию из любой программы запускаешь и больше ничего делать не надо. Даже при всех выгруженных программах MQL4 обновление продолжается, отслеживается открытие и закрытие графиков.

Альтернативу Вашему коду предложил не из-за того, что ей пользуюсь. Это простое решение этой проблемы, исходя из поставленной Вами задачи. Одна строка кода значительно проще, чем Ваш код. Каждый день чистить логи не надо. Только в выходные. В остальное время этот код не нужен. Это рационально. Лог, как не крути, чистить надо в любом случае. Так что, это не причина.

======================

Запустил Ваш код. Не работает на Window 7.

Может избавится от функции AddBytes()? Инициализировать массив так:

  int code[7] = {0x558BEC6A, 0x16A0268, 0, 0, 0, 0, 0x33C05DC3};
  code[2] = MT4InternalMsg;
  code[3] = 0x68000000 + (hWnd >> 8);
  code[4] = (hWnd << 24) + 0x00B80000 + (PostMsgAddr >> 16);
  code[5] = (PostMsgAddr << 16) + 0x0000FFD0;
Покороче будет. Всё же, это один раз делается.
 
Zhunko:

Лог у меня забивается только после подкачки истории. Бывает это по средам и субботам. Забыл, что это такое из-за его автоматической чистки.

Автономное обновление графиков давно сделал. Реализовано здесь. Один раз функцию из любой программы запускаешь и больше ничего делать не надо. Даже при всех выгруженных программах MQL4 обновление продолжается, отслеживается открытие и закрытие графиков.

Альтернативу Вашему коду предложил не из-за того, что ей пользуюсь. Это простое решение этой проблемы, исходя из поставленной Вами задачи. Одна строка кода значительно проще, чем Ваш код. Каждый день чистить логи не надо. Только в выходные. В остальное время этот код не нужен. Это рационально. Лог, как не крути, чистить надо в любом случае. Так что, это не причина.

======================

Запустил Ваш код. Не работает на Window 7.

Может избавится от функции AddBytes()? Инициализировать массив так:

Покороче будет. Всё же, это один раз делается.

 

Да, разумеется мой выложенный код - это просто исходник, чтоб был понятен смысл, а использовать его конечно удобней уже в упакованном виде ...если конечно не понадобится его потом редактировать :)  Но как выясняется, компилировать его пока рано, т.к. у многих он почему-то не работает :)  Хотя у меня он отлично работает и в XP, и в 7, ничего не вылетает, хотя гонял его на протяжении часа. Прям мистика какая-то...

Одна строка кода значительно проще, чем Ваш код. Каждый день чистить логи не надо. Только в выходные. В остальное время этот код не нужен. Это рационально.

Лично для вас может это и не критично, если у вас параллельно работает "чистилка логов". Т.е. у вас там своя кухня. Но мы то говорим об общем случае. Представьте обычного пользователя, который не занимается подобными танцами с бубнами. Тогда получается, что для нормальной полноценной работы с вашим индикатором ему понадобится ещё и "чистилка логов". Т.е. целый комплект из нескольких файлов. А это, согласитесь, уже гораздо больше, чем размер моего кода ;)  Так что насчёт рациональности и лаконичности, я считаю, Вы не правы. Особенно если брать мой код уже в упакованном виде, типа как вы предложили. Это конечно не одна строчка, но зато к нему уже не требуются никакие прочие примочки, т.е. это уже законченный продукт.

Лог, как не крути, чистить надо в любом случае

 С чего бы вдруг? Если у меня он ничем не засоряется, так от чего мне его очищать то?

 

Алексей, чистилка может быть не обязательно автоматической. Например, правой кнопкой мыши на папке и выбрать "очистить папку". Делать это после экспериментов по выходным.

За год накапливается 365 файлов в экспертах и журнале. Т.е. 730 файлов. Это чистить не надо? Странно такое слышать. Не засоряется у Вас из-за того, что Вы ничего не делаете. При ежедневной работе логи сильно растут в размере.

 
Zhunko:

Алексей, чистилка может быть не обязательно автоматической. Например, правой кнопкой мыши на папке и выбрать "очистить папку". Делать это после экспериментов по выходным.

За год накапливается 365 файлов в экспертах и журнале. Т.е. 730 файлов. Это чистить не надо? Странно такое слышать. Не засоряется у Вас из-за того, что Вы ничего не делаете. При ежедневной работе логи сильно растут в размере.

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

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

 
Meat:

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

Так, я про то, что такая примочка нужна только в выходные. В остальное время она не нужна.
 

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

 

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

Т.е., - в исследовательских целях.  

 

Я понял, в чём была проблема.  Массив то нужно объявлять на глобальном уровне, а не на локальном.

Выкладываю исправленный вариант. Я тут заодно сократил код. А тот вариант, который предложил Zhunko, хоть и короче этого на 3 строчки, но уж слишком закручен и неудобен для восприятия алгоритма, так с ходу и не поймёшь что делает тот код, вдруг там какой-то вирус :) Да и не гибок совершенно. Так что, думаю, не стоит впадать в крайности ради сокращения кода.

#property indicator_chart_window

#import "user32.dll"
  int   RegisterWindowMessageA(string lpString);
  int   SetTimer(int hWnd,int nIDEvent,int uElapse,int& lpTimerFunc[]);
  bool  KillTimer(int hWnd,int uIDEvent);
#import "kernel32.dll"
  int   GetModuleHandleA(string lpModuleName);
  int   GetProcAddress(int hModule,string lpProcName);
  
int TimerId=666;
int TimerCode[7];

//----------------------------------------------------------------------

int init()
{
  SetMyTimer(1000);  // интервал в миллисекундах
}
//----------------------------------------------------------------------

int deinit()
{
  KillMyTimer();
  Comment("");
}  

//+------------------------------------------------------------------+
//| program start function                                           |
//+------------------------------------------------------------------+
int start()
{
  static int n=0;
  n++; 
  Comment("tick:  ",n);
  PlaySound("tick.wav");
}
//-------------------------------------------------------------------

int SetMyTimer(int interval)
{    
  int MT4InternMsg= RegisterWindowMessageA("MetaTrader4_Internal_Message");
  int hWnd= WindowHandle(Symbol(),Period());
  int PostMsgAddr= GetProcAddress(GetModuleHandleA("user32.dll"),"PostMessageA");
  if (PostMsgAddr==0) return(0);
  // push ebp; move ebp,esp; push 01; push 02; push MT4InternMsg; push hWnd; mov eax,PostMsgAddr; call eax; pop ebp; ret;    
  int value[]={ 0x55, 0x8B,0xEC, 0x6A,01, 0x6A,02, 0x68,0000, 0x68,0000, 0xB8,0000, 0xFF,0xD0, 0x5D, 0xC3 };
  int len[]=  { 1,    1,   1,    1,   1,  1,   1,  1,   4,    1,   4,    1,   4,    1,   1,    1,    1    };
  value[8]=MT4InternMsg;  value[10]=hWnd;  value[12]=PostMsgAddr; 
  int byte=0;
  for (int i=0; i<ArraySize(value); i++)
    for (int j=0;  j<len[i];  j++, byte++)
      TimerCode[byte/4] += (value[i]>>(8*j)&0xFF) <<(byte%4*8);
  
  return ( SetTimer(hWnd, TimerId, interval, TimerCode) );
}

//---------------------------------------------------

bool KillMyTimer()
{
  return( KillTimer(WindowHandle(Symbol(),Period()), TimerId) );
}
 
Meat:

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

Хоть один случай для примера?

Сколько пишу и пользую, ниразу не понадобилось, кроме выходных.

Эксперт + индикатор. Это решается зацикливанием эксперта. Результат тот же, что у Вас. Чтобы получать данные вовремя, достаточно реагировать на изменение времени сервера. Для этого WinAPI не нужно.

Единственный случай, когда это нужно, это запуск старта эксперта в выходные. Даже это можно реализовать той строкой, что привёл выше. Только для эксперта. 

Причина обращения: