Navigation:Home > Content >

Xavier-MaxPosition.mq4

Time: 2012-01-06 | Download file:Xavier-MaxPosition.mq4

//+------------------------------------------------------------------+
//|                                           Xavier-MaxPosition.mq4 |
//|                                    Copyright © 2009, MQL Service |
//|                                        http://www.mqlservice.net |
//+------------------------------------------------------------------+
//| $Id: //mqlservice/mt4files/experts/Xavier-MaxPosition.mq4#2 $
//+------------------------------------------------------------------+
#property copyright "Copyright © 2009, MQL Service"
#property link      "http://www.mqlservice.net"
#include 
#include 

//--- Standard parameters
extern bool      Buy            = false;
extern bool      Sell           = false;
extern bool      ContinueTrading = false; // When false do only the initial trade, true = buy/sell more when there is free margin
extern double    TradeMaxRisk   = 100;    // TradeMaxRisk > 0 so much % risk will be used, either based on SL or Account equity
extern int       StopLoss       = 30;   // 0 deactivates Stop Loss
extern int       StartTrail     = 0;    // Start trail after so many pips.
extern int       TrailingStop   = 0;    // 0 deactivates Trailing Stop
extern int       TrailStep      = 1;    // With which increments TS moves
extern int       TakeProfit     = 0;    // 0 deactivates Take Profit
extern int       GainForBE      = 0;    // How many pips will trigger Break Even. 0 deactivates.
extern int       PipsBE         = 0;    // Level at which Break Even will be put
extern int       Slippage     = 3;
bool      UseMultiMagic = false; // Allows for the same EA on the same symbol and TF
int       Magic         = 20090511;
//---- Debugging
extern bool      DoScreenShots = false; // Makes screen shots when a trade is open

// Automatic Magic setting
#define SEM "SEM"
#define MAG "MAG"
#define TIMEOUT 10 // 10 seconds for GV
int MAGIC = 0;

int init()
{
  if(!IsTesting())
  if(UseMultiMagic)
  {
    if(MAGIC==0)
    {
      datetime _now = TimeLocal();
      if(!GlobalVariableCheck(SEM)) GlobalVariableSet(SEM,0);
      while(!GlobalVariableSetOnCondition(SEM, 1, 0))
      {
        Sleep(333);
        if(TimeLocal() > _now+TIMEOUT) break;
      }
      while(GlobalVariableCheck(MAG+Symbol()+Magic)) Magic++;
      GlobalVariableSet(MAG+Symbol()+Magic, Magic);
      GlobalVariableSet(SEM, 0);
    } else // MAGIC!=0
    {
      Magic = MAGIC;
      GlobalVariableSet(MAG+Symbol()+Magic, Magic);
    }
  }
  Comment("Waiting for the first tick... (magic==",Magic,")");
  Print("$Id: //mqlservice/mt4files/experts/Xavier-MaxPosition.mq4#2 $");
  Print("Copyright © 2008, MQL Service", ", ", "http://www.mqlservice.net", " magic==",Magic);
  return(0);
}

int deinit()
{
  if(!IsTesting())
  switch(UninitializeReason())
  {
    case REASON_CHARTCLOSE:
    case REASON_REMOVE:      
    case REASON_RECOMPILE:   GlobalVariableDel(MAG+Symbol()+Magic); MAGIC=0; break; // cleaning up and deallocation of all resources.
    case REASON_CHARTCHANGE:
    case REASON_PARAMETERS:
    case REASON_ACCOUNT:     MAGIC=Magic; break;  // prepare to restart
  }
  Comment(WindowExpertName()," (magic==",Magic,") finished.");
  return(0);
}

int start()
{
  static datetime _tick=0;
  if(_tick > 0)
    if((TimeCurrent()-_tick) > Period()*60)
      Print("Warning: Missed candle!");
  _tick = TimeCurrent();

  if(Bars<100)
  {
    Comment("Waiting for bars...");
    return(0);
  }

  double _lots;
  {
    _lots = _MM(TradeMaxRisk, Symbol(), StopLoss);
  }
  return(_Expert(Symbol(), Period(), Magic, _lots, StopLoss, StartTrail, TrailingStop, TrailStep,
                 TakeProfit, GainForBE, PipsBE, Slippage));
}

int _Expert(string symbol, int period, int magic, double lots, int stoploss, int starttrail, int trailingstop, int trailstep,
            int takeprofit, int gainforbe, int pipsbe, int slippage)
{
  // Internals
  int _Digits = MarketInfo(symbol, MODE_DIGITS), i;
  if(_Digits == 0) _Digits = 4;
  double _Point = MarketInfo(symbol, MODE_POINT);
  if(NormalizeDouble(_Point, _Digits) == 0.0) _Point = Point;
  double _Bid = MarketInfo(symbol, MODE_BID);
  double _Ask = MarketInfo(symbol, MODE_ASK);
  int    _spread = MathRound((_Ask-_Bid)/_Point);
  int   _iBid = MathRound(_Bid/_Point);
  int   _iAsk = MathRound(_Ask/_Point);
  string _cm = "";
  static datetime _bt = 0;
  
  if(_Digits==3||_Digits>4)
  {
    stoploss     *= 10;
    starttrail   *= 10;
    trailingstop *= 10;
    trailstep    *= 10;
    takeprofit   *= 10;
    gainforbe    *= 10;
    pipsbe       *= 10;
    slippage     *= 10;
  }

  Comment(_cm);
  WindowRedraw();

  // S&R
  if(stoploss > 0) stoploss = MathMax(1, stoploss-_spread);
  if(takeprofit > 0) takeprofit = MathMax(1, takeprofit+_spread);


  if(Buy)
  {
    _cm = StringConcatenate("Max Lots=",lots,"\nFree margin check=",AccountFreeMarginCheck(symbol, OP_BUY, lots),
                            "\nStopout=",AccountStopoutLevel());
    
    if(AccountFreeMarginCheck(symbol, OP_BUY, lots)>0&&(GetLastError()!=134))
      if(_OrderSend(symbol, OP_BUY, _nv(symbol, lots), _Ask, slippage, _sl(OP_BUY, symbol, _Bid, stoploss), _tp(OP_BUY, symbol, _Bid, takeprofit),
                 WindowExpertName(), magic, 0, Blue)>0)
                 Buy=ContinueTrading;
  }
  
  if(Sell)
  {
    _cm = StringConcatenate("Max Lots=",lots,"\nFree margin check=",AccountFreeMarginCheck(symbol, OP_SELL, lots),
                            "\nStopout=",AccountStopoutLevel());
    if(AccountFreeMarginCheck(symbol, OP_SELL, lots)>0&&(GetLastError()!=134))
      if(_OrderSend(symbol, OP_SELL, _nv(symbol, lots), _Bid, slippage, _sl(OP_SELL, symbol, _Ask, stoploss), _tp(OP_SELL, symbol, _Ask, takeprofit),
                            WindowExpertName(), magic, 0, Red)>0)
                            Sell = ContinueTrading;
  }
  // S&R

  // TrailingStop
  if(trailingstop > 0)
    for(i=0; i < OrdersTotal(); i++)
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)){
        if(OrderSymbol() == symbol)
          if(OrderMagicNumber() == magic)
            if(OrderType() == OP_BUY){
              if(MathRound((OrderClosePrice()-OrderOpenPrice())/_Point) > starttrail)
              if(MathRound((OrderClosePrice()-OrderStopLoss())/_Point) >= trailingstop+trailstep)
                _OrderModify(OrderTicket(), OrderOpenPrice(), OrderClosePrice()-trailingstop*_Point, OrderTakeProfit(),
                                OrderExpiration(), Blue);
            }else if(OrderType() == OP_SELL){
              if(MathRound((OrderOpenPrice()-OrderClosePrice())/_Point) > starttrail)
              if((MathRound((OrderStopLoss()-OrderClosePrice())/_Point) >= trailingstop+trailstep)||(OrderStopLoss()<_Bid))
                _OrderModify(OrderTicket(), OrderOpenPrice(), OrderClosePrice()+trailingstop*_Point, OrderTakeProfit(),
                                OrderExpiration(), Red);
            }
      }else
        Print("OrderSelect() error - ", ErrorDescription(GetLastError()));
  // TrailingStop

  // BreakEven
  if(gainforbe > 0)
    for(i=0; i < OrdersTotal(); i++)
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)){
        if(OrderSymbol() == symbol)
          if(OrderMagicNumber() == magic)
            if(OrderType() == OP_BUY){
              if(MathRound((OrderClosePrice()-OrderOpenPrice())/_Point) >= gainforbe)
              if(MathRound((OrderStopLoss()-OrderOpenPrice())/_Point) < pipsbe)
                _OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()+pipsbe*_Point, OrderTakeProfit(),
                                OrderExpiration(), Blue);
            }else if(OrderType() == OP_SELL){
              if(MathRound((OrderOpenPrice()-OrderClosePrice())/_Point) >= gainforbe)
              if(MathRound((OrderOpenPrice()-OrderStopLoss())/_Point) < pipsbe||(OrderStopLoss()==0))
                _OrderModify(OrderTicket(), OrderOpenPrice(), OrderOpenPrice()-pipsbe*_Point, OrderTakeProfit(),
                                OrderExpiration(), Red);
            }
      }else
        Print("OrderSelect() error - ", ErrorDescription(GetLastError()));
  // BreakEven

  Comment(_cm);
  return(0);
}

double _sl(int type, string symbol, double price, int stoploss, int offset=0, bool obey_stoplevel=true)
{
  if(obey_stoplevel)
    if(stoploss > 0)
      stoploss = MathMax(stoploss, (MarketInfo(symbol, MODE_STOPLEVEL)));
  if(type == OP_BUY||type == OP_BUYSTOP||type == OP_BUYLIMIT)
    if(stoploss > 0)
      return(price-(stoploss+offset)*MarketInfo(symbol, MODE_POINT));
    else
      return(0.0);
  else if(type == OP_SELL||type == OP_SELLSTOP||type == OP_SELLLIMIT)
    if(stoploss > 0)
      return(price+(stoploss+offset)*MarketInfo(symbol, MODE_POINT));
    else
      return(0.0);    
  return(0.0);
}

double _tp(int type, string symbol, double price, int takeprofit, int offset=0, bool obey_stoplevel=true)
{
  if(obey_stoplevel)
    if(takeprofit>0)
      takeprofit = MathMax(takeprofit,(MarketInfo(symbol, MODE_STOPLEVEL)));
  if(type == OP_BUY||type == OP_BUYSTOP||type == OP_BUYLIMIT)
    if(takeprofit > 0)
      return(price+(takeprofit+offset)*MarketInfo(symbol, MODE_POINT));
    else
      return(0.0);
  else if(type == OP_SELL||type == OP_SELLSTOP||type == OP_SELLLIMIT)
    if(takeprofit > 0)
      return(price-(takeprofit+offset)*MarketInfo(symbol, MODE_POINT));
    else
      return(0.0);
  return(0.0);
}

double _nv(string symbol, double lots, bool return_zero=false){
  // Adjust trade volume to broker. Take into account minimum & maximum position size.
  double step   = MarketInfo(symbol, MODE_LOTSTEP);
  double min    = MarketInfo(symbol, MODE_MINLOT);
  double max    = MarketInfo(symbol, MODE_MAXLOT);
  if(step > 0)
  if(max  > 0)
    if(return_zero)
      return(MathMin(MathRound(lots/step)*step, max));
    else if(min > 0) // When you don't want return 0 lots (default)
      return(MathMax(MathMin(MathRound(lots/step)*step, max), min));    
  return(lots);
}

int _OrderSend(string symbol, int cmd, double lots, double price, int slippage, double stoploss, double takeprofit,
               string comment, int magic, datetime expiration, color cl)
// Adds 1R to the order comment
{
  if(lots==0)
  {
    Print("Invalid lots: ",lots);
    return(-1);
  }
  string _sc = _strcmd(cmd, symbol, price, stoploss, takeprofit);
  double _point = MarketInfo(symbol, MODE_POINT);
  if(_point > 0)
    if(stoploss > 0)
      string _rp = StringConcatenate(DoubleToStr(MathAbs((price-stoploss)/_point), 0),":",DoubleToStr(lots*MathAbs((price-stoploss)/_point)*MarketInfo(symbol, MODE_TICKVALUE),2),AccountCurrency());
    else
    {
      double _ts = MarketInfo(symbol, MODE_TICKSIZE);
      if(_ts==0) _ts = 10;
      double _lev = AccountStopoutLevel();
      if(AccountStopoutMode()==0)
        double _max=AccountEquity()*(1.0-_lev/100.0);
      else
        _max=AccountEquity()-_lev;
      _rp = StringConcatenate(DoubleToStr(_max/_ts/lots, 0),":",DoubleToStr(_max,2),AccountCurrency(),":MC");
    }
  int ticket = OrderSend(symbol, cmd, lots, price, slippage, stoploss, takeprofit, StringConcatenate("R=",_rp,":",comment), magic, expiration, cl);
  if(ticket < 0){
    int err = GetLastError();
    //#define ERR_TRADE_NOT_ALLOWED                      4109
    //#define ERR_LONGS__NOT_ALLOWED                     4110
    //#define ERR_SHORTS_NOT_ALLOWED                     4111
    if((err==4109) || (err==4110) || (err==4111)) return(-1);    
    Print("ERROR OrderSend #",err,": ", ErrorDescription(err),_sc);
    if(DoScreenShots){_MakeScreenShot(symbol, "OrderSend ERROR"+ErrorDescription(err)+_sc);}
  }else
    if(DoScreenShots){_MakeScreenShot(symbol, "OrderSend"+_sc);}
  return(ticket);
}

string _strcmd(int cmd, string symbol, double price, double sl, double tp)
{
  int _mode = MODE_BID;
  int _d = MarketInfo(symbol, MODE_DIGITS);
  string _str = "";
  switch(cmd)
  {
    case OP_BUY: 
      _mode = MODE_ASK;
      _str  = ";BUY@"+DoubleToStr(price, _d)+";SL"+DoubleToStr(sl, _d)+";TP"+DoubleToStr(tp, _d);
      break;
    case OP_SELL:
      _mode = MODE_BID;
      _str  = ";SELL@"+DoubleToStr(price, _d)+";SL"+DoubleToStr(sl, _d)+";TP"+DoubleToStr(tp, _d);
      break;
    case OP_BUYSTOP:
      _mode = MODE_ASK;
      _str  = ";BUYSTOP@"+DoubleToStr(price, _d)+";SL"+DoubleToStr(sl, _d)+";TP"+DoubleToStr(tp, _d);
      break;
    case OP_BUYLIMIT:
      _mode = MODE_ASK;
      _str  = ";BUYLIMIT@"+DoubleToStr(price, _d)+";SL"+DoubleToStr(sl, _d)+";TP"+DoubleToStr(tp, _d);
      break;
    case OP_SELLSTOP:
      _mode = MODE_BID;
      _str  = ";SELLSTOP@"+DoubleToStr(price, _d)+";SL"+DoubleToStr(sl, _d)+";TP"+DoubleToStr(tp, _d);
      break;
    case OP_SELLLIMIT:
      _mode = MODE_BID;
      _str  = ";SELLLIMIT@"+DoubleToStr(price, _d)+";SL"+DoubleToStr(sl, _d)+";TP"+DoubleToStr(tp, _d);
      break;
    default:
      _str = "; UNKNOWN command "+cmd;
      break;
  }
    
  _str = _str +";M@" + DoubleToStr(MarketInfo(symbol, _mode), _d)+";SLv"+DoubleToStr(MarketInfo(symbol, MODE_STOPLEVEL),0);
  return(_str);
}

bool _OrderModify(int ticket, double price, double stoploss, double takeprofit, datetime expiration, color cl=CLR_NONE)
{
  OrderSelect(ticket, SELECT_BY_TICKET);
  string _symbol = OrderSymbol();
  int _d = MarketInfo(_symbol, MODE_DIGITS);
  string _sc = ";@"+DoubleToStr(price, _d)+";SL"+DoubleToStr(stoploss, _d)+";TP"+DoubleToStr(takeprofit, _d);

  bool result = OrderModify(ticket, price, stoploss, takeprofit, expiration, cl);
  if(!result){
    int err = GetLastError();
    Print("ERROR OrderModify #",err,": ", ErrorDescription(err),_sc);
    if(DoScreenShots){_MakeScreenShot(_symbol, "OrderModify ERROR"+ErrorDescription(err)+_sc);}
  }else
    if(DoScreenShots){_MakeScreenShot(_symbol, "OrderModify"+_sc);}
  return(result);
}

double _MM(double risk, string symbol, int stop_loss=0)
{
  double _tv  = MarketInfo(symbol, MODE_TICKVALUE);
  double _ask = MarketInfo(symbol, MODE_ASK);
  double _ls  = MarketInfo(symbol, MODE_LOTSIZE);
  if(_tv!=0 && _ask!=0)
    double _maxlots = AccountFreeMargin()*AccountLeverage()*MarketInfo(symbol, MODE_POINT)/_tv/_ask;
  else if(_ls != 0)
    _maxlots = (AccountFreeMargin()*AccountLeverage()/_ls); // Correct only when symbol is the same as AccountCurrency
  else
    _maxlots = (AccountFreeMargin()*AccountLeverage()/100000.0);

  _maxlots = MathFloor(_maxlots/_ls)*_ls;
  if(stop_loss==0)
  { // Based on account equity
    double lots =_maxlots*risk/100.0;
  }else{
    // Based on SL
    double _val_per_pip = risk*AccountEquity()/stop_loss/100.0;
    if(_tv != 0)
      lots = MathMin(_val_per_pip/_tv,_maxlots);
    else
      lots = MathMin(_val_per_pip/10.0,_maxlots);
  }
  return(_nv(symbol, lots));
}

//--- Screenshot function
void _MakeScreenShot(string symbol, string sx=""){
  static int no=0;
  no++;
  string fn = WindowExpertName()+symbol+"\\"+Year()+"-"+_al0(Month(),2)+"-"+_al0(Day(),2)+" "+
              _al0(Hour(),2)+"_"+_al0(Minute(),2)+"_"+_al0(Seconds(),2)+" "+no+sx+".gif";
  if(!WindowScreenShot(fn,640,480)) Print("ScreenShot error: ", ErrorDescription(GetLastError()));
}

string _al0(int number, int digits){
  // add leading zeros that the resulting string has 'digits' length.
  string result;
  result = DoubleToStr(number, 0);
  while(StringLen(result)        

Recommend