The next function closes orders in my EA. It works fine while the 3rd if(...)-code-block is quoted-out.
When it is activated in the function, MT4 stops and W7 pops up with a message saying there's a problem with the program (MT4). Defining the variable prijsOpen or not makes no difference.
Can anybody tell me what's wrong??
void sluitBUY( double waarde ){
for ( int i = 0; i < OrdersTotal(); i++ ){
if ( OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) == true ){
double prijsOpen = OrderOpenPrice();
if ( OrderType() == 0 ){
if ( waarde != 0
&& prijsOpen < waarde
) //<============================================ CAUSES CRASH
OrderClose( OrderTicket(),
OrderLots(),
OrderClosePrice(),
3,
clrCyan
);
}
}
}
}
I don't see anything wrong with the code you provided. But I have seen the behavior that you are describing. Your MT4 platform may be corrupted. Try the same code on a different instance of MT4 and see if it still has the same problem. I'm guessing that it won't.
Related
I was writing code in MQL4 Meta Editor.
I wrote the code in such a way that it is possible to open both a buy and a sell position.
I tried to calculate the date and time of the candle that I entered with the trading function OrderOpenTime, but I don't know how to calculate the date and time of both buy and sell if the entry is both buy and sell.
I need your help.
Add the code I are currently writing
I'm sorry if my native language is Japanese and the English is strange.
for(int i = OrdersTotal() - 1; i >= 0; i--){
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) break;
if(OrderMagicNumber() != MagicNumber) continue;
if(OrderSymbol() != Symbol()) continue;
oder_shift = iBarShift(Symbol(),Period(),OrderOpenTime() , false );
}
I have a small dxl script and I need to return the number of assigned positions from an array of, let's say, size 20 in which only 10 positions are assigned.
I tried to use noError() and lastError() functions, but after lastError() is called, the script is halted and I can't continue the execution.
Here's my code:
int returnArrayLength(string array[]){
int lengthOfArray = 0,i = 0;
for (i=0; i < sizeof array ; i++){
noError()
if (!null array[i]){
lengthOfArray++
print lengthOfArray
}
if (!null lastError()){
print "Exception caught!" // not printed
break
}
}
return lengthOfArray
}
string labels[6]
labels[0] = "label0"
labels[1] = "label1"
labels[2] = "label2"
labels[3] = "label3"
print returnArrayLength(labels) // not printed
The above code prints the following:
1
2
3
4
How can I resume the execution after the lastError() function is called ?
This was tougher than I thought it would be!
So, as it turns out, an unassigned element error halts the DXL program entirely. So what do we need to do?
Well, we need to run a snippet of code, in it's own environment, and let it crash if it needs to!
To do so, we need to create an eval_, pass it our array, and then have it return_ (which won't be executed if the eval_ fails)
Take a look:
int returnArrayLength(string array[]){
int lengthOfArray = 0,i = 0;
for (i=0; i < sizeof array ; i++){
string scode = "noError()
string ( &passedAr)[] = (addr_ "( ( addr_ array ) int ) ")
string s = passedAr["i"]
lastError()
return_ \"Y\""
if ( ( eval_ scode ) == "Y" ){
lengthOfArray++
print lengthOfArray
} else {
print "Exception caught!" "\n"
break
}
}
return lengthOfArray
}
string labels[6]
labels[0] = "label0"
labels[1] = "label1"
labels[2] = "label2"
labels[3] = "label3"
print returnArrayLength(labels)
What a fantastic little problem.
Resources I used to help solve this:
How to pass an array into an eval_
eval_ , addr_ , and memory leaks
Testing for unassigned variables - This one doesn't quite work because of the nature of arrays, at least as far as I could tell!
In any case, thanks for the challenge!
There are Bollinger Bands with three RSI running in the basement.
I want to do a check on the signal in such a way that when 3 RSI struck the zone of the upper Bbands, there was a signal down and vice versa:
int start(){
double ma, stdev;
int i, limit, count=IndicatorCounted();
if(count<0) return(0);
limit=Bars-count;
if(limit>1) limit=Bars-1;
for(i=limit; i>=0; i--) {
RSI[i] =iRSI(Symbol(),Period(),rsi_period, PRICE_CLOSE,i);
RSI2[i]=iRSI(Symbol(),Period(),rsi_period_2,PRICE_CLOSE,i);
RSI3[i]=iRSI(Symbol(),Period(),rsi_period_3,PRICE_CLOSE,i);
}
for(i=limit; i>=0; i--) {
ma=iMAOnArray(RSI3,0,bb_period,0,0,i); // midle line
stdev=iStdDevOnArray(RSI3,0,bb_period,0,0,i); // dev
BBUP[i]=ma+bb_dev*stdev; // up line
BBDOWN[i]=ma-bb_dev*stdev; // down line
UP[i]=0;
DOWN[i]=0;
}
if(limit<Bars-1) limit++;
for(i=limit; i>0; i--) {
if(RSI[i] <= BBDOWN[i] && RSI[i+1] > BBDOWN[i+1] && RSI2[i] <= BBDOWN[i] && RSI2[i+1] > BBDOWN[i+1] && RSI3[i] <= BBDOWN[i] && RSI3[i+1] > BBDOWN[i+1]){
DOWN[i] = iLow(_Symbol, _Period, i);
}
if(RSI[i] >= BBUP[i] && RSI[i+1] < BBUP[i+1] &&W RSI2[i] >= BBUP[i] && RSI2[i+1] < BBUP[i+1] && RSI3[i] >= BBUP[i] && RSI3[i+1] < BBUP[i+1]){
UP[i]= iHigh(_Symbol, _Period, i);
}
}
The whole problem is that I have very crooked signals.
Appear where they should not be, and there is no where to be.
THE BEST PRACTICE:
Step 0: Let's first agree in written WHAT is the actual TARGET:
If the TARGET is to compute & paint on GUI the Bollinger Bands on RSI3[] values, the best way to do this is to use:
UPPER[i] = iBandsOnArray( RSI3, // ArrayAsSeries[]
array_calculation_depth, // reduce overheads
BB_MA_period, // BBands period
BB_StDev_MUL, // how many sigmas
BB_Zero_Shift, // #DEFINE BB_Zero_Shift 0
MODE_UPPER, // BBands upper line
i // shifting operator[i]
);
This way one may efficiently produce each of the { MODE_UPPER | MODE_MAIN | MODE_LOWER } Bollinger Bands lines here, consistently generated over dimension-less RSI3[] data, thus protecting the sense of any additive operations in signal-composition(s) with other, dimension-less data, as in { RSI2[], RSI[] }.
Step 1: visually check the lines to validate any signal-conditions:
Given the GUI shows lines accordingly, one may try to compose signal-conditions. The "hot"-bar [0] is a live-bar, where novice may encounter tricking signalling situations, if not handled with due professional care.
Step 2: implement signal-conditions in code:
Only after Step 0) & 1) took place and both meet one's own prior expectations, any code starts to make sense to get built.
From MQL4 docs https://docs.mql4.com/indicators/imaonarray
Unlike iMA(...), the iMAOnArray() function does not take data by
symbol name, timeframe, the applied price. The price data must be
previously prepared. The indicator is calculated from left to right.
To access to the array elements as to a series array (i.e., from right
to left), one has to use the ArraySetAsSeries() function.
RSI3 is currently orientated right to left (0 is most recent time point, limit is furthest element).
Same issue with iStdDevOnArray()
Fix those issues and it should work as you want. Whether there is any value in drawing Bollinger bands on RSI is another matter
Update
The function ArraySetAsSeries() can be used to swap the array between left-to-right and right-to-left
When you first initialise the RSI arrays ( in the OnInit() ) tell MetaTrader Terminal that they are timeseries.
ArraySetAsSeries(RSI1,True);
ArraySetAsSeries(RSI2,True);
ArraySetAsSeries(RSI3,True);
Then in main body, add ArraySetAsSeries(RSI3,False); before your second for loop to swap the array orientation. Then ArraySetAsSeries(RSI3,True); after the loop to restore the array orientation.
for(i=limit; i>=0; i--) {
RSI[i ] = iRSI(Symbol(),Period(),rsi_period,PRICE_CLOSE,i);
RSI2[i] = iRSI(Symbol(),Period(),rsi_period_2,PRICE_CLOSE,i);
RSI3[i] = iRSI(Symbol(),Period(),rsi_period_3,PRICE_CLOSE,i);
}
ArraySetAsSeries(RSI3,False);
for(i=limit; i>=0; i--) {
ma=iMAOnArray(RSI3,0,bb_period,0,0,i); // midle line
stdev=iStdDevOnArray(RSI3,0,bb_period,0,0,i); // dev
BBUP[i]=ma+bb_dev*stdev; // up line
BBDOWN[i]=ma-bb_dev*stdev; // down line
UP[i]=0;
DOWN[i]=0;
}
ArraySetAsSeries(RSI3,True);
if(limit<Bars-1) limit++;
for(i=limit; i>0; i--) {
if( RSI[i] <= BBDOWN[i] &&
RSI[i+1] > BBDOWN[i] &&
RSI2[i] <= BBDOWN[i] &&
RSI2[i+1] > BBDOWN[i] &&
RSI3[i] <= BBDOWN[i] &&
RSI3[i+1] > BBDOWN[i]) {
DOWN[i] = iLow(_Symbol, _Period, i);
}
if( RSI[i] >= BBUP[i] &&
RSI[i+1] < BBUP[i+1] &&
RSI2[i] >= BBUP[i] &&
RSI2[i+1] < BBUP[i+1] &&
RSI3[i] >= BBUP[i] &&
RSI3[i+1] < BBUP[i+1]) {
UP[i]= iHigh(_Symbol, _Period, i);
}
}
Basic indicator structure
You need to go through the MQL4 Documentation and learn the proper structure of an indicator. There needs to be an OnInit() function where you initialise values. Then an OnCalculate() function where you fill the indicator buffers.
//+-----------------------------------------------------------------+
//| Custom indicator initialization function |
//+-----------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
ArraySetAsSeries(RSI3,True);
//---
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[])
{
// Do your calculations here
//--- return value of prev_calculated for next call
return(rates_total);
}
If you use iBandsOnArray() to calculate Bollinger bands you won't need to swap the array direction after it is set in OnInit()
If the indicator is compiling but crashing, you will need to debug it. Simplest way is to look at the errors in the log and add PrintFormat() statements throughout your code so you can see what the indicator is doing at different points and see where it crashes.
The problem is that when the i in the for loop reaches 15, I get an Array out of range error.
What I want to achieve is on every tick to check every Symbol in the MarketWatch and in each Symbol to check the current bar ( PERIOD_M5 ) and the previous one if there is a gap.
void OnTick()
{
int size = ArraySize( Symbols );
for( int i = 0; i < size; i++ )
{
int current_bar_index = iHighest( Symbols[i], PERIOD_M5, MODE_HIGH, 1, 0 );
int previous_bar_index = iHighest( Symbols[i], PERIOD_M5, MODE_HIGH, 1, 1 );
int current_bar_index_low = iLowest( Symbols[i], PERIOD_M5, MODE_LOW, 1, 0 );
int previous_bar_index_low = iLowest( Symbols[i], PERIOD_M5, MODE_LOW, 1, 1 );
double current_high = High[ current_bar_index];
double previous_high = High[previous_bar_index];
double current_low = Low[ current_bar_index_low];
double previous_low = Low[ previous_bar_index_low];
if ( current_low > ( previous_high + 0.00002 )
|| current_high < ( previous_low - 0.00002 )
)
{
Print( "There is a gap" );
}
}
}
Symbols[] is the array containing all the symbols. I loop through it and pass the current Symbol and get the index for the current bar and the previous one and then simply check if there is a gap.
The first problem is that passing every Symbol doesn't work. It gets only one and that's it. How can I achieve that and also, why I get an Array out of range error?
Let's start with the Array out of range error:
Given the MCVE was not present, let's assume, there is some fair declaration of the MQL4 code in the header or something like that.
So to diagnose this, add a trivial debug tool:
string SymbolsARRAY[] = { ..., // be carefull, some Brokers
..., // have quite strange names
...
};
for ( int cellPTR = 0;
cellPTR < ArraySize( SymbolsARRAY );
cellPTR++
)
PrintFormat( "%s[%d] = %s",
"SymbolsARRAY",
cellPTR,
SymbolsARRAY[cellPTR]
);
and post here the output.
Next, the GAP detection:
if you would not mind, checking a pair of M5-Bars for a GAP on each and every price QUOTE message arrival, is quite devastating the MQL4 computing resources. The GAP may principally appear only upon a new Bar starts ( and yet may disappear, during the Bar duration ).
Let's detect the initial GAP-condition ( it is similar to engulfing detection ):
if ( iLow( SymbolsARRAY[cellPTR], PERIOD_M5, 1 ) > iHigh( SymbolsARRAY[cellPTR], PERIOD_M5, 0 )
|| iHigh( SymbolsARRAY[cellPTR], PERIOD_M5, 1 ) < iLow( SymbolsARRAY[cellPTR], PERIOD_M5, 0 )
)
Print( "Initial GAP detected" );
Using this inside a detection of a new bar event may look like this:
void OnTick(){
// -----------------------------------------------------------------
// MINIMALISTIC CONTEXT-AWARE GAP DETECT/REMOVE
// -----------------------------------------------------------------
static bool aCurrentGAP = False;
static datetime aCurrentBAR = Time[0];
if ( aCurrentBAR != Time[0] ){
aCurrentBAR = Time[0];
// testInitGAP .........................present?
aCurrentGAP = testInitialGAP_onNewBarEVENT();
}
else {
if ( aCurrentGAP ){
// testInitGAP .....................disappeared?
aCurrentGAP = testInitialGAP_DISAPPEARED();
}
}
// -----------------------------------------------------------------
// MAIN COMPUTING & TRADING DUTIES OF EA-MQL4-CODE
// -----------------------------------------------------------------
...
}
about the error - when you receive it, it also can see the address of the code that generates it: number of line and symbol number in that line
about Symbol - as you may know, in MQL5 you can select all symbols from the market watch, in MQL4 such option is not available, as far as I remember, so I suspect your array of symbol names is empty or sth like that.
Could you show how you initialized that array? A correct way is the following one:
string Symbol[]={"EURUSD","AUDUSD","GBPUSD"};
also your code doesn't make any sense - when you select iHighest(*,*,*,i,j) - that means that EA-code checks i-elements, starting from j-th element ( 1, 0 ) means a current bar only, ( 1, 1 ) means to select just 1 bar, starting from bar 1, so still only 1 Bar is used.
For that it is much easier to have
double cur_high = iHigh( Symbol[i], 5, 0 ),
prev_high = iHigh( Symbol[i], 5, 1 );
After performing
ChartNavigate(0, CHART_END, -5142);
I want to get the max and min price of that particular chart.
I tried
ChartGetDouble(0,CHART_PRICE_MAX,0,top)
ChartGetDouble(0,CHART_PRICE_MIN,0,top)
WindowPriceMax
WindowPriceMin
None of them gives me the price after the ChartNavigate.
What is the right way to do this?
New-MQL4.56789 features may surprise, nevertheless:
Step 0: always catch Chart_OkFLAG
bool Chart_OkFLAG;
double Chart_min,
Chart_MAX;
int Chart_ToBeMODIFIED = ChartID();
int Chart_ToBeMODIFIED_SubWinID = 0;
int Chart_nBarsRelativeSHIFT = 0;
Chart_OkFLAG = ChartNavigate( Chart_ToBeMODIFIED,
< CHART_BEGIN |
CHART_END |
CHART_CURRENT_POS >,
Chart_nBarsRelativeSHIFT
);
If OK: you won the first round, the GUI command has been accepted for being syntactically & context-wise correct. That does not mean, it was executed by the GUI processor. It was just let in, to the tail of the GUI-command-QUEUE.
Step 1: Enforce it's execution ( wise to think about deferring such processing to some safe place, after mission-critical elements have been fulfilled )
if ( Chart_OkFLAG ){
WindowRedraw(); // ol'-MQL4
ChartRedraw( Chart_ToBeMODIFIED ); // new-MQL4
Chart_min = ChartPriceMin( Chart_ToBeMODIFIED,
Chart_ToBeMODIFIED_SubWinID
);
Chart_MAX = ChartPriceMAX( Chart_ToBeMODIFIED,
Chart_ToBeMODIFIED_SubWinID
);
}
else{
// ERROR HANDLING onChartNavigate(T)ERROR
}
ALWAYS: do not hesitate to inline error handlers, even where MQL4 language seems straightforward ( you never know, when that effort pays off by avoiding hours of bug tracking )
double ChartPriceMin( const long Chart_ID = 0,
const int Chart_SubWindow_ID = 0
) {
double result = EMPTY_VALUE;
ResetLastError();
if ( !ChartGetDouble( Chart_ID,
CHART_PRICE_MIN,
Chart_SubWindow_ID,
result
)
){
PrintFormat( "ERROR: Code(%d) in [%s]",
GetLastError(),
__FUNCTION__,
);
}
return( result );
}
double ChartPriceMAX( const long Chart_ID = 0,
const int Chart_SubWindow_ID = 0
) {
double result = EMPTY_VALUE;
ResetLastError();
if ( !ChartGetDouble( Chart_ID,
CHART_PRICE_MAX,
Chart_SubWindow_ID,
result
)
){
PrintFormat( "ERROR: Code(%d) in [%s]",
GetLastError(),
__FUNCTION__,
);
}
return( result );
}