Reputation: 1349
I would like to convert a bunch of stock/forex indicators written in MQL4 (.mq4 files) to C++. Previously, I had only been programming in Python and had very little exposure to both MQL4 and C++. Furthermore, I am not at all aware of the ways to go about such a problem, and whether it is even feasible. (Although, worst case scenario, manually recoding them all should definitely be feasible.)
I took a simple indicator, the Simple Moving Average, as an example and started tinkering with it and running it using a C++ compiler. Knowing that the syntax of the two languages is highly similar, I thought this could be a relatively easy process, and even automable to some degree.
Here is the Simple Moving Average script extracted from the .mq4 file available at this link:
MA_Period=5;
void sma()
{
double sum=0;
int i,pos=Bars-ExtCountedBars-1;
//---- initial accumulation
if(pos<MA_Period) pos=MA_Period;
for(i=1;i<MA_Period;i++,pos--)
sum+=Close[pos];
//---- main calculation loop
while(pos>=0)
{
sum+=Close[pos];
ExtMapBuffer[pos]=sum/MA_Period;
sum-=Close[pos+MA_Period-1];
pos--;
}
//---- zero initial bars
if(ExtCountedBars<1)
for(i=1;i<MA_Period;i++) ExtMapBuffer[Bars-i]=0;
}
And here is my C++ implementation, at the moment testing it on a short array arr[]
representing the Close
array in MQL4. Furthermore, I dropped MQL4's Bars
and ExtCountedBars
variables (as I want to run the indicator on static, historical data), and replaced ExtMapBuffer
with an array called output[]
, with equal length as the "price" array arr[]
.
#include <iostream>
using namespace std;
int main()
{
int MA_Period=5;
int arr[20] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
double sum=0;
int i, pos=0;
int output[20];
cout << "Pos: " << pos << endl;
//---- initial accumulation
if(pos<MA_Period) pos=MA_Period;
for(i=1;i<MA_Period;i++,pos--)
sum+=arr[pos];
cout << "Sum of past " << MA_Period << " prices : " << sum << endl;
cout << "Pos = " << pos << endl;
//---- main calculation loop
while(pos>=0)
{
sum+=arr[pos];
output[pos]=sum/MA_Period;
sum-=arr[pos+MA_Period-1];
pos--;
}
for(int j=0;j<sizeof(output)/sizeof(output[0]);j++){
cout << "output[" << j << "] = " << output[j] << endl;
}
return 0;
}
The console output I'm gettign for the output
array values are:
output[0] = 3
output[1] = 4
output[2] = 65535
output[3] = 1
output[4] = 1706671568
output[5] = 32766
output[6] = 4197523
output[7] = 0
output[8] = 2
output[9] = 0
output[10] = 4197613
output[11] = 0
output[12] = 124
output[13] = 0
output[14] = 0
output[15] = 0
output[16] = 4197536
output[17] = 0
output[18] = 4196352
output[19] = 0
which is clearly not correct. I tried retaining as much from the original MQL4 code when converting to C++ but now hit a roadblock as to why the output is massively different from the expected:
output[0] = nan
output[1] = nan
output[2] = nan
output[3] = nan
output[4] = 3
output[5] = 4
output[6] = 5
output[7] = 6
output[8] = 7
output[9] = 8
output[10] = 9
output[11] = 10
output[12] = 11
output[13] = 12
output[14] = 13
output[15] = 14
output[16] = 15
output[17] = 16
output[18] = 17
output[19] = 18
What am I missing / misunderstanding in the process of converting my MQL4 code to C++?
Upvotes: 1
Views: 890
Reputation: 7973
There are several problems with this code. The main issue is your use of indices i
and pos
. In particular, after the initial accumulation, pos
is equal to 1
, so the main calculation loop will only run one iteration before it is done. So only output[1]
gets written to, the rest of the array is uninitialized, and may contain any value.
Also note that array indices in C start at zero. Your initial accumulation loop starts at 1
, which is not what you want.
I would avoid having two variables for indices, and only use one. To initialize sum
, write:
for (int i = 0; i < MA_Period; ++i) {
sum += arr[i];
output[i] = -1;
}
Then to do the remainder write:
for (int i = MA_Period; i < sizeof(output) / sizeof(output[0]); ++i) {
sum += arr[i];
sum -= arr[i - MA_Period];
output[i] = sum / MA_Period;
}
This will give you the expected output. Note that there is no way to get nan
for the first 5 values, as an int
can never be nan
. If you make output
an array of double
it is possible though, for example using this line in the initial loop:
output[i] = 0.0 / 0.0;
As for why the original MQL4 code worked: it initializes pos
to Bars - ExtCountedBars - 1
, whereas you initialized it to 0
in your C++ version.
Upvotes: 2