Los fans de GUOs

 
Hubo un tema muy ruidoso de gestión gráfica de pedidos ......
Ayer me acordé y pensé: ¿por qué no ponerlo en práctica?

19.03.2005
Lea las instrucciones antes de utilizarlo =)

//+------------------------------------------------------------------+
//|                                           Send_Pending_Order.mq4 |
//|                                                        komposter |
//|                                      mailto:komposterius@mail.ru |
//+------------------------------------------------------------------+
#property copyright "komposter"
#property link      "mailto:komposterius@mail.ru"
/*
-----------------------------В-Н-И-М-А-Н-И-Е---------------------------------
Перед запуском скрипта настоятельно рекомендую изучить следующее руководство:

Скрипт предназначен для установки отложенного ордера.
Для этого необходимо:
 1) Ознакомиться с данным руководством =), !установить значения по умолчанию! (находятся под описанием,
 	 начинаются и заканчиваются строкой //+----------------------------------------------+ ),
 	 разрешить импорт внешних экспертов через меню
 	 "Сервис" -> "Настройки" -> "Советники" -> "Разрешить импортирование внешних экспертов"
 	 (необходимо для описания ошибки, которая может возникнуть при установке ордера)
 2) Перетащить скрипт на график. При этом учитывать, что место прикрепления - это будущая
 	 цена открытия (OpenPrice). В процессе установки её можно будет менять, но для упрощения
 	 работы рекомендую перетаскивать скрипт сразу на нужный уровень.
 3) Переместить все линии на необходимые уровни:
		- Open_Price_Line (по умолчанию - белая) - цена открытия  (ОБЯЗАТЕЛЬНАЯ линия)
		- Stop_Loss_Line (красная) - уровень Стоп Лосс (ОБЯЗАТЕЛЬНАЯ)
		- Take_Profit_Line (зелёная) - уровень Тейк Профит (необязательная)
		- Expiration_Line (жёлтая) - время истечения (необязательная)
		(необязательные линии можно удалять)
		- "````" - размер позиции. Необходимо установить напротив нужного значения (от 0,1 до 10 лотов)
	В зависимости от расположения линий Open_Price и Stop_Loss выбирается тип ордера:
	Open_Price  >  Bid и Open_Price  >  Stop_Loss  -  BUYSTOP-ордер,
	Open_Price  >  Bid и Open_Price  <  Stop_Loss  -  SELLLIMIT-ордер,
	Open_Price  <  Ask и Open_Price  >  Stop_Loss  -  BUYLIMIT-ордер,
	Open_Price  <  Ask и Open_Price  <  Stop_Loss  -  SELLSTOP-ордер.
 4) Когда всё будет готово, в появившемся окне нажать кнопку "ОК".
 
 
 Для прекращения работы скрипта в любой момент можно воспользоваться кнопкой "Отмена".
 Если Вами будет найдена ошибка в коде, или в логике работы скрипта, просьба сообщить на komposterius@mail.ru
*/
//+------------------------------------------------------------------+
// Все нижеописанные переменные можно будет изменить в окне свойств скрипта,
// которое откроется при прикреплении. Это полезно, например, при необходимости выбрать
// непредставленный в списке "Lots" размер позиции. Для этого, написав нужную цифру в окне свойств (например, 1.5),
// НЕ ДВИГАЙТЕ указатель размера лота ( "````" ).
// Если окно свойств не нужно, надо закомментировать следующую строку (поставить в начало //)
#property show_inputs


// Тип ордера по умолчанию (влияет на начальное расположение линий стоп-лосс и тейк-профит)
extern int _OrderType = 1; //( "1" - BUYSTOP или BUYLIMIT, "-1" - SELLSTOP или SELLLIMIT )

// Обьём сделки по умолчанию (можно менять в процессе работы)
// от 0.1 до 1.0 с шагом 0.1, от 1 до 10 с шагом 1
extern double Lots = 0.1;

// Расстояние между линией Take_Profit/Stop_Loss и линией Open_Price в пунктах по умолчанию.
// Если Take_Profit использоваться не будет, установите 0
extern int Stop_Loss = 50;
extern int Take_Profit = 50;

// Максимальное отклонение от запрошенной цены
extern int Slippage = 5;

// Комментарий к ордеру
extern string _Comment = "Opened by script";

// Order ID
extern int MagicNumber = 0;

// Время истечения ордера, выраженное в свечах
// Для периода графика H4 и Expiration_Shift = 3 время истечения наступит через 12 часов после установки
// Если необходимо стандартное время истечения для всех периодов графика, укажите "0" (без кавычек), и переходите к следующей настройке
// Если время истечения ордера использоваться не будет, установите 0
extern int Expiration_Shift = 0;
// Время истечения ордера, выраженное в часах
// Для того, чтоб использовать эту настройку, необходимо установить Expiration_Shift (см. выше на 2 строки) "0" (без кавычек)
// Если время истечения ордера использоваться не будет, установите 0
extern int Expiration_Shift_H = 0;

extern string Order_Color = "----------------------------------------------------------------------------------------";
// Цвета отображения ордеров на графике
extern color Buy_Color = Lime; //( для ордеров BUYSTOP и BUYLIMIT )
extern color Sell_Color = Red; //( для ордеров SELLLIMIT и SELLSTOP )

extern string Line_Color = "----------------------------------------------------------------------------------------";
// Цвета линий:
extern color Open_Price_Line_Color = White;
extern color Stop_Loss_Line_Color = Red;
extern color Take_Profit_Line_Color = Lime;
extern color Expiration_Line_Color = Yellow;

//+------------------------------------------------------------------+

#include <stdlib.mqh>
int first = 1;
int start()
{
// Установка начальных значений:
double Open_Price_Level, Stop_Loss_Level, Take_Profit_Level;
datetime Expiration_Time;
// ---Open_Price_Level
	Open_Price_Level = PriceOnDropped();
	if ( Open_Price_Level <= 0 )
		{ Open_Price_Level = Bid + MarketInfo( Symbol(), MODE_STOPLEVEL )*Point; }
// ---Stop_Loss_Level
	Stop_Loss_Level = Open_Price_Level - Stop_Loss * Point;
// ---Take_Profit_Level
	if ( Take_Profit > 0 )
	{ Take_Profit_Level = Open_Price_Level + Take_Profit * Point; }

if ( _OrderType == -1 )
{
// ---Open_Price_Level
	Open_Price_Level = PriceOnDropped();
	if ( Open_Price_Level <= 0 )
		{ Open_Price_Level = Ask - MarketInfo( Symbol(), MODE_STOPLEVEL )*Point; }
// ---Stop_Loss_Level
	Stop_Loss_Level = Open_Price_Level + Stop_Loss * Point;
// ---Take_Profit_Level
	if ( Take_Profit > 0 )
	{ Take_Profit_Level = Open_Price_Level - Take_Profit * Point; }
}

// ---Expiration_Time
	if ( Expiration_Shift > 0 )
	{ Expiration_Time = CurTime() + Period()*60*Expiration_Shift; }
	else
	{
		if ( Expiration_Shift_H > 0 )
			{ Expiration_Time = CurTime() + 3600*Expiration_Shift_H; }
	}
// Создание линий:
if ( first == 1 )
{
	ObjectCreate( "Open_Price_Line", OBJ_HLINE, 0, 0, Open_Price_Level, 0, 0, 0, 0 );
	ObjectSet( "Open_Price_Line", OBJPROP_COLOR, Open_Price_Line_Color );
	ObjectSetText( "Open_Price_Line", "Open_Price_Line", 6, "Arial", Open_Price_Line_Color );

	ObjectCreate( "Stop_Loss_Line", OBJ_HLINE, 0, 0, Stop_Loss_Level, 0, 0, 0, 0 );
	ObjectSet( "Stop_Loss_Line", OBJPROP_COLOR, Stop_Loss_Line_Color );
	ObjectSetText( "Stop_Loss_Line", "Stop_Loss_Line", 6, "Arial", Stop_Loss_Line_Color );

	if ( Take_Profit_Level > 0 )
	{
		ObjectCreate( "Take_Profit_Line", OBJ_HLINE, 0, 0, Take_Profit_Level, 0, 0, 0, 0 );
		ObjectSet( "Take_Profit_Line", OBJPROP_COLOR, Take_Profit_Line_Color );
		ObjectSetText( "Take_Profit_Line", "Take_Profit_Line", 6, "Arial", Take_Profit_Line_Color );
	}

	if ( Expiration_Time > 0 )
	{
		ObjectCreate( "Expiration_Line", OBJ_VLINE, 0, Expiration_Time, 0, 0, 0, 0, 0 );
		ObjectSet( "Expiration_Line", OBJPROP_COLOR, Expiration_Line_Color );
		ObjectSetText( "Expiration_Line", "Expiration_Line", 6, "Arial", Expiration_Line_Color );
	}
// создание "Шкалы размера лота" и установка на значение по умолчанию
	int Lots_value_y = 30;
	switch ( Lots )
	{
		case 0.2: Lots_value_y = 45; break;
		case 0.3: Lots_value_y = 60; break;
		case 0.4: Lots_value_y = 75; break;
		case 0.5: Lots_value_y = 90; break;
		case 0.6: Lots_value_y = 105; break;
		case 0.7: Lots_value_y = 120; break;
		case 0.8: Lots_value_y = 135; break;
		case 0.9: Lots_value_y = 150; break;
		case 1.0: Lots_value_y = 165; break;
		case 2.0: Lots_value_y = 180; break;
		case 3.0: Lots_value_y = 195; break;
		case 4.0: Lots_value_y = 210; break;
		case 5.0: Lots_value_y = 225; break;
		case 6.0: Lots_value_y = 240; break;
		case 7.0: Lots_value_y = 255; break;
		case 8.0: Lots_value_y = 270; break;
		case 9.0: Lots_value_y = 285; break;
		case 10.0: Lots_value_y = 300; break;
	}
	if ( Lots > 10.0 ) Lots_value_y = 315;
	int Lots_value_y_start_position = Lots_value_y;
	
	ObjectCreate( "Lots", OBJ_LABEL, 0,0,0,0,0,0,0);
	ObjectSet( "Lots", OBJPROP_CORNER, 1);
	ObjectSet( "Lots", OBJPROP_XDISTANCE, 1);
	ObjectSet( "Lots", OBJPROP_YDISTANCE, 10);
	ObjectSetText(  "Lots", "Lots", 10, "Arial", Open_Price_Line_Color);

	ObjectCreate( "Lots_value", OBJ_LABEL, 0,0,0,0,0,0,0);
	ObjectSet( "Lots_value", OBJPROP_CORNER, 1);
	ObjectSet( "Lots_value", OBJPROP_XDISTANCE, 25);
	ObjectSet( "Lots_value", OBJPROP_YDISTANCE, Lots_value_y);
	ObjectSetText(  "Lots_value", "`````", 10, "Arial", Open_Price_Line_Color);

	int y = 25;
	for ( double z = 0.1; z <= 1; z += 0.1 )
	{
		ObjectCreate( DoubleToStr( z, 1 ), OBJ_LABEL, 0,0,0,0,0,0,0);
		ObjectSet( DoubleToStr( z, 1 ), OBJPROP_CORNER, 1);
		ObjectSet( DoubleToStr( z, 1 ), OBJPROP_XDISTANCE, 1);
		ObjectSet( DoubleToStr( z, 1 ), OBJPROP_YDISTANCE, y);
		ObjectSetText(  DoubleToStr( z, 1 ), DoubleToStr( z, 1 ), 10, "Arial", Open_Price_Line_Color);
		y += 15;
	}
	y = 160;
	for ( z = 1; z <= 10; z ++ )
	{
		ObjectCreate( DoubleToStr( z, 1 ), OBJ_LABEL, 0,0,0,0,0,0,0);
		ObjectSet( DoubleToStr( z, 1 ), OBJPROP_CORNER, 1);
		ObjectSet( DoubleToStr( z, 1 ), OBJPROP_XDISTANCE, 1);
		ObjectSet( DoubleToStr( z, 1 ), OBJPROP_YDISTANCE, y);
		ObjectSetText(  DoubleToStr( z, 1 ), DoubleToStr( z, 1 ), 10, "Arial", Open_Price_Line_Color);
		y += 15;
	}
	ObjectCreate( ">", OBJ_LABEL, 0,0,0,0,0,0,0);
	ObjectSet( ">", OBJPROP_CORNER, 1);
	ObjectSet( ">", OBJPROP_XDISTANCE, 1);
	ObjectSet( ">", OBJPROP_YDISTANCE, 310);
	ObjectSetText(  ">", ">10", 10, "Arial", Open_Price_Line_Color);

// вывод месседжбокса
	string Question = "Для установки ордера переместите линии на необходимые уровни и нажмите \"ОК\".\n" + 
							"Чтоб отказаться от установки, нажмите \"Отмена\".";
	int  Answer = MessageBox( Question, "Установка отложенного ордера", 0x00000001 | 0x00000040 | 0x00040000 );
	first = 0;
	// если нажата любая кроме "ОК" кнопка - выходим
	if ( Answer != 1 ) { deinit(); return(0); }
}

// считываем значения с объектов и нормализуем:

// размер лота
	Lots_value_y = ObjectGet( "Lots_value", OBJPROP_YDISTANCE );
	if ( Lots_value_y_start_position != Lots_value_y )
	{
		Lots = 0.1;
		if ( Lots_value_y >= 35  && Lots_value_y < 50  ) Lots = 0.2;
		if ( Lots_value_y >= 50  && Lots_value_y < 65  ) Lots = 0.3;
		if ( Lots_value_y >= 65  && Lots_value_y < 80  ) Lots = 0.4;
		if ( Lots_value_y >= 80  && Lots_value_y < 95  ) Lots = 0.5;
		if ( Lots_value_y >= 95  && Lots_value_y < 110 ) Lots = 0.6;
		if ( Lots_value_y >= 110 && Lots_value_y < 125 ) Lots = 0.7;
		if ( Lots_value_y >= 125 && Lots_value_y < 140 ) Lots = 0.8;
		if ( Lots_value_y >= 140 && Lots_value_y < 155 ) Lots = 0.9;
		if ( Lots_value_y >= 155 && Lots_value_y < 170 ) Lots = 1.0;
		if ( Lots_value_y >= 170 && Lots_value_y < 185 ) Lots = 2.0;
		if ( Lots_value_y >= 185 && Lots_value_y < 200 ) Lots = 3.0;
		if ( Lots_value_y >= 200 && Lots_value_y < 215 ) Lots = 4.0;
		if ( Lots_value_y >= 215 && Lots_value_y < 230 ) Lots = 5.0;
		if ( Lots_value_y >= 230 && Lots_value_y < 245 ) Lots = 6.0;
		if ( Lots_value_y >= 245 && Lots_value_y < 260 ) Lots = 7.0;
		if ( Lots_value_y >= 260 && Lots_value_y < 275 ) Lots = 8.0;
		if ( Lots_value_y >= 275 && Lots_value_y < 290 ) Lots = 9.0;
		if ( Lots_value_y >= 290 							  ) Lots = 10.0;
	}
	Lots = NormalizeDouble( Lots, 1 );
// Open_Price
	Open_Price_Level = NormalizeDouble( ObjectGet( "Open_Price_Line", OBJPROP_PRICE1 ), MarketInfo( Symbol(), MODE_DIGITS ) );
// Stop_Loss
	Stop_Loss_Level = NormalizeDouble( ObjectGet( "Stop_Loss_Line", OBJPROP_PRICE1 ), MarketInfo( Symbol(), MODE_DIGITS ) );
// Take_Profit
	Take_Profit_Level = NormalizeDouble( ObjectGet( "Take_Profit_Line", OBJPROP_PRICE1 ), MarketInfo( Symbol(), MODE_DIGITS ) );
// Expiration_Time
	Expiration_Time = ObjectGet( "Expiration_Line", OBJPROP_TIME1 );
	
// определяем тип ордера
	if ( Open_Price_Level - Bid >= 0 )
	{
		if ( Open_Price_Level - Stop_Loss_Level > 0 )
		{ _OrderType = OP_BUYSTOP; }
		else
		{ _OrderType = OP_SELLLIMIT; }
	}
	else
	{
		if ( Open_Price_Level - Stop_Loss_Level > 0 )
		{ _OrderType = OP_BUYLIMIT; }
		else
		{ _OrderType = OP_SELLSTOP; }
	}

color _Color;
// проверяем все значения
	if ( _OrderType == OP_BUYLIMIT || _OrderType == OP_BUYSTOP )
	{
		_Color = Buy_Color;
		if ( Open_Price_Level - Stop_Loss_Level < MarketInfo( Symbol(), MODE_STOPLEVEL )*Point )
		{
			Answer = MessageBox(  "Неправильно установлена Stop_Loss_Line (красная линия)!\n" + 
					 		 			 "\n" +
					 		 			 "Для BuyLimit и BuyStop - ордеров она должна быть НИЖЕ линии Open_Price_Line.	\n" + 
					 		 			 "Минимальный отступ (" + Symbol() + ") - " + DoubleToStr( MarketInfo( Symbol(), MODE_STOPLEVEL ), 0 ) + " пунктов.\n" + 
					 		 			 "\n\n" +
					 		 			 "Чтобы начать установку с начала, нажмите \"Повтор\".\n" +
					 		 			 "Чтоб отказаться от установки, нажмите \"Отмена\".", "Установка отложенного ордера", 0x00000005 | 0x00000030 | 0x00040000 );
			if ( Answer == 4 ) { ObjectsRedraw(); start(); }
			deinit();
			return(-1);
		}
		if ( Take_Profit_Level - Open_Price_Level < MarketInfo( Symbol(), MODE_STOPLEVEL )*Point && Take_Profit_Level > 0 )
		{
			Answer = MessageBox(  "Неправильно установлена Take_Profit_Line (зелёная линия)!\n" + 
					 		 			 "\n" +
					 		 			 "Для BuyLimit и BuyStop - ордеров она должна быть ВЫШЕ линии Open_Price_Line.	\n" + 
					 		 			 "Минимальный отступ (" + Symbol() + ") - " + DoubleToStr( MarketInfo( Symbol(), MODE_STOPLEVEL ), 0 ) + " пунктов.\n" + 
					 		 			 "\n\n" +
					 		 			 "Чтобы начать установку с начала, нажмите \"Повтор\".\n" +
					 		 			 "Чтоб отказаться от установки, нажмите \"Отмена\".", "Установка отложенного ордера", 0x00000005 | 0x00000030 | 0x00040000 );
			if ( Answer == 4 ) { ObjectsRedraw(); start(); }
			deinit();
			return(-1);
		}
		if ( _OrderType == OP_BUYSTOP )
		{
			if ( Open_Price_Level - Bid < MarketInfo( Symbol(), MODE_STOPLEVEL )*Point )
			{
				Answer = MessageBox( "Неправильно установлена Open_Price_Line (белая линия)!\n" + 
					 		 			 	"\n" +
					 		 			 	"Для BuyStop - ордера она должна быть ВЫШЕ текущей цены.	\n" + 
					 		 			 	"Минимальный отступ (" + Symbol() + ") - " + DoubleToStr( MarketInfo( Symbol(), MODE_STOPLEVEL ), 0 ) + " пунктов.\n" + 
					 		 			 	"\n\n" +
					 		 			 	"Чтобы начать установку с начала, нажмите \"Повтор\".\n" +
					 		 			 	"Чтоб отказаться от установки, нажмите \"Отмена\".", "Установка отложенного ордера", 0x00000005 | 0x00000030 | 0x00040000 );
				if ( Answer == 4 ) { ObjectsRedraw(); start(); }
				deinit();
				return(-1);
			}
		}
		else
		{
			if ( Bid - Open_Price_Level < MarketInfo( Symbol(), MODE_STOPLEVEL )*Point )
			{
				Answer = MessageBox( "Неправильно установлена Open_Price_Line (белая линия)!\n" + 
					 		 			 	"\n" +
					 		 			 	"Для BuyLimit - ордера она должна быть НИЖЕ текущей цены.	\n" + 
					 		 			 	"Минимальный отступ (" + Symbol() + ") - " + DoubleToStr( MarketInfo( Symbol(), MODE_STOPLEVEL ), 0 ) + " пунктов.\n" + 
					 		 			 	"\n\n" +
					 		 			 	"Чтобы начать установку с начала, нажмите \"Повтор\".\n" +
					 		 			 	"Чтоб отказаться от установки, нажмите \"Отмена\".", "Установка отложенного ордера", 0x00000005 | 0x00000030 | 0x00040000 );
				if ( Answer == 4 ) { ObjectsRedraw(); start(); }
				deinit();
				return(-1);
			}
		}
	}
	if ( _OrderType == OP_SELLLIMIT || _OrderType == OP_SELLSTOP )
	{
		_Color = Sell_Color;
		if ( Stop_Loss_Level - Open_Price_Level < MarketInfo( Symbol(), MODE_STOPLEVEL )*Point )
		{
			Answer = MessageBox(  "Неправильно установлена Stop_Loss_Line (красная линия)!\n" + 
					 		 			 "\n" +
					 		 			 "Для SellLimit и SellStop - ордеров она должна быть ВЫШЕ линии Open_Price_Line.	\n" + 
					 		 			 "Минимальный отступ (" + Symbol() + ") - " + DoubleToStr( MarketInfo( Symbol(), MODE_STOPLEVEL ), 0 ) + " пунктов.\n" + 
					 		 			 "\n\n" +
					 		 			 "Чтобы начать установку с начала, нажмите \"Повтор\".\n" +
					 		 			 "Чтоб отказаться от установки, нажмите \"Отмена\".", "Установка отложенного ордера", 0x00000005 | 0x00000030 | 0x00040000 );
			if ( Answer == 4 ) { ObjectsRedraw(); start(); }
			deinit();
			return(-1);
		}
		if ( Open_Price_Level - Take_Profit_Level < MarketInfo( Symbol(), MODE_STOPLEVEL )*Point && Take_Profit_Level > 0 )
		{
			Answer = MessageBox(  "Неправильно установлена Take_Profit_Line (зелёная линия)!\n" + 
					 		 			 "\n" +
					 		 			 "Для SellLimit и SellStop - ордеров она должна быть НИЖЕ линии Open_Price_Line.	\n" + 
					 		 			 "Минимальный отступ (" + Symbol() + ") - " + DoubleToStr( MarketInfo( Symbol(), MODE_STOPLEVEL ), 0 ) + " пунктов.\n" + 
					 		 			 "\n\n" +
					 		 			 "Чтобы начать установку с начала, нажмите \"Повтор\".\n" +
					 		 			 "Чтоб отказаться от установки, нажмите \"Отмена\".", "Установка отложенного ордера", 0x00000005 | 0x00000030 | 0x00040000 );
			if ( Answer == 4 ) { ObjectsRedraw(); start(); }
			deinit();
			return(-1);
		}
		if ( _OrderType == OP_SELLLIMIT )
		{
			if ( Open_Price_Level - Ask < MarketInfo( Symbol(), MODE_STOPLEVEL )*Point )
			{
				Answer = MessageBox( "Неправильно установлена Open_Price_Line (белая линия)!\n" + 
					 		 			 	"\n" +
					 		 			 	"Для SellLimit - ордера она должна быть НИЖЕ текущей цены.	\n" + 
					 		 			 	"Минимальный отступ (" + Symbol() + ") - " + DoubleToStr( MarketInfo( Symbol(), MODE_STOPLEVEL ), 0 ) + " пунктов.\n" + 
					 		 			 	"\n\n" +
					 		 			 	"Чтобы начать установку с начала, нажмите \"Повтор\".\n" +
					 		 			 	"Чтоб отказаться от установки, нажмите \"Отмена\".", "Установка отложенного ордера", 0x00000005 | 0x00000030 | 0x00040000 );
				if ( Answer == 4 ) { ObjectsRedraw(); start(); }
				deinit();
				return(-1);
			}
		}
		else
		{
			if ( Ask - Open_Price_Level < MarketInfo( Symbol(), MODE_STOPLEVEL )*Point )
			{
				Answer = MessageBox( "Неправильно установлена Open_Price_Line (белая линия)!\n" + 
					 		 			 	"\n" +
					 		 			 	"Для SellStop - ордера она должна быть ВЫШЕ текущей цены.	\n" + 
					 		 			 	"Минимальный отступ (" + Symbol() + ") - " + DoubleToStr( MarketInfo( Symbol(), MODE_STOPLEVEL ), 0 ) + " пунктов.\n" + 
					 		 			 	"\n\n" +
					 		 			 	"Чтобы начать установку с начала, нажмите \"Повтор\".\n" +
					 		 			 	"Чтоб отказаться от установки, нажмите \"Отмена\".", "Установка отложенного ордера", 0x00000005 | 0x00000030 | 0x00040000 );
				if ( Answer == 4 ) { ObjectsRedraw(); start(); }
				deinit();
				return(-1);
			}
		}
	}

	if ( Expiration_Time <= CurTime() && Expiration_Time > 0 )
	{
			Answer = MessageBox(  "Неправильно установлена Expiration_Line (жёлтая линия)!\n" + 
					 		 			 "\n" +
					 		 			 "Срок истечения ордера не может быть в прошедшем времени!		\n" + 
					 		 			 "\n\n" +
					 		 			 "Чтобы начать установку с начала, нажмите \"Повтор\".\n" +
					 		 			 "Чтоб отказаться от установки, нажмите \"Отмена\".", "Установка отложенного ордера", 0x00000005 | 0x00000030 | 0x00040000 );
			if ( Answer == 4 ) { ObjectsRedraw(); start(); }
			deinit();
			return(-1);
	}
	
// выводим инфу о запросе и пытаемся установить ордер
	Print( "Symbol=",Symbol(), ",_OrderType=",_OrderType, ",Lots=",Lots, ",Open_Price_Level=",Open_Price_Level, ",Slippage=", Slippage, ",Stop_Loss_Level=", Stop_Loss_Level, ",Take_Profit_Level=", Take_Profit_Level, ",_Comment=", _Comment, ",MagicNumber=", MagicNumber, ",Expiration_Time=", Expiration_Time, ",_Color=", _Color );
	int ordersend = OrderSend( Symbol(), _OrderType, Lots, Open_Price_Level, Slippage, Stop_Loss_Level, Take_Profit_Level, _Comment, MagicNumber, Expiration_Time, _Color );
	if ( ordersend > 0 )
	{
// если всё ок, выводим лог и выходим
		OrderPrint();
		Print( "Ордер №", ordersend, " установлен успешно!");
		return(0);
	}
// если ошибка - выводим сообщение и выходим
	int error = GetLastError();
	Print("Ошибка при установке! GetLastError = ", error, ", ErrorDescription =  \"", ErrorDescription( error ), "\"" );
	MessageBox( "Ошибка при установке! GetLastError = " + error + ", ErrorDescription = \"" + ErrorDescription( error ) + "\"", 
             	 	"Ошибка установки ордера", 0x00000000 | 0x00000010 | 0x00040000 ); 
return(-1);
}

int deinit()
{
// удаление всех объектов, созданных скриптом
	ObjectDelete( "Open_Price_Line" );
	ObjectDelete( "Stop_Loss_Line" );
	ObjectDelete( "Take_Profit_Line" );
	ObjectDelete( "Expiration_Line" );

	for ( double z = 0.1; z <= 1; z += 0.1 )
	{ ObjectDelete( DoubleToStr( z, 1 )); }
	for ( z = 1; z <= 10; z ++ )
	{ ObjectDelete( DoubleToStr( z, 1 )); }
	ObjectDelete( "Lots" );
	ObjectDelete( "Lots_value" );
	ObjectDelete( ">" );
return(0);
}


Si alguien tiene alguna idea, que nos lo haga saber y lo pensaremos.
Tal vez podamos hacer un GUO nosotros mismos.........;)

 
No veo ningún entusiasmo en nuestras filas =)
Al menos dime qué te parece la idea...




Olvidé decir: la línea de ganancias puede ser eliminada si no es necesaria.
El tipo de orden se elige en función de la ubicación de la apertura y del stoploss...
 
La idea de un metaquista. Y su implementación es tan-tan, cruda :)
 
La idea de utilizar MessageBox para el indicador para ralentizar su ejecución es excelente. Probablemente nunca lo hubiera imaginado. Abre muchas posibilidades para la realización interactiva de pedidos. ¡Mis respetos para ti komposter!
En cuanto a los que critican la aplicación, no sé por qué dicen que es "burda".
Estoy seguro de que a mucha gente le resultará muy cómodo utilizar su script para hacer pedidos pendientes.

Para aquellos que les gusta operar desde el mercado, ofrecí la versión del script que compra al precio actual del mercado con el cálculo automático del tamaño del lote sobre la base de un stop loss colocado en Forex Magazine (ver el artículo "Bibliotecas de funciones y su uso en programas", número 52, 24 de enero de 2005). En ese momento, era imposible llevar el precio al que se "bajaba" el script al gráfico en MQL4, por lo que el precio en el script es siempre el mismo que en el mercado.

El mismo programa puede modificarse fácilmente para abrir, por ejemplo, un minilote con una parada permanente. Este truco de MessageBox definitivamente me permitirá añadir funcionalidad a mi script también.
 
Aquí está mi siguiente intento de un script de orden de compra de mercado por cierto

//+------------------------------------------------------------------+
//|                                                    order_buy.mq4 |
//|                              Copyright c 2004, Alexander Ivanov. |
//|                                        mailto:alexander@indus.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright c 2004, Alexander Ivanov."
#property link      "mailto:alexander@indus.ru"

#include <WinUser32.mqh>
#include <stderror.mqh>

// Далее константа DAYS_TO_CONSIDER будет нам заменять количество
// дней, на которых мы будем искать минимум для выставления Stop loss'а
#define DAYS_TO_CONSIDER 3

//////////////////////////////////////////////////////////////////
//
// Необходимо разрешить импорт функций из библиотек. Для этого
// нужно поставив галочку 'Разрешить импортирование внешних экспертов'
// на закладке 'Советники' окна 'Настройки' вызываемого выбором пункта
// меню 'Сервис'->'Настройки'
//
//////////////////////////////////////////////////////////////////

#include <stdlib.mqh> // содержит нужную нам функцию ErrorDescription(...)

int init()
{     
   return(0);
}

int start()
{
   double DaysLowArray[];
   int nBarWithMinimum = 0;
   double dMyStopLoss = 0;  
   double dMyPrice = 0;
   double dMyTakeProfit = 0;
   double dMyLots = 0;

   if(ArrayCopySeries(DaysLowArray, MODE_LOW, Symbol(),PERIOD_D1) < DAYS_TO_CONSIDER) {
      return(PrintErrorDescription());
   }
   
   dMyPrice = Ask;
   dMyStopLoss = DaysLowArray[Lowest(Symbol(),PERIOD_D1,MODE_LOW,DAYS_TO_CONSIDER)];
   dMyTakeProfit = dMyPrice + 2*MathMax((MathAbs(Ask-Bid)/2),MathAbs(dMyPrice-dMyStopLoss));
   dMyStopLoss -= 10*Point;
   dMyLots = 0.1;

   Print("Цена = ", dMyPrice, " Стоп = ", dMyStopLoss, " Тейк профит = ", dMyTakeProfit, " Лот = ", dMyLots);

   ObjectCreate( "order_buy_Stop_Loss_Line", OBJ_HLINE, 0, 0, dMyStopLoss, 0, 0, 0, 0 );
   ObjectSet( "order_buy_Stop_Loss_Line", OBJPROP_COLOR, Red );
   ObjectSetText( "order_buy_Stop_Loss_Line", "Stop_Loss_Line", 6, "Arial", Red );

   ObjectCreate( "order_buy_Take_Profit_Line", OBJ_HLINE, 0, 0, dMyTakeProfit, 0, 0, 0, 0 );
   ObjectSet( "order_buy_Take_Profit_Line", OBJPROP_COLOR, Lime );
   ObjectSetText( "order_buy_Take_Profit_Line", "Take_Profit_Line", 6, "Arial", Lime );

   int MyError = 0;
   int Answer = MessageBoxA( 0, "\"order_buy\"\nПереместите линии на необходимые уровни, и нажмите ОК",
		     "Установка ордера", MB_OKCANCEL | MB_ICONASTERISK | MB_TOPMOST);
		     
   if ( Answer == IDOK ) {
   
      dMyStopLoss = ObjectGet( "order_buy_Stop_Loss_Line", OBJPROP_PRICE1);
      dMyTakeProfit = ObjectGet( "order_buy_Take_Profit_Line", OBJPROP_PRICE1);

      while(true) {
      
         if(OrderSend(Symbol(),OP_BUY,dMyLots,dMyPrice,3,dMyStopLoss,dMyTakeProfit,
                      "Ordered by \"order_buy\" script" ,255,0,HotPink) <= 0) {

            MyError = PrintErrorDescription();

            if((MyError == ERR_NOT_ENOUGH_MONEY) || (MyError == ERR_TRADE_DISABLED) || (MyError == ERR_INVALID_TRADE_PARAMETERS)) {
                  MessageBoxA(0,ErrorDescription(MyError), "Ошибка", MB_OK | MB_ICONERROR); 
                  break;
            } else if(MyError == ERR_INVALID_STOPS) {
                     dMyStopLoss = ObjectGet( "order_buy_Stop_Loss_Line", OBJPROP_PRICE1);
                     dMyTakeProfit = ObjectGet( "order_buy_Take_Profit_Line", OBJPROP_PRICE1);
                     Print("Цена = ", dMyPrice, " Стоп = ", dMyStopLoss, " Тейк профит = ", dMyTakeProfit, " Лот = ", dMyLots);
            } else if(MyError == ERR_PRICE_CHANGED) {
                  MessageBoxA(0,"Цена успела измениться", "Ошибка", MB_OK | MB_ICONERROR); 
                  RefreshRates();
            } else {
                  // 10 seconds wait
                  Sleep(10000);
            }
            
         } else {
            Answer = MessageBoxA( 0, "Ордер успешно исполнен\nРаспечатать ордер?",
		     "Установка ордера", MB_OKCANCEL | MB_ICONASTERISK | MB_TOPMOST);
            if(Answer == IDOK ) {
               OrderPrint();
            }
            break;
         }
      }
   }

   return(MyError);
}

int PrintErrorDescription()
{
   int error=GetLastError();
   Print("Error = ",ErrorDescription(error));
   
   return(error);         
}

int deinit()
{
   ObjectDelete( "order_buy_Stop_Loss_Line");
   ObjectDelete( "order_buy_Take_Profit_Line");

   return(0);
}
 
Por cierto, si los desarrolladores de MQL4 lo "ven"
tengo de alguna manera un comportamiento inadecuado de la función Lowest y ArrayMinimum en el gráfico de EURUSD_H1
La cuestión es que aparentemente el mínimo debería coincidir con el valor del último viernes, pero no ocurre y obtengo un mínimo de dos días como mínimo.

El código de arriba, antes de que el gráfico cambie, por favor, compruébalo (es decir, antes del domingo por la noche).
¿Quizás estoy haciendo algo mal?
 
Inicio 05.02.05 17:14

la implementación es realmente cruda :) he estado escribiendo este script durante una hora y media.....
Lo sugerí como una idea, si te gusta, tendrás que refinarlo...


cuerno 06.02.05 06:45

¡gracias por el respeto ;) y la oportunidad es realmente el mar - hay que buscarla!



rty: si alguien sabe cómo hacer un mensaje "encima de todas las ventanas", que me lo diga, plz.... es tan indubitable.....
 
Un script muy interesante que muestra muchas posibilidades de uso de MQL4
para automatizar las operaciones rutinarias.

Aquí hay una versión seriamente corregida y en funcionamiento del script para la colocación de órdenes visuales:
//+------------------------------------------------------------------+
//|                                                    order_buy.mq4 |
//|                              Copyright c 2004, Alexander Ivanov. |
//|                                        mailto:alexander@indus.ru |
//+------------------------------------------------------------------+
//| Разрешите импорт функций из библиотек через:                     |
//| "Сервис -> Настройки -> Советники -> Разрешить импорт DLL"       |
//+------------------------------------------------------------------+
#property copyright "Copyright c 2004, Alexander Ivanov."
#property link      "mailto:alexander@indus.ru"

#include <WinUser32.mqh>
#include <stdlib.mqh>
#include <stderror.mqh>
//+------------------------------------------------------------------+
//| Указываем количество последних дней, на которых ищем минимум     |
//| для установки стоплосса                                          |
//+------------------------------------------------------------------+
#define DAYS_TO_CONSIDER 3
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int init() { return(0); }
int deinit()
  {  
//---- просто удалим свои линии стопов
   ObjectDelete( "order_buy_Stop_Loss_Line");
   ObjectDelete( "order_buy_Take_Profit_Line");
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Основная функция скрипта                                         |
//+------------------------------------------------------------------+
int start()
  {
   double DaysLowArray[];
   double dMyStopLoss = 0;  
   double dMyPrice = 0;
   double dMyTakeProfit = 0;
   double dMyLots = 0;
//---- скопируем массив дневных данных
   if(ArrayCopySeries(DaysLowArray, MODE_LOW, Symbol(),PERIOD_D1) < DAYS_TO_CONSIDER) 
     {
      return(-1);
     }
//---- расчет цен
   dMyPrice      = Ask;
   dMyStopLoss   = DaysLowArray[Lowest(Symbol(),PERIOD_D1,MODE_LOW,DAYS_TO_CONSIDER,0)];
   dMyTakeProfit = dMyPrice + 2*MathMax((MathAbs(Ask-Bid)/2),MathAbs(dMyPrice-dMyStopLoss));
   dMyStopLoss  -= 10*Point;
   dMyLots       = 0.1;
//---- выставим линии для визуального управления стопами
   ObjectCreate( "order_buy_Stop_Loss_Line", OBJ_HLINE, 0, 0, dMyStopLoss, 0, 0, 0, 0 );
   ObjectSet( "order_buy_Stop_Loss_Line", OBJPROP_COLOR, Red );
   ObjectSetText( "order_buy_Stop_Loss_Line", "Stop_Loss_Line", 6, "Arial", Red );

   ObjectCreate( "order_buy_Take_Profit_Line", OBJ_HLINE, 0, 0, dMyTakeProfit, 0, 0, 0, 0 );
   ObjectSet( "order_buy_Take_Profit_Line", OBJPROP_COLOR, Lime );
   ObjectSetText( "order_buy_Take_Profit_Line", "Take_Profit_Line", 6, "Arial", Lime );
//---- запросим подтверждение на отработку
   string quest="Вы хотите купить "+DoubleToStr(dMyLots,2)+" "+Symbol()+" по цене Ask "+
                DoubleToStr(dMyPrice,Digits)+"    \n\n"+
                "Переместите выставленные линии на необходимые уровни и нажмите ОК           \n"+
                "(красная линия - Stop Loss, зеленая - Take Profit)\n\n"+
                "Нажмите Отмена чтобы отказаться от сделки";
   if(MessageBoxA(0,quest,"Визуальная установка ордера на покупку",
                  MB_OKCANCEL | MB_ICONASTERISK | MB_TOPMOST)!=IDOK) return(-2);
//---- трейдер согласился, возьмем новые уровни стопов и обязательно проверим их!
   dMyStopLoss  =NormalizeDouble(ObjectGet( "order_buy_Stop_Loss_Line", OBJPROP_PRICE1),Digits);
   dMyTakeProfit=NormalizeDouble(ObjectGet( "order_buy_Take_Profit_Line",OBJPROP_PRICE1),Digits);
   
   if((dMyStopLoss>0 && dMyStopLoss>Ask) || (dMyTakeProfit>0 && dMyTakeProfit<Ask))
     {
      Print("Неправильно выставлены уровни Stop Loss и Take Profit!");
      MessageBoxA(0,"Неправильно выставлены уровни Stop Loss и Take Profit!         \n"+
                    "Операция отменена\n\n",
                    "Визуальная установка ордера на покупку",MB_OK | MB_ICONSTOP | MB_TOPMOST);
      return(-3);
     }
//---- выведем в лог сообщение об заявке
   Print("buy ",DoubleToStr(dMyLots,2)," ",Symbol()," at ",DoubleToStr(dMyPrice,Digits),
         "sl ",DoubleToStr(dMyStopLoss,Digits)," tp ",DoubleToStr(dMyTakeProfit,Digits));
//---- пробуем послать команду
   int ticket=OrderSend(Symbol(),OP_BUY,dMyLots,dMyPrice,3,dMyStopLoss,dMyTakeProfit,
                        "Ordered by \"order_buy\" script" ,255,0,HotPink);
   if(ticket>0) // все отлично - заявка прошла
     {
      //---- сразу же выведем в лог подтверждение
      Print("#",ticket," buy ",DoubleToStr(dMyLots,2)," ",Symbol()," at ",
            DoubleToStr(dMyPrice,Digits)," is done");
      //---- покажем окно 
      if(MessageBoxA(0,"Ордер успешно исполнен     \nРаспечатать его?",
		     "Визуальная установка ордера на покупку", MB_YESNO | MB_ICONASTERISK | MB_TOPMOST)==IDYES)
		  {
         OrderPrint();
        }
      //---- все ок, выходим
      return(0);
     }
//---- тут все плохо - выведем в лог сообщение
   int err=GetLastError();
   Print("buy ",DoubleToStr(dMyLots,2)," ",Symbol()," at ",
         DoubleToStr(dMyPrice,Digits)," failed [",ErrorDescription(err),"]");
//----покажем окно
   MessageBoxA(0,ErrorDescription(err), 
               "Ошибка визуальной установки ордера", MB_OK | MB_ICONERROR | MB_TOPMOST); 
   return(-4);
  }
//+------------------------------------------------------------------+



Lo que está arreglado:
1) se especifican todos los parámetros en Lowest(Symbol(),PERIOD_D1,MODE_LOW,DAYS_TO_CONSIDER,0),
parece que el error de Horn fue que no se estableció el valor por defecto. vamos a comprobar cómo se llama y funciona la función Lowest
2) NormalizeDouble - ¡esto es muy importante!
3) Comprobación previa de la corrección de los niveles de parada antes de enviar las órdenes
4) el comerciante recibe más información en las ventanas (en la primera versión del script sin leer el código era muy difícil entender lo que hace el script)
5) salida detallada y puntual de los registros
6) comentarios añadidos
7) Se ha eliminado el intento cíclico de enviar una solicitud - es muy importante.

 
Me gustaría profundizar en la recuperación de los errores de las solicitudes de envío y las repeticiones de envío.

Por desgracia, el uso de algoritmos en bucle como :

while(true)
  {
   if(OrderSend(....)<=0)
     {
      // проверимся
      Sleep(10000);
     }
  }


está absolutamente contraindicado, incluso prohibido.

Intentaré explicar a grandes rasgos la razón:
Si capturas un error, no podrás manejar todos los tipos de errores por ti mismo de todos modos. Es demasiado probable que se detecten unos cinco errores populares y se haga algo al respecto, pero que se sigan repitiendo las operaciones para el resto. Y Sleep(10000) no servirá de excusa para que el script envíe peticiones incorrectas. Los corredores simplemente bloquearán la cuenta.

Cómo debe proceder el redactor de un Asesor Experto:
1) Preparar una orden
a) comprobar que los parámetros de entrada del Asesor Experto son correctos
b) normalizar independientemente todos los precios y volúmenes (¡sí, esos también!) de la solicitud
c) comprobar de forma independiente todos los campos de la solicitud en busca de errores tontos, al menos - para que todos los precios sean más o menos correctos
d) antes de enviar la solicitud, mostrar los detalles de la solicitud en el registro

2) organizar el ciclo de envío de la solicitud
a) el ciclo debe ser finito, por ejemplo no más de 3 veces for(i=0;i<3;i++) y en ningún caso while(true)
b) si la solicitud pasa, entonces todo es fácil salida al registro, notificar al comerciante y salir
c) atrapado un error, entonces el punto 3

3) manejo de los errores de envío de órdenes
a) comprobar las situaciones en las que podemos recuperar, y para cualquier otro error - salir con notificaciones tan pronto como sea posible
b) los casos de recuperación elegir tan pocos como sea posible, sólo los más importantes y potencialmente recuperables
c) no intentar "empujar" su orden repetida pensando "tal vez todavía aceptan?"
d) contabilidad obligatoria del deslizamiento, al menos 1 punto (sea honesto consigo mismo, el deslizamiento es inevitable en el comercio real)

Uno de los puntos principales en el uso de la ejecución de órdenes de MQL4 - minimizar el número de órdenes.
Esto afecta directamente a la calidad de su servicio.

Además, para los expertos que escriben para el público, hay que escribir el código más infalible.
Y también para uso interno.

 
hhy: si alguien sabe como hacer un mensaje "encima de todas las ventanas", que me lo diga, por favor.... es tan poco intuitivo.....

He utilizado MB_TOPMOST, pruébalo, parece que me funciona.
 
¿dónde debo escribirlo?