Обсуждение статьи "Написание советника в MQL5 с использованием объектно-ориентированного подхода" - страница 2

 
Yedelkin:
Если Bid при открытии будет на 1.2695, то 5 пунктов убытка мы уже имеем автоматически. Если при этом SL составляет по замыслу разработчика 50 pips, то до его срабатывания осталось пройти в неблагоприятном направлении ещё 45 pips. Т.е. при срабатывании стоплосса Bid должен быть не на 1.2645, а на 1.2650; а Ask, соответственно, - на 1.2655.

1. На счет убытка в 5 pips при открытии

На счет убытков вы  правы, если закрыть позицию в тот же момент (условно) то мы получим убыток в размере спреда, те самые 5 pips.

Поскольку лонги прикрываются по цене Bid (встречной).

По крайней меры по логике вещей в этом случае мы должны получить этот убыток (и это правильно).

Это также справедливо для закрытия встречным ордером. Как вы думаете какой результат мы получим при срабатывании встречного ордера по цене 1,2695 (а ведь там в данный момент находится Bid)?

Ну не будете же вы утверждать, что ценой открытия ШОРТОВых поз является Ask?

2. Давайте разбираться с закрытием по БУ

Мы помним что мы открылись в Buy по 1,27 (эта цена для нас сейчас является уровнем БУ)

Разумно предположить то, что в закрытие по БУ произойдет в том случае если если цена Bid достигнет значения 1,27 (т.е пройдет ровно 5 пипсов вверх)

Проверим наше утверждение закрытием по БУ при помощи встречного ордера. Цена открытия такой позиции должна быть на 1.27, а как известно ордера открытые Sell выставляются по Bid. В настоящее время Bid находится на 1.2695. Следовательно для закрытия в БУ ему нужно пройти 5 пипсов, а значит ошибки в расчетах нет и утверждение верно.

3. На счет SL и TP

Тут рулят два утверждения:

а. Лонги открываются по Ask, а закрываются по Bid; Шорты открываются по Bid, а закрываются по Ask

б. Расстояние до TP и SL рассчитываются от цены открытия (Open Price), расчет происходит с учетом направления позиции


В точном соответствии со вторым утверждением мы определим для нашего примера цены SL и TP. При цене открытия 1,27 SL = 1.2650, а TP = 1.28 (согласно условиям описанным выше).

Согласно первому утверждению ЛОНГ (а в примере именно он) откроется при условии что Ask будет равно 1.27 (при этом Bid будет равен 1.2695, исходя из спреда в 5 pips)

4. Теперь определимся с тем при каких условиях сработают наши SL и TP

Наша позиция будет закрыта при удовлетворении одного из условий (если нет других факторов):

По TP - Если Bid достигнет 1,28 (100 pips от 1,27), Ask в это время будет находится на 1,2805 (тут рулят первое утверждение и размер спреда). 

Проверим наше утверждение закрытием по TP при помощи встречной позы. Цена открытия такой позиции должна быть на 1.28, а как известно ордера открытые Sell выставляются по Bid. В настоящее время Bid находится на 1.2695. Следовательно для закрытия по TP нужно пройти 5 пипсов (для покрытия потерь по спреду) + 100 пипсов до фиксации профита.

По SL - Если цена дойдет до уровня SL, равного как мы помним 1,2650.


Теперь давайте разбираться какая это будет цена. По логике вещей это должна быт цена по Bid (что соответствует цене открытия встречного ордера)

Мы помним о том, что в настоящее время (по условию открытия позиции) Bid находится на 1.2695. Следовательно, до срабатывания SL цене нужно пройти 45 пипсов.

Таким образом мы зафиксируем убыток равный спреду (5 пунктов) + 45 пунктов которые цена успела протий до срабатывания SL.

С этой точки зрения вы правы

Проверим наше утверждение закрытием по SL при помощи встречной позы. Цена открытия такой позиции должна быть на 1.2650, а как известно ордера открытые Sell выставляются по Bid. В настоящее время Bid находится на 1.2695. Следовательно для закрытия по SL нужно пройти 45 пипсов. При срабатывании SL будет зафиксирован убыток в размере 50 пипсов (5 пипсов по спреду + 45 по ходу против нас).

PS

Но с этой точки зрения мне не очень понятен вот этот пример для MQL4

int ticket;

  if(iRSI(NULL,0,14,PRICE_CLOSE,0)<25)
    {
     ticket=OrderSend(Symbol(),OP_BUY,1,Ask,3,Bid-25*Point,Ask+25*Point,"My order #"+counter,16384,0,Green);
     if(ticket<0)
       {
        Print("OrderSend failed with error #",GetLastError());
        return(0);
       }
    }

Верней мне не очен понятно на основании какой логики и каких утверждений считается SL и только он.

Но исходя из этого примера (и только из него) я получаю следующее

//Базовый пример
ticket=OrderSend(Symbol(),OP_BUY,1,Ask,3,SL = Bid-Loss*Point,TP = Ask+Profit*Point,"My order #"+counter,16384,0,Green);
//Приказ на открытие рыночной позиции
ticket=OrderSend(Symbol(),OP_BUY,1,1.27,3,1.2645 = 1.2695-50*Point,1.28 = 1.27+100*Point);

Исходя из значений Open = 1.27, SL = 1.2645 и TP = 1.28 я понимаю следующее:

1. Позиция открывается когда Ask достигает цены 1.27 (в нашем случае он уже на ней);

2. Уровень БУ расположен на цене 1,27 и чтобы закрыться по нему курс символа (в нашем случае EUR) должен вырасти на размер спреда (в нашем случае 5 пунктов);

3. В момент открытия мы сразу получаем убыток в размере спреда (в том случае если МГНОВЕННО закрыть позицию), поскольку открытая позиция, исходя из логических утверждений, должна закрыться встречным ордером. В коде MQL4 такая операция будет выглядеть следующим образом

//Базовый пример
ticket=OrderSend(Symbol(),OP_SELL,1,Bid,3,0,0);
//Закрытие позиции по рынку встречным ордером
ticket=OrderSend(Symbol(),OP_SELL,1,1.2695,3,0,0);

4. TP срабатывает после того как цена достигает уровня 1.28. Исходя из логики это должна быть цена Bid, поскольку встречный ордер открывается именно но ней (сделка совершается в момен достижена цены Bid значения 1.28). Исходя из этого закрытие в коде MQL4 должно выглядеть следующим образом

//Закрытие позиции по TP рыночным ордером (встречным)
ticket=OrderSend(Symbol(),OP_SELL,1,1.28,3,0,0);
//Закрытие позиции встречным отложенным ордером (лимитником)
ticket=OrderSend(Symbol(),OP_SELLLIMIT,1,1.28,3,0,0);

5. SL сработает после того как курс торуемого символа (в нашем случае EUR) упадет на 50 пунктов с момента открытия.


Теперь самое интересное

Проверяем открытие рыночной позиции на основе все тогоже примера из справки по MQL4 (классического примера, который наверное юзало тысячи людей).

Для проверки будем использовать вот такой код

//+------------------------------------------------------------------+
double PriceOpen,PriceSL,PriceTP;
int ticket;
//+------------------------------------------------------------------+
//Формируем цены для приказа
PriceOpen = Ask;
PriceSL   = Bid-500*Point;
PriceTP   = PriceOpen+1000*Point;
//Приказ на открытие рыночной позиции
ticket = OrderSend(Symbol(),OP_BUY,0.10,PriceOpen,5,PriceSL,PriceTP);
//+------------------------------------------------------------------+

Выполнение этого кода на сервере от Alpari (по реальным котировкам) дает вот такой результат

2010.08.24 09:12:47 '******': instant order buy 0.10 EURUSD at 1.26292 sl: 1.25776 tp: 1.27292

Легко догадаться что размер при таком раскладе мы получим следующие размеры SL = 516 (или 51 пунк по 4 знаков) TP = 1000 (или 100 пунктов для 4 знаков)

PPS

Смотрим в справку по MQL4:

Параметры:
symbol   -   Наименование финансового инструмента, с которым проводится торговая операция.
cmd   -   Торговая операция. Может быть любым из значений торговых операций.
volume   -   Количество лотов.
price   -   Цена открытия.
slippage   -   Максимально допустимое отклонение цены для рыночных ордеров (ордеров на покупку или продажу).
stoploss   -   Цена закрытия позиции при достижении уровня убыточности (0 в случае отсутствия уровня убыточности).
takeprofit   -   Цена закрытия позиции при достижении уровня прибыльности (0 в случае отсутствия уровня прибыльности).
comment   -   Текст комментария ордера. Последняя часть комментария может быть изменена торговым сервером.
magic   -   Магическое число ордера. Может использоваться как определяемый пользователем идентификатор.
expiration   -   Срок истечения отложенного ордера.
arrow_color   -   Цвет открывающей стрелки на графике. Если параметр отсутствует или его значение равно CLR_NONE, то открывающая стрелка не отображается на графике.
Пример:
  int ticket;
  if(iRSI(NULL,0,14,PRICE_CLOSE,0)<25)
    {
     ticket=OrderSend(Symbol(),OP_BUY,1,Ask,3,Bid-25*Point,Ask+25*Point,"My order #"+counter,16384,0,Green);
     if(ticket<0)
       {
        Print("OrderSend failed with error #",GetLastError());
        return(0);
       }
    }

"Вот и скажи, мне где правда брат?"...

OrderSend - Документация на MQL4
  • docs.mql4.com
OrderSend - Документация на MQL4
 
Yedelkin:

Немного не понял следующую часть кода:

// Скопируем цену закрытия предыдущего бара (бар 1) в соответствующую переменную эксперта
   Cexpert.setCloseprice(mrate[1].close);  // цена закрытия бара 1
//--- Проверка наличия позиции на покупку
   if (Cexpert.checkBuy()==true)
   {
      if (Buy_opened) 
         {
            Alert("У нас уже есть позиция на покупку!!!"); 
            return;    // Не добавляем к длинной позиции
         }
      double aprice = NormalizeDouble(latest_price.ask,_Digits);
      double stl    = NormalizeDouble(latest_price.ask - STP*_Point,_Digits);
      double tkp    = NormalizeDouble(latest_price.ask + TKP*_Point,_Digits);
      int    mdev   = 100;
      // размещаем ордер
      Cexpert.openBuy(ORDER_TYPE_BUY,Lot,aprice,stl,tkp,mdev);
   }
Если мы собираемся открывать позицию на покупку, то ориентироваться следует на цену latest_price.ask, но при выставлении стоплосса и тейкпрофита для такой позиции - на цену latest_price.bid. Правильно? Почему же тогда в тексте кода стоплосс и тейкпрофит выставляются исходя из цены ask? Это - опечатка или особенность конкретной стратегии (в отношении открытия позиции на продажу код имеет аналогичную конструкцию)?

Эту часть кода следует понимать на основе следующих утверждений:

а. Long - открываются по Ask, а закрываются по Bid; Short - открываются по Bid, а закрываются по Ask;

б. Позиции закрываются встречными ордерами;

в. Уровень БУ находится на цене открытия (Open Price);

г. Расстояние до TP и SL рассчитываются от цены открытия (уровня БУ);

д. TP сработает при достижении ценной Bid уровня равного Open Price + Profit size;

e. SL сработает при достижении ценной Bid уровня равного Open Price - Loss size.

Автор советника скорей всего в своей работе руководствовался подобными утверждениями. Чтобы все было максимально наглядно предлагаю иллюстрацию всего вышестказанного при помощи следующего скрина (нас интересует красный прямоугольник).


 
Interesting:

e. SL сработает при достижении ценной Bid уровня равного Open Price - Loss size.

Спасибо, логику понял. Но всё равно, по пункту "е" получается, что при срабатывании стоплосса Bid должен быть не на 1.2645, а на 1.2650; а Ask, соответственно, - на 1.2655. 

 
Yedelkin:

Спасибо, логику понял. Но всё равно, по пункту "е" получается, что при срабатывании стоплосса Bid должен быть не на 1.2645, а на 1.2650; а Ask, соответственно, - на 1.2655. 

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


Для пункта "е" (как я понимаю)

В случае отсчета от Open (Ask) он там и будет 1,27-50 = 1,2650 (цена пройдет 45 pips и поза прикроется), если я все правильно понял. В этом случае вроде SL должен сработать по цене Bid 1,2650 и Ask 1.2655.

Другое дело, если считать от Bid, тогда мы получим цену 1,2695-50 - 1,2645 (с математикой не поспорить). При расчете SL от Bid мы получим 1,27-1,2645 = 55 pips (что как я понимаю в наши планы не входило).

PS

По крайней мере, такая модель, позволяет правильно пробить уровни SL и TP от цены Open (на мой взгляд правильно)...

Конечно было бы интересно услышать официальное мнение разработчиков как в действительности нужно рассчитывать цены (не только SL и TP).

 

Вопросик.


100 зелененькие - это в руб или у.е.? ;)

 

это обещали убрать
 
Jager:

Вопросик.


100 зелененькие - это в руб или у.е.? ;)

Это значение таймаута в миллисекундах. Этот параметр уже убрали из всех торговых функций.
 

Помогите, пожалуйста, разобраться, что-то никак не догоняю :

В самом начале в советнике вызывается функция

  Cexpert.doInit(ADX_Period,MA_Period);
при этом для ее корректного выполнения требуются уже установленные параметры symbol и period :
//+-----------------------------------------------------------------------+
// ОТКРЫТЫЕ(PUBLIC)ФУНКЦИИ НАШЕГО КЛАССА 
//+-----------------------------------------------------------------------+
/*
   Инициализация 
*/
void MyExpert::doInit(int adx_period,int ma_period)
{
   //--- Получаем хэндл индикатора ADX
   ADX_handle=iADX(symbol,period,adx_period);
  //--- Получаем хэндл индикатора Moving Average
   MA_handle=iMA(symbol,period,ma_period,0,MODE_EMA,PRICE_CLOSE);
однако, заполнение этих параметров конкретными значениями происходит позже, уже после Cexpert.doInit :
//--- запуск функции инициализации
   Cexpert.doInit(ADX_Period,MA_Period);
//--- установка всех необходимых переменных для нашего объекта класса
   Cexpert.setPeriod(_Period);     // задает период
   Cexpert.setSymbol(_Symbol);     // задает символ (валютную пару)
   
   Никак не пойму, как может правильно выполниться Cexpert.doInit, если переменной symbol пока не присвоено
значение (или как-то присвоено ?) Застрял тут и дальше никак . Спасибо.
 
VictorD:

Помогите, пожалуйста, разобраться, что-то никак не догоняю :

В самом начале в советнике вызывается функция

doInit сработал (вероятно по умолчанию этим переменным присвоено NULL и 0). setPeriod и setSymbol должны быть до Init.
 
Snaf:
doInit сработал (вероятно по умолчанию этим переменным присвоено NULL и 0). setPeriod и setSymbol должны быть до Init.

Понятно, спасибо