Скорость работы торговых функций

 

В связи с тем, что обычно в работе десятки рыночных и отложенных ордеров, давно интересовало, насколько выгоднее по времени запоминать параметры ордера, чем каждый раз получать их через OrderGet******(). Написал небольшой тест, можете запускать на демо или реале, он открывает только отложенники на безопасном расстоянии от цены. После нескольких проходов эксперт автоматом выгружается и все за собой закрывает.

Файл в аттаче, вот результаты, ниже код. Время в микросекундах, всего 50 ордеров, тысяча повторов. Видно, что запрос данных у терминала занимает от 10 до 18 раз больше времени, чем если запоминать их самому. Хотя 20-40 нс на один параметр в принципе немного.

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

2017.02.07 00:25:19.548 TestSpeedTradeFunctions (EURUSD,M15)    Время запроса через торг. функции= 1074
2017.02.07 00:25:19.548 TestSpeedTradeFunctions (EURUSD,M15)    Время копирования запомненных значений= 104
2017.02.07 00:25:24.547 TestSpeedTradeFunctions (EURUSD,M15)    Время запроса через торг. функции= 1806
2017.02.07 00:25:24.547 TestSpeedTradeFunctions (EURUSD,M15)    Время копирования запомненных значений= 104
2017.02.07 00:25:29.569 TestSpeedTradeFunctions (EURUSD,M15)    Время запроса через торг. функции= 1115
2017.02.07 00:25:29.569 TestSpeedTradeFunctions (EURUSD,M15)    Время копирования запомненных значений= 104
2017.02.07 00:25:34.555 TestSpeedTradeFunctions (EURUSD,M15)    Время запроса через торг. функции= 1080
2017.02.07 00:25:34.555 TestSpeedTradeFunctions (EURUSD,M15)    Время копирования запомненных значений= 104
2017.02.07 00:25:39.548 TestSpeedTradeFunctions (EURUSD,M15)    Время запроса через торг. функции= 1159
2017.02.07 00:25:39.548 TestSpeedTradeFunctions (EURUSD,M15)    Время копирования запомненных значений= 104
2017.02.07 00:25:44.547 TestSpeedTradeFunctions (EURUSD,M15)    Время запроса через торг. функции= 1086
2017.02.07 00:25:44.547 TestSpeedTradeFunctions (EURUSD,M15)    Время копирования запомненных значений= 105
2017.02.07 00:25:49.559 TestSpeedTradeFunctions (EURUSD,M15)    ExpertRemove() function called
2017.02.07 00:25:49.561 TestSpeedTradeFunctions (EURUSD,M15)    Время запроса через торг. функции= 1794
2017.02.07 00:25:49.561 TestSpeedTradeFunctions (EURUSD,M15)    Время копирования запомненных значений= 104

 

И сам код

//+------------------------------------------------------------------+
//|                                      TestSpeedTradeFunctions.mq5 |
//|                                               Alexey Volchanskiy |
//|                                            http://mql.gnomio.com |
//+------------------------------------------------------------------+
#property copyright "Alexey Volchanskiy"
#property link      "http://mql.gnomio.com"
#property version   "1.00"

#include <Trade\OrderInfo.mqh>
#include <Trade\Trade.mqh>

input int TimerMS       = 5000;
input int PendingOrders = 50;
input int Magic         = 123456;
input double Lot        = 0.1;

struct SOrderParams
{
public:
   ulong             m_ticket;
   ENUM_ORDER_TYPE   m_type;
   ENUM_ORDER_STATE  m_state;
   datetime          m_expiration;
   double            m_volume_curr;
   double            m_price_open;
   double            m_stop_loss;
   double            m_take_profit;
} OrderParams[], OrderParamsCurrent;  

COrderInfo Order;
CTrade Trade;
int LastDeinitReason = -1;
int OrdersCount = 0;

void OnTimer()
{
    static int count = 5;
    if(count-- < 0)
    {
        CloseAllOrders(Magic);
        ExpertRemove();
    }
    ulong dt1=GetMicrosecondCount();
    for(int m = 0; m < 1000; m++)
        for(int n = 0; n < OrdersCount; n++)
        {
            OrderParamsCurrent.m_expiration = Order.TimeExpiration();
            OrderParamsCurrent.m_type = Order.OrderType();
            OrderParamsCurrent.m_stop_loss = Order.StopLoss();
            OrderParamsCurrent.m_take_profit = Order.TakeProfit();
        }
    Print("Время запроса через торг. функции= ", GetMicrosecondCount() - dt1);
    dt1=GetMicrosecondCount();
    for(int m = 0; m < 1000; m++)
        for(int n = 0; n < OrdersCount; n++)
        {
            OrderParamsCurrent.m_expiration = OrderParams[n].m_expiration;
            OrderParamsCurrent.m_type = OrderParams[n].m_type;
            OrderParamsCurrent.m_stop_loss = OrderParams[n].m_stop_loss;
            OrderParamsCurrent.m_take_profit = OrderParams[n].m_take_profit;
        }
    Print("Время копирования запомненных значений= ", GetMicrosecondCount() - dt1);
}



int OnInit()
{
    if(LastDeinitReason==REASON_CHARTCHANGE || LastDeinitReason==REASON_TEMPLATE)
    {
        LastDeinitReason = 0;
        return(INIT_SUCCEEDED);
    }
    EventSetMillisecondTimer(TimerMS);
    ArrayResize(OrderParams, PendingOrders);
    if(OrdersTotal() > 0)
        CloseAllOrders(Magic);
    OrdersCount = OpenAllOrders(Magic);    
    return(INIT_SUCCEEDED);
}

ulong CloseAllOrders(int magic)
{
    ulong ticket, count = 0;
    for(int n = OrdersTotal()-1; n <= 0; n--)
    {
        ticket = OrderGetTicket(n);
        if(OrderGetInteger(ORDER_MAGIC) == magic)
        {
            if(!Trade.OrderDelete(ticket))
                Print("Can't delete order ", ticket);
            else
                count++;    
        }        
    }
    return count;
}

int OpenAllOrders(int magic)
{
    ENUM_ORDER_TYPE otype = ORDER_TYPE_BUY_LIMIT;
    double price = SymbolInfoDouble(_Symbol, SYMBOL_ASK) - 0.02;
    int ordCount = 0;
    for(int n = 0; n < PendingOrders; n++)
    {
        Trade.SetExpertMagicNumber(magic);
        if(Trade.OrderOpen(_Symbol, otype, Lot, 0, price, 0, 0, ORDER_TIME_SPECIFIED, TimeCurrent() + 3*60, "TestSpeed"))
        {
            if(Order.Select(Trade.ResultOrder()))
            {
                OrderParams[n].m_expiration = Order.TimeExpiration();
                OrderParams[n].m_type = Order.OrderType();
                OrderParams[n].m_stop_loss = Order.StopLoss();
                OrderParams[n].m_take_profit = Order.TakeProfit();
                ordCount++;
            }    
        }
    }
    return ordCount;
}


void OnDeinit(const int reason)
{
    LastDeinitReason = reason;
    if(reason==REASON_CHARTCHANGE)
        return;
    CloseAllOrders(Magic);
    EventKillTimer();
}


 ***

Файлы:
 
void OnTimer()
{
    for(int m = 0; m < 1000; m++)
        for(int n = 0; n < OrdersCount; n++)
        {
            OrderParamsCurrent.m_expiration = Order.TimeExpiration();
            OrderParamsCurrent.m_type = Order.OrderType();
            OrderParamsCurrent.m_stop_loss = Order.StopLoss();
            OrderParamsCurrent.m_take_profit = Order.TakeProfit();
        }
}
Забыл тут сделать Select, но на время это не влияет, завтра поправлю.
 
Так еще быстрее будет
OrderParamsCurrent = OrderParams[n];

Разработчики настоятельно рекомендовали кэшировать историю, чтобы избегать тормозов. Так и делаю в библе.

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

Тем более, текущее окружение меняется, поэтому опрашивать просто необходимо. А вот история - не меняется, за редким исключением.

 

Кстати, этот кусок

    dt1=GetMicrosecondCount();
    for(int m = 0; m < 1000; m++)
        for(int n = 0; n < OrdersCount; n++)
        {
            OrderParamsCurrent.m_expiration = OrderParams[n].m_expiration;
            OrderParamsCurrent.m_type = OrderParams[n].m_type;
            OrderParamsCurrent.m_stop_loss = OrderParams[n].m_stop_loss;
            OrderParamsCurrent.m_take_profit = OrderParams[n].m_take_profit;
        }

    Print("Время копирования запомненных значений= ", GetMicrosecondCount() - dt1);

MQL5-компилятор даже не включит в EX5. Пример, как правильно замерять.
 

 

О ! Полезная информация.

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

 
Лучше бы придумали рабочую стратегию, чем фигней заниматься
 
roma_krasava:
Лучше бы придумали рабочую стратегию, чем фигней заниматься
И отдали вам, было бы вообще идеально)
 
Maxim Romanov:
И отдали вам, было бы вообще идеально)

Так кто-то стратегии разрабатывает, а кто-то ворчит на весь белый свет )

Как было написано на воротах Освенцима - каждому свое.