Скачать MetaTrader 5
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий
Хочешь стать известным разработчиком? Выполняй заказы трейдеров в сервисе Фриланс!
Mike Kharkov
846
Mike Kharkov 2014.07.27 10:39 
Здравствуйте.
В MQL программировании я новичек.
Есть такой код:

//+------------------------------------------------------------------+
//|                                                  My_Practics.mq5 |
//|                                                     Mike_Kharkov |
//|                                https://www.fl.ru/users/Yamaradg/ |
//+------------------------------------------------------------------+
#property copyright "Mike_Kharkov"
#property link      "https://www.fl.ru/users/Yamaradg/"
#property version   "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {

  
  /*
  Print(" Тикет сделки:" , result.deal);
  Print(" Ордер: ", result.order);
  Print(" Обьём: " , result.volume);
  Print(" Цена в сделке, подтверждённая брокером: " , result.price);
  Print(" Текущая рыночная цена предложения (цены реквоты): " , result.bid);
  Print(" Текущая рыночная цена спроса (цены реквоты): " , result.ask);
  Print(" Комментарий брокера к операции (по умолчанию заполняется расшифровкой: " , result.comment);
  Print(" Идентификатор запроса, проставляемый терминалом при отсылке на торговый сервер: " , result.request_id);
  */

//---
   
//---
   return(INIT_SUCCEEDED);
  };
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
  };
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  { 
   
  MqlTradeRequest request={0};
  
  request.action = TRADE_ACTION_DEAL;                                        // Тип выполняемого действия
  request.symbol = _Symbol;                                                  // Имя торгового инструмента
  request.volume = 0.01;                                                     // Запрашиваемый объем сделки в лотах
  request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);                     // Цена  
  request.type = ORDER_TYPE_BUY;                                             // Тип ордера
  request.tp = SymbolInfoDouble(_Symbol, SYMBOL_ASK)+1000*_Point;                                                            // Цена, по которой сработает Take Profit ордер при движении цены в благоприятном направлении
  request.sl = 0;                                                            // Цена, по которой сработает Stop Loss ордер при движении цены в неблагоприятном направлении
  request.type_filling = ORDER_FILLING_FOK;                                  // Тип ордера по исполнению
  request.type_time = ORDER_TIME_GTC;
                                    
  MqlTradeResult result={0};
  
  int positions_total = PositionsTotal();
  
  if(PositionsTotal() < 1)
     {
      bool send1 = OrderSend(request,result);
      uint result_retcode = result.retcode;
      Print(" Код возврата торгового сервера: ", result_retcode);
      Print(" Количество открытых позиций: ", PositionsTotal());
      Print(" Цена в сделке, подтверждённая брокером : ", result.price);
      double res = result.price;
      
           if(SymbolInfoDouble(_Symbol, SYMBOL_BID) <= res-50*_Point && PositionsTotal() == 1)
              {
               request.volume = 0.01*2;
               request.price = res-150*_Point;
               request.tp = SymbolInfoDouble(_Symbol, SYMBOL_ASK)+1150*_Point; 
               bool send2 = OrderSend(request,result);
               uint result_retcode_2 = result.retcode;
               Print(" Код возврата торгового сервера_2: ", result_retcode_2);
               Print(" Количество открытых позиций_2: ", PositionsTotal());
               Print(" Цена в сделке, подтверждённая брокером_2 : ", result.price);
               };
      
     };

//---
   
  };

Хочу что бы как только цена шла против меня - можно было докупиться.

(пытаюсь написать примитивного мартингейла или что то в этом роде.)

Не могу понять некоторые вещи:

1) Почему в этом варианте кода позиция доливается по той же цене(1.35990) что и самая первая сделка?


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



2) Если такая конструкция не правильна с точки зрения синтаксиса - то где можно прочесть о том, почему она не правильна?

+ какие есть альтернативняе варианты реализации данной идеи?

(скачивал себе пару советников по мартину но ниче там не понял практически.

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



3) Если не создавать условие(If) внутри другого условия то что можно вообще придумать?

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

Что только не пробовал делать - ничего не выходит. )

(например функцию внутри другой функции в этом языке прописывать нельзя.

 Переменную, если объявить внутри одного условия - то её больше нигде(помимо этого условия) "видно" не будет.)



P.S. Буду благодарен за любые конструктивные советы.
Igor Konyashin
3118
Igor Konyashin 2014.07.27 11:49  

1) Структуру MqlTradeRequest заполняйте перед каждой отправкой ордера, предварительно её обнулив (как и MqlTradeResult). Заранее заполнять не надо, так только запутаетесь.

2) Анализируйте ответ от сервера.

Igor Konyashin
3118
Igor Konyashin 2014.07.27 12:02  
Думаю вам, как новичку, стоит попробовать использовать готовый класс CTrade, упрощающий торговые операции.
Mike Kharkov
846
Mike Kharkov 2014.07.27 12:30  
i_logic:

1) Структуру MqlTradeRequest заполняйте перед каждой отправкой ордера, предварительно её обнулив (как и MqlTradeResult). Заранее заполнять не надо, так только запутаетесь.

2) Анализируйте ответ от сервера.

   Cделал вроде т.к. вы сказали - но позиция вообще перестала докупаться.

   результаты:

   Часть Кода была переписана следующим образом:

  

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  { 
  int positions_total = PositionsTotal();
  
  if(PositionsTotal() < 1)
     {
      MqlTradeRequest request={0};
  
      request.action = TRADE_ACTION_DEAL;                                        // Тип выполняемого действия
      request.symbol = _Symbol;                                                  // Имя торгового инструмента
      request.volume = 0.01;                                                     // Запрашиваемый объем сделки в лотах
      request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);                     // Цена  
      request.type = ORDER_TYPE_BUY;                                             // Тип ордера
      request.tp = SymbolInfoDouble(_Symbol, SYMBOL_ASK)+400*_Point;                                                            // Цена, по которой сработает Take Profit ордер при движении цены в благоприятном направлении
      request.sl = 0;                                                            // Цена, по которой сработает Stop Loss ордер при движении цены в неблагоприятном направлении
      request.type_filling = ORDER_FILLING_FOK;                                  // Тип ордера по исполнению
      request.type_time = ORDER_TIME_GTC;
                                          
      MqlTradeResult result={0};
      bool send1 = OrderSend(request,result);
      uint result_retcode = result.retcode;
      Print(" Код возврата торгового сервера: ", result_retcode);
      Print(" Количество открытых позиций: ", PositionsTotal());
      Print(" Цена в сделке, подтверждённая брокером : ", result.price);
      double res = result.price;
      
           if(SymbolInfoDouble(_Symbol, SYMBOL_BID) <= res-200*_Point && PositionsTotal() == 1)
              {
                  MqlTradeRequest request2={0};
              
                  request2.action = TRADE_ACTION_DEAL;                                        // Тип выполняемого действия
                  request2.symbol = _Symbol;                                                  // Имя торгового инструмента
                  request2.volume = 0.02;                                                     // Запрашиваемый объем сделки в лотах
                  request2.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);                     // Цена  
                  request2.type = ORDER_TYPE_BUY;                                             // Тип ордера
                  request2.tp = SymbolInfoDouble(_Symbol, SYMBOL_ASK)+600*_Point;                                                            // Цена, по которой сработает Take Profit ордер при движении цены в благоприятном направлении
                  request2.sl = 0;                                                            // Цена, по которой сработает Stop Loss ордер при движении цены в неблагоприятном направлении
                  request2.type_filling = ORDER_FILLING_FOK;                                  // Тип ордера по исполнению
                  request2.type_time = ORDER_TIME_GTC;
                                                      
                  MqlTradeResult result2={0};
                  bool send2 = OrderSend(request,result);
                  uint result_retcode2 = result2.retcode;
                  Print(" Код возврата торгового сервера_2: ", result_retcode2);
                  Print(" Количество открытых позиций_2: ", PositionsTotal());
                  Print(" Цена в сделке, подтверждённая брокером_2 : ", result2.price);
               };
     };

//---
   
  };
//+------------------------------------------------------------------+
 
Igor Konyashin
3118
Igor Konyashin 2014.07.27 13:19  
Mike_Kharkov:
   Cделал вроде т.к. вы сказали - но позиция вообще перестала докупаться.
   
Неудивительно. Сразу же, через несколько миллисекунд после открытия ордера, вы проверяете падение цены на 200 пунктов. Такого не происходит, и советник выходит из OnTick. Ну а на следующем тике код открытия ордеров вообще не задействуется, поскольку стоит условие
if(PositionsTotal() < 1)
Mike Kharkov
846
Mike Kharkov 2014.07.27 14:03  
i_logic:
Неудивительно. Сразу же, через несколько миллисекунд после открытия ордера, вы проверяете падение цены на 200 пунктов. Такого не происходит, и советник выходит из OnTick. Ну а на следующем тике код открытия ордеров вообще не задействуется, поскольку стоит условие

   Но в самой первой версии кода позиция же докупалась почему то?
   (осуществлялась она по цене первой сделки - видимо потому, что на том же самом тике все это дело произошло.
   Но почему тогда не было соблюдено условие - что докупаться удвоенным лотом можно только при условии, если цена упадёт на 200 пунктов?

   P.S. А что тогда можно придумать что бы была возможность докупаться в том или ином случае?
   (Если первая сделка у меня находится в условии - тогда мне надо получается как то вытащить(если это реально) значение(цены сделки) из этого условия и сравнить
   со значением в другом(отдельно взятом) условии и там докупаться.
   Я в правильном направлении двигаюсь или есть другие(более простые) реализации данной задачи.
   (Пытался просматривать код в одном из советников по мартину, но тот код мне непонятен + написан он однозначно неправильно с точки зрения оформления, как мне кажется.
   http://webmaster.ayrveda.ru/martin.htm
   Поэтому хотелось бы самому поэтапно двигаться от простого к сложному и понемногу допиливать то с чего начинаю, консультируясь при этом у грамотных людей на форумах.)
  

  

Igor Konyashin
3118
Igor Konyashin 2014.07.27 14:23  
Mike_Kharkov:

   Но в самой первой версии кода позиция же докупалась почему то?

   

В первой версии кода у вас в условии указано:

if(SymbolInfoDouble(_Symbol, SYMBOL_BID) <= res-50*_Point && PositionsTotal() == 1)

Во второй верcии на этом месте стоит уже "200"

if(SymbolInfoDouble(_Symbol, SYMBOL_BID) <= res-200*_Point && PositionsTotal() == 1)

То, что цена упадет на 50 пунктов через несколько миллисекунд после открытия ордера - более вероятно, чем падение цены на 200 пунктов за то же время.


Mike_Kharkov:

 
   (Если первая сделка у меня находится в условии - тогда мне надо получается как то вытащить(если это реально) значение(цены сделки) из этого условия и сравнить
   со значением в другом(отдельно взятом) условии и там докупаться.
     

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


Кстати, обратите внимание, что у вас во второй верии кода, там где вы докупаетесь, в функции отправки указаны request и result,

bool send2 = OrderSend(request,result);

хотя, следуя вашей логике обозначения структур в советнике, там должны быть request2 и result2

bool send2 = OrderSend(request2,result2);
Mike Kharkov
846
Mike Kharkov 2014.07.27 15:05  

i_logic:


1) Во второй верcии на этом месте стоит уже "200" То, что цена упадет на 50 пунктов через несколько миллисекунд после открытия ордера - более вероятно, чем падение цены на 200 пунктов за то же время.


2) Можете сохранять значение цены открытия ордера в свою переменную, или же тащить значение цены из позиции: PositionGetDouble(POSITION_PRICE_OPEN)


3)Кстати, обратите внимание, что у вас во второй верии кода, там где вы докупаетесь, в функции отправки указаны request и result, хотя, следуя вашей логике обозначения структур в советнике, там должны быть request2 и result2

    1) Смотрите: я имел ввиду почему все таки позиция докупилась?
    Она же не имела право по идее, по тому как цена не упала на 50(либо больше) пунктов в тот момент?

    2) Я пробовал вчера так делать - но переменная которая сохраняется в одном условии, не находится в области видимости другого условия.
    (или я вас не правильно понял в данном контексте?)
  

    3) Ничё не понял. )
    В первом условии я указал просто request и result, а во втором условии(которое внутри первого) прописал request2 и result2 т.к. компилятор показывал предупреждение из за того,
    что одно имя переменной перекрывает другое(в другом условии.)
    На что именно тут надо внимание обратить?(в чем конкретно загвоздка?)

Igor Konyashin
3118
Igor Konyashin 2014.07.27 17:06  

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

Входим в OnTick

-   Если есть позиция

       └   Проверка условий для доливки

-   Если нет позиции

       └   Проверка условий для открытия позиции

Выход из OnTick

А то сейчас ваш код выглядит как проба работоспособности отдельных функций.

Igor Konyashin
3118
Igor Konyashin 2014.07.27 17:22  
Mike_Kharkov:

  
    2) Я пробовал вчера так делать - но переменная которая сохраняется в одном условии, не находится в области видимости другого условия.
    (или я вас не правильно понял в данном контексте?)
  

    3) Ничё не понял. )
    В первом условии я указал просто request и result, а во втором условии(которое внутри первого) прописал request2 и result2 т.к. компилятор показывал предупреждение из за того,
    что одно имя переменной перекрывает другое(в другом условии.)   

Область видимости переменных: https://www.mql5.com/ru/docs/basis/variables/variable_scope

Глобальные переменные: https://www.mql5.com/ru/docs/basis/variables/global

Локальные переменные: https://www.mql5.com/ru/docs/basis/variables/local

Igor Konyashin
3118
Igor Konyashin 2014.07.27 17:30  

Объявите request и result глобальными переменными и не будете в дальнейшем путаться в них, заполняя одну структкру, но отправляя ордер со старой заполненной структурой:

                  request2.action = TRADE_ACTION_DEAL;                                        // Тип выполняемого действия
                  request2.symbol = _Symbol;                                                  // Имя торгового инструмента
                  request2.volume = 0.02;                                                     // Запрашиваемый объем сделки в лотах
                  request2.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);                     // Цена  
                  request2.type = ORDER_TYPE_BUY;                                             // Тип ордера
                  request2.tp = SymbolInfoDouble(_Symbol, SYMBOL_ASK)+600*_Point;                                                            // Цена, по которой сработает Take Profit ордер при движении цены в благоприятном направлении
                  request2.sl = 0;                                                            // Цена, по которой сработает Stop Loss ордер при движении цены в неблагоприятном направлении
                  request2.type_filling = ORDER_FILLING_FOK;                                  // Тип ордера по исполнению
                  request2.type_time = ORDER_TIME_GTC;
                                                      
                  MqlTradeResult result2={0};
                  bool send2 = OrderSend(request,result); <-----------------------
                  uint result_retcode2 = result2.retcode;
                  Print(" Код возврата торгового сервера_2: ", result_retcode2);
                  Print(" Количество открытых позиций_2: ", PositionsTotal());
                  Print(" Цена в сделке, подтверждённая брокером_2 : ", result2.price);
/ /123
Авторизуйтесь или зарегистрируйтесь, чтобы добавить комментарий