주문 열거 주기의 구성 - 페이지 9

 
fxsaber :

변경됨

이제 경고 없이.

대답은 스스로 제안합니다 - 만약 Ticket == PrevTicket ---> return WRONG_VALUE .

함수가 0보다 작은 값을 반환했다면 다시 호출해야 합니다.

 
Artyom Trishkin :

대답은 스스로 제안합니다 - 만약 Ticket == PrevTicket ---> return WRONG_VALUE .

따라서 이것은 문제의 특정 경우에 대한 솔루션입니다. 이를 명확하게 하기 위해 인접 티켓의 평등의 형태로 설명했습니다.

실제로 문제는 여전히 동일합니다. 즉, 주기 동안 인덱싱을 뒤흔드는 것입니다. 이로 인해 일부 티켓을 건너뛰거나 티켓이 한 티켓 이후에 반복되는 등의 상황이 발생할 수 있습니다.

IsChange에 대한 대안을 찾지 못했습니다.

 
fxsaber :

따라서 이것은 문제의 특정 경우에 대한 솔루션이며, 이를 명확성을 위해 인접 티켓의 평등의 형태로 설명했습니다.

실제로 문제는 여전히 동일합니다. 즉, 주기 동안 인덱싱을 뒤흔드는 것입니다. 이로 인해 일부 티켓을 건너뛰거나 티켓이 한 티켓 이후에 반복되는 등의 상황이 발생할 수 있습니다.

IsChange에 대한 대안을 찾지 못했습니다.

타이머에 목록을 만들고 작업합니다.

 
Artyom Trishkin :

타이머에 목록을 만들고 작업합니다.

더 나은 코드.

 
fxsaber :

더 나은 코드.

코드를 보여주는 것은 매우 어렵습니다. 상호 관련된 클래스의 전체 라이브러리가 있습니다.

의미는 이것입니다. 타이머에서 우리는 계정의 모든 주문과 위치를 살펴보고 CArrayObj 목록을 채웁니다. 한 번에 최신 정보를 얻을 수 있도록 지속적으로 업데이트합니다.

포지션 을 청산하거나 주문을 삭제해야 하는 경우, 우리는 이 목록을 가져와서 필요한 주문 개체와 이 목록에서 청산(수정) 기능에 필요한 티켓을 선택합니다. 이 주문 객체가 물리적으로 존재하지 않는 경우(이러한 작업 중에 닫히거나 삭제됨) 목록의 다음 개체로 이동합니다. 이 개체는 이미 닫혀 있고 타이머의 다음 반복에서 목록이 이미 업데이트되기 때문입니다. 가능한 문제에서 가장 먼저 떠오르는 것은 수신된 목록으로 작업을 실행하는 동안 거래 환경이 변경될 때 수신된 목록의 관련성이 없다는 것입니다. 그러나 내가 보기에 목록에 기록된 주문의 물리적 부재는 그다지 성가시지 않아야 합니다. 오류가 발생하고 목록의 다음 항목으로 이동합니다. 이 목록은 거래 환경에서처럼 섞이지 않으며, 건너 뛰는 것은 불가능합니다-주문이 없다는 사실에 대한 진술 만 목록의 해당 항목.

이것이 내가 아직 코드에서 이것을 구현하지 않았기 때문에 지금까지 나에게 보이는 방법입니다. 이제 막 구현에 가까워지고 있지만 처음에는 다른 클래스를 완료해야 합니다(기능 교체에 대한 질문은 기능 분기에서 요청되었습니다). 구현을 시작하면 가능한 문제가 거기에 표시되고 문제를 해결하고 제거하는 방법을 결정할 것입니다.

 
Artyom Trishkin :

대답은 스스로 제안합니다 - 만약 Ticket == PrevTicket ---> return WRONG_VALUE .

함수가 0보다 작은 값을 반환했다면 다시 호출해야 합니다.

아무것도 할 필요가 없습니다. 바보의 표정으로 논리를 훑어보면 충분하다.

1. 6개의 주문이 있습니다.

  • 0 티켓 100
  • 1 티켓 101
  • 2권 102
  • 3권 103
  • 4권 104
  • 5 티켓 105

우리는 수정에 대한 주문을 정렬하기 시작합니다.

5번 티켓 105번 선택, 수정이 필요한지 확인, 수정.

이때 장난꾸러기 손이 2차 티켓(102)을 삭제하고 목록이 변경되었습니다. 이제 티켓 105가 있는 주문은 목록에서 4번째가 되었습니다. 4. 그리고 다시 수정을 위해 선택되었습니다. 하지만 결국 우리는 검증없이 작동하지 않습니다 ... 우리는 수정이 필요한지 확인했습니다. 그러나 !!! 하지마..그래서??? 주문이 재선정된 것에 대해 누가 기분이 나빴습니까?

 
Artyom Trishkin :

코드를 보여주는 것은 매우 어렵습니다. 상호 관련된 클래스의 전체 라이브러리가 있습니다.

의미는 이것입니다. 타이머에서 우리는 계정의 모든 주문과 위치를 살펴보고 CArrayObj 목록을 채웁니다. 한 번에 최신 정보를 얻을 수 있도록 지속적으로 업데이트합니다.

포지션 을 청산하거나 주문을 삭제해야 하는 경우, 우리는 이 목록을 가져와서 필요한 주문 개체와 이 목록에서 청산(수정) 기능에 필요한 티켓을 선택합니다. 이 주문 객체가 물리적으로 존재하지 않는 경우(이러한 작업 중에 닫히거나 삭제됨) 목록의 다음 개체로 이동합니다. 이 개체는 이미 닫혀 있고 타이머의 다음 반복에서 목록이 이미 업데이트되기 때문입니다. 가능한 문제에서 가장 먼저 떠오르는 것은 수신된 목록으로 작업을 실행하는 동안 거래 환경이 변경될 때 수신된 목록의 관련성이 없다는 것입니다. 그러나 내가 보기에 목록에 기록된 주문의 물리적 부재는 그다지 성가시지 않아야 합니다. 오류가 발생하고 목록의 다음 항목으로 이동합니다. 이 목록은 거래 환경에서처럼 섞이지 않으며, 건너 뛰는 것은 불가능합니다-주문이 없다는 사실에 대한 진술 만 목록의 해당 항목.

이것이 내가 아직 코드에서 이것을 구현하지 않았기 때문에 지금까지 나에게 보이는 방법입니다. 이제 막 구현에 가까워지고 있지만 처음에는 다른 클래스를 완료해야 합니다(기능 교체에 대한 질문은 기능 분기에서 요청되었습니다). 구현을 시작하면 가능한 문제가 거기에 표시되고 문제를 해결하고 제거하는 방법을 결정할 것입니다.

다음은 이것의 구현입니다

거래, 자동 거래 시스템 및 거래 전략 테스트에 관한 포럼

주문 열거 주기의 구성

fxsaber , 2017.09.11 20:29

 // Редкий, но правильный костяк модификации ордеров
for ( int i = OrdersTotal () - 1 ; i >= 0 ; i--)
   if ( OrderSelect (i, SELECT_BY_POS ))
     if ( OrderModify ( OrderTicket (), Price, SL, TP, OrderExpiration ()))     
    {
       i = OrdersTotal (); // Хотя бы так
      
       // А лучше так
//      OnTick(); break; // вместо строки выше лучше делать такой вызов (переполнения стека от рекурсивных вызовов быть не должно)
    }


거래 요청 을 보낸 후 거래 환경이 바뀌므로 거래 서버의 응답 직후 TS의 모든 거래 로직을 처음부터 처음부터 실행하는 것이 좋습니다.

여전히 IsChange가 필요합니다. 타이머는 전혀 옵션이 아닙니다. Sleep(1) 조차도 전체 그림을 망칩니다.

 
Alexey Viktorov :

아무것도 할 필요가 없습니다. 바보의 표정으로 논리를 훑어보면 충분하다.

그래서 네, 주문의 마감/활성화가 체크되어 있으면 문제가 되지 않습니다.
글쎄, 당신이 자신의 티켓 배열을 가지고 있다면 주문은 단순히 건너 뛸 것입니다.

추신. 나는 한 번 더 경우를 던질 것이다. 만약 보류가 실제 주문의 중지로 설정되어 있다면(쿠데타에 대한), 중지가 촉발될 때, 보류는 무기한 오픈에서 지연될 수 있다. 즉, 하나의 주문은 시장에서 작동하고 두 번째 주문은 특정 수의 틱을 걸 것입니다...

 
fxsaber :

다음은 이것의 구현입니다

여전히 IsChange가 필요합니다. 타이머는 전혀 옵션이 아닙니다. Sleep(1) 조차도 전체 그림을 망칩니다.

IsChange()는 타이머에서 구현됩니다(아직 완료되지 않은 테스트 버전).

 //+------------------------------------------------------------------+
//| Обновляет список ордеров                                         |
//+------------------------------------------------------------------+
int CMarketCollection::Refresh( void )
  {
   :: ZeroMemory (m_struct_market);
   int number_new= 0 , total=:: OrdersTotal ();
   m_list_all_orders.Clear();
   for ( int i= 0 ; i<total; i++){
       if (!:: OrderSelect (i, SELECT_BY_POS )) continue ;
       long ticket=:: OrderTicket ();
      m_struct_market.hash_sum_acc+=ticket;
      m_struct_market.total_volumes+=:: OrderLots ();
       ENUM_ORDER_TYPE type=( ENUM_ORDER_TYPE ):: OrderType ();
       if (type== ORDER_TYPE_BUY || type== ORDER_TYPE_SELL ){
         CMarketOrder* order= new CMarketOrder();
         if (order== NULL ) continue ;
         m_list_all_orders.InsertSort(order);
         m_struct_market.total_positions++;
         }
       else {
         CMarketPending* order= new CMarketPending();
         if (order== NULL ) continue ;
         m_list_all_orders.InsertSort(order);
         m_struct_market.total_pending++;
         }
      }
   //--- Первый запуск
   if (m_hash_sum_acc_prev== WRONG_VALUE ){
      m_hash_sum_acc_prev=m_struct_market.hash_sum_acc;
      m_total_positions_prev=m_struct_market.total_positions;
      m_total_pending_prev=m_struct_market.total_pending;
      m_total_volume_prev=m_struct_market.total_volumes;
      }
   //---
   if (m_struct_market.hash_sum_acc!=m_hash_sum_acc_prev){
      number_new=(m_struct_market.total_pending+m_struct_market.total_positions)-(m_total_positions_prev+m_total_pending_prev);
       Print (FUNC, "Хэш-сумма всех ордеров и позиций изменилась" );
       //--- Увеличисля общий объём
       if (:: NormalizeDouble (m_struct_market.total_volumes-m_total_volume_prev, 3 )> 0 ){
         Print (FUNC, "Общий объём увеличился" );
         if (m_struct_market.total_positions>m_total_positions_prev) Print (FUNC, "Количество позиций увеличилось" );
         if (m_struct_market.total_pending>m_total_pending_prev) Print (FUNC, "Количество ордеров увеличилось" );
         //--- Отправка EVENT в управляющий класс CEngine
         // сделать!
         }
       //--- Уменьшился общий объём
       else if (:: NormalizeDouble (m_struct_market.total_volumes-m_total_volume_prev, 3 )< 0 ){
         Print (FUNC, "Общий объём уменьшился" );
         if (m_struct_market.total_positions<m_total_positions_prev) Print (FUNC, "Количество позиций уменьшилось" );
         if (m_struct_market.total_pending<m_total_pending_prev) Print (FUNC, "Количество ордеров уменьшилось" );
         //--- Отправка EVENT в управляющий класс CEngine
         // сделать!
         }
       else {
         // что-то ещё, не пойму пока что именно - не было претендентов ещё
         }
       //---
      m_hash_sum_acc_prev=m_struct_market.hash_sum_acc;
      m_total_positions_prev=m_struct_market.total_positions;
      m_total_pending_prev=m_struct_market.total_pending;
      m_total_volume_prev=m_struct_market.total_volumes;
      }
   //---
   //---
   return number_new;
  }
//+------------------------------------------------------------------+

제어 클래스에서 (테스터에서) 두 클래스의 Refresh()에서 반환된 숫자로 변경 사항을 포착할 수 있습니다.

 //+------------------------------------------------------------------+
//| Таймер                                                           |
//+------------------------------------------------------------------+
void CEngine:: OnTimer ( void )
  {
   //--- Обновление списка исторических ордеров и позиций
   m_new_history=History.Refresh();
   if (m_new_history> 0 ){
       Print (FUNC, "Изменение в исторических на " ,m_new_history);
       //--- реакция
      }
   //--- Обновление списка рыночных ордеров и позиций
   m_new_market=Market.Refresh();
   if (m_new_market!= 0 ){
       Print (FUNC, "Изменение в активных на " ,m_new_market);
       //--- реакция
      }
   //---
   Sym. OnTimer ();
  }
//+------------------------------------------------------------------+

또는 아직 구현되지 않은 사용자 지정 이벤트(데모, 실제).

 
Artyom Trishkin :

IsChange()는 타이머에서 구현됩니다(아직 완료되지 않은 테스트 버전).

IsChange가 5줄이면 어떻게 될까요?