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

 
fxsaber #:

Очень медленно. Возможно, в этом дело.

Я удалил `OrderSymbol() != _Symbol`, и обработка 10 миллионов тиков сократилась до 5 секунд.

 
hini #:

Я удалил `OrderSymbol() != _Symbol`, и обработка 10 миллионов тиков сократилась до 5 секунд.

Желательно найти альтернативу любым string-операциям.

 
fxsaber #:

Желательно найти альтернативу любым string-операциям.

Разве неизбежно время выполнения `for (int i = OrdersTotal() - 1; i >= 0; --i)`? Я заметил, что большая часть времени уходит именно на это. Мне нужно обновлять самое раннее время открытия позиции, самое позднее время открытия позиции, прибыль, количество ордеров, общее количество лотов и т. д.

 
hini #:

Мне нужно обновлять самое раннее время открытия позиции, самое позднее время открытия позиции, прибыль, количество ордеров, общее количество лотов и т. д.

Ну и зачем делать расчет этого на каждом тике? Можно же сохранить эти данные и делать перерасчеты только в случае, если что-то поменялось с ордерами.

 
fxsaber #:

Ну и зачем делать расчет этого на каждом тике? Можно же сохранить эти данные и делать перерасчеты только в случае, если что-то поменялось с ордерами.

Но прибыль нужно обновлять постоянно.

 
hini #:

Но прибыль нужно обновлять постоянно.

Разве для обновления прибыли нужен OrdersTotal-цикл?

 
fxsaber #:

Разве для обновления прибыли нужен OrdersTotal-цикл?

Хорошо, спасибо за напоминание. Использовать массив для сохранения ticket, и проверять только заказы внутри массива, а затем выйти из цикла, верно? 
 
hini #:
Использовать массив для сохранения ticket, и проверять только заказы внутри массива, а затем выйти из цикла, верно? 

SELECT_BY_TICKET всегда является дорогой операцией. Нечасто это оправдано.

Приведите здесь распечатку VIRTUAL::ToString стандартного состояния. И на этих данных покажите, какая нужна информация.


Ну и сам цикл OrdersTotal хорошо бы показать.

 
fxsaber #:

делать перерасчеты только в случае, если что-то поменялось с ордерами.

Похоже, забыл рассказать про древний функционал.

VIRTUAL::IsChanged(); // Возвращает true только в том случае, если что-то произошло с ордерами с предыдущего вызова этой функции в том же виртуальном окружении.


Пример.

//#define VIRTUAL_ALTERNATIVE // Альтернативная скорость расчетов
#include <fxsaber\Virtual\Virtual.mqh>

#define TOSTRING(A) #A + " = " + (string)(A)
#define PRINT(A) A; Print("--------------\nOperation: " + #A); \
                    Print("Result:\n" + VIRTUAL::ToString());  \
                    Print(TOSTRING(VIRTUAL::IsChanged()));

void OnStart()
{
  const double Offset = 100 * _Point;
  
  MqlTick Tick;  
  SymbolInfoTick(_Symbol, Tick);
  
  PRINT(VIRTUAL::SelectByHandle(VIRTUAL::Create(1000.0))) // VIRTUAL::IsChanged() = true
  
  PRINT(VIRTUAL::NewTick(Tick)) // VIRTUAL::IsChanged() = false

  PRINT(OrderSend(_Symbol, OP_BUYLIMIT, 1, Tick.ask - Offset, 0, 0, Tick.bid + Offset)) // VIRTUAL::IsChanged() = true/false

  PRINT(Tick.ask -= Offset / 2; VIRTUAL::NewTick(Tick)) // VIRTUAL::IsChanged() = false

  PRINT(Tick.ask -= Offset; VIRTUAL::NewTick(Tick)) // VIRTUAL::IsChanged() = true

  PRINT(Tick.bid += Offset / 2; VIRTUAL::NewTick(Tick)) // VIRTUAL::IsChanged() = false

  PRINT(Tick.bid += Offset; VIRTUAL::NewTick(Tick)) // VIRTUAL::IsChanged() = true

  PRINT(VIRTUAL::NewTick(Tick)) // VIRTUAL::IsChanged() = false
}


Результат.

--------------
Operation: VIRTUAL::SelectByHandle(VIRTUAL::Create(1000.0))
Result:
 time = 1970.01.01 00:00:00.000 bid = 0.00000 ask = 0.00000 last = 0.00000 volume = 0 65536 FLAG_UNKNOWN (65536)

Balance = 1000.00, Equity = 1000.00, Profit = 0.00, 2025.03.04 - 1970.01.01 00:00:00
VIRTUAL::IsChanged() = true
--------------
Operation: VIRTUAL::NewTick(Tick)
Result:
 time = 2025.03.04 14:26:35.335 bid = 1.05495 ask = 1.05495 last = 0.00000 volume = 0 66566 TICK_FLAG_BID TICK_FLAG_ASK FLAG_UNKNOWN (66560)

Balance = 1000.00, Equity = 1000.00, Profit = 0.00, 2025.03.04 - 2025.03.04 14:26:35
VIRTUAL::IsChanged() = false
--------------
Operation: OrderSend(_Symbol, OP_BUYLIMIT, 1, Tick.ask - Offset, 0, 0, Tick.bid + Offset)
Result:
 time = 2025.03.04 14:26:35.335 bid = 1.05495 ask = 1.05495 last = 0.00000 volume = 0 66566 TICK_FLAG_BID TICK_FLAG_ASK FLAG_UNKNOWN (66560)

#2 2025.03.04 14:26:35.335 buy limit 1.00 EURUSD 1.05395 0.00000 1.05595 1.05495 0.00 0.00 0.00 0 - 00:00:00

Balance = 1000.00, Equity = 1000.00, Profit = 0.00, 2025.03.04 - 2025.03.04 14:26:35
VIRTUAL::IsChanged() = false
--------------
Operation: Tick.ask -= Offset / 2; VIRTUAL::NewTick(Tick)
Result:
 time = 2025.03.04 14:26:35.335 bid = 1.05495 ask = 1.05445 last = 0.00000 volume = 0 66566 TICK_FLAG_BID TICK_FLAG_ASK FLAG_UNKNOWN (66560)

#2 2025.03.04 14:26:35.335 buy limit 1.00 EURUSD 1.05395 0.00000 1.05595 1.05445 0.00 0.00 0.00 0 - 00:00:00

Balance = 1000.00, Equity = 1000.00, Profit = 0.00, 2025.03.04 - 2025.03.04 14:26:35
VIRTUAL::IsChanged() = false
--------------
Operation: Tick.ask -= Offset; VIRTUAL::NewTick(Tick)
Result:
 time = 2025.03.04 14:26:35.335 bid = 1.05495 ask = 1.05345 last = 0.00000 volume = 0 66566 TICK_FLAG_BID TICK_FLAG_ASK FLAG_UNKNOWN (66560)

#2 2025.03.04 14:26:35.335 buy 1.00 EURUSD 1.05395 0.00000 1.05595 1.05495 0.00 0.00 100.00 0: +100 (+100) - 00:00:00

Balance = 1000.00, Equity = 1100.00, Profit = 100.00, 2025.03.04 - 2025.03.04 14:26:35
VIRTUAL::IsChanged() = true
--------------
Operation: Tick.bid += Offset / 2; VIRTUAL::NewTick(Tick)
Result:
 time = 2025.03.04 14:26:35.335 bid = 1.05545 ask = 1.05345 last = 0.00000 volume = 0 66566 TICK_FLAG_BID TICK_FLAG_ASK FLAG_UNKNOWN (66560)

#2 2025.03.04 14:26:35.335 buy 1.00 EURUSD 1.05395 0.00000 1.05595 1.05545 0.00 0.00 150.00 0: +150 (+150) - 00:00:00

Balance = 1000.00, Equity = 1150.00, Profit = 150.00, 2025.03.04 - 2025.03.04 14:26:35
VIRTUAL::IsChanged() = false
--------------
Operation: Tick.bid += Offset; VIRTUAL::NewTick(Tick)
Result:
 time = 2025.03.04 14:26:35.335 bid = 1.05645 ask = 1.05345 last = 0.00000 volume = 0 66566 TICK_FLAG_BID TICK_FLAG_ASK FLAG_UNKNOWN (66560)

Balance = 1200.00, Equity = 1200.00, Profit = 200.00, 2025.03.04 - 2025.03.04 14:26:35
VIRTUAL::IsChanged() = true
--------------
Operation: VIRTUAL::NewTick(Tick)
Result:
 time = 2025.03.04 14:26:35.335 bid = 1.05645 ask = 1.05345 last = 0.00000 volume = 0 66566 TICK_FLAG_BID TICK_FLAG_ASK FLAG_UNKNOWN (66560)

Balance = 1200.00, Equity = 1200.00, Profit = 200.00, 2025.03.04 - 2025.03.04 14:26:35
VIRTUAL::IsChanged() = false
 
fxsaber #:

SELECT_BY_TICKET всегда является дорогой операцией. Нечасто это оправдано.

Приведите здесь распечатку VIRTUAL::ToString стандартного состояния. И на этих данных покажите, какая нужна информация.


Ну и сам цикл OrdersTotal хорошо бы показать.

Я не понимаю, какое это имеет отношение к ToString(). Я редко использую его. Это контент UpdatePosi

  void               UpdatePosi() {
    int totalPosi = OrdersTotal();
    CStrategyBase::ResetPosiVariable();
    datetime firstBuyOpenTime = 0, firstSellOpenTime = 0;
    datetime lastBuyOpenTime = 0, lastSellOpenTime = 0;
    double totalProfit = 0, totalComm = 0;
    for(int i = OrdersTotal() - 1; i >= 0; --i) {
      if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderMagicNumber() != m_magic) continue;
      m_totalCnt++;
      totalProfit += OrderProfit() + OrderSwap();// + OrderCommission();
      totalComm += OrderCommission();
      ENUM_ORDER_TYPE type = (ENUM_ORDER_TYPE)OrderType();
      datetime orderOpenTime = OrderOpenTime();
      double orderOpenPrice = OrderOpenPrice();
      if (type == OP_BUY) {
        m_buyCnt++;
        m_buyLot += OrderLots();
        if (firstBuyOpenTime == 0 || orderOpenTime < firstBuyOpenTime) {
          m_firstBuyPrice = orderOpenPrice;
          firstBuyOpenTime = orderOpenTime;
        }
        if (lastBuyOpenTime == 0 || orderOpenTime > lastBuyOpenTime) {
          m_lastBuyPrice = orderOpenPrice;
          lastBuyOpenTime = orderOpenTime;
        }
      } else if (type == OP_SELL) {
        m_sellCnt++;
        m_sellLot += OrderLots();
        if (firstSellOpenTime == 0 || orderOpenTime < firstSellOpenTime) {
          m_firstSellPrice = orderOpenPrice;
          firstSellOpenTime = orderOpenTime;
        }
        if (lastSellOpenTime == 0 || orderOpenTime > lastSellOpenTime) {
          m_lastSellPrice = orderOpenPrice;
          lastSellOpenTime = orderOpenTime;
        }
      }
    }

  }