Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам - страница 2585

 
Aleksandr Slavskii #:

Они у вас добавлены, только так, что работать не будут.

Правильно потому что их надо минусовать из прибыли. А такой формулы ещё нет в этом коде.

 

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

Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам

Alexey Belyakov, 2025.04.01 15:13

Ура! получилось! "Доехал сам")))  Всем спасибо за помощь!

Рабочий вариант будет выглядеть так:

     HistorySelect(0, TimeCurrent());
        double profit = 0.0;
        ulong ticket_out = 0;
        for(int i = HistoryDealsTotal() - 1; i >= 0; i--)
        {
                ulong  deal_ticket = HistoryDealGetTicket(i);
                
                if (  HistoryDealGetInteger(deal_ticket, DEAL_ENTRY) == DEAL_ENTRY_OUT
                && HistoryDealGetInteger(deal_ticket, DEAL_POSITION_ID))
                {
                        ticket_out = deal_ticket;
                        break;
                }
        }
        profit += HistoryDealGetDouble(ticket_out, DEAL_PROFIT);
        profit += HistoryDealGetDouble(ticket_out, DEAL_SWAP);
        profit += HistoryDealGetDouble(ticket_out, DEAL_COMMISSION);
        profit += HistoryDealGetDouble(ticket_out, DEAL_FEE);
 
 Print ("ПРОФИТ",profit);
 

А зачем колупать всю историю, если надо только последнюю сделку? Почему не за сегодня? Если за сегодня сделок нет, то повторно HistorySelect() начиная со вчерашнего 00:00.

Это во первых.

Во вторых, если надо профит позиции сразу после её закрытия, то лучше ловите момент закрытия в функции 

void OnTradeTransaction(const MqlTradeTransaction& trans,
                        const MqlTradeRequest& request,
                        const MqlTradeResult& result)
    if(HistoryDealGetInteger(trans.deal, DEAL_ENTRY) == DEAL_ENTRY_OUT)

Это выдернутые строки из моего советника. Дальше самостоятельно читайте документацию и всё получится.

 
Aleksandr Slavskii #:

Этот код будет верным только если нет свопа и комиссия берётся при закрытии позиции.

Да, действительно. Спасиб. А я то умничать полез))

[Удален]  
помогите исправить ошибку
 
kokosovich84 #:
помогите исправить ошибку

Вы можете скопировать ошибку и перевести её переводчиком

'{' - unbalanced parentheses    --   '{' - несбалансированные скобки

Тоесть у вас не хватает парной скобки. Ищите.

Вы можете настроить МЕ, чтоб он подсвечивал парные скобки. Для Этого почитайте справку по МЕ.

 
Alexey Viktorov #:

А зачем вам это? Ведь двойной клик по строке 

двигает график к метке открытия или закрытия ордера. Только надо предваоительно отключить автопрокрутку.

Мне это для удобства анализа сделок. Да, двойным нажатием можно перейти к сделке, но тестер стратегий большую часть экрана перекрывает и что бы дальше что-то анализировать, нужно тестер свренуть, а для анализа другой сделки опят ьразвирнуть, порматать модификации ордера, нажать на открытие след ордера и так туда сюда это открывать и закрывать уже надоело. а с кнопками на графике- тестер свернул и кнопками перемещаешься по сделкам- и быстрее и удобней 😉
 

Ещё раз всем добрый день. Продолжаю биться над реализацией перемещения фокуса графика по открытым ордерам, после теста в окне инструмента на котором проводился тест.  Как мне и советовали попробовал находить объект стрелку от сделки и перемещать график к ней. Вот код, как это дело организованно.

//+------------------------------------------------------------------+
//| Индикатор для навигации по сделкам в тестере стратегий            |
//+------------------------------------------------------------------+
#property strict
#property indicator_chart_window

#include <stdlib.mqh> // Библиотека для работы с объектами

int currentTradeIndex = 0; // Индекс текущей сделки
datetime tradeTimes[];     // Массив времени открытия сделок

//+------------------------------------------------------------------+
//| Инициализация индикатора                                         |
//+------------------------------------------------------------------+
int OnInit()
{
    Print("▶ Инициализация индикатора...");
    GetTradeObjects();  // Собираем сделки
    CreateButtons();    // Создаем кнопки

    EventSetTimer(1);    // Устанавливаем таймер на 1 секунду
    return INIT_SUCCEEDED;
}

//+------------------------------------------------------------------+
//| Деинициализация индикатора                                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    Print("❌ Деинициализация индикатора...");
    EventKillTimer();  // Останавливаем таймер
    DeleteButtons();    // Удаляем кнопки
}

//+------------------------------------------------------------------+
//| Получаем объекты сделок после теста                               |
//+------------------------------------------------------------------+
void GetTradeObjects()
{
    int totalObjects = ObjectsTotal();
    Print(" Всего объектов на графике: ", totalObjects);
    ArrayResize(tradeTimes, 0); // Очищаем массив

    for (int i = 0; i < totalObjects; i++)
    {
        string name = ObjectName(i);
        int objType = ObjectGetInteger(0, name, OBJPROP_TYPE);
        string comment = ObjectGetString(0, name, OBJPROP_TEXT);

        if (objType == OBJ_ARROW && 
            StringFind(name, "#") == 0 && 
            (StringFind(name, "buy") > 0 || StringFind(name, "sell") > 0) && 
            StringFind(comment, "супер ордер") >= 0)
        {
            datetime openTime = ObjectGetInteger(0, name, OBJPROP_TIME);
            int size = ArraySize(tradeTimes);
            ArrayResize(tradeTimes, size + 1);
            tradeTimes[size] = openTime;

            Print("✅ Найден ордер: ", name, ", время: ", TimeToString(openTime));
        }
    }

    Print(" Всего найдено сделок: ", ArraySize(tradeTimes));
}

//+------------------------------------------------------------------+
//| Создание кнопок                                                   |
//+------------------------------------------------------------------+
void CreateButtons()
{
    CreateButton("PrevTrade", "⬅ Пред. сделка", 10, 30);
    CreateButton("NextTrade", "След. сделка ➡", 150, 30);
}

//+------------------------------------------------------------------+
//| Функция для создания кнопки                                       |
//+------------------------------------------------------------------+
void CreateButton(string name, string text, int x, int y)
{
    if (!ObjectCreate(0, name, OBJ_BUTTON, 0, 0, 0))
        return;
    
    ObjectSetInteger(0, name, OBJPROP_XSIZE, 120);
    ObjectSetInteger(0, name, OBJPROP_YSIZE, 25);
    ObjectSetInteger(0, name, OBJPROP_CORNER, 0);
    ObjectSetInteger(0, name, OBJPROP_XDISTANCE, x);
    ObjectSetInteger(0, name, OBJPROP_YDISTANCE, y);
    ObjectSetString(0, name, OBJPROP_TEXT, text);
    ObjectSetInteger(0, name, OBJPROP_FONTSIZE, 10);
    ObjectSetInteger(0, name, OBJPROP_COLOR, clrGold);
}

//+------------------------------------------------------------------+
//| Удаление кнопок                                                   |
//+------------------------------------------------------------------+
void DeleteButtons()
{
    ObjectDelete("PrevTrade");
    ObjectDelete("NextTrade");
}

//+------------------------------------------------------------------+
//| Обработка нажатий кнопок                                         |
//+------------------------------------------------------------------+
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
{
    if (id == CHARTEVENT_OBJECT_CLICK)
    {
        Print(" Нажата кнопка: ", sparam);
        if (sparam == "PrevTrade") MoveToTrade(-1);
        if (sparam == "NextTrade") MoveToTrade(1);
    }
}

//+------------------------------------------------------------------+
//| Перемещение графика к сделке                                     |
//+------------------------------------------------------------------+
void MoveToTrade(int step)
{
    int totalTrades = ArraySize(tradeTimes);
    if (totalTrades == 0)
    {
        Print("⚠ Нет найденных сделок.");
        return;
    }

    currentTradeIndex += step;
    if (currentTradeIndex < 0) currentTradeIndex = 0;
    if (currentTradeIndex >= totalTrades) currentTradeIndex = totalTrades - 1;

    datetime moveToTime = tradeTimes[currentTradeIndex];
    int barIndex = iBarShift(Symbol(), 0, moveToTime, false);

    Print(" Перемещение к сделке №", currentTradeIndex + 1, " (", TimeToString(moveToTime), "), бар: ", barIndex);

    if (barIndex != -1)
    {
        // Устанавливаем первый видимый бар
        ChartSetInteger(0, CHART_FIRST_VISIBLE_BAR, barIndex - (int)(ChartGetInteger(0, CHART_WIDTH_IN_BARS) / 2));

        // Устанавливаем фиксированный масштаб
        ChartSetInteger(0, CHART_SCALE, 2); // Пример масштаба (можно подобрать другой)

        // Перемещаем курсор к бару
        ChartSetInteger(0, CHART_BRING_TO_TOP, barIndex);
    }
    else
    {
        Print("❌ Ошибка: не найден бар для времени ", TimeToString(moveToTime));
    }
}

//+------------------------------------------------------------------+
//| Таймер (для устойчивости работы)                                 |
//+------------------------------------------------------------------+
void OnTimer()
{
    // Можно добавить дополнительные проверки
}

//+------------------------------------------------------------------+
//| Обязательная функция для индикатора                               |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,      // КОЛИЧЕСТВО БАРОВ
                const int prev_calculated,  // ПРЕДЫДУЩИЕ РАСЧЁТЫ
                const datetime &time[],      // МАССИВ ВРЕМЕНИ
                const double &open[],        // МАССИВ ЦЕН ОТКРЫТИЯ
                const double &high[],        // МАССИВ МАКСИМАЛЬНЫХ ЦЕН
                const double &low[],         // МАССИВ МИНИМАЛЬНЫХ ЦЕН
                const double &close[],       // МАССИВ ЦЕН ЗАКРЫТИЯ
                const long &tick_volume[],  // ОБЪЁМЫ
                const long &volume[],        // ОБЪЁМЫ
                const int &spread[])         // СПРЭДЫ
{
    return rates_total; // Просто возвращаем количество баров
}

По логам видно, что нажатие на кнопки работает, нормально ищется 1 сделка, при нажатии на след сделка ищется 2 стрелка, при нажатии на пред сделка опять находиться 1 стрелка. Но график только при первом нажатии масштабируется по другому и всё. Последующие нажатия кнопок график никуда не двигают(( А если вручную изменить масштаб графика и ещё раз кнопку нажать, то график опять масштабируется, но не перематывается к найденной сделке.

Подскажите пожалуйста, что я делаю не так и как завести это добро- чтобы мне чётко прокручивался график к местам открытия ордеров?

 
DanilaMactep #:

Ещё раз всем добрый день. Продолжаю биться над реализацией перемещения фокуса графика по открытым ордерам, после теста в окне инструмента на котором проводился тест.  Как мне и советовали попробовал находить объект стрелку от сделки и перемещать график к ней. Вот код, как это дело организованно.

По логам видно, что нажатие на кнопки работает, нормально ищется 1 сделка, при нажатии на след сделка ищется 2 стрелка, при нажатии на пред сделка опять находиться 1 стрелка. Но график только при первом нажатии масштабируется по другому и всё. Последующие нажатия кнопок график никуда не двигают(( А если вручную изменить масштаб графика и ещё раз кнопку нажать, то график опять масштабируется, но не перематывается к найденной сделке.

Подскажите пожалуйста, что я делаю не так и как завести это добро- чтобы мне чётко прокручивался график к местам открытия ордеров?

Предыдущие два мои коммента ты проигнорил. Ну, что-ж, бог любит троицу, попробую третий раз.

Третий вариант, можно посмотреть как  програмно двигаются графики у кого нибудь в коде. Например у меня))).

 
Aleksandr Slavskii #:
Предыдущие два мои коммента ты проигнорил.

И не только твои. Я ему писал чтоб вывел в печать нужные параметры для понимания происходящего.

 

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

вот в п.11 статьи переход с МТ 4 есть кое что - может есть что то поэлегантнее... )

https://www.mql5.com/ru/articles/81

типа этого на МТ 4 сделано

// время торгов, заканчивает работу в 22, то есть в 22 часа и после советник не выставляет новых ордеров и ждет рабочего времени в 8 ч
input bool Use_Time=true;
input int HourStart=8; // время начала работы советника в часах по времени терминала - может быть от 0 до 23
input int HourEnd=22; // время окончания работы советника в часах по времени терминала
input int MinStart =30;
input int MinEnd   =40;

....

void OnTick()
  {
    //  ограничение входа в рынок по времени
   bool time_trade=false;
  
   if(Use_Time==false)
     {
      time_trade=true;
     }
   if(Use_Time==true && Hour()>=HourStart && Minute() >= MinStart && Minute() <= MinEnd && Hour() < HourEnd)
     {time_trade=true;}
...
 }
Переход с MQL4 на MQL5
Переход с MQL4 на MQL5
  • www.mql5.com
Данная статья, построенная в форме справочника по функциям MQL4, призвана помочь переходу с MQL4 на MQL5. Для каждой функции языка MQL4 приведено описание и представлен способ ее реализации на MQL5, что позволит вам значительно ускорить перевод своих программ с MQL4 на MQL5. Для удобства функции разбиты на группы, как в документации по MQL4.