FORTS:帮助初学者

 

下午好!

在这里,我将发布 FORTS 期货市场上的建议、错误、功能和常用功能

重要提示:为了不“拉长”话题,如有意见,

或有问题 - 在本节中创建一个单独的主题(我不会在这里回答)。

建议

MQL5 标准库已针对外汇市场“锐化”,因此对于

FORTS专家的发展我建议自己写一切。

常用和有用的功能:

检查经纪商服务器交易参数的功能。

在这个函数中,有必要检查那些参数

您将在您的顾问中使用。这是一个例子:

(仅在 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 );
} 

使用示例:

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

获取距离工具到期的剩余天数:

 #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 );
  }
}

获取“净”头寸价格,不包括清算:

 //+------------------------------------------------------------------+
//| 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 );
} 

创建用于计数交易的全局终端变量:

(仅在 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 );
    }
  }

对终端全局变量(事务计数器)的受保护写入:

 //+------------------------------------------------------------------+
//| 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 );
}

如果参数up_down = true,那么我们增加终端的全局变量,

反之亦然。

在资金短缺的情况下,自动减少交易量检查资金:

 //| 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 );
}

使用 OrderSend() 命令放置市价单/限价单

如果价格 = ''0" - 市价单:

 //+------------------------------------------------------------------+
//| 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 );
  }
}

使用 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 );
      }
    }
  }
}

使用 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: Ордер не отослан! " );
  }
}

使用 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 );
      }
    }
  }
}

使用 OrderSendAsync() 命令设置挂单

使用此命令时,因此无法获得票证

函数,但在 OnTradeTransaction() 函数中。在 OrderSendAsync() 函数中,我们

获取下单请求的编号:

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 );
  }
}

通过请求号获取票证:

 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 ;
                                    
  }
}

处理 OrderSend() 和 OrderSendAsync() 函数的错误(返回码)

CheckError() 函数被添加到订单发送的实现中。示例:

 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 );
      }
    }
  }
}

CheckError() 函数本身(示例中并非所有返回码

 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 ;            
  }
}

见续


特点:

当使用 ORDER_FILLING_IOC 执行的 LIMIT 订单购买多份合约时,

如果订单以第一笔成交,历史中的订单可以存储为 ORDER_STATE_CANCELED,

第二个失败了。

例子:

以 LIMIT 订单购买 3 份合约,执行 ORDER_FILLING_IOC,

有以下情况:

1. 如果我们买了三张合约,那么历史订单的状态 = ORDER_STATE_FILLED

2.如果我们什么都没买,那么在历史状态= ORDER_STATE_CANCELED

3.如果我们买了前两份合约(28449),但没有买1份合约(28450),那么历史状态= ORDER_STATE_CANCELED

4.如果我们没有买前两份合约(28449),而是买了1份(28450),那么历史状态=ORDER_STATE_PARTIAL

=======示例结束====================

低效交易的数量(低效交易是没有导致交易的交易。

在期货市场 FORTS 的下单、修改和删除订单每个完整交易时段限制为2000

从当天的 19-00 到次日的 18-45。对于超过 - 罚款的交易所

http://moex.com/n8725

错误:

1.如果经纪商的MT5服务器或者交易所出现故障,那么命令

删除(修改)现有订单服务器返回:

错误 10013 = TRADE_RETCODE_INVALID = 无效请求(无效请求)

2. 有时,在尝试下挂单或限价单失败时,也会出现错误 - “该工具当前不可用

(这不是错字,这是信息)

文档中没有交易服务器的返回码!

 

如果某些政权不被支持,那又如何?为什么要让它禁止你交易?

特别是如果 "不支持止损限价订单设置模式"?这就是根本无法交易的麻烦。

© 头部破坏

 

它写在开头。

重要提示:为了不 "拉长 "话题,如果你有任何意见。

或有问题,请在本节创建一个单独的主题(我不会在这里回答)

P / S为特别 "有天赋 "的人。

在这个函数中,你需要检查以下参数

你将在你的EA中使用。下面是一个例子。

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

 

继续。

经常使用和有用的功能。

CheckError()函数本身(例子中不是所有的返回代码

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

返回代码的解释。

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 );
}

建议

当为FORTS设计EA时,我不建议使用Tick事件,但是

最好是使用BookEvent事件

例子。

添加一个勾。

(只在OnInit()中使用 )

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

撤消对玻璃的订阅。

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

从价格的翻滚中获得最佳的ASK和BID以及它们的数量。

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); 
}

功能调用。

检查是否 ( a_symbol == _Symbol )是MUST,它确保是你的价格栈发生了变化

//+------------------------------------------------------------------+
//| 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
    }
  }
}
 

谢谢你!!!)

 

特殊功能。

对低效和错误的计算和给分公式

附件中的交易。

P/S 规则和积分都经常被改变。

附加的文件:
 

经常使用和有用的功能

SetStDayTime()函数返回交易日的开始时间(在请求的时候)。

函数GetExgangeFee()返回交易日(请求时)的交易所佣金和交易数量。

//+------------------------------------------------------------------+
//|                                                       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 );
}
 
Михаил:

经常使用和有用的功能

SetStDayTime()函数返回交易日的开始时间(在请求的时候)。

函数GetExgangeFee()返回交易日(请求时)的交易所佣金和交易数量。

这是一个史无前例的 "印度教编码者--2015 "称号的竞争者。

SetStDayTime()是用两行字解决的。但当然,你不需要...

 

迈克尔,感谢你的专题报道!

由我发明的一些自行车被取消了 )

 
Михаил:

我必须这样做。

那么你是如何做到的呢?

你必须与时间的数字表示法一起工作。

datetime a=TimeTradeServer(); 

当天的开始时间。

datetime r=(a/86400)*86400

今天下午7点的时间。

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

如果今天19:00的时间大于当前时间,那么我们需要昨天的19:00。

if(r>a)r-=86400;

在这里,如果我们需要跳过周末,我们检查一周中的哪一天,如果是星期天,就减去86400*2,如果是星期六,就减去86400(得到星期五)。

情况是这样的。

然后,为了显示,如果需要的话,转换为一个字符串。

TimeToStr(r)
 
Михаил:

而高年?

现在,把你的想法翻译成具体的代码。

用你自己的方式重写我的功能,就像你说的那样,用两行字就可以了!

闰年是怎么回事?一切都会好起来的。

你就自己做吧,我不想完全理解你的代码,万一我错过了什么,你会有多大的快乐。

原因: