//+------------------------------------------------------------------+ //| xBest.mq4 | //| Copyright 2018, MetaQuotes Software Corp. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2018, MetaQuotes Software Corp." #property link "https://www.mql5.com" #property version "1.00" #property description "xBest - Grid Hedging Expert Advisor" #property description "================================================================" #property description "This EA init a cycle of buy or sell depending of signaling, it start with the base" #property description "lot and increase the size at every step by its factor and set a global take profit," #property description "if max trades is set the ea only open thats quantity orders, it will close trades if" #property description "max drawdown or expiry time are hit, also have trailing stop option." #property description "Coder: xJhamil, Mail: yamilhurtado@gmail.com" #property strict //--- input parameters input int InpSize=3; // Step Size in Pips input int InpTake=3; // Take Profit in Pips input int InpStop=0; // Trail Stop [0 means no Trail] input int InpLots=0; // Lot Percent [0 for Minimum Size] input int InpFactor=30; // Lot Increment Percent [Exponent Factor] input int InpTrades=0; // Max Trades [0 means no Limit] input int InpDown=0; // Drawdown Percent [0 means no Limit] input int InpExp=0; // Expiration in Hours [0 means no Expiry] //--- int SlipPage=3; int MagicNumber=7799; string m_symbol; double m_lots,m_size,m_take,m_stop,m_pip,m_factor; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- m_symbol=Symbol(); m_pip=1.0/MathPow(10,Digits-1); m_size=InpSize*m_pip; m_take=InpTake*m_pip; m_stop=InpStop*m_pip; m_factor=1.0+InpFactor/100.0; printf("xBest - Grid Hedging Expert Advisor"); //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { RefreshRates(); //--- Variable Declaration datetime order_open_time; double order_open_price,order_lots; double account_balance,margin_required; double order_stop,order_delta,weighted_take; double volume_min,volume_max,volume_step, lots; int order_ticket, order_type, orders_total, index, ticket; //--- Variable Initialization datetime time_current=TimeCurrent(); double ask_price=Ask, bid_price=Bid; double lots_sum=0.0, weighted_sum=0.0; int buyer_counter=0, seller_counter=0; int buy_ticket=0, sell_ticket=0, orders_count=0; bool short_condition=false, long_condition=false, was_trade=false; double buy_price=0.0, sell_price=0.0, orders_profit=0.0; //--- Base Lot Size volume_min=SymbolInfoDouble(m_symbol,SYMBOL_VOLUME_MIN); volume_step=SymbolInfoDouble(m_symbol,SYMBOL_VOLUME_STEP); if(InpLots>0) { account_balance=InpLots*AccountBalance()/100.0; margin_required=MarketInfo(m_symbol,MODE_MARGINREQUIRED); volume_max=SymbolInfoDouble(m_symbol,SYMBOL_VOLUME_MAX); m_lots=MathFloor(account_balance/margin_required,volume_step); } else m_lots=volume_min; //--- Calculation Loop orders_total=OrdersTotal(); for(index=orders_total-1;index>=0;index--) { if(!OrderSelect(index,SELECT_BY_POS,MODE_TRADES)) continue; if(OrderMagicNumber()!=MagicNumber||OrderSymbol()!=m_symbol) continue; order_open_price=OrderOpenPrice(); order_ticket=OrderTicket(); order_type=OrderType(); order_lots=OrderLots(); order_open_time=OrderOpenTime(); if(order_type==OP_BUY) { //--- Expiration Check if(InpExp>0&&time_current>=order_open_time+InpExp*3600) { if(OrderClose(order_ticket,order_lots,bid_price,SlipPage)) continue; } //--- Set Last Buy Order if(order_ticket>buy_ticket) { buy_price=order_open_price; buy_ticket=order_ticket; } //--- Trailing Stop if(InpStop>0) { order_stop=OrderStopLoss(); order_delta=MathFloor(bid_price-m_stop,m_pip); if(order_delta>order_stop) OrderModify(order_ticket,order_open_price,order_delta,OrderTakeProfit(),0); } buyer_counter++; } if(order_type==OP_SELL) { //--- Expiration Check if(InpExp>0&&time_current>=order_open_time+InpExp*3600) { if(OrderClose(order_ticket,order_lots,ask_price,SlipPage)) continue; } //--- Set Last Sell Order if(order_ticket>sell_ticket) { sell_price=order_open_price; sell_ticket=order_ticket; } //--- Trailing Stop if(InpStop>0) { order_stop=OrderStopLoss(); order_delta=MathCeil(ask_price+m_stop,m_pip); if(order_delta0) { double balance=AccountBalance(); if(orders_profit<0 && MathAbs(orders_profit)>InpDown*balance/100.0) { orders_total=OrdersTotal(); for(index=orders_total-1;index>=0;index--) { if(!OrderSelect(index,SELECT_BY_POS,MODE_TRADES)) continue; if(OrderMagicNumber()!=MagicNumber||OrderSymbol()!=m_symbol) continue; order_type=OrderType(); if(order_type==OP_BUY) OrderClose(OrderTicket(),OrderLots(),bid_price,SlipPage); if(order_type==OP_SELL) OrderClose(OrderTicket(),OrderLots(),ask_price,SlipPage); } orders_count=0; buyer_counter=0; seller_counter=0; weighted_sum=0.0; lots_sum=0.0; } } //--- Trade Conditions if(orders_count>0) { if(InpTrades==0||orders_count0&&buy_price-ask_price>=m_size) long_condition = true; if (seller_counter>0&&bid_price-sell_price>=m_size) short_condition = true; } } else { /* ### First Engine ### if(iHigh(NULL,0,1)>iLow(NULL,0,2)&&iRSI(NULL,PERIOD_H1,14,PRICE_CLOSE,1)>30.0) long_condition=true; if(iHigh(NULL,0,1)iClose(NULL,0,2)) long_condition=true; if(iClose(NULL,0,1)iClose(NULL,0,2)&&iRSI(NULL,PERIOD_H1,14,PRICE_CLOSE,1)>30.0) long_condition=true; if(iClose(NULL,0,1)iMA(NULL,0,3,0,MODE_EMA,PRICE_OPEN,0)) long_condition=true; if (iOpen(NULL,0,0)0) order_stop=ask_price-m_stop; ticket=OpenTrade(OP_BUY,lots,ask_price,order_stop); if(ticket>0) was_trade=true; } if(short_condition) { order_stop=0.0; if(InpStop>0) order_stop=bid_price+m_stop; ticket=OpenTrade(OP_SELL,lots,bid_price,order_stop); if(ticket>0) was_trade=true; } //--- Setup Global Take Profit if(was_trade) { //--- Recalc Values OrderSelect(ticket,SELECT_BY_TICKET); order_open_price=OrderOpenPrice(); weighted_sum+=order_open_price*lots; lots_sum+=lots; weighted_take=NormalizeDouble(weighted_sum/lots_sum,Digits); if(long_condition) weighted_take+=m_take; if(short_condition) weighted_take-=m_take; //--- Execution Loop orders_total=OrdersTotal(); for(index=orders_total-1;index>=0;index--) { if(!OrderSelect(index,SELECT_BY_POS,MODE_TRADES)) continue; if(OrderMagicNumber()!=MagicNumber||OrderSymbol()!=m_symbol) continue; order_type=OrderType(); if(order_type==OP_BUY) OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss(),weighted_take,0); if(order_type==OP_SELL) OrderModify(OrderTicket(),OrderOpenPrice(),OrderStopLoss(),weighted_take,0); } } } int OpenTrade(int cmd, double volume, double price, double stop=0.0, double take=0.0) { return OrderSend(m_symbol,cmd,volume,price,SlipPage,stop,take,NULL,MagicNumber,0); } //+------------------------------------------------------------------+ double MathRound(double x, double m) { return m*MathRound(x/m); } double MathFloor(double x, double m) { return m*MathFloor(x/m); } double MathCeil (double x, double m) { return m*MathCeil (x/m); }