OpenPosition() для MQL5 - страница 2

 
Prival:

.... Скрипт бы где показывалось как это все использовать (как это работает) легче было бы разобраться

//+------------------------------------------------------------------+
//|                                                         test.mq5 |
//|                                        Copyright 2010, KTS Group |
//|                                               http://www.koss.su |
//+------------------------------------------------------------------+
#property copyright "2010, KTS Group"
#property link      "http://www.koss.su"
#property version   "1.00"


#include <CH\TM.mqh>  


CTradingManager tm;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
    int mes=MessageBox("Вы действительно хотите открыть позицию?","Запрос",MB_ICONQUESTION|MB_YESNO);
    switch(mes)
     {
      case IDYES:
        tm.OpenPosition(Symbol(),ORDER_TYPE_BUY,0.1,0,0);
      break;
      
      case IDNO:
      break;
     }
                         
  }

Примитивный пример скрипта для открытия позиции. Как видите ничего сложного в этом нет.

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

 
Kos:
Разницы никакой. false=NULL=0, это просто привычка:)

Суть NULL похожа на суть void. И, если попытаться выразить эту суть одним словом - ничто.

Тип void - это такой тип, объектов которого не может быть по определению. Однако некоторые типы могут содержать в качестве составной части тип void. Например, функция может "возвращать объект типа void" для указания того, что данная функция ничего не возвращает и одновременно - для обеспечения невозможности использования "значения" этого "типа" в выражении. Иными словами, для невозможности, например, написать:

void fun()
{
  ...
}

int a = fun(); /* Ошибка, какой бы не был тип переменной a */

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

Разумно применено такое значение может быть лишь к указателю для указания того, что указатель не содержит адрес ни одного объекта/переменной, как существующих, так и, возможно, вновь созданных в процессе дальнейшей работы (и это гарантируется компилятором, то есть, ни один объект/переменная ни при каких условиях не могут иметь своим адресом значение NULL).

Более того, если использование типа void полностью отлавливается компилятором на этапе компиляции, и он имеет возможность просто отказаться компилировать такой код, то использование значения NULL может быть отловлено в общем случае только во время исполнения. При этом использование несуществующего значения NULL имеет такой же смысл, и должно приводить примерно к таким же последствиям, как и деление на 0.

В программах, написанных на языках C/C++ попытка использовать объект, неважно какого типа, по адресу NULL приводит к широко известным сообщениям вида "Программа выполнила недопустимую операцию...".

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

Кстати, использование NULL в качестве валидного значения для основных операций над типом показывает глубину понимания области разработчиками, несмотря на декларируемый ими опыт.

Да, ещё, наверное, не поздно "подправить" язык так, чтобы NULL не использовался более в качестве валидного значения для основных операций.

Для желающих расширить кругозор в популярной форме - NULL (Си).

 

Не наводите тень на плетень.

 
Prival:

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


Если предполагается открывать только BUY или SELL market order, то есть, имеется только ДВА возможных варианта, то имеет смысл использовать тип bool:

int OpenPosition(string sy, bool buy, double lot, double sl=0, double tp=0, int mn=0)

Тогда в коде будут две исчерпывающих ветви, и передать что-то отличное от указания BUY или SELL будет невозможно по определению (и не надо отслеживать эту ситуацию и обрабатывать её):

if(buy) {
  /* Actions for BUY */
} else {
  /* Actions for SELL */
}

А в оригинальном коде ведь в качестве op могут быть переданы значения, отличные и от ORDER_TYPE_BUY, и от ORDER_TYPE_SELL. В этом случае ни один из блоков

if(op==ORDER_TYPE_BUY) {
      trReq.price = NormalizeDouble(tick.ask,_Digits);                   // последняя цена ask
      trReq.sl = NormalizeDouble(tick.ask - sl*_Point,_Digits);          // Stop Loss
      trReq.tp = NormalizeDouble(tick.ask + tp*_Point,_Digits);          // Take Profit
      trReq.type = ORDER_TYPE_BUY;                                       // ордер на покупку
   }
if(op==ORDER_TYPE_SELL)  {
      trReq.price = NormalizeDouble(tick.bid,_Digits);                   // последняя цена Bid
      trReq.sl = NormalizeDouble(tick.bid + sl*_Point,_Digits);          // Stop Loss
      trReq.tp = NormalizeDouble(tick.bid - tp*_Point,_Digits);          // Take Profit
      trReq.type= ORDER_TYPE_SELL;                                       // ордер на продажу
  }

не отработает, хотя наверняка имеется ввиду, что ровно один из них должен отработать. Кстати, в подобных случаях полезен switch:

switсh(op) {
case ORDER_TYPE_BUY:
      trReq.price = NormalizeDouble(tick.ask,_Digits);                   // последняя цена ask
      trReq.sl = NormalizeDouble(tick.ask - sl*_Point,_Digits);          // Stop Loss
      trReq.tp = NormalizeDouble(tick.ask + tp*_Point,_Digits);          // Take Profit
      trReq.type = ORDER_TYPE_BUY;                                       // ордер на покупку
      break;
case ORDER_TYPE_SELL:
      trReq.price = NormalizeDouble(tick.bid,_Digits);                   // последняя цена Bid
      trReq.sl = NormalizeDouble(tick.bid + sl*_Point,_Digits);          // Stop Loss
      trReq.tp = NormalizeDouble(tick.bid - tp*_Point,_Digits);          // Take Profit
      trReq.type= ORDER_TYPE_SELL;                                       // ордер на продажу
      break;
default: /* Здесь будут отловлены все остальные случаи, то есть, когда op и не ORDER_TYPE_BUY, и не ORDER_TYPE_SELL */
      Print("AAAAAAAAAAAAAA!!!");
}
Вместо "магических" чисел
case 10004:

используют

case TRADE_RETCODE_REQUOTE:

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

Во-вторых, чтобы код был сразу понятен, обладал некоторой самодокументированностью, и не надо было бы к "магическому" числу дописывать комментарий вида /* TRADE_RETCODE_REQUOTE */.

Большую задачу разбивают на подзадачи, каждой подзадаче сопоставляют функцию. Большие подзадачи, в свою очередь, таким же образом разбиваются на подзадачи и оформляются в виде функций. Это - очень мощный метод для решения, казалось бы, на первый взгляд, неподъёмных задач, несмотря на свою простоту.

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

Если же всё свалить в одну большую функцию, то, с какого-то момента сложности, код становится неуправляемым. При таком подходе с некоторого момента любые усилия приводят к нулевому продвижению вперёд.

В идеале каждая функция должна умещаться на экране монитора (скажем, не более 50 строк). Для написания более длинной функции должны быть веские основания (например, "длинный" switch, в котором обрабатывается очень много case'ов).

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

Разбиение на подзадачи должно подчиняться принципу "однородности" - если подзадача-функция выполняет два блока действий, каждый из которых имеет мало отношения к другому, то позадача должны быть разбита на две подподзадачи. Например, из оригинальной функции имеет смыл вынести в отдельную функцию обработку ошибок switch(answer), с тем, чтобы вместо этого большого switch'а в коде стоял вызов этой отдельной функции.

Документация по MQL5: Основы языка / Типы данных / Целые типы / Тип bool
Документация по MQL5: Основы языка / Типы данных / Целые типы / Тип bool
  • www.mql5.com
Основы языка / Типы данных / Целые типы / Тип bool - Документация по MQL5
 
Renat:

Не наводите тень на плетень.

Ну, прочтите информацию на Википедии, там тема некорректности использования значения NULL как валидного вполне раскрыта.

Также полезно посмотреть перевод самого слова null. Один из синонимов к нему, кстати, - invalid, как это не смешно.

 
simpleton:
Ну, прочтите информацию на Википедии, там тема некорректности использования значения NULL как валидного вполне раскрыта.

Я предлагаю не мелочиться, заклеймить Кернигана, Риччи, Страуструпа и обязательно подать иск в Европейский Суд по правам человека девелопера со ссылкой на некую "тему некорректного использования". Странно, что Вы перешли на столь туманную формулировку без четкого указания на проблему?

А пока смотрим на следующий код в MSVS C++ 2008 (в режиме максимальных ворнингов) или Intel C++ 11 и не видим ни единого предупреждения про NULL:

int _tmain(int argc, _TCHAR* argv[])
  {
   char   var1=NULL;
   int    var2=NULL;
   long   var3=NULL;
   char  *var4=NULL;
   int   *var5=NULL;
   long  *var6=NULL;
   return(0);
  }

Будьте аккуратнее с излишне активным толкованием теории, пожалуйста. Ибо в реальности Вы его пытаетесь использовать во вред.

 

В MQL5 очень жесткий статический контроль синтаксиса на этапе компиляции и динамический type контроль на этапе выполнения. Отказ от классических ссылок С/С++ позволил сделать реально контролируемый код. 

Никто не заставляет использовать NULL в качестве заменителя нуля. Но если очень хочется, то используйте по аналогии с C/C++.

 
simpleton:

Ну, прочтите информацию на Википедии, там тема некорректности использования значения NULL как валидного вполне раскрыта.

Также полезно посмотреть перевод самого слова null. Один из синонимов к нему, кстати, - invalid, как это не смешно.

 

По памяти из MSC 5.0 года примерно 1988 (когда инты были 2-байтовыми, а лонги 4-байтовыми)

#define NUL 0

#define NULL 0L 

 
Renat:

Я предлагаю не мелочиться, заклеймить Кернигана, Риччи, Страуструпа и обязательно подать иск в Европейский Суд по правам человека девелопера со ссылкой на некую "тему некорректного использования". Странно, что Вы перешли на столь туманную формулировку без четкого указания на проблему?

А пока смотрим на следующий код в MSVS C++ 2008 (в режиме максимальных ворнингов) или Intel C++ 11 и не видим ни единого предупреждения про NULL:

int _tmain(int argc, _TCHAR* argv[])
  {
   char   var1=NULL;
   int    var2=NULL;
   long   var3=NULL;
   char  *var4=NULL;
   int   *var5=NULL;
   long  *var6=NULL;
   return(0);
  }

Будьте аккуратнее с излишне активным толкованием теории, пожалуйста. Ибо в реальности Вы его пытаетесь использовать во вред.

 

В MQL5 очень жесткий статический контроль синтаксиса на этапе компиляции и динамический type контроль на этапе выполнения. Отказ от классических ссылок С/С++ позволил сделать реально контролируемый код. 

Никто не заставляет использовать NULL в качестве заменителя нуля. Но если очень хочется, то используйте по аналогии с C/C++.

Вы ставите себя (как фирму, коллектив разработчиков) в один ряд с этими громкими именами? Европейский Суд? Велико же самомнение.

Проблема чётко сформулирована обсуждавшими: "Какая разница между false и NULL?". Странно как раз то, что Вы этого не увидели. Или уже не странно, потому что для Вас это стало характерно? Взгляните на цитату, на которую я отвечал в своём первом сообщении, там именно про разницу.

Что доказывает отсутствие предупреждений при компиляции приведённого кода одной или другой реализацией компилятора в режиме C++? Ровным счётом ничего.
Кстати, хочу заметить: хороши же у Вас аргументы! Апеллируете не к Стандарту C++, а к поведению неких реализаций компилятора языка! Подобный подход значительно более напоминает подход любителя, нежели профессионала.

В Стандарте C++ 2003-го года сказано по поводу NULL:

C.2.2.3 Macro NULL
1 The macro NULL, defined in any of <clocale>, <cstddef>, <cstdio>, <cstdlib>, <cstring>,
<ctime>, or <cwchar>, is an implementation-defined C  +  + null pointer constant in this International

Standard (18.1).

Прошу заметить, - сказано чётко: "null pointer constant". Смотрим ссылку на 18.1:

18.1 Types
...
4 The macro NULL is an implementation-defined C  +  + null pointer constant in this International Standard
(4.10). 180)

И опять: "null pointer constant".

Ссылка 180 (которая, кстати, объясняет, почему нет предупреждений для приведённого Вами кода):

180)
Possible definitions include 0 and 0L, but not (void*)0.

И, чтобы завершить цепочку ссылок, имеющуюся в процитированных отрывках и относящихся к NULL:

4.10 Pointer conversions
1 A null pointer constant is an integral constant expression (5.19) rvalue of integer type that evaluates to
zero.  A null pointer constant can be converted to a pointer type; the result is the null pointer value of that
type and is distinguishable from every other value of pointer to object or pointer to function type.

Поскольку в действующем Стандарте C++ явно указано, что возможные определения для NULL есть 0 или 0L, то в первой строке тела функции приведённого кода, а также во второй или третьей, в зависимости от того, как в конкретной реализации компилятора определён NULL, происходит неявное приведение типа, только и всего.

А теперь вопрос: что Вы доказали утверждением о том, что компилятор предупреждений не выдаёт на этот код? Верный ответ: ничего.

То, о чём пишу я - не теория. Вы профессионализм теорией любите почему-то называть.

Люди стали спорить: что лучше? Что лучше для типа bool, NULL или false, и чем они отличаются? Я объяснил, в чём разница.

Попробуйте найти в стандарте упоминание о NULL ВНЕ связи с null pointer constant/value, а в связи с чем-либо другим, отличным от указателя. У Вас же в языке это - запросто, и Вы не хотите понять это и пресечь. Или это так здорово - во всех языках, где есть логический тип, - два значения, а у нас - три?

Язык C++ имеет достаточное количество своих нехороших проблем, в том числе и в связи с определение NULL как целочисленного константного выражения, значение которого есть 0. Например, если есть две перегруженные функции, void foo(char *); и void foo(int);, то вызов foo(NULL); будет вызовом foo(int), а не foo(char*).

Именно поэтому, чтобы, наконец-то, уйти от проблем, порождённых "некачественным" NULL прежних времён, в планирующемся стандарте C++0x собираются исправить это с помощью введения нового ключевого слова nullptr служащего в качестве отдельной null pointer constant, о чем можно кратко прочесть, например, здесь. Будете тогда предлагать заменить в своём вышеприведённом коде NULL на nullptr и смотреть, будут ли предупреждения? Вопрос риторический, задан для того, чтобы Вам стала понятна абсурдность Вашей позиции по данному вопросу. Лучше исправьте язык MQL5 в смысле верной трактовки NULL, а не позорьтесь как разработчик с 20-летним стажем.
 
stringo:

По памяти из MSC 5.0 года примерно 1988 (когда инты были 2-байтовыми, а лонги 4-байтовыми)

#define NUL 0

#define NULL 0L 

В то время не было Стандарта даже по C (через год вышел), а C++ был ещё в полуэмбриональном состоянии, когда, например, operator new реализовывался прямым присваиванием указателю this.

Опять же, характерна апелляция к реализациям, да ещё таким древним, а не к Стандарту.

Вы - ведущий разработчик? Прочтите мой ответ Renat'у.

 

Теоретик детектед.

Практика есть мерило реальности, а не игры теоретиков.

"Некие реализации языка" являются конечным мерилом приемлемости и главным мейнстримом в разработке на протяжении многих лет. В С++ int i=NULL; работает и будет работать без выдачи ошибок до скончания веков ибо никуда не деться от тонны созданного кода.

В MQL5 документации нет никаких указаний использовать NULL неправильно. Но никто не остановит программистов испортить свой код плохими конструкциями.

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