![MQL5 - Language of trade strategies built-in the MetaTrader 5 client terminal](https://c.mql5.com/i/registerlandings/logo-2.png)
You are missing trading opportunities:
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
Registration
Log in
You agree to website policy and terms of use
If you do not have an account, please register
I have written a C++ DLL to calculate an sma using a recursive formula which should update on the completion of a new bar only, and most of the time it works OK. However, occasionally it updates on the newly forming bar and the sma shoots off at a bizarre angle as shown in the screenshot below. Once this has happened the sma updates correctly once the currently forming bar is complete, but this "overshoot" problem remains on the next newly forming bar. Can someone look at my DLL code, also shown below, and point out if there are any bugs in the code? The DLL was compiled with Dev C++ 4.9.9.2, installed on Wine 1.2, and the DLL is run in MetaTrader 4 running under Wine 1.2 on a AMD64 machine running Kubuntu 10.04 LTS.
The code for the DLL is
#ifdef __cplusplus
extern "C" {
#endif
#include "sma_rec.h"
#include <windows.h>
BOOL APIENTRY DllMain (HINSTANCE hInst /* Library instance handle. */,
DWORD reason /* Reason this function is being
called. */,
LPVOID reserved /* Not used. */ )
{
switch (reason)
{
case DLL_PROCESS_ATTACH:
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
/* Returns TRUE on success, FALSE on failure */
return TRUE;
}
#define WIN32_LEAN_AND_MEAN
#define MT4_EXPFUNC __declspec(dllexport)
//+------------------------------------------------------------------+
//| MT4 HISTORY DATA STRUCT |
//+------------------------------------------------------------------+
#pragma pack(push,1)
struct RateInfo { unsigned int ctm; double open; double low; double high;
double close; double vol; };
struct MqlStr { int len; char * string; };
#pragma pack(pop)
MT4_EXPFUNC void _stdcall updateBuffer( RateInfo* Rates, double buffer[],
int Bars, int IndicatorCounted, int ma_period, double internal_calcs[2] )
{
// check if the DLL is being called for the very first time
if ( IndicatorCounted == 0 )
{
// if so, calculate indicator values from the beginning of the array up to
// "current" bar - firstly for buffer[0] to buffer[ma_period - 1] fill the
// buffer with increasing moving average values up to the desired moving
// average period i.e. the second bar in buffer has value of ma_period = 2;
// the third bar in buffer array has value of ma_period = 3 etc.
buffer[0] = Rates[0].close;
buffer[1] = ( Rates[0].close + Rates[1].close ) / 2.0;
for( int ii = 2 ; ii < ma_period ; ii++ )
{
buffer[ii] = ( ( buffer[ii-1] * ii ) / (ii+1) ) + ( Rates[ii].close/(ii+1) );
}
// secondly, after the initial part of the buffer is filled, the rest of the
// buffer is filled using a recursive SMA algorithm. If the SMA were
// calculated by looping over previous bar values there would be ma_period-1
// additions and one division operation per loop of a nested loop. This
// simple recursive algorithm does away with the need for a nested loop
// completely and reduces the number of arithmetic operations to four per
// bar. More importantly, for learning purposes, it will enable code to be
// shown for passing parameters that hold the state of internal calculations
// to and from the DLL.
for( int ii = ma_period ; ii < Bars - 1 ; ii++ )
{
buffer[ii] = ( buffer[ii-1] - (Rates[ii-ma_period].close/ma_period) ) +
( Rates[ii].close/ma_period );
}
// now return the values of the internal calculations to the internal_calcs
// array pending the next call to the DLL
internal_calcs[0] = (Rates[Bars-1-ma_period].close/ma_period); // the value
// to be used in the next SMA calculation
internal_calcs[1] = Bars - 1; // how many indicator values calculated so far
} // end of ( IndicatorCounted = 0 ) if statement for first call of the DLL.
// Once this piece of the code has been run once, on the initial call to the
// DLL, it will never be run again because the condition IndicatedCounted ==
// 0 will never be true again.
// this next piece of code will be evaluated on the second and all subsequent
// calls to the DLL because the condition IndicatorCounted > 0 will always be
// true after the DLL's initial call. Note that the second part of the
// logical AND, namely (Bars - 1) > internal_calcs[1], ensures that the code
// will only run when a bar has completely formed and a new bar has opened.
// This is important to ensure that values contained in the internal_calcs
// array are not overwritten by the constantly changing values of the
// currently forming bar. Note that, as above, this is a recursive SMA
// algorithm so there is no loop.
if ( IndicatorCounted > 0 && (Bars - 1) > internal_calcs[1] ) // evaluates to
// TRUE if there is a new bar
{
buffer[Bars-2] = ( buffer[Bars-3] - internal_calcs[0] ) +
( Rates[Bars-2].close/ma_period ); // calculate new SMA value
internal_calcs[0] = (Rates[Bars-1-ma_period].close/ma_period); // update
// internal_calcs with new value for next SMA calc.
internal_calcs[1] = Bars - 1; // update how many indicator values calculated so
// far
} // end of ( IndicatorCounted > 0 && (Bars - 1) > internal_calcs[1]) if
// statement
} // end of main function call
#ifdef __cplusplus
}
#endif