143 lines
5.5 KiB
MQL5
143 lines
5.5 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| CustomSymbolFilterTicks.mq5 |
|
|
//| Copyright 2022, MetaQuotes Ltd. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2022, MetaQuotes Ltd."
|
|
#property link "https://www.mql5.com"
|
|
#property description "Create specified custom symbol based on current chart's symbol with prunned ticks for faster tests and optimizations."
|
|
#property script_show_inputs
|
|
|
|
//#include "..\..\Include\PRTF.mqh"
|
|
#define PRTF
|
|
#include "..\..\Include\TickFilter.mqh"
|
|
#include "..\..\Include\Timing.mqh"
|
|
#include "..\..\Include\CustomSymbolMonitor.mqh"
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Inputs |
|
|
//+------------------------------------------------------------------+
|
|
input string CustomPath = "MQL5Book\\Part7"; // Custom Symbol Folder
|
|
input datetime _Start; // Start (default: 120 days back)
|
|
input TickFilter::FILTER_MODE Mode = TickFilter::SEQUENCE;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Globals |
|
|
//+------------------------------------------------------------------+
|
|
string CustomSymbol = _Symbol + ".TckFltr" + "-" + EnumToString(Mode);
|
|
const uint DailySeconds = 60 * 60 * 24;
|
|
datetime Start = _Start == 0 ? TimeCurrent() - DailySeconds * 120 : _Start;
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Script program start function |
|
|
//+------------------------------------------------------------------+
|
|
void OnStart()
|
|
{
|
|
bool custom = false;
|
|
if(PRTF(SymbolExist(CustomSymbol, custom)) && custom)
|
|
{
|
|
if(IDYES == MessageBox(StringFormat("Delete existing custom symbol '%s'?", CustomSymbol),
|
|
"Please, confirm", MB_YESNO))
|
|
{
|
|
PRTF(SymbolSelect(CustomSymbol, false));
|
|
PRTF(CustomRatesDelete(CustomSymbol, 0, LONG_MAX));
|
|
PRTF(CustomTicksDelete(CustomSymbol, 0, LONG_MAX));
|
|
PRTF(CustomSymbolDelete(CustomSymbol));
|
|
}
|
|
else
|
|
{
|
|
return;
|
|
}
|
|
}
|
|
|
|
if(IDYES == MessageBox(StringFormat("Create new custom symbol '%s'?", CustomSymbol),
|
|
"Please, confirm", MB_YESNO))
|
|
{
|
|
if(PRTF(CustomSymbolCreate(CustomSymbol, CustomPath, _Symbol)))
|
|
{
|
|
|
|
//PRTF(CustomSymbolSetDouble(CustomSymbol, SYMBOL_TRADE_TICK_VALUE_PROFIT, 1.0));
|
|
|
|
// BUG: some properties are not set as expected, including very important ones:
|
|
// SYMBOL_TRADE_TICK_VALUE, SYMBOL_TRADE_TICK_SIZE, etc. which remain zeros,
|
|
// so we need to edit them "manually"
|
|
SymbolMonitor sm;
|
|
CustomSymbolMonitor csm(CustomSymbol, &sm);
|
|
int props[] = {SYMBOL_TRADE_TICK_VALUE, SYMBOL_TRADE_TICK_SIZE/*,
|
|
SYMBOL_TRADE_TICK_VALUE_PROFIT, SYMBOL_TRADE_TICK_VALUE_LOSS*/};
|
|
const int d1 = csm.verify(props);
|
|
if(d1)
|
|
{
|
|
Print("Number of found descrepancies: ", d1);
|
|
if(csm.verify(props)) // check again
|
|
{
|
|
Alert("Custom symbol can not be created, internal error!");
|
|
return;
|
|
}
|
|
Print("Fixed");
|
|
}
|
|
|
|
CustomSymbolSetString(CustomSymbol, SYMBOL_DESCRIPTION, "Prunned ticks by " + EnumToString(Mode));
|
|
|
|
if(GenerateTickData())
|
|
{
|
|
SymbolSelect(CustomSymbol, true);
|
|
ChartOpen(CustomSymbol, PERIOD_H1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Day-by-day tick data processor |
|
|
//+------------------------------------------------------------------+
|
|
bool GenerateTickData()
|
|
{
|
|
bool result = true;
|
|
datetime from = Start / DailySeconds * DailySeconds; // round up to a day boundary
|
|
ulong read = 0, written = 0;
|
|
uint day = 0;
|
|
const uint total = (uint)((TimeCurrent() - from) / DailySeconds + 1);
|
|
Timing timing;
|
|
MqlTick array[];
|
|
|
|
while(!IsStopped() && from < TimeCurrent())
|
|
{
|
|
Comment(TimeToString(from, TIME_DATE), " ", day++, "/", total,
|
|
" elapsed: ", timing.elapsed(), ", remain: ", timing.remain(day * 1.0f / total));
|
|
|
|
const int r = PRTF(CopyTicksRange(_Symbol, array, COPY_TICKS_ALL,
|
|
from * 1000L, (from + DailySeconds) * 1000L - 1));
|
|
if(r < 0)
|
|
{
|
|
Alert("Error reading ticks at ", TimeToString(from, TIME_DATE));
|
|
result = false;
|
|
break;
|
|
}
|
|
read += r;
|
|
|
|
if(r > 0)
|
|
{
|
|
const int t = PRTF(TickFilter::filter(Mode, array));
|
|
const int w = PRTF(CustomTicksReplace(CustomSymbol,
|
|
from * 1000L, (from + DailySeconds) * 1000L - 1, array));
|
|
if(w <= 0)
|
|
{
|
|
Alert("Error writing custom ticks at ", TimeToString(from, TIME_DATE));
|
|
result = false;
|
|
break;
|
|
}
|
|
written += w;
|
|
}
|
|
from += DailySeconds;
|
|
}
|
|
|
|
if(read > 0)
|
|
{
|
|
PrintFormat("Done ticks - read: %lld, written: %lld, ratio: %.1f%%",
|
|
read, written, written * 100.0 / read);
|
|
}
|
|
Comment("");
|
|
return result;
|
|
}
|
|
//+------------------------------------------------------------------+
|