TraillingStop - страница 2

 
Yedelkin:

Так Ренат как-то говорил на тему, что нормализация цен - это компетенция программиста, а не разработчиков. 

При не нормализованных ценах может просто не открыться позиция.
 
Yedelkin:

Так Ренат как-то говорил на тему, что нормализация цен - это компетенция программиста, а не разработчиков. 

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

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

 
tol64:
При ненормализованных ценах может просто не открыться позиция.

Вот тогда программист и задумается, почему позиция не открывается. Узнает новое :)

 

Идея такова:

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

#property copyright "Copyright © 2012, eXPert"
#property version   "1.0"
//+-----------------------------------+
#include <Trade\Trade.mqh>
input int TP = 100;
input int SL = 35;
input int VLStep = 10;
input int                  ma_period=10;                 // период средней
input int                  ma_shift=0;                   // смещение
input ENUM_MA_METHOD       ma_method=MODE_LWMA;          // тип сглаживания
input ENUM_APPLIED_PRICE   applied_price=PRICE_CLOSE;    // тип цены

CTrade trade;

void OnInit()
{
}

void OnTick()
{   
   double Ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);    //лучшая покупка
   double Bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);    //лучшая продажа
   
   if (PositionsTotal() < 1)     //если нет позиций
   {      
      double MAcur = iMA(_Symbol,0,MODE_LWMA,ma_shift,ma_method,PRICE_CLOSE);       //текущее значение MA
      double MAprev = iMA(_Symbol,1,MODE_LWMA,ma_shift,ma_method,PRICE_CLOSE);      //предыдущее значение MA
      if (MAcur > MAprev)
         trade.PositionOpen(_Symbol,ORDER_TYPE_BUY,0.1,Ask,Ask-500*_Point,Ask+TP*_Point,NULL);     //если текущее больше - покупаем
      else
         if (MAcur < MAprev)
            trade.PositionOpen(_Symbol,ORDER_TYPE_SELL,0.1,Bid,Bid+500*_Point,Bid-TP*_Point,NULL); //если меншье - продаем
   }
   
   if (PositionSelect(_Symbol))        //если удалось выбрать позицию
   {
      if (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)      //и ее тип покупка
      {
         if (Ask+VLStep*_Point < PositionGetDouble(POSITION_PRICE_OPEN))   //если рынок пошел не туда на VLStep пунктов - доливаемся
            trade.Buy(0.1,NULL,Ask,Ask-500*_Point,Ask+TP*_Point,NULL);      
         if (Ask-SL*_Point > PositionGetDouble(POSITION_SL))               //трейлим
            trade.PositionModify(_Symbol,Ask-SL*_Point,NULL);
      }      
      else
      {
         if (Bid-VLStep*_Point > PositionGetDouble(POSITION_PRICE_OPEN))      
            trade.Sell(0.1,NULL,Bid,Bid+500*_Point,Bid-TP*_Point,NULL);      
         if (Bid+SL*_Point < PositionGetDouble(POSITION_SL))            
            trade.PositionModify(_Symbol,Bid+SL*_Point,NULL);
      }
   }     
}
 

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

1. При отправке торгового запроса на сервер требуется указание нормализованных цен. Класс CTrade такой нормализации не предоставляет. Поэтому, как правильно отметил Interesting, желательно самостоятельно нормализовывать все ненормализованные значения при отправке торговых запросов (trade.PositionModify, trade.Sell и т.д.) - или поискать методы нормализации в других торговых классах. Для "ручной" нормализации существует функция NormalizeDouble (см. примечание к этой функции).

2.  В коде заложено расстояние SL=35. При этом в случае BUY-позиции предусмотрена строчка

trade.PositionModify(_Symbol,Ask-SL*_Point,NULL);

 т.е. в качестве уровня закрытия BUY-позиции по стоп-лоссу предлагается значение Ask-0.00035. Это означает выставление уровня крайне близко к рынку Однако проверка на минимальный отступ  от текущей цены закрытия для установки Stop ордеров необоснованно не проводится (SYMBOL_TRADE_STOPS_LEVEL). Т.е., например, если спред>18 и SYMBOL_TRADE_STOPS_LEVEL>18, то метод trade.PositionModify в коде никогда не сработает.

3. tol64 уже советовал повсеместно использовать функцию Print() для поиска проблемных мест в коде. При использовании методов из класса  CTrade  желательно также обращаться к методам

ResultRetcode, ResultRetcodeDescription, а также к CheckResultRetcode и CheckResultRetcodeDescription.

 
Yedelkin:

...

3. tol64 уже советовал повсеместно использовать функцию Print() для поиска проблемных мест в коде. При использовании методов из класса  CTrade  желательно также обращаться к методам

ResultRetcode, ResultRetcodeDescription, а также к CheckResultRetcode и CheckResultRetcodeDescription.

Каждое действие нужно обрабатывать на наличие ошибок. Нужно учесть, чтобы при оптимизации в печать ничего не выводилось, это увеличит скорость оптимизации. На каждую группу операций можно создать свои флаги. В данном случае это был бы флаг для торговых операций. То есть, если флаг установлен, то вывод в журнал производится. Если есть понимание, что ошибка не связана с торговыми операциями, то флаг отключен. Если изначально не делать такую систему вывода сообщений, то потом их будет столько, что на просмотр и поиск будет уходить много времени. Если функции расположены в разных файлах, то полезно использовать предопределенные макроподстановки:  __FUNCTION__ __LINE__ и т.д.
 

C этим разобрался, спасибо. Теперь разбираюсь с ценами но не все так прозрачно как в 4й версии.

Допустимы мы открыли позицию по цене в 100 пунктов лотом в 0,1. В этот момент Ask, POSITION_PRICE_CURRENT и POSITION_PRICE_OPEN равны

Через время цена стала 150 пунктов и мы сделали еще один ордер в том же направлении тем же лотом, т.е. 0,1

Вопрос: чему равны POSITION_PRICE_CURRENT и POSITION_PRICE_OPEN в этот момент. По идее  POSITION_PRICE_OPEN должна остаться той же, а POSITION_PRICE_CURRENT стать посередине, т.е 125. Ask понятное дело будет 150

Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Свойства позиций
Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Свойства позиций
  • www.mql5.com
Стандартные константы, перечисления и структуры / Торговые константы / Свойства позиций - Документация по MQL5
 
ITeXPert:

Идея такова: позиции открываются на основании результатов сравнения текущей и предыдущей MA.

      double MAcur = iMA(_Symbol,0,MODE_LWMA,ma_shift,ma_method,PRICE_CLOSE);       //текущее значение MA
      double MAprev = iMA(_Symbol,1,MODE_LWMA,ma_shift,ma_method,PRICE_CLOSE);      //предыдущее значение MA
Да, ещё. Сам я со стандартными индикаторами не работаю, но вторым параметром у iMA выступает период из значений перечисления ENUM_TIMEFRAMES. У Вас первый хендл запущен на текущем таймфрейме, а второй - на ТФ со значением 1. Что такое ТФ со значением 1 и как он соотносится с понятием "предыдущая МА" - не совсем понятно. Может поэтому получается, что всегда MAcur < MAprev?
 
ITeXPert:

C этим разобрался, спасибо. Теперь разбираюсь с ценами но не все так прозрачно как в 4й версии.

Допустимы мы открыли позицию по цене в 100 пунктов лотом в 0,1. В этот момент Ask, POSITION_PRICE_CURRENT и POSITION_PRICE_OPEN равны

Через время цена стала 150 пунктов и мы сделали еще один ордер в том же направлении тем же лотом, т.е. 0,1

Вопрос: чему равны POSITION_PRICE_CURRENT и POSITION_PRICE_OPEN в этот момент. По идее  POSITION_PRICE_OPEN должна остаться той же, а POSITION_PRICE_CURRENT стать посередине, т.е 125. Ask понятное дело будет 150

Насколько я помню, в описанной ситуации в качестве POSITION_PRICE_OPEN указывается некая усреднённая цена. Посмотрите в Руководстве по терминалу, там в описании поля "Цена позиции" (или что-то в этом роде) должно быть про этом сказано. По-моему, даже с формулой.

А описание POSITION_PRICE_CURRENT  дано в Справочнике :)

 
Yedelkin:
Да, ещё. Сам я со стандартными индикаторами не работаю, но вторым параметром у iMA выступает период из значений перечисления ENUM_TIMEFRAMES. У Вас первый хендл запущен на текущем таймфрейме, а второй - на ТФ со значением 1. Что такое ТФ со значением 1 и как он соотносится с понятием "предыдущая МА" - не совсем понятно. Может поэтому получается, что всегда MAcur < MAprev?

Не один Вы от кода в недоумении. Я лично сильно повесилился (ITeXPert, без обид).

ITeXPert:

Идея такова:

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

MT5 это Вам не MT4 с его логикой. Если используете индюки делайте это правильно.

Несколько замечаний по поводу представленного кода:

1. Ask и Bid

double Ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);    //лучшая покупка
double Bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);    //лучшая продажа

Переменные лучше объявить отдельно на глобальном уровне, так чтобы они были доступны во всем теле эксперта.

//Что-то вроде такого
double Ask = 0; //лучшая покупка
double Bid = 0; //лучшая продажа

2. Хендлы индикаторов

double MAcur = iMA(_Symbol,0,MODE_LWMA,ma_shift,ma_method,PRICE_CLOSE);       //текущее значение MA
double MAprev = iMA(_Symbol,1,MODE_LWMA,ma_shift,ma_method,PRICE_CLOSE);      //предыдущее значение MA

Это в MQL4 значения возвращались, теперь возвращаются ХЕНДЛЫ (получение значений ведется отдельно).

а. Открываем справку по функции iMA и видим следующее

int  iMA(
   string               symbol,          // имя символа
   ENUM_TIMEFRAMES      period,          // период
   int                  ma_period,       // период усреднения
   int                  ma_shift,   // смещение индикатора по горизонтали
   ENUM_MA_METHOD       ma_method,       // тип сглаживания
   ENUM_APPLIED_PRICE   applied_price    // тип цены или handle
   );

б. Работать с хендлами индюков нужно в блоке инициализации и деинициализации (где обязательно нужно хендлы освободить).

Постоянная работа с хндлами сильно затормозит работу и вызовет кучу проблем

в. Данные нужно получать при помощи иных функций, к примеру CopyBuffer()

г. Справку читать все же нужно, там иногда есть очень замечательные примеры.

3. Работа с хендлами.

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

if(MAcur > MAprev)
{
//Этот блок мягко говоря ошибочен
}

4. Хендлы также как и цены желательно вынести на глобальный уровень.

PS

Желательно уже начать использовать ООП, все будет намного проще и веселей

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