Hello
Here is a code that passes validation
I think you are not checking per the limit of orders of the broker and whether or not trading is allowed for this symbol
if(IsConnected()&&IsTradeAllowed(Symbol(),TimeCurrent())&&(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)==1)&&!IsTradeContextBusy()) { int errors=0; ResetLastError(); int mot=OrdersTotal();errors+=GetLastError(); int cot=(int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS);errors+=GetLastError(); double lot=(double)MarketInfo(Symbol(),MODE_MINLOT);errors+=GetLastError(); if(errors==0&&mot<cot) { if(AccountFreeMarginCheck(Symbol(),OP_BUY,lot)>0&&GetLastError()==0) { lot=NormalizeDouble(lot,2); RefreshRates(); double ask=NormalizeDouble(Ask,Digits); int tick=OrderSend(Symbol(),OP_BUY,lot,ask,sim_slip,0,0,NULL,ot_magic,0,clrRed); } } }
I'm not sure if it's the cause, but you should not be reading market information in the global declarations ...
double Max_Lot = MarketInfo(Symbol(),MODE_MAXLOT)/1000;
You should not even be doing it in OnInit() event handler either.
You should only read market information after the first tick has arrived.
Also, MarketInfo() is the old MQL4 functions. Instead use the modern MQL4+/MQL5 functions for that. Here is an example ...
double dbLotsMinimum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MIN ), dbLotsMaximum = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_MAX ), dbLotsStep = SymbolInfoDouble( _Symbol, SYMBOL_VOLUME_STEP ), dbTickSize = SymbolInfoDouble( _Symbol, SYMBOL_TRADE_TICK_SIZE ), dbTickValue = SymbolInfoDouble( _Symbol, SYMBOL_TRADE_TICK_VALUE );
Hello
Here is a code that passes validation
I think you are not checking per the limit of orders of the broker and whether or not trading is allowed for this symbol
//+------------------------------------------------------------------+ //| Checks //+------------------------------------------------------------------+ if(count == 0) // Check no opened orders { if(DayOfWeek() != 0 || DayOfWeek() != 6) // Check market is opened { if(IsConnected()&&IsTradeAllowed(Symbol(),TimeCurrent())&&// check connection with server (TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)==1)&&// check Trade is allowed !IsTradeContextBusy()) // check Context isn't Busy { int errors=0; ResetLastError(); int mot=OrdersTotal();errors+=GetLastError(); int cot=(int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS);errors+=GetLastError(); double lot=(double)SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);errors+=GetLastError(); if(errors==0&&mot<cot) { //+------------------------------------------------------------------+ //| Open BUY Order //+------------------------------------------------------------------+ if(AccountFreeMarginCheck(Symbol(),OP_BUY,LotSize)>0&&GetLastError()==0) { lot=NormalizeDouble(lot,2); RefreshRates(); double ask=NormalizeDouble(Ask,Digits); if(MA90_1 - ask >= distance * pip && MACD5 < CCI_Min && IsNewCandle()) { if(CheckVolumeValue(LotSize,Desc)) { int TicketB = OrderSend(Symbol(),OP_BUY,LotSize,ask,3,0,0,NULL,0,0,clrGreen); if(TicketB < 1)Print("Error #",GetLastError(),"in a BUY Order"); count ++; Alert("Initial BUY Order Opened for ",OrderSymbol()); } } } //+------------------------------------------------------------------+ //| Open SELL Order //+------------------------------------------------------------------+ if(AccountFreeMarginCheck(Symbol(),OP_BUY,LotSize)>0&&GetLastError()==0) { lot=NormalizeDouble(lot,2); RefreshRates(); double bid=NormalizeDouble(Bid,Digits); if(bid - MA90_1 >= distance * pip && MACD5 > CCI_Max && IsNewCandle()) { if(CheckVolumeValue(LotSize,Desc)) { int TicketS = OrderSend(Symbol(),OP_SELL,LotSize,bid,3,0,0,NULL,0,0,clrRed); if(TicketS < 1) Print("Error #",GetLastError(),"in a SELL Order"); count ++; Alert("Initial SELL Order Opened for ",OrderSymbol()); } } } } } } }
I'm not sure if it's the cause, but you should not be reading market information in the global declarations ...
You should not even be doing it in OnInit() event handler either.
You should only read market information after the first tick has arrived.
Also, MarketInfo() is the old MQL4 functions. Instead use the modern MQL4+/MQL5 functions for that. Here is an example ...
thanks, I took your advice into consideration in the above code.
Thank you for replying me. I included the code that you mentioned above but it didn't work either. Can you please check if I'm included it the right way?
Okay i think some checks changed again . I just passed the below code .
If i'm not mistaken the tester may fail in SymbolInfo requests so it should have an alternative for MarketInfo on lots.(that or i should use Symbol() , or they are testing on old terminals too)
The following code may have issues in the margin calculation , does not account for ECN types and does not handle Freeze Level which i'm not experienced with.
The rest is okay and passed in a hidden project that i have in the market for testing .
here is the all in one trade code in its test form (this ea passed as is).
#property version "33.00" #property strict datetime barstamp=0; int clock=0,clock_limit=7; int OnInit() { barstamp=0; clock=0; return(INIT_SUCCEEDED); } void OnDeinit(const int reason) { } void OnTick() { if(Time[0]>barstamp){ barstamp=Time[0]; clock++; if(clock==clock_limit){ clock=0; if(MathRand()>16000){ trade_result result=SafeMarketTrade(OP_BUY,0.01,10,false,10,false,false,1.5,10,333,1000,23,NULL,clrBlue); if(!result.success){ Print(result.error_message); } } else{ trade_result result=SafeMarketTrade(OP_SELL,0.01,Ask+(10*_Point),true,0.0,false,false,1.5,10,333,1000,23,NULL,clrRed); if(!result.success){ Print(result.error_message); } } }} } struct trade_result{ bool success; int ticket; double open_price; double initial_price,ask,bid,spread; double stop_loss; double take_profit; double lots; double margin_used; datetime open_time; int slippage; int attempts; long time_to_open_ms; string error_message; trade_result(void){reset();} ~trade_result(void){reset();} void reset(){ success=false; ticket=-1; attempts=0; error_message=""; } }; trade_result SafeMarketTrade(ENUM_ORDER_TYPE direction,//buy or sell double lots,//the volume of the trade double sl,//stop loss price or distance from entry price bool sl_is_price,//true if stop loss is not distance double tp,//take profit price or distance from entry price bool tp_is_price,//true if take profit is not distance bool reject_if_stops_too_close,//reject trade if stops are too close for broker double stops_expansion_multiple_of_limit,//if not rejecting trade for stop level , expand by this much (off of the limit) int max_attempts,//max attempts to open uint timeout,//timeout between attempts int max_slippage,//max allowed slippage int magic_number, string order_comment, color clr){ trade_result result; //log the start ms result.time_to_open_ms=GetTickCount(); //create id for the order attempt string id="{"+_Symbol+" "+EnumToString(direction)+" "+DoubleToString(lots,2)+" #Magic("+IntegerToString(magic_number)+")'"+order_comment+"'}"; //Proper Type if(direction==OP_BUY||direction==OP_SELL) { //Context and Connection if(!IsTradeContextBusy()&&IsConnected()) { //total orders and account limits ResetLastError(); int account_orders_limit=(int)AccountInfoInteger(ACCOUNT_LIMIT_ORDERS); if(GetLastError()==0&&OrdersTotal()<account_orders_limit){ //Trade allowance ResetLastError(); if(IsTradeAllowed(_Symbol,TimeCurrent())&&(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)==1)&&GetLastError()==0){ //minlot , maxlot , step , total max ResetLastError(); bool volumes_acquired=true; double volume_min=(double)SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN); if(GetLastError()!=0){ ResetLastError(); volume_min=(double)MarketInfo(_Symbol,MODE_MINLOT); if(GetLastError()!=0){volumes_acquired=false;} } ResetLastError(); double volume_max=(double)SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MAX); if(GetLastError()!=0&&volumes_acquired){ ResetLastError(); volume_max=(double)MarketInfo(_Symbol,MODE_MAXLOT); if(GetLastError()!=0){volumes_acquired=false;} } ResetLastError(); double volume_step=(double)SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP); if(GetLastError()!=0&&volumes_acquired){ ResetLastError(); volume_step=(double)MarketInfo(_Symbol,MODE_LOTSTEP); if(GetLastError()!=0){volumes_acquired=false;} } ResetLastError(); double volume_limit=(double)SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_LIMIT); if(GetLastError()!=0){volume_limit=0.0;} if(volumes_acquired){ //check against step int steps=(int)(MathFloor(lots/volume_step)); lots=((double)steps)*volume_step; if(lots<volume_min){lots=volume_min;} else if(lots>volume_max){lots=volume_max;} //Total symbol volume double total_symbol_volume=get_symbol_volume(_Symbol,true)+lots; if(total_symbol_volume<volume_limit||volume_limit<=0.0){ //get max available margin with margin of error on top double max_available_margin=get_max_available_margin_with_error_margin(0.2);//20% buffer //free margin check //the free margin remaining must be above free margin - max available free margin double margin_min=AccountFreeMargin()-max_available_margin; ResetLastError(); if(AccountFreeMarginCheck(_Symbol,direction,lots)>margin_min&&GetLastError()==0){ //turn all stops to distance if they are not and catch the first price double sl_ticks=0.0,tp_ticks=0.0; RefreshRates(); result.ask=Ask; result.bid=Bid; if(direction==OP_BUY){result.initial_price=Ask;} else{result.initial_price=Bid;} //get stop level limit ResetLastError(); double stop_limit=((double)SymbolInfoInteger(_Symbol,SYMBOL_TRADE_STOPS_LEVEL))*_Point; if(GetLastError()==0){ //stop loss if(sl!=0.0){ if(sl_is_price){ if(direction==OP_BUY){ sl_ticks=result.bid-sl; }else{ sl_ticks=sl-result.ask; } } else{ sl_ticks=sl*_Point; } //if the stop loss is below the limit and the limit is not zero if(stop_limit>0.0&&sl_ticks<=stop_limit){ //adjust or reject if(reject_if_stops_too_close){ result.error_message="SL is too close , rejecting trade "+id; return(result); } else{ sl_ticks=NormalizeDouble(stop_limit*stops_expansion_multiple_of_limit,_Digits); } } } //stop loss ends here //take profit if(tp!=0.0){ if(tp_is_price){ if(direction==OP_BUY){ tp_ticks=tp-result.ask; }else{ tp_ticks=result.bid-tp; } } else{ tp_ticks=tp*_Point; } //if the take profit is below the limit and the limit is not zero if(stop_limit>0.0&&tp_ticks<=stop_limit){ //adjust or reject if(reject_if_stops_too_close){ result.error_message="TP is too close , rejecting trade "+id; return(result); } else{ tp_ticks=NormalizeDouble(stop_limit*stops_expansion_multiple_of_limit,_Digits); } } } //take profit ends here /* At this point we have everything we need now we will start attempting to place the trade */ //TRADE double fm_snap=0.0; while(result.ticket==-1&&result.attempts<max_attempts){ result.attempts++; RefreshRates(); result.ask=Ask; result.bid=Bid; fm_snap=AccountFreeMargin(); if(direction==OP_BUY){result.open_price=Ask;}else{result.open_price=Bid;} //format sl + tp ,we have the ticks so we can use sl , tp variables if(sl_ticks!=0.0){ if(direction==OP_BUY){ sl=result.bid-sl_ticks; }else{ sl=result.ask+sl_ticks; } } if(tp_ticks!=0.0){ if(direction==OP_BUY){ tp=result.ask+tp_ticks; }else{ tp=result.bid-tp_ticks; } } ResetLastError(); result.ticket=OrderSend(_Symbol,direction,lots,result.open_price,max_slippage,sl,tp,order_comment,magic_number,0,clr); Sleep(timeout); } //TRADE ENDS HERE //if trade failed if(result.ticket==-1){ result.error_message="Trade failed error#"+IntegerToString(GetLastError())+" "; } //if trade succeeded else{ result.success=true; //time to open long endms=GetTickCount(); if(endms<result.time_to_open_ms){ result.time_to_open_ms=UINT_MAX-result.time_to_open_ms+endms; }else{ result.time_to_open_ms=endms-result.time_to_open_ms; } //spread result.spread=result.ask-result.bid; //margin used result.margin_used=fm_snap-AccountFreeMargin(); //select for more info if(OrderSelect(result.ticket,SELECT_BY_TICKET)){ result.open_price=OrderOpenPrice(); result.open_time=OrderOpenTime(); result.lots=OrderLots(); result.stop_loss=OrderStopLoss(); result.take_profit=OrderTakeProfit(); //slippage if(direction==OP_BUY){ result.slippage=(int)((result.initial_price-result.open_price)/_Point); }else{ result.slippage=(int)((result.open_price-result.initial_price)/_Point); } } } //if trade succeeded ends here } else{ result.error_message="Cannot get stops level "; } //get stop level limit ends here }else{ result.error_message="Not enough margin for lots "; } //free margin check ends here }else{ result.error_message="Volume will exceed total limit "; } //Total symbol volume ends here }else{ result.error_message="Cannot acquire symbol volume info "; } //minlot , maxlot , step ,total max ends here }else{ if(!IsTradeAllowed(_Symbol,TimeCurrent())){result.error_message="Trade not possible for symbol ";} if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)==0){result.error_message+="Trade switch is off ";} } //Trade allowance ends here }else{ result.error_message="Total orders account limit reached "; } //total orders and account limits ends here }else{ if(IsTradeContextBusy()){result.error_message="Trade Context Busy ";} if(!IsConnected()){result.error_message+="No Connection ";} } //Context and Connection Ends Here }else{ result.error_message="Wrong trade type.Market orders only please "; } //Proper Type Ends Here result.error_message+=id; return(result); } double get_symbol_volume(string _symbol,bool only_live_orders){ double sum=0.0; for(int i=0;i<OrdersTotal();i++){ if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)){ if(!only_live_orders||(OrderType()==OP_BUY||OrderType()==OP_SELL)){ sum+=OrderLots(); }}} return(sum); } double get_max_available_margin_with_error_margin(double error_margin_buffer_percent){ double avail_margin=0.0; ResetLastError(); int margin_call_mode=AccountStopoutMode();//https://docs.mql4.com/account/accountstopoutmode if(GetLastError()==0){ //if absolute value mode if(margin_call_mode==1){ avail_margin=AccountFreeMargin()-AccountStopoutLevel(); } //if % mode else if(margin_call_mode==0){ double min_ratio=AccountStopoutLevel(); //at min ratio the margin must be double margin_at_min=AccountEquity()/(min_ratio/100.0); avail_margin=MathMin(margin_at_min-AccountMargin(),AccountFreeMargin()); } //and margin of error avail_margin-=avail_margin*error_margin_buffer_percent; } return(avail_margin); }Edit : Volume limit should not reject the acquisition switch of lots in case the broker does not support it , or its not supported at all i guess . That means maybe the symbol info doubles are working too . This works however .
Okay i think some checks changed again . I just passed the below code .
If i'm not mistaken the tester may fail in SymbolInfo requests so it should have an alternative for MarketInfo on lots.(that or i should use Symbol() , or they are testing on old terminals too)
The following code may have issues in the margin calculation , does not account for ECN types and does not handle Freeze Level which i'm not experienced with.
The rest is okay and passed in a hidden project that i have in the market for testing .
here is the all in one trade code in its test form (this ea passed as is).
Edit : Volume limit should not reject the acquisition switch of lots in case the broker does not support it , or its not supported at all i guess . That means maybe the symbol info doubles are working too . This works however .Thanks. I will try to fit it to my EA.
- 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 guys.
I have the issue which faced most developers on this website (no trading operations). I hope someone helps me find what checks are required to pass this validation. (I tried check for lot size validity, enough money, valid ticket) knowing that the code run perfectly on tester (specially on the symbols mentioned in the test report.
here is the complete code for the EA (comments on the code may help you understand the idea)
----------------------------------------------------------------------------------------------------------------------