mql4에서 OnTradeTransaction()을 대체하는 방법은 무엇입니까? - 페이지 8

 
Vitaly Muzichenko :

그게 다야, 해결책은 간단하다: 우리는 히스토리를 변경하기 위해 한 번 더 검사를 도입한다. 그래서 아무 것도 잃지 않고 100% 작동할 것이다.

열등한 OnTrade()로도 사용할 수 있습니다.

 void OnTrade()
 {
  ...
 }

static __OTotal = - 1 ;
static __HTotal = - 1 ;
int OT= OrdersTotal ();
int HT=OrdersHistoryTotal();
   if (OT!=__OTotal || HT!=__HTotal) // если изменилось - выполняем
   {
     OnTrade(); // здесь дёргаем текущую ситуацию на счёте и заполняем структуры
     __OTotal= OrdersTotal (); // запомним текущее количество
     __HTotal=OrdersHistoryTotal(); // запомним количество в истории
   }
 
Vitaly Muzichenko :

마음이 약한 것 같다)

그것을 적용하는 방법?

딱 한가지 문제가 있고 극히 드문 경우인데 몇 년 만에 처음 발견했는데 그 이전이었을 수도 있고 그냥 눈치채지 못한 것일 뿐


기호 이름을 구성하는 문자 코드 값을 계산하기 위해 해시 합계 계산(해시 합계의 ulong 값에 기호 이름을 추가하는 방법)에 대해 이야기했습니다.

 
Vitaly Muzichenko :

그게 다야, 해결책은 간단하다: 우리는 히스토리를 변경하기 위해 한 번 더 검사를 도입한다. 그래서 아무 것도 잃지 않고 100% 작동할 것이다.

다음은 내 기사 #3에서 발췌한 내용입니다.

-------

구조의 해시 합계를 자세히 살펴보겠습니다.
계정에서 발생한 변경 사항을 정확하게 파악하기 위해서는 주문 및 포지션의 수를 아는 것만으로는 충분하지 않습니다. 보류 중인 주문을 삭제할 수 있으며, 이 경우 계정의 총 주문 및 위치가 변경됩니다. 하지만... 보류 중인 주문이 작동하여 직위가 될 수 있습니다. 이 경우 주문 및 포지션의 총액은 변경되지 않습니다(헤지 계정 및 MQL4의 경우) − 포지션 수는 늘었지만 주문 수는 줄어들어 전체 수는 그대로였다. 그것은 우리에게 적합하지 않습니다.

티켓을 고려하십시오. 보류 중인 주문을 추가/제거해도 계정의 총 티켓 금액이 변경되며, 보류 중인 주문을 실행해도 계정의 총 티켓 금액은 변경되지 않습니다.

총 부피를 고려하십시오. 보류 중인 주문을 제출하거나 삭제했습니다. 계정의 총 거래량이 변경, 개설, 마감 또는 변경되었습니다. — 계정의 총액이 변경되었습니다. 맞는 것 같지만 보류 중인 주문을 다시 활성화해도 총 볼륨은 변경되지 않습니다.

그래서 우리는 위치의 속성을 하나 더 봅니다. 변경 시간(밀리초): 새 위치를 열면 전체 위치 변경 시간이 변경되고, 부분 청산하면 위치 변경 시간이 변경되며, 상계 계정에 볼륨을 추가하면 총 위치 변경 시간이 변경됩니다.

이 모든 것 중 계정에서 발생한 변경 사항을 명확하게 결정하는 데 적합한 것은 무엇입니까? 티켓 + 포지션 변경 시간. 점검 해보자:

  • 열린 포지션 - 변경된 티켓 금액 + 포지션 변경 시간 금액 변경 변화가 있다
  • 포지션을 닫았다 변경된 티켓 금액 + 포지션 변경 시간 금액 변경 변화가 있다
  • 보류 중인 주문을 했습니다 티켓 금액 이 변경됨 + 포지션 변경 시간 금액이 변경 되지 않음 변화가 있다
  • 삭제된 보류 중인 주문 - 티켓 금액 이 변경되었습니다 + 포지션 변경 시간 이 변경되지 않은 금액 - 변경이 있습니다
  • 보류 중인 주문 활성화됨 — 티켓 금액이 변경되지 않은 경우 + 포지션 변경 시간 이 변경된 금액 — 변화가 있다
  • 포지션의 부분 청산 — 변경된 티켓 금액 + 포지션 변경 시간 금액 변경 변화가 있다
  • 위치에 볼륨 추가 — 티켓 금액이 변경되지 않은 경우 + 포지션 변경 시간 이 변경된 금액 — 변화가 있다
따라서 해시 합계의 경우 티켓 + 위치 변경 시간(밀리초)을 사용합니다.

그러나 여기서는 해시 합계에 기호를 추가하지 않았습니다. 이에 대한 전례는 없습니다. 그러나 그것은 기록 확인과 함께 저에게 효과적입니다. 따라서 - 오류 없이 이행해야 합니다. 그러나 어쨌든 확인하겠습니다.

Библиотека для простого и быстрого создания программ для MetaTrader (Часть III): Коллекция рыночных ордеров и позиций, поиск и фильтрация
Библиотека для простого и быстрого создания программ для MetaTrader (Часть III): Коллекция рыночных ордеров и позиций, поиск и фильтрация
  • www.mql5.com
В первой части данного цикла статей мы начали создавать большую кроссплатформенную библиотеку, целью которой является облегчение создания программ для платформы MetaTrader 5 и MetaTrader 4. Во второй части продолжили развитие библиотеки и сделали коллекцию исторических ордеров и сделок. В данной части повествования создадим класс для удобного...
 
Vitaly Muzichenko :

그게 다야, 해결책은 간단하다: 우리는 히스토리를 변경하기 위해 한 번 더 검사를 도입한다. 그래서 아무 것도 잃지 않고 100% 작동할 것이다.

그리고 예. 열린 주문의 수가 변경되지 않으면 내역의 수가 변경됩니다. (나는 지연에 대해 신경 쓰지 않습니다 - 나는 그것들을 사용하지 않습니다) 그리고 당신은 단 하나의 이벤트를 잡기 위해 하루 종일 영장을 분류하는 할머니 를 얽매일 필요가 없습니다.

그리고 SMS가 사용자의 머리에 와서 지난 달의 전체 기록 대신 터미널에 기록을 반영하기로 결정한 경우 모든 주문을 열거하여 추가 확인이 간단하게 수행되며 치명적이지는 않습니다. , 한 번이 아닙니다.

좋은 솔루션인 것 같습니다. 그리고 무엇에도 얽매이지 않고 있는 그대로 사용하며, 거래 계좌와 단말기가 있습니다.

 
Artyom Trishkin :

다음은 내 기사 #3에서 발췌한 내용입니다.

-------

구조의 해시 합계를 자세히 살펴보겠습니다.
계정에서 발생한 변경 사항을 정확하게 파악하기 위해서는 주문 및 포지션의 수를 아는 것만으로는 충분하지 않습니다. 보류 중인 주문을 삭제할 수 있으며, 이 경우 계정의 총 주문 및 위치가 변경됩니다. 하지만... 보류 중인 주문이 작동하여 직위가 될 수 있습니다. 이 경우 주문 및 포지션의 총액은 변경되지 않습니다(헤지 계정 및 MQL4의 경우) − 포지션 수는 늘었지만 주문 수는 줄어들어 전체 수는 그대로였다. 그것은 우리에게 적합하지 않습니다.

티켓을 고려하십시오. 보류 중인 주문을 추가/제거해도 계정의 총 티켓 금액이 변경되며, 보류 중인 주문을 실행해도 계정의 총 티켓 금액은 변경되지 않습니다.

총 부피를 고려하십시오. 보류 중인 주문을 제출하거나 삭제했습니다. 계정의 총 거래량이 변경, 개설, 마감 또는 변경되었습니다. — 계정의 총액이 변경되었습니다. 맞는 것 같지만 보류 중인 주문을 다시 활성화해도 총 볼륨은 변경되지 않습니다.

그래서 우리는 위치의 속성을 하나 더 봅니다. 변경 시간(밀리초): 새 위치를 열면 전체 위치 변경 시간이 변경되고, 부분 청산하면 위치 변경 시간이 변경되며, 상계 계정에 볼륨을 추가하면 총 위치 변경 시간이 변경됩니다.

이 모든 것 중 계정에서 발생한 변경 사항을 명확하게 결정하는 데 적합한 것은 무엇입니까? 티켓 + 포지션 변경 시간. 점검 해보자:

  • 열린 포지션 - 변경된 티켓 금액 + 포지션 변경 시간 금액 변경 변화가 있다
  • 포지션을 닫았다 변경된 티켓 금액 + 포지션 변경 시간 금액 변경 변화가 있다
  • 보류 중인 주문을 했습니다 티켓 금액 이 변경됨 + 포지션 변경 시간 금액이 변경 되지 않음 변화가 있다
  • 삭제된 보류 중인 주문 - 티켓 금액 이 변경되었습니다 + 포지션 변경 시간 이 변경되지 않은 금액 - 변경이 있습니다
  • 보류 중인 주문 활성화됨 — 티켓 금액이 변경되지 않은 경우 + 포지션 변경 시간 이 변경된 금액 — 변화가 있다
  • 포지션의 부분 청산 — 변경된 티켓 금액 + 포지션 변경 시간 금액 변경 변화가 있다
  • 위치에 볼륨 추가 — 티켓 금액이 변경되지 않은 경우 + 포지션 변경 시간 이 변경된 금액 — 변화가 있다
따라서 해시 합계의 경우 티켓 + 위치 변경 시간(밀리초)을 사용합니다.

그러나 여기서는 해시 합계에 기호를 추가하지 않았습니다. 이에 대한 전례는 없습니다. 그러나 그것은 기록 확인과 함께 저에게 효과적입니다. 따라서 - 오류 없이 이행해야 합니다. 그러나 어쨌든 확인하겠습니다.

그런 선택이 필요하지 않은 반면 뚱뚱한 결정입니다.

고맙습니다!

 
Vitaly Muzichenko :

그런 선택이 필요하지 않은 반면 뚱뚱한 결정입니다.

고맙습니다!

"굵게" 표시된 것은 로컬 솔루션이 아니라 OnTradeXXXX에 대한 본격적인 교체의 일부로 수행되었기 때문입니다. 구성에는 역사와 관련된 작업도 있습니다.

그리고 필요에 따라 프로그램의 모든 주문 및 위치를 검색하고 정렬하기 위한 기성품 데이터(프로그램의 요구에 따라 주문 및 위치를 다시 검색할 필요가 없음 - 모든 것이 이미 목록에 있음) 그리고 한 가지 더 - 프로그램은 위에서 언급한 옵션에서 수행할 수 없는 MQL4에서 위치가 생성된 순서를 알고 있습니다.

그러나 반복합니다. 도서관은 매우 길고 값비싼 시간 동안 스스로 모든 것을 하는 사람들의 삶을 더 쉽게 만들기 위해 만들어지고 있습니다. 물론 나는 아무 것도 주장하지 않습니다. :)

 
Aleksandr Volotko :

그리고 예. 열린 주문의 수가 변경되지 않으면 내역의 수가 변경됩니다. ( 나는 지연에 대해 신경 쓰지 않습니다 - 나는 그것들을 사용하지 않습니다 ) 그리고 당신은 단 하나의 이벤트를 잡기 위해 하루 종일 영장을 분류하는 할머니를 뒤죽박죽 할 필요가 없습니다.

그리고 SMS가 사용자의 마음에 와서 지난 달 전체가 아닌 터미널에 기록을 반영하기로 결정했다면 모든 주문을 검색하여 추가 확인이 간단하게 수행되며 이는 치명적이지 않습니다. , 한 번이 아닙니다.

좋은 솔루션인 것 같습니다. 그리고 무엇에도 얽매이지 않고 있는 그대로 사용하며, 거래 계좌와 단말기가 있습니다.

하루 종일 진행하지 않으려면 포지션 변경, 오픈, 클로징, 즉 포지션 변경으로 이어질 수 있는 조건이 충족될 때만 체크를 할 수 있습니다. 전문가가 TP, SL을 여는 데 사용하는 가격을 달성하는 데 중점을 둡니다. 글쎄요, 그것은 전문가의 논리에 달려 있습니다. 당신이 거기에서 더 싼 것이 무엇인지 더 잘 압니다.

 
Aleksey Mavrin :

하루 종일 진행하지 않으려면 포지션 변경, 오픈, 클로징, 즉 포지션 변경으로 이어질 수 있는 조건이 충족될 때만 체크를 할 수 있습니다. 전문가가 TP, SL을 여는 데 사용하는 가격을 달성하는 데 중점을 둡니다. 글쎄요, 그것은 전문가의 논리에 달려 있습니다. 당신이 거기에서 더 싼 것이 무엇인지 더 잘 압니다.

한 명의 고문(한 대의 컴퓨터, 한 대륙)이 거래합니다. 다른 컴퓨터(다른 컴퓨터에서, 다른 대륙에서)가 자체 작업을 수행하고 있습니다. 해결책은 이미 찾았습니다.

 
fxsaber :

(거래 내역 폴링 없이) 재현 가능한 몇 가지 예를 제공해 주시면 감사하겠습니다.

다음은 일어난 일입니다(여기서는 주제가 아니지만 여기에서 질문함).

산 채로 베었다. MT4 호환성 없음(물론), 오류 처리 등이 없습니다.

거래는 원시적이며 BUY를 열고 SL/TP로 마감합니다. 유일한 요점은 OnTradeTransaction() 과 "서버 폴링"을 비교하는 것입니다.

지정된 간격 동안 2.34초 대 3.06초가 걸렸습니다. 서버 기능에 대한 부하가 적기 때문에 그 차이는 작습니다(단 하나의 위치, 매직 및 기호 검사 없음). 실제 Expert Advisor에서는 그 차이가 훨씬 더 클 것입니다. 신호 계산 및 후행 추가로 인해 차이가 약간 평준화되지만 매 틱마다 수행할 필요는 없습니다. M1에서 ATR을 계산했지만 6시간 동안입니다(즉, TF 업스케일링을 위한 여지가 있음). 그리고 후행 및 손익분기점은 H3에서 계산됩니다. 그것은 모두 전략에 달려 있습니다.

 // Test OnTradeTransaction.mqh
#property version    "1.00"
#property copyright "(c)2020 Edgar Akhmadeev"
#property link        "https://www.mql5.com/en/users/dali"
// 2020.01.27

//      Primitive expert to test OnTradeTransaction().
//      BUY only one position a time. There's no any signals.
//      Try OHLC M1 EURUSD 2016.12.19-2018.04.14 (bull trend) with default SL/TP.



//#define TESTER



#define MT4_TICKET_TYPE
#include <MT4Orders.mqh>
#include <mql4_to_mql5.mqh>



struct PosInfoBase {
         double                   price, sl, tp;
         datetime                 time;
         int                      ticket;
         ENUM_ORDER_TYPE 	type;

         #ifndef TESTER
                 int              mn;
                 string           sym;
         #endif 
};

struct PosInfo {
        PosInfoBase             base;
         int                      ticket;
};



input int        SL              = 6 ;
input int        TP              = 900 ;



MqlTick          tick;
PosInfo         posInfo         = { 0 };



#ifdef TESTER

//*************************************************************************************************************
void 
OnTradeTransaction ( const MqlTradeTransaction & trans, const MqlTradeRequest & request, const MqlTradeResult & result) {
         if (trans.type == TRADE_TRANSACTION_ORDER_DELETE && trans.order_state == ORDER_STATE_PLACED ) {
                 // No money
                 //errFatal = true;
                 return ;
        }
        
         static long lastTick;

         if (trans.type == TRADE_TRANSACTION_DEAL_ADD && trans.order_state == ORDER_STATE_STARTED ) {
                 // Open on market step1, SL/Order triggered step1, SL/Order triggered step4
                
                 if (! HistoryDealSelect (trans.deal)) {
                         //errFatal = true;
                         return ;
                }
                
                 ENUM_DEAL_ENTRY entry = ( ENUM_DEAL_ENTRY ) HistoryDealGetInteger (trans.deal, DEAL_ENTRY );
                 if (entry != DEAL_ENTRY_OUT )
                         return ;
                
                 ENUM_DEAL_REASON reason = ( ENUM_DEAL_REASON ) HistoryDealGetInteger (trans.deal, DEAL_REASON );
                 if (reason != DEAL_REASON_SL && reason != DEAL_REASON_TP )
                         return ;
                
                 if (lastTick == tick.time_msc)
                         return ;

                posInfo.base.ticket = 0 ;
                InitPos();

                lastTick = tick.time_msc;
                 return ;
        }
}



#else // TESTER



//*************************************************************************************************************
bool
Support() {
        posInfo.base.ticket = 0 ;
        
         int cnt = PosTotal();
         if (cnt > 1 )
                 return false ;
        
        PosInfo _posInfo;
        
         if (cnt == 0 )
                _posInfo.base.ticket = 0 ;
         else {
                PosInfoFill(_posInfo);
                _posInfo.ticket = _posInfo.base.ticket;
        }

         //-------------------------------------------------------------------------------------------------------------
         // Position: process
        
         if (_posInfo.base.ticket != 0 && posInfo.ticket != 0 && _posInfo.base.ticket == posInfo.ticket) {
                 // Ничего не произошло, та же позиция
                
                posInfo.base.ticket = _posInfo.base.ticket;
                posInfo.base.time = _posInfo.base.time;
                 //posInfo.base.price = _posInfo.base.price;
                posInfo.base.sl = _posInfo.base.sl;
                posInfo.base.tp = _posInfo.base.tp;
        }

         //-------------------------------------------------------------------------------------------------------------
         // Инициализация новой позиции
        
         if (posInfo.base.ticket > 0 )
                 return true ;
        
         return InitPos();
}

#endif // TESTER



//*************************************************************************************************************
bool
InitPos() {
         if (! SymbolInfoTick ( _Symbol , tick))
                 return false ;
        
        posInfo.base.type = ORDER_TYPE_BUY ;
        posInfo.base.sl = NormalizeDouble (tick.bid - SL * Point , Digits ); 
        posInfo.base.tp = NormalizeDouble (tick.bid + TP * Point , Digits );       

         ResetLastError ();
         int order = OrderSend ( _Symbol , posInfo.base.type, 0.01 , tick.ask, 99 , posInfo.base.sl, posInfo.base.tp); 
         if (order < 0 )
                 return false ;
        
         if (! OrderSelect (order, SELECT_BY_TICKET))
                 return false ;

        posInfo.base.price = OrderOpenPrice();
        posInfo.ticket = posInfo.base.ticket = order;
        posInfo.base.time = tick.time;
         return true ;
}



//*************************************************************************************************************
int
PosTotal() {
         int posTotal = OrdersTotal ();
         int cnt = 0 ;
         for ( int i = posTotal - 1 ; i >= 0 ; --i) {
                 if (! OrderSelect (i, SELECT_BY_POS)) {
                         //errFatal = true;
                         return - 1 ;
                }

                 if (OrderType() > OP_SELL)
                         continue ;

                 /*
                #ifndef TESTER
                        if (OrderMagicNumber() != MagicNum)
                                continue;
                        if (OrderSymbol() != symInfo.sym)
                                continue;
                #endif 
                */
                        
                ++cnt;
        } // for
        
         return cnt;
}


        
//*************************************************************************************************************
void
PosInfoFill(PosInfo& _posInfo) {
         ZeroMemory (_posInfo);

        _posInfo.base.ticket = ( int ) PositionGetInteger ( POSITION_TICKET );
        _posInfo.base.type = ( ENUM_ORDER_TYPE ) PositionGetInteger ( POSITION_TYPE );
        _posInfo.base.price = PositionGetDouble ( POSITION_PRICE_OPEN );
        _posInfo.base.time = ( datetime ) PositionGetInteger ( POSITION_TIME );
        _posInfo.base.sl = PositionGetDouble ( POSITION_SL );
        _posInfo.base.tp = PositionGetDouble ( POSITION_TP );

         #ifndef TESTER
                _posInfo.base.mn = ( int ) PositionGetInteger ( POSITION_MAGIC );
                _posInfo.base.sym = PositionGetString ( POSITION_SYMBOL );
         #endif 
}



//*************************************************************************************************************
void 
OnTick () {
         ResetLastError ();
         if (! SymbolInfoTick ( _Symbol , tick)) {
                 int LE = GetLastError ();
                 //errFatal = true;
                 return ;
        }
        
         #ifdef TESTER

                 if (posInfo.base.ticket > 0 )
                         return ;
                
                 if (!InitPos()) {
                         //errFatal = true;
                         return ;
                }

         #else   // TESTER
                
                 if (!Support()) {
                         //errFatal = true;
                         return ;
                }
        
         #endif // TESTER
}



//*************************************************************************************************************
int 
OnInit () {
         return INIT_SUCCEEDED ;
}



//*************************************************************************************************************
void 
OnDeinit ( const int reason) {
}
 
prostotrader :

당신은 절망적으로 시대에 뒤떨어져 있습니다!

이 이벤트는 오랫동안 보장 됩니다!

OnTradeTransaction() 에서 이벤트가 발생한 후 일부 작업을 수행해야 하지만 이러한 작업을 수행하려는 첫 번째 시도 중에 오류가 발생했다고 가정합니다. 무엇을 할까요? 분명히 다시 시도해야 하며 이를 위해서는 이러한 작업을 반복해야 할 필요성에 대한 데이터를 어딘가에 저장해야 합니다. 대부분 이 데이터를 저장하는 것은 어드바이저의 일반적인 전역 변수 또는 정적 함수에서 수행됩니다. 그리고 갑자기 터미널을 다시 시작해야 했습니다... 데이터가 사라졌습니다.

그리고 현재의 상황과 역사를 분석해 보면 아무 것도 날아가지 않습니다.