오류 #130 유효하지 않은 손절매에 대한 도움이 필요합니다. - 페이지 4

 
랩터를 찾아주셔서 감사합니다.
MODE_TICKSIZE(0.25) 대신 MODE_TICKVALUE(12.50)를 사용하여 DoubleRound 함수 를 호출했습니다.

고쳤지만 #130이 사라지지 않았습니다.

   if ( long )
      SL = MarketInfo ( Symbol (), MODE_BID) - (stoploss * MarketInfo ( Symbol (), MODE_POINT));
   else
      SL = MarketInfo ( Symbol (), MODE_ASK) + (stoploss * MarketInfo ( Symbol (), MODE_POINT));
   Log( "SL: " + SL);   
   //round to nearest Tickvalue   
   SL = DoubleRound(SL, MarketInfo ( Symbol (), MODE_TICKSIZE));
   Log( "SL rounded: " + SL);

업데이트된 DoubleRound 라인의 오류 로그는 다음과 같습니다.

 #ESZ1,M5: loaded successfully 
#ESZ1,M5: Date: 2011/11/16 21:54
#ESZ1,M5: Symbol: #ESZ1
#ESZ1,M5: Depot: 56127.45000000
#ESZ1,M5: Stop Level [Points]: 75.00000000
#ESZ1,M5: Freeze Level [Points]: 0.00000000
#ESZ1,M5: Spread [Points]: 25.00000000
#ESZ1,M5: Min/Max Lot: 0.01000000/1000.00000000
#ESZ1,M5: Point: 0.01000000
#ESZ1,M5: Tick Size: 0.25000000
#ESZ1,M5: Tick Value: 12.50000000
#ESZ1,M5: Digits: 2.00000000
#ESZ1,M5: Contract: 2011.09.14 00:00-2011.12.16 23:59
#ESZ1,M5: Expert ID: 35698390 
#ESZ1,M5: Init successfully completed.
#ESZ1,M5: initialized

#ESZ1,M5: Opening Position: Short
#ESZ1,M5: pos size: 1.00000000
#ESZ1,M5: Ask/Bid 1251.00000000/1250.75000000
#ESZ1,M5: Spread 0.25000000
#ESZ1,M5: open #13719226 sell 1.00 #ESZ1 at 1250.75 ok
#ESZ1,M5: Order 13719226 Successfully Opened
#ESZ1,M5: Stoplevel: 75.00000000
#ESZ1,M5: Freezelevel: 0.00000000
#ESZ1,M5: stoploss: 100.00000000
#ESZ1,M5: SL: 1252.00000000
#ESZ1,M5: SL rounded: 1252.00000000
#ESZ1,M5: error=130

비교를 위해 다음은 작동한 로그입니다.

 #ESZ1,M5: Opening Position: Long
#ESZ1,M5: pos size: 1.00000000
#ESZ1,M5: Ask/Bid 1249.25000000/1249.00000000
#ESZ1,M5: Spread 0.25000000
#ESZ1,M5: open #13719321 buy 1.00 #ESZ1 at 1249.25 ok 
#ESZ1,M5: Order 13719321 Successfully Opened 
#ESZ1,M5: Stoplevel: 75.00000000
#ESZ1,M5: Freezelevel: 0.00000000
#ESZ1,M5: stoploss: 100.00000000
#ESZ1,M5: SL: 1248.00000000
#ESZ1,M5: SL rounded: 1248.00000000
#ESZ1,M5: modify #13719321 buy 1.00 #ESZ1 at 1249.25 sl: 1248.00 tp: 0.00 ok 
#ESZ1,M5: Stoploss successfully set

어쨌든 이제는 더 자주 작동하는 것 같고 확실히 가까워지고 있습니다. :)
 
shinobi :

어쨌든 이제는 더 자주 작동하는 것 같고 확실히 가까워지고 있습니다. :)

수정이 실패한 이유를 알 수 없습니다. . . OrderSend와 OrderModify 사이에 새로운 Bid/Ask를 받고 있습니까?

내가 지금 제안할 수 있는 것은 오류가 발생했을 때 130 이라는 것입니다. . . 모든 것을 새로 인쇄, Bid, Ask(MarketInfo 사용), OOP, StopLevel, 설정하려는 SL 등

 
shinobi :
MODE_TICKSIZE(0.25) 대신 MODE_TICKVALUE(12.50)를 사용하여 DoubleRound 함수를 호출했습니다.
눈금 값이 확실히 틀립니다. 대신 ticksize를 사용해 보세요.
 double DoubleRound( double number, double step){
   return ( MathRound (number/step)*step );
}
 
친애하는 랩터, WHRoeder 및 SDC,

#130 stoploss 오류는 더 이상 나타나지 않습니다. 마지막 단계가 마침내 문제를 파악한 것처럼 보였습니다.
이 후에 취한 모든 단계를 요약하여 다른 게시물을 게시하겠습니다. 따라서 오류 #130과 싸우는 포럼의 다른 사람들은 이 스레드를 참조로 사용할 수 있습니다.


지속적인 도움에 감사드립니다 :).

시노비
 
shinobi :

지속적인 도움에 감사드립니다 :).

시노비
그것 을 고수 하기 위해 잘 했어 . . 항상 설명이 있지만 때로는 찾기가 까다로울 수 있습니다.
 
오류 #130: 유효하지 않은 손절매의 가능한 원인에 대한 참조.
  1. 일반 팁
  2. ECN 브로커
  3. 4/5자리 브로커
  4. 시장 환율 변경
  5. 확산
  6. 정지 레벨
  7. 동결 수준
  8. 틱사이즈
  9. 완전한 예
  10. 감사의 말
  1. 일반 팁
    오류 방지를 위한 가장 중요한 기술은 과도한 로깅입니다. 원격으로 오류에 연결할 수 있는 모든 항목을 출력합니다. 켜고 끌 수 있는 로그 기능을 정의하면 문제를 해결한 후에도 코드를 유지할 수 있습니다.
    전문 고문을 초기화할 때 MarketInfo에서 알려줄 수 있는 모든 정보를 기록해야 합니다. https://docs.mql4.com/constants/marketinfo
    또한 항상 함수의 반환 값을 확인하십시오(예: OrderModify의 경우):
     if (! OrderSelect (ticket, SELECT_BY_TICKET)) {
           int error_code = GetLastError ();
           Print ( "Error: " + ErrorDescription(error_code));
           return (- 1 );
    }  


  2. ECN 브로커
    ECN 브로커는 매수/매도 및 손절매/이익 실현에 대해 별도의 주문을 해야 합니다. 따라서 다음과 같이 코드를 두 가지 순서로 분할해야 합니다.
     int ticket = OrderSend ( Symbol (), OP_BUY, 1 , MarketInfo ( Symbol (), MODE_ASK), 2 , 0 , 0 , "" , 12345 );
    OrderSelect (ticket, SELECT_BY_TICKET);
    entry_price = OrderOpenPrice ();
    OrderModify (ticket, entry_price, stoploss, takeprofit, 0 );
    
    판매 주문의 경우 OP_BUY를 OP_SELL로 바꿔야 합니다. 또한 OrderSelect 및 OrderModify의 반환 값을 확인해야 합니다(위의 일반 팁 참조).

  3. 4/5자리 브로커
    일부 중개인은 손절매, 이익 실현 및 슬리피지를 4/5 자리로 조정하도록 요구합니다. init() 함수(thx WHRoeder)에 다음 코드를 넣으면 됩니다.
     int      pips2points;     // slippage  3 pips    3=points    30=points
    double   pips2dbl;       // Stoploss 15 pips    0.0015      0.00150
    int      Digits .pips;     // DoubleToStr(dbl/pips2dbl, Digits.pips)
    
    //init digit adjustment
    if ( Digits % 2 == 1 ) {       // DE30=1/JPY=3/EURUSD=5 forum.mql4.com/43064#515262
        pips2dbl    = Point * 10 ; pips2points = 10 ;   Digits .pips = 1 ;
    } else {
        pips2dbl    = Point ;    pips2points =   1 ;   Digits .pips = 0 ; 
    }
    그런 다음 브로커에게 보내기 전에 pips2db1로 손절매, 이익실현 및 슬리피지를 곱해야 합니다.
     OrderModify ( ticket , entry_price, stoploss * pips2points, takeprofit * pips2points, 0);

  4. 시장 환율 변경
    또 다른 가능한 원인은 틱이 Expert Advisor(EA)를 활성화하고 EA OrderSend() 또는 OrderModify()가 실행된 사이에 시장 환율이 변경되었기 때문입니다. 이 문제를 방지하기 위해 두 가지 가능한 솔루션이 있습니다.
    첫 번째는 Ask 및 Bid와 같은 사전 정의된 시장 변수를 사용하기 전에 RefreshRates()를 사용하는 것입니다. (이 변수는 틱이 EA를 활성화할 때 값을 얻습니다)
    두 번째는 미리 정의된 시장 변수를 전혀 사용하지 않는 것입니다. 대신 MarketInfo()를 사용하여 현재 시장 가치를 사용할 수 있습니다. Ask 대신 Bid 및 Point 사용
     MarketInfo ( Symbol (), MODE_ASK)
    MarketInfo ( Symbol (), MODE_BID)
    MarketInfo ( Symbol (), MODE_POINT)
    

  5. 확산
    손절매 또는 이익실현이 진입 가격에 너무 가까우면 주문이 거부됩니다. 이 문제를 피하려면 Ask와 Bid 사이의 현재 스프레드를 고려해야 합니다. 다시 두 가지 솔루션이 있습니다.
    첫 번째는 스프레드를 계산하고 손절매/이익 실현에 더하거나 빼는 것입니다.
     double spread = MarketInfo ( Symbol (), MODE_ASK) - MarketInfo ( Symbol (), MODE_BID);
    //buy
    stoploss = stoploss - spread;
    takeprofit = takeprofit + spread;
    //sell
    stoploss = stoploss + spread;
    takeprofit = takeprofit - spread;
    손절매 또는 이익실현을 계산할 때 Ask 및 Bid를 사용하여 스프레드를 암시적으로 고려하는 두 번째 솔루션:
     stoploss = 50
    takeprofit = 50
    //buy
    SL = MarketInfo ( Symbol (), MODE_BID) - (stoploss * MarketInfo(Symbol(), MODE_POINT))
    TP = MarketInfo ( Symbol (), MODE_ASK) + (takeprofit * MarketInfo(Symbol(), MODE_POINT))
    //sell
    SL = MarketInfo ( Symbol (), MODE_ASK) + (stoploss * MarketInfo(Symbol(), MODE_POINT))
    TP = MarketInfo ( Symbol (), MODE_BID) -  (takeprofit * MarketInfo(Symbol(), MODE_POINT))

  6. 정지 레벨
    브로커는 특정 정지 수준이 있습니다. 손절매가 해당 수준보다 낮으면 주문이 거부됩니다. MarketInfo(Symbol(), MODE_STOPLEVEL)로 스톱 레벨을 확인할 수 있습니다.
    이를 방지하려면 브로커의 정지 수준에 대해 손절매를 확인하고 필요한 경우 조정하십시오.
     double stoplevel = MarketInfo ( Symbol (), MODE_STOPLEVEL);
    if (stoploss < stoplevel)
       stoploss = stoplevel + 1 ;

  7. 동결 수준
    동결 수준도 비슷한 개념입니다. 손절매는 또한 브로커의 동결 수준보다 커야 합니다. MarketInfo(Symbol(), MODE_FREEZELEVEL)로 동결 수준을 확인할 수 있습니다.
    이를 방지하려면 브로커의 동결 수준에 대해 손절매를 다시 확인하십시오.
     double freezelevel = MarketInfo ( Symbol (), MODE_FREEZELEVEL);
    if (stoploss < freezelevel)
       stoploss = freezelevel + 1 ;

  8. 틱사이즈
    마지막으로 귀하의 손절매 또는 이익실현은 거부될 수 있습니다. 왜냐하면 Symbol은 틱 크기와 일치하는 손절매/이익실현만 지원하기 때문입니다. ticksize는 심볼의 상품이 위아래로 움직일 수 있는 최소 거리입니다. 예를 들어 가격이 1000이고 ticksize가 0.25이면 가격은 0.25의 배수(0.25 * n, 여기서 n은 자연수)만큼만 오르거나 내릴 수 있습니다. 따라서 가격은 0.25에서 1000.25로 올라가거나 1.75에서 998.25로 내려갈 수 있습니다.
    ticksize를 설명하려면 double 값을 특정 단계 값(예: 가장 가까운 0.25)으로 반올림하는 함수가 필요합니다. 다음은 그러한 기능입니다.
     double DoubleRound( double number, double step)
    {
         double mod = MathMod (number, step);
         if (mod < step/ 2.0 )
          step = 0 ;
         double rounded = number - mod + step;
         return (rounded);
    }
    예를 들어 숫자 = 1023.81234이고 단계 = 0.25인 DoubleRound를 호출하면 1023.75가 반환됩니다. 1023.967834로 호출하면 1024.00이 반환됩니다.
    이제 손절매나 이익실현을 보내기 전에 다음을 사용하여 기호의 눈금 크기로 반올림하십시오.
    stoploss = (stoploss, MarketInfo ( Symbol (), MODE_TICKSIZE));
    takeprofit = (takeprofit, MarketInfo ( Symbol (), MODE_TICKSIZE));

  9. 완전한 예
    다음은 위의 모든 대응 조치를 고려한 완전한 작은 예입니다.
     int init()
    {
         //for 4/5 Digits-Broker adjustment
         int      pips2points;     // slippage  3 pips    3=points    30=points
         double   pips2dbl;       // Stoploss 15 pips    0.0015      0.00150
         int      Digits .pips;     // DoubleToStr(dbl/pips2dbl, Digits.pips)
    
       //init digit adjustment
       if ( Digits % 2 == 1 ) {       // DE30=1/JPY=3/EURUSD=5 forum.mql4.com/43064#515262
                   pips2dbl    = Point * 10 ; pips2points = 10 ;   Digits .pips = 1 ;
       } else {
                   pips2dbl    = Point ;    pips2points =   1 ;   Digits .pips = 0 ; 
       }
    
       Print ( "Date: " + Year () + "/" + Month () + "/" + Day() + " " + Hour () + ":" + Minute ());
       Print ( "Symbol: " + Symbol ());
       Print ( "Depot: " + AccountBalance ());
       Print ( "Stop Level [Points]: " + MarketInfo ( Symbol (), MODE_STOPLEVEL));
       Print ( "Freeze Level [Points]: " + MarketInfo ( Symbol (), MODE_FREEZELEVEL));
       Print ( "Spread [Points]: " + MarketInfo ( Symbol (), MODE_SPREAD));
       Print ( "Min/Max Lot: " + MarketInfo ( Symbol (), MODE_MINLOT) + "/" + MarketInfo ( Symbol (), MODE_MAXLOT));
       Print ( "Point: " + MarketInfo ( Symbol (), MODE_POINT));
       Print ( "Tick Size: " + MarketInfo ( Symbol (), MODE_TICKSIZE));
       Print ( "Tick Value: " + MarketInfo ( Symbol (), MODE_TICKVALUE));
       Print ( "Digits: " + MarketInfo ( Symbol (), MODE_DIGITS));
       Print ( "Contract: " + TimeToStr ( MarketInfo ( Symbol (), MODE_STARTING)) + "-" + TimeToStr ( MarketInfo ( Symbol (), MODE_EXPIRATION)));
    }
    
    //long = true: buy; long = false: sell
    int take_position( bool long )
    {
       int stoploss = 50 ;
       double SL = 0.0 ;
       int ticket = - 1 ;
       
       //send order
       if ( long )   //buy
          ticket = OrderSend ( Symbol (), OP_BUY, 1 , MarketInfo ( Symbol (), MODE_ASK), 2 , 0 , 0 , "" , 1234 );  
       else        //sell
          ticket = OrderSend ( Symbol (), OP_SELL, 1 , MarketInfo ( Symbol (), MODE_BID), 2 , 0 , 0 , "" , 1234 ); 
    
       //check for errors
       if (result_ticket == - 1 ) {
           int error_code = GetLastError ();
           Print ( "Error: " + ErrorDescription(error_code));
           return (- 1 );
       }
       Print ( "order " +ticket+ " successfully opened" );
    
       //select order
       if (! OrderSelect (result_ticket, SELECT_BY_TICKET)) {
           int error_code = GetLastError ();
           Print ( "Error: " + ErrorDescription(error_code));
           return (- 1 );
       }    
       double entry_price = OrderOpenPrice ();
       
       //check stoplevel
       double stoplevel = MarketInfo ( Symbol (), MODE_STOPLEVEL);
       Print( "Stoplevel: " + stoplevel);
       if (stoploss < stoplevel)
          stoploss = stoplevel + 1 ;
    
       //check freezelevel
       double freezelevel = MarketInfo ( Symbol (), MODE_FREEZELEVEL);
       Print( "Freezelevel: " + freezelevel);
       if (stoploss < freezelevel)
          stoploss = freezelevel + 1 ;
    
       Print( "adjusted stoploss: " + stoploss);
       
       //account for spread AND account for 4/5-Digit Brokers
       if ( long )
          SL = MarketInfo ( Symbol (), MODE_BID) - (stoploss * pips2dbl);
       else
          SL = MarketInfo ( Symbol (), MODE_ASK) + (stoploss * pips2dbl);
       Print( "SL: " + SL);
       
       //round to nearest Tickvalue   
       SL = DoubleRound(SL, MarketInfo ( Symbol (), MODE_TICKSIZE));
       Print( "SL rounded: " + SL);
       
       //set stoploss
       if (! OrderModify (result_ticket, entry_price, SL, 0 , Red )) {
           int error_code = GetLastError ();
           Print ( "Error: " + ErrorDescription(error_code));
           return (- 1 );
       }
    
       Print( "Stoploss successfully set" );
       return ( 0 );
    }
    #130을 제거하는 데 도움이 되길 바랍니다. 코드 수정이 작동하지 않으면 먼저 위와 같은 최소한의 예제를 사용하십시오. 그런 다음 오류가 사라지면 변경된 내용이 코드에 적용됩니다.

    행운을 빕니다,
    시노비

  10. 감사의 말
    오류를 제거하고 이 참조를 통합하는 데 도움을 준 Raptor, WHRoeder, SDC, BigAl, gjol 및 35806에 감사드립니다.