Adwizard/Strategies/HistoryStrategy.mqh

205 lines
16 KiB
MQL5
Raw Permalink Normal View History

2025-04-11 13:28:40 +03:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| HistoryStrategy.mqh |
//| Copyright 2024, Yuriy Bykov |
//| https://www.mql5.com/ru/users/antekov |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Yuriy Bykov"
#property link "https://www.mql5.com/ru/articles/15330"
#property version "1.01"
#include "../Utils/NewBarEvent.mqh"
#include "../Virtual/VirtualStrategy.mqh"
// =45:AK =C6=KE AB>;1F>2 2 8AB>@88 A45;>:
#define DATE 0
#define TYPE 2
#define SYMBOL 3
#define VOLUME 4
#define ENTRY 5
//+------------------------------------------------------------------+
//| ">@3>20O AB@0B538O 2>A?@>872545=8O 8AB>@88 A45;>: |
//+------------------------------------------------------------------+
class CHistoryStrategy : public CVirtualStrategy {
protected:
string m_symbols[]; // !8<2>;K (B>@3>2K5 8=AB@C<5=BK)
string m_history[][15]; // 0AA82 8AB>@88 A45;>: (N AB@>: * 15 AB>;1F>2)
int m_totalDeals; // >;8G5AB2> A45;>: 2 8AB>@88
int m_currentDeal; // "5:CI89 =><5@ A45;:8
CSymbolInfo m_symbolInfo; // 1J5:B 4;O ?>;CG5=8O 8=D>@<0F88 > A2>9AB20E A8<2>;0
public:
CHistoryStrategy(string p_params); // >=AB@C:B>@
virtual void Tick() override; // 1@01>BG8: A>1KB8O OnTick
virtual string operator~() override; // @5>1@07>20=85 >1J5:B0 2 AB@>:C
};
//+------------------------------------------------------------------+
//| >=AB@C:B>@ |
//+------------------------------------------------------------------+
CHistoryStrategy::CHistoryStrategy(string p_params) {
m_params = p_params;
// '8B05< 8<O D09;0 87 ?0@0<5B@>2
string fileName = ReadString(p_params);
// A;8 8<O ?@>G8B0=>, B>
if(IsValid()) {
// @>1C5< >B:@KBL D09; 2 ?0?:5 40==KE
int f = FileOpen(fileName, FILE_READ | FILE_CSV | FILE_ANSI | FILE_SHARE_READ, ',');
// A;8 >B:@KBL =5 ?>;CG8;>AL, B> ?@>1C5< >B:@KBL D09; 87 >1I59 ?0?:8
if(f == INVALID_HANDLE) {
f = FileOpen(fileName, FILE_COMMON | FILE_READ | FILE_CSV | FILE_ANSI | FILE_SHARE_READ, ',');
}
// A;8 =5 ?>;CG8;>AL, B> A>>1I05< >1 >H81:5 8 2KE>48<
if(f == INVALID_HANDLE) {
SetInvalid(__FUNCTION__,
StringFormat("Can't open file %s from common folder %s, error code: %d",
fileName, TerminalInfoString(TERMINAL_COMMONDATA_PATH), GetLastError()));
return;
}
// '8B05< D09; 4> AB@>:8 703>;>2:0 (>1KG=> >=0 84QB ?5@2>9)
while(!FileIsEnding(f)) {
string s = FileReadString(f);
// A;8 =0H;8 AB@>:C 703>;>2:0, B> G8B05< =0720=8O 2A5E AB>;1F>2 =5 A>E@0=OO 8E
if(s == "DATE") {
FOR(14) FileReadString(f);
break;
}
}
// '8B05< >AB0;L=K5 AB@>:8 4> :>=F0 D09;0
while(!FileIsEnding(f)) {
// A;8 <0AA82 4;O E@0=5=8O ?@>G8B0==>9 8AB>@88 70?>;=5=, B> C25;8G8205< 53> @07<5@
if(m_totalDeals == ArraySize(m_history)) {
ArrayResize(m_history, ArraySize(m_history) + 10000, 100000);
}
// '8B05< 15 7=0G5=89 87 >G5@54=>9 AB@>:8 D09;0 2 AB@>:C <0AA820
FOR(15) m_history[m_totalDeals][i] = FileReadString(f);
// A;8 A8<2>; C A45;:8 =5 ?CAB>9, B>
if(m_history[m_totalDeals][SYMBOL] != "") {
// >102;O5< 53> 2 <0AA82 A8<2>;>2, 5A;8 B0:>3> A8<2>;0 B0< 5IQ =5B
ADD(m_symbols, m_history[m_totalDeals][SYMBOL]);
}
// #25;8G8205< AGQBG8: ?@>G8B0==KE A45;>:
m_totalDeals++;
}
// 0:@K205< D09;
FileClose(f);
PrintFormat(__FUNCTION__" | OK: Found %d rows in %s", m_totalDeals, fileName);
// A;8 5ABL ?@>G8B0==K5 A45;:8 :@><5 A0<>9 ?5@2>9 (?>?>;=5=8O AGQB0), B>
if(m_totalDeals > 1) {
// #AB0=02;8205< B>G=K9 @07<5@ 4;O <0AA820 8AB>@88
ArrayResize(m_history, m_totalDeals);
// "5:CI55 2@5<O
datetime ct = TimeCurrent();
PrintFormat(__FUNCTION__" |\n"
"Start time in tester: %s\n"
"Start time in history: %s",
TimeToString(ct, TIME_DATE), m_history[0][DATE]);
// A;8 40B0 =0G0;0 B5AB8@>20=8O 1>;LH5 40BK =0G0;0 8AB>@88, B> A>>1I05< >1 >H81:5
if(StringToTime(m_history[0][DATE]) < ct) {
SetInvalid(__FUNCTION__,
StringFormat("For this history file [%s] set start date less than %s",
fileName, m_history[0][DATE]));
}
}
// !>740Q< 28@BC0;L=K5 ?>78F88 4;O :064>3> A8<2>;0
CVirtualReceiver::Get(GetPointer(this), m_orders, ArraySize(m_symbols));
// 538AB@8@C5< >1@01>BG8: A>1KB8O =>2>3> 10@0 =0 <8=8<0;L=>< B09<D@59<5
FOREACH(m_symbols) IsNewBar(m_symbols[i], PERIOD_M1);
}
}
//+------------------------------------------------------------------+
//| 1@01>BG8: A>1KB8O OnTick |
//+------------------------------------------------------------------+
void CHistoryStrategy::Tick() override {
//---
while(m_currentDeal < m_totalDeals && StringToTime(m_history[m_currentDeal][DATE]) <= TimeCurrent()) {
// !8<2>; A45;:8
string symbol = m_history[m_currentDeal][SYMBOL];
// I5< 8=45:A A8<2>;0 B5:CI59 A45;:8 2 <0AA825 A8<2>;>2
int index;
FIND(m_symbols, symbol, index);
// A;8 =5 =0H;8, B> ?@>?CA:05< B5:CICN A45;:C
if(index == -1) {
m_currentDeal++;
continue;
}
// "8? A45;:8
ENUM_DEAL_TYPE type = (ENUM_DEAL_TYPE) StringToInteger(m_history[m_currentDeal][TYPE]);
// 1J5< B5:CI59 A45;:8
double volume = NormalizeDouble(StringToDouble(m_history[m_currentDeal][VOLUME]), 2);
// A;8 MB> ?>?>;=5=85/A=OB85 A> AGQB0, B> ?@>?CA:05< MBC A45;:C
if(volume == 0) {
m_currentDeal++;
continue;
}
// !>>1I05< 8=D>@<0F8N > ?@>G8B0==>9 A45;:5
PrintFormat(__FUNCTION__" | Process deal #%d: %s %.2f %s",
m_currentDeal, (type == DEAL_TYPE_BUY ? "BUY" : (type == DEAL_TYPE_SELL ? "SELL" : EnumToString(type))),
volume, symbol);
// A;8 MB> A45;:0 =0 ?@>406C, B> 45;05< >1JQ< >B@8F0B5;L=K<
if(type == DEAL_TYPE_SELL) {
volume *= -1;
}
// A;8 28@BC0;L=0O ?>78F8O 4;O A8<2>;0 B5:CI59 A45;:8 >B:@KB0, B>
if(m_orders[index].IsOpen()) {
// >102;O5< 5Q >1J5< : >1JQ<C B5:CI59 A45;:8
volume += m_orders[index].Volume();
// 0:@K205< 28@BC0;L=CN ?>78F8N
m_orders[index].Close();
}
// A;8 >1JQ< ?> B5:CI5<C A8<2>;C =5 @025= 0, B>
if(MathAbs(volume) > 0.00001) {
// B:@K205< 28@BC0;L=CN ?>78F8N =C6=>3> >1JQ<0 8 =0?@02;5=8O
m_orders[index].Open(symbol, (volume > 0 ? ORDER_TYPE_BUY : ORDER_TYPE_SELL), MathAbs(volume));
}
// #25;8G8205< AGQBG8: >1@01>B0==KE A45;>:
m_currentDeal++;
}
}
//+------------------------------------------------------------------+
//| @5>1@07>20=85 >1J5:B0 2 AB@>:C |
//+------------------------------------------------------------------+
string CHistoryStrategy::operator~() {
return StringFormat("%s(%s)", typename(this), m_params);
}
// A2>1>605< 8<5=0 :>=AB0=B
#undef DATE
#undef TYPE
#undef SYMBOL
#undef VOLUME
#undef ENTRY
//+------------------------------------------------------------------+