Любой вопрос новичка, чтоб не захламлять форум. Профи, не проходите мимо. Без вас никуда - 6. - страница 739

 
korobok777:
Lot=NormalizeDouble(Balance*0.001,2);
 
Vinin:
Что-то Вы не то написали

Да, опечатка, поправил. Или принцип не тот? Смысл был в том, что если баланс делится на 10 без остатка, лот берём как произведение начального лота на 1/10 баланса. Не так? А как тогда?


Хотя Вадим тут проще написал, да )))

 
evillive:

Да, опечатка, поправил. Или принцип не тот? Смысл был в том, что если баланс делится на 10 без остатка, лот берём как произведение начального лота на 1/10 баланса. Не так? А как тогда?


Хотя Вадим тут проще написал, да )))

Баланс очень редко делится без остатка на 10. В остальных случаях (в большинстве) был бы лот по умолчанию
 
evillive:
double StartLot=0.01;
if(MathMod(AccountBalance(),10)==0) Lot=StartLot*AccountBalance()/10;

А MarketInfo()?

А MODE_MINLOT, MODE_MAXLOT, MODE_LOTSTEP?

Нужно же ещё попасть в разрешённую разрядную сетку значений лотов:

#property strict

/******************************************************************************/
double getLot(double factor = 0.001) {
  double minLot = MarketInfo(Symbol(), MODE_MINLOT);

  if (minLot > 0) { // Проверка значения от функции MetaQuotes на вменяемость
    double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);

    if (maxLot >= minLot) { // Проверка второго значения от функции MetaQuotes на вменяемость
      double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);

      if (lotStep > 0) { // Проверка третьего значения от функции MetaQuotes на вменяемость
        double rawLot = AccountBalance() * factor; // Грубо вычисленное значение лота

        // В процессе "рихтования" грубо вычисленного значения лота подразумевается, что "округление" происходит всегда к меньшему
        if (rawLot >= minLot && rawLot < maxLot + lotStep) { // Если грубо вычисленное значение "влезает" в диапазон разрешённых значений лотов
          int stepNum = int((rawLot - minLot) / lotStep); // Количество step'ов, которое надо "отступить вправо на числовой оси" от минимального значения лота (при преобразовании double -> int как раз и происходит нужный тип округления)

          return minLot + lotStep * stepNum; // Вычисляем значение лота в "разрядной сетке" разрешённых лотов.
        }
      }
    }
  }

  return 0; // Какие-то обстоятельства не позволили выдать значение в "разрядной сетке" разрешённых лотов; для индикации данного события выдаётся специальное значение 0.
}

/******************************************************************************/
void OnStart() {
  Print("AccountBalance() = ", AccountBalance(), ", getLot() = ", getLot());
}

Прогнал, получил нечто похожее на правду:

0       20:09:49.699    Script 3 EURUSDm,H1: loaded successfully
0       20:09:49.699    3 EURUSDm,H1: initialized
0       20:09:49.699    3 EURUSDm,H1: AccountBalance() = 152.82, getLot() = 0.15
0       20:09:49.699    3 EURUSDm,H1: uninit reason 0
0       20:09:49.699    Script 3 EURUSDm,H1: removed

Ошибиться, вроде, не удалось.

 
simpleton:

А MarketInfo()?

А MODE_MINLOT, MODE_MAXLOT, MODE_LOTSTEP?

Нужно же ещё попасть в разрешённую разрядную сетку значений лотов:

Прогнал, получил нечто похожее на правду:

Ошибиться, вроде, не удалось.

Спасибо, мне уже обьяснили :D

Понятно, что для себя я пишу со всеми проверками, как надо, там был просто набросок как лот к соотношению баланс/10 привести, но идея неудачная была...

Но у вас что-то много текста, можно и проще:

  lotstep= MarketInfo(Symbol(),MODE_LOTSTEP);
  lotmax=MarketInfo(Symbol(), MODE_MAXLOT);
  lotmin=MarketInfo(Symbol(), MODE_MINLOT);

lot=lotstep*MathRound(AccountBalance()*0.001/lotstep);
if(lot < lotmin) lot = lotmin;
if(lot > lotmax) lot = lotmax;
 
simpleton:

А MarketInfo()?

А MODE_MINLOT, MODE_MAXLOT, MODE_LOTSTEP?

Нужно же ещё попасть в разрешённую разрядную сетку значений лотов:

Прогнал, получил нечто похожее на правду:

Ошибиться, вроде, не удалось.

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

double Lot = NormalizeDouble(AccountBalance()/1000,2);
if(Lot<Min_Lot)Lot=Min_Lot;
 
_new-rena:

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

У некоторых шаг лота не 0,01 а, например, 0,03 или вовсе 0,1. И как тогда? Проверки нужны на все случаи, благо много времени не занимает.
 
evillive:
У некоторых шаг лота не 0,01 а, например, 0,03. И как тогда? Проверки нужны на все случаи, благо много времени не занимает.
задаешь (ниже) в ините и больше не мучаешь сервак и комп
double Min_Lot=MarketInfo(Symbol(), MODE_MINLOT);
 
речь про шаг, а не мин. лот, но ладно, проехали.
 
_new-rena:

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

Потому что всякая хрень поджидает на каждом шагу, и нужно защищаться. Если не защититься, будет очень низкое качество, которое, в конечном счёте, может обойтись очень дорого. 90% усилий тратится на обеспечение защиты от всяких хреней и только 10% - собственно, на решение самой задачи. В случае MT4 и MQL4++ соотношение ещё более асимметричное.

Хрень начинается ещё во время чтения документации:

Возвращаемое значение

Информация о финансовом инструменте. Часть информации о текущем финансовом инструменте хранится в предопределенных переменных.

Всё. Обязана вернуть информацию о финансовом инструменте, и никак иначе. Других исходов не предусмотрено. Получаем информацию об инструменте "Фигня":

#property strict

/******************************************************************************/
void OnStart() {
  Print("MarketInfo(\"Фигня\", MODE_MINLOT) = ", MarketInfo("Фигня", MODE_MINLOT));
  Print("MarketInfo(\"Фигня\", MODE_MAXLOT) = ", MarketInfo("Фигня", MODE_MAXLOT));
  Print("MarketInfo(\"Фигня\", MODE_LOTSTEP) = ", MarketInfo("Фигня", MODE_LOTSTEP));
}

Смотрим, каковы параметры лотности для этого инструмента:

0       21:12:18.980    Script 3 EURUSDm,H1: loaded successfully
0       21:12:18.980    3 EURUSDm,H1: initialized
0       21:12:18.980    3 EURUSDm,H1: MarketInfo("Фигня", MODE_MINLOT) = 0.0
0       21:12:18.980    3 EURUSDm,H1: MarketInfo("Фигня", MODE_MAXLOT) = 0.0
0       21:12:18.980    3 EURUSDm,H1: MarketInfo("Фигня", MODE_LOTSTEP) = 0.0
0       21:12:18.980    3 EURUSDm,H1: uninit reason 0
0       21:12:18.980    Script 3 EURUSDm,H1: removed

Интересные параметры. Я не знаю, почему в документации не описано поведение данной функции в случае ошибочных ситуаций. Придётся пользоваться недокументированными особенностями, выясненными в процессе наблюдения за поведением данной функции.

Итак, для данных запрашиваемых параметров, значения которых по природе своей должны отличаться от 0, функция MarketInfo() может вернуть 0, что является недокументированным признаком ошибочной ситуации. Код обязан проверить, не возникла ли ошибка при запросе каждого из параметров. Только по этой причине 3 проверки в коде обеспечены.

Далее. Очевидно, что вычисленный размер лота может не уложиться в диапазон разрешённых размеров лота. Не будем проверять? Или, всё-таки явно запрограммируем данную ситуацию и запрограммируем потом в верхнеуровневом коде реакцию на неё, а не "как оно само получится"? Примером того, как оно выглядит, когда не всё запрограммировано, и работает так, как оно само получается, может служить очередной свежий выпуск MT4, когда что-то где-то съехало, где-то чудесато заглючило, а где-то вообще перестало работать. Наверное, это не тот результат, который хочется получить?

Код развёрнут и прокомментирован, чтобы был виден ход мысли и применяемая модель вычисления. Раз модель лотности, установленная MetaQuotes, выполнена в виде "разрядной сетки значений ордеров", заданной параметрами MINLOT, MAXLOT и LOTSTEP, то логичнее в этих терминах и вычислять конкретное значение лота. Модель вычисления поэтому и была выполнена в этих терминах.

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

Для большей компактности кода все 3 значения можно было бы получить сразу и проверить все 3 условия сразу в одном if'е. Но, в случае ошибки при первом же вызове, 2 других вызова представляли бы из себя бесполезную трату вычислительных ресурсов.

Замечу, что при программировании выражения, где используется деление на lotStep, специально было обращено внимание на то, что оно используется под if'ом, в котором только что проверено, что значение lotStep отличается от 0, то есть, деления на 0 там произойти не может. В принципе, код можно ещё улучшить, объявив все переменные на "double" и "int", а "const double" и "const int", защитившись от самого себя при последующей возможной модификации кода. В частности, если под if'ом, в котором только что была проверена отличность значения переменой lotStep от 0, случайно в каком-нибудь вновь добавленном в этом месте коде ошибочно присвоить этой переменной значение 0, то далее в выражении возникнет деление на 0. Если же переменная будет объявлена как "const double", то компилятор, я надеюсь, мгновенно сообщит о неправомерной попытке деяния по модификации переменной lotStep, тем самым не дав ошибиться таким образом.

Так что "полукилометры" обусловлены суровыми объективными условиями, а не чьей-то прихотью.

Как ветка называется? Уж, если помогать, то - как следует, чтобы можно было реально чему-то научиться.

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