Working with files from multiple charts

 

Hi friends,

I'm writing a code in my EA to export the opened orders data from my trading account in a single CSV file. Through the OnTick function, with any new tick comes, the EA checks the file to see whether a newly order has just opened or not, and if there is a new opened order that has not been written into the file, then it writes the newly opened orders and its related data in the CSV file. Suppose that I run this EA on multiple charts with different symbol .

Now my problem is that I'm concerned with a situation that for example the EA on the EURUSD opened the CSV file to read the data to check if an order is written there or not, and simultaneously the EA on the GBPUSD chart needs to open the CSV file and write a newly opened orders data into it. I'm not sure whether the EA on the GBPUSD chart can write the data simultaneously on the CSV file while the file is opened from the other chart for READING its data.

Your kind guidance is highly appreciated,

Best regards,

 
parham.trader: Suppose that I run this EA on multiple charts with different symbol .

You do understand that you can get all open orders from an order select loop? No files are required.

If the file is open for writing(/appending,) all other open attempts will fail until the file closes. If you add the shared read flag, all other write attempts fail. A simple return and retry on the next tick may work, depending on how frequent your read and write attempts are.

The Safest/easiest way is to use a mutex around open/IO/close sequence.
          Prevent EA from opening trades at the same time across two or more pairs? (Steve) - MQL4 programming forum 2016.06.21

 
William Roeder:

Then you have a race condition.

If the file is open for writing, all other open attempts will fail until the file closes. If you add the shared read flag, all other write attempts fail. A simple return and retry on the next tick may work, depending on how frequent you read and write attempts are.

Safest way is to use a mutex.
          Prevent EA from opening trades at the same time across two or more pairs? (Steve) - MQL4 programming forum 2016.06.21

Dear William,

Thank you so much for your kind help and your time,

what if I use the FILE_SHARE_WRITE and FILE_SHARE_READ flags together ? Does it help to overcome the above-mentioned issue so that the EA that is going to write data can write data in the file which was previously opened by another EA for reading its data, at the same time?

 
parham.trader:

Dear William,

Thank you so much for your kind help and your time,

what if I use the FILE_SHARE_WRITE and FILE_SHARE_READ flags together ? Does it help to overcome the above-mentioned issue so that the EA that is going to write data can write data in the file which was previously opened by another EA for reading its data, at the same time?

Not reliable flags, if you need to share a file among multiple charts, use Pipe or Resource.
 
Mohammad Hossein Sadeghi:
Not reliable flags, if you need to share a file among multiple charts, use Pipe or Resource.

Why not reliable ?

If coded properly it can work reliably with any technique. The main difference between the different ways is performance but not reliability.

 
Alain Verleyen:

Why not reliable ?

If coded properly it can work reliably with any technique. The main difference between the different ways is performance but not reliability.

When it comes to multi thread and simultaneous reading and writing, using share open/read flags will still result in file access error. 
 
Mohammad Hossein Sadeghi:
When it comes to multi thread and simultaneous reading and writing, using share open/read flags will still result in file access error. 
Only if it's poorly coded. Pipe and resource, or whatever, can also be poorly coded.
 

Thank you all for your kind guidances.

Alain Verleyen:
Only if it's poorly coded. Pipe and resource, or whatever, can also be poorly coded.

Dear @Alain Verleyen, I actually didn't get what you mean by poorly coded? is there any secret about using FILE_SHARE_WRITE and FILE_SHARE_READ flags together that is not stated within the mql4 documentation?

I assume that the only thing that I need to do is using the above-mentioned flags and the inter-process of reading and writing within a unique file between different EAs that are attached on different charts would be handled thoroughly. Is there anything else that I should be concerned of so that the code work fine with reading and writing file from different EAs? I'd appreciate if you kindly share your precious experience regarding the issue.

Any other recommendation regarding the matter is highly appreciated as well. 

Thanking in advance for your time.

Documentation on MQL5: Constants, Enumerations and Structures / Input/Output Constants / File Opening Flags
Documentation on MQL5: Constants, Enumerations and Structures / Input/Output Constants / File Opening Flags
  • www.mql5.com
CSV file (all its elements are converted to strings of the appropriate type, Unicode or ANSI, and separated by separator). Flag is used in FileOpen(). Shared access for reading from several programs. Flag is used in FileOpen(), but it does not replace the necessity to indicate FILE_WRITE and/or the FILE_READ flag when opening a file. Shared...
 
parham.trader:

Thank you all for your kind guidances.

Dear @Alain Verleyen, I actually didn't get what you mean by poorly coded? is there any secret about using FILE_SHARE_WRITE and FILE_SHARE_READ flags together that is not stated within the mql4 documentation?

I assume that the only thing that I need to do is using the above-mentioned flags and the inter-process of reading and writing within a unique file between different EAs that are attached on different charts would be handled thoroughly. Is there anything else that I should be concerned of so that the code work fine with reading and writing file from different EAs? I'd appreciate if you kindly share your precious experience regarding the issue.

Any other recommendation regarding the matter is highly appreciated as well. 

Thanking in advance for your time.

Post your code if you need coding help. There is no point discussing about code without any code.
 
Alain Verleyen:
Post your code if you need coding help. There is no point discussing about code without any code.

Here is my code that is related to the exporting of deleted orders on CSV files:

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
//---
   export_DeletedOrders_in_file_func();
}

//+------------------------------------------------------------------+
//|               export_DeletedOrders_in_file_func                  |
//+------------------------------------------------------------------+
void export_DeletedOrders_in_file_func()
{
   for(int order_index=OrdersHistoryTotal()-1; order_index>=0; order_index--)
      {
      select_res=OrderSelect(order_index,SELECT_BY_POS,MODE_HISTORY);
      if(select_res==False)
         {
         Print("Unsuccessful select order for order index of ",order_index," due to error #",GetLastError());
         continue;
         }
      else // if order selected successfully
         {
         if(OrderType()<=1) //if the selected order was an OPENED orders which has been CLOSED so we should go for the next order
            continue;
         else //if the selected order was not oepened previously and it was a pending order which was DELETED
            {
            int column_to_check=find_column_index_in_file_func(DeletedOrders_file_directory,"OrderTicket",0);//--- first we need to find the column index of the "OrderTicket" in the file
            if(find_row_index_in_file_func(DeletedOrders_file_directory,IntegerToString(OrderTicket()),column_to_check)>0)//--- If the TicketNumber of selected order is found in the file, then no need to rewrite it and we should go for the next order
               continue;
            else
               write_DeletedOrders_in_file_func(write_data);
            }
         }
      }
}
//+------------------------------------------------------------------+
//|                 write_DeletedOrders_in_file_func                 |
//+------------------------------------------------------------------+
int write_DeletedOrders_in_file_func(int header_or_data)
{
   int result=EMPTY;

   int
   file_open_flags=FILE_READ|FILE_WRITE|FILE_CSV|FILE_SHARE_READ|FILE_SHARE_WRITE,
   file_handle=file_open_func(DeletedOrders_file_directory,file_open_flags);

//--- agar file_open fail shode bashe dige nabayd func edame peyda kone & bayad az func kharej shavim
   if(file_handle==INVALID_HANDLE)
      return(result);

   if(header_or_data==write_header)//--- Write Header in DeletedOrders file
      {
      result=(int)FileWrite(file_handle,
                            "OrderTicket",
                            "OrderSymbol",
                            "OrderOpenTime",
                            "OrderOpenPrice",
                            "OrderType",
                            "OrderDeleteTime",
                            "OrderDeletePrice",
                            "HeighttoOpenPip",
                            "EAName",
                            "AccountLivingType",
                            "AccountNumber",
                            "AccountBroker"
                           );
      }

   else if(header_or_data==write_data)//--- Write Variables in DeletedOrders file
      {
      //--- finding OrderType
      string OrderType_Str=EnumToString(ENUM_order_type(OrderType()));

      //--- finding OrderDeletePrice & HeighttoOpenPip
      double
      OrderDeletePrice=mkt_price,
      HeighttoOpenPip=NULL;
      if(OrderType()==OP_BUYLIMIT || OrderType()==OP_BUYSTOP)
         {
         OrderDeletePrice=mkt_price_to_buy;
         HeighttoOpenPip=MathAbs((OrderOpenPrice()-(mkt_price_to_buy))/_Point)/PointPerPip;
         }
      else if(OrderType()==OP_SELLLIMIT || OrderType()==OP_SELLSTOP)
         {
         OrderDeletePrice=mkt_price_to_sell;
         HeighttoOpenPip=MathAbs((OrderOpenPrice()-(mkt_price_to_sell))/_Point)/PointPerPip;
         }

      result=(int)FileWrite(file_handle,
                            OrderTicket(),
                            OrderSymbol(),
                            OrderOpenTime(),
                            OrderOpenPrice(),
                            OrderType_Str,
                            OrderCloseTime(),
                            OrderDeletePrice,
                            HeighttoOpenPip,
                            WindowExpertName(),
                            AccountLivingType,
                            AccountInfoInteger(ACCOUNT_LOGIN),
                            AccountInfoString(ACCOUNT_COMPANY)
                           );

      }

//--- close the file
   FileClose(file_handle);

   return(result);
}
//+------------------------------------------------------------------+
//|                         file_open_func                           |
//+------------------------------------------------------------------+
int file_open_func(string file_name,int file_open_flags,ENUM_FILE_POSITION pointer_position_origin=SEEK_END,long pointer_position_shift=0,short delimiter=';')
{
   int
   file_handle=INVALID_HANDLE;

   file_handle=FileOpen(file_name,file_open_flags,delimiter);
   if(file_handle==INVALID_HANDLE)
      {
      Print("File ",file_name," can not be opened due to error ",GetLastError());
      return(file_handle);
      }

// Now the file is opened successfully and the pointer position in the file should be set
   FileSeek(file_handle,pointer_position_shift,pointer_position_origin);

   return(file_handle);
}
//+------------------------------------------------------------------+
//|                   find_row_index_in_file_func                    |
//+------------------------------------------------------------------+
int find_row_index_in_file_func(string file_to_check_directory,string value_to_look_for, int specific_column_to_search_in=EMPTY)
{
//--- open the file
   ResetLastError();
   int
   func_result=EMPTY,
   file_open_flags=FILE_READ|FILE_CSV|FILE_SHARE_READ;

   int file_handle=file_open_func(file_to_check_directory,file_open_flags,SEEK_SET,0,',');

   if(file_handle!=INVALID_HANDLE)
      {
      //--- additional variables
      int column_counter=0,row_counter=0;
      string str;
      //--- read data from the file
      while(!FileIsEnding(file_handle))
         {
         //--- read the string
         str=FileReadString(file_handle);

         if(specific_column_to_search_in==EMPTY || (column_counter==specific_column_to_search_in))
            {
            if(str==value_to_look_for)
               {
               func_result=row_counter;
               break;
               }
            }

         if(FileIsLineEnding(file_handle))
            {
            column_counter=0;
            (row_counter)++;
            }
         else
            (column_counter)++;

         }
      //--- close the file
      FileClose(file_handle);
      }
   else
      PrintFormat("Failed to open %s file, Error code = %d",file_to_check_directory,GetLastError());

   return(func_result);
}
//+------------------------------------------------------------------+
//|                find_column_index_in_file_func                    |
//+------------------------------------------------------------------+
int find_column_index_in_file_func(string file_to_check_directory,string value_to_look_for, int specific_row_to_search_in=EMPTY)
{
//--- open the file
   ResetLastError();
   int
   func_result=EMPTY,
   file_open_flags=FILE_READ|FILE_CSV|FILE_SHARE_READ;

   int file_handle=file_open_func(file_to_check_directory,file_open_flags,SEEK_SET,0,',');

   if(file_handle!=INVALID_HANDLE)
      {
      //--- additional variables
      int column_counter=0,row_counter=0;
      string str;
      //--- read data from the file
      while(!FileIsEnding(file_handle))
         {
         //--- read the string
         str=FileReadString(file_handle);

         if(specific_row_to_search_in==EMPTY || (row_counter==specific_row_to_search_in))
            {
            if(str==value_to_look_for)
               {
               func_result=column_counter;
               break;
               }
            }

         if(FileIsLineEnding(file_handle))
            {
            column_counter=0;
            (row_counter)++;
            }
         else
            (column_counter)++;

         }

      //--- close the file
      FileClose(file_handle);
      }
   else
      PrintFormat("Failed to open %s file, Error code = %d",file_to_check_directory,GetLastError());

   return(func_result);
}

I've used it on my EA and attached it on multiple charts but it continuously get an error #5001and error #5004 !

Your kind guidance is highly appreciated.

Thanking in advance,

 
parham.trader:

Hi friends,

I'm writing a code in my EA to export the opened orders data from my trading account in a single CSV file. Through the OnTick function, with any new tick comes, the EA checks the file to see whether a newly order has just opened or not, and if there is a new opened order that has not been written into the file, then it writes the newly opened orders and its related data in the CSV file. Suppose that I run this EA on multiple charts with different symbol .

Now my problem is that I'm concerned with a situation that for example the EA on the EURUSD opened the CSV file to read the data to check if an order is written there or not, and simultaneously the EA on the GBPUSD chart needs to open the CSV file and write a newly opened orders data into it. I'm not sure whether the EA on the GBPUSD chart can write the data simultaneously on the CSV file while the file is opened from the other chart for READING its data.

Your kind guidance is highly appreciated,

Best regards,

create per order csv file withi similar data structure, have a directory watcher service that will combine these cvs files into one..read the target file programatically..this way you could avoid file writing lock in case there is...hope this helps
Reason: