1. Файловая операция FileReadNumber может вызвать ошибку, в приведенном коде проверки нет. В справке для MQL5 (не для MQL4) по FileReadNumber есть примеры более надежной работы, нежели в приведенном коде.
2. Режим открытия файлов FILE_SHARE_WRITE применяется и в случае master, и в случае slave. Это нехорошо, одновременно править один файл двумя программами - работа огромной сложности. Думаю, master должен открывать файл монопольно, а slave в режиме многопользовательского чтения FILE_SHARE_READ - копий может потребоваться много. Кроме того, открытие на чтение может не пройти сразу, вдруг в этот момент он перезаписывается. Лучше подождать Sleep(10) и попробовать еще раз, или еще так же 10 раз.
3. Инициализация volume_buy=0 не позволяет выявить, что значение не получено из файла, ведь в файле может прийти тот же самый 0. Лучше volume_buy=10000000, а после считывания проверить, обновилось ли значение volume_buy.
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Всем привет! Нужна помощь сообщества. Накидал простого копировщика ордеров через файлы, но в какой-то момент читает нулевое значение, хотя на мастер счете ордер не закрывался, а на счете приемнике постоянно идет перезакрытие. Я уже весь мозг сломал как это обойти.
//| test06.mq4 |
//| Sergey Gritsay |
//| https://www.mql5.com/ru/users/sergey1294 |
//+------------------------------------------------------------------+
#property copyright "Sergey Gritsay"
#property link "https://www.mql5.com/ru/users/sergey1294"
#property version "1.00"
#property strict
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
enum copier_mode
{
master,
slave,
};
input copier_mode mode=master; // Working mode
string rezult;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- create timer
EventSetMillisecondTimer(1);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- destroy timer
EventKillTimer();
if(mode==master)DeleteFile();
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//---
}
//+------------------------------------------------------------------+
//| Timer function |
//+------------------------------------------------------------------+
void OnTimer()
{
//---
if(mode==master)master_file_save();
if(mode==slave)slave_file_scan();
}
//+------------------------------------------------------------------+
void master_file_save()
{
int symbol_total=SymbolsTotal(true);
string symbol=NULL;
string filename=NULL;
string file="_Master.csv";
for(int i=symbol_total-1; i>=0; i--)
{
symbol=SymbolName(i,true);
filename=(string)AccountInfoInteger(ACCOUNT_LOGIN)+"_"+symbol+file;
int orders_total=OrdersTotal();
double volume_b=0;
double volume_s=0;
for(int k=orders_total-1; k>=0; k--)
{
if(!OrderSelect(k,SELECT_BY_POS))continue;
if(OrderSymbol()!=symbol)continue;
if(OrderType()==OP_BUY)volume_b+=OrderLots();
if(OrderType()==OP_SELL)volume_s+=OrderLots();
}
int filehandle=FileOpen(filename,FILE_WRITE|FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_CSV|FILE_UNICODE|FILE_COMMON,';');
if(filehandle!=INVALID_HANDLE)
{
FileWrite(filehandle,volume_b,volume_s);
FileClose(filehandle);
}
}
}
//+------------------------------------------------------------------+
void DeleteFile()
{
string file_name; // переменная для хранения имен файлов
string filter="*"; // фильтр для поиска файлов
long search_handle=FileFindFirst(filter,file_name,FILE_COMMON);
if(search_handle!=INVALID_HANDLE)
{
do
{
//--- сбрасываем значение ошибки
ResetLastError();
//Print("file_name = ",file_name);
if(StringFind(file_name,(string)AccountInfoInteger(ACCOUNT_LOGIN))>=0) FileDelete(file_name,FILE_COMMON);
}
while(FileFindNext(search_handle,file_name) && !IsStopped());
//--- закрываем хэндл поиска
FileFindClose(search_handle);
}
}
//+------------------------------------------------------------------+
void slave_file_scan()
{
int symbol_total=SymbolsTotal(true);
string symbol=NULL;
for(int i=symbol_total-1; i>=0; i--)
{
symbol=SymbolName(i,true);
double volume_buy=0;
double volume_sell=0;
string file_name; // переменная для хранения имен файлов
string filter="*"; // фильтр для поиска файлов
long search_handle=FileFindFirst(filter,file_name,FILE_COMMON);
if(search_handle!=INVALID_HANDLE)
{
do
{
ResetLastError();//--- сбрасываем значение ошибки
if(StringFind(file_name,symbol)>=0)
{
int filehandle=FileOpen(file_name,FILE_READ|FILE_SHARE_WRITE|FILE_SHARE_READ|FILE_CSV|FILE_COMMON,';');
if(filehandle!=INVALID_HANDLE)
{
volume_buy+=FileReadNumber(filehandle);
volume_sell+=FileReadNumber(filehandle);
if(symbol==_Symbol)Print(symbol,": ","volume_buy = ",volume_buy,", volume_sell = ",volume_sell);
FileClose(filehandle);
}
else Print("Ошибка filehandle");
}
}
while(FileFindNext(search_handle,file_name) && !IsStopped());
//--- закрываем хэндл поиска
FileFindClose(search_handle);
}
else Print("Ошибка search_handle");
//if(symbol==_Symbol)
//Print(symbol,": ","volume_buy = ",volume_buy,", volume_sell = ",volume_sell);
CorectionPosition(symbol,volume_buy,volume_sell);
}
}
//+------------------------------------------------------------------+
void CorectionPosition(string symbol,double vb,double vs)
{
double lot=0.0;
double lot_b=LotTotal(symbol,OP_BUY);
double lot_s=LotTotal(symbol,OP_SELL);
//Print(symbol,": ","volume_buy = ",vb,", volume_sell = ",vs,", lot_b = ",lot_b,", lot_s = ",lot_s);
if(lot_b<vb)
{
lot=NormalizeVolume(symbol,MathAbs(vb-lot_b));
Print(symbol,": lot_b<vb: ",lot_b,": ",vb,": lot = ",lot);
OrderOpen(symbol,OP_BUY,lot);
}
if(lot_b>vb)
{
lot=NormalizeVolume(symbol,MathAbs(vb-lot_b));
Print(symbol,": lot_b>vb: ",lot_b,": ",vb,": lot = ",lot);
CloseOrder(symbol,OP_BUY,lot);
}
if(lot_s<vs)
{
lot=NormalizeVolume(symbol,MathAbs(vs-lot_s));
Print(symbol,": lot_s<vs: ",lot_s,": ",vs,": lot = ",lot);
OrderOpen(symbol,OP_SELL,lot);
}
if(lot_s>vs)
{
lot=NormalizeVolume(symbol,MathAbs(vs-lot_s));
Print(symbol,": lot_s>vs: ",lot_s,": ",vs,": lot = ",lot);
CloseOrder(symbol,OP_SELL,lot);
}
}
//+------------------------------------------------------------------+
double LotTotal(string symbol,int type)
{
int total=OrdersTotal();
double lot=0.0;
for(int i=total-1; i>=0; i--)
{
if(!OrderSelect(i,SELECT_BY_POS))continue;
if(OrderSymbol()!=symbol)continue;
if(OrderType()!=type)continue;
lot+=OrderLots();
}
return(lot);
}
//+------------------------------------------------------------------+
double NormalizeVolume(string symbol,double lot)
{
double MinLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN);
double MaxLot=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX);
double volume_step=SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP);
int volume_digits=(int)(MathLog(1.0/volume_step)/MathLog(10.0));
if(lot<MinLot)lot=MinLot;
if(lot>MaxLot)lot=MaxLot;
return(NormalizeDouble(lot,volume_digits));
}
//+------------------------------------------------------------------+
void OrderOpen(string symbol,int type,double volume)
{
double price=0.0;
int digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
if(type==OP_BUY)
{
RefreshRates();
price=NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_ASK),digits);
if(AccountFreeMarginCheck(symbol,type,volume)<=0)
{
//rezult="not enough money";
return;
}
}
if(type==OP_SELL)
{
RefreshRates();
price=NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_BID),digits);
if(AccountFreeMarginCheck(symbol,type,volume)<=0)
{
//rezult="not enough money";
return;
}
}
int Ticket=OrderSend(symbol,type,volume,price,10000,0,0);
if(Ticket>0)
{
//rezult=StringConcatenate(symbol,": open order ",DoubleToString(volume,LotDigits(symbol,volume))," ",StrToType(type)," Ticket:",Ticket);
//Alert(rezult);
}
else
{
int error=GetLastError();
rezult=StringConcatenate(symbol,": error open order №- ",error);
Print(rezult);
}
}
//+------------------------------------------------------------------+
void CloseOrder(string symbol,int type,double volume)
{
double price=0.0;
double lot=0.0;
int total=OrdersTotal();
if(volume<=0)return;
for(int i=total-1; i>=0; i--)
{
if(!OrderSelect(i,SELECT_BY_POS))continue;
if(OrderSymbol()!=symbol)continue;
if(OrderType()!=type)continue;
if(OrderLots()<volume)lot=OrderLots();
if(OrderLots()>=volume)lot=volume;
int digits=(int)SymbolInfoInteger(symbol,SYMBOL_DIGITS);
if(type==OP_BUY) price=NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_BID),digits);
if(type==OP_SELL)price=NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_ASK),digits);
bool res=OrderClose(OrderTicket(),lot,price,10000);
if(!res)Print("Error close order № - ",GetLastError()," : ",OrderTicket()," ",OrderSymbol()," Lot = ",lot);
else break;
}
}
//+------------------------------------------------------------------+
...