Какой то баг чтением из файла помогите разобратся

 

Всем привет! Нужна помощь сообщества. Накидал простого копировщика ордеров через файлы, но в какой-то момент читает нулевое значение, хотя на мастер счете ордер не закрывался, а на счете приемнике постоянно идет перезакрытие. Я уже весь мозг сломал как это обойти.

 

//+------------------------------------------------------------------+
//|                                                       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;

     }
  }
//+------------------------------------------------------------------+

 ...

Файлы:
test06.mq4  20 kb
 

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.