FORTS: 초보자를 돕기 위해

 

안녕하세요!

여기에 FORTS 선물 시장에 대한 권장 사항, 버그, 기능 및 자주 사용하는 기능을 게시합니다.

중요: 주제를 "확장"하지 않으려면 의견이 있는 경우

또는 질문이 있습니다 - 이 섹션에서 별도의 주제를 만드십시오(여기서 대답하지 않겠습니다).

추천 :

MQL5 표준 라이브러리 는 FOREX 시장을 위해 "날카롭게" 되어 있으므로

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 로 저장할 수 있습니다.

그리고 두 번째는 실패했다.

예시:

ORDER_FILLING_IOC 실행으로 LIMIT 주문으로 3 계약 구매,

다음과 같은 상황이 있습니다.

1. 3개의 계약을 모두 구매했다면 히스토리의 주문 상태는 ORDER_STATE_FILLLED입니다.

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 특히 "영재"의 경우:

이 기능에서는 해당 매개변수를 확인해야 합니다.

당신은 당신의 고문에서 사용할 것입니다. 다음은 예입니다.

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

 

계속:

자주 사용하고 유용한 기능:

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용 Expert Advisors를 디자인할 때 Tick 이벤트를 사용하는 것은 권장하지 않지만

BookEvent 이벤트를 사용하는 것이 좋습니다

예:

유리 추가:

(OnInit()에서만 사용)

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

유리 구독 삭제:

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

Depth of Market에서 최고의 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 ); 
}

함수 호출:

if ( a_symbol == _Symbol ) 검사는 필수이며 변경된 시장 깊이임을 보장합니다.

 //+------------------------------------------------------------------+
//| 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() 함수는 교환 수수료와 거래일(요청 시)당 거래 수를 반환합니다.

글쎄, "Hindu Coder - 2015"라는 제목을위한 전례없는 경쟁자입니다.

SetStDayTime()은 두 줄로 해결됩니다. 물론 그럴 필요는 없지만...

 

마이클, 당신의 기능에 감사드립니다!

일부 자전거의 발명이 취소되었습니다)

 
Михаил :

정말 필요합니다.

그리고 어떻게?

시간을 숫자로 표현하는 작업이 필요합니다.

 datetime a= TimeTradeServer (); 

하루 시작 시간:

 datetime r=(a/ 86400 )* 86400

오늘 19:00 시간:

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

오늘 19:00의 시간이 현재 시간보다 크면 어제의 19:00이 필요합니다.

 if (r>a)r-= 86400 ;

여기에서 주말을 건너뛰어야 하는 경우 요일을 확인하고 일요일이면 86400 * 2를 빼고 토요일이면 86400(금요일을 구하려면)을 뺍니다.

이 같은.

그런 다음 표시를 위해 필요한 경우 문자열로 변환합니다.

TimeToStr(r)
 
Михаил :

그리고 전성기?

이제 생각을 구체적인 코드로 변환하십시오.

내 기능을 자신의 방식으로 다시 작성하십시오. 두 줄로 말했듯이!

윤년은 어떻습니까? 모든 게 잘 될거야.

직접 구현하십시오. 귀하의 코드를 완전히 이해하고 싶지는 않습니다. 무언가를 놓치면 기쁨을 느낄 것입니다.

사유: