How to repair an Error 4059 on calling the OrderModify() function | MQL4? - trading

My EA comes up with an error code of 4059which meansthat the OrderModify() function is apparently not allowed in (back) testing.
Is there any way in which this could be allowed at all?
All I'm wanting to do is change the position to breakeven, when it gets 100 pips "to the good"
PrintFormat( "TKT[%.2d]OP:[%7.5f]SL:[%7.5f]CurrentPrice:[%7.5f]Stoplevel:[%.3d]FreezeLevel:[%.3d]",
aTicket,
anOpenPrice,
aCurrentSL,
anAskPrice,
stopLevel,
freezeLevel
);
SellMod = OrderModify( aTicket,
NormalizeDouble( anOpenPrice, Digits ),
NormalizeDouble( aNewSLPrice, Digits ),
NormalizeDouble( aNewTpPrice, Digits ),
0,
sellcolor
);
SendMail( "Notification of Order Modification for Ticket#"
+ IntegerToString( OrderTicket(), 10 ),
"Good news! Order Ticket#"
+ IntegerToString( OrderTicket(), 10 )
+ "has been changed to breakeven"
);
if ( !SellMod )
{ PrintFormat( "Order modification for ticket %10d has failed modify the order under the Error Code# %5d. Check MQL4 Documentation",
aTicket,
GetLastError()
);
result = false;
}

4059 ERR_FUNC_NOT_ALLOWED_IN_TESTINGis clear, not the source of it though
Function is not allowed in testing mode[ HIDDEN REMAINS _WHERE_ + _WHY_ IT IS REPORTED] :)
So,
modify a few details on Error-Detection
so as to get back to the riding saddle and to get the things back under your full control:
.
..
...
// ======================================== .ASSUME NOTHING ; the best
// advice
// ever :)
// // ALWAYS (pre-clear)
GetLastError(); /* _ _ _ _ _ _ _ _ _ _ _ AND ERR_SYSREG, 0 ; CLEAR SYSREG
; (
; prevents
; from reading
; a value from
; some "old"
; error-code
; on a "next"
; GetLastError
; call
; )
*/
OrderModify(...); // CALL _OrderModify
gotLastERROR = // MOV VAR, ERR_SYSREG ; CATCH ERR
GetLastError(); // _ _ _ _ _ _ _ _ _ _ _ AND ERR_SYSREG, 0 ; CLEAR SYSREG
// ---------------------------------------- ( a main-effect )
// ( VAR has this _FUN call error-code )
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- ( a side-effect )
// ( ERR_SYSREG is clear AGAIN )
...
..
.
With a similarly systematic approach to Error-Detection you will soon realise the root cause of the observed problem and any Error-Handling will only start to have sense.
Most probably, the error originates a few SLOC-s lower, under your OrderModify() call, where SendMail() call appears, in spite of the fact, that HELP explicitly says:
NoteSending can be prohibited in settings, email address can be omitted as well. For the error information call GetLastError().
SendMail() function does not work in the Strategy Tester.

OrderModify() does NOT generate error 4059.
That error comes from SendMail(). Documentation states that:
https://docs.mql4.com/common/sendmail

Related

Can I make a while-loop that uses RSI value as the condition?

When I try to run this while-loop in MQL4, it can not seem to update the rsi from within the loop. It always returns the same value of the rsi and thus stays in an eternal loop. I have tried it on an EA as well as a script.
I have also tried making rsi a globally defined variable too but still did not work.
void OnTick()
{
double rsi = iRSI(NULL,0,14,PRICE_CLOSE,0); // defining rsi
while( rsi < 50 )
{
double rsi = iRSI(NULL,0,14,PRICE_CLOSE,0); // update rsi
Sleep(10000); // slow down loop
Alert("this is from inside while loop rsi is "+rsi);
}
Alert("While loop exited, condition met"); // now code goes
Alert("opening an order now " ); // to place an order
}
Can I make a while-loop that uses RSI value as the condition?
Oh sure you can.
Let's move out the colliding elements.
Given the code as-is, there are several brutal misconceptions to repair:
if a code spends some time "inside" such a loop, there will never be heard a new incoming QUOTE-message from market, so your Close[0]-value will remain "blind" to any such update from Market.
if a second double rsi = ... declaration takes place "inside" a scope of a while-loop-constructor, the newer versions ( Builds ) of the MQL4 language will actually "mask" the older ( "outer" ) variable, that is yet still used in the loop-constructor control variables / conditions. Result? You assign "new" values to an "inner"-variable, that bears just by coincidence a same name as the "outer"-variable ( both are named rsi, yet the "inner" keeps-masking the "outer", so the "outer" never gets any update(s), if any such were stored inside the loop into the "inner" )
Solution
avoid masking by not declaring any same-name named variables (always, it is a sign of good engineering practice)
avoid receiving market-QUOTE-updates by deaf-loop-locking - prefer the non-blocking use of if(){...} instead of while(){...}
MQL4 is a responsive-ecosystem, where OnTick() is automatically called whenever a new QUOTE-message arrives from FX-Market, so design your algorithms so as these never block.
For your learning-directed inspiration, you may try your next few steps using this template :
string MASK = "[%s]_INF:: " // DEF. & INIT...
+ "This is a QUOTE# %5d "
+ "Having arrived at [%s]_FX-MarketTIME\n"
+ "|Ask %16.8f\n"
+ "|Bid %16.8f\n"
+ "|Vol %16d\n"
+ "|RSI %16.8f";
double rsi = EMPTY; // DEF. & INIT...
int nTicks = 0; // DEF. & INIT...
void OnDeinit( const int aDeinitReason )
{ EventKillTimer();
}
int OnInit()
{ EventSetTimer( 1 );
Comment( "------------------------------------------------------\n ",
"WAITING for a first QUOTE-arrival from FX-Market\n",
"------------------------------------------------------"
);
return( 0 );
}
void OnTick()
{ nTicks++; // update COUNTER
rsi = iRSI( NULL, 0, 14, PRICE_CLOSE, 0 ); // update rsi
Comment( SetupComment() ); // update GUI
// -------------------------------- FIRST 50 FX-Market Ticks delivered
if ( nTicks < 50 ) return;
// -------------------------------- AFTER 50 FX-Market Ticks delivered
// -------------------------------- BE WARNED, THIS IS AN AWFUL ANTI-PATTERN
while( True )
{
rsi = iRSI( NULL, 0, 14, PRICE_CLOSE, 0 ); // update rsi
Comment( SetupComment() ); // update GUI
Sleep( 10000 );
}
// -------------------------------- NEVER GETS HERE
Alert( "?" );
}
string SetupComment()
{ return( StringFormat( MASK,
TimeToStr( TimeLocal(),
TIME_DATE|TIME_MINUTES|TIME_SECONDS
),
nTicks,
TimeToStr( TimeCurrent(),
TIME_DATE|TIME_MINUTES|TIME_SECONDS
),
NormalizeDouble( Ask, 8 ),
NormalizeDouble( Bid, 8 ),
Volume[0],
NormalizeDouble( rsi, 8 )
)
);
}
void OnTimer()
{ Comment( ChartGetString( 0, CHART_COMMENT ),
"\n",
TimeToStr( TimeLocal(),
TIME_DATE|TIME_MINUTES|TIME_SECONDS
)
);
Print( ChartGetString( 0, CHART_COMMENT ) );
}
Declare rsi only once, outside the loop, as you already have it. To make it work as you intend REMOVE the type double from in front of variable rsi inside the loop.

Getting the max and min price of current chart

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 );
}

Error 1 in OrderModify

I'm trying to modify an Order, but I always get Error #1.
From my research, I have discovered that error 1 means I have input parameter in a wrong way. How can I fix my OrderModify() function?
stoploss = NormalizeDouble(Ask - Point * TrailingStop,Digits);
int ticket;
takeprofit = NormalizeDouble(Ask + Point * TrailingStopTP,Digits);
double minstoplevel = MarketInfo( Symbol(), MODE_STOPLEVEL );
if(stoploss > NormalizeDouble(Ask - Point*minstoplevel,Digits)) {
stoploss = NormalizeDouble(Ask - Point*minstoplevel,Digits);
}
if(takeprofit < NormalizeDouble( Ask + Point*minstoplevel2, Digits )) {
takeprofit = NormalizeDouble( Ask + Point*minstoplevel2, Digits );
}
if(AccountFreeMarginCheck(Symbol(),OP_SELL,lotsize)>0) {
ticket=OrderSend(Symbol(),OP_BUY,lotsize,Ask, 0, 0.0, 0.0, "comment", MagicNumber, 0, Lime);
if(ticket<0) {
Print("Order send failed with error #",GetLastError());
} else {
Print("Order send sucesso!! Ticket#", ticket);
res=OrderModify(ticket,OrderOpenPrice(),stoploss,takeprofit,0,Blue);
if(res==false) {
Print("Error modifying order!, error#",GetLastError());
} else {
Print("Order modified successfully, res#", res);
}
}
} else {
Print("Sem dinheiro na conta D=");
}
}
Not exactly "wrong", OrderModify() legally sets _LastError == 1
There might be a bit surprise, but OrderModify() has an obligation to signal _LastError == 1 in case, the call was both syntactically and semantically correct, however, the values supplied for modification(s) were actually the very same, as the identified ticket# has already had in database.
This means, there was nothing to modify, as all the attributes already had the "quasi-new" target value(s).
One may pre-check all fields for a potential identity, which might allow our code to skip the OrderModify() call in this very case of an identity-of-{ current | target } values.
ERR_NO_RESULT == 1 // No error returned, but the result is unknown
GetLastError() - returns a last generated error-code. The same value is available via a system variable named _LastError. It's value can be reset before a critical activity to zero by calling ResetLastError().
Error codes are defined in stderror.mqh.
To print the error description you can use the ErrorDescription() function, defined in stdlib.mqh file
#include <stderror.mqh>
#include <stdlib.mqh>
The problem is that even though the entry price, stoploss, and take profit parameters to the OrderModify() call appear to be the same, they likely differ by a fraction of a unit ( smaller than "Digits" ).
To fix this,simply normalize the parameters to make sure they are a maximum of Digits decimal places long.
double entryPrice = NormalizeDouble( entryPrice, Digits );
double stoploss = NormalizeDouble( stoploss, Digits );
double target = NormalizeDouble( target, Digits );
Then pass them into the OrderModify() call.

Order Sent Failed with Error #130

I'm trying to insert a takeprofit and stoploss argument in my SendOrder() function, but I'm getting the following error:
Order Sent Failed with Error #130
This is my code:
extern double takeprofit = 30.0;
extern double stoploss = 20.0;
stoploss = NormalizeDouble( stoploss, 5 ); // SET stop loss
Print( "stoploss", stoploss );
takeprofit = NormalizeDouble( takeprofit, 5 ); // SET take profit
ticket = OrderSend( Symbol(),
OP_SELL,
lotsize,
Ask,
100,
stoploss,
takeprofit,
0,
0,
0,
CLR_NONE
);
if ( ticket < 0 ) {
Print( "Order send failed with error #", GetLastError() );
}
else Print( "Order send sucesso!!" );
I already checked documentation for the function NormalizeDouble(), but I'm still getting the error.
What should I do?
A ) Fully comply with the MQL4 OrderSend() syntax requirements
int anOrderTKT; // DECLARE int
double anOrderLotSIZE; // DECLARE double
string anOrderCommentSTRING; // DECLARE string
anOrderTKT = OrderSend( _Symbol, // CPU-glitch, is faster than calling Symbol(),
OP_SELL, // XTO.Type
anOrderLotSIZE, // XTO.Size [LT]s
Bid, // XTO.EntryPRICE { OP_BUY: Ask | OP_SELL: Bid }
100, // XTO.SLIPPAGE [PT]s
0, // XTO.SL_PRICE
0, // XTO.TP_PRICE,
anOrderCommentSTRING, // XTO.Comment
0, // XTO.MagNUM#
0, // XTO.PendingOrderEXPIRE
CLR_NONE // GUI.MarkerCOLOR
); // ==> { EMPTY | aTkt# }
Your code fails at setting a correct SHORT trade Entry-Price, as it shall read rather Bid, not Ask ( this error is hidden as it is effectively masked-out by a rather cosmic distance of 100 points in a tolerable slippage distance from the said price ).
Your code fails at assigning int ( 0 ) in place, where string is expected.
B) Error 130: == "invalid stops"
You shall verify with your Broker a few details:
Does their Terms & Conditions allow to OrderSend() one-stop-instruction, incl, TP & SL, or does the Broker T&C require to first open a trade-position & only after that happens to allow an OrderModify() instruction to setup TP & SL price-levels?
In either case, check your Broker T&C settings for STOPLEVEL & FREEZELEVEL distances, within which Broker rejects any TP & SL setup(s) or modification(s) thereof.
C) A good practice is not to assign into extern iterator-variables
While this is not a root-cause for your trouble, do get accustomed with an industry best practices, one of which is not to assign any value to a declared extern. Rather declare your own variable, that you control scope & assignments thereof, but leave extern(s) un-touched from your code side.

How to notify a number increase & decrease in MQL4 code?

can anyone help me, how to write MQL4 code to know if the result is increase OR decrease..
Example:
if a result was first 0.0543 and then it is increased to 0.1342 and later decreased to 0.10345, I want to implement it to my code below:
int start()
{
double val = iCustom( NULL, 0, "SS2009_B", 0, 0, 0 );
ObjectSet( "TimeLable11", OBJPROP_CORNER, obCorner );
ObjectSetText( "TimeLable11", "Result : " + val,
fsize,
"Microsoft Sans Serif",
Yellow
);
return( 0 );
}
I want the result to have an increasing OR a decreasing notification.
Example :
Result : 0.1849 Increasing
Result : 0.01324 Decreasing
To have a SIMPLE example:
//------------------------------------------------------------------
#property copyright "Copyright 2015"
//------------------------------------------------------------------
// Standard Variables (define a variable to store previous value)
//------------------------------------------------------------------
double viIndicatorValuePrev = 0.0000;
int start() {
double viIndicatorValueNow = iCustom(NULL,0,"SS2009_B",0,0,0);
//------------------------------------------------
//Decide on direction (increasing or decreasing)
//------------------------------------------------
string vsDirection = "Same";
if( viIndicatorValueNow>viIndicatorValuePrev)
vsDirection = "Increasing";
if( viIndicatorValueNow<viIndicatorValuePrev)
vsDirection = "Decreasing";
//------------------------------------------------
//------------------------------------------------
// Do your thing here (ie, display stuff)
//------------------------------------------------
ObjectSet( "TimeLable11", OBJPROP_CORNER, obCorner);
ObjectSetText(
"TimeLable11"
, "Result : " + viIndicatorValueNow + " (" + vsDirection + ")"
, fsize, "Microsoft Sans Serif", Yellow
);
//------------------------------------------------
// Store current value for future comparison
//------------------------------------------------
viIndicatorValuePrev = viIndicatorValueNow;
//------------------------------------------------
return(0);
}
Hope this example helps.
Solution to monitor & show delta per each aMarketEVENT call of start() ( upon aMarketQUOTE aka Tick arrival )
First you need a method to store and retain a value, that becomes "old", in the meantime, before the start() ( well actually an OnTick() in the new-MQL century ) is called next time.
A static double is a smart way to go:
static double previousVALUE = EMPTY; // initialised to EMPTY
Next, initialise it in accord with a forward-stepping logic of the Custom Indicator "SS2009_B"
if ( previousVALUE == EMPTY ) {
previousVALUE = iCustom( NULL, // a Symbol
0, // a TimeFRAME
"SS2009_B",
0,
0, // a Buffer# to get value from
1 // step-back one Bar
);
}
For syntax details, review MQL4 documentation
double iCustom(
string symbol, // symbol
int timeframe, // timeframe
string name, // path/name of the custom indicator compiled program
... // custom indicator input parameterA (if
... // custom indicator input parameterB (if
... // custom indicator input parameterC (if necessary)
int mode, // line index
int shift // shift
);
Finally calculate delta & show it on UI & shuffle to get ready for a next call
double currentVALUE = iCustom( NULL, 0, "SS2009_B", 0, 0, 0);
double deltaVALUE = previousVALUE - currentVALUE;
previousVALUE = currentVALUE; // shuffle [1]<-[0] before RET/next call
if ( deltaVALUE > 0 ){
ObjectSetText( "TimeLabel11",
"RESULT: " + NormalizeDouble( deltaVALUE, Digits ) + "|^|",
fsize,
"Courier New",
Yellow // can be deltaVALUE specific too :o)
);
}
if ( deltaVALUE < 0 ){
ObjectSetText( "TimeLabel11",
"RESULT: " + NormalizeDouble( deltaVALUE, Digits ) + "|v|",
fsize,
"Courier New",
Cyan // can be deltaVALUE specific too :o)
);
}
A few remarks on precision of float numbers
You may notice a use of NormalizeDouble()
This is rather important step, to avoid problems with comparison of floats.
If the precision of standard floats ( MQL4 double ) is not sufficient, you may opt-in to use extended precision numbers in MQL4. Check documentation for that.
However, always be carefull on float comparisons.
Best practice, to be on a safer side, is to use both NormalizeDouble() ( as a prevention )
and
comparing to some thresholdDELTA like if ( MathAbs( floatA - floatB ) < anEqualityTresholdDELTA ){ ... } rather than if ( floatA == floatB ) {...}

Resources