2026-03-23 12:55:37 +07:00
|
|
|
//+------------------------------------------------------------------+
|
2026-03-23 12:49:42 +07:00
|
|
|
//| Article-15026-MQL5-Trade-History-Visualizer.mq5 |
|
|
|
|
|
//| Copyright 2026, MetaQuotes Ltd. |
|
|
|
|
|
//| https://www.mql5.com |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-03-23 12:55:37 +07:00
|
|
|
#include "PositionsControl.mqh"
|
|
|
|
|
|
|
|
|
|
#define KEY_LEFT 37
|
|
|
|
|
#define KEY_RIGHT 39
|
|
|
|
|
#define KEY_UP 38
|
|
|
|
|
#define KEY_DOWN 40
|
|
|
|
|
|
|
|
|
|
//--- global variables
|
|
|
|
|
CPositionsControl ExtPositions; // Экземпляр класса исторических позиций
|
|
|
|
|
bool ExtChartScroll; // Флаг прокрутки графика
|
|
|
|
|
bool ExtChartHistory; // Флаг отображения торговой истории
|
|
|
|
|
|
2026-03-23 12:49:42 +07:00
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Expert initialization function |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
int OnInit()
|
|
|
|
|
{
|
2026-03-23 12:55:37 +07:00
|
|
|
//--- Запоминаем флаг автопрокрутки графика и отключаем автопрокрутку
|
|
|
|
|
ExtChartScroll=ChartGetInteger(ChartID(), CHART_AUTOSCROLL);
|
|
|
|
|
ChartSetInteger(ChartID(), CHART_AUTOSCROLL, false);
|
2026-03-23 12:49:42 +07:00
|
|
|
|
2026-03-23 12:55:37 +07:00
|
|
|
//--- Запоминаем флаг отображения торговой истории и отключаем показ истории
|
|
|
|
|
ExtChartHistory=ChartGetInteger(ChartID(), CHART_SHOW_TRADE_HISTORY);
|
|
|
|
|
ChartSetInteger(ChartID(), CHART_SHOW_TRADE_HISTORY, false);
|
|
|
|
|
|
|
|
|
|
//--- Создаём список закрытых позиций и выводим в журнал время создания списка
|
|
|
|
|
ulong start=GetTickCount64();
|
|
|
|
|
Print("Reading trade history and creating a list of historical positions");
|
|
|
|
|
ExtPositions.Refresh();
|
|
|
|
|
ulong msec=GetTickCount64()-start;
|
|
|
|
|
PrintFormat("List of historical positions created in %I64u msec", msec);
|
|
|
|
|
//ExtPositions.Print();
|
|
|
|
|
|
|
|
|
|
//--- Если это запуск после смены периода графика - отображаем текущую выбранную позицию
|
|
|
|
|
if(UninitializeReason()==REASON_CHARTCHANGE)
|
|
|
|
|
ExtPositions.ShowCurrent(true);
|
|
|
|
|
//--- иначе - отображаем последнюю закрытую позицию
|
|
|
|
|
else
|
|
|
|
|
ExtPositions.ShowLast(true);
|
|
|
|
|
|
|
|
|
|
//--- Успешно
|
2026-03-23 12:49:42 +07:00
|
|
|
return(INIT_SUCCEEDED);
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Expert deinitialization function |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void OnDeinit(const int reason)
|
|
|
|
|
{
|
2026-03-23 12:55:37 +07:00
|
|
|
//--- Восстанавливаем начальное значение свойства автопрокрутки, торговой истории и удаляем комментарии на графике
|
|
|
|
|
ChartSetInteger(ChartID(), CHART_AUTOSCROLL, ExtChartScroll);
|
|
|
|
|
ChartSetInteger(ChartID(), CHART_SHOW_TRADE_HISTORY, ExtChartHistory);
|
|
|
|
|
Comment("");
|
2026-03-23 12:49:42 +07:00
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| Expert tick function |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void OnTick()
|
|
|
|
|
{
|
|
|
|
|
//---
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| TradeTransaction function |
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
void OnTradeTransaction(const MqlTradeTransaction& trans,
|
|
|
|
|
const MqlTradeRequest& request,
|
|
|
|
|
const MqlTradeResult& result)
|
|
|
|
|
{
|
2026-03-23 12:55:37 +07:00
|
|
|
//--- Если тип транзакции - добавление новой сделки
|
|
|
|
|
if(trans.type==TRADE_TRANSACTION_DEAL_ADD)
|
|
|
|
|
{
|
|
|
|
|
//--- обновляем список позиций и их сделок
|
|
|
|
|
ExtPositions.Refresh();
|
|
|
|
|
|
|
|
|
|
//--- Получаем тикет новой сделки
|
|
|
|
|
ulong deal_ticket=trans.deal;
|
|
|
|
|
|
|
|
|
|
//--- Если тикет не получен, или не удалось получить из свойств сделки способ изменения позиции - уходим
|
|
|
|
|
long entry;
|
|
|
|
|
if(deal_ticket==0 || !HistoryDealGetInteger(deal_ticket, DEAL_ENTRY, entry))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
//--- Если это сделка выхода из позиции - отобразим на графике последнюю закрытую позицию
|
|
|
|
|
if(entry==DEAL_ENTRY_OUT || entry==DEAL_ENTRY_OUT_BY)
|
|
|
|
|
ExtPositions.ShowLast(true);
|
|
|
|
|
}
|
2026-03-23 12:49:42 +07:00
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
|
|
|
//| ChartEvent function |
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-03-23 12:55:37 +07:00
|
|
|
void OnChartEvent(const int id,
|
2026-03-23 12:49:42 +07:00
|
|
|
const long &lparam,
|
|
|
|
|
const double &dparam,
|
|
|
|
|
const string &sparam)
|
|
|
|
|
{
|
2026-03-23 12:55:37 +07:00
|
|
|
//--- Если идентификатор события - нажатие клавиши
|
|
|
|
|
if(id==CHARTEVENT_KEYDOWN)
|
|
|
|
|
{
|
|
|
|
|
//--- Если удерживается клавиша Ctrl
|
|
|
|
|
if(TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL)<0)
|
|
|
|
|
{
|
|
|
|
|
//--- Если прокрутка графика клавишами активна - выключим прокрутку графика клавишами
|
|
|
|
|
if((bool)ChartGetInteger(0, CHART_KEYBOARD_CONTROL))
|
|
|
|
|
ChartSetInteger(0, CHART_KEYBOARD_CONTROL, false);
|
|
|
|
|
|
|
|
|
|
//--- Если нажата клавиша "курсор влево" - отображаем предыдущую закрытую позицию
|
|
|
|
|
if(lparam==KEY_LEFT)
|
|
|
|
|
ExtPositions.ShowPrev(true);
|
|
|
|
|
|
|
|
|
|
//--- Если нажата клавиша "курсор вправо" - отображаем следующую закрытую позицию
|
|
|
|
|
if(lparam==KEY_RIGHT)
|
|
|
|
|
ExtPositions.ShowNext(true);
|
|
|
|
|
|
|
|
|
|
//--- Если нажата клавиша "курсор вверх" - отображаем первую закрытую позицию
|
|
|
|
|
if(lparam==KEY_UP)
|
|
|
|
|
ExtPositions.ShowFirst(true);
|
|
|
|
|
|
|
|
|
|
//--- Если нажата клавиша "курсор вниз" - отображаем последнюю закрытую позицию
|
|
|
|
|
if(lparam==KEY_DOWN)
|
|
|
|
|
ExtPositions.ShowLast(true);
|
|
|
|
|
}
|
|
|
|
|
//--- Если клавиша Ctrl не нажата
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
//--- Если прокрутка графика клавишами не активна - включим прокрутку графика клавишами
|
|
|
|
|
if(!(bool)ChartGetInteger(0, CHART_KEYBOARD_CONTROL))
|
|
|
|
|
ChartSetInteger(0, CHART_KEYBOARD_CONTROL, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Если удерживается клавиша Shift - выводим в комментарии на график описание текущей позиции
|
|
|
|
|
if(TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT)<0)
|
|
|
|
|
Comment(ExtPositions.CurrentSelectedDescription());
|
|
|
|
|
//--- Если клавиша Shift не нажата - проверяем комментарий на графике и стираем, если он не пустой
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if(ChartGetString(ChartID(),CHART_COMMENT)!=NULL)
|
|
|
|
|
Comment("");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//--- Если изменился горизонтальный масштаб графика - отобразим текущую выбранную позицию
|
|
|
|
|
static int scale=-1;
|
|
|
|
|
if(id==CHARTEVENT_CHART_CHANGE)
|
|
|
|
|
{
|
|
|
|
|
int scale_curr=(int)ChartGetInteger(ChartID(), CHART_SCALE);
|
|
|
|
|
if(scale!=scale_curr)
|
|
|
|
|
{
|
|
|
|
|
ExtPositions.ShowCurrent(true);
|
|
|
|
|
scale=scale_curr;
|
|
|
|
|
}
|
|
|
|
|
}
|
2026-03-23 12:49:42 +07:00
|
|
|
}
|
|
|
|
|
//+------------------------------------------------------------------+
|
2026-03-23 12:55:37 +07:00
|
|
|
|