//+------------------------------------------------------------------+ //| MA_Angle_EA.mq4 | //| Copyright © 2007 Robert Hill | //+------------------------------------------------------------------+ #property copyright "Copyright © 2007, Robert Hill" #include #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 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 = 4; extern double Angle_Threshold=15; extern int PrevMAShift=4; extern int CurMAShift=0; //+---------------------------------------------------+ //|General controls | //+---------------------------------------------------+ string setup; double lotMM; int TradesInThisSymbol; int MagicNumber; //+---------------------------------------------------+ //| 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 = Close[length-i+shift];break; case 1: pr = Open[length-i+shift];break; case 2: pr = High[length-i+shift];break; case 3: pr = Low[length-i+shift];break; case 4: pr = (High[length-i+shift] + Low[length-i+shift])/2;break; case 5: pr = (High[length-i+shift] + Low[length-i+shift] + Close[length-i+shift])/3;break; case 6: pr = (High[length-i+shift] + Low[length-i+shift] + Close[length-i+shift] + Close[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,0,MAPeriod,0,MA_Type,MA_AppliedPrice,Cur); MAPrevious=iMA(NULL,0,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); } } bool CheckTrend(int cmd) { bool TrendUP, TrendDOWN; double maAngle; GetMA_Trend(MA_Type, MA_Period , PrevMAShift, CurMAShift); maAngle = MA_Angle(PrevMAShift, CurMAShift, MAPrevious, MACurrent); switch (cmd) { case OP_BUY : if (maAngle > Angle_Threshold) return(true); break; case OP_SELL : if (maAngle < -Angle_Threshold) return(true); } return(false); } //+------------------------------------------------------------------+ //| CheckExitCondition | //| Check if AngleSep cross 0 line | //+------------------------------------------------------------------+ bool CheckExitCondition(int cmd) { bool trend; switch (cmd) { case OP_BUY : trend = CheckTrend(OP_SELL); break; case OP_SELL: trend = CheckTrend (OP_BUY); } return (trend); } //+------------------------------------------------------------------+ //| CheckEntryCondition | //| Check if separation on LSMA pair | //+------------------------------------------------------------------+ bool CheckEntryCondition(int cmd) { bool trend; trend = CheckTrend(cmd); return (trend); } //+------------------------------------------------------------------+ //| 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);} // 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 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); }