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++?
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.
Related
The listed code is from a larger project that I am working on (I deleted almost everything else that wasn't necessary for this posting) that is having some trouble running properly. I found the line that is causing the error but I'm hoping for an explanation as to why this line is causing it.
#include <iostream>
#include <tgmath.h>
using namespace std;
int main() {
const int m = 2; // Number of rows
const int n = 2; // Number of cols
int totalPoss = 0; // Number of unique possibile m X n binary matrices
// 2^(m * n) = the number of unique binary
// combinations of m X n matrices
int stop = pow(2, m * n);
// Error when a = 0, 1 | m = 0 | n = 1
for (int a = 0; a < stop; a++) {
int poss[m][n] = {0}; // 2D Array to store each possible matrix
int nextGen[m][n] = {0}; // 2D Array to store the next generation of cells
int rem[m * n]; // 1D Array to store the binary entries of the poss[m][n]
totalPoss = a;
int hold = a; // Stores the current "possibility number" (i.e when
// a = hold = 1 the binary equivilent of 1 will be stored
// in rem[m * n])
// Generate binary number based on whatever a is at current iteration
int c = 0;
while (hold > 0) {
// storing remainder in binary array
rem[c] = hold % 2;
hold = hold / 2;
c++;
}
cout << "Binary: ";
for (int i = 0; i < (m * n); i++) {
cout << rem[i] << " ";
}
cout << endl << endl;
}
cout << "Total possibilities: " << totalPoss+1 << endl;
return 0;
}
The line in question is line 19, or int nextGen[m][n] = {0};. The program's purpose in this state is to output all possible unique binary numbers of 4 bits. The number to translate to binary is determined by the initial for loop. The number is translated in the while loop and stored in rem[m][n]. This code works fine unless you include line 19. For whatever reason when this 2D array is created the output for 0 and 1 is 1 14 0 0 but outputs correctly for 2-15. My question is why this one (seemingly) unrelated line breaks my code.
Thank you!
rem is not completely initialized. The loop that assigns values only iterates until hold is zero, so it does not set the higher elements. But the loop that prints it always prints n * m elements.
The effect of defining nextGen is incidental. It may affect where rem is placed in memory, resulting in it happening to contain zeroes rather than other bits (and likely you are compiling without optimization).
Initialize rem to all zeroes or change the loop that sets its elements.
So I am working on a very "basic" problem for my c++ class and have encountered some errors. The problem is this
An interesting problem in number theory is sometimes called the “necklace problem.” This problem begins with two single-digit numbers. The next number is obtained by adding the first two numbers together and saving only the ones-digit. This process is repeated until the “necklace” closes by returning to the original two numbers. For example, if the starting numbers are 1 and 8, twelve steps are required to close the “necklace”:
18976392134718
Write a program that asks the user for two starting numbers, and then displays the sequence and the number of steps taken. The program output should look similar to:
Enter first number: 1
Enter ssecond number: 8
18976392134718
Your numbers required 12 steps.
What I have done is this:
` #include <iostream>
using namespace std;
int necklace(){
int firstNumber, secondNumber, total = 0, counter = 10, sumOfTwo, tempOne, tempTwo, count;
// 2 single digit numbers
// add first two numbers and save only one digit
// process keeps going until original numbers are found
cout << "Enter the first number: \n";
cin >> firstNumber;
cout << "Enter the second number: \n";
cin >> secondNumber;
sumOfTwo = firstNumber + secondNumber;
while (sumOfTwo >= 10){
sumOfTwo /= 10;
}
int numbersArray[] = {firstNumber, secondNumber, sumOfTwo};
for(int i = 0; i <= 20; i++){
tempOne = numbersArray[i + 1];
tempTwo = numbersArray[i + 2];
sumOfTwo = tempOne + tempTwo;
while (sumOfTwo >= 10){
sumOfTwo %= 10;
}
numbersArray[i + 3] = sumOfTwo;
total++;
if(tempOne == firstNumber && tempTwo == secondNumber){
break;
}
}
for(int i = 0; i < sizeof(numbersArray); i++){
cout << numbersArray[i];
}
cout << endl << "It took " << total << " steps to finish. \n";
return total;
}
int main() {
necklace();
}
`
The problem I am getting is that it will print out all the numbers except the original 2, for example if I use the example with 1 and 8, it will print out 189763921347 and then crash, when it is supposed to print out 18976392134718 with the 1 and 8 at the end of it. Any suggestions? Thanks!
int numbersArray[] = {firstNumber, secondNumber, sumOfTwo};
with three elements on the right hand side makes it an array of size 3. Meaning with indexes 0, 1 and 2.
The use of higher indexes will result in Undefined Behaviour (UB).
On the other hand:
for(int i = 0; i <= 20; i++){
tempOne = numbersArray[i + 1];
tempTwo = numbersArray[i + 2];
[...]
numbersArray[i + 3] = sumOfTwo;
with i up to 20 (included) indexes this very same array from 0 to 23 for the last line!
Next:
for(int i = 0; i < sizeof(numbersArray); i++){
sizeof(numbersArray) returns the size in bytes of the array:
sizeof(numbersArray) = 3 * sizeof(int)
Higher than 3, the real size of the array.
But, if you intend to print the values but not store them, you don't need an array. You just need to "exchange" the values like:
one two // beginning of loop
___|
| __ new_digit
| |
v v
one two // end of loop
2^15 = 32768 and the sum of its digits is 3 + 2 + 7 + 6 + 8 = 26.
What is the sum of the digits of the number 2^1000?
currently I am working on power digit sum in C++. my program is working properly but it gives inappropriate output.
#include<iostream>
#include<math.h>
using namespace std;
long double calculate(long double n)
{
long double i,j,temp = 0,sum = 0;
while(n != 0)
{
temp = fmod(n,10);
sum = sum + temp;
n = n / 10;
}
return sum;
}
int main()
{
long double i,j,n = 1000,temp = 1,value = 0;
for(i = 1;i <= n;i++)
{
temp = temp * 2;
}
cout << "Multiplication is : " << temp << endl;
value = calculate(temp);
cout.precision(100);
cout << "Sum is : " << value << endl;
return 0;
}
I am getting o/p like this.
Multiplication is : 1.07151e+301
Sum is : 1200.63580205668592182366438692042720504105091094970703125
it shouldn't be in points.it should print in digits.
Representing 2^1000 in binary would take a 1000 bits. Doubles are only 64bits long (long doubles are 80 or 128 bits depending on compiler/architecture). So doubles represent 2^1000 approximately. The input to calculate isn't 2^1000, but rather as close an approximation to it as 80bits allow. That approximation does not contain the lowest digits that calculate would like to sum over.
You can't use any primitive datatype to calculate 2^1000 and later sum of its digits, as its a big number (however, in languages like python and ruby you can do it).
For solving this problem in C/C++, you have to use array (or any other linear data structure like linked list, etc) and apply logic similar to usual pen-paper method of multiplying numbers.
First try to find a bound on number of digits in 2^1000 and then initialize an integer array of size greater than it with all zeroes. Keep the last element to be 1. Now multiply the array (thinking it as a large number such that each digit is in a different cell of the array) with 2, thousand times, taking modulo and carry overs.
Here is the code for above logic:
int ar[303];
int sum =0;
ar[0]=1;
for(int j=1;j<303;j++)
ar[j]=0;
for(int i=1;i<1001;i++)
{
ar[0]=2*ar[0];
for(int k=1;k<303;k++)
ar[k]=2*ar[k] + ar[k-1]/10;
for(int j=0;j<303;j++)
ar[j]=ar[j]%10;
}
for(int i=0;i<303;i++)
sum = sum + ar[i];
cout<<sum;
Hope it helps.
The reason why you are getting your sum with decimal points is because you are dividing a double by 10. This will not result in a clean integer unless the doubles last digit before the decimal point is a zero.
example:
376 / 10 = 37.6
370 / 10 = 37
To solve this change this in your code on line 12:
n = (n-temp)/10;
This will cut the float numbers from your sum at least.
finally i have solved my problem.
#include<iostream>
#include<math.h>
#include<string>
using namespace std;
long double calculate(string n)
{
long double i,j,temp = 0,sum = 0;
for (i = 0;i < n.length();i++)
{
if(n[i] == '.')
{
break;
}
sum = sum + (n[i] - 48);
}
return sum;
}
int main()
{
long double i,j,n = 1000,temp = 1,value = 0;
string str;
temp = pow(2,n);
cout << "Power is : " << temp << endl;
str = to_string(temp);
cout << str << endl;
value = calculate(str);
cout.precision(100);
cout << "Sum is : " << value << endl;
return 0;
}
I want a function that works.
I believe my logic is correct, thus my (vector out of range error) must be coming from the lack of familiarity and using the code correctly.
I do know that there is long code out there for this fairly simple algorithm.
Please help if you can.
Basically, I take the length as the "moving" window as it loops through j to the end of the size of the vector. This vector is filled with stock prices.
If the length equaled 2 for a 2 day moving average for numbers 1 2 3 4. I should be able to output 1.5, 2.5, and 3.5. However, I get an out of range error.
The logic is shown in the code. If an expert could help me with this simple moving average function that I am trying to create that would be great! Thanks.
void Analysis::SMA()
{
double length;
cout << "Enter number days for your Simple Moving Average:" << endl;
cin >> length;
double sum = 0;
double a;
while (length >= 2){
vector<double>::iterator it;
for (int j = 0; j < close.size(); j++){
sum = vector1[length + j - 1] + vector1[length + j - 2];
a = sum / length;
vector2.push_back(a);
vector<double>::iterator g;
for (g = vector2.begin(); g != vector2.end(); ++g){
cout << "Your SMA: " << *g;
}
}
}
}
You don't need 3 loops to calculate a moving average over an array of data, you only need 1. You iterate over the array and keep track of the sum of the last n items, and then just adjust it for each new value, adding one value and removing one each time.
For example suppose you have a data set:
4 8 1 6 9
and you want to calculate a moving average with a window size of 3, then you keep a running total like this:
iteration add subtract running-total output average
0 4 - 4 - (not enough values yet)
1 8 - 12 -
2 1 - 13 13 / 3
3 6 4 15 15 / 3
4 9 8 16 16 / 3
Notice that we add each time, we start subtracting at iteration 3 (for a window size of 3) and start outputting the average at iteration 2 (window size minus 1).
So the code will be something like this:
double runningTotal = 0.0;
int windowSize = 3;
for(int i = 0; i < length; i++)
{
runningTotal += array[i]; // add
if(i >= windowSize)
runningTotal -= array[i - windowSize]; // subtract
if(i >= (windowSize - 1)) // output moving average
cout << "Your SMA: " << runningTotal / (double)windowSize;
}
You can adapt this to use your vector data structure.
Within your outermost while loop you never change length so your function will run forever.
Then, notice that if length is two and closes.size() is four, length + j - 1 will be 5, so my psychic debugging skills tell me your vector1 is too short and you index off the end.
This question has been answered but I thought I'd post complete code for people in the future seeking information.
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<double> vector1 { 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 };
double length;
cout << "Enter number days for your Simple Moving Average:" << endl;
cin >> length;
double sum = 0;
int cnt = 0;
for (int i = 0; i < vector1.size(); i++) {
sum += vector1[i];
cnt++;
if (cnt >= length) {
cout << "Your SMA: " << (sum / (double) length) << endl;
sum -= vector1[cnt - length];
}
}
return 0;
}
This is slightly different than the answer. A 'cnt' variable in introduced to avoid an additional if statement.
i'm buisy learning myself to program and i'm trying to copy a game that i find fun to play to c++ (basicly just for the sake of learning. So if i formulated the question wrong please forgive me.)
Now i have an issue with randomising a 2 dimentional array. The thing is that i manage it partially to get it to work but i just fail to reason how i can make it fully work.
The code:
// Random generate and return nr 2 or 4 on calling this function.
int startValue1(){
srand(time(NULL));
int arrayStart[2] = {2, 4};
int randIndex = rand() % 2;
return arrayStart[randIndex];
}
// Random generate and return nr 4 or 2 on calling this function.
int startValue2(){
srand(time(NULL));
int arrayStart[2] = {4, 2};
int randIndex = rand() % 2;
return arrayStart[randIndex];
}
int tester(){
//generate 2 start values and assign to variables
int a = startValue1();
int b = startValue2();
//initialize 2 dimentional array and add the 2 starting numbers.
int board[4][4] = {{a,0,0,0},
{0,0,0,0},
{0,0,0,0},
{0,0,0,b}
};
// print out the board in console to check/test the function(S).
for(int row = 0; row<4; row++){
for (int column = 0; column<4; column++){
cout << board[row][column] << " ";
}
cout << endl << endl;
}
cout << endl;
//Randomize the elements in the 2 dimentional array.
random_shuffle(board, board +4) ;
//print out the array to console after the board is randomised (for testing/checking only)
for(int row = 0; row<4; row++){
for (int column = 0; column<4; column++){
cout << board[row][column] << " ";
}
cout << endl << endl;
}
}
The output of this looks something like this :
0 0 0 0
0 0 0 0
4 0 0 0
0 0 0 2
The problem is that the elements only arrange verticaly and never horizontally as if the random_shuffle function only works on one dimention.
I did read up on that function but i just fail to see/reason how i can make it work on a 2 dimentional array.
Hopefully someone can give me some pointers or directions to the info on how to solve this.
Personally i thought that it would be best if i just now somehow arrange the elements horizontally and continue from there. But if there is a better solution i'm al open for it ofcourse.
(In case for anyone who wonders: i'm trying to remake the webgame 2048 in c++ and i plan to use this code to initialize the board and make it ready to play.
Most likely it's not the best approach to solve this but i'm trying to tackle one problem at the time and learn from it and just keep redoing the code till it works.)