FORTS: Para ajudar iniciantes

 

Boa tarde!

Aqui postarei recomendações, bugs, recursos e funções usadas com frequência no mercado de futuros FORTS

IMPORTANTE: Para não "esticar" o tópico, caso haja algum comentário,

ou tiver dúvidas - crie um tópico separado nesta seção (não responderei aqui).

Recomendação :

Abiblioteca padrão MQL5 é "aprimorada" para o mercado FOREX, então para

desenvolvimentos de especialistas para FORTS Eu recomendo escrever tudo sozinho.

Recursos frequentemente usados e úteis:

A função de verificar os parâmetros de negociação do servidor do corretor.

Nesta função, é necessário verificar os parâmetros que

Você usará em seu orientador. Aqui está um exemplo:

(use SOMENTE em OnInit() )

 //+------------------------------------------------------------------+
//| Expert Check Market Parameters function                          |
//+------------------------------------------------------------------+
bool CheckMarketParam( const string a_symbol )
{
//--- Check for full mode
   ENUM_SYMBOL_TRADE_MODE trade_mode = ENUM_SYMBOL_TRADE_MODE ( SymbolInfoInteger ( a_symbol, SYMBOL_TRADE_MODE ) );
  
   if ( trade_mode != SYMBOL_TRADE_MODE_FULL )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает полную торговлю!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
//--- Check trade execution mode
   ENUM_SYMBOL_TRADE_EXECUTION market_info = ENUM_SYMBOL_TRADE_EXECUTION ( SymbolInfoInteger ( a_symbol, SYMBOL_TRADE_EXEMODE ) );
    
   if ( market_info != SYMBOL_TRADE_EXECUTION_EXCHANGE )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает TRADE EXECUTION EXCHANGE режим!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
//--- Check orders mode
   int order_mode = int ( SymbolInfoInteger ( a_symbol, SYMBOL_ORDER_MODE ) );
  
   if ( ( SYMBOL_ORDER_MARKET & order_mode )!= SYMBOL_ORDER_MARKET )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает Market Execution режим установки ордеров!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
  
   if ( ( SYMBOL_ORDER_LIMIT & order_mode )!= SYMBOL_ORDER_LIMIT )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает Limit режим установки ордеров!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
  
   if ( ( SYMBOL_ORDER_STOP_LIMIT & order_mode ) != SYMBOL_ORDER_STOP_LIMIT )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает Stop Limit режим установки ордеров!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
  
   if ( ( SYMBOL_ORDER_STOP & order_mode )!= SYMBOL_ORDER_STOP )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает Stop режим установки ордеров!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
  
   if ( ( SYMBOL_ORDER_SL & order_mode) != SYMBOL_ORDER_SL )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает Stop Loss режим установки ордеров!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
  
   if ( ( SYMBOL_ORDER_TP & order_mode) != SYMBOL_ORDER_TP )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает Take Profit режим установки ордеров!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
//---Filing mode
   int filling_mode = int ( SymbolInfoInteger ( a_symbol, SYMBOL_FILLING_MODE ) );
  
   if ( ( SYMBOL_FILLING_IOC & filling_mode ) != SYMBOL_FILLING_IOC )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает filling IOC режим исполнения ордеров!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
  
   if ( ( SYMBOL_FILLING_FOK & filling_mode ) != SYMBOL_FILLING_FOK )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает filling FOK режим исполнения ордеров!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }      
//---Ckeck expiration
   int symbol_exp_type = int ( SymbolInfoInteger ( a_symbol, SYMBOL_EXPIRATION_MODE ) );
//---  
   if ( ( symbol_exp_type & SYMBOL_EXPIRATION_DAY ) != SYMBOL_EXPIRATION_DAY )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает экспирацию DAY!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
   if ( ( symbol_exp_type & SYMBOL_EXPIRATION_SPECIFIED_DAY ) != SYMBOL_EXPIRATION_SPECIFIED_DAY )
  {
     MessageBox ( "Символ " + a_symbol + " не поддерживает экспирацию SPECIFIED DAY!" , "Ошибка" , MB_OK | MB_ICONHAND );
     return ( false );
  }
   return ( true );
} 

Exemplo de uso:

 int OnInit ()
{
   if ( !CheckMarketParam( _Symbol ) ) return ( INIT_FAILED );
   return ( INIT_SUCCEEDED );
}

Obtendo o número de dias restantes até a expiração do instrumento:

 #define YEAR           365

int GetExpiration( const string aSymbol )
{
   MqlDateTime ExpData, CurData;
    
   datetime exp_time = datetime ( SymbolInfoInteger ( aSymbol, SYMBOL_EXPIRATION_TIME ) );
      
   TimeToStruct ( exp_time, ExpData );
   TimeTradeServer ( CurData );
      
   if ( ExpData.year != CurData.year )
  {
     return ( YEAR * ( ExpData.year - CurData.year ) - CurData.day_of_year + ExpData.day_of_year );
  }
   else
  {
     return ( ExpData.day_of_year - CurData.day_of_year );
  }
}

Obtendo o preço de posição "líquido", excluindo as compensações:

 //+------------------------------------------------------------------+
//| Expert Get position price function                               |
//+------------------------------------------------------------------+
double GetPositionPrice( const string aSymbol )
{
   double price_in = 0 ;
   double volume_in = 0 ;
   double price_out = 0 ;
   double volume_out = 0 ;
   double price = 0 ;
   double volume = 0 ;
  
   if ( PositionSelect ( aSymbol ) )
  {
     ulong pos_id = ulong ( PositionGetInteger ( POSITION_IDENTIFIER ) );
    
     if ( pos_id > 0 )
    {
       if ( HistorySelectByPosition ( pos_id ) )
      {
         int deals = HistoryDealsTotal ();
      
         for ( int i = 0 ; i < deals; i++ )
        {
           ulong deal_ticket = HistoryDealGetTicket ( i );
           ulong order_ticket = ulong ( HistoryDealGetInteger ( deal_ticket, DEAL_ORDER ) );
        
           if ( order_ticket > 0 )
          {
             ENUM_DEAL_ENTRY deal_entry = ENUM_DEAL_ENTRY ( HistoryDealGetInteger ( deal_ticket, DEAL_ENTRY ) );
              
             if ( deal_entry == DEAL_ENTRY_IN )
            {
              price = HistoryDealGetDouble ( deal_ticket, DEAL_PRICE );
              volume = HistoryDealGetDouble ( deal_ticket, DEAL_VOLUME );
                                
              price_in += price * volume;
              volume_in += volume;  
            }
             else
             if ( deal_entry == DEAL_ENTRY_OUT )
            {
              price = HistoryDealGetDouble ( deal_ticket, DEAL_PRICE );
              volume = HistoryDealGetDouble ( deal_ticket, DEAL_VOLUME );
                                
              price_out += price * volume;
              volume_out += volume;  
            }
          }
        }
         if ( volume_out > 0 )
        {
           if ( volume_in > 0 ) { price_in = price_in / volume_in; } else return ( 0 );
          price_out = price_out / volume_out;
          price = ( price_in - price_out ) * ( volume_in - volume_out );
        }
         else
        {
           if ( volume_in > 0 ) { price = price_in / volume_in; } else return ( 0 );
        }
         return ( NormalizeDouble ( price, _Digits ) );
      }
       else
      {
         Print ( "GetPositionPrice: Невозможно получить историю позиции по символу " , aSymbol );
      }
    }
     else
    {
       Print ( "GetPositionPrice: Невозможно определить идентификатор позиции по символу " , aSymbol );
    }
  }
   return ( 0 );
} 

Criando uma variável de terminal global para contar transações:

(Use SOMENTE em OnInit())

   if ( ! GlobalVariableCheck ( "trans_count" ) )
  {
     datetime a_time = GlobalVariableSet ( "trans_count" , 0 );
    
     if ( ulong ( a_time ) == 0 )
    {
       MessageBox ( "Глобальная переменная терминала 'Счётчик транзакций' не создана!" , "Ошибка" , MB_OK | MB_ICONHAND );
       return ( INIT_FAILED );
    }
  }

Gravação protegida na variável global do terminal (contador de transações):

 //+------------------------------------------------------------------+
//| Expert Set transaction count function                            |
//+------------------------------------------------------------------+
void SetTransCount( const bool up_down )
{
   double tr_count;
   uint i = 0 ;
   do
  {
    i++;
     if ( GlobalVariableGet ( "trans_count" , tr_count ) )
    {
       if ( up_down )
      {
         if ( GlobalVariableSetOnCondition ( "trans_count" , tr_count + 1 , tr_count ) )
        {
          i = 100 ;
        }
      }
       else
      {
         if ( GlobalVariableSetOnCondition ( "trans_count" , tr_count - 1 , tr_count ) )
        {
          i = 100 ;
        }
      }
    }
  }  
   while ( i < 100 );
}

Se o parâmetro up_down = true, aumentamos a variável global do terminal,

e vice versa.

Verificação de fundos com redução automática do volume, em caso de falta de dinheiro:

 //| Expert Check money function                                      |
//+------------------------------------------------------------------+ 
bool CheckMoney( long &volume )
{
   if ( volume <= 0 ) return ( false );
//---
   double symbol_go = SymbolInfoDouble ( _Symbol , SYMBOL_MARGIN_INITIAL );
   double free_margin = ( AccountInfoDouble ( ACCOUNT_FREEMARGIN ) / 100 ) * 90 ; //90% от свободных средств
   double real_go = NormalizeDouble ( symbol_go * volume, 2 );
//---     
   if ( real_go <= free_margin )
  {
     return ( true );
  }
   else
  {
     while ( real_go > free_margin )
    {
      volume--;
      
       if ( volume <= 0 )
      {
         Print ( "CheckMoney: Не хватает средств!" );
         return ( false );
      }  
      real_go = NormalizeDouble ( symbol_go * volume, 2 );
    }
     return ( true );
  }
   Print ( "CheckMoney: Не хватает средств!" ); 
   return ( false );
}

Colocando uma ordem de mercado/limite com o comando OrderSend()

se preço = ''0" - ordem de mercado:

 //+------------------------------------------------------------------+
//| Expert set order function                                        |
//+------------------------------------------------------------------+
void SetOrder( const string aSymbol, ulong &ticket, const double price, const double volume, const bool buy_sell )
{
   MqlTradeRequest request = { 0 };
   MqlTradeResult   result  = { 0 };
  ticket = 0 ;
   
//--- Fill structure
  request.magic = 1234567890 ;
  request.symbol = aSymbol;
  request.volume = volume; 
  request.type_filling = ORDER_FILLING_IOC ;
  request.type_time = ORDER_TIME_DAY ;
    
   if ( price == 0 )
  {
    request.action = TRADE_ACTION_DEAL ;
    request.comment = "Рыночный ордер..." ;
//---    
     if ( buy_sell )
    {
      request.type = ORDER_TYPE_BUY ;
    }
     else
    {
      request.type = ORDER_TYPE_SELL ;
    }
  }
   else
  { 
    request.action = TRADE_ACTION_PENDING ;
    request.price = price;
    request.comment = "Лимитный ордер..." ;
//---    
     if (buy_sell)
    {
      request.type = ORDER_TYPE_BUY_LIMIT ;
    }
     else
    {
      request.type = ORDER_TYPE_SELL_LIMIT ;
    }   
  }  
//--- Send order
   if ( OrderSend ( request, result ) )
  {
     if ( result.retcode == TRADE_RETCODE_PLACED ) 
    {
      ticket = result.order;
    }
     else
    {
       Print ( "SeOrder: Установка ордера не выполнена! " , aSymbol );
    }
  }
   else
  {
     Print ( "SeOrder: Ордер не отправлен! " , aSymbol );
  }
}

Excluindo um pedido com o comando OrderSend()

 void RemoveOrder( ulong & ord_ticket )
{
   if ( ord_ticket >   0 )
  {
     if ( OrderSelect ( ord_ticket ) )
    {
       MqlTradeRequest request = { 0 };
       MqlTradeResult   result  = { 0 };
//---  
      request.action = TRADE_ACTION_REMOVE ;
      request.order  = ord_ticket;
//---  
       if ( OrderSend ( request, result ) )
      {
         if ( result.retcode == TRADE_RETCODE_PLACED )
        { 
          ord_ticket = result.order;
        }
         else
        {
           Print ( "RemoveOrder: Удаление старого ордера не выполнено! Билет = " , ord_ticket );
        }  
      }
       else
      {
         Print ( "RemoveOrder: Ордер не отослан! Билет = " , ord_ticket );
      }
    }
  }
}

Colocando uma ordem pendente com o comando OrderSend()

 //+------------------------------------------------------------------+
//| Place order                                                      |
//+------------------------------------------------------------------+
void PlaceOrder( const string aSymbol, ulong & ticket, const double price, const double volume, const bool buy_sell )
{
   MqlTradeRequest request = { 0 };
   MqlTradeResult   result  = { 0 };
  ticket = 0 ;
     
//--- Fill structure
  request.action = TRADE_ACTION_PENDING ;
  request.magic  = 1234567890 ;
  request.symbol = aSymbol;
  request.volume = volume;
  request.price  = price;
    
   if ( buy_sell )
  {
    request.type = ORDER_TYPE_BUY_LIMIT ;
  }
   else
  {
    request.type = ORDER_TYPE_SELL_LIMIT ;
  } 
  request.comment = "Отложенный ордер..." ;      
  request.type_filling = ORDER_FILLING_RETURN ;
  request.type_time = ORDER_TIME_DAY ;
  
//--- Send order
   if ( OrderSend ( request, result ) )
  {
     if ( result.retcode == TRADE_RETCODE_PLACED ) 
    {
      ticket = result.order;
    }
     else
    {
       Print ( "PlaceOrder: Ордер не установлен!" );
    }
  }
   else
  {
     Print ( "PlaceOrder: Ордер не отослан! " );
  }
}

Modificando uma ordem pendente com o comando OrderSend()

 //+------------------------------------------------------------------+
// Modify order                                                      |
//+------------------------------------------------------------------+
void ModifyOrder( const string aSymbol, const double price, ulong & ticket )
{
   if ( ticket > 0 )
  {
     if ( OrderSelect ( ticket ) )
    {
       MqlTradeRequest request = { 0 };
       MqlTradeResult   result  = { 0 };
   
      request.action = TRADE_ACTION_MODIFY ;
      request.symbol = aSymbol;
      request.order  = ticket;
      request.price  = price;
      request.type_time = ORDER_TIME_DAY ;
  
       if ( OrderSend ( request, result ) )
      {
         if ( result.retcode == TRADE_RETCODE_PLACED ) 
        {
          ticket = result.order;
        }
         else
        {
           Print ( "ModifyOrder: Ордер не модифицирован! Билет = " , ticket );
        }
      }
       else
      {
         Print ( "ModifyOrder: Ордер не отослан! Билет " , ticket );
      }
    }
  }
}

Configurando uma ordem pendente com o comando OrderSendAsync()

Ao usar este comando, o ticket não é obtido como resultado deste

funções, mas na função OnTradeTransaction(). Na função OrderSendAsync(), nós

obter o número do pedido para fazer um pedido:

uint req_id;
 ulong order_ticket = 0;
 void PlaceAsync( const string a_symbol, uint & req_id, const double price, const double volume, const bool buy_sell )
{
   MqlTradeRequest request = { 0 };
   MqlTradeResult   result  = { 0 };
  req_id = 0 ;
     
//--- Fill structure
  request.action = TRADE_ACTION_PENDING ;
  request.magic  = 1234567890 ;
  request.symbol = a_symbol;
  request.volume = volume;
  request.price  = price;
    
   if ( buy_sell )
  {
    request.type = ORDER_TYPE_BUY_LIMIT ;
  }
   else
  {
    request.type = ORDER_TYPE_SELL_LIMIT ;
  } 
  request.comment = "Отложенный ордер..." ;      
  request.type_filling = ORDER_FILLING_RETURN ;
  request.type_time = ORDER_TIME_DAY ;
  
//--- Send order
   if ( OrderSendAsync ( request, result ) )
  {
     if ( result.retcode == TRADE_RETCODE_PLACED ) 
    {
      req_id = result.request_id;
    }
     else
    {
       Print ( "PlaceAsync: Ордер не установлен! " , a_symbol );
    }
  }
   else
  {
     Print ( "PlaceAsync: Ордер на отослан! " , a_symbol );
  }
}

Obtendo um ticket pelo número da solicitação:

 void OnTradeTransaction ( const MqlTradeTransaction &trans,
                         const MqlTradeRequest &request,
                         const MqlTradeResult &result )
{
   switch ( trans.type )
  {
     case TRADE_TRANSACTION_REQUEST : if ( trans.order_state == ORDER_STATE_STARTED )
                                    {
                                       if ( ( req_id != 0 ) && ( result.request_id == req_id ) )
                                      {
                                         if ( result.retcode == TRADE_RETCODE_PLACED )
                                        {
                                           if ( result.order > 0 )
                                          {
                                            order_ticket = result.order;
                                          }
                                           else
                                          {
                                             Print ( "OnTradeTransaction: Не получен билет! Запрос = " , req_id );
                                          }
                                        }
                                      }
                                    }  
                                     break ;
                                    
  }
}

Manipulação de erros (códigos de retorno) das funções OrderSend() e OrderSendAsync()

a função CheckError() é adicionada à implementação do envio de pedidos. Exemplo:

 void ModifyOrder( const string aSymbol, const double price, ulong & ticket )
{
   if ( ticket > 0 )
  {
     if ( OrderSelect ( ticket ) )
    {
       MqlTradeRequest request = { 0 };
       MqlTradeResult   result  = { 0 };
   
      request.action = TRADE_ACTION_MODIFY ;
      request.symbol = aSymbol;
      request.order  = ticket;
      request.price  = price;
      request.type_time = ORDER_TIME_DAY ;
  
       if ( OrderSend ( request, result ) )
      {
         if ( result.retcode == TRADE_RETCODE_PLACED ) 
        {
          ticket = result.order;
        }
         else
        {
          CheckError( result.retcode, "ModifyOrder: Ордер не модифицирован! Билет = " , ticket );
        }
      }
       else
      {
        CheckError( result.retcode, "ModifyOrder: Ордер не отослан! Билет " , ticket );
      }
    }
  }
}

A própria função CheckError() ( nem todos os códigos de retorno no exemplo )

 void CheckError( const uint ret_code, const string err_msg, const ulong a_ticket )
{
   switch ( ret_code )
  {
     case TRADE_RETCODE_TRADE_DISABLED :
                                           break ;
     case TRADE_RETCODE_MARKET_CLOSED :
                                           break ;
     case TRADE_RETCODE_NO_MONEY :
                                           break ; 
     case TRADE_RETCODE_PRICE_OFF :
                                           break ;   
     case TRADE_RETCODE_TOO_MANY_REQUESTS :
                                           break ;
     case TRADE_RETCODE_SERVER_DISABLES_AT : 
                                           break ;
     case TRADE_RETCODE_CLIENT_DISABLES_AT : 
                                           break ;
     case TRADE_RETCODE_INVALID_PRICE :      
                                           break ;
     case TRADE_RETCODE_INVALID :
                                           break ;                                                       
                
     default : Print ( err_msg, GetRetCode( ret_code ), "; Билет = " , a_ticket );  
             break ;            
  }
}

Ver continuação


Peculiaridades:

Ao comprar mais de UM contrato com uma ordem LIMIT com execução ORDER_FILLING_IOC,

um pedido no histórico pode ser armazenado como ORDER_STATE_CANCELED se o pedido for preenchido com o primeiro volume,

e o segundo falhou.

Exemplo:

Comprando 3 contratos com uma ordem LIMIT com execução ORDER_FILLING_IOC,

existe a seguinte situação:

1. Se compramos os três contratos, o pedido no histórico tem o estado = ORDER_STATE_FILLED

2. Se não compramos nada, então no estado do histórico = ORDER_STATE_CANCELED

3. Se compramos os dois primeiros contratos (28449), mas não compramos 1 contrato (28450), o estado no histórico = ORDER_STATE_CANCELED

4. Se não compramos os dois primeiros contratos (28449), mas compramos 1 (28450), então no histórico state = ORDER_STATE_PARTIAL

======= Fim do exemplo ===================

O número de transações ineficientes (uma transação ineficiente é uma transação que não levou a uma transação.

Colocação, modificação e exclusão de uma ordem) no mercado de futuros FORTS é limitado a 2000 por sessão de negociação completa

das 19-00 do dia atual às 18-45 do dia seguinte. Por exceder - multa do Câmbio

http://moex.com/n8725

Insetos:

1. Se ocorrer uma falha no servidor MT5 do corretor ou na bolsa, o comando

delete(modify) O servidor de pedidos EXISTENTE retorna:

erro 10013 = TRADE_RETCODE_INVALID = Solicitação inválida ( Solicitação inválida )

2. Às vezes, também quando falha, ao tentar colocar uma ordem pendente ou limitada, ocorre um erro - " O instrumento não está disponível no momento "

(isso não é um erro de digitação, essa é a mensagem)

Não há código de retorno para o servidor de negociação na documentação!

 

Então e se algum regime não for apoiado? Por que isso deveria proibi-lo de negociar?

Especialmente se "não suporta o modo de ajuste de ordem Stop Limit"? Este é o problema de não poder negociar de forma alguma.

© DESTRUIÇÃO NA CABEÇA

 

Está escrito no início:

IMPORTANTE: Para não "esticar" o tema, se você tiver algum comentário,

ou ter perguntas, criarum tópico separadonesta seção(não vou responder aqui).

P / S para os especialmente "dotados" :

Nesta função, você precisa verificar os parâmetros que

que você usará em sua EA. Aqui está um exemplo:

.......................

 

Continua:

Funções úteis e freqüentemente utilizadas:

A própria função CheckError() (nem todos os códigos de retorno no exemplo)

.........................................................................

Decodificação de códigos de retorno:

string GetRetCode( const uint code )
{
  string retcode;
  
  switch( code )
  {
    case TRADE_RETCODE_REQUOTE: retcode = "Реквота";
         break;
    case TRADE_RETCODE_REJECT: retcode = "Запрос отвергнут";
         break;
    case TRADE_RETCODE_CANCEL: retcode = "Запрос отменен трейдером";
         break;
    case TRADE_RETCODE_PLACED: retcode = "Ордер размещен";
         break;
    case TRADE_RETCODE_DONE: retcode = "Заявка выполнена";
         break;
    case TRADE_RETCODE_DONE_PARTIAL: retcode = "Заявка выполнена частично";
         break;
    case TRADE_RETCODE_ERROR: retcode = "Ошибка обработки запроса";
         break;
    case TRADE_RETCODE_TIMEOUT: retcode = "Запрос отменен по истечению времени";
         break;
    case TRADE_RETCODE_INVALID: retcode = "Неправильный запрос";
         break;
    case TRADE_RETCODE_INVALID_VOLUME: retcode = "Неправильный объем в запросе";
         break;
    case TRADE_RETCODE_INVALID_PRICE: retcode = "Неправильная цена в запросе";
         break;
    case TRADE_RETCODE_INVALID_STOPS: retcode = "Неправильные стопы в запросе";
         break;
    case TRADE_RETCODE_TRADE_DISABLED: retcode = "Торговля запрещена";
         break;
    case TRADE_RETCODE_MARKET_CLOSED: retcode = "Рынок закрыт";
         break;
    case TRADE_RETCODE_NO_MONEY: retcode = "Нет достаточных денежных средств для выполнения запроса";
         break;
    case TRADE_RETCODE_PRICE_CHANGED: retcode = "Цены изменились";
         break;
    case TRADE_RETCODE_PRICE_OFF: retcode = "Отсутствуют котировки для обработки запроса";
         break;
    case TRADE_RETCODE_INVALID_EXPIRATION: retcode = "Неверная дата истечения ордера в запросе";
         break;
    case TRADE_RETCODE_ORDER_CHANGED: retcode = "Состояние ордера изменилось";
         break;
    case TRADE_RETCODE_TOO_MANY_REQUESTS: retcode = "Слишком частые запросы";
         break;
    case TRADE_RETCODE_NO_CHANGES: retcode = "В запросе нет изменений";
         break;
    case TRADE_RETCODE_SERVER_DISABLES_AT: retcode = "Автотрейдинг запрещен сервером";
         break;
    case TRADE_RETCODE_CLIENT_DISABLES_AT: retcode = "Автотрейдинг запрещен клиентским терминалом";
         break;
    case TRADE_RETCODE_LOCKED: retcode = "Запрос заблокирован для обработки";
         break;
    case TRADE_RETCODE_FROZEN: retcode = "Ордер или позиция заморожены";
         break;
    case TRADE_RETCODE_INVALID_FILL: retcode = "Указан неподдерживаемый тип исполнения ордера по остатку";
         break;
    case TRADE_RETCODE_CONNECTION: retcode = "Нет соединения с торговым сервером";
         break;
    case TRADE_RETCODE_ONLY_REAL: retcode = "Операция разрешена только для реальных счетов";
         break;
    case TRADE_RETCODE_LIMIT_ORDERS: retcode = "Достигнут лимит на количество отложенных ордеров";
         break;
    case TRADE_RETCODE_LIMIT_VOLUME: retcode = "Достигнут лимит на объем ордеров и позиций для данного символа";
         break;
    case TRADE_RETCODE_INVALID_ORDER: retcode = "Неверный или запрещённый тип ордера";
         break;
    case TRADE_RETCODE_POSITION_CLOSED: retcode = "Позиция с указанным POSITION_IDENTIFIER уже закрыта";
         break;
    default: retcode = "Нет кода возврата.";  
         break; 
  }
  return( retcode );
}

Recomendação:

Ao projetar EAs para FORTS, não recomendo o uso do evento Tick, mas

é melhor usar o evento BookEvent

Exemplos:

Adicionando um Tick:

(Use SOMENTE no OnInit() )

  if ( !MarketBookAdd( _Symbol ) )
  {
    MessageBox( "Не добавлен стакан фьючерса " + _Symbol + "!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  } 

Remoção de uma assinatura de um copo:

void OnDeinit( const int reason )
{
  MarketBookRelease( _Symbol );
}

Obtenha o melhor ASK e BID e seus volumes do tumbler de preços:

double sell_price, buy_price;
long sell_volume, buy_volume;

//+------------------------------------------------------------------+
//| Expert Get Stakan values function                                |
//+------------------------------------------------------------------+ 
bool GetStakanValues( const string aSymbol, double &sell_price,
                      double &buy_price, long &sell_volume, long &buy_volume )
{
  MqlBookInfo book_price[];
  buy_price  = 0;
  sell_price = DBL_MAX;
  buy_volume = 0;
  sell_volume = 0;
  
//--- Get stakan
  if ( MarketBookGet( aSymbol, book_price ) )//getBook )
  {
    int size = ArraySize( book_price );
//---    
    if ( size > 0 )
    {
      double a_min_price = SymbolInfoDouble( aSymbol, SYMBOL_SESSION_PRICE_LIMIT_MIN );
      double a_max_price = SymbolInfoDouble( aSymbol, SYMBOL_SESSION_PRICE_LIMIT_MAX );
//---     
      for( int i = 0; i < size; i++ )
      {
        if ( book_price[i].type == BOOK_TYPE_SELL )
        {
          if ( book_price[i].price < sell_price )
          {
            sell_price = book_price[i].price;
            sell_volume = book_price[i].volume;  
          }
        }
        else
        if ( book_price[i].type == BOOK_TYPE_BUY ) //First buy - exit
        {
          buy_price = book_price[i].price;
          buy_volume = book_price[i].volume;
          break;
        }
      }
      if ( ( buy_price <= a_max_price ) && ( buy_price >= a_min_price ) &&
           ( sell_price <= a_max_price ) && ( sell_price >= a_min_price ) )
      {
        if ( sell_price == DBL_MAX ) sell_price = 0;
//---        
        if ( ( sell_price > 0 ) && ( buy_price > 0 ) )
        {
          return( true );
        }  
      }
    }
  }
//---
  if ( sell_price == DBL_MAX ) sell_price = 0;
//---   
  return( false); 
}

Chamada de função:

Verificandose ( a_símbolo == _Símbolo ) é OBRIGATÓRIO, ele garante que é sua pilha de preços que mudou.

//+------------------------------------------------------------------+
//| Expert On Book event function                                    |
//+------------------------------------------------------------------+  
void OnBookEvent( const string &a_symbol )
{
  if ( a_symbol == _Symbol )
  {
    if ( GetStakanValues( _Symbol, sell_price, buy_price, sell_volume, buy_volume ) )
    {
      //you code
    }
  }
}
 

OBRIGADO!!!)

 

Características especiais:

Fórmulas de cálculo e atribuição de pontos por ineficaz e defeituoso

transações no anexo.

P/S Tanto as regras como os pontos são alterados com frequência suficiente :(

Arquivos anexados:
 

Funções úteis e freqüentemente utilizadas:

A função SetStDayTime() retorna a hora de início do dia de negociação (no momento do pedido).

Função GetExgangeFee() retorna comissão de câmbio e número de transações para o dia de negociação (no momento do pedido):

//+------------------------------------------------------------------+
//|                                                       Tr_fee.mq5 |
//|                                          Copyright 2015, Mikalas |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Mikalas"
#property link      "https://www.mql5.com"
#property version   "1.00"
//
input long   TrPoint   = 1;              //Балл за транзакцию
input long   DealPoint = 40;             //Балл за сделку
//
datetime start_day_time;
//
//+------------------------------------------------------------------+
//| Expert Set start day time function                               |
//+------------------------------------------------------------------+
datetime SetStDayTime()
{
  MqlDateTime  dt_str; 
  TimeTradeServer( dt_str );
//---
  if ( ( dt_str.day_of_week == 0 ) || ( dt_str.day_of_week == 6 ) ) return( datetime( 0 ) );  
//---
  string time_str = IntegerToString( dt_str.year ) + "." + IntegerToString( dt_str.mon ) +
                    "." + IntegerToString( dt_str.day ) + " 19:00:00";
  ulong cur_day = ulong( StringToTime( time_str ) );                     

  if ( ( dt_str.hour >= 19 ) && ( dt_str.hour <= 23 ) )
  {
    return( StringToTime( time_str ) );
  }
  else
  {
    ulong one_day = 24 * 60 * 60;
//---      
    if ( dt_str.day_of_week == 1 )
    {
      cur_day -= one_day * 3;
    }
    else
    {
      cur_day -= one_day;
    }
    return( datetime( cur_day ) );
  }  
  return( datetime( 0 ) );
}
//+------------------------------------------------------------------+
//| Expert calc deals fee function                                   |
//+------------------------------------------------------------------+
double GetExgangeFee( const datetime start_time, long& deals )
{
  double all_fee = 0.0;
  ulong deal_ticket;
  deals = 0;
//---  
  if ( HistorySelect( start_time, TimeTradeServer() ) )
  {
    int deals_total = HistoryDealsTotal();
//---   
    if ( deals_total > 0 )
    {
      for ( uint i = 0; i < uint( deals_total ); i++ )
      {
        deal_ticket = HistoryDealGetTicket( i );
//---        
        if ( deal_ticket > 0 )
        {
          ulong order_ticket = ulong( HistoryDealGetInteger( deal_ticket, DEAL_ORDER ) );
          
          if ( order_ticket > 0 )
          {
            deals++;
            all_fee += HistoryDealGetDouble( deal_ticket, DEAL_COMMISSION );
          }  
        }
      }
      return( MathAbs( all_fee ) );
    }  
  }
  return( 0 );
}
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
  long a_deals;
  start_day_time = SetStDayTime();
//---  
  if ( ulong( start_day_time ) == 0 )
  {
    MessageBox( "Не установлено время начала торгового дня!", "Ошибка", MB_OK | MB_ICONHAND );
    return( INIT_FAILED );
  } 
  Print( "Exgange Fee = ", GetExgangeFee( start_day_time, a_deals ), "; Deals = ", a_deals );
  return( INIT_SUCCEEDED );
}
 
Михаил:

Funções úteis e freqüentemente utilizadas:

A função SetStDayTime() retorna a hora de início do dia de negociação (no momento do pedido).

Função GetExgangeFee() retorna comissão de câmbio e número de transações para o dia de negociação (no momento do pedido):

Este é um candidato sem precedentes para o título de "Hindu Coder - 2015".

SetStDayTime() é resolvido com duas linhas. Mas é claro que você não precisa...

 

Michael, obrigado por suas características!

A invenção de algumas bicicletas por mim é cancelada )

 
Михаил:

Eu tenho que fazê-lo.

E como você faz isso?

Você tem que trabalhar com a representação numérica do tempo.

datetime a=TimeTradeServer(); 

A hora de início do dia:

datetime r=(a/86400)*86400

O horário de hoje às 19h00:

datetime r=(a/86400)*86400+19*3600;

Se a hora às 19:00 de hoje for maior do que a hora atual, então precisamos das 19:00 de ontem:

if(r>a)r-=86400;

Aqui, se precisarmos saltar o fim de semana, verificamos o dia da semana, se domingo, subtrair 86400*2, se sábado, subtrair 86400 (para obter sexta-feira).

É mais ou menos assim.

Em seguida, para exibição, se necessário, converter para uma corda:

TimeToStr(r)
 
Михаил:

E o ano alto?

Agora, traduza seus pensamentos em código concreto.

Reescreva minha função à sua maneira, e como você disse em DOIS linhas!

E o ano bissexto? Tudo vai ficar bem.

Faça-o você mesmo, não quero entender seu código completamente, caso eu perca alguma coisa, que prazer será para você.