//+------------------------------------------------------------------+ //| LSMA_Daily_EA | //| Copyright © 2008 Robert Hill | //| | //| Written by Robert Hill aka MrPip | //| | //+------------------------------------------------------------------+ #property copyright "Robert Hill" #property link "None" #include <stdlib.mqh> #include <stderror.mqh> extern string Expert_Name = "LSMA_Daily"; extern int MagicNumberBase = 200000; string UserComment = "LSMA_EA"; string in="---Indicator settings---"; int LSMAShortPeriod=7; int LSMALongPeriod=16; int MonthStart = 9; int MonthEnd = 11; bool UseFreshCross = true; //+---------------------------------------------------+ //|Money Management | //+---------------------------------------------------+ extern string mm = "---Money Management---"; extern double Lots=0.1; extern bool UseMoneyManagement = true; // Change to false to shutdown money management controls. extern double TradeSizePercent = 10; // Change to whatever percent of equity you wish to risk. extern bool BrokerPermitsFractionalLots = true; extern string m1="Set mini and micro to false for standard account"; extern bool AccountIsMini = false; extern bool AccountIsMicro = false; extern bool BrokerIsIBFX = false; extern bool BrokerIsCrownForex = false; extern string fm="UseFreeMargin = false to use Account Balance"; extern bool UseFreeMargin = false; //+---------------------------------------------------+ //|Profit controls | //+---------------------------------------------------+ extern string st6 = "--Profit Controls--"; extern double StopLoss=0; extern double TakeProfit=0; extern int Slippage=3; //+---------------------------------------------------+ //|General controls | //+---------------------------------------------------+ int MagicNumber=0; string setup; int TradesInThisSymbol = 0; double mLots=0; bool YesStop; double myPoint; int totalTries = 5; int retryDelay = 1000; int myTradeErr; //+------------------------------------------------------------------+ //| Calculate MagicNumber, setup comment | //| | //+------------------------------------------------------------------+ int init() { MagicNumber = MagicNumberBase + func_Symbol2Val(Symbol())*100 + func_TimeFrame_Const2Val(Period()); setup=Expert_Name + Symbol() + "_" + func_TimeFrame_Val2String(func_TimeFrame_Const2Val(Period())); setup = UserComment; myPoint = SetPoint(Symbol()); return(0); } int deinit() { return(0); } //+------------------------------------------------------------------------+ //| LSMA - Least Squares Moving Average function calculation | //| LSMA_In_Color Indicator plots the end of the linear regression line | //+------------------------------------------------------------------------+ double LSMADaily(int Rperiod, int shift) { int i; double sum; 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; tmp = ( i - lengthvar)*iClose(NULL,1440,length-i+shift); sum+=tmp; } wt = sum*6/(length*(length+1)); return(wt); } //+------------------------------------------------------------------+ //| CheckExitCondition | //| Check if AngleSep cross 0 line | //+------------------------------------------------------------------+ bool CheckExitCondition(int TradeType) { bool YesClose; double L_Fast,L_Slow; YesClose = false; L_Fast=LSMADaily(LSMAShortPeriod,1); L_Slow=LSMADaily(LSMALongPeriod,1); if (TradeType == OP_BUY) { if (L_Fast < L_Slow) YesClose = true; } if (TradeType == OP_SELL) { if (L_Fast > L_Slow) YesClose = true; } return (YesClose); } //+------------------------------------------------------------------+ //| CheckEntryCondition | //| Check if separation on LSMA pair | //+------------------------------------------------------------------+ bool CheckEntryCondition(int TradeType) { bool YesTrade; double L_Fast,L_Slow; double L_FastPrev,L_SlowPrev; L_Fast=LSMADaily(LSMAShortPeriod,1); L_Slow=LSMADaily(LSMALongPeriod,1); YesTrade = false; if (TradeType == OP_BUY) { if ( L_Fast > L_Slow) { if (UseFreshCross == true) { L_FastPrev=LSMADaily(LSMAShortPeriod,2); L_SlowPrev=LSMADaily(LSMALongPeriod,2); if (L_FastPrev < L_SlowPrev) YesTrade = true; else YesTrade = false; } else YesTrade = true; } } if (TradeType == OP_SELL) { if ( L_Fast < L_Slow) { if (UseFreshCross == true) { L_FastPrev=LSMADaily(LSMAShortPeriod,2); L_SlowPrev=LSMADaily(LSMALongPeriod,2); if (L_FastPrev > L_SlowPrev) YesTrade = true; else YesTrade = false; } else YesTrade = true; } } return (YesTrade); } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Start | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ int start() { if (IsTradeAllowed()==false ) return(0); //+------------------------------------------------------------------+ //| Check for Open Position | //+------------------------------------------------------------------+ HandleOpenPositions(); if (Month() < MonthStart) return(0); if (Month() > MonthEnd) return(0); // Check if any open positions were not closed TradesInThisSymbol = CheckOpenPositions(); // Only allow 1 trade per Symbol if(TradesInThisSymbol > 0) { return(0);} mLots = GetLots(); if(CheckEntryCondition(OP_BUY) == true) { OpenBuyOrder(mLots, StopLoss,TakeProfit, Slippage, setup, MagicNumber, Green); return(0); } if(CheckEntryCondition(OP_SELL) == true) { OpenSellOrder(mLots, StopLoss,TakeProfit, Slippage, setup, MagicNumber, Red); } return(0); } //+------------------------------------------------------------------+ //| Get number of lots for this trade | //+------------------------------------------------------------------+ double GetLots() { double lot; double myMaxLot = MarketInfo(Symbol(), MODE_MAXLOT); if(UseMoneyManagement == false) return(Lots); if (BrokerIsIBFX == true) { lot = Calc_Money_Management(); return(lot); } if (BrokerIsCrownForex == true) { lot = Calc_CrownMoney_Management(); return(lot); } lot = LotsOptimized(); // Use at least 1 micro lot if (AccountIsMicro == true) { lot = MathFloor(lot*100)/100; if (lot < 0.01) lot = 0.01; if (lot > myMaxLot) lot = myMaxLot; return(lot); } // Use at least 1 mini lot if(AccountIsMini == true) { lot = MathFloor(lot*10)/10; if (lot < 0.1) lot = 0.1; if (lot > myMaxLot) lot = myMaxLot; return(lot); } // Standard account if( BrokerPermitsFractionalLots == false) { if (lot >= 1.0) lot = MathFloor(lot); else lot = 1.0; } if (lot < 1.0) lot = 1.0; if (lot > myMaxLot) lot = myMaxLot; return(lot); } //+------------------------------------------------------------------+ //| Calculate optimal lot size | //+------------------------------------------------------------------+ double LotsOptimized() { double lot=Lots; //---- select lot size if (UseFreeMargin == true) lot=NormalizeDouble(MathFloor(AccountFreeMargin()*TradeSizePercent/10000)/10,2); else lot=NormalizeDouble(MathFloor(AccountBalance()*TradeSizePercent/10000)/10,2); return(lot); } double Calc_CrownMoney_Management() { double lot; lot=NormalizeDouble((AccountEquity()*TradeSizePercent/10000)/10,1); // lot = MathRound( lot/myStep ) * myStep; // Use at least 1 mini lot if(AccountIsMini == true) { lot = MathFloor(lot*10)/10 * 10000; if (lot < 10000) lot = 10000; // if (lot > myMaxLot) lot = myMaxLot; return(lot); } // Standard account lot = lot * 100000; if (lot < 100000) lot = 100000; // if (lot > myMaxLot) lot = myMaxLot; return(lot); } double Calc_Money_Management() { // variables used for money management double MM_MinLotSize=0; double MM_MaxLotSize=0; double MM_LotStep=0; double MM_Decimals=0; int MM_AcctLeverage=0; int MM_CurrencyLotSize=0; double OrderLotSize; MM_AcctLeverage = AccountLeverage(); MM_MinLotSize = MarketInfo(Symbol(),MODE_MINLOT); MM_MaxLotSize = MarketInfo(Symbol(),MODE_MAXLOT); MM_LotStep = MarketInfo(Symbol(),MODE_LOTSTEP); MM_CurrencyLotSize = MarketInfo(Symbol(),MODE_LOTSIZE); if(MM_LotStep == 0.01) {MM_Decimals = 2;} if(MM_LotStep == 0.1) {MM_Decimals = 1;} OrderLotSize = AccountEquity() * (TradeSizePercent * 0.01) / (MM_CurrencyLotSize / MM_AcctLeverage); if(BrokerPermitsFractionalLots == true) OrderLotSize = StrToDouble(DoubleToStr(OrderLotSize, MM_Decimals)); else OrderLotSize = MathRound(OrderLotSize); if (OrderLotSize < MM_MinLotSize) {OrderLotSize = MM_MinLotSize;} if (OrderLotSize > MM_MaxLotSize) {OrderLotSize = MM_MaxLotSize;} return(OrderLotSize); } //+------------------------------------------------------------------+ //| OpenBuyOrder | //| If Stop Loss or TakeProfit are used the values are calculated | //| for each trade | //+------------------------------------------------------------------+ int OpenBuyOrder(double mLots, double mStopLoss, double mTakeProfit, int mSlippage, string mComment, int mMagic, color mColor) { int err,ticket; double myPrice, myStopLoss = 0, myTakeProfit = 0; double TPprice, STprice; RefreshRates(); myStopLoss = StopLong(Bid,mStopLoss, myPoint); myTakeProfit = TakeLong(Bid,mTakeProfit, myPoint); // Normalize all price / stoploss / takeprofit to the proper # of digits. if (Digits > 0) { myPrice = NormalizeDouble( Ask, Digits); myStopLoss = NormalizeDouble( myStopLoss, Digits); myTakeProfit = NormalizeDouble( myTakeProfit, Digits); } ticket=myOrderSend(Symbol(),OP_BUY,mLots,myPrice,mSlippage,0,0,mComment,mMagic,0,mColor); if (ticket > 0) { if (OrderSelect( ticket,SELECT_BY_TICKET, MODE_TRADES) ) { Print("BUY order opened : ", OrderOpenPrice( )); if (myStopLoss != 0 || myTakeProfit != 0) { TPprice = 0; if (myTakeProfit > 0) TPprice=TakeLong(OrderOpenPrice(), myTakeProfit, myPoint); STprice = 0; if (myStopLoss > 0) { STprice = StopLong(OrderOpenPrice(), myStopLoss, myPoint); STprice = ValidStopLoss(Symbol(), OP_BUY,Bid, STprice, myPoint); } // Normalize stoploss / takeprofit to the proper # of digits. if (Digits > 0) { STprice = NormalizeDouble( STprice, Digits); TPprice = NormalizeDouble( TPprice, Digits); } ModifyOrder(ticket, OrderOpenPrice(), STprice, TPprice, LightGreen); } } } else { err = GetLastError(); if(err==0) { return(ticket); } else { Print("Error opening BUY order [" + setup + "]: (" + err + ") " + ErrorDescription(err)); } } return(ticket); } //+------------------------------------------------------------------+ //| OpenSellOrder | //| If Stop Loss or TakeProfit are used the values are calculated | //| for each trade | //+------------------------------------------------------------------+ void OpenSellOrder(double mLots, double mStopLoss, double mTakeProfit, int mSlippage, string mComment, int mMagic, color mColor) { int err, ticket; double myPrice, myStopLoss = 0, myTakeProfit = 0; double STprice, TPprice; RefreshRates(); myStopLoss = StopShort(Ask,mStopLoss, myPoint); myTakeProfit = TakeShort(Ask,mTakeProfit, myPoint); // Normalize all price / stoploss / takeprofit to the proper # of digits. if (Digits > 0) { myPrice = NormalizeDouble( Bid, Digits); myStopLoss = NormalizeDouble( myStopLoss, Digits); myTakeProfit = NormalizeDouble( myTakeProfit, Digits); } ticket=myOrderSend(Symbol(),OP_SELL,mLots,myPrice,mSlippage,0,0,mComment,mMagic,0,mColor); if (ticket > 0) { if (OrderSelect( ticket,SELECT_BY_TICKET, MODE_TRADES) ) { Print("Sell order opened : ", OrderOpenPrice()); if (myStopLoss != 0 || myTakeProfit != 0) { TPprice = 0; if (myTakeProfit > 0) TPprice=TakeShort(OrderOpenPrice(),myTakeProfit, myPoint); STprice = 0; if (myStopLoss > 0) { STprice = StopShort(OrderOpenPrice() ,myStopLoss, myPoint); STprice = ValidStopLoss(Symbol(), OP_SELL,Ask, STprice, myPoint); } // Normalize stoploss / takeprofit to the proper # of digits. if (Digits > 0) { STprice = NormalizeDouble( STprice, Digits); TPprice = NormalizeDouble( TPprice, Digits); } ModifyOrder(ticket, OrderOpenPrice(), STprice, TPprice, LightGreen); } } } else { err = GetLastError(); if(err==0) { return(ticket); } else { Print("Error opening Sell order [" + mComment + "]: (" + err + ") " + ErrorDescription(err)); } } return(ticket); } int myOrderSend(string symbol, int cmd, double lot, double price, int slippage, double stoploss, double takeprofit, string comment, int magic, datetime expiration = 0, color arrow_color = CLR_NONE) { int ticket = -1; double mPoint; int cnt = 0; while (!IsTradeAllowed() && cnt < totalTries) { Sleep(retryDelay); cnt++; } if (!IsTradeAllowed()) { myTradeErr = ERR_TRADE_CONTEXT_BUSY; return(-1); } // Normalize all price / stoploss / takeprofit to the proper # of digits. price = NormalizeDouble(price, Digits); mPoint = SetPoint(symbol); int err = GetLastError(); // clear the global variable. err = 0; myTradeErr = 0; bool exit_loop = false; if ((cmd == OP_BUY) || (cmd == OP_SELL)) { cnt = 0; while (!exit_loop) { if (IsTradeAllowed()) { double pnow = price; int slippagenow = slippage; if (cmd == OP_BUY) { pnow = NormalizeDouble(MarketInfo(symbol, MODE_ASK), MarketInfo(symbol, MODE_DIGITS)); // we are buying at Ask if (pnow > price) { slippagenow = slippage - (pnow - price) / mPoint; } } else if (cmd == OP_SELL) { pnow = NormalizeDouble(MarketInfo(symbol, MODE_BID), MarketInfo(symbol, MODE_DIGITS)); // we are buying at Ask if (pnow < price) { // moved in an unfavorable direction slippagenow = slippage - (price - pnow) / mPoint; } } if (slippagenow > slippage) slippagenow = slippage; if (slippagenow >= 0) { ticket = OrderSend(symbol, cmd, lot, pnow, slippagenow, stoploss, takeprofit, comment, magic, expiration, arrow_color); err = GetLastError(); myTradeErr = err; } else { // too far away, manually signal ERR_INVALID_PRICE, which // will result in a sleep and a retry. err = ERR_INVALID_PRICE; myTradeErr = err; } } else { cnt++; } switch (err) { case ERR_NO_ERROR: exit_loop = true; break; case ERR_SERVER_BUSY: case ERR_NO_CONNECTION: case ERR_INVALID_PRICE: case ERR_OFF_QUOTES: case ERR_BROKER_BUSY: case ERR_TRADE_CONTEXT_BUSY: cnt++; // a retryable error break; case ERR_PRICE_CHANGED: case ERR_REQUOTE: continue; // we can apparently retry immediately according to MT docs. default: // an apparently serious, unretryable error. exit_loop = true; break; } // end switch if (cnt > totalTries) exit_loop = true; if (!exit_loop) { Sleep(retryDelay); } } // we have now exited from loop. if (err == ERR_NO_ERROR) { return(ticket); // SUCCESS! } return(-1); } } double StopLong(double price,int stop, double mPoint) { if(stop==0) return(0); else return(price-(stop*mPoint)); } double StopShort(double price,int stop, double mPoint) { if(stop==0) return(0); else return(price+(stop*mPoint)); } double TakeLong(double price,int take, double mPoint) { if(take==0) return(0); else return(price+(take*mPoint)); } double TakeShort(double price,int take, double mPoint) { if(take==0) return(0); else return(price-(take*mPoint)); } double ValidStopLoss(string mySymbol, int type, double price, double SL, double mPoint) { double minstop; if (SL < 0.1) return(SL); minstop = MarketInfo(mySymbol,MODE_STOPLEVEL); if (type == OP_BUY) { if((price - SL) < minstop*mPoint) SL = price - minstop*mPoint; } if (type == OP_SELL) { if((SL-price) < minstop*mPoint) SL = price + minstop*mPoint; } return(SL); } //+------------------------------------------------------------------+ //| Handle Open Positions | //| Check if any open positions need to be closed or modified | //+------------------------------------------------------------------+ int HandleOpenPositions() { int cnt; for(cnt=OrdersTotal()-1;cnt>=0;cnt--) { OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol() != Symbol()) continue; if ( OrderMagicNumber() != MagicNumber) continue; if(OrderType() == OP_BUY) { if (CheckExitCondition(OP_BUY) == true) { CloseOrder(OrderTicket(),OrderOpenPrice(),OrderLots(),OP_BUY); } } if(OrderType() == OP_SELL) { if (CheckExitCondition(OP_SELL) == true) { CloseOrder(OrderTicket(),OrderOpenPrice(), OrderLots(),OP_SELL); } } } } //+------------------------------------------------------------------+ //| Check Open Position Controls | //+------------------------------------------------------------------+ int CheckOpenPositions() { int cnt, total; int NumTrades; NumTrades = 0; total=OrdersTotal(); for(cnt=OrdersTotal()-1;cnt>=0;cnt--) { OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol() != Symbol()) continue; if ( OrderMagicNumber() != MagicNumber) continue; if(OrderType() == OP_BUY ) NumTrades++; if(OrderType() == OP_SELL ) NumTrades++; } return (NumTrades); } int CloseOrder(int ticket, double op, double numLots,int cmd) { bool exit_loop = false, result; int cnt, err; int digits; double myPrice; // string olStr, bidStr, askStr; RefreshRates(); if (cmd == OP_BUY) myPrice = Bid; if (cmd == OP_SELL) myPrice = Ask; if (Digits > 0) myPrice = NormalizeDouble( myPrice, Digits); // olStr = DoubleToStr(numLots,2); // bidStr = DoubleToStr(Bid, Digits); // askStr = DoubleToStr(Ask, Digits); // try to close 3 Times cnt = 0; while (!exit_loop) { if (IsTradeAllowed() == true) { result = OrderClose(ticket,numLots,myPrice,Slippage,Violet); err = GetLastError(); } else cnt++; if (result == true) exit_loop = true; err=GetLastError(); switch (err) { case ERR_NO_ERROR: exit_loop = true; break; case ERR_SERVER_BUSY: case ERR_NO_CONNECTION: case ERR_INVALID_PRICE: case ERR_OFF_QUOTES: case ERR_BROKER_BUSY: case ERR_TRADE_CONTEXT_BUSY: case ERR_TRADE_TIMEOUT: // for modify this is a retryable error, I hope. cnt++; // a retryable error break; case ERR_PRICE_CHANGED: case ERR_REQUOTE: RefreshRates(); continue; // we can apparently retry immediately according to MT docs. default: // an apparently serious, unretryable error. exit_loop = true; break; } // end switch if (cnt > totalTries) exit_loop = true; if (!exit_loop) { Sleep(retryDelay); RefreshRates(); } } // we have now exited from loop. if ((result == true) || (err == ERR_NO_ERROR)) { // OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES); return(true); // SUCCESS! } Print(" Error closing order : (", err , ") " + ErrorDescription(err)); return(false); } int ModifyOrder(int ord_ticket,double op, double oSL, double oTP, color mColor) { int CloseCnt, err; double myStop, myTake; CloseCnt=0; while (CloseCnt < 3) { if (OrderModify(ord_ticket,op,oSL,oTP,0,mColor)) { CloseCnt = 3; } else { err=GetLastError(); Print(CloseCnt," Error modifying order : (", err , ") " + ErrorDescription(err)); if (err>0) CloseCnt++; } } } double SetPoint(string mySymbol) { double mPoint, myDigits; myDigits = MarketInfo (mySymbol, MODE_DIGITS); if (myDigits < 4) mPoint = 0.01; else mPoint = 0.0001; return(mPoint); } 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=="NZDJPY") return(15); if(mySymbol=="NZDUSD") return(16); if(mySymbol=="USDCAD") return(17); if(mySymbol=="USDCHF") return(18); if(mySymbol=="USDJPY") return(19); Comment("unexpected Symbol"); return(999); } //+------------------------------------------------------------------+ //| 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); } } //+------------------------------------------------------------------+
Sample
Analysis
Market Information Used:
Series array that contains close prices for each bar
Indicator Curves created:
Indicators Used:
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: