Библиотеки: Virtual - страница 43

 
fxsaber #:

Добавлены указатели на виртуальные окружения. Это предоставляет наибольшую гибкость/удобство использования при работе одновременно с несколькими торговыми окружениями.

Еще пример работы с указателями.

bool Filter( const string ID )
{
  return(true);  
}

// Объединяем нужные виртуальные окружения в одно.
int Summary( const string ID = NULL )
{
  const VIRTUAL_POINTER VirtualPointer = VIRTUAL::Create(); // Создали окружения для суммирования.
  
  // Бежим по окружениям.
  for (int i = VIRTUAL::Total() - 1; i > 0 ; i--)
  {
    const VIRTUAL_POINTER VirtualPointerFrom = _VI(i, VIRTUAL::GetHandle()); // Выбрали очередное.
    
    if (_VP(VirtualPointerFrom, Filter(VIRTUAL::GetID()))) // Подходит ли для добавления.
      VirtualPointer += VirtualPointerFrom; // Добавили.
  }
  
  _VP(VirtualPointer, VIRTUAL::SetID(ID)); // Прописали ID.

  return(VirtualPointer.GetHandle());
}
 
После исправления этого недуга компилятора, работа данной библиотеки должна заметно ускориться.
 
fxsaber #:
После исправления этого недуга компилятора, работа данной библиотеки должна заметно ускориться.

Аналогично.

 
fxsaber #:
После исправления этого недуга компилятора, работа данной библиотеки должна заметно ускориться.

Вышел новый MT5-build b3584, где добавили скорости. И появилась возможность честно попробовать ускорить быстрый код.

Раньше было сравнение, что виртуальный тестер значительно опережает по скорости MT5-тестер, но в данном случае все несколько иначе.

Никаких виртуальных окружений, нужно ускориться именно в MT5-тестере.


Применил две вещи: снепшоты и особенность MT4Orders. Вот такой код вышел.

#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006

#define VIRTUAL_SNAPSHOT_REFRESHTIME 1000 // Время жизни снепшота для обновления. В MT5 требует подключенной MT4Orders.mqh
#define VIRTUAL_SNAPSHOT_WITHOUT_HISTORY // Отказ от снепшота истории для повышения производительности
#include <fxsaber\Virtual\Virtual.mqh> // https://www.mql5.com/ru/code/22577

input int inAmountMagics = 50; // Сколько ТС эмулировать

// Для каждой ТС открываем позицию и отложку. MT4-код для лаконичности.
void OnInit()
{
  MqlTick Tick;
  
  if (SymbolInfoTick(_Symbol, Tick))  
    for (int i = 0; i < inAmountMagics; i++)
    {
      OrderSend(_Symbol, OP_BUY, 1, Tick.ask, 0, 0, 0, NULL, i);
      
      OrderSend(_Symbol, OP_BUYLIMIT, 1, Tick.ask - 1e4*_Point, 0, 0, 0, NULL, i);
    }
}

// Сбор информации с нужных позиций/ордеров. MT4-код.
double CountOrders( const int Type, const int Magic, const int AmountPendingOrders )
{
  double Res = 0;
  
  // https://www.mql5.com/ru/forum/93352/page76#comment_45322854
  const int Begin = (Type <= OP_SELL) ? OrdersTotal() -  AmountPendingOrders : OrdersTotal();
  const int End = (Type <= OP_SELL) ? 0 : OrdersTotal() -  AmountPendingOrders;   
  
  for (int i = Begin - 1; i >= End; i--)
    if (OrderSelect(i, SELECT_BY_POS) && (OrderType() == Type) && (OrderMagicNumber() == Magic))
      Res += OrderOpenPrice() + OrderClosePrice() + OrderTakeProfit() + OrderStopLoss();
        
  return(Res);
}

// https://www.mql5.com/ru/forum/93352/page76#comment_45322854
int GetAmountPendingOrders()
{
  int Res = 0;
  
  for (int i = OrdersTotal() - 1; i >= 0; i--)
    if (OrderSelect(i, SELECT_BY_POS) && (OrderType() > OP_SELL))
      Res++;
    else
      break;
      
  return(Res);
}

// Число для контроля корректности альтернативных реализаций.
double OnTesterValue = 0;
double OnTester() { return(OnTesterValue); }

void OnTick()
{
  VIRTUAL::Snapshot(); // Снепшот.
  
  const int AmountPendingOrders = GetAmountPendingOrders(); // https://www.mql5.com/ru/forum/93352/page76#comment_45322854
  
  // Симулируем работу по всем ТС.
  for (int i = 0; i < inAmountMagics; i++)
    OnTesterValue += CountOrders(POSITION_TYPE_BUY, i, AmountPendingOrders) + 
                     CountOrders(POSITION_TYPE_SELL, i, AmountPendingOrders) +
                     CountOrders(ORDER_TYPE_BUY_LIMIT, i, AmountPendingOrders) +
                     CountOrders(ORDER_TYPE_SELL_LIMIT, i, AmountPendingOrders);  
}


Результат.

OnTester result 54790620.97344553
EURCAD,M1: 192394 ticks, 1440 bars generated. Environment synchronized in 0:00:00.023. Test passed in 0:00:46.653 (including ticks preprocessing 0:00:00.016).

Контрольная сумма совпадает. Получилось ускориться почти в два раза.


Для ускорения имеет смысл создавать свои снепшоты даже в Тестере. Virtual - только одна из возможных реализаций, взята для примера.

 

Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Новая версия платформы MetaTrader 5 build 3660: Улучшения и исправления

fxsaber, 2023.03.23 21:19

Я делал различные варианты на базе Virtual.

  • Реджекты первые N тиков или первые M миллисекунд после первого тика-акцепта отложки.

Можно выпросить пример на реализацию этого, раз уже было сделано?

 
traveller00 #:

Можно выпросить пример на реализацию этого, раз уже было сделано?

Готового не сохранилось. Но там просто:

  1. Добавляете нужные счетчики-поля в ORDER.
  2. Учитываете их в ORDER::IsChange( const MqlTick &Tick ).
 
Просто я думал, может удалось сделать надстройкой, не меняя сами исходники, чтоб их потом можно было без проблем обновлять. Но аккуратно без костылей не выйдет. Спасибо.
 
traveller00 #:
Просто я думал, может удалось сделать надстройкой, не меняя сами исходники, чтоб их потом можно было без проблем обновлять. Но аккуратно без костылей не выйдет. Спасибо.

Я не нашел полезным данный функционал. Включал/выключал через макросы, чтобы не оказывало влияние на быстродействие, когда не нужно.

Как итог, можно, конечно, оптимизировать ТС с условием, что срабатывают ордера по какому-то условию. Типа сделать ее менее зависимой от реджектов в реале. Но я не стал копать и забросил.


Реализация, как написал выше, очень простая. 5-10 строк добавить. А дальше уже решать, нужно ли, действительно, это или нет. Мне пока не нужно.

 
fxsaber #:

Контрольная сумма совпадает. Получилось ускориться почти в два раза.

Дополнительное ускорение за счет простого способа.
#include <MT4Orders.mqh> // https://www.mql5.com/ru/code/16006

#define VIRTUAL_SNAPSHOT_REFRESHTIME 1000 // Время жизни снепшота для обновления. В MT5 требует подключенной MT4Orders.mqh
#define VIRTUAL_SNAPSHOT_WITHOUT_HISTORY // Отказ от снепшота истории для повышения производительности
#include <fxsaber\Virtual\Virtual.mqh> // https://www.mql5.com/ru/code/22577

input int inAmountMagics = 50; // Сколько ТС эмулировать

// Для каждой ТС открываем позицию и отложку. MT4-код для лаконичности.
void OnInit()
{
  MqlTick Tick;
  
  if (SymbolInfoTick(_Symbol, Tick))  
    for (int i = 0; i < inAmountMagics; i++)
    {
      OrderSend(_Symbol, OP_BUY, 1, Tick.ask, 0, 0, 0, NULL, i);
      
      OrderSend(_Symbol, OP_BUYLIMIT, 1, Tick.ask - 1e4*_Point, 0, 0, 0, NULL, i);
    }
}

#define MAX_ORDERS 100

// Индексы позиций/ордеров по типам.
struct TYPE_INDEXES
{
  int Index[OP_SELLSTOP + 1][MAX_ORDERS];
  int Amount[OP_SELLSTOP + 1];
  
  // Заполнение индексов.
  void Fill( void )
  {
    ::ArrayInitialize(this.Amount, 0);
    
    for (int i = OrdersTotal() - 1; i >= 0; i--)
      if (OrderSelect(i, SELECT_BY_POS))
        this.Index[OrderType()][this.Amount[OrderType()]++] = i;
      
    return;          
  }
};

#undef MAX_ORDERS

// Сбор информации с нужных позиций/ордеров. MT4-код.
double CountOrders( const int Type, const int Magic, const TYPE_INDEXES &TypeIndexes )
{
  double Res = 0;
  
  for (int i = TypeIndexes.Amount[Type] - 1; i >= 0; i--)
    if (OrderSelect(TypeIndexes.Index[Type][i], SELECT_BY_POS) && (OrderType() == Type) && (OrderMagicNumber() == Magic))
      Res += OrderOpenPrice() + OrderClosePrice() + OrderTakeProfit() + OrderStopLoss();
        
  return(Res);
}

// Число для контроля корректности альтернативных реализаций.
double OnTesterValue = 0;
double OnTester() { return(OnTesterValue); }

void OnTick()
{
  VIRTUAL::Snapshot(); // Снепшот.

  TYPE_INDEXES TypeIndexes; // Индексы позиций/ордеров по типам.
  
  TypeIndexes.Fill(); // Заполнение индексов.
    
  // Симулируем работу по всем ТС.
  for (int i = 0; i < inAmountMagics; i++)
    OnTesterValue += CountOrders(POSITION_TYPE_BUY, i, TypeIndexes) + 
                     CountOrders(POSITION_TYPE_SELL, i, TypeIndexes) +
                     CountOrders(ORDER_TYPE_BUY_LIMIT, i, TypeIndexes) +
                     CountOrders(ORDER_TYPE_SELL_LIMIT, i, TypeIndexes);  
}
 

В Virtual\Orders.mqh

#define MAX_ORDERS 100

Если заменить, например на 500, ничего не сломается?

Причина обращения: