forked from airat77786/MQL5Book
88 lines
3.4 KiB
MQL5
88 lines
3.4 KiB
MQL5
//+------------------------------------------------------------------+
| |||
//| ChartCloseIdle.mq5 |
| |||
//| Copyright 2021, MetaQuotes Ltd. |
| |||
//| https://www.mql5.com |
| |||
//+------------------------------------------------------------------+
| |||
#include "..\..\Include\Periods.mqh"
| |||
#include "..\..\Include\MapArray.mqh"
| |||
| |||
#define PUSH(A,V) (A[ArrayResize(A, ArraySize(A) + 1) - 1] = V)
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Script program start function |
| |||
//+------------------------------------------------------------------+
| |||
void OnStart()
| |||
{
| |||
MapArray<string,int> chartCounts;
| |||
ulong duplicateChartIDs[];
| |||
// collect duplicated idle charts
| |||
if(ChartIdleList(chartCounts, duplicateChartIDs))
| |||
{
| |||
for(int i = 0; i < ArraySize(duplicateChartIDs); ++i)
| |||
{
| |||
const ulong id = duplicateChartIDs[i];
| |||
// request the next idle chart to bring to front
| |||
ChartSetInteger(id, CHART_BRING_TO_TOP, true);
| |||
// refresh the windows, so the chart is actually brought to front
| |||
ChartRedraw(id);
| |||
// ask user confirmation for deletion
| |||
const int button = MessageBox(
| |||
"Remove idle chart: "
| |||
+ ChartSymbol(id) + "/" + PeriodToString(ChartPeriod(id)) + "?",
| |||
__FILE__, MB_YESNOCANCEL);
| |||
if(button == IDCANCEL) break;
| |||
if(button == IDYES)
| |||
{
| |||
ChartClose(id);
| |||
}
| |||
}
| |||
}
| |||
else
| |||
{
| |||
Print("No idle charts.");
| |||
}
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Main worker function to collect idle charts |
| |||
//+------------------------------------------------------------------+
| |||
int ChartIdleList(MapArray<string,int> &map, ulong &duplicateChartIDs[])
| |||
{
| |||
// keep enumerating all charts until no more found
| |||
for(long id = ChartFirst(); id != -1; id = ChartNext(id))
| |||
{
| |||
// skip objects with charts
| |||
if(ChartGetInteger(id, CHART_IS_OBJECT)) continue;
| |||
| |||
// obtain main properties of the chart
| |||
const int win = (int)ChartGetInteger(id, CHART_WINDOWS_TOTAL);
| |||
const string expert = ChartGetString(id, CHART_EXPERT_NAME);
| |||
const string script = ChartGetString(id, CHART_SCRIPT_NAME);
| |||
const int objectCount = ObjectsTotal(id);
| |||
| |||
// calculate number of indicators (if any)
| |||
int indicators = 0;
| |||
for(int i = 0; i < win; ++i)
| |||
{
| |||
indicators += ChartIndicatorsTotal(id, i);
| |||
}
| |||
| |||
const string key = ChartSymbol(id) + "/" + PeriodToString(ChartPeriod(id));
| |||
| |||
if(map[key] == 0 // always count first time occurence of symbol/timeframe
| |||
// otherwise count only empty charts:
| |||
|| (indicators == 0 // no indicators
| |||
&& StringLen(expert) == 0 // no expert
| |||
&& StringLen(script) == 0 // no script
| |||
&& objectCount == 0)) // no objects
| |||
{
| |||
const int i = map.inc(key);
| |||
if(map[i] > 1) // duplicate
| |||
{
| |||
PUSH(duplicateChartIDs, id);
| |||
}
| |||
}
| |||
}
| |||
return map.getSize();
| |||
}
| |||
//+------------------------------------------------------------------+
|