Скачать MetaTrader 5

Передача котировок в dll

Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Forex Trader
114297
Forex Trader  
Не могли бы многоуважаемые программисты - разработчики ответить на несколько вопросов?
1. Мне нужно передать в длл ровно 500 свечей для работы советника в реалтайме. Как это сделать со стороны MQL? Меня интересует следующий вопрос, не может ли МТ в процессе обновления данных залезть в этот массив и его "подправить", в то время, когда моя длл будет с ним работать? Если не сложно, приведите правильный код обработки ERR_HISTORY_WILL_UPDATED.

2. Напишите, пожалуйста на программистском языке, что делают
а) ArrayCopyRates - (например, "ArrayCopyRates устанавливает ссылку на начало массива с котировками"), если она выделяет память, напишите тожа.
б) ArrayCopy()

3. oftop :) как вернуть из функции более одного значения? Интересует возможность передачи параметров в длл по ссылке. Можно это сделать? Опять же со стороны MQL. внутри длл я разберусь сам, если там особых хитростей нет.
Forex Trader
114297
Forex Trader  
Я знал, что сразу не получится :)
Вот уже и следующий вопрос. Почему не работает закомментированный код. МТ вешается.
ЭТО СКРИПТ.

так работает
int start()
{
   int err;
   double price[][6];
   double price500[500][6];
   int count = ArrayCopyRates( price, "EURUSD", PERIOD_H1);
   err = GetLastError();
   if ( err == 4066) // ERR_HISTORY_WILL_UPDATED
   {
        // Пропускаем этот тик
        return (0);
   }
   
   Print( count);
   // count == 2680
   bbl_write_rates( price, count);   
   
//   count = ArrayCopy( price500, price, 0, count-499, 500);
//   bbl_write_rates( price500, count);
   
   return(0);
}




так не работает

int start()
{
   int err;
   double price[][6];
   double price500[500][6];
   int count = ArrayCopyRates( price, "EURUSD", PERIOD_H1);
   err = GetLastError();
   if ( err == 4066) // ERR_HISTORY_WILL_UPDATED
   {
        // Пропускаем этот тик
        return (0);
   }
   
   Print( count);
   // count == 2680
//   bbl_write_rates( price, count);   
   
   count = ArrayCopy( price500, price, 0, count-499, 500);
   bbl_write_rates( price500, count);
   
   return(0);
}




Чем же так отличаются массивы price & price500

код длл примерно такой


MT4_EXPFUNC void __stdcall bbl_write_rates(const RateInfo* rates, const int bar_count)
{
	file_open_write( "C:\\Work\\Test\\rates.txt");
	char buf[200];
	for( int i=bar_count-1; i>=0; i--)
	{
		sprintf_s( buf, 199, "%6d %f\r\n", i, rates[i].close);
		file_write( buf);
	}
	file_close();
}


Forex Trader
114297
Forex Trader  
Чем же так отличаются массивы price & price500

код длл примерно такой


Дело в том, что функция ArrayCopyRates() не производит фактического копирования в массив price[], происходит простое перенаправление, поэтому обращение к price[] становится равносильным обращению к EURUSD H1 (в данном случае) .
Соотвественно , ресайзить массив price после
ArrayCopyRates( price, "EURUSD", PERIOD_H1);


тоже не получится (на всякий случай добавляю).

Вот здесь предположим, что массив price[] содержит 500 элементов. Тогда вот это

count = ArrayCopy( price500, price, 0, count-499, 500);
   bbl_write_rates( price500, count);


можем переписать как

count = ArrayCopy( price500, price, 0, 1, 500);
   bbl_write_rates( price500, count);

так как count-499==500-499==1

Forex Trader
114297
Forex Trader  
я не понял ответ
ArrayCopyRates() у меня работает. и скрипт выводит опены в файл.
во втором варианте я не делаю ресайза, а копирую один массив в другой. В хелпе так написано.
А копирование это я делаю, для предотвращения несанкционированного мной доступа какой-нибудь обновлялки котировок к массиву в мойе длл (так уж я понял хелп и старые посты на этом форуме)
Forex Trader
114297
Forex Trader  
я не понял ответ
ArrayCopyRates() у меня работает. и скрипт выводит опены в файл.
во втором варианте я не делаю ресайза, а копирую один массив в другой. В хелпе так написано.
А копирование это я делаю, для предотвращения несанкционированного мной доступа какой-нибудь обновлялки котировок к массиву в мойе длл (так уж я понял хелп и старые посты на этом форуме)




Попробуй написать
count = ArrayCopy( price500, price, 0, count-500, 500);
   bbl_write_rates( price500, count);
Forex Trader
114297
Forex Trader  
попробовал 500 и 510 написать - виснет :(
я предполагаю, что в price больше 2500 свечей


   Print( count);
   // count == 2680
  // bbl_write_rates( price, count);   
   
   count = ArrayCopy( price500, price, 0, count-510, 500);
   Print( count);
   // count == 500
Forex Trader
114297
Forex Trader  
похоже, разница в выравнивании
//#pragma pack(push,1)
struct RateInfo
  {
   unsigned int      ctm;
   double            open;
   double            low;
   double            high;
   double            close;
   double            vol;
  };
//#pragma pack(pop)


так второй вариант не виснет

ПРОСЬБА К ПРОГРАММИСТАМ.
Ответьте на уже заданные мною вопросы. И еще один вопрос
Если разное выравнивание - это ваша ошибка, то будет ли эта разница устранена.

Forex Trader
114297
Forex Trader  
Вот полный код длл VisualStudio 2005
#include "stdafx.h"


#define MT4_EXPFUNC __declspec(dllexport)

#ifdef _MANAGED
#pragma managed(push, off)
#endif

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
    return TRUE;
}

#ifdef _MANAGED
#pragma managed(pop)
#endif

//#pragma pack(push,1)
struct RateInfo
  {
   unsigned int      ctm;
   double            open;
   double            low;
   double            high;
   double            close;
   double            vol;
  };
//#pragma pack(pop)

//////////////////////////
// for Test only !
#include <stdio.h>
#include <fstream>
#include <time.h>
using namespace std;

void mb( char* str)
{
	WCHAR wszMessage[5000];
	char* source = str;
	int k=0;
	while ( *source != 0)
		wszMessage[k++] = *(source++);
	wszMessage[k] = 0;
	::MessageBoxW( NULL, wszMessage, L"Hello! :)", MB_OK);
}

ofstream* m_pOutFileStream;
char FileName[500];

void file_open_write( char* file_name)
{
	strcpy_s( FileName, 499, file_name);
	m_pOutFileStream = new ofstream( FileName, ios::out | ios::binary);
	//"C:\\Work\\Umnick\\test.txt"
}

void file_close()
{
	m_pOutFileStream->close();
}

void file_write( char* str)
{
	m_pOutFileStream->write( str, std::streamsize( strlen(str)));
}
//////////////////////////////////////////

MT4_EXPFUNC void __stdcall bbl_write_rates(const RateInfo* rates, const int bar_count)
{
//	char timebuf[26];
//	_tzset();

	file_open_write( "C:\\Work\\Test\\rates.txt");
	char buf[200];
	for( int i=bar_count-1; i>=0; i--)
	{
//		time_t ltime = rates[i].ctm;
//		tm today;
//		_localtime64_s( &today, <ime );
//ctime_s(timebuf, 26, <ime);

//		sprintf_s( buf, 199, "%d.%d.%d %d:%d:%d\r\n", today.tm_mday, today.tm_mon, today.tm_year, today.tm_hour, today.tm_min, today.tm_sec);
//		sprintf_s( buf, 199, "%f\r\n", rates[i].close);
		sprintf_s( buf, 199, "%6d %f\r\n", i, rates[i].close);
//		rates[i].close;
		file_write( buf);
	}
	file_close();
}



сори, за лишние комменты в коде :)

с массивом price работает вариант

#pragma pack(push,1)
struct RateInfo
  {
   unsigned int      ctm;
   double            open;
   double            low;
   double            high;
   double            close;
   double            vol;
  };
#pragma pack(pop)
Forex Trader
114297
Forex Trader  
Нет, думаю тут проблема в другом. Вот выкладываю отлаженный вариант скрипта, который корректно копирует из Rate серии в обычный массив

//+------------------------------------------------------------------+
//|                                       CheckArrayCopybabybear.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                             http://www.metaquotes.ru/forum/8121/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.ru/forum/8121/"

#define copyBars 100
int start()
{
   int err;
   double price[][6];
   double price500[copyBars][6];
   int count1 = ArrayCopyRates( price, "EURUSD", PERIOD_H1);
   err = GetLastError();
   if ( err == 4066) // ERR_HISTORY_WILL_UPDATED
   {
        // Пропускаем этот тик
        Alert("Идет подкачка отсутствующих данных, перезапустите скрипт через несколько секунд");
        return (0);
   }
   Print("copyBars=",copyBars);
   Print( "count1=",count1);
   // count == 2680
   //bbl_write_rates( price, count);   
   
   int count2 = ArrayCopy( price500, price, 0, 0, copyBars*6);
   Print( "count2=",count2);




   for (int i=0;i<copyBars;i++)
      {
      Print("i=",i,"  price500[i]=",TimeToStr(price500[copyBars-i-1][0])
      /*,"  price500[i]=",price500[copyBars-i-1][1],"  price500[i]=",
      price500[copyBars-i-1][2],"  price500[i]=",price500[copyBars-i-1][3],"  price500[i]=",price500[copyBars-i-1][4],
      "  price500[i]=",price500[copyBars-i-1][5]
      */
      ,"  price[count1-i]=",TimeToStr(price[count1-i-1][0]));
      
      }
   return(0);
}



В кратком виде можно посмотреть здесь - "MQL4: ArrayCopy with arrays of rank 2."

Forex Trader
114297
Forex Trader  
Кончательный вариант такой
struct RateInfo
  {
   double		     dtime;
   double            open;
   double            low;
   double            high;
   double            close;
   double            vol;
  };

MT4_EXPFUNC void __stdcall bbl_write_rates(const RateInfo* rates, const int bar_count)
{
	file_open_write( "C:\\Work\\Test\\rates.txt");
	char buf[200];
	for( int i=bar_count-1; i>=0; i--)
	{
		time_t ltime = time_t( rates[i].dtime);
		tm today;
		_gmtime64_s( &today, &ltime );
		
		sprintf_s( buf, 199, "%6d %02d.%02d.%4d %02d:%02d:%02d ", i, today.tm_mday, today.tm_mon, today.tm_year+1900, today.tm_hour, today.tm_min, today.tm_sec);
		file_write( buf);
		sprintf_s( buf, 199, "%.4f\r\n", rates[i].close);
		file_write( buf);
	}
	file_close();
}



int start()
{
   int err;
   double price[][6];
   double price500[500][6];
   int count = ArrayCopyRates( price, "EURUSD", PERIOD_H1);
   err = GetLastError();
   if ( err == 4066) // ERR_HISTORY_WILL_UPDATED
   {
        // Пропускаем этот тик
        return (0);
   }
   
   count = ArrayCopy( price500, price, 0, 6*(count-500), 6*500);
   bbl_write_rates( price500, count/6);
   
   return(0);
}
Forex Trader
114297
Forex Trader  
В нашем ExpertSample.dll и в соответствующем ему ExportFunctions.mq4 есть уже готовый пример вызова функции GetRatesItemValue. В длл передаётся массив котировок, возвращает прочитанное в этом массиве значение.
12
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий