forked from rosh/MQL5Book
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;
| |
}
| |
//+------------------------------------------------------------------+
|