//+------------------------------------------------------------------+ //| LSMA_Daily_EA | //| Copyright © 2008 Robert Hill | //| | //| Written by Robert Hill aka MrPip | //| | //+------------------------------------------------------------------+ #property copyright "Robert Hill" #property link "None" #include #include 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); } } //+------------------------------------------------------------------+