Нуждаюсь в совете по роботу - страница 2

 
Dmitry Fedoseev:
Читая вас, Михаил, временами даже хочется слезу пустить.
Дмитрий, в чем проблема? Вам Михаила жалко?)
 
Sergey Chalyshev:
Дмитрий, в чем проблема? Вам Михаила жалко?)

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

 
Sergey Chalyshev:
Дмитрий, в чем проблема? Вам Михаила жалко?)
да никого и ничего ему не жалко, они жесткие оппоненты
 

В документации попал код советника как пример асинхронной работы вот интересно нельзя ли его для работы на ФОРТСе приспособить, даже есть кнопки для BUY Sell торговли...

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

#property description "Эксперт для отправки торговых запросов "
                      " с использованием функции OrderSendAsync().\r\n"
#property description "Показана обработка торговых событий с помощью"
                      " функций-обработчиков OnTrade() и OnTradeTransaction()\r\n"
#property description "В параметрах эксперта можно задать Magic Number"
                      " (уникальный идентификатор) "
#property description "и режим вывода сообщений в журнал "Эксперты". По умолчанию выводятся все детали.\r\n"
//--- input parameters
input int  MagicNumber=1234567;      // Идентификатор эксперта
input bool DescriptionModeFull=true; // Режим детального вывода
//--- переменная для использования в вызове HistorySelect()
datetime history_start;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- проверим разрешение на автотрейдинг
   if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
     {
      Alert("Автотрейдинг в терминале запрещен, эксперт будет выгружен.");
      ExpertRemove();
      return(-1);
     }
//--- на реальном счете торговать нельзя
   if(AccountInfoInteger(ACCOUNT_TRADE_MODE)==ACCOUNT_TRADE_MODE_REAL)
     {
      Alert("Советнику запрещено торговать на реальном счете!");
      ExpertRemove();
      return(-2);
     }
//--- можно ли торговать на данном счете (под инвест-паролем нельзя, например)
   if(!AccountInfoInteger(ACCOUNT_TRADE_ALLOWED))
     {
      Alert("Торговля на данном счете запрещена");
      ExpertRemove();
      return(-3);
     }
//--- запомним время запуска эксперта для получения торговой истории
   history_start=TimeCurrent();
//---
   CreateBuySellButtons();
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- удалим за собой графические объекты
   ObjectDelete(0,"Buy");
   ObjectDelete(0,"Sell");
//---
  }
//+------------------------------------------------------------------+
//| TradeTransaction function                                        |
//+------------------------------------------------------------------+
void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
  {
//--- заголовок по имени функции-обработчика торгового события 
   Print("=> ",__FUNCTION__," at ",TimeToString(TimeCurrent(),TIME_SECONDS));
//--- получим тип транзакции в виде значения перечисления 
   ENUM_TRADE_TRANSACTION_TYPE type=trans.type;
//--- если транзакция является результатом обработки запроса
   if(type==TRADE_TRANSACTION_REQUEST)
     {
      //---выведем название транзакции
      Print(EnumToString(type));
      //--- затем выведем строковое описание обработанного запроса
      Print("------------RequestDescription\r\n",
            RequestDescription(request,DescriptionModeFull));
      //--- и выведем описание результата запроса
      Print("------------ ResultDescription\r\n",
            TradeResultDescription(result,DescriptionModeFull));
     }
   else // для транзакций другого типа выведем полное описание транзакции
     {
      Print("------------ TransactionDescription\r\n",
            TransactionDescription(trans,DescriptionModeFull));
     }
//---     
  }
//+------------------------------------------------------------------+
//| Trade function                                                   |
//+------------------------------------------------------------------+
void OnTrade()
  {
//--- статические члены для хранения состояния торгового счета
   static int prev_positions=0,prev_orders=0,prev_deals=0,prev_history_orders=0;
//--- запросим торговую историю
   bool update=HistorySelect(history_start,TimeCurrent());
   PrintFormat("HistorySelect(%s , %s) = %s",
               TimeToString(history_start),TimeToString(TimeCurrent()),(string)update);
//--- заголовок по имени функции-обработчика торгового события 
   Print("=> ",__FUNCTION__," at ",TimeToString(TimeCurrent(),TIME_SECONDS));
//--- выведем имя обработчика и количество ордеров на момент обработки
   int curr_positions=PositionsTotal();
   int curr_orders=OrdersTotal();
   int curr_deals=HistoryOrdersTotal();
   int curr_history_orders=HistoryDealsTotal();
//--- выводим количество ордеров, позиций, сделок, а также изменение в скобках 
   PrintFormat("PositionsTotal() = %d (%+d)",
               curr_positions,(curr_positions-prev_positions));
   PrintFormat("OrdersTotal() = %d (%+d)",
               curr_orders,curr_orders-prev_orders);
   PrintFormat("HistoryOrdersTotal() = %d (%+d)",
               curr_deals,curr_deals-prev_deals);
   PrintFormat("HistoryDealsTotal() = %d (%+d)",
               curr_history_orders,curr_history_orders-prev_history_orders);
//--- вставка разрыва строк для удобного чтения Журнала
   Print("");
//--- запомним состояние счета
   prev_positions=curr_positions;
   prev_orders=curr_orders;
   prev_deals=curr_deals;
   prev_history_orders=curr_history_orders;
//---
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//--- обработка события CHARTEVENT_CLICK ("Нажатие кнопки мышки на графике")
   if(id==CHARTEVENT_OBJECT_CLICK)
     {
      Print("=> ",__FUNCTION__,": sparam = ",sparam);
      //--- минимальный объем для сделки
      double volume_min=SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
      //--- если нажата кнопка "Buy", то покупаем
      if(sparam=="Buy")
        {
         PrintFormat("Buy %s %G lot",_Symbol,volume_min);
         BuyAsync(volume_min);
         //--- отожмем нажатую кнопку обратно
         ObjectSetInteger(0,"Buy",OBJPROP_STATE,false);
        }
      //--- если нажата кнопка "Sell", то продаем
      if(sparam=="Sell")
        {
         PrintFormat("Sell %s %G lot",_Symbol,volume_min);
         SellAsync(volume_min);
         //--- отожмем нажатую кнопку обратно
         ObjectSetInteger(0,"Sell",OBJPROP_STATE,false);
        }
      ChartRedraw();
     }
//---         
  }
//+------------------------------------------------------------------+
//| Возвращает текстовое описание транзакции                         |
//+------------------------------------------------------------------+
string TransactionDescription(const MqlTradeTransaction &trans,
                              const bool detailed=true)
  {
//--- подготовим строку для возврата из функции
   string desc=EnumToString(trans.type)+"\r\n";
//--- в детальном режиме добавим максимум информации
   if(detailed)
     {
      desc+="Symbol: "+trans.symbol+"\r\n";
      desc+="Deal ticket: "+(string)trans.deal+"\r\n";
      desc+="Deal type: "+EnumToString(trans.deal_type)+"\r\n";
      desc+="Order ticket: "+(string)trans.order+"\r\n";
      desc+="Order type: "+EnumToString(trans.order_type)+"\r\n";
      desc+="Order state: "+EnumToString(trans.order_state)+"\r\n";
      desc+="Order time type: "+EnumToString(trans.time_type)+"\r\n";
      desc+="Order expiration: "+TimeToString(trans.time_expiration)+"\r\n";
      desc+="Price: "+StringFormat("%G",trans.price)+"\r\n";
      desc+="Price trigger: "+StringFormat("%G",trans.price_trigger)+"\r\n";
      desc+="Stop Loss: "+StringFormat("%G",trans.price_sl)+"\r\n";
      desc+="Take Profit: "+StringFormat("%G",trans.price_tp)+"\r\n";
      desc+="Volume: "+StringFormat("%G",trans.volume)+"\r\n";
     }
//--- вернем полученную строку
   return desc;
  }
//+------------------------------------------------------------------+
//| Возвращает текстовое описание торгового запроса                  |
//+------------------------------------------------------------------+
string RequestDescription(const MqlTradeRequest &request,
                          const bool detailed=true)
  {
//--- подготовим строку для возврата из функции
   string desc=EnumToString(request.action)+"\r\n";
//--- в детальном режиме добавим максимум информации
   if(detailed)
     {
      desc+="Symbol: "+request.symbol+"\r\n";
      desc+="Magic Number: "+StringFormat("%d",request.magic)+"\r\n";
      desc+="Order ticket: "+(string)request.order+"\r\n";
      desc+="Order type: "+EnumToString(request.type)+"\r\n";
      desc+="Order filling: "+EnumToString(request.type_filling)+"\r\n";
      desc+="Order time type: "+EnumToString(request.type_time)+"\r\n";
      desc+="Order expiration: "+TimeToString(request.expiration)+"\r\n";
      desc+="Price: "+StringFormat("%G",request.price)+"\r\n";
      desc+="Deviation points: "+StringFormat("%G",request.deviation)+"\r\n";
      desc+="Stop Loss: "+StringFormat("%G",request.sl)+"\r\n";
      desc+="Take Profit: "+StringFormat("%G",request.tp)+"\r\n";
      desc+="Stop Limit: "+StringFormat("%G",request.stoplimit)+"\r\n";
      desc+="Volume: "+StringFormat("%G",request.volume)+"\r\n";
      desc+="Comment: "+request.comment+"\r\n";
     }
//--- вернем полученную строку
   return desc;
  }
//+------------------------------------------------------------------+
//| Возвращает текстовое описание результата обработки запроса       |
//+------------------------------------------------------------------+
string TradeResultDescription(const MqlTradeResult &result,
                              const bool detailed=true)
  {
//--- подготовим строку для возврата из функции
   string desc="Retcode "+(string)result.retcode+"\r\n";
//--- в детальном режиме добавим максимум информации
   if(detailed)
     {
      desc+="Request ID: "+StringFormat("%d",result.request_id)+"\r\n";
      desc+="Order ticket: "+(string)result.order+"\r\n";
      desc+="Deal ticket: "+(string)result.deal+"\r\n";
      desc+="Volume: "+StringFormat("%G",result.volume)+"\r\n";
      desc+="Price: "+StringFormat("%G",result.price)+"\r\n";
      desc+="Ask: "+StringFormat("%G",result.ask)+"\r\n";
      desc+="Bid: "+StringFormat("%G",result.bid)+"\r\n";
      desc+="Comment: "+result.comment+"\r\n";
     }
//--- вернем полученную строку
   return desc;
  }
//+------------------------------------------------------------------+
//| Создает две кнопки для покупки и продажи                         |
//+------------------------------------------------------------------+
void CreateBuySellButtons()
  {
//--- проверим наличие объекта с именем "Buy"
   if(ObjectFind(0,"Buy")>=0)
     {
      //--- если найденный объект не является кнопкой, удалим его
      if(ObjectGetInteger(0,"Buy",OBJPROP_TYPE)!=OBJ_BUTTON)
         ObjectDelete(0,"Buy");
     }
   else
      ObjectCreate(0,"Buy",OBJ_BUTTON,0,0,0); // создадим кнопку "Buy"
//--- настроим кнопку "Buy"
   ObjectSetInteger(0,"Buy",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
   ObjectSetInteger(0,"Buy",OBJPROP_XDISTANCE,100);
   ObjectSetInteger(0,"Buy",OBJPROP_YDISTANCE,50);
   ObjectSetInteger(0,"Buy",OBJPROP_XSIZE,70);
   ObjectSetInteger(0,"Buy",OBJPROP_YSIZE,30);
   ObjectSetString(0,"Buy",OBJPROP_TEXT,"Buy");
   ObjectSetInteger(0,"Buy",OBJPROP_COLOR,clrRed);
//--- проверим наличие объекта с именем "Sell"
   if(ObjectFind(0,"Sell")>=0)
     {
      //--- если найденный объект не является кнопкой, удалим его
      if(ObjectGetInteger(0,"Sell",OBJPROP_TYPE)!=OBJ_BUTTON)
         ObjectDelete(0,"Sell");
     }
   else
      ObjectCreate(0,"Sell",OBJ_BUTTON,0,0,0); // создадим кнопку "Sell"
//--- настроим кнопку "Sell"
   ObjectSetInteger(0,"Sell",OBJPROP_CORNER,CORNER_RIGHT_UPPER);
   ObjectSetInteger(0,"Sell",OBJPROP_XDISTANCE,100);
   ObjectSetInteger(0,"Sell",OBJPROP_YDISTANCE,100);
   ObjectSetInteger(0,"Sell",OBJPROP_XSIZE,70);
   ObjectSetInteger(0,"Sell",OBJPROP_YSIZE,30);
   ObjectSetString(0,"Sell",OBJPROP_TEXT,"Sell");
   ObjectSetInteger(0,"Sell",OBJPROP_COLOR,clrBlue);
//--- принудительно обновим график, чтобы кнопки отрисовались немедленно
   ChartRedraw();
//---
  }
//+------------------------------------------------------------------+
//| Покупка через асинхронную функцию OrderSendAsync()               |
//+------------------------------------------------------------------+
void BuyAsync(double volume)
  {
//--- подготовим запрос
   MqlTradeRequest req={0};
   req.action      =TRADE_ACTION_DEAL;
   req.symbol      =_Symbol;
   req.magic       =MagicNumber;
   req.volume      =0.1;
   req.type        =ORDER_TYPE_BUY;
   req.price       =SymbolInfoDouble(req.symbol,SYMBOL_ASK);
   req.deviation   =10;
   req.comment     ="Buy using OrderSendAsync()";
   MqlTradeResult  res={0};
   if(!OrderSendAsync(req,res))
     {
      Print(__FUNCTION__,": ошибка ",GetLastError(),", retcode = ",res.retcode);
     }
//---
  }
//+------------------------------------------------------------------+
//| Продажа через асинхронную функцию OrderSendAsync()               |
//+------------------------------------------------------------------+
void SellAsync(double volume)
  {
//--- подготовим запрос
   MqlTradeRequest req={0};
   req.action      =TRADE_ACTION_DEAL;
   req.symbol      =_Symbol;
   req.magic       =MagicNumber;
   req.volume      =0.1;
   req.type        =ORDER_TYPE_SELL;
   req.price       =SymbolInfoDouble(req.symbol,SYMBOL_BID);
   req.deviation   =10;
   req.comment     ="Sell using OrderSendAsync()";
   MqlTradeResult  res={0};
   if(!OrderSendAsync(req,res))
     {
      Print(__FUNCTION__,": ошибка ",GetLastError(),", retcode = ",res.retcode);
     }
//---
  }
//+------------------------------------------------------------------+ 
//| Получить цену случайным образом                                  | 
//+------------------------------------------------------------------+ 
double GetRandomPrice(ENUM_ORDER_TYPE type) 
  { 
   int t=(int)type; 
//--- уровень стопов по символу 
   int distance=(int)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL); 
//--- получим данные последнего тика 
   MqlTick last_tick={0}; 
   SymbolInfoTick(_Symbol,last_tick); 
//--- вычислим цену в соответствие с типом 
   double price; 
   if(t==2 || t==5) // ORDER_TYPE_BUY_LIMIT или ORDER_TYPE_SELL_STOP 
     { 
      price=last_tick.bid; // оттолкнемся от цены Bid 
      price=price-(distance+(MathRand()%10)*5)*_Point; 
     } 
   else             // ORDER_TYPE_SELL_LIMIT или ORDER_TYPE_BUY_STOP 
     { 
      price=last_tick.ask; // оттолкнемся от цены Ask 
      price=price+(distance+(MathRand()%10)*5)*_Point; 
     } 
//--- 
   return(price); 
  }
 
Сергей Криушин:

В документации попал код советника как пример асинхронной работы вот интересно нельзя ли его для работы на ФОРТСе приспособить, даже есть кнопки для BUY Sell торговли...


Для ручной торговли асинхронный режим не нужен. Считаю что если советник работает с одним инструментом то он тоже не нужен (зачем?).

По моему он пригождается только когда нужно в одном советнике совершить сделки по нескольким инструментам одновременно.

В данном скрипте можно посмотреть реакцию ontradetransaction на асинхронный запрос. Чтобы практически обрабатывать асинхронные запросы на сделку нужно будет самому пилить свою логику.

Т.к. при асинхронном вызове после отправки запроса известен только request_id, то чтобы связать request_id->order_id->ticket_id нужно самому писать логику обработки ontradetransaction.

 
akuloff:

Для ручной торговли асинхронный режим не нужен. Считаю что если советник работает с одним инструментом то он тоже не нужен (зачем?).

По моему он пригождается только когда нужно в одном советнике совершить сделки по нескольким инструментам одновременно.

В данном скрипте можно посмотреть реакцию ontradetransaction на асинхронный запрос. Чтобы практически обрабатывать асинхронные запросы на сделку нужно будет самому пилить свою логику.

Т.к. при асинхронном вызове после отправки запроса известен только request_id, то чтобы связать request_id->order_id->ticket_id нужно самому писать логику обработки ontradetransaction.

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