//+------------------------------------------------------------------+ //| mmaa.mq5 | //| Copyright 2019, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2019, MetaQuotes Software Corp." #property link "https://www.mql5.com" #include <MovingAverages.mqh> #property version "1.00" #property indicator_buffers 2 //4 #property indicator_plots 2 #property indicator_separate_window #property indicator_label1 "Oscar" #property indicator_type1 DRAW_LINE #property indicator_color1 clrBlue //Blue #property indicator_label2 "Signal" #property indicator_type2 DRAW_LINE #property indicator_color2 clrRed //Red input int iLookBack = 8; input int OscarAve = 5; input int highstop = 3; input int lowstop = 2; //double Y = 0; double Buffer1[]; double Buffer2[]; //double Buffer3[]; //double Buffer4[]; int weights = 0; //+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- indicator buffers mapping SetIndexBuffer(0, Buffer1, INDICATOR_DATA); SetIndexBuffer(1, Buffer2, INDICATOR_DATA); //SetIndexBuffer(2, Buffer3, INDICATOR_CALCULATIONS); //SetIndexBuffer(3, Buffer4, INDICATOR_CALCULATIONS); PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, iLookBack); for (int i = 1; i <= OscarAve; i++) { for (int j = i; j <= OscarAve; j++) weights += 1; } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { //--- //int weights = 1; int start = iLookBack; double Y = 0; if(rates_total < iLookBack) return(0); //if(prev_calculated == 0) start = iLookBack - 1; //else start = prev_calculated - 1; for(int i = start; i < rates_total; i++) { double X = Y; double A = high[ArrayMaximum(high, i - iLookBack + 1, iLookBack)]; double B = low[ArrayMinimum(low, i - iLookBack + 1, iLookBack)]; /*for(int j = i; j + iLookBack > i; j--) { A = MathMax(high[j], A); B = MathMin(low[j], B); }*/ double C = close[i]; double rough = ((C - B) / (A - B)) * 100; Y = (X / 3) * 2 + (rough / 3); Buffer1[i] = Y; //Buffer3[i] = (A + highstop / 10000); //Buffer4[i] = (B - lowstop / 10000); } LinearWeightedMAOnBuffer(rates_total, prev_calculated, iLookBack, OscarAve, Buffer1, Buffer2, weights); return(rates_total); } //+------------------------------------------------------------------+
The second problem was that for the most recent value of the oscar line, the X value was recalculated with every new tick, so now X will be the the value of Y of the previous tick, when it's supposed to be equal to the value of Y of the previous Bar not previous tick.
You solved this problem by calculating the values of the indicator from first bar up to the most recent bar with each new tick, which solves the miscalculation problem, but it has one pitfall, it's inefficient, we don't need to calculate all values with each new tick, we only need to calculate the value of oscar for most recent bar.
So what I did to solve the problem is by making X and Y dynamics array, and for each bar there is a corresponding value of X and Y, so when we want to calculate the value of X[i], we use Y[i-1], by doing that we ensure that the value of X is actually the value of oscar of the previous bar and not the previous tick. and then used prev_calculated like I did in my earlier post.
Anyway your post was absolutely helpful, thanks again
About the weights:
Bar1 1 --> 1
Bar2 11 --> 2
Bar3 111 --> 3
Bar4 1111 --> 4
Bar5 11111 --> 5
The "LWMA" weights are as above when it's "Period" is five. The sum of these weights is the "weights".
I made this into a program as it is, but it can be more easily calculated as "1 + 2 + 3 + 4 + 5".
for (int i = 1; i <= OscarAve; i++) weights += i; /*{ for (int j = i; j <= OscarAve; j++) weights += 1; }*/
About the XY:
"Buffer1[i] = Y;", as you point out, it can be "X = Buffer1[i - 1];".
In this case, the value of Buffer1[i - 1] is already fixed and does not need to be recalculated.
In the end, I can rewrite it as follows. Maybe there will be no problem.
{ //--- int start; if(rates_total < iLookBack) return(0); if(prev_calculated == 0) { start = iLookBack; Buffer1[start - 1] = 0.0; } else start = prev_calculated - 1; for(int i = start; i < rates_total; i++) { double X = Buffer1[i - 1]; double A = high[ArrayMaximum(high, i - iLookBack + 1, iLookBack)]; double B = low[ArrayMinimum(low, i - iLookBack + 1, iLookBack)]; double C = close[i]; double rough = ((C - B) / (A - B)) * 100; Buffer1[i] = (X / 3) * 2 + (rough / 3); } LinearWeightedMAOnBuffer(rates_total, prev_calculated, iLookBack, OscarAve, Buffer1, Buffer2, weights); return(rates_total); }
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hi everyone, so I want to convert the mql4 code of an indicator to mql5 code
The indicator name is Oscar, it's basically a two lines cross indicator, first line is an oscillator and the second line is the moving average of the oscillator.
Here is how the indicator is calculated according to the author of the indicator:
""
let A = the highest high of the last eight days (including today)
let B = the lowest low of the past eight days (including today)
let C = today's closing price
let X = yesterday's oscillator figure (Oscar)
Today's "rough" oscillator equals (C-B) divided by (A-B) times 100.
Next we "smooth" our rough number (let's call it Y) like this:
Y = ((X divided by 3) times 2), plus (rough divided by 3).
Let’s do an example. We’ll use a common stock, United Technology. The program was
originally written for stocks, but works equally well with the Forex market.
Turn to the next page. Go to April 8th. Count back eight days. The high for that period is
91.32 ( just happened to be today). The low is 84.75, made on March 30th (just happened
to be 8 days back). Today's close is 89.80.
Yesterday's oscillator (shown in the second column), is 87.
Today's closing price, 89.80 minus the 8 day low, 84.75, equals 5.05.
The 8 day high, 91.32, minus the 8 day low, 84.75, equals 6.57.
5.05 divided by 6.57 equals 0.769. 0.769 times 100 equals 76.9.
87 divided by 3 equals 29.00. 29.00 times 2 equals 58.00.
76.9 divided by 3 equals 25.63.
58.00 + 25.63 = 83.63, or 84 rounded off.
""
Here is the mql4 code of the indicator I found online
And here is my Attempt to write an mql5 code for the indicator
When I compare the output of the buffers for both the original mql4 version and the version I developed for mql5, the outputs differs slightly, like mql4 version will give value of 80 but mql5 will give 85, but then when it comes to most recent value the mql5 behave weirdly, like it output totally unexpected value, and the moving average line gives very high number like 800 or 900 even though all previous numbers were less than 100.
So can anyone help me, I think the code needs very little tweaking then it will work perfectly, but can't find where is the problem in the code.