Article-16952-MQL5-Visual-T.../TradingByHistoryDeals.mq5

646 lines
55 KiB
MQL5
Raw Permalink Normal View History

2026-03-24 13:06:02 +07:00
<EFBFBD><EFBFBD>//+------------------------------------------------------------------+
//| TradingByHistoryDeals.mq5 |
//| Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include "SymbolTrade.mqh"
//+------------------------------------------------------------------+
//| Expert |
//+------------------------------------------------------------------+
//--- input parameters
input string InpTestedSymbol = ""; /* The symbol being tested in the tester */ // "5AB8@C5<K9 A8<2>;
input long InpTestedMagic = -1; /* The magic number being tested in the tester */ // "5AB8@C5<K9 <038:
sinput bool InpShowDataInLog = false; /* Show collected data in the log */ // >:070BL A>1@0==K5 40==K5 A45;>: 2 6C@=0;5
//--- global variables
CSymbolTrade SymbTradeTmp;
SDeal ExtArrayDeals[]={};
CArrayObj ExtListSymbols;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- A;8 A>25B=8: 70?CI5= =5 2 B5AB5@5
if(!MQLInfoInteger(MQL_TESTER))
{
//--- ?>43>B>28< D09; A> 2A5<8 8AB>@8G5A:8<8 A45;:0<8
if(!PreparesDealsHistoryFile(ExtArrayDeals))
return(INIT_FAILED);
//--- @0A?5G0B05< 2 6C@=0;5 2A5 A45;:8 ?>A;5 703@C7:8 8E 87 D09;0
if(InpShowDataInLog)
DealsArrayPrint(ExtArrayDeals);
//--- ?>;CG05< ?5@2CN 10;0=A>2CN A45;:C, A>740Q< B5:AB A>>1I5=8O 2 2K2>48< 53> ?@8 ?><>I8 Alert
SDeal deal=ExtArrayDeals[0];
long leverage=AccountInfoInteger(ACCOUNT_LEVERAGE);
double start_money=deal.profit;
datetime first_time=deal.time;
string start_time=TimeToString(deal.time, TIME_DATE);
string message=StringFormat("Now you can run testing\nInterval: %s - current date\nInitial deposit: %.2f, leverage 1:%I64u", start_time, start_money, leverage);
//--- A>>1I8< 0;5@B>< @5:><5=4C5<K5 ?0@0<5B@K B5AB5@0 AB@0B5389 4;O 70?CA:0 B5AB8@>20=8O
Alert(message);
}
//--- !>25B=8: 70?CI5= 2 B5AB5@5
else
{
//--- ?@>G8B05< 40==K5 87 D09;0 2 <0AA82
ulong file_size=0;
ArrayResize(ExtArrayDeals, 0);
if(!FileReadDealsToArray(ExtArrayDeals, file_size))
{
PrintFormat("Failed to read file \"%s\". Error %d", FILE_NAME, GetLastError());
return(INIT_FAILED);
}
//--- A>>1I8< 2 6C@=0;5 > :>;8G5AB25 ?@>G8B0==KE 109B 87 D09;0 8 > 70?8A8 <0AA820 A45;>:.
PrintFormat("%I64u bytes were read from the file \"%s\" and written to the deals array. A total of %u deals were received", file_size, FILE_NAME, ExtArrayDeals.Size());
}
//--- 7 <0AA820 8AB>@8G5A:8E A45;>: A>740Q< A?8A>: B>@3>2KE >1J5:B>2 ?> A8<2>;0<
if(!CreateListSymbolTrades(ExtArrayDeals, &ExtListSymbols))
{
Print("Errors found while creating symbol list");
return(INIT_FAILED);
}
//--- 0A?5G0B05< 2 6C@=0;5 A>740==K9 A?8A>: A45;>:
SymbolsArrayPrint(&ExtListSymbols);
//--- 1@0B8<AO : :064><C A8<2>;C 4;O =0G0;0 70:0G:8 8AB>@8G5A:8E 40==KE
//--- 8 >B:@KB8O 3@0D8:>2 ?@>B>@3>20==KE A8<2>;>2 2 B5AB5@5 AB@0B5389
datetime array[];
int total=ExtListSymbols.Total();
for(int i=0; i<total; i++)
{
CSymbolTrade *obj=ExtListSymbols.At(i);
if(obj==NULL)
continue;
CopyTime(obj.Symbol(), PERIOD_CURRENT, 0, 1, array);
}
//--- AQ CA?5H=>
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- >G8I05< A>740==K5 A?8A:8 8 <0AA82K
ExtListSymbols.Clear();
ArrayFree(ExtArrayDeals);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//--- @01>B05< B>;L:> 2 B5AB5@5 AB@0B5389
if(!MQLInfoInteger(MQL_TESTER))
return;
//--- 1@010BK205< 2 B5AB5@5 A?8A>: A45;>: 87 D09;0
TradeByHistory(InpTestedSymbol, InpTestedMagic);
}
//+------------------------------------------------------------------+
//| Tester function |
//+------------------------------------------------------------------+
double OnTester(void)
{
//--- ?>AG8B05< 8 25@=Q< >1I55 :>;8G5AB2> >1@01>B0==KE 2 B5AB5@5 A45;>:
double ret=0.0;
int total=ExtListSymbols.Total();
for(int i=0; i<total; i++)
{
CSymbolTrade *obj=ExtListSymbols.At(i);
if(obj!=NULL)
ret+=obj.OnTester();
}
return(ret);
}
//+------------------------------------------------------------------+
//| !>E@0=O5B A45;:8 87 8AB>@88 2 <0AA82 |
//+------------------------------------------------------------------+
int SaveDealsToArray(SDeal &array[], bool logs=false)
{
//--- AB@C:BC@0 A45;:8
SDeal deal={};
//--- 70?@>A8< 8AB>@8N A45;>: 2 8=B5@20;5 A A0<>3> =0G0;0 ?> B5:CI89 <><5=B
if(!HistorySelect(0, TimeCurrent()))
{
Print("HistorySelect() failed. Error ", GetLastError());
return 0;
}
//--- >1I55 :>;8G5AB2> A45;>: 2 A?8A:5
int total=HistoryDealsTotal();
//--- >1@01>B05< :064CN A45;:C
for(int i=0; i<total; i++)
{
//--- ?>;CG05< B8:5B >G5@54=>9 A45;:8 (A45;:0 02B><0B8G5A:8 2K18@05BAO 4;O ?>;CG5=8O 5Q A2>9AB2)
ulong ticket=HistoryDealGetTicket(i);
if(ticket==0)
continue;
//--- A>E@0=O5< B>;L:> 10;0=A>2K5 8 B>@3>2K5 A45;:8
ENUM_DEAL_TYPE deal_type=(ENUM_DEAL_TYPE)HistoryDealGetInteger(ticket, DEAL_TYPE);
if(deal_type!=DEAL_TYPE_BUY && deal_type!=DEAL_TYPE_SELL && deal_type!=DEAL_TYPE_BALANCE)
continue;
//--- A>E@0=O5< A2>9AB20 A45;:8 2 AB@C:BC@5
deal.ticket=ticket;
deal.type=deal_type;
deal.order=HistoryDealGetInteger(ticket, DEAL_ORDER);
deal.entry=(ENUM_DEAL_ENTRY)HistoryDealGetInteger(ticket, DEAL_ENTRY);
deal.reason=(ENUM_DEAL_REASON)HistoryDealGetInteger(ticket, DEAL_REASON);
deal.time=(datetime)HistoryDealGetInteger(ticket, DEAL_TIME);
deal.time_msc=HistoryDealGetInteger(ticket, DEAL_TIME_MSC);
deal.pos_id=HistoryDealGetInteger(ticket, DEAL_POSITION_ID);
deal.volume=HistoryDealGetDouble(ticket, DEAL_VOLUME);
deal.price=HistoryDealGetDouble(ticket, DEAL_PRICE);
deal.profit=HistoryDealGetDouble(ticket, DEAL_PROFIT);
deal.commission=HistoryDealGetDouble(ticket, DEAL_COMMISSION);
deal.swap=HistoryDealGetDouble(ticket, DEAL_SWAP);
deal.fee=HistoryDealGetDouble(ticket, DEAL_FEE);
deal.sl=HistoryDealGetDouble(ticket, DEAL_SL);
deal.tp=HistoryDealGetDouble(ticket, DEAL_TP);
deal.magic=HistoryDealGetInteger(ticket, DEAL_MAGIC);
deal.SetSymbol(HistoryDealGetString(ticket, DEAL_SYMBOL));
deal.SetComment(HistoryDealGetString(ticket, DEAL_COMMENT));
deal.SetExternalID(HistoryDealGetString(ticket, DEAL_EXTERNAL_ID));
deal.digits=(int)SymbolInfoInteger(deal.Symbol(), SYMBOL_DIGITS);
//--- C25;8G8205< <0AA82 8
int size=(int)array.Size();
ResetLastError();
if(ArrayResize(array, size+1, total)!=size+1)
{
Print("ArrayResize() failed. Error ", GetLastError());
continue;
}
//--- A>E@0=O5< 2 <0AA825 A45;:C
array[size]=deal;
//--- 5A;8 @07@5H5=>, 2K2>48< >?8A0=85 A>E@0=Q==>9 A45;:8 2 6C@=0;
if(logs)
DealPrint(deal, i);
}
//--- 2>72@0I05< :>;8G5AB2> A>E@0=Q==KE 2 <0AA825 A45;>:
return (int)array.Size();
}
//+------------------------------------------------------------------+
//| K2>48B A45;:8 87 <0AA820 2 6C@=0; |
//+------------------------------------------------------------------+
void DealsArrayPrint(SDeal &array[])
{
int total=(int)array.Size();
//--- 5A;8 ?5@540= ?CAB>9 <0AA82 - A>>1I05< >1 MB>< 8 2>72@0I05< false
if(total==0)
{
PrintFormat("%s: Error! Empty deals array passed",__FUNCTION__);
return;
}
//---  F8:;5 ?> <0AA82C A45;>: @0A?5G0B05< >?8A0=85 :064>9 A45;:8
for(int i=0; i<total; i++)
{
DealPrint(array[i], i);
}
}
//+------------------------------------------------------------------+
//| >72@0I05B >?8A0=85 B8?0 A45;:8 |
//+------------------------------------------------------------------+
string DealTypeDescription(const ENUM_DEAL_TYPE type)
{
switch(type)
{
case DEAL_TYPE_BUY : return "Buy";
case DEAL_TYPE_SELL : return "Sell";
case DEAL_TYPE_BALANCE : return "Balance";
case DEAL_TYPE_CREDIT : return "Credit";
case DEAL_TYPE_CHARGE : return "Additional charge";
case DEAL_TYPE_CORRECTION : return "Correction";
case DEAL_TYPE_BONUS : return "Bonus";
case DEAL_TYPE_COMMISSION : return "Additional commission";
case DEAL_TYPE_COMMISSION_DAILY : return "Daily commission";
case DEAL_TYPE_COMMISSION_MONTHLY : return "Monthly commission";
case DEAL_TYPE_COMMISSION_AGENT_DAILY : return "Daily agent commission";
case DEAL_TYPE_COMMISSION_AGENT_MONTHLY: return "Monthly agent commission";
case DEAL_TYPE_INTEREST : return "Interest rate";
case DEAL_TYPE_BUY_CANCELED : return "Canceled buy deal";
case DEAL_TYPE_SELL_CANCELED : return "Canceled sell deal";
case DEAL_DIVIDEND : return "Dividend operations";
case DEAL_DIVIDEND_FRANKED : return "Franked (non-taxable) dividend operations";
case DEAL_TAX : return "Tax charges";
default : return "Unknown deal type: "+(string)type;
}
}
//+------------------------------------------------------------------+
//| >72@0I05B >?8A0=85 A?>A>10 87<5=5=8O ?>78F88 |
//+------------------------------------------------------------------+
string DealEntryDescription(const ENUM_DEAL_ENTRY entry)
{
switch(entry)
{
case DEAL_ENTRY_IN : return "Entry In";
case DEAL_ENTRY_OUT : return "Entry Out";
case DEAL_ENTRY_INOUT : return "Entry InOut";
case DEAL_ENTRY_OUT_BY : return "Entry OutBy";
default : return "Unknown entry: "+(string)entry;
}
}
//+------------------------------------------------------------------+
//| >72@0I05B >?8A0=85 A45;:8 |
//+------------------------------------------------------------------+
string DealDescription(SDeal &deal, const int index)
{
string indexs=StringFormat("% 5d", index);
if(deal.type!=DEAL_TYPE_BALANCE)
return(StringFormat("%s: deal #%I64u %s, type %s, Position #%I64d %s (magic %I64d), Price %.*f at %s, sl %.*f, tp %.*f",
indexs, deal.ticket, DealEntryDescription(deal.entry), DealTypeDescription(deal.type),
deal.pos_id, deal.Symbol(), deal.magic, deal.digits, deal.price,
TimeToString(deal.time, TIME_DATE|TIME_MINUTES|TIME_SECONDS), deal.digits, deal.sl, deal.digits, deal.tp));
else
return(StringFormat("%s: deal #%I64u %s, type %s %.2f %s at %s",
indexs, deal.ticket, DealEntryDescription(deal.entry), DealTypeDescription(deal.type),
deal.profit, AccountInfoString(ACCOUNT_CURRENCY), TimeToString(deal.time)));
}
//+------------------------------------------------------------------+
//| >72@0I05B >?8A0=85 A45;:8 |
//+------------------------------------------------------------------+
string DealDescription(CDeal *deal, const int index)
{
string indexs=StringFormat("% 5d", index);
if(deal.TypeDeal()!=DEAL_TYPE_BALANCE)
return(StringFormat("%s: deal #%I64u %s, type %s, Position #%I64d %s (magic %I64d), Price %.*f at %s, sl %.*f, tp %.*f",
indexs, deal.Ticket(), DealEntryDescription(deal.Entry()), DealTypeDescription(deal.TypeDeal()),
deal.PositionID(), deal.Symbol(), deal.Magic(), deal.Digits(), deal.Price(),
TimeToString(deal.Time(), TIME_DATE|TIME_MINUTES|TIME_SECONDS), deal.Digits(), deal.SL(), deal.Digits(), deal.TP()));
else
return(StringFormat("%s: deal #%I64u %s, type %s %.2f %s at %s",
indexs, deal.Ticket(), DealEntryDescription(deal.Entry()), DealTypeDescription(deal.TypeDeal()),
deal.Profit(), AccountInfoString(ACCOUNT_CURRENCY), TimeToString(deal.Time())));
}
//+------------------------------------------------------------------+
//| 0A?5G0BK205B 2 6C@=0;5 40==K5 A45;:8 |
//+------------------------------------------------------------------+
void DealPrint(SDeal &deal, const int index)
{
Print(DealDescription(deal, index));
}
//+------------------------------------------------------------------+
//| B:@K205B D09; 4;O 70?8A8, 2>72@0I05B EM=4; |
//+------------------------------------------------------------------+
bool FileOpenToWrite(int &handle)
{
ResetLastError();
handle=FileOpen(PATH, FILE_WRITE|FILE_BIN|FILE_COMMON);
if(handle==INVALID_HANDLE)
{
PrintFormat("%s: FileOpen() failed. Error %d",__FUNCTION__, GetLastError());
return false;
}
//--- CA?5H=>
return true;
}
//+------------------------------------------------------------------+
//| B:@K205B D09; 4;O GB5=8O, 2>72@0I05B EM=4; |
//+------------------------------------------------------------------+
bool FileOpenToRead(int &handle)
{
ResetLastError();
handle=FileOpen(PATH, FILE_READ|FILE_BIN|FILE_COMMON);
if(handle==INVALID_HANDLE)
{
PrintFormat("%s: FileOpen() failed. Error %d",__FUNCTION__, GetLastError());
return false;
}
//--- CA?5H=>
return true;
}
//+------------------------------------------------------------------+
//| !>E@0=O5B 2 D09; 40==K5 A45;>: 87 <0AA820 |
//+------------------------------------------------------------------+
bool FileWriteDealsFromArray(SDeal &array[], ulong &file_size)
{
//--- 5A;8 ?5@540= ?CAB>9 <0AA82 - A>>1I05< >1 MB>< 8 2>72@0I05< false
if(array.Size()==0)
{
PrintFormat("%s: Error! Empty deals array passed",__FUNCTION__);
return false;
}
//--- >B:@>5< D09; 4;O 70?8A8, ?>;CG8< 53> EM=4;
int handle=INVALID_HANDLE;
if(!FileOpenToWrite(handle))
return false;
//--- ?5@5<5AB8< D09;>2K9 C:070B5;L =0 :>=5F D09;0
bool res=true;
ResetLastError();
res&=FileSeek(handle, 0, SEEK_END);
if(!res)
PrintFormat("%s: FileSeek(SEEK_END) failed. Error %d",__FUNCTION__, GetLastError());
//--- 70?8H5< 40==K5 <0AA820 2 :>=5F D09;0
file_size=0;
res&=(FileWriteArray(handle, array)==array.Size());
if(!res)
PrintFormat("%s: FileWriteArray() failed. Error ",__FUNCTION__, GetLastError());
else
file_size=FileSize(handle);
//--- 70:@K205< D09;
FileClose(handle);
return res;
}
//+------------------------------------------------------------------+
//| 03@C605B 2 <0AA82 40==K5 A45;>: 87 D09;0 |
//+------------------------------------------------------------------+
bool FileReadDealsToArray(SDeal &array[], ulong &file_size)
{
//--- >B:@>5< D09; 4;O GB5=8O, ?>;CG8< 53> EM=4;
int handle=INVALID_HANDLE;
if(!FileOpenToRead(handle))
return false;
//--- ?5@5<5AB8< D09;>2K9 C:070B5;L =0 :>=5F D09;0
bool res=true;
ResetLastError();
//--- ?@>G8B05< 40==K5 87 D09;0 2 <0AA82
file_size=0;
res=(FileReadArray(handle, array)>0);
if(!res)
PrintFormat("%s: FileWriteArray() failed. Error ",__FUNCTION__, GetLastError());
else
file_size=FileSize(handle);
//--- 70:@K205< D09;
FileClose(handle);
return res;
}
//+------------------------------------------------------------------+
//| >43>B02;8205B D09; A> A45;:0<8 8AB>@88 |
//+------------------------------------------------------------------+
bool PreparesDealsHistoryFile(SDeal &deals_array[])
{
//--- A>E@0=8< 2A5 A45;:8 AGQB0 2 <0AA82 A45;>:
int total=SaveDealsToArray(deals_array);
if(total==0)
return false;
//--- 70?8H5< 40==K5 <0AA820 A45;>: 2 D09;
ulong file_size=0;
if(!FileWriteDealsFromArray(deals_array, file_size))
return false;
//--- @0A?5G0B05< 2 6C@=0;5 A:>;L:> A45;>: 1K;> ?@>G8B0=> 8 A>E@0=5=> 2 D09;, ?CBL : D09;C 8 53> @07<5@
PrintFormat("%u deals were saved in an array and written to a \"%s\" file of %I64u bytes in size",
deals_array.Size(), "TERMINAL_COMMONDATA_PATH\\Files\\"+ PATH, file_size);
//--- B5?5@L 4;O ?@>25@:8 ?@>G8B05< 40==K5 87 D09;0 2 <0AA82
ArrayResize(deals_array, 0, total);
if(!FileReadDealsToArray(deals_array, file_size))
return false;
//--- @0A?5G0B05< 2 6C@=0;5 A:>;L:> 109B 1K;> ?@>G8B0=> 87 D09;0 8 :>;8G5AB2> ?>;CG5==KE 2 <0AA82 A45;>:
PrintFormat("%I64u bytes were read from the file \"%s\" and written to the deals array. A total of %u deals were received", file_size, FILE_NAME, deals_array.Size());
return true;
}
//+------------------------------------------------------------------+
//| !>740QB >1J5:B A45;:8 87 AB@C:BC@K |
//+------------------------------------------------------------------+
CDeal *CreateDeal(SDeal &deal_str)
{
//--- A;8 >1J5:B A45;:8 A>740BL =5 C40;>AL - A>>1I05< 2 6C@=0;5 >1 >H81:5 8 2>72@0I05< NULL
CDeal *deal=new CDeal(deal_str.ticket, deal_str.Symbol());
if(deal==NULL)
{
PrintFormat("%s: Error. Failed to create deal object");
return NULL;
}
//--- 70?>;=O5< A2>9AB20 A45;:8 87 ?>;59 AB@C:BC@K
deal.SetOrder(deal_str.order); // @45@, =0 >A=>20=88 :>B>@>3> 1K;0 >B:@KB0 A45;:0
deal.SetPositionID(deal_str.pos_id); // 45=B8D8:0B>@ ?>78F88
deal.SetTimeMsc(deal_str.time_msc); // @5<O 2 <8;;8A5:C=40E
deal.SetTime(deal_str.time); // @5<O
deal.SetVolume(deal_str.volume); // 1JQ<
deal.SetPrice(deal_str.price); // &5=0
deal.SetProfit(deal_str.profit); // @81K;L
deal.SetCommission(deal_str.commission); // ><8AA8O ?> A45;:5
deal.SetSwap(deal_str.swap); // 0:>?;5==K9 A2>? ?@8 70:@KB88
deal.SetFee(deal_str.fee); // ?;0B0 70 ?@>2545=85 A45;:8, =0G8A;O5BAO A@07C ?>A;5 A>25@H5=8O A45;:8
deal.SetSL(deal_str.sl); // #@>25=L Stop Loss
deal.SetTP(deal_str.tp); // #@>25=L Take Profit
deal.SetType(deal_str.type); // "8?
deal.SetEntry(deal_str.entry); // !?>A>1 87<5=5=8O ?>78F88
deal.SetReason(deal_str.reason); // @8G8=0 8;8 8AB>G=8: ?@>2545=8O A45;:8
deal.SetMagic(deal_str.magic); // 45=B8D8:0B>@ M:A?5@B0
deal.SetComment(deal_str.Comment()); // ><<5=B0@89 : A45;:5
deal.SetExternalID(deal_str.ExternalID()); // 45=B8D8:0B>@ A45;:8 2> 2=5H=59 B>@3>2>9 A8AB5<5 (=0 18@65)
//--- >72@0I05< C:070B5;L =0 A>740==K9 >1J5:B
return deal;
}
//+------------------------------------------------------------------+
//| !>740QB <0AA82 8A?>;L7C5<KE A8<2>;>2 |
//+------------------------------------------------------------------+
bool CreateListSymbolTrades(SDeal &array_deals[], CArrayObj *list_symbols)
{
bool res=true; // @57C;LB0B
int total=(int)array_deals.Size(); // >1I55 :>;8G5AB2> A45;>: 2 <0AA825
//--- 5A;8 <0AA82 A45;>: ?CAB>9 - 2>72@0I05< false
if(total==0)
{
PrintFormat("%s: Error! Empty deals array passed",__FUNCTION__);
return false;
}
//--- 2 F8:;5 ?> <0AA82C A45;>:
CSymbolTrade *SymbolTrade=NULL;
for(int i=0; i<total; i++)
{
//--- ?>;CG05< >G5@54=CN A45;:C 8, 5A;8 MB> =5 ?>:C?:0 8 =5 ?@>4060 - 84Q< : A;54CNI59
SDeal deal_str=array_deals[i];
if(deal_str.type!=DEAL_TYPE_BUY && deal_str.type!=DEAL_TYPE_SELL)
continue;
//--- =094Q< B>@3>2K9 >1J5:B 2 A?8A:5, C :>B>@>3> A8<2>; @025= A8<2>;C A45;:8
string symbol=deal_str.Symbol();
SymbTradeTmp.SetSymbol(symbol);
list_symbols.Sort();
int index=list_symbols.Search(&SymbTradeTmp);
//--- 5A;8 8=45:A 8A:><>3> >1J5:B0 2 A?8A:5 @025= -1 - B0:>3> >1J5:B0 2 A?8A:5 =5B
if(index==WRONG_VALUE)
{
//--- A>740Q< =>2K9 B>@3>2K9 >1J5:B A8<2>;0 8, 5A;8 A>740BL =5 ?>;CG8;>AL -
//--- 4>102;O5< : @57C;LB0BC 7=0G5=85 false 8 84Q< : A;54CNI59 A45;:5
SymbolTrade=new CSymbolTrade(symbol);
if(SymbolTrade==NULL)
{
res &=false;
continue;
}
//--- 5A;8 B>@3>2K9 >1J5:B A8<2>;0 =5 C40;>AL 4>1028BL 2 A?8A>: -
//--- C40;O5< 2=>2L A>740==K9 >1J5:B, 4>102;O5< : @57C;LB0BC 7=0G5=85 false
//--- 8 84Q< : A;54CNI59 A45;:5
if(!list_symbols.Add(SymbolTrade))
{
delete SymbolTrade;
res &=false;
continue;
}
}
//--- 8=0G5, 5A;8 B>@3>2K9 >1J5:B C65 ACI5AB2C5B 2 A?8A:5 - ?>;CG05< 53> ?> 8=45:AC
else
{
SymbolTrade=list_symbols.At(index);
if(SymbolTrade==NULL)
continue;
}
//--- 5A;8 B5:CI59 A45;:8 5IQ =5B 2 A?8A:5 A45;>: B>@3>2>3> >1J5:B0 A8<2>;0
if(SymbolTrade.GetDealByTime(deal_str.time)==NULL)
{
//--- A>740Q< >1J5:B A45;:8 ?> 5Q >1@07FC-AB@C:BC@5
CDeal *deal=CreateDeal(deal_str);
if(deal==NULL)
{
res &=false;
continue;
}
//--- : 7=0G5=8N @57C;LB0B0 4>102;O5< @57C;LB0B 4>102;5=8O >1J5:B0 A45;:8 2 A?8A>: A45;>: B>@3>2>3> >1J5:B0 A8<2>;0
res &=SymbolTrade.AddDeal(deal);
}
}
//--- 2>72@0I05< 8B>3>2K9 @57C;LB0B A>740=8O B>@3>2KE >1J5:B>2 8 4>102;5=8O A45;>: 2 8E A?8A:8
return res;
}
//+------------------------------------------------------------------+
//| K2>48B 2 6C@=0; A?8A>: B>@3>2KE >1J5:B>2 A8<2>;>2 |
//+------------------------------------------------------------------+
void SymbolsArrayPrint(CArrayObj *list_symbols)
{
int total=list_symbols.Total();
if(total==0)
return;
Print("Symbols used in trading:");
for(int i=0; i<total; i++)
{
string index=StringFormat("% 3d", i+1);
CSymbolTrade *obj=list_symbols.At(i);
if(obj==NULL)
continue;
PrintFormat("%s. %s",index, obj.Description());
}
}
//+------------------------------------------------------------------+
//| ">@3>2;O ?> 8AB>@88 |
//+------------------------------------------------------------------+
void TradeByHistory(const string symbol="", const long magic=-1)
{
datetime time=0;
int total=ExtListSymbols.Total(); // :>;8G5AB2> B>@3>2KE >1J5:B>2 2 A?8A:5
//--- 2 F8:;5 ?> 2A5< B>@3>2K< >1J5:B0< A8<2>;>2
for(int i=0; i<total; i++)
{
//--- ?>;CG05< >G5@54=>9 B>@3>2K9 >1J5:B
CSymbolTrade *obj=ExtListSymbols.At(i);
if(obj==NULL)
continue;
//--- ?>;CG05< B5:CICN A45;:C, =0 :>B>@CN C:07K205B 8=45:A A?8A:0 A45;>:
CDeal *deal=obj.GetDealCurrent();
if(deal==NULL)
continue;
//--- D8;LB@C5< A45;:C ?> <038:C 8 A8<2>;C
if((magic>-1 && deal.Magic()!=magic) || (symbol!="" && deal.Symbol()!=symbol))
continue;
//--- D8;LB@C5< A45;:C ?> B8?C (B>;L:> A45;:8 ?>:C?:8/?@>4068)
ENUM_DEAL_TYPE type=deal.TypeDeal();
if(type!=DEAL_TYPE_BUY && type!=DEAL_TYPE_SELL)
continue;
//--- 5A;8 MB> C65 >1@01>B0==0O 2 B5AB5@5 A45;:0 - 84Q< : A;54CNI59
if(deal.TicketTester()>0)
continue;
//--- 5A;8 2@5<O A45;:8 5IQ =5 =0AB0;> - 84Q< : A;54CNI5<C B>@3>2><C >1J5:BC A;54CNI53> A8<2>;0
if(!obj.CheckTime(deal.Time()))
continue;
//--- 5A;8 A45;:0 2E>40 2 @K=>:
ENUM_DEAL_ENTRY entry=deal.Entry();
if(entry==DEAL_ENTRY_IN)
{
//--- >B:@K205< ?>78F8N ?> B8?C A45;:8
double sl=0;
double tp=0;
ulong ticket=(type==DEAL_TYPE_BUY ? obj.Buy(deal.Volume(), deal.Magic(), sl, tp, deal.Comment()) :
type==DEAL_TYPE_SELL ? obj.Sell(deal.Volume(),deal.Magic(), sl, tp, deal.Comment()) : 0);
//--- 5A;8 ?>78F8O >B:@KB0 (?>;CG8;8 5Q B8:5B)
if(ticket>0)
{
//--- C25;8G8205< :>;8G5AB2> >1@01>B0==KE B5AB5@>< A45;>: 8 70?8AK205< B8:5B A45;:8 2 B5AB5@5 2 A2>9AB20 >1J5:B0 A45;:8
obj.SetNumProcessedDeals(obj.NumProcessedDeals()+1);
deal.SetTicketTester(ticket);
//--- ?>;CG05< 845=B8D8:0B>@ ?>78F88 2 B5AB5@5 8 70?8AK205< 53> 2 A2>9AB20 >1J5:B0 A45;:8
long pos_id_tester=0;
if(HistoryDealSelect(ticket))
{
pos_id_tester=HistoryDealGetInteger(ticket, DEAL_POSITION_ID);
deal.SetPosIDTester(pos_id_tester);
}
}
}
//--- 5A;8 A45;:0 2KE>40 87 @K=:0
if(entry==DEAL_ENTRY_OUT || entry==DEAL_ENTRY_INOUT || entry==DEAL_ENTRY_OUT_BY)
{
//--- ?>;CG05< A45;:C, =0 >A=>20=88 :>B>@>9 1K;0 >B:@KB0 ?>78F8O
CDeal *deal_in=obj.GetDealInByPosID(deal.PositionID());
if(deal_in==NULL)
continue;
//--- ?>;CG05< B8:5B ?>78F88 2 B5AB5@5 87 A2>9AB2 >B:@K20NI59 A45;:8
//--- 5A;8 B8:5B @025= =C;N, 7=0G8B A:>@55 2A53> ?>78F8O 2 B5AB5@5 C65 70:@KB0
ulong ticket_tester=deal_in.TicketTester();
if(ticket_tester==0)
{
PrintFormat("Could not get position ticket, apparently position #%I64d (#%I64d) is already closed \n", deal.PositionID(), deal_in.PosIDTester());
obj.SetNextDealIndex();
continue;
}
//--- 5A;8 ?>78F8O 70:@KB0 ?> B8:5BC
if(obj.ClosePos(ticket_tester))
{
//--- C25;8G8205< :>;8G5AB2> >1@01>B0==KE B5AB5@>< A45;>: 8 70?8AK205< B8:5B A45;:8 2 B5AB5@5 2 A2>9AB20 >1J5:B0 A45;:8
obj.SetNumProcessedDeals(obj.NumProcessedDeals()+1);
deal.SetTicketTester(ticket_tester);
}
}
//--- 5A;8 B5?5@L 2 >1J5:B5 A45;:8 70?8A0= B8:5B - 7=0G8B A45;:0 CA?5H=> >1@01>B0=0 -
//--- CAB0=02;8205< 8=45:A A45;:8 2 A?8A:5 =0 A;54CNICN A45;:C
if(deal.TicketTester()>0)
{
obj.SetNextDealIndex();
}
}
}
//+------------------------------------------------------------------+