오류, 버그, 질문 - 페이지 958

 
antt :

다른 입력 매개변수를 전달합니다. 기호, 기간, 입력 매개변수가 동일하고 표시기가 동일합니다. 터미널은 리소스 소비를 최소화하려고 시도하며 이 경우 표시기의 새 복사본이 생성되지 않습니다. 하나의 mql5 프로그램이 실제로 작동합니다.

이 간단한 질문에 대해 알려주십시오. https://www.mql5.com/ru/forum/1111/page975#comment_469324 그렇지 않으면 아무도 모릅니다. )))

 

문제를 해결하는 데 도움이 됩니다. 테스터에서는 모든 것이 완벽하게 작동하지만 m1의 RTS 데모에서는 때때로 3로트가 많은 위치 대신 각각 3로트씩 2개의 주문을 보내며 총 6로트의 위치를 ​​가집니다.

 #property copyright "Copyright 2013, DKeN"
#property link       ""
#property version   "1.00"
/*
1 Название: Параболик
2 Терминал: МТ5
3​ Рабочий инструмент: любой инструмент и период
4​ Индикатор: параболик
5​ Правила:
 при пересечение входим в направлении пересечения по рынку , 
 профит делим на 3 части , при закрытие первого выставляем стоп в ноль или чуть в плюс, 
 если профит не достигнут, а цена ушла в минус переворачиваем позицию при пересечении параболика…
6​ второй вариант: при пересечение входим в направлении пересечения по рынку , профит делим на 2 части , при закрытие первой части вторую оставляем до пересечения параболика
7​ настройки: а) к-во лотов
б) индикатор
в) время работы
8. возможность работы по нескольким инструментам на одном счете

если торгуем на РТС необходимо строго со спецификацией инструмента данные задавать!

*/
input string comment= "" ;
//комментарий к ордеру
input int     slippage= 10 ; 
//проскальзывание
input double lot= 3 ;
//рабочий лот позиции
input int     takeprofit= 200 ;
//тейк профит основной позиции
input int     stoploss= 1000 ;
//стоп лосс основной позиции
input int     mode= 1 ;
/*режим выхода 1 или 2*/
input int     takeprofit1= 100 ;
//точка закрытия первой части профита в пунктах
input double lot1= 1 ;
//объем закрываемой части ордера
input double bu1= 10 ; 
//для режима 1, пренос в безубыток +1
input int     takeprofit2= 150 ;
//точка закрытия второй части профита в пунктах
input double lot2= 1 ;
//объем закрываемой позиции

input ENUM_TIMEFRAMES tf= 0 ; 
//период, 0 - по умолчанию с графика текущий
input double step= 0.02 ;
input double maximum= 0.2 ;
//настрйоки для сар step,maximum
input string times= "00:00-24:00" ;
//поддерживаются интервалы через , например 00:00-12:00, 16:00-20:00 и т.д. поддержка ночного перехода например 22:00-05:00
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int psar=- 1 ;
ulong semafor= 0 ;

int OnInit ()
  {
//---
   psar= iSAR ( NULL ,tf,step,maximum);
   if (psar== INVALID_HANDLE ){
       PrintFormat ( "Не удалось создать хэндл индикатора iSAR для пары %s/%s, код ошибки %d" , _Symbol , EnumToString ( _Period ), GetLastError ());
       return (- 1 );
   }    
   semafor= 0 ;
//---
   return ( 0 );
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit ( const int reason)
  {
//---
   if (psar!= INVALID_HANDLE ) IndicatorRelease (psar);
   Comment ( "" );
   
  }
  
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick ()
  {
//---
     
   bool bWork=time_check(times);
   Comment ( "Торговый интервал времени" );
   if (!bWork) Comment ( "Неторговый интервал времени. Разрешено закрытие по обратному сигналу и частичное закрытие. Открытие новых сделок запрещено." );
   double sar[],dLot,open,stop,take;
   
   ENUM_POSITION_TYPE type;
   ArraySetAsSeries (sar, true );  
   string n= _Symbol ;
   
   if ( CopyBuffer (psar, 0 , 0 , 2 ,sar)>= 0 ){     
       //1 - предыдущее значение
       //0 - текущий бар
       MqlRates rates[];
       MqlTick tick;
      
       ArraySetAsSeries (rates, true );
       int op= 0 ;
      
       if ( CopyRates ( NULL ,tf, 0 , 2 ,rates)> 0 ){
         
         if ( SymbolInfoTick (n,tick)){
             if (tick.bid<sar[ 1 ] && sar[ 1 ]<rates[ 0 ].open) op=- 1 ;
             else if (tick.ask>sar[ 1 ] && sar[ 1 ]>rates[ 0 ].open) op= 1 ;
         }
                 
         //првоерим если позиции в рынке нет, попробуем открыть по сигналу
         if (! PositionSelect (n)) {
            order_OrderDeleteAll(n); //удалим отложки
            
             if (op== 0 ) return ; //сигнала нет!   
            
             if (bWork){
               if (op== 1 ) order_OrderSend(n, ORDER_TYPE_BUY ,lot, 0 ,stoploss,takeprofit,comment);
               if (op==- 1 ) order_OrderSend(n, ORDER_TYPE_SELL ,lot, 0 ,stoploss,takeprofit,comment);
            }
            
         } else {
            type=( ENUM_POSITION_TYPE ) PositionGetInteger ( POSITION_TYPE );
            dLot= PositionGetDouble ( POSITION_VOLUME );
            
             if (dLot==lot){
                   int orders[];
                   int all=order_OrdersTotal(n,orders);
                  
                  open= PositionGetDouble ( POSITION_PRICE_OPEN );
                  
                   if (type== POSITION_TYPE_BUY && orders[ ORDER_TYPE_SELL_LIMIT ]== 0 ){
                     if (mode== 2 || mode== 1 )order_OrderSend(n, ORDER_TYPE_SELL_LIMIT ,lot1,open+takeprofit1* _Point , 0 , 0 , "" );
                     if (mode== 1 )order_OrderSend(n, ORDER_TYPE_SELL_LIMIT ,lot2,open+takeprofit2* _Point , 0 , 0 , "" );
                  }
                  
                   if (type== POSITION_TYPE_SELL && orders[ ORDER_TYPE_BUY_LIMIT ]== 0 ){
                     if (mode== 2 || mode== 1 )order_OrderSend(n, ORDER_TYPE_BUY_LIMIT ,lot1,open-takeprofit1* _Point , 0 , 0 , "" );
                     if (mode== 1 )order_OrderSend(n, ORDER_TYPE_BUY_LIMIT ,lot2,open-takeprofit2* _Point , 0 , 0 , "" );
                  }
                  
            } else if (dLot<lot && mode== 1 ){
               open= PositionGetDouble ( POSITION_PRICE_OPEN );
               stop= PositionGetDouble ( POSITION_SL );
               take= PositionGetDouble ( POSITION_TP );
               
               if (type== POSITION_TYPE_BUY && (stop<open || stop== 0.0 )) order_OrderModify(n,open+bu1* _Point ,take);
               if (type== POSITION_TYPE_SELL && (stop>open || stop== 0.0 )) order_OrderModify(n,open-bu1* _Point ,take);
            }
            
             //Print(GetLastError()," op=",op," type=",type);           
             if (op== 0 ) return ;
             //позиция к этому моменту могла быть уже закрыта, перепроверим и проверим ее лот и тип
             if ( PositionSelect (n)){
               type=( ENUM_POSITION_TYPE ) PositionGetInteger ( POSITION_TYPE );
               dLot= PositionGetDouble ( POSITION_VOLUME );
               //осуществим переворот, да так чтобы закрыть остаток и открыть начальным лотом
               if (type== POSITION_TYPE_BUY && op==- 1 ) {
                  order_OrderDeleteAll(n); //удалим отложки
                  order_OrderSend(n, ORDER_TYPE_SELL ,dLot, 0 , 0 , 0 ,comment);
               } else if (type== POSITION_TYPE_SELL && op== 1 ) {
                  order_OrderDeleteAll(n); //удалим отложки
                  order_OrderSend(n, ORDER_TYPE_BUY ,dLot, 0 , 0 , 0 ,comment);
               }
            }
            
         }
      }
     
   }
   
  }
//+------------------------------------------------------------------+
bool order_OrderModify( string name, double sl, double tp){
/* 
SL & TP Modification
Торговый приказ на модификацию уровней StopLoss и/или TakeProfit. Требуется указание 4 полей:
action 
symbol 
sl 
tp 
*/
   MqlTradeRequest   rq={ 0 };       // структура запроса
   MqlTradeResult    rs={ 0 };    
   
   rq.action= TRADE_ACTION_SLTP ; 
   rq.symbol=name;
   rq.sl=sl;
   rq.tp=tp;
   
   return ( OrderSend (rq,rs)); 
}
bool order_OrderSend( string name, ENUM_ORDER_TYPE type, double dlot, double open, double sl, double tp, string cmt){
   MqlTradeRequest   rq={ 0 };       // структура запроса
   MqlTradeResult    rs={ 0 };    
   MqlTick tick={ 0 };
   MqlTradeCheckResult cr={ 0 };    
   if ( PositionSelect (name)) semafor= 0 ;
   
   if (semafor> 0 ) return ( false );
   
   if (type== ORDER_TYPE_BUY || type== ORDER_TYPE_SELL ){
      
      
         
      rq.action= TRADE_ACTION_DEAL ;
      rq.symbol=name;
      rq.volume=NLot(name,dlot);
      rq.type=type;
      
       bool ntick= SymbolInfoTick (name,tick);
      
       if (open<= 0 ){
         if (type== ORDER_TYPE_BUY ) rq.price=tick.ask;
         else if (type== ORDER_TYPE_SELL ) rq.price=tick.bid;
      } else {
         rq.price=open; //если цена указана явно, то откроем по цене+проскальзывание
      }
      
      rq.sl= 0 ;
      rq.tp= 0 ;
       //выставим стоп
       if (sl> 0 && type== ORDER_TYPE_BUY ) rq.sl= NormalizeDouble (rq.price-sl* _Point , _Digits );
       else if (sl> 0 && type== ORDER_TYPE_SELL ) rq.sl= NormalizeDouble (rq.price+sl* _Point , _Digits );
       //выставим тейк
       if (tp> 0 && type== ORDER_TYPE_BUY ) rq.tp= NormalizeDouble (rq.price+tp* _Point , _Digits );
       else if (tp> 0 && type== ORDER_TYPE_SELL ) rq.tp= NormalizeDouble (rq.price-tp* _Point , _Digits );
      
      rq.deviation=slippage; //допустимое проскальзывание
      rq.type_filling= ORDER_FILLING_FOK ;
   
      rq.comment=cmt;
   } else {
      
      
      rq.action= TRADE_ACTION_PENDING ;
      rq.symbol=name;
      rq.volume=NLot(name,dlot);
      rq.type=type;
      rq.deviation=slippage; //допустимое проскальзывание
      rq.type_time= ORDER_TIME_DAY ;
//ORDER_TIME_GTC; //ордер будет до снятия его программно или вручную

       //bool ntick=SymbolInfoTick(name,tick);
      
      rq.price=open; 
      
      rq.sl=sl; //должна быть ценой!
      rq.tp=tp;
      rq.type_filling= ORDER_FILLING_RETURN ;

      rq.comment=cmt;
   }
   
      
   if ( OrderCheck (rq,cr)){
         
             if ( OrderSend (rq,rs)){
               if (rs.retcode!= TRADE_RETCODE_DONE && rs.retcode!= TRADE_RETCODE_PLACED ){
                   Comment ( "Debug: order_OrderSend(retcode=" ,ResultRetcodeDescription(cr.retcode), ")" );
               }
                  
               semafor=rs.deal;
                   
               if (rs.retcode== TRADE_RETCODE_DONE || rs.retcode== TRADE_RETCODE_PLACED ){
                  
                       
                   if (type== ORDER_TYPE_BUY || type== ORDER_TYPE_SELL ){
                     rq.action= TRADE_ACTION_SLTP ; 
                     rq.order= rs.order;
           
                     return ( OrderSend (rq,rs)); 
                  }
               }
               
               return ( true );
            }
            
         
   } else {   
         semafor= 0 ;
         Comment ( "Debug: order_OrderSend(retcode=" ,ResultRetcodeDescription(cr.retcode), ")" );
   }
   
   
   return ( false );
   
}
/*удаляет отложки*/
bool order_OrderDeleteAll( string name){
   ulong ticket;
   MqlTradeRequest rq={ 0 };
   MqlTradeResult rs={ 0 };
   
   for ( int i= OrdersTotal ()- 1 ;i>= 0 ;i--){
      
       if ((ticket= OrderGetTicket (i))> 0 ){
         ZeroMemory (rq);
         ZeroMemory (rs);
         rq.action= TRADE_ACTION_REMOVE ;
         rq.order=ticket;
         
         OrderSend (rq,rs);
      }
   }
   
   return ( false );
}

int order_OrdersTotal( string name, int &orders[]){
   ulong ticket;
   int total= 0 ;
   ArrayResize (orders, 10 , 0 );
   ArrayInitialize (orders, 0 );
//--- пройдем по всем отложенным ордерам
   for ( int i= OrdersTotal ()- 1 ;i>= 0 ;i--)
       if ((ticket= OrderGetTicket (i))> 0 )
         if ( OrderGetString ( ORDER_SYMBOL )==name){
             orders[( int ) OrderGetInteger ( ORDER_TYPE )]++;
             total++;
         }    
//---
   return (total);
  }


//+------------------------------------------------------------------+ 
//| возврат стрингового результата торговой операции по его коду     | 
//+------------------------------------------------------------------+ 
string ResultRetcodeDescription( int retcode) 
  { 
   string str; 
//---- 
   switch (retcode) 
     { 
       case TRADE_RETCODE_REQUOTE : str= "Реквота" ; break ; 
       case TRADE_RETCODE_REJECT : str= "Запрос отвергнут" ; break ; 
       case TRADE_RETCODE_CANCEL : str= "Запрос отменен трейдером" ; break ; 
       case TRADE_RETCODE_PLACED : str= "Ордер размещен" ; break ; 
       case TRADE_RETCODE_DONE : str= "Заявка выполнена" ; break ; 
       case TRADE_RETCODE_DONE_PARTIAL : str= "Заявка выполнена частично" ; break ; 
       case TRADE_RETCODE_ERROR : str= "Ошибка обработки запроса" ; break ; 
       case TRADE_RETCODE_TIMEOUT : str= "Запрос отменен по истечению времени" ; break ; 
       case TRADE_RETCODE_INVALID : str= "Неправильный запрос" ; break ; 
       case TRADE_RETCODE_INVALID_VOLUME : str= "Неправильный объем в запросе" ; break ; 
       case TRADE_RETCODE_INVALID_PRICE : str= "Неправильная цена в запросе" ; break ; 
       case TRADE_RETCODE_INVALID_STOPS : str= "Неправильные стопы в запросе" ; break ; 
       case TRADE_RETCODE_TRADE_DISABLED : str= "Торговля запрещена" ; break ; 
       case TRADE_RETCODE_MARKET_CLOSED : str= "Рынок закрыт" ; break ; 
       case TRADE_RETCODE_NO_MONEY : str= "Нет достаточных денежных средств для выполнения запроса" ; break ; 
       case TRADE_RETCODE_PRICE_CHANGED : str= "Цены изменились" ; break ; 
       case TRADE_RETCODE_PRICE_OFF : str= "Отсутствуют котировки для обработки запроса" ; break ; 
       case TRADE_RETCODE_INVALID_EXPIRATION : str= "Неверная дата истечения ордера в запросе" ; break ; 
       case TRADE_RETCODE_ORDER_CHANGED : str= "Состояние ордера изменилось" ; break ; 
       case TRADE_RETCODE_TOO_MANY_REQUESTS : str= "Слишком частые запросы" ; break ; 
       case TRADE_RETCODE_NO_CHANGES : str= "В запросе нет изменений" ; break ; 
       case TRADE_RETCODE_SERVER_DISABLES_AT : str= "Автотрейдинг запрещен сервером" ; break ; 
       case TRADE_RETCODE_CLIENT_DISABLES_AT : str= "Автотрейдинг запрещен клиентским терминалом" ; break ; 
       case TRADE_RETCODE_LOCKED : str= "Запрос заблокирован для обработки" ; break ; 
       case TRADE_RETCODE_FROZEN : str= "Ордер или позиция заморожены" ; break ; 
       case TRADE_RETCODE_INVALID_FILL : str= "Указан неподдерживаемый тип исполнения ордера по остатку " ; break ; 
       case TRADE_RETCODE_CONNECTION : str= "Нет соединения с торговым сервером" ; break ; 
       case TRADE_RETCODE_ONLY_REAL : str= "Операция разрешена только для реальных счетов" ; break ; 
       case TRADE_RETCODE_LIMIT_ORDERS : str= "Достигнут лимит на количество отложенных ордеров" ; break ; 
       case TRADE_RETCODE_LIMIT_VOLUME : str= "Достигнут лимит на объем ордеров и позиций для данного символа" ; break ; 
       default : str= "Неизвестный результат" ; 
     } 
//---- 
   return (str); 
  } 
  
   double NLot( string name, double dlot){
       double stepLot= SymbolInfoDouble (name, SYMBOL_VOLUME_STEP );
      
       return ( MathFloor (dlot/stepLot)*stepLot);
  }
  
   bool time_check( string timeList){
       //разделим строку на подстроки (разделитель , )
       ushort usep1= StringGetCharacter ( "," , 0 );
       ushort usep2= StringGetCharacter ( "-" , 0 );
       ushort usep3= StringGetCharacter ( ":" , 0 );
       string param[],param2[],param3[],param4[];
       long start_hour= 0 ,start_minute= 0 ,start_seconds= 0 ;
       long end_hour= 0 ,end_minute= 0 ,end_seconds= 0 ;
       datetime start_tm= 0 ,end_tm= 0 ,tm[];
       ArrayInitialize (tm, 0 );
       ArraySetAsSeries (tm, true );
       CopyTime ( _Symbol , PERIOD_D1 , 0 , 2 ,tm);
       MqlDateTime dt={ 0 };
       TimeToStruct ( TimeCurrent (),dt);
      
       int c= StringSplit (timeList,usep1,param);
       if (c< 0 ) return ( true ); //диапозон не задан, можно торговать весь день
       for ( int i= 0 ;i<c;i++){
         StringTrimRight (param[i]);
         StringTrimLeft (param[i]);
         
         if ( StringSplit (param[i],usep2,param2)== 2 ){
             StringTrimRight (param2[ 0 ]);
             StringTrimLeft (param2[ 0 ]);
             StringTrimRight (param2[ 1 ]);
             StringTrimLeft (param2[ 1 ]);
             //удалили возможные лишние пробелы, теперь у нас есть время начала и окончания
             //разделим на чч.мм.сс
             if ( StringSplit (param2[ 0 ],usep3,param3)>= 1 ){
             //время начала
               start_hour= StringToInteger (param3[ 0 ]);
               if ( ArraySize (param3)>= 2 ) start_minute= StringToInteger (param3[ 1 ]);
               if ( ArraySize (param3)== 3 ) start_seconds= StringToInteger (param3[ 2 ]);
            }
             if ( StringSplit (param2[ 1 ],usep3,param4)>= 1 ){
             //время окончания
               end_hour= StringToInteger (param4[ 0 ]);
               if ( ArraySize (param4)>= 2 ) end_minute= StringToInteger (param4[ 1 ]);
               if ( ArraySize (param4)== 3 ) end_seconds= StringToInteger (param4[ 2 ]);
            }
            
             if (start_hour<=end_hour){
               start_tm=( datetime )(tm[ 0 ]+start_hour* 3600 +start_minute* 60 +start_seconds);
               end_tm=( datetime )(tm[ 0 ]+end_hour* 3600 +end_minute* 60 +end_seconds);
            } else {
               if (dt.hour>= 0 && dt.hour<start_hour){
                  start_tm=( datetime )(tm[ 1 ]+start_hour* 3600 +start_minute* 60 +start_seconds);
                  end_tm=( datetime )(tm[ 0 ]+end_hour* 3600 +end_minute* 60 +end_seconds);
               }
               if (dt.hour> 0 && dt.hour>=start_hour){
                  start_tm=( datetime )(tm[ 0 ]+start_hour* 3600 +start_minute* 60 +start_seconds);
                  end_tm=( datetime )(tm[ 0 ]+ 24 * 3600 +end_hour* 3600 +end_minute* 60 +end_seconds);
               }
            }
            
             if ( TimeCurrent ()>=start_tm && TimeCurrent ()<=end_tm)   return ( true );
              
         }
         
      }
      
       return ( false );    
  }
  
   void OnTrade (){
      
       if (semafor> 0 ){
           PrintFormat ( "Открыт ордер %d" ,semafor);
          semafor= 0 ; //сбросим семафор, операция с ордером завершаена, можно открывать следующий ордер
      }    
  }
 
아마도 이것은 버그일듯) MT5를 시작할 때 MT4와 달리 서버에 연결 하지 않고 시작할 때 어떤 이유로 마지막 인증(로그인/비밀번호)이 로드되지 않고 다시 로그인해야 하므로 비밀번호와 로그인 저장되지 않습니다. 무엇이 문제가 될 수 있습니까?
 

여기에 기술이 왔습니다 - 하나의 계정에서 동시에 다른 이익 (일반적으로 쉬는 날, 견적, 진입 가격, 스왑 - 동일, 이익 만 일치하지 않음)

유일한 차이점은 첫 번째 사진에서 터미널이 투자 비밀번호로 로그인되어 있고 최적화 프로세스가 실행되고 있다는 것입니다. 두 번째 사진에서 - 거래 비밀번호를 통해 로그인하십시오. 그리고 터미널을 다시 시작하고 업데이트한 후에도 모든 것이 동일하게 유지되었습니다. 따옴표가 갔을 때 모든 것이 정상으로 돌아온 것 같았습니다.

 
notused :

이것은 기술이 온 것입니다 - 동일한 계정에서 동시에 다른 이익 (일반적으로 쉬는 날, 견적, 진입 가격, 스왑 - 동일하지만 이익 만 일치하지 않음)

유일한 차이점은 첫 번째 사진에서 터미널이 투자 비밀번호로 로그인되어 있고 최적화 프로세스가 실행되고 있다는 것입니다. 두 번째 사진에서 - 거래 비밀번호를 통해 로그인하십시오. 그리고 터미널을 다시 시작하고 업데이트한 후에도 모든 것이 동일하게 유지되었습니다. 따옴표가 갔을 때 모든 것이 정상으로 돌아온 것 같았습니다.

분명히 변동 이익 을 계산 하기 위해 터미널에서 사용할 수있는 교차 요금 값이 다릅니다.
 
Rosh :
분명히 변동 이익 을 계산 하기 위해 터미널에서 사용할 수있는 교차 요금 값이 다릅니다.
그것은 나에게 한 번 일어났고 다시는 일어나지 않을 것입니다. 즉, 전혀 중요하지 않습니다. 그래서 서비스 데스크에 편지를 쓰지 않았습니다. 손익 계산 절차는 이상적이지 않습니다(예: 교차 비율이 다른 이유는 무엇입니까?)
Документация по MQL5: Торговые функции / OrderCalcProfit
Документация по MQL5: Торговые функции / OrderCalcProfit
  • www.mql5.com
Торговые функции / OrderCalcProfit - Документация по MQL5
 

2분마다 이러한 "세트" 오류가 거래 신호에 의해 전송됩니다. 어떻게 고치는 지?

 
또는 거래 신호의 오류에 대해 어디에서 확인할 수 있습니까?
 
kharti : 또는 거래 신호의 오류에 대해 어디에서 확인할 수 있습니까?
ServiceDesk로(귀하의 프로필에 있음)
 
antt :

다른 입력 매개변수를 전달합니다. 기호, 기간, 입력 매개변수가 동일하고 표시기가 동일합니다. 터미널은 리소스 소비를 최소화하려고 시도하며 이 경우 표시기의 새 복사본이 생성되지 않습니다. 하나의 mql5 프로그램이 실제로 작동합니다.

리소스 소비 최적화에 대해 이해하고 기억하지만 기호, 마침표, 입력 매개변수와 함께 표시기의 짧은 이름 도 확인할 수 있습니까? 프로그래머 가 고유한 짧은 이름을 명시적으로 설정하면 자신이 하는 일을 이해하고 그러한 지표가 이미 차트에 있더라도 별도의 사본이 필요합니다. 예를 들어, 입력 데이터가 전혀 없는 지표는 초기 단계에서 모든 초기 데이터를 자동으로 계산하지만 사용자가 가짜 매개변수를 입력하도록 강제하고 다른 매개변수에 입력하지 않도록 기억해야 합니다.