//+------------------------------------------------------------------+ //| 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)