//+------------------------------------------------------------------+ //| MA_Angle_EA.mq4 | //| Copyright © 2007 Robert Hill | //+------------------------------------------------------------------+ #property copyright "Copyright © 2007, Robert Hill" #include <stdlib.mqh> #define UP 1 #define DOWN 2 #define SMA 0 #define EMA 1 #define SMMA 2 #define LWMA 3 #define LSMA 4 extern bool Debug = false; // Change to true to allow print //+---------------------------------------------------+ //|Account functions | //+---------------------------------------------------+ extern bool AccountIsMini = true; // Change to true if trading mini account //+---------------------------------------------------+ //|Money Management | //+---------------------------------------------------+ extern bool MoneyManagement = true; // Change to false to shutdown money management controls. // Lots = 1 will be in effect and only 1 lot will be open regardless of equity. extern double TradeSizePercent = 10; // Change to whatever percent of equity you wish to risk. extern double Lots = 0.1; // standard lot size. extern double MaxLots = 30; //+---------------------------------------------------+ //|Profit controls | //+---------------------------------------------------+ extern double StopLoss = 0; // Maximum pips willing to lose per position. extern bool UseTrailingStop = false; extern int TrailingStopType = 1; extern double TrailingStop = 20; // Change to whatever number of pips you wish to trail your position with. double FirstMove = 20; // Type 3 first level pip gain double FirstStopLoss = 50; // Move Stop to Breakeven double SecondMove = 30; // Type 3 second level pip gain double SecondStopLoss = 30; // Move stop to lock is profit double ThirdMove = 40; // type 3 third level pip gain double TrailingStop3 = 20; // Move stop and trail from there extern int Slippage = 10; // Possible fix for not getting filled or closed extern int TakeProfit = 0; extern double Margincutoff = 800; // Expert will stop trading if equity level decreases to that level. //+---------------------------------------------------+ //|Indicator Variables | //| Change these to try your own system | //| or add more if you like | //+---------------------------------------------------+ int SignalCandle = 1; extern int SignalTimeFrame = 60; extern int MA_Period=34; extern string m = "--Moving Average Types--"; extern string m0 = " 0 = SMA"; extern string m1 = " 1 = EMA"; extern string m2 = " 2 = SMMA"; extern string m3 = " 3 = LWMA"; extern string m4 = " 4 = LSMA"; extern int MA_Type = 1; //0=SMA, 1=EMA, 2=SMMA, 3=LWMA, 4=LSMA extern string p = "--Applied Price Types--"; extern string p0 = " 0 = close"; extern string p1 = " 1 = open"; extern string p2 = " 2 = high"; extern string p3 = " 3 = low"; extern string p4 = " 4 = median(high+low)/2"; extern string p5 = " 5 = typical(high+low+close)/3"; extern string p6 = " 6 = weighted(high+low+close+close)/4"; extern int MA_AppliedPrice = 0; extern double EntryAngle_Threshold=10; // What size angle to trigger a trade extern double ExitAngle_Threshold=2; extern int PrevMAShift=3; extern int CurMAShift=1; extern bool UseTradingHours = true; extern int StartHour = 2; // Start trades after time extern int StopHour = 15; // Stop trading after time //+---------------------------------------------------+ //|General controls | //+---------------------------------------------------+ string setup; double lotMM; int TradesInThisSymbol; int MagicNumber; bool YesStop; //+---------------------------------------------------+ //| Indicator values for filters | //| Add or Change to test your system | //+---------------------------------------------------+ double MACurrent, MAPrevious; //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { //---- MagicNumber = 3000 + func_Symbol2Val(Symbol())*100 + func_TimeFrame_Const2Val(Period()); setup="MA_Angle_EA" + Symbol() + "_" + func_TimeFrame_Val2String(func_TimeFrame_Const2Val(Period())); //---- return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { return(0); } //+------------------------------------------------------------------+ //| The functions from this point to the start function are where | //| changes are made to test other systems or strategies. | //|+-----------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Custom Indicators | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| LSMA with PriceMode | //| LSMA - Least Squares Moving Average function calculation | //| LSMA_In_Color Indicator plots the end of the linear regression line | //| PrMode 0=close, 1=open, 2=high, 3=low, 4=median(high+low)/2, | //| 5=typical(high+low+close)/3, 6=weighted(high+low+close+close)/4 | //+------------------------------------------------------------------+ double fLSMA(int Rperiod, int prMode, int shift) { int i; double sum, pr; int length; double lengthvar; double tmp; double wt; length = Rperiod; sum = 0; for(i = length; i >= 1 ; i--) { lengthvar = length + 1; lengthvar /= 3; tmp = 0; switch (prMode) { case 0: pr = iClose(NULL, SignalTimeFrame,length-i+shift);break; case 1: pr = iOpen(NULL, SignalTimeFrame,length-i+shift);break; case 2: pr = iHigh(NULL, SignalTimeFrame,length-i+shift);break; case 3: pr = iLow(NULL, SignalTimeFrame,length-i+shift);break; case 4: pr = (iHigh(NULL, SignalTimeFrame,length-i+shift) + iLow(NULL, SignalTimeFrame,length-i+shift))/2;break; case 5: pr = (iHigh(NULL, SignalTimeFrame,length-i+shift) + iLow(NULL, SignalTimeFrame,length-i+shift) + iClose(NULL, SignalTimeFrame,length-i+shift))/3;break; case 6: pr = (iHigh(NULL, SignalTimeFrame,length-i+shift) + iLow(NULL, SignalTimeFrame,length-i+shift) + iClose(NULL, SignalTimeFrame,length-i+shift) + iClose(NULL, SignalTimeFrame,length-i+shift))/4;break; } tmp = ( i - lengthvar)*pr; sum+=tmp; } wt = sum*6/(length*(length+1)); return(wt); } double MA_Angle( int PrevShift, int CurShift, double fPrevMA, double fCurMA) { double fAngle, mFactor; string Sym; int ShiftDif; mFactor = 100000.0; Sym = StringSubstr(Symbol(),3,3); if (Sym == "JPY") mFactor = 1000.0; ShiftDif = PrevShift-CurShift; mFactor /= ShiftDif; fAngle = mFactor * (fCurMA - fPrevMA)/2.0; return(fAngle); } void GetMA(int MAPeriod, int Prev, int Cur) { MACurrent=iMA(NULL,SignalTimeFrame,MAPeriod,0,MA_Type,MA_AppliedPrice,Cur); MAPrevious=iMA(NULL,SignalTimeFrame,MAPeriod,0,MA_Type,MA_AppliedPrice,Prev); } void GetLSMA(int MAPeriod, int Prev, int Cur) { MACurrent=fLSMA(MAPeriod,MA_AppliedPrice,Cur); MAPrevious=fLSMA(MAPeriod,MA_AppliedPrice,Prev); } void GetMA_Trend (int TrendMethod, int myPeriod, int PrevShift, int CurShift) { switch (TrendMethod) { case LSMA : GetLSMA(myPeriod, PrevShift, CurShift); break; default : GetMA( myPeriod, PrevShift, CurShift); } } //+------------------------------------------------------------------+ //| CheckExitCondition | //| Check if AngleSep cross 0 line | //+------------------------------------------------------------------+ bool CheckExitCondition(int cmd) { double maAngle; GetMA_Trend(MA_Type, MA_Period , PrevMAShift, CurMAShift); maAngle = MA_Angle(PrevMAShift, CurMAShift, MAPrevious, MACurrent); switch (cmd) { case OP_BUY : if (maAngle < ExitAngle_Threshold) return(true); break; case OP_SELL : if (maAngle > -ExitAngle_Threshold) return(true); } return(false); } //+------------------------------------------------------------------+ //| CheckEntryCondition | //| Check if separation on LSMA pair | //+------------------------------------------------------------------+ bool CheckEntryCondition(int cmd) { double maAngle; GetMA_Trend(MA_Type, MA_Period , PrevMAShift, CurMAShift); maAngle = MA_Angle(PrevMAShift, CurMAShift, MAPrevious, MACurrent); switch (cmd) { case OP_BUY : if (maAngle > EntryAngle_Threshold) return(true); break; case OP_SELL : if (maAngle < -EntryAngle_Threshold) return(true); } return(false); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { //---- if(CurMAShift >= PrevMAShift) { Print("Error: CurMAShift >= PrevMAShift"); PrevMAShift = 6; CurMAShift = 0; } //+------------------------------------------------------------------+ //| Check for Open Position | //+------------------------------------------------------------------+ HandleOpenPositions(); // Check if any open positions were not closed TradesInThisSymbol = CheckOpenPositions(); //+------------------------------------------------------------------+ //| Check if OK to make new trades | //+------------------------------------------------------------------+ if(AccountFreeMargin() < Margincutoff) { return(0);} if (UseTradingHours) { // trading from 7:00 to 13:00 GMT // trading from Start1 to Start2 YesStop = true; if (Hour() >= StartHour && Hour() <= StopHour) YesStop = false; // Comment ("Trading has been stopped as requested - wrong time of day"); if (YesStop) return (0); } // Only allow 1 trade per Symbol if(TradesInThisSymbol > 0) { return(0);} lotMM = GetLots(); if(CheckEntryCondition(OP_BUY) && !CheckExitCondition(OP_BUY)) { OpenBuyOrder(); return(0); } if(CheckEntryCondition(OP_SELL) && !CheckExitCondition(OP_SELL)) { OpenSellOrder(); } //---- return(0); } //+------------------------------------------------------------------+ //| Functions beyond this point should not need to be modified | //| Eventually will be placed in include file | //+------------------------------------------------------------------+ //+-------------------------------------------+ //| DoTrades module cut from start | //| No real changes | //+-------------------------------------------+ void OpenBuyOrder() { int err,ticket, digits; double myPrice, myStopLoss = 0, myTakeProfit = 0; myPrice = MarketInfo(Symbol( ), MODE_ASK); myStopLoss = 0; if ( StopLoss > 0 ) myStopLoss = myPrice - StopLoss * Point ; myTakeProfit = 0; if (TakeProfit>0) myTakeProfit = myPrice + TakeProfit * Point; // Normalize all price / stoploss / takeprofit to the proper # of digits. digits = MarketInfo(Symbol( ), MODE_DIGITS) ; if (digits > 0) { myPrice = NormalizeDouble( myPrice, digits); myStopLoss = NormalizeDouble( myStopLoss, digits); myTakeProfit = NormalizeDouble( myTakeProfit, digits); } ticket=OrderSend(Symbol(),OP_BUY,lotMM,myPrice,Slippage,myStopLoss,myTakeProfit,setup,MagicNumber,0,Green); if (ticket > 0) { if (OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) { if (Debug) Print("BUY order opened : ", OrderOpenPrice()); // if (Scalp == 1) OpenBuyScalpOrders( OrderOpenPrice()); } } else { err = GetLastError(); Print("Error opening BUY order [" + setup + "]: (" + err + ") " + ErrorDescription( err) ); } } //+------------------------------------------------------------------+ //| OpenSellOrder | //| If Stop Loss or TakeProfit are used the values are calculated | //| for each trade | //+------------------------------------------------------------------+ void OpenSellOrder() { int err, ticket, digits; double myPrice, myStopLoss = 0, myTakeProfit = 0; myPrice = MarketInfo(Symbol( ), MODE_BID); myStopLoss = 0; if ( StopLoss > 0 ) myStopLoss = myPrice + StopLoss * Point; myTakeProfit = 0; if (TakeProfit > 0) myTakeProfit = myPrice - TakeProfit * Point; // Normalize all price / stoploss / takeprofit to the proper # of digits. digits = MarketInfo(Symbol( ), MODE_DIGITS) ; if (digits > 0) { myPrice = NormalizeDouble( myPrice, digits); myStopLoss = NormalizeDouble( myStopLoss, digits); myTakeProfit = NormalizeDouble( myTakeProfit, digits); } ticket=OrderSend(Symbol(),OP_SELL,lotMM,myPrice,Slippage,myStopLoss,myTakeProfit,setup,MagicNumber,0,Red); if (ticket > 0) { if (OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)) { if (Debug) Print("SELL order opened : ", OrderOpenPrice()); // if (Scalp == 1) OpenSellScalpOrders(OrderOpenPrice()); } } else { err = GetLastError(); Print("Error opening Sell order [" + setup + "]: (" + err + ") " + ErrorDescription(err)); } } //+------------------------------------------------------------------+ //| Check Open Position Controls | //+------------------------------------------------------------------+ int CheckOpenPositions() { int cnt, total, NumPositions; int NumBuyTrades, NumSellTrades; // Number of buy and sell trades in this symbol NumBuyTrades = 0; NumSellTrades = 0; total=OrdersTotal(); for(cnt=0;cnt<total;cnt++) { OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol() != Symbol()) continue; if ( OrderMagicNumber() != MagicNumber) continue; if(OrderType() == OP_BUY ) NumBuyTrades++; if(OrderType() == OP_SELL ) NumSellTrades++; } NumPositions = NumBuyTrades + NumSellTrades; return (NumPositions); } int CloseOrder(int ticket,double numLots,int type) { int CloseCnt, err; double close_price; // try to close 3 Times CloseCnt = 0; while (CloseCnt < 3) { switch (type) { case OP_BUY : close_price = MarketInfo(Symbol(),MODE_BID); break; case OP_SELL : close_price = MarketInfo(Symbol(),MODE_ASK); } if (!OrderClose(ticket,numLots,close_price,Slippage,Violet)) { err=GetLastError(); Print(CloseCnt," Error closing order : (", err , ") " + ErrorDescription(err)); if (err > 0) CloseCnt++; } else { CloseCnt = 3; } } } int ModifyOrder(int ord_ticket,double op, double price,double tp) { int CloseCnt, err; CloseCnt=0; while (CloseCnt < 3) { if (OrderModify(ord_ticket,op,price,tp,0,Aqua)) { CloseCnt = 3; } else { err=GetLastError(); Print(CloseCnt," Error modifying order : (", err , ") " + ErrorDescription(err)); if (err>0) CloseCnt++; } } } //+------------------------------------------------------------------+ //| HandleTrailingStop | //| Type 1 moves the stoploss without delay. | //| Type 2 waits for price to move the amount of the trailStop | //| before moving stop loss then moves like type 1 | //| Type 3 uses up to 3 levels for trailing stop | //| Level 1 Move stop to 1st level | //| Level 2 Move stop to 2nd level | //| Level 3 Trail like type 1 by fixed amount other than 1 | //| Possible future types | //| Type 4 uses 2 for 1, every 2 pip move moves stop 1 pip | //| Type 5 uses 3 for 1, every 3 pip move moves stop 1 pip | //+------------------------------------------------------------------+ int HandleTrailingStop(string type, int ticket, double op, double os, double tp) { double pt, TS=0; double bos,bop,opa,osa; if (type == "BUY") { switch(TrailingStopType) { case 1: pt = Point*StopLoss; if(Bid-os > pt) ModifyOrder(ticket,op,Bid-pt,tp); break; case 2: pt = Point*TrailingStop; if(Bid-op > pt && os < Bid - pt) ModifyOrder(ticket,op,Bid - pt,tp); break; case 3: if (Bid - op > FirstMove * Point) { TS = op + FirstMove*Point - FirstStopLoss * Point; if (os < TS) { ModifyOrder(ticket,op,TS,tp); } } if (Bid - op > SecondMove * Point) { TS = op + SecondMove*Point - SecondStopLoss * Point; if (os < TS) { ModifyOrder(ticket,op,TS,tp); } } if (Bid - op > ThirdMove * Point) { TS = Bid - ThirdMove*Point; if (os < TS) { ModifyOrder(ticket,op,TS,tp); } } break; } return(0); } if (type == "SELL") { switch(TrailingStopType) { case 1: pt = Point*StopLoss; if(os - Ask > pt) ModifyOrder(ticket,op,Ask+pt,tp); break; case 2: pt = Point*TrailingStop; if(op - Ask > pt && os > Ask+pt) ModifyOrder(ticket,op,Ask+pt,tp); break; case 3: if (op - Ask > FirstMove * Point) { TS = op - FirstMove * Point + FirstStopLoss * Point; if (os > TS) { ModifyOrder(ticket,op,TS,tp); } } if (op - Ask > SecondMove * Point) { TS = op - SecondMove * Point + SecondStopLoss * Point; if (os > TS) { ModifyOrder(ticket,op,TS,tp); } } if (op - Ask > ThirdMove * Point) { TS = Ask + ThirdMove * Point; if (os > TS) { ModifyOrder(ticket,op,TS,tp); } } break; } } return(0); } //+------------------------------------------------------------------+ //| Handle Open Positions | //| Check if any open positions need to be closed or modified | //| Three attempts are made to close or modify | //+------------------------------------------------------------------+ int HandleOpenPositions() { int cnt; bool YesClose; int myOrderType; for(cnt=OrdersTotal()-1;cnt>=0;cnt--) { OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol() != Symbol()) continue; if ( OrderMagicNumber() != MagicNumber) continue; myOrderType = OrderType(); if(myOrderType == OP_BUY) { if (CheckExitCondition(OP_BUY)) { CloseOrder(OrderTicket(),OrderLots(),OP_BUY); } else { if (UseTrailingStop) { HandleTrailingStop("BUY",OrderTicket(),OrderOpenPrice(),OrderStopLoss(),OrderTakeProfit()); } } } if(myOrderType == OP_SELL) { if (CheckExitCondition(OP_SELL)) { CloseOrder(OrderTicket(),OrderLots(),OP_SELL); } else { if(UseTrailingStop) { HandleTrailingStop("SELL",OrderTicket(),OrderOpenPrice(),OrderStopLoss(),OrderTakeProfit()); } } } } } //+------------------------------------------------------------------+ //| Get number of lots for this trade | //+------------------------------------------------------------------+ double GetLots() { double lot; if(MoneyManagement) { lot = LotsOptimized(); } else { lot = Lots; } if(AccountIsMini) { if (lot < 0.1) lot = 0.1; } else { if (lot >= 1.0) lot = MathFloor(lot); else lot = 1.0; } if (lot > MaxLots) lot = MaxLots; return(lot); } //+------------------------------------------------------------------+ //| Calculate optimal lot size | //+------------------------------------------------------------------+ double LotsOptimized() { double lot=Lots; //---- select lot size lot=NormalizeDouble(MathFloor(AccountBalance()*TradeSizePercent/10000)/10,1); // lot at this point is number of standard lots // if (Debug) Print ("Lots in LotsOptimized : ",lot); // Check if mini or standard Account if(AccountIsMini) { lot = MathFloor(lot*10)/10; } return(lot); } //+------------------------------------------------------------------+ //| Time frame interval appropriation function | //+------------------------------------------------------------------+ int func_TimeFrame_Const2Val(int Constant ) { switch(Constant) { case 1: // M1 return(1); case 5: // M5 return(2); case 15: return(3); case 30: return(4); case 60: return(5); case 240: return(6); case 1440: return(7); case 10080: return(8); case 43200: return(9); } } //+------------------------------------------------------------------+ //| Time frame string appropriation function | //+------------------------------------------------------------------+ string func_TimeFrame_Val2String(int Value ) { switch(Value) { case 1: // M1 return("PERIOD_M1"); case 2: // M1 return("PERIOD_M5"); case 3: return("PERIOD_M15"); case 4: return("PERIOD_M30"); case 5: return("PERIOD_H1"); case 6: return("PERIOD_H4"); case 7: return("PERIOD_D1"); case 8: return("PERIOD_W1"); case 9: return("PERIOD_MN1"); default: return("undefined " + Value); } } int func_Symbol2Val(string symbol) { string mySymbol = StringSubstr(symbol,0,6); if(mySymbol=="AUDCAD") return(1); if(mySymbol=="AUDJPY") return(2); if(mySymbol=="AUDNZD") return(3); if(mySymbol=="AUDUSD") return(4); if(mySymbol=="CHFJPY") return(5); if(mySymbol=="EURAUD") return(6); if(mySymbol=="EURCAD") return(7); if(mySymbol=="EURCHF") return(8); if(mySymbol=="EURGBP") return(9); if(mySymbol=="EURJPY") return(10); if(mySymbol=="EURUSD") return(11); if(mySymbol=="GBPCHF") return(12); if(mySymbol=="GBPJPY") return(13); if(mySymbol=="GBPUSD") return(14); if(mySymbol=="NZDUSD") return(15); if(mySymbol=="USDCAD") return(16); if(mySymbol=="USDCHF") return(17); if(mySymbol=="USDJPY") return(18); return(19); }
Sample
Analysis
Market Information Used:
Series array that contains close prices for each bar
Series array that contains open prices of each bar
Series array that contains the highest prices of each bar
Series array that contains the lowest prices of each bar
Indicator Curves created:
Indicators Used:
Moving average indicator
Custom Indicators Used:
Order Management characteristics:
It automatically opens orders when conditions are reached
Checks for the total of open orders
It Closes Orders by itself
It can change open orders parameters, due to possible stepping strategy
Other Features: