//+------------------------------------------------------------------+ //| sonic | //| Copyright 2021, NhatNamBe | //| | //+------------------------------------------------------------------+ #include #include #include //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int GetStepWise(ENUM_POSITION_TYPE posType) { return (posType==POSITION_TYPE_BUY)?1:-1; } //+------------------------------------------------------------------+ //|Check trading account will be used for bot's operation | //+------------------------------------------------------------------+ int CheckAccount() { //--- unable to trade on a real account CAccountInfo account; long login=account.Login(); Print("Login:", login); ENUM_ACCOUNT_TRADE_MODE account_type=account.TradeMode(); if(account_type==ACCOUNT_TRADE_MODE_REAL) { Alert("Expert Advisor cannot trade on a real account!"); return(-2); } Print("Account type: ", EnumToString(account_type)); //--- check if it is possible to trade on this account (for example, trading is impossible when using an investor password) if(account.TradeAllowed()) Print("Trading on this account is allowed"); else { Print("Trading on this account is forbidden: you may have entered using the Investor password"); return(-3); } //--- clarifying if we can use an Expert Advisor on this account if(account.TradeExpert()) Print("Automated trading on this account is allowed"); else { Print("Automated trading using Expert Advisors and scripts on this account is forbidden"); return(-4); } //--- clarifying if the permissible number of orders has been set int orders_limit=account.LimitOrders(); if(orders_limit!=0) Print("Maximum permissible amount of active pending orders: ",orders_limit); //--- displaying company and server names Print(account.Company(),": server ",account.Server()); //--- displaying balance and current profit on the account in the end Print("Balance=",account.Balance()," Profit=",account.Profit()," Equity=",account.Equity()); Print(__FUNCTION__," completed"); //--- return(0); } //+------------------------------------------------------------------+ //| Get properties of the symbol | //+------------------------------------------------------------------+ void GetSymbolInfo() { //--- object for receiving symbol settings CSymbolInfo symbol_info; //--- set the name for the appropriate symbol symbol_info.Name(_Symbol); //--- receive current rates and display symbol_info.RefreshRates(); Print(symbol_info.Name()," (",symbol_info.Description(),")", " Bid=",symbol_info.Bid()," Ask=",symbol_info.Ask()); //--- receive minimum freeze levels for trade operations Print("StopsLevel=",symbol_info.StopsLevel()," pips, FreezeLevel=", symbol_info.FreezeLevel()," pips"); //--- receive the number of decimal places and point size Print("Digits=",symbol_info.Digits(), ", Point=",DoubleToString(symbol_info.Point(),symbol_info.Digits())); //--- spread info Print("SpreadFloat=",symbol_info.SpreadFloat(),", Spread(current)=", symbol_info.Spread()," pips"); //--- request order execution type for limitations Print("Limitations for trade operations: ",EnumToString(symbol_info.TradeMode()), " (",symbol_info.TradeModeDescription(),")"); //--- clarifying trades execution mode Print("Trades execution mode: ",EnumToString(symbol_info.TradeExecution()), " (",symbol_info.TradeExecutionDescription(),")"); //--- clarifying contracts price calculation method Print("Contract price calculation: ",EnumToString(symbol_info.TradeCalcMode()), " (",symbol_info.TradeCalcModeDescription(),")"); //--- sizes of contracts Print("Standard contract size: ",symbol_info.ContractSize(), " (",symbol_info.CurrencyBase(),")"); //--- minimum and maximum volumes in trade operations Print("Volume info: LotsMin=",symbol_info.LotsMin()," LotsMax=",symbol_info.LotsMax(), " LotsStep=",symbol_info.LotsStep()); //--- Print(__FUNCTION__," completed"); } //+------------------------------------------------------------------+ //| Place Order | //+------------------------------------------------------------------+ ulong PlaceOrder(const string symbol,const ENUM_POSITION_TYPE pos_type,const ENUM_ORDER_TYPE order_type,const double volume, const double price,const double sl_value,const double tp_value,const string comment,const bool retry=true) { CTrade trade; bool ret; double TP=0; double SL=0; //--- number of decimal places int digits=(int)SymbolInfoInteger(_Symbol,SYMBOL_DIGITS); //--- calculate and normalize SL and TP levels if(sl_value) SL=NormalizeDouble(price-GetStepWise(pos_type)*sl_value,digits); if(tp_value) TP=NormalizeDouble(price+GetStepWise(pos_type)*tp_value,digits); if(order_type==ORDER_TYPE_BUY || order_type==ORDER_TYPE_SELL) ret=trade.PositionOpen(symbol,order_type,volume,price,SL,TP,comment); else ret=trade.OrderOpen(symbol,order_type,volume,0,price,SL,TP,ORDER_TIME_GTC,0,comment); if(!ret) { if(retry) { //--- failed to place limit order cause price is moving to market, replace while(!ret) { //--- failure message DebugBreak(); Print("PlaceOrder() method failed. Return code=",trade.ResultRetcode(), ". Code description: ",trade.ResultRetcodeDescription()); double newPrice; if(order_type==ORDER_TYPE_BUY || order_type==ORDER_TYPE_SELL) //--- market order newPrice=(pos_type==POSITION_TYPE_BUY)?SymbolInfoDouble(_Symbol,SYMBOL_ASK):SymbolInfoDouble(_Symbol,SYMBOL_BID); else //--- limit order newPrice=(pos_type==POSITION_TYPE_BUY)?SymbolInfoDouble(_Symbol,SYMBOL_BID):SymbolInfoDouble(_Symbol,SYMBOL_ASK); //--- calculate and normalize SL and TP levels double orderPrice; if(newPrice*GetStepWise(pos_type) < price*GetStepWise(pos_type)) orderPrice=newPrice; else orderPrice=price; if(sl_value) SL=NormalizeDouble(orderPrice-GetStepWise(pos_type)*sl_value,digits); if(tp_value) TP=NormalizeDouble(orderPrice+GetStepWise(pos_type)*sl_value,digits); if(order_type==ORDER_TYPE_BUY || order_type==ORDER_TYPE_SELL) ret=trade.PositionOpen(symbol,order_type,volume,orderPrice,SL,TP,comment); else ret=trade.OrderOpen(symbol,order_type,volume,0,orderPrice,SL,TP,ORDER_TIME_GTC,0,comment); } Print("PlaceOrder() method executed successfully order ticket: ",trade.ResultOrder(),". Return code=",trade.ResultRetcode(), " (",trade.ResultRetcodeDescription(),")"); return(trade.ResultOrder()); } else { //--- failure message Print("PlaceOrder() method failed. Return code=",trade.ResultRetcode(), ". Code description: ",trade.ResultRetcodeDescription()); return(-1); } } else { Print("PlaceOrder() method executed successfully order ticket: ",trade.ResultOrder(),". Return code=",trade.ResultRetcode(), " (",trade.ResultRetcodeDescription(),")"); return(trade.ResultOrder()); } } //+------------------------------------------------------------------+ //| convert numeric response codes to string mnemonics | //+------------------------------------------------------------------+ string GetRetcodeID(int retcode) { switch(retcode) { case 10004: return("TRADE_RETCODE_REQUOTE"); break; case 10006: return("TRADE_RETCODE_REJECT"); break; case 10007: return("TRADE_RETCODE_CANCEL"); break; case 10008: return("TRADE_RETCODE_PLACED"); break; case 10009: return("TRADE_RETCODE_DONE"); break; case 10010: return("TRADE_RETCODE_DONE_PARTIAL"); break; case 10011: return("TRADE_RETCODE_ERROR"); break; case 10012: return("TRADE_RETCODE_TIMEOUT"); break; case 10013: return("TRADE_RETCODE_INVALID"); break; case 10014: return("TRADE_RETCODE_INVALID_VOLUME"); break; case 10015: return("TRADE_RETCODE_INVALID_PRICE"); break; case 10016: return("TRADE_RETCODE_INVALID_STOPS"); break; case 10017: return("TRADE_RETCODE_TRADE_DISABLED"); break; case 10018: return("TRADE_RETCODE_MARKET_CLOSED"); break; case 10019: return("TRADE_RETCODE_NO_MONEY"); break; case 10020: return("TRADE_RETCODE_PRICE_CHANGED"); break; case 10021: return("TRADE_RETCODE_PRICE_OFF"); break; case 10022: return("TRADE_RETCODE_INVALID_EXPIRATION"); break; case 10023: return("TRADE_RETCODE_ORDER_CHANGED"); break; case 10024: return("TRADE_RETCODE_TOO_MANY_REQUESTS"); break; case 10025: return("TRADE_RETCODE_NO_CHANGES"); break; case 10026: return("TRADE_RETCODE_SERVER_DISABLES_AT"); break; case 10027: return("TRADE_RETCODE_CLIENT_DISABLES_AT"); break; case 10028: return("TRADE_RETCODE_LOCKED"); break; case 10029: return("TRADE_RETCODE_FROZEN"); break; case 10030: return("TRADE_RETCODE_INVALID_FILL"); break; case 10031: return("TRADE_RETCODE_CONNECTION"); break; case 10032: return("TRADE_RETCODE_ONLY_REAL"); break; case 10033: return("TRADE_RETCODE_LIMIT_ORDERS"); break; case 10034: return("TRADE_RETCODE_LIMIT_VOLUME"); break; case 10035: return("TRADE_RETCODE_INVALID_ORDER"); break; case 10036: return("TRADE_RETCODE_POSITION_CLOSED"); break; default: return("TRADE_RETCODE_UNKNOWN="+IntegerToString(retcode)); break; } //--- } //+------------------------------------------------------------------+