MQL4 iCustom return Empty value for some buffers but not all
MQL4 iCustom return Empty value for some buffers but not all
Loading saved threads...
Infinity Cliff · External communityPost link
External question — Stack Overflow Stack Exchange
Author: Infinity Cliff
Original post: https://stackoverflow.com/questions/79682030
License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/
Adaptation: HTML converted to plain text; contact email addresses removed.
I have the following indicator, that compiles and shows the arrows properly when attached to a chart. When I try to use iCustom to get values from the indicator buffers I get the empty value for the buffers that are calculated in the if (
ExtBULLBuffer
,
ExtBEARBuffer
and
PatternID
). Note as a test i added the
ExtBULLBuffer
calc and set it to
close
price to check. To show what I mean I have added a sample EA below that print out the values on each new bar. Why is it doing this?
#property description "Sample indicator that plots ALL Candle Pattern arrows."
#property version "1.0"
#property strict
//---- Indicator drawing and buffers
#property indicator_chart_window
#property indicator_buffers 6
#property indicator_color1 clrDodgerBlue
#property indicator_color2 clrOrange
#property indicator_width1 2
#property indicator_width2 2
int ARROW_OFFSET = 30; // Offset of Arrow from price (PIPS)
bool ENGULFING = true; // Engulfing Patterns (Bull & Bear)
int TREND_PERIOD = 50; // Period to determine up and down trend entering pattern
ENUM_MA_METHOD TREND_MA_METHOD = MODE_SMA; // MA method for trend
//---- Buffer Arrays
double ExtBULLBuffer[];
double ExtBEARBuffer[];
double PatternID[];
double C_Body[];
double C_BodyAvg[];
double C_Price[];
double C_VolAve[];
int pattern_length = 4;
int Body_len = 5;
string Bull_index_name = "Candle Pattern Bull";
string Bear_index_name = "Candle Pattern Bear";
// Technical Indicator Page 362 Figure 16.29 Figure 16.30
//+------------------------------------------
//| Custom indicator initialization function
//+------------------------------------------
int OnInit()
{
IndicatorShortName("Candle Patterns");
IndicatorDigits(Digits);
IndicatorBuffers(6);
// First buffer
SetIndexBuffer (0, ExtBULLBuffer); // Assign buffer array
SetIndexStyle (0, DRAW_ARROW); // Style to arrow
SetIndexArrow (0, 233); // Arrow code
SetIndexLabel (0, Bull_index_name);
SetIndexEmptyValue(0,-1.0);
//Second buffer
SetIndexBuffer (1, ExtBEARBuffer); // Assign buffer array
SetIndexStyle (1, DRAW_ARROW); // Style to arrow
SetIndexArrow (1, 234); // Arrow code
SetIndexLabel (1, Bear_index_name);
SetIndexEmptyValue(1,-1.0);
//PatternID Buffer
SetIndexBuffer (2, PatternID); // Assign buffer array
SetIndexStyle (2, DRAW_NONE); // Style to arrow
SetIndexLabel (2, "Pattern ID");
SetIndexEmptyValue(2, 0.0);
SetIndexBuffer (3, C_Body); // Assign buffer array
SetIndexStyle (3, DRAW_NONE); // Style to arrow
SetIndexLabel (3, "C_Body");
SetIndexEmptyValue(3, 0.0);
SetIndexBuffer (4, C_BodyAvg); // Assign buffer array
SetIndexStyle (4, DRAW_NONE); // Style to arrow
SetIndexLabel (4, "C_BodyAvg");
SetIndexEmptyValue(4, 0.0);
SetIndexBuffer (5, C_Price); // Assign buffer array
SetIndexStyle (5, DRAW_NONE); // Style to arrow
SetIndexLabel (5, "C_Price");
SetIndexEmptyValue(5, 0.0);
return(0);
}
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 limit = rates_total-prev_calculated-TREND_PERIOD-1;
if ( limit < 5 )
limit = 5;
int i;
i = limit;
while ( i >= 0 ) {
C_Body[i] = Body(i, open, close);
C_BodyAvg[i] = BodyAvg(i, open, close);
i--; }
i = 0;
while ( i <= limit ) {
C_Price[i] = close[i];
// Bull Patterns -----------------------------------------------------------------------------------------------
if( EngulfingBull(i, open, low, close) ) {
ExtBULLBuffer[i] = low[i+1] - ARROW_OFFSET*Point;
PatternID[i] = 1.0;
}
ExtBULLBuffer[i] = close[i];
// Bear Patterns -----------------------------------------------------------------------------------------------
if( EngulfingBear(i, open, high, close) ) {
ExtBEARBuffer[i] = high[i+1] + ARROW_OFFSET*Point;
PatternID[i] = -1.0;
}
i++;
}
return(rates_total);
}
bool is_DownTrend(int i, const double &close[]){
return iMA(Symbol(), Period(), TREND_PERIOD, 0, TREND_MA_METHOD, PRICE_CLOSE, i) <
iMA(Symbol(), Period(), TREND_PERIOD, 0, TREND_MA_METHOD, PRICE_CLOSE, i+1); }
bool is_UpTrend(int i, const double &close[]){
return iMA(Symbol(), Period(), TREND_PERIOD, 0, TREND_MA_METHOD, PRICE_CLOSE, i) >
iMA(Symbol(), Period(), TREND_PERIOD, 0, TREND_MA_METHOD, PRICE_CLOSE, i+1); }
bool is_Bull(int i, const double &open[], const double &close[]) {
return open[i] < close[i]; }
bool is_Bear(int i, const double &open[], const double &close[]) {
return open[i] > close[i]; }
bool is_LongBody(int i, const double &open[], const double &close[]) {
return Body(i, open, close) >= BodyAvg(i, open, close); }
bool is_SmallBody(int i, const double &open[], const double &close[]) {
return Body(i, open, close) <= BodyAvg(i, open, close); }
double BodyAvg(int i, const double &open[], const double &close[]) {
double sum = 0;
int j;
for (j=i+1; j<=i+Body_len; j++)
sum = sum + MathAbs(open[j] - close[j]);
return sum / Body_len; }
double Body(int i, const double &open[], const double &close[]) {
return MathAbs(open[i] - close[i]); }
// =====================================================================================================================
// BULL PATTERNS
// =====================================================================================================================
bool EngulfingBull(const int i, const double &open[], const double &low[], const double &close[]) {
if (
is_LongBody (i+2, open, close) && // Long,
is_Bear (i+2, open, close) && // Bear candle entering
is_SmallBody(i+1, open, close) && // Short,
is_Bear (i+1, open, close) && // Bear target candle
is_LongBody (i, open, close) && // Long,
is_Bull (i, open, close) && // Bull candle engulfing target candle
is_DownTrend(i, close) && // MA is moving down
is_DownTrend(i+1, close) && // MA is moving down
is_DownTrend(i+2, close) && // MA is moving down
close[i] >= open[i+1] &&
open[i] <= close[i+1] &&
(close[i] > open[i+1] || open[i] < close[i+1]) ) {
return true;
}
return false;
}
// =====================================================================================================================
// BEAR PATTERNS
// =====================================================================================================================
bool EngulfingBear(const int i, const double &open[], const double &high[], const double &close[]) {
if (
is_LongBody (i+2, open, close) && // Long,
is_Bull (i+2, open, close) && // Bull candle entering
is_SmallBody(i+1, open, close) && // Short,
is_Bull (i+1, open, close) && // Bull target candle
is_LongBody (i, open, close) && // Long,
is_Bear (i, open, close) && // Bear candle engulfing target candle
is_UpTrend (i, close) && // MA is moving up
is_UpTrend (i+1, close) && // MA is moving up
is_UpTrend (i+2, close) && // MA is moving up
close[i] <= open[i+1] &&
open[i] >= close[i+1] &&
(close[i] < open[i+1] || open[i] > close[i+1]) ) {
return true;
}
return false;
}
sample EA
#define VERSION "6.0"
#property version VERSION
#property strict
#define CandlePatternIND "Indicators\\Valuta\\CandlePatternsTest.ex4"
#resource "\\" + CandlePatternIND
input int ARROW_OFFSET = 30; // Offset of Arrow from price (PIPS)
input bool ENGULFING = true; // Engulfing Patterns (Bull & Bear)
input int TREND_PERIOD = 50; // Period to determine up and down trend entering pattern
input ENUM_MA_METHOD TREND_MA_METHOD = MODE_SMA; // MA method for trend
datetime NewCandleTime = 0;
int OnInit() {
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason) {
}
bool IsNewBar(){
if (NewCandleTime == iTime(NULL, 0, 0)) {
return false;}
else {
NewCandleTime = iTime(NULL, 0, 0);
return true; }
}
void OnTick() {
if(IsNewBar()){
double bull = iCustom(Symbol(), Period(), "::" + CandlePatternIND, 0, 1);
double bear = iCustom(Symbol(), Period(), "::" + CandlePatternIND, 1, 1);
double id = iCustom(Symbol(), Period(), "::" + CandlePatternIND, 2, 1);
double body = iCustom(Symbol(), Period(), "::" + CandlePatternIND, 3, 1);
double bodyave = iCustom(Symbol(), Period(), "::" + CandlePatternIND, 4, 1);
double pp = iCustom(Symbol(), Period(), "::" + CandlePatternIND, 5, 1);
Print("bull buff ", bull);
Print("bear buff ", bear);
Print("body ", body);
Print("bodyave ", bodyave);
Print("price ", pp);
Print("id ", id);
Print("---------------");
}
}
Quote
Report
user3666197 · External communityPost link
External answer — Stack Overflow Stack Exchange
Author: user3666197
Original post: https://stackoverflow.com/a/79748623
License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/
Adaptation: HTML converted to plain text; contact email addresses removed.
Why is it doing this?
Because computers are ( nothing but dumb, yet fast, my father used to tell me ) finite-state-automatons and the code was not instructing to do anything else but these very things, was it?
Let's review the nest of problems -- Our Working Plan :
let's make the code work without
#resource
after (1) works, let's try to decode MQL4 (as-is, EoL-product, Builds used to creep ( dramatically ( may find earlier posts about "
New
-MQL4" nightmares in production, the more be aware of this)
For the sake of (1), let's re-factor and polish futher the Expert Advisor side :
/* MQL4 Expert Advisor code --------------------------------------------// https://stackoverflow.com/questions/79682030/mql4-icustom-return-empty-value-for-some-buffers-but-not-all */
#define VERSION "6.0"
#property version VERSION
#property strict
int OnInit() { return( INIT_SUCCEEDED ); }
void OnDeinit(const int reason) {}
Next get this extended with inputs :
/* INPUTs ----------------------------------------------------// INPUTs for Custom Indicator
input int ARROW_OFFSET = 30; // Offset of Arrow from price (PIPS)
input bool ENGULFING = true; // Engulfing Patterns (Bull & Bear)
input int TREND_PERIOD = 50; // Period to determine up and down trend entering pattern
input ENUM_MA_METHOD TREND_MA_METHOD = MODE_SMA; // MA method for trend
Next get this extended with actually passing these inputs via
iCustom()
-call signatures, as were defined inside ( original ) Custom indicator source code :
void PrintREPORTER() {
#define MQL4_Indicator_file_name "Valuta\\CandlePatternsTest" // relative to iCustom()-referenced default location <terminal_dir>/MQL4/Indicators
#define _Current_Symbol NULL
#define _Current_TimeFrame 0
#define Candle_Pattern_BULL 0
#define Candle_Pattern_BEAR 1
#define Candle_Pattern_ID 2
#define Candle_Pattern_BODY 3
#define Candle_Pattern_BODY_AVG 4
#define Candle_Pattern_PRICE 5
Print("bull buff ", iCustom( _Current_Symbol, // 1
_Current_TimeFrame, // 2
MQL4_Indicator_file_name, // 3
/* ---iCustom()-VARIADIC-SECTION--------- // Custom Indicator specified INPUTs, passed down the line per-call */
ARROW_OFFSET,
ENGULFING,
TREND_PERIOD,
TREND_MA_METHOD,
/* ---iCustom()-------------------------------------- tail context
Candle_Pattern_BULL, // -2 BufferIndex#
1 // -1 bar-offset from [0]
)
);
Print("bear buff ", iCustom( _Current_Symbol, _Current_TimeFrame, MQL4_Indicator_file_name, ARROW_OFFSET, ENGULFING, TREND_PERIOD, TREND_MA_METHOD, Candle_Pattern_BEAR, 1) );
Print("body ", iCustom( _Current_Symbol, _Current_TimeFrame, MQL4_Indicator_file_name, ARROW_OFFSET, ENGULFING, TREND_PERIOD, TREND_MA_METHOD, Candle_Pattern_BODY, 1) );
Print("bodyave ", iCustom( _Current_Symbol, _Current_TimeFrame, MQL4_Indicator_file_name, ARROW_OFFSET, ENGULFING, TREND_PERIOD, TREND_MA_METHOD, Candle_Pattern_BODY_AVG, 1) );
Print("price ", iCustom( _Current_Symbol, _Current_TimeFrame, MQL4_Indicator_file_name, ARROW_OFFSET, ENGULFING, TREND_PERIOD, TREND_MA_METHOD, Candle_Pattern_PRICE, 1) );
Print("id ", iCustom( _Current_Symbol, _Current_TimeFrame, MQL4_Indicator_file_name, ARROW_OFFSET, ENGULFING, TREND_PERIOD, TREND_MA_METHOD, Candle_Pattern_ID, 1) );
Print("---------------");
}
Next make the Expert process a New Bar Event using a minimalistic
OnTick()
handler :
void OnTick() { if( IsNewBar() ) PrintREPORTER(); }
bool IsNewBar() {
static int _lastFxTick_iTime = -1;
if ( _lastFxTick_iTime == iTime(NULL, 0, 0) ) { return false;}
else { _lastFxTick_iTime = iTime(NULL, 0, 0); return true; }
}
Supposing all the above works as expected, it starts to make sense to turn attention into "baking-in" the well working, RTO-state of the Custom Indicator .EX4, as a "
resource
".
Forcing MQL4 compiler pre-processor to do this before everything else works is bad idea.
Now, given (1) was completed,
#resource
directive might help "pack"-Custom-Indicator-as-a-resource into Expert Advisor EX4-file.
MQL4 documentation is kind-of helping in doing that right, yet we have to admit, the text is not readable or easy to understand, what will work without pain, so be patient and re-read the section "
Working with custom indicators included as resources
" :
"(...)Inclusion of indicators as resources simplifies the distribution of applications.
Below is an example of including and using SampleIndicator.ex4 custom indicator located in terminal_data_folder\MQL4\Indicators\ directory(...)"
There notice the syntax, used in compiler pre-processor directive
#resource "\\Indicators\\SampleIndicator.ex4"
( no expression attempts or other tricks here )
There also notice the syntax, used inside the
iCustom()
-call signature, denoting by added "
::
" in a classical string
"::Indicators\\SampleIndicator.ex4"
that this call shall resort to a pre-processor, compile-time pre-baked,
#resource
without trying to find some file ( not distributed ) on target system MT4-Terminal sandbox-filesystem.
#define MQL4_Indicator_rsrc_name "::Indicators\\Valuta\\CandlePatternsTest.mq4" // meets https://docs.mql4.com/runtime/resources
If we stay within MQL4-documented features, the compiled results ought work as documented, just by swapping the finally
#defined
symbol
MQL4_Indicator_rsrc_name
in place of the so far used
MQL4_Indicator_file_name
symbol.
Quote
Report
Post Reply
Quoted from Forex.com.bd-Editorial External answer — Stack Overflow Stack Exchange Author: user3666197 Source score (net votes, not local likes): 0 Original post: https://stackoverflow.com/a/79748623 License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/ Adaptation: HTML converted to plain text; contact email addresses removed. Why is it doing this? Because computers are ( nothing but dumb, yet fast, my father used to tell me ) finite-state-automatons and the code was not instructing to do anything else but these very things, was it? Let's review the nest of problems -- Our Working Plan : let's make the code work without #resource after (1) works, let's try to decode MQL4 (as-is, EoL-product, Builds used to creep ( dramatically ( may find earlier posts about " New -MQL4" nightmares in production, the more be aware of this) For the sake of (1), let's re-factor and polish futher the Expert Advisor side : /* MQL4 Expert Advisor code --------------------------------------------// https://stackoverflow.com/questions/79682030/mql4-icustom-return-empty-value-for-some-buffers-but-not-all */ #define VERSION "6.0" #property version VERSION #property strict int OnInit() { return( INIT_SUCCEEDED ); } void OnDeinit(const int reason) {} Next get this extended with inputs : /* INPUTs ----------------------------------------------------// INPUTs for Custom Indicator input int ARROW_OFFSET = 30; // Offset of Arrow from price (PIPS) input bool ENGULFING = true; // Engulfing Patterns (Bull & Bear) input int TREND_PERIOD = 50; // Period to determine up and down trend entering pattern input ENUM_MA_METHOD TREND_MA_METHOD = MODE_SMA; // MA method for trend Next get this extended with actually passing these inputs via iCustom() -call signatures, as were defined inside ( original ) Custom indicator source code : void PrintREPORTER() { #define MQL4_Indicator_file_name "Valuta\\CandlePatternsTest" // relative to iCustom()-referenced default location <terminal_dir>/MQL4/Indicators #define _Current_Symbol NULL #define _Current_TimeFrame 0 #define Candle_Pattern_BULL 0 #define Candle_Pattern_BEAR 1 #define Candle_Pattern_ID 2 #define Candle_Pattern_BODY 3 #define Candle_Pattern_BODY_AVG 4 #define Candle_Pattern_PRICE 5 Print("bull buff ", iCustom( _Current_Symbol, // 1 _Current_TimeFrame, // 2 MQL4_Indicator_file_name, // 3 /* ---iCustom()-VARIADIC-SECTION--------- // Custom Indicator specified INPUTs, passed down the line per-call */ ARROW_OFFSET, ENGULFING, TREND_PERIOD, TREND_MA_METHOD, /* ---iCustom()-------------------------------------- tail context Candle_Pattern_BULL, // -2 BufferIndex# 1 // -1 bar-offset from [0] ) ); Print("bear buff ", iCustom( _Current_Symbol, _Current_TimeFrame, MQL4_Indicator_file_name, ARROW_OFFSET, ENGULFING, TREND_PERIOD, TREND_MA_METHOD, Candle_Pattern_BEAR, 1) ); Print("body ", iCustom( _Current_Symbol, _Current_TimeFrame, MQL4_Indicator_file_name, ARROW_OFFSET, ENGULFING, TREND_PERIOD, TREND_MA_METHOD, Candle_Pattern_BODY, 1) ); Print("bodyave ", iCustom( _Current_Symbol, _Current_TimeFrame, MQL4_Indicator_file_name, ARROW_OFFSET, ENGULFING, TREND_PERIOD, TREND_MA_METHOD, Candle_Pattern_BODY_AVG, 1) ); Print("price ", iCustom( _Current_Symbol, _Current_TimeFrame, MQL4_Indicator_file_name, ARROW_OFFSET, ENGULFING, TREND_PERIOD, TREND_MA_METHOD, Candle_Pattern_PRICE, 1) ); Print("id ", iCustom( _Current_Symbol, _Current_TimeFrame, MQL4_Indicator_file_name, ARROW_OFFSET, ENGULFING, TREND_PERIOD, TREND_MA_METHOD, Candle_Pattern_ID, 1) ); Print("---------------"); } Next make the Expert process a New Bar Event using a minimalistic OnTick() handler : void OnTick() { if( IsNewBar() ) PrintREPORTER(); } bool IsNewBar() { static int _lastFxTick_iTime = -1; if ( _lastFxTick_iTime == iTime(NULL, 0, 0) ) { return false;} else { _lastFxTick_iTime = iTime(NULL, 0, 0); return true; } } Supposing all the above works as expected, it starts to make sense to turn attention into "baking-in" the well working, RTO-state of the Custom Indicator .EX4, as a " resource ". Forcing MQL4 compiler pre-processor to do this before everything else works is bad idea. Now, given (1) was completed, #resource directive might help "pack"-Custom-Indicator-as-a-resource into Expert Advisor EX4-file. MQL4 documentation is kind-of helping in doing that right, yet we have to admit, the text is not readable or easy to understand, what will work without pain, so be patient and re-read the section " Working with custom indicators included as resources " : "(...)Inclusion of indicators as resources simplifies the distribution of applications. Below is an example of including and using SampleIndicator.ex4 custom indicator located in terminal_data_folder\MQL4\Indicators\ directory(...)" There notice the syntax, used in compiler pre-processor directive #resource "\\Indicators\\SampleIndicator.ex4" ( no expression attempts or other tricks here ) There also notice the syntax, used inside the iCustom() -call signature, denoting by added " :: " in a classical string "::Indicators\\SampleIndicator.ex4" that this call shall resort to a pre-processor, compile-time pre-baked, #resource without trying to find some file ( not distributed ) on target system MT4-Terminal sandbox-filesystem. #define MQL4_Indicator_rsrc_name "::Indicators\\Valuta\\CandlePatternsTest.mq4" // meets https://docs.mql4.com/runtime/resources If we stay within MQL4-documented features, the compiled results ought work as documented, just by swapping the finally #defined symbol MQL4_Indicator_rsrc_name in place of the so far used MQL4_Indicator_file_name symbol.
Checking account access…