Полезные функции от KimIV - страница 110

 
Спасибо за разъяснения, теперь буду двигаться дальше)))))
 

Функция WritingLineInFile().

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

Параметры функции WritingLineInFile():

  • fn - наименование файла
  • st - строка, записываемая в файл
  • fs - первая строка (шапка таблицы)

//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 28.04.2012                                                     |
//+----------------------------------------------------------------------------+
//|  Описание : Запись строки в файл                                           |
//|  Параметры:                                                                |
//|    fn - имя файла                                                          |
//|    st - строка                                                             |
//|    fs - первая строка (шапка таблицы)                                      |
//+----------------------------------------------------------------------------+
void WritingLineInFile(string fn, string st, string fs="") {
  int fh=FileOpen(fn, FILE_READ|FILE_WRITE, " ");

  if (fh>0) {
    if (FileSize(fh)==0 && StringLen(fs)>0) FileWrite(fh, fs);
    FileSeek (fh, 0, SEEK_END);
    FileWrite(fh, st);
    FileClose(fh);
  }
}

ЗЫ. Во вложении скрипт для тестирования функции.

Файлы:
 
Добрый вечер, Игорь! Остановилась на функции
DateBeginQuarter

в первую очередь пытаюсь понять строки:

int ye=Year()-MathFloor(nq/4);
  nq=MathMod(nq, 4);

по умолчанию nq = 0, поэтому не ясно что мы получаем от выражения MathMod(nq/4), ведь результат всегда будет 0. Так же не ясна вторая строка, так как 0/4 не имеет остатка, разъясните пожалуйста.

 

Благодарю, Наташа, за вопрос. Благодаря Вам, я заново проверил работу функции и нашёл ошибку. В строке

int ye=Year()-MathFloor(nq/4);

нужно заменить знак минус на плюс

int ye=Year()+MathFloor(nq/4);

А теперь по существу Вашего вопроса. nq ведь не всегда равно нулю. Могут быть любые целые значения, в том числе и отрицательные. Указанные Вами строки работают в случаях, когда nq кратно 4, то есть, когда нужно прибавить или отнять 4 квартала (год).

 
KimIV:

Благодарю, Наташа, за вопрос. Благодаря Вам, я заново проверил работу функции и нашёл ошибку. В строке

нужно заменить знак минус на плюс

А теперь по существу Вашего вопроса. nq ведь не всегда равно нулю. Могут быть любые целые значения, в том числе и отрицательные. Указанные Вами строки работают в случаях, когда nq кратно 4, то есть, когда нужно прибавить или отнять 4 квартала (год).

Спасибо за ответ, Игорь.... с функцией разбиралась дольше обычного, но все же разобралась))))))) в этой же функции, мне кажется, не нужно уменьшать год в выражении:

 if (mo<1) {
    mo+=12;
    ye--;

тогда все будет верно.

 
Lisi4ka330:

...в этой же функции, мне кажется, не нужно уменьшать год в выражении...

Обоснуйте, Наташа, почему не нужно? Мне, наоборот, представляется логичным уменьшать год после замыкания месячного круга в обратную сторону. В указанном Вами выражении уменьшить год - это тоже самое, что передвинуть часовую стрелку на один час назад после того, как минутную отмотали на целый круг. Приведите свой вариант функции, обсудим... может быть Ваш вариант окажется удачнее моего.
 

Функция GetDrawdownOpenPosInPoint()

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

  • sy - Наименование инструмента. Если задать этот параметр, то функция проверит позиции только заданного инструмента. NULL означает текущий инструмент, а "" (по умолчанию) - любой инструмент.
  • op - Торговая операция, тип позиции. Допустимые значения: OP_BUY, OP_SELL или -1. Значение по умолчанию -1 - означает любую позицию.
  • mn - Идентификатор позиции (MagicNumber). Значение по умолчанию -1 - любой магик.
  • tf - Таймфрейм графика, на котором смотреть значения High и Low баров. Значение по умолчанию 0 - текущий таймфрейм.
//+----------------------------------------------------------------------------+
//|  Автор    : Ким Игорь В. aka KimIV,  http://www.kimiv.ru                   |
//+----------------------------------------------------------------------------+
//|  Версия   : 01.05.2012                                                     |
//|  Описание : Возвращает максимальную просадку в пунктах текущих открытых    |
//|             позиций.                                                       |
//+----------------------------------------------------------------------------+
//|  Параметры:                                                                |
//|    sy - наименование инструмента   (""   - любой символ,                   |
//|                                     NULL - текущий символ)                 |
//|    op - операция                   (-1   - любая позиция)                  |
//|    mn - MagicNumber                (-1   - любой магик)                    |
//|    tf - таймфрейм                  ( 0   - текущий таймфрейм)              |
//+----------------------------------------------------------------------------+
int GetDrawdownOpenPosInPoint(string sy="", int op=-1, int mn=-1, int tf=0) {
  if (sy=="0") sy=Symbol();
  if (tf==0) tf=Period();

  datetime to=TimeOpenFirstPos(sy, op, mn); // Время открытия первой позиции
  datetime tb=GetTimeOpenBar(sy, tf, to);
  int      dd, md=0;                        // Просадка
  double   po, sp;                          // Пункт, спрэд
  int      i, k=OrdersTotal();              // Номера позиций
  int      nb;                              // Номер бара

  if (tb>0) {
    while (tb<TimeCurrent()) {
      dd=0;
      for (i=0; i<k; i++) {
        if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {
          if ((OrderSymbol()==sy || sy=="") && (mn<0 || OrderMagicNumber()==mn)) {
            if ((op<0 || OrderType()==op) && (OrderType()==OP_BUY || OrderType()==OP_SELL)) {
              if (tb>OrderOpenTime()) {
                nb=iBarShift(OrderSymbol(), tf, tb, True);
                if (nb>=0) {
                  po=MarketInfo(OrderSymbol(), MODE_POINT);
                  if (po==0) Message("В обзоре рынка отсутствует символ "+OrderSymbol()+". Точность расчётов не гарантируется!");
                  else {
                    if (OrderType()==OP_BUY) {
                      dd+=(OrderOpenPrice()-iLow(OrderSymbol(), tf, nb)+po)/po;
                    }
                    if (OrderType()==OP_SELL) {
                      sp=po*MarketInfo(OrderSymbol(), MODE_SPREAD);
                      dd+=(iHigh(OrderSymbol(), tf, nb)-OrderOpenPrice()+sp)/po;
                    }
                  }
                }
              }
            }
          }
        }
      }
      if (md<dd) md=dd;
      tb+=60*tf;
    }
  }
  return(md);
}

ЗЫ. Во вложении скрипт для тестирования функции GetDrawdownOpenPosInPoint().

 
KimIV:
Обоснуйте, Наташа, почему не нужно? Мне, наоборот, представляется логичным уменьшать год после замыкания месячного круга в обратную сторону. В указанном Вами выражении уменьшить год - это тоже самое, что передвинуть часовую стрелку на один час назад после того, как минутную отмотали на целый круг. Приведите свой вариант функции, обсудим... может быть Ваш вариант окажется удачнее моего.

Я рассуждала так: допустим нам нужно определить начало 7 квартала в прошлом и будущем, тогда nq= -7 и nq=7 соответственно. Mathfloor вернет -2 для прошлого и +1 для будущего (судя по описанию функции в документации), следовательно для ситуации в прошлом мы будем вычитать на один год больше, чем прибавлять в будущем..... если продолжать дальнейшие вычисления для прошлого, то нам придется еще раз уменьшить год и мы окажемся в 2009.....

К сожалению из-за нехватки времени (я едва успеваю прочесть страничку сайта), я не могу сейчас предоставить правильный на мой взгляд код, но думаю при необходимости подправить его будет не сложно.

 
Lisi4ka330:

Я рассуждала так: допустим нам нужно определить начало 7 квартала в прошлом и будущем, тогда nq= -7 и nq=7 соответственно. Mathfloor вернет -2 для прошлого и +1 для будущего (судя по описанию функции в документации), следовательно для ситуации в прошлом мы будем вычитать на один год больше, чем прибавлять в будущем..... если продолжать дальнейшие вычисления для прошлого, то нам придется еще раз уменьшить год и мы окажемся в 2009...

Я согласен с Вашими рассуждениями, но Вы забываете о типах данных, участвующих в операциях. От функции MathFloor() вообще можно отказаться. Посмотрите результат работы скрипта во вложении.

Файлы:
test.mq4  1 kb
 
Добрый день, Игорь)))) Если честно, я не совсем поняла Ваш ответ, и даже вложенный скрипт не внес ясность, а скорее наоборот...)))) но думаю со временем разберусь)))) Подскажите пожалуйста, для чего в строке return(StrToTime(ye+"."+mo+".01")) стоят плюсы.