Если параллельно используются несколько виртуальных окружений, то можно существенно экономить на выборе окружения, если вместо SelectByHandle использовать SelectByIndex.
#include <fxsaber\Virtual\Virtual.mqh> // https://www.mql5.com/ru/code/22577struct VIRTUAL_SYSTEM
{
public:
constint Handle;
VIRTUAL_SYSTEM( void ) : Handle(VIRTUAL::Create()), Index(VIRTUAL::Total())
{
}
bool SelectMe()
{
// return(VIRTUAL::SelectByHandle(this.Handle)); // Если много окружений - небыстро.return(VIRTUAL::SelectByIndex(this.Index, this.Handle)); // Если много окружений - быстро.
}
private:
int Index; // https://www.mql5.com/ru/forum/170952/page227#comment_43069017
};
double GetSumProfit( VIRTUAL_SYSTEM &Virtuals[] )
{
double Sum = 0;
for (int i = ArraySize(Virtuals) - 1; i >= 0; i--)
if (Virtuals[i].SelectMe())
Sum += TesterStatistics(STAT_PROFIT);
return(Sum);
}
VIRTUAL_SYSTEM Virtuals1[1000]; // Много виртуальных окружений.
VIRTUAL_SYSTEM Virtuals2[2000]; // Много виртуальных окружений.#include <fxsaber\Benchmark\Benchmark.mqh> // https://www.mql5.com/ru/code/31279#define _C(A) _B(A, 1)
voidOnStart()
{
_C(GetSumProfit(Virtuals1));
_C(GetSumProfit(Virtuals2));
}
Rorschach #: Код к скрину из параллельной ветки. В fn0() торговая система и вывод баланса в виде индикатора. Как мне объединить это и это? Торговая система будет в отдельном файле. То есть нужно что то вроде AccountInfoDouble(ACCOUNT_BALANCE).
Нужно торговую систему переписать в классический вид: OnTick в стиле MT4. Тогда легко Vitual подключить и получить величину баланса на любой момент.
Однако, библиотека не отвечает за работу с таймсериями. На вход подаются только тики.
void OnTick()
{
//---double ma[]; CopyBuffer(h,0,0,1,ma); // Работа с таймсерией реального торгового окружения. Т.е. это значение 9000 раз не менялось.double pr=SymbolInfoDouble(_Symbol, SYMBOL_BID); // Вот это значение менялось, т.к. оно соответствует значению тика из 9000 проброшенных.if(PositionsTotal()==0) // Это всегда из реального окружения, т.к. не относится к MT4-Style.
{if(pr-ma[0]> Dev)OrderSend(_Symbol,OP_BUY ,1,SymbolInfoDouble(_Symbol,SYMBOL_ASK),0,0,0); // Это выражение могло выполниться до 9000 раз.if(pr-ma[0]<-Dev) OrderSend(_Symbol,OP_SELL,1,SymbolInfoDouble(_Symbol,SYMBOL_BID),0,0,0);
}
else
{
if(fabs(pr-ma[0])<0.001 && OrderSelect(0,SELECT_BY_POS)) OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(),0);
}
}
Мы видим, что ma[0] (и PositionsTotal) ни разу за 9000 вызовов не изменилось, т.к. бралось из реального окружения - каждый раз изнутри одного вызова fn0(). Т.е. формировалось до 9000 открытых позиций, когда количество одновременно открытых ордеров ограничено (можете поменять).
#define MAX_ORDERS 100
Далее в каждом вызове OnTimer создаете новое виртуальное торговое окружение.
Все виртуальные окружения до этого остаются! Вы просто все новые и новые создаете, пока не закончится под них память. Если виртуальное окружение больше не нужно - удаляйте его.
Если параллельно используются несколько виртуальных окружений, то можно существенно экономить на выборе окружения, если вместо SelectByHandle использовать SelectByIndex.
Добавлены указатели на виртуальные окружения. Это предоставляет наибольшую гибкость/удобство использования при работе одновременно с несколькими торговыми окружениями. И скорость переключения.
Производительность.
Замер производился таким скриптом.
#include <fxsaber\Virtual\Virtual.mqh> // https://www.mql5.com/ru/code/22577struct VIRTUAL_SYSTEM
{
public:
constint Handle;
VIRTUAL_SYSTEM( void ) : Handle(VIRTUAL::Create()),
Index(VIRTUAL::Total()),
VirtualPointer(VIRTUAL::GetHandle())
{
}
bool SelectMe()
{
// return(VIRTUAL::SelectByHandle(this.Handle)); // Если много окружений - медленно// return(VIRTUAL::SelectByIndex(this.Index, this.Handle)); // Если много окружений - быстро.return(this.VirtualPointer.Select()); // Если много окружений - очень быстро.
}
private:
// https://www.mql5.com/ru/forum/170952/page227#comment_43069017int Index;
const VIRTUAL_POINTER VirtualPointer;
};
double GetSumProfit( VIRTUAL_SYSTEM &Virtuals[] )
{
double Sum = 0;
for (int i = ArraySize(Virtuals) - 1; i >= 0; i--)
if (Virtuals[i].SelectMe())
Sum += TesterStatistics(STAT_PROFIT);
return(Sum);
}
VIRTUAL_SYSTEM Virtuals1[1000]; // Много виртуальных окружений.
VIRTUAL_SYSTEM Virtuals2[2000]; // Много виртуальных окружений.#include <fxsaber\Benchmark\Benchmark.mqh> // https://www.mql5.com/ru/code/31279#define _C(A) _B(A, 1)
voidOnStart()
{
_C(GetSumProfit(Virtuals1));
_C(GetSumProfit(Virtuals2));
}
Добавлены указатели на виртуальные окружения. Это предоставляет наибольшую гибкость/удобство использования при работе одновременно с несколькими торговыми окружениями.
Пример работы с несколькими виртуальными окружениями.
#include <fxsaber\Virtual\Virtual.mqh> // https://www.mql5.com/ru/code/22577#define Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)
string Example()
{
string Str = NULL;
VIRTUAL_POINTER Pointers[10];
// Создали виртуальные окружения и привязали их к указателям.for (int i = 1; i < 10; i++)
{
Pointers[i] = VIRTUAL::Create(i * 123.45 ); // Создали окружение и привязали указатель.// Вошли в него, выполнили SetID и вышли.
_VP(Pointers[i], VIRTUAL::SetID("Virtual_" + AccountInfoString(ACCOUNT_SERVER) + "_" + (string)VIRTUAL::GetHandle()));
}
_VSP(Pointers[5]) // Вошли в "пятое" виртуальное окружение.
VIRTUAL::NewTick();
// Открыли позицию в "пятом" окружении.if (OrderSelect(OrderSend(_Symbol, OP_BUY, 1, Ask, 0, 0, 0, VIRTUAL::GetID() + "_Example"), SELECT_BY_TICKET))
{
_VSP(Pointers[3]) // Вошли в "третье" виртуальное окружение.
VIRTUAL::NewTick();
// Выставили лимитник в "третьем" окружении.OrderSend(_Symbol, OP_BUYLIMIT, 1, Ask - 1000 * _Point, 0, 0, 0, VIRTUAL::GetID() + "_Example");
Str += "\n\n" + VIRTUAL::GetID() + "\n" + VIRTUAL::ToString(); // Собрали данные "третьего" окружения.
} // Вышли из "третьего" виртуального окружения, оказавшись в предыдущем - "пятом".// Вошли в "восьмое" окружение, собрали данные и вышли из него, попав в предыдущее - "пятое".
Str += "\n\n" + _VP(Pointers[8], VIRTUAL::GetID() + "\n" + VIRTUAL::ToString(1));
Str += "\n\n" + VIRTUAL::GetID() + "\n" + VIRTUAL::ToString(); // Собрали данные "пятого" окружения.return(Str);
} // Вышли из "пятого" окружения, оказавшись в предыдущем.#define TOSTRING(A) #A + " = " + (string)(A) + " "voidOnStart()
{
Print(Example());
// Сколько всего окружений и где сейчас находимся.Print("\n\n" + TOSTRING(VIRTUAL::Total()) + TOSTRING(VIRTUAL::GetHandle()));
}
В примере было создано девять виртуальных окружений. Показано, как одновременно в двух из них соответственно открывается позиция и выставляется лимитник, а из третьего берутся данные.
В итоге выводится информация из этих трех окружений, сколько всего виртуальных окружения и в каком находимся.
Пример работы с несколькими виртуальными окружениями.
Одно из боевых применений.
В советнике находится пять ТС.
Каждая ТС имеет три виртуальных окружения: V1 - торговля без фильтра, V2 - наложение фильтра на V1 и синхронизация с реальным окружением для открытия позиций, V3 - торговля без каких-либо остановок и синхронизация с реальным окружением для закрытия позиций.
Итого активны 15 виртуальных окружений в советнике. Поэтому максимально быстрая и удобная работа необходима.
В некоторых сценариях использования в Терминале могут постоянно работать несколько сотен виртуальных окружений, временно - тысячи.
Если параллельно используются несколько виртуальных окружений, то можно существенно экономить на выборе окружения, если вместо SelectByHandle использовать SelectByIndex.
SelectByHandle:
SelectByIndex:
Код к скрину из параллельной ветки. В fn0() торговая система и вывод баланса в виде индикатора. Как мне объединить это и это? Торговая система будет в отдельном файле. То есть нужно что то вроде AccountInfoDouble(ACCOUNT_BALANCE).
Нужно торговую систему переписать в классический вид: OnTick в стиле MT4. Тогда легко Vitual подключить и получить величину баланса на любой момент.
Однако, библиотека не отвечает за работу с таймсериями. На вход подаются только тики.
Вот этим действием Вы пробросили в виртуальное окружение 9000 сгенерированных тиков.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Библиотеки: Virtual
Rorschach, 2023.01.17 21:17
На каждом проброшеном тике внутри сформированного виртуального окружения был вызван OnTick.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Библиотеки: Virtual
Rorschach, 2023.01.17 21:17
Мы видим, что ma[0] (и PositionsTotal) ни разу за 9000 вызовов не изменилось, т.к. бралось из реального окружения - каждый раз изнутри одного вызова fn0(). Т.е. формировалось до 9000 открытых позиций, когда количество одновременно открытых ордеров ограничено (можете поменять).
Далее в каждом вызове OnTimer создаете новое виртуальное торговое окружение.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Библиотеки: Virtual
Rorschach, 2023.01.17 21:17
Все виртуальные окружения до этого остаются! Вы просто все новые и новые создаете, пока не закончится под них память. Если виртуальное окружение больше не нужно - удаляйте его.
Напишите советник без использования таймсерий.
Спасибо, немного накостылил и заработало
Если параллельно используются несколько виртуальных окружений, то можно существенно экономить на выборе окружения, если вместо SelectByHandle использовать SelectByIndex.
Добавлены указатели на виртуальные окружения. Это предоставляет наибольшую гибкость/удобство использования при работе одновременно с несколькими торговыми окружениями. И скорость переключения.
Производительность.
Замер производился таким скриптом.
Результаты замеров на обеих платформах.
97326 mcs
77569 mcs
869 mcs
525 mcs
36 mcs
8 mcs
13 mcs
Полностью перешел на указатели.
Добавлены указатели на виртуальные окружения. Это предоставляет наибольшую гибкость/удобство использования при работе одновременно с несколькими торговыми окружениями.
Пример работы с несколькими виртуальными окружениями.
В примере было создано девять виртуальных окружений. Показано, как одновременно в двух из них соответственно открывается позиция и выставляется лимитник, а из третьего берутся данные.
В итоге выводится информация из этих трех окружений, сколько всего виртуальных окружения и в каком находимся.
Пример работы с несколькими виртуальными окружениями.
Одно из боевых применений.
Итого активны 15 виртуальных окружений в советнике. Поэтому максимально быстрая и удобная работа необходима.
В некоторых сценариях использования в Терминале могут постоянно работать несколько сотен виртуальных окружений, временно - тысячи.
Сама библиотека не была обновлена?
Сама библиотека не была обновлена?
Обновлены Orders.mqh и Virtual.mqh.
Пояснение по сохранению OrderSelect-выбора окружением.
Пример, показывающий такое поведение.
Результат.
Видим, что в каждом окружении выбор соответствует последнему OrderSelect, сделанному в соответствующем окружении.
Грубо говоря, OrderSelect одного окружения не влияет на ранее выбранный ордер из другого окружения.
Если совсем кратко, все работает правильно.