How to export to a CSV file from an Existent MT4 Indicator code

4.2k views Asked by At

I would like to export the results to a CSV file. This is the iExposure Indicator (iExposure.mq4) from MT4. Currently there is now way that I know how to export the values to CSV

This is the code i tried to use which could export to CSV.

int h1;
h1 = FileOpen("data3.csv", FILE_CSV | FILE_WRITE | FILE_READ, ',');
FileSeek( ExtSymbolsSummaries[i][DEALS]=0, ExtSymbolsSummaries[i],

 [BUY_PRICE]=0,ExtSymbolsSummaries[i][SELL_LOTS]=0 ,ExtSymbolsSummaries[i]  
[SELL_PRICE]=0,ExtSymbolsSummaries[i][NET_LOTS]=0, ExtSymbolsSummaries[i][PROFIT]=0, SEEK_END);
FileWrite(h1, Symbols[i]=SymbolName, ExtSymbolsSummaries[i][DEALS]=0, ExtSymbolsSummaries[i]
[BUY_PRICE]=0,ExtSymbolsSummaries[i][SELL_LOTS]=0 ,ExtSymbolsSummaries[i]  
[SELL_PRICE]=0,ExtSymbolsSummaries[i][NET_LOTS]=0, ExtSymbolsSummaries[i][PROFIT]=0 );
FileClose(h1)

This is the original code :

     //+------------------------------------------------------------------+
//|                                                    iExposure.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"

#property indicator_separate_window
#property indicator_buffers 1
#property indicator_minimum 0.0
#property indicator_maximum 0.1

#define SYMBOLS_MAX 1024
#define DEALS          0
#define BUY_LOTS       1
#define BUY_PRICE      2
#define SELL_LOTS      3
#define SELL_PRICE     4
#define NET_LOTS       5
#define PROFIT         6

extern color ExtColor=LightSeaGreen;

string ExtName="Exposure";
string ExtSymbols[SYMBOLS_MAX];
int    ExtSymbolsTotal=0;
double ExtSymbolsSummaries[SYMBOLS_MAX][7];
int    ExtLines=-1;
string ExtCols[8]={"Symbol",
                   "Deals",
                   "Buy lots",
                   "Buy price",
                   "Sell lots",
                   "Sell price",
                   "Net lots",
                   "Profit"};
int    ExtShifts[8]={ 10, 80, 130, 180, 260, 310, 390, 460 };
int    ExtVertShift=14;
double ExtMapBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void init()
  {
    IndicatorShortName(ExtName);
   SetIndexBuffer(0,ExtMapBuffer);
   SetIndexStyle(0,DRAW_NONE);
   IndicatorDigits(0);
    SetIndexEmptyValue(0,0.0);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void deinit()
  {
   int windex=WindowFind(ExtName);
   if(windex>0) ObjectsDeleteAll(windex);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
void start()
  {
   string name;
   int    i,col,line,windex=WindowFind(ExtName);
//----
   if(windex<0) return;
//---- header line
   if(ExtLines<0)
     {
      for(col=0; col<8; col++)
        {
         name="Head_"+col;
         if(ObjectCreate(name,OBJ_LABEL,windex,0,0))
           {
            ObjectSet(name,OBJPROP_XDISTANCE,ExtShifts[col]);
            ObjectSet(name,OBJPROP_YDISTANCE,ExtVertShift);
            ObjectSetText(name,ExtCols[col],9,"Arial",ExtColor);
           }
        }
      ExtLines=0;
     }
//----
   ArrayInitialize(ExtSymbolsSummaries,0.0);
   int total=Analyze();
   if(total>0)
     {
      line=0;
      for(i=0; i<ExtSymbolsTotal; i++)
        {
         if(ExtSymbolsSummaries[i][DEALS]<=0) continue;
         line++;
         //---- add line
         if(line>ExtLines)
           {
            int y_dist=ExtVertShift*(line+1)+1;
            for(col=0; col<8; col++)
              {
               name="Line_"+line+"_"+col;
               if(ObjectCreate(name,OBJ_LABEL,windex,0,0))
                 {
                  ObjectSet(name,OBJPROP_XDISTANCE,ExtShifts[col]);
                  ObjectSet(name,OBJPROP_YDISTANCE,y_dist);
                 }
              }
            ExtLines++;
           }
         //---- set line
         int    digits=MarketInfo(ExtSymbols[i],MODE_DIGITS);
         double buy_lots=ExtSymbolsSummaries[i][BUY_LOTS];
         double sell_lots=ExtSymbolsSummaries[i][SELL_LOTS];
         double buy_price=0.0;
         double sell_price=0.0;
         if(buy_lots!=0)  buy_price=ExtSymbolsSummaries[i][BUY_PRICE]/buy_lots;
         if(sell_lots!=0) sell_price=ExtSymbolsSummaries[i][SELL_PRICE]/sell_lots;
         name="Line_"+line+"_0";
         ObjectSetText(name,ExtSymbols[i],9,"Arial",ExtColor);
         name="Line_"+line+"_1";
         ObjectSetText(name,DoubleToStr(ExtSymbolsSummaries[i][DEALS],0),9,"Arial",ExtColor);
         name="Line_"+line+"_2";
         ObjectSetText(name,DoubleToStr(buy_lots,2),9,"Arial",ExtColor);
         name="Line_"+line+"_3";
         ObjectSetText(name,DoubleToStr(buy_price,digits),9,"Arial",ExtColor);
         name="Line_"+line+"_4";
         ObjectSetText(name,DoubleToStr(sell_lots,2),9,"Arial",ExtColor);
         name="Line_"+line+"_5";
         ObjectSetText(name,DoubleToStr(sell_price,digits),9,"Arial",ExtColor);
         name="Line_"+line+"_6";
         ObjectSetText(name,DoubleToStr(buy_lots-sell_lots,2),9,"Arial",ExtColor);
         name="Line_"+line+"_7";
         ObjectSetText(name,DoubleToStr(ExtSymbolsSummaries[i][PROFIT],2),9,"Arial",ExtColor);
        }
     }
//---- remove lines
   if(total<ExtLines)
     {
      for(line=ExtLines; line>total; line--)
        {
         name="Line_"+line+"_0                                    ";
         ObjectSetText(name,"");
         name="Line_"+line+"_1";
         ObjectSetText(name,"");
         name="Line_"+line+"_2";
         ObjectSetText(name,"");
         name="Line_"+line+"_3";
         ObjectSetText(name,"");
         name="Line_"+line+"_4";
         ObjectSetText(name,"");
         name="Line_"+line+"_5";
         ObjectSetText(name,"");
         name="Line_"+line+"_6";
         ObjectSetText(name,"","                       ");
         name="Line_"+line+"_7";
         ObjectSetText(name,"","                           ");
        }
     }
//---- to avoid minimum==maximum
   ExtMapBuffer[Bars-1]=-1;
//----
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int Analyze()
  {
   double profit;
   int    i,index,type,total=OrdersTotal();
//----
   for(i=0; i<total; i++)
     {
      if(!OrderSelect(i,SELECT_BY_POS)) continue;
      type=OrderType();
      if(type!=OP_BUY && type!=OP_SELL) continue;
      index=SymbolsIndex(OrderSymbol());
      if(index<0 || index>=SYMBOLS_MAX) continue;
      //----
      ExtSymbolsSummaries[index][DEALS]++;
      profit=OrderProfit()+OrderCommission()+OrderSwap();
      ExtSymbolsSummaries[index][PROFIT]+=profit;
      if(type==OP_BUY)
        {
         ExtSymbolsSummaries[index][BUY_LOTS]+=OrderLots();
         ExtSymbolsSummaries[index][BUY_PRICE]+=OrderOpenPrice()*OrderLots();
        }
      else
        {
         ExtSymbolsSummaries[index][SELL_LOTS]+=OrderLots();
         ExtSymbolsSummaries[index][SELL_PRICE]+=OrderOpenPrice()*OrderLots();
        }
     }
//----
   total=0;
   for(i=0; i<ExtSymbolsTotal; i++)
     {
      if(ExtSymbolsSummaries[i][DEALS]>0) total++;
     }
//----
   return(total);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int SymbolsIndex(string SymbolName)
  {
   bool found=false;
//----
   for(int i=0; i<ExtSymbolsTotal; i++)
     {
      if(SymbolName==ExtSymbols[i])
        {
         found=true;
         break;
        }
     }
//----
   if(found) return(i);
   if(ExtSymbolsTotal>=SYMBOLS_MAX) return(-1);
//----
   i=ExtSymbolsTotal;
   ExtSymbolsTotal++;
   ExtSymbols[i]=SymbolName;
   ExtSymbolsSummaries[i][DEALS]=0;
   ExtSymbolsSummaries[i][BUY_LOTS]=0;
   ExtSymbolsSummaries[i][BUY_PRICE]=0;
   ExtSymbolsSummaries[i][SELL_LOTS]=0;
   ExtSymbolsSummaries[i][SELL_PRICE]=0;
   ExtSymbolsSummaries[i][NET_LOTS]=0;
   ExtSymbolsSummaries[i][PROFIT]=0;




//----
   return(i);
  }



//+------------------------------------------------------------------+

END of Code

1

There are 1 answers

0
Jason Ausborn On BEST ANSWER

CSV Output Example:

For this example, I will be describing a way to achieve the following:

  1. Add input strings for the Folder and CSV File names.
  2. Create a Button for generating the CSV.
  3. Listen for Events so that we can detect when the button has been clicked.
  4. Parse the Objects list and write the name and description from objects to CSV file.

Note: If you are unable to complete step 2, skip to step 3, and look at the code inside the OnChartEvent(), then customize it for when you want to write the CSV file. However, be aware that it will be a lot of file writing if you are writing the file every time the OnCalculate() Event occurs.

Since iExposure.mq4 comes available by default (at least for version: 4.0 Build 765), let's start by creating a duplicate of the original. I named my example as iExposureTest.

Step 1: Add the input strings for our Folder and CSV File.

This is one of our easiest steps, just add the input strings for our Folder and CSV file. I added these next to the other input variable.

//Step 1
input string  InputFileName="iExposure.csv";      // File name
input string  InputDirectoryName="Data";     // Folder name

Step 2: Create the CSV button.

Include the header for ChartObjectPanel.mqh. I chose to place my include line directly above the input variables.

//Part of Step 2
#include <ChartObjects\ChartObjectPanel.mqh>

This gives us access for creating a CChartObjectButton type, and we will need to access the button Globally for this example, so add this next line of code before OnInit().

//Part of Step 2
CChartObjectButton CSVButton;

We have a button type of CChartObjectButton, but it's not instantiated yet. Let's do that with a function that we call from OnInit().

Inside OnInit(), add this below:

//Part of Step 2
CreateCSVButton(0);

Now we need the actual function, so at the end of the indicator code let's add this function next.

//Part of Step 2
bool CreateCSVButton(const long chart_ID=0)
{ 
     //--- reset the error value
     ResetLastError();

     //--- set property values
     if(!CSVButton.Create(0,"CSVButton",0,10,25,75,15))
     {
         //--- display the error message in Experts journal
         Print(__FUNCTION__+", Error Code = ",GetLastError());
         return(false);
     }

     CSVButton.Description("CSV");

     CSVButton.FontSize(10);
     CSVButton.Corner(CORNER_LEFT_LOWER);
     CSVButton.Anchor(ANCHOR_CENTER);

     CSVButton.State(false);

     return true;
} 

At this point, when we compile there should be a CSV button available on the window. This was mainly created so we can generate the CSV from a click. It should look similar to the image below.

CSV Button

If you have the CSV button, then we are finished with Step 2.

Step 3: Listen for Events and capture that the CSV button was clicked.

We are able to capture the event we need by using the built in OnChartEvent().

In our OnChartEvent(), we are checking if the event was a CHARTEVENT_OBJECT_CLICK event, then if the sparam equals our CSVButton and the button state is true, we do our file work.

Also, notice that we call the function WriteCSVObjects that doesn't exist yet which we pass the file_handle to. We will create that in step 4.

  //step 3
  void OnChartEvent(const int id,
                    const long &lparam,
                    const double &dparam,
                    const string &sparam)
    {

     if(id==CHARTEVENT_OBJECT_CLICK)
       {  
           if (sparam=="CSVButton") 
           {
              if(CSVButton.State() == true)
              {

                 ResetLastError();

                 int file_handle=FileOpen(InputDirectoryName+"//"+InputFileName,FILE_READ|FILE_WRITE|FILE_CSV);

                 if(file_handle!=INVALID_HANDLE)
                 {
                    PrintFormat("%s file is available for writing",InputFileName);
                    PrintFormat("File path: %s\\Files\\",TerminalInfoString(TERMINAL_DATA_PATH));

                    //Call Step 4  
                    WriteCSVObjects(file_handle);   

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

                    PrintFormat("Data is written, %s file is closed",InputFileName);

                 }
                 else
                 {
                    PrintFormat("Failed to open %s file, Error code = %d",InputFileName,GetLastError());
                 }

              }

              ChartRedraw();
           }

       }
    }

Step 4: Parse the Objects list and write the name and description to CSV.

Almost there! This is the final part to solve your question. Add this function to the end of our code example.

  //Step 4
  void WriteCSVObjects(int file_hand)
  {
     int obj_total=ObjectsTotal();
     string name;
     string desc;

     for(int i=obj_total;i>=0;i--)
      {
        name = ObjectName(i);
        desc = ObjectDescription(name);

        if(name == "")
        {
         name = "Empty Name";
        }

        if(desc == "")
        {
         desc = "Empty Desc";
        }
        FileWrite(file_hand, name + "," + desc);    
      }
  }

In the above function, notice we are looping the objects and writing out the name and description for each object. The order of the output and objects may not be what your goal is, so modify accordingly.

At this point, when we compile and click the CSV button, it should generate the values to a CSV file stored at Files//Data//iExposure.csv.