Calculating RSI on array from csv file in MQL5?

Levente Csibi  

I have a bunch of csv files in MQL5/Files and a function that reads a csv into an array called output_arr[]. The function prototype is: 

void ReadCsvData(double &output_arr[], string ticker, string column="close")

It works fine and I am able to view close prices (or any other OHLCV values) in the Expert log when running the code. Returning "close" values for "AAPL.csv", i.e. a csv containing Apple stock prices, and as a sanity check, printing the first 10 values, can be achieved as follows:

int OnInit() {
   double output_arr[];
   ReadCsvData(output_arr, "AAPL", "close");
   
   for(int i=0; i<10; i++) {
      Print(i," ", DoubleToString(output_arr[i],2));
   }

   return(INIT_SUCCEEDED);
  }

 Now, my plan is to take output_arr[] (i.e. a double array with close, open, high, low ... prices, or volume) and calculate the Relative Strength Index on that array. Apart from the RSI, I plan to repeat this process on some other indicators as well, both indicators found in the code base and indicators available online in .mq5 format.

I have come across this forum post from 2017 asking a very similar question, albeit the goal there was to create a new indicator. There, OnCalculate() was recommended:

int OnCalculate(const int rates_total,      // size of the price[] array 
                const int prev_calculated,  // bars handled on a previous call 
                const int begin,            // where the significant data start from 
                const double& price[]       // array to calculate 
);

"The parameter price can be specified in indicator's settings dialog as a custom array from other indicator." - quote by Stanislav Korotky on August 20, 2017. 

However, if I understand everything correctly, this method is not entirely applicable to my needs, since I need an EA (not a new indicator file) to do file IO operations and calculate RSI values. I haven't found more specific articles or forum posts that would suit my need, and I'm right now a bit confused as to how a simple EA calculating RSI(14) on a single array could be implemented. Could someone please point me in the right direction, either with a relevant article or a sample code? 

Calculate technical indicator on custom array
Calculate technical indicator on custom array
  • 2017.08.20
  • www.mql5.com
Hello. I'd like to calculate a technical indicator in MQL5 based on the custom values array, i.e...
Tsung Che Kuo  
Levente Csibi:

I have a bunch of csv files in MQL5/Files and a function that reads a csv into an array called output_arr[]. The function prototype is: 

It works fine and I am able to view close prices (or any other OHLCV values) in the Expert log when running the code. Returning "close" values for "AAPL.csv", i.e. a csv containing Apple stock prices, and as a sanity check, printing the first 10 values, can be achieved as follows:

 Now, my plan is to take output_arr[] (i.e. a double array with close, open, high, low ... prices, or volume) and calculate the Relative Strength Index on that array. Apart from the RSI, I plan to repeat this process on some other indicators as well, both indicators found in the code base and indicators available online in .mq5 format.

I have come across this forum post from 2017 asking a very similar question, albeit the goal there was to create a new indicator. There, OnCalculate() was recommended:

"The parameter price can be specified in indicator's settings dialog as a custom array from other indicator." - quote by Stanislav Korotky on August 20, 2017. 

However, if I understand everything correctly, this method is not entirely applicable to my needs, since I need an EA (not a new indicator file) to do file IO operations and calculate RSI values. I haven't found more specific articles or forum posts that would suit my need, and I'm right now a bit confused as to how a simple EA calculating RSI(14) on a single array could be implemented. Could someone please point me in the right direction, either with a relevant article or a sample code? 

if you don't mind i give you advice again.  if this is exclusively for mql5, you might leverage mql5's new feature of "custom symbol". 

inject csv data to a temporary custom symbol and use ordinary iRSI (or other mql5 defined iXXX indicator functions) to ease calculation.

delete that temporary custom symbol at OnDeinit()

below are sample codes.

int prDg=2,rsiHandle,rsiPeriod=14;
string csvSymbol="AAPL";
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   ReadCsvData();//as suggestd at prior thread
///create custom symbol: AAPL
   CustomSymbolCreate(csvSymbol,"");
   SymbolSelect(csvSymbol,true);
   CustomSymbolSetInteger(csvSymbol,SYMBOL_SELECT,false);
   CustomSymbolSetInteger(csvSymbol,SYMBOL_VISIBLE,false);
   CustomSymbolSetInteger(csvSymbol,SYMBOL_DIGITS,prDg);
///fill csv data to MqlRates array
   MqlRates rates[];
   int csvSz=ArraySize(CsvList);
   ArrayResize(rates,csvSz);
   for(int ii=0; ii<csvSz; ii++)//reverse csv array order for custom symbol 
     {
      rates[ii].time=CsvList[csvSz-ii-1].time;
      rates[ii].open=CsvList[csvSz-ii-1].open;
      rates[ii].high=CsvList[csvSz-ii-1].high;
      rates[ii].low=CsvList[csvSz-ii-1].low;
      rates[ii].close=CsvList[csvSz-ii-1].close;
      rates[ii].tick_volume=(int)CsvList[csvSz-ii-1].volume;
     }
   CustomRatesDelete(csvSymbol,0,INT_MAX);//purge the custom symbol data
   CustomRatesUpdate(csvSymbol,rates);//update MqlRates to custom symbol
///
   rsiHandle=iRSI(csvSymbol,Period(),rsiPeriod,PRICE_CLOSE);//which Period() doesn't matter as there's only one period data at that custom symbol
///
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   ArrayFree(CsvList);
///remove custom symbol & release rsi indicator handle
   
SymbolSelect(csvSymbol,false);
   CustomRatesDelete(csvSymbol,0,INT_MAX);
   CustomSymbolDelete(csvSymbol);
   IndicatorRelease(rsiHandle); 
///
  }
void OnTick()
  {
   int indC=5;
   double rsiArr[];
   ArraySetAsSeries(rsiArr,true);
   ArrayResize(rsiArr,indC);
   CopyBuffer(rsiHandle,0,0,indC,rsiArr);
   Print(csvSymbol+" bar0 rsi value: ",DoubleToString(rsiArr[0],2));
  }


if above sample ea is on chart, you might find a new symbol called "AAPL" at MT5 "Market Watch" window.  open "AAPL" chart (regardless chart period) and apply rsi indicator with rsi value=14.

you will see the latest rsi value indeed matches above sample code output.

lippmaje  

This should work, too:

#include <RSIOnArray.mqh>

int OnInit() {
   double output_arr[];
   ReadCsvData(output_arr, "AAPL", "close");
   
   for(int i=0; i<10; i++) {
      Print(i," ", DoubleToString(output_arr[i],2));
   }
   int total=0;
   int period=14;
   int shift=0;
   double rsi=iRSIOnArray(output_arr,total,period,shift);
   Print("rsi: ",rsi);

   return INIT_SUCCEEDED;
  }

https://www.mql5.com/en/code/27478

iRSIOnArray for MT5
iRSIOnArray for MT5
  • www.mql5.com
Header with iRSIOnArray function for use with MQL 4 or 5 code.
Levente Csibi  
Tsungche Kuo:

if you don't mind i give you advice again.  if this is exclusively for mql5, you might leverage mql5's new feature of "custom symbol". 

inject csv data to a temporary custom symbol and use ordinary iRSI (or other mql5 defined iXXX indicator functions) to ease calculation.

delete that temporary custom symbol at OnDeinit()

below are sample codes.


if above sample ea is on chart, you might find a new symbol called "AAPL" at MT5 "Market Watch" window.  open "AAPL" chart (regardless chart period) and apply rsi indicator with rsi value=14.

you will see the latest rsi value indeed matches above sample code output.

@Tsungche Kuo , thank you tremendously, once again, for your truly educative help. I really appreciate it. You have already helped me advance my skills in MQL4/MQL5 so much that I made more progress in the past two weeks, than in the two months before then. Thank you!! 

I managed to incorporate everything into my script and it works like a charm. :) 

Levente Csibi  
lippmaje:

This should work, too:

https://www.mql5.com/en/code/27478

That is very great to be aware of, @lippmaje, thank you very much. This might really be a solution for those only interested in a quick and easy replication of the old RSIOnArray() function. However, for my needs, Tsungche Kuo's reply is more adaptable due to this constraint mentioned in my post: "Apart from the RSI, I plan to repeat this process on some other indicators as well, both indicators found in the code base and indicators available online in .mq5 format." Apart from this, this is still a neat solution and I do appreciate you enlarging my options. :) 

Pluto999  
Levente Csibi #:

@Tsungche Kuo , thank you tremendously, once again, for your truly educative help. I really appreciate it. You have already helped me advance my skills in MQL4/MQL5 so much that I made more progress in the past two weeks, than in the two months before then. Thank you!! 

I managed to incorporate everything into my script and it works like a charm. :) 

Can I have the code I have been searching for something like that for my EA and I have found nothing