/*-----------------------------+ | | | Shared by www.Aptrafx.com | | | +------------------------------*/ //+------------------------------------------------------------------+ //| MakeGridLSMA.mq4 | //| Copyright © 2005, hdb | //| http://www.dubois1.net/hdb | //+------------------------------------------------------------------+ #property copyright "Copyright © 2005, hdb" #property link "http://www.dubois1.net/hdb" //#property version "1.93" // DISCLAIMER ***** IMPORTANT NOTE ***** READ BEFORE USING ***** // This expert advisor can open and close real positions and hence do real trades and lose real money. // This is not a 'trading system' but a simple robot that places trades according to fixed rules. // The author has no pretentions as to the profitability of this system and does not suggest the use // of this EA other than for testing purposes in demo accounts. // Use of this system is free - but u may not resell it - and is without any garantee as to its // suitability for any purpose. // By using this program you implicitly acknowledge that you understand what it does and agree that // the author bears no responsibility for any losses. // Before using, please also check with your broker that his systems are adapted for the frequest trades // associated with this expert. // 1.8 changes // made wantLongs and wantShorts into local variables. Previously, if u set UseMACD to true, // it did longs and shorts and simply ignored the wantLongs and wantShorts flags. // Now, these flags are not ignored. // added a loop to check if there are 'illicit' open orders above or below the EMA when the limitEMA34 // flag is used. These accumulate over time and are never removed and is due to the EMA moving. // removed the switch instruction as they dont seem to work - replaced with if statements // made the EMA period variable // // 1.9 changes - as per kind suggestions of Gideon // Added a routine to delete orders and positions if they are older than keepOpenTimeLimit hours. // Added OsMA as a possible filter. Acts exactly like MACD. // Added 4 parameters for MACD or OsMA so that we can optimise // Also cleaned up the code a bit. // 1.92 changes by dave // added function openPOsitions to count the number of open positions // modified the order logic so that openPOsitions is not > GridMaxOpen // 1.93 added long term direction indicator // Added tradeForMinutes - will only trade for this time then stop till EA is reset. // // modified by cori. Using OrderMagicNumber to identify the trades of the grid // modified by MrPip to use LSMA and removed a large amount of code that is not needed // when grid is only open in direction of LSMA // Also added a second version of Trailing Stop and combined some routines, passing parameteres // to keep the same functionality. extern int uniqueGridMagic = 11111; // Magic number of the trades. must be unique to identify // the trades of one grid extern double Lots = 0.1; // extern double GridSize = 10; // pips between orders - grid or mesh size extern double GridSteps = 10; // total number of orders to place extern bool ExtendGrid = true; // Used to limit grid to original when buy and sell stops are filled extern double TakeProfit = 0 ; // number of ticks to take profit. normally is = grid size but u can override extern double StopLoss = 0; // if u want to add a stop loss. normal grids dont use stop losses extern int trailStop = 0; // will trail if > 0 extern int TrailingStopType = 1; // Type 1 will trail immediately, type 2 will wait for price to move amount of trailStop extern double UpdateInterval = 15; // update orders every x minutes // Added by MrPip to trade in the direction of the LSMA cross extern int LSMAShortPeriod=7; // extern int LSMALongPeriod=16; extern int PipsDifference = 16; extern int gridOffset = 0; // positions are opened at price modulo GridSize and offset with this parameter. // used essentially to enter at non round numbers // the following flags set bounds on the prices at which orders may be placed // this code was developed for and is kindly made public by Exc_ite2 extern bool suspendGrid = false; // if set to true, will close all unfilled Orders extern bool shutdownGrid = false; // if set to true, will close all orders and positions. // modified by cori. internal variables only string GridName = "Grid"; // identifies the grid. allows for several co-existing grids - old variable.. shold not use any more double LastUpdate = 0; // counter used to note time of last update double startTime = 0; // counter to note trade start time. double closedProfit = 0; // counts closed p&l double openProfit = 0; // counts open p&l double accumulatedProfit = 0; // for back testing only int openLongs = 0; // how many longs are open int openShorts = 0; // how many shorts are open bool gridActive = true; // is the grid active // modified by MrPip double LongTradeRate; // Keeps track of where to extend a long grid double ShortTradeRate; // Keeps track of where to extend a short grid int GridCount; // How many Buy Stop or Sell Stop are in the grid // Used to determine how many to add when extend grid is true //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { //---- #property show_inputs // shows the parameters - thanks Slawa... //---- GridName = StringConcatenate( "Grid-", Symbol(),"-",uniqueGridMagic ); return(0); } //+------------------------------------------------------------------------+ //| LSMA - Least Squares Moving Average function calculation | //| LSMA_In_Color Indicator plots the end of the linear regression line | //| Code is placed here and locked for Daily direction | //+------------------------------------------------------------------------+ 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,PERIOD_D1,length-i+shift); sum+=tmp; } wt = sum*6/(length*(length+1)); return(wt); } //+------------------------------------------------------------------------+ //| LSMA - Least Squares Moving Average function calculation | //| LSMA_In_Color Indicator plots the end of the linear regression line | //| Cose is placed here for any chart period | //+------------------------------------------------------------------------+ double LSMA(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)*Close[length-i+shift]; sum+=tmp; } wt = sum*6/(length*(length+1)); return(wt); } //+------------------------------------------------------------------+ //| CheckDailyDirection | //| Check daily direction for trade | //| return 1 for up, -1 for down, 0 for flat | //+------------------------------------------------------------------+ int CheckDailyDirection() { double SlowEMA, FastEMA; double Dif; Dif = LSMADaily(LSMAShortPeriod,1) - LSMADaily(LSMALongPeriod,1); if(Dif > 0 ) return(1); if(Dif < 0 ) return(-1); return(0); } //+------------------------------------------------------------------+ //| CheckExitCondition | //| Check if LSMAs cross down to exit BUY or up to exit SELL | //+------------------------------------------------------------------+ bool CheckExitCondition(string TradeType) { bool YesClose; double Dif; YesClose = false; Dif=LSMA(LSMAShortPeriod,1)-LSMA(LSMALongPeriod,1); // Dif=CheckDailyDirection(); if (TradeType == "BUY" && Dif < 0) YesClose = true; if (TradeType == "SELL" && Dif > 0) YesClose = true; return (YesClose); } //+------------------------------------------------------------------+ //| CheckEntryCondition | //| Check if LSMAs cross up for BUY or down for SELL | //+------------------------------------------------------------------+ bool CheckEntryCondition(string TradeType) { bool YesTrade; double Dif; YesTrade = false; Dif = LSMA(LSMAShortPeriod,1) - LSMA(LSMALongPeriod,1); // Dif=CheckDailyDirection(); // if (TradeType == "BUY" && Dif > PipsDifference * Point ) YesTrade = true; // if (TradeType == "SELL" && Dif < PipsDifference * Point ) YesTrade = true; if (TradeType == "BUY" && Dif > 0 ) YesTrade = true; if (TradeType == "SELL" && Dif < 0 ) YesTrade = true; return (YesTrade); } //+------------------------------------------------------------------------+ //| cancels all pending orders and closes open positions | //| Combined several routines that did almost the same thing | //+------------------------------------------------------------------------+ void ClosePendingOrdersAndPositions(bool CloseOpenPos,string type) { int totalorders = OrdersTotal(); for(int i=totalorders-1;i>=0;i--) { OrderSelect(i, SELECT_BY_POS); bool result = false; // modified by cori. Using OrderMagicNumber to identify the trades of the grid // hdb added or gridname for compatibility if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) ) // only look if mygrid and symbol... { if (CloseOpenPos) { if (type == "BUY") { //Close opened long positions if ( OrderType() == OP_BUY ) result = OrderClose( OrderTicket(), OrderLots(), Bid, 5, Red ); } if (type == "SELL") { //Close opened short positions if ( OrderType() == OP_SELL ) result = OrderClose( OrderTicket(), OrderLots(), Ask, 5, Red ); } } //Close pending orders if (type == "BUY" && OrderType() == OP_BUYSTOP ) result = OrderDelete( OrderTicket() ); if (type == "SELL" && OrderType() == OP_SELLSTOP ) result = OrderDelete( OrderTicket() ); } } return; } //+------------------------------------------------------------------------+ //| counts the number of open positions | //+------------------------------------------------------------------------+ int openPositions( ) { int op =0; int totalorders = OrdersTotal(); for(int i=totalorders-1;i>=0;i--) // scan all orders and positions... { OrderSelect(i, SELECT_BY_POS); if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) ) // only look if mygrid and symbol... { int type = OrderType(); if ( type == OP_BUY ) {op=op+1;} if ( type == OP_SELL ) {op=op+1;} } } return(op); } //+------------------------------------------------------------------------+ //| counts the number of grid positions | //+------------------------------------------------------------------------+ int openGrids( ) { int op =0; int totalorders = OrdersTotal(); for(int i=totalorders-1;i>=0;i--) // scan all orders and positions... { OrderSelect(i, SELECT_BY_POS); if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) ) // only look if mygrid and symbol... { int type = OrderType(); if ( type == OP_BUYSTOP ) {op=op+1;} if ( type == OP_SELLSTOP ) {op=op+1;} } } return(op); } //+------------------------------------------------------------------+ //| Check how much profit so far | //+------------------------------------------------------------------+ void TestForProfit( int forMagic, bool testOpen, bool testHistory ) // based on trailing stop code from MT site... but modified as per Hiro { closedProfit = 0; // counts closed p&l if (testHistory == true) { int total = HistoryTotal(); for(int i=0;i<total;i++) // scan all closed / cancelled transactions { OrderSelect(i, SELECT_BY_POS, MODE_HISTORY ); if ( OrderSymbol() == Symbol() && OrderMagicNumber() == forMagic ) // only look if mygrid and symbol... { closedProfit = closedProfit + OrderProfit(); } } } else { accumulatedProfit =0; } openProfit = 0; // counts open p&l if (testOpen == true) { total = OrdersTotal(); openLongs = 0; openShorts = 0; for(i=0;i<total;i++) // scan all open orders and positions { OrderSelect(i, SELECT_BY_POS ); if ( OrderSymbol() == Symbol() && OrderMagicNumber() == forMagic ) // only look if mygrid and symbol... { openProfit = openProfit + OrderProfit(); int type = OrderType(); if ( type == OP_BUY ) {openLongs=openLongs+1;} if ( type == OP_SELL ) {openShorts=openShorts+1;} } } } accumulatedProfit = accumulatedProfit + closedProfit + openProfit; } //+------------------------------------------------------------------+ //| Trailing stop procedure | //| Added new type of trailing stop(Type 1) that moves the stoploss | //| without delay. Old version (Type 2) waited for price to move the | //| amount of the trailStop before moving stop loss | //+------------------------------------------------------------------+ void TrailIt( int byPips ) // based on trailing stop code from MT site... thanks MT! { if (byPips >=5) { for (int i = 0; i < OrdersTotal(); i++) { OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol()==Symbol() && ( (OrderMagicNumber() == uniqueGridMagic) || (OrderComment() == GridName)) ) // only look if mygrid and symbol... { if (OrderType() == OP_BUY) { //if (Bid > (OrderValue(cnt,VAL_OPENPRICE) + TrailingStop * Point)) { // OrderClose(OrderTicket(), OrderLots(), Bid, 3, Violet); // break; //} if (TrailingStopType == 1) { if (Bid - OrderStopLoss() > StopLoss * Point) { OrderModify(OrderTicket(), OrderOpenPrice(), Bid - StopLoss * Point, OrderTakeProfit(),0, Red); } } else { if (Bid - OrderOpenPrice() > byPips * Point) { if (OrderStopLoss() < Bid - byPips * Point) { OrderModify(OrderTicket(), OrderOpenPrice(), Bid - byPips * Point, OrderTakeProfit(),0, Red); } } } } else if (OrderType() == OP_SELL) { if (TrailingStopType == 1) { if ((OrderStopLoss() - Ask > StopLoss * Point) || (OrderStopLoss() == 0)) { OrderModify(OrderTicket(), OrderOpenPrice(), Ask + StopLoss * Point, OrderTakeProfit(),0, Red); } } else { if (OrderOpenPrice() - Ask > byPips * Point) { if ((OrderStopLoss() > Ask + byPips * Point) || (OrderStopLoss() == 0)) { OrderModify(OrderTicket(), OrderOpenPrice(), Ask + byPips * Point, OrderTakeProfit(),0, Red); } } } } } } } } // proc TrailIt() //+------------------------------------------------------------------+ //| New Long Grid | //| Open a new grid using Buy Stops | //| No counter trades are placed | //| If Stop Loss or TakeProfit are used the values are calculated | //| for each trade | //+------------------------------------------------------------------+ void NewLongGrid() { int i,ticket; double myStopLoss = 0; LongTradeRate = Ask; for( i=1;i<=GridSteps;i++) { LongTradeRate = LongTradeRate + Point*GridSize; myStopLoss = 0; if ( StopLoss > 0 ) myStopLoss = LongTradeRate-Point*StopLoss ; // modified by cori. Using OrderMagicNumber to identify the trades of the grid if (TakeProfit>0) { ticket=OrderSend(Symbol(),OP_BUYSTOP,Lots,LongTradeRate,0,myStopLoss,LongTradeRate+Point*TakeProfit,GridName,uniqueGridMagic,0,Green); } else { ticket=OrderSend(Symbol(),OP_BUYSTOP,Lots,LongTradeRate,0,myStopLoss,0,GridName,uniqueGridMagic,0,Green); } } GridCount=GridSteps; } //+------------------------------------------------------------------+ //| Add To Long Grid | //| Add new positions to a long grid using Buy Stops | //| No counter trades are placed | //| If Stop Loss or TakeProfit are used the values are calculated | //| for each trade | //| LongTradeRate is used to determine where new Buy Stops occur | //| GridCount is used to determine how many new grid trades to add | //+------------------------------------------------------------------+ void AddToLongGrid() { int i,ticket,Num2Add; double myStopLoss = 0; Num2Add = GridSteps - GridCount; for( i=1;i<=Num2Add;i++) { LongTradeRate = LongTradeRate + Point*GridSize; myStopLoss = 0; if ( StopLoss > 0 ) myStopLoss = LongTradeRate-Point*StopLoss ; // modified by cori. Using OrderMagicNumber to identify the trades of the grid if (TakeProfit>0) { ticket=OrderSend(Symbol(),OP_BUYSTOP,Lots,LongTradeRate,0,myStopLoss,LongTradeRate+Point*TakeProfit,GridName,uniqueGridMagic,0,Green); } else { ticket=OrderSend(Symbol(),OP_BUYSTOP,Lots,LongTradeRate,0,myStopLoss,0,GridName,uniqueGridMagic,0,Green); } } GridCount=GridSteps; } //+------------------------------------------------------------------+ //| New Short Grid | //| Open a new grid using Sell Stops | //| No counter trades are placed | //| If Stop Loss or TakeProfit are used the values are calculated | //| for each trade | //+------------------------------------------------------------------+ void NewShortGrid() { int i, ticket; double myStopLoss = 0; ShortTradeRate = Bid; for( i=1;i<=GridSteps;i++) { ShortTradeRate = ShortTradeRate - Point*GridSize; myStopLoss = 0; if ( StopLoss > 0 ) myStopLoss = ShortTradeRate+Point*StopLoss ; // modified by cori. Using OrderMagicNumber to identify the trades of the grid if (TakeProfit > 0) { ticket=OrderSend(Symbol(),OP_SELLSTOP,Lots,ShortTradeRate,0,myStopLoss,ShortTradeRate-Point*TakeProfit,GridName,uniqueGridMagic,0,Red); } else { ticket=OrderSend(Symbol(),OP_SELLSTOP,Lots,ShortTradeRate,0,myStopLoss,0,GridName,uniqueGridMagic,0,Red); } } GridCount=GridSteps; } //+------------------------------------------------------------------+ //| Add To Short Grid | //| Add new positions to a short grid using Sell Stops | //| No counter trades are placed | //| If Stop Loss or TakeProfit are used the values are calculated | //| for each trade | //| ShortTradeRate is used to determine where new Sell Stops occur | //| GridCount is used to determine how many new grid trades to add | //+------------------------------------------------------------------+ void AddToShortGrid() { int i, ticket,Num2Add; double myStopLoss = 0; Num2Add = GridSteps - GridCount; for( i=1;i<=Num2Add;i++) { ShortTradeRate = ShortTradeRate - Point*GridSize; myStopLoss = 0; if ( StopLoss > 0 ) myStopLoss = ShortTradeRate+Point*StopLoss ; // modified by cori. Using OrderMagicNumber to identify the trades of the grid if (TakeProfit > 0) { ticket=OrderSend(Symbol(),OP_SELLSTOP,Lots,ShortTradeRate,0,myStopLoss,ShortTradeRate-Point*TakeProfit,GridName,uniqueGridMagic,0,Red); } else { ticket=OrderSend(Symbol(),OP_SELLSTOP,Lots,ShortTradeRate,0,myStopLoss,0,GridName,uniqueGridMagic,0,Red); } } GridCount=GridSteps; } //+------------------------------------------------------------------+ //| DetermineLots | //| Attempt at money management | //+------------------------------------------------------------------+ double DetermineLots() { double MyLots, AB; MyLots = Lots; AB = AccountBalance(); if (AB > 20000) MyLots = 0.2; if (AB > 40000) MyLots = 0.3; if (AB > 60000) MyLots = 0.4; if (AB > 80000) MyLots = 0.5; if (AB > 100000) MyLots = 1; return (MyLots); } //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int start() { //---- int currentOpen = 0; bool haveLongGrid=false,haveShortGrid=false; //---- setup parameters bool myWantLongs = true; bool myWantShorts = true; //---- test if we want to shutdown or suspend if (suspendGrid == true) { // close unfilled orders and then test if profit target ClosePendingOrdersAndPositions(false,"BUY"); ClosePendingOrdersAndPositions(false,"SELL"); return(0); } if (shutdownGrid == true) { // close all positions and orders. then exit.. there is nothing more to do ClosePendingOrdersAndPositions(true,"BUY"); ClosePendingOrdersAndPositions(false,"SELL"); return(0); } //---- if (gridActive == false) { // if grid not active, do nothing. return(0); } //---- if (MathAbs(CurTime()-LastUpdate)> UpdateInterval*60) // we update the first time it is called and every UpdateInterval minutes { TestForProfit(uniqueGridMagic, true, false ); if (!IsTesting()) { Comment(" v 1.93 "," Server time is ",TimeToStr(CurTime( )), "\n", // "\n"," Closed p&l = ",closedProfit, "\n"," Open p&l = ",openProfit, // "\n"," Total p&l = ",closedProfit + openProfit, "\n"," Long, Short = ",openLongs," ",openShorts, "\n"," Net pos = ",openLongs-openShorts, "\n", "\n"," Balance = ",AccountBalance(), "\n"," Equity = ",AccountEquity(), "\n"," Margin = ",AccountMargin(), "\n"," Free mrg = ",AccountFreeMargin(), ); } LastUpdate = CurTime(); } Lots = DetermineLots(); // Check if open positions need to be closed because of change in trend if (CheckExitCondition("BUY")) // if (haveLongGrid && CheckExitCondition("BUY")) { // CloseAllPendingOrders(); // if ( CloseOpenPositions == true ) { ClosePendingOrdersAndPositions(); } ClosePendingOrdersAndPositions(true,"BUY"); haveLongGrid = false; GridCount = 0; myWantLongs = false; myWantShorts = true; } if (CheckExitCondition("SELL")) // if (haveShortGrid && CheckExitCondition("SELL")) { // CloseAllPendingOrders(); // if ( CloseOpenPositions == true ) { ClosePendingOrdersAndPositions(); } ClosePendingOrdersAndPositions(true,"SELL"); haveShortGrid = false; GridCount = 0; myWantLongs = true; myWantShorts = false; } // Check if any open positions currentOpen = openPositions(); if (currentOpen > 0) { if (trailStop > 0) TrailIt(trailStop); } GridCount = openGrids(); if ( myWantLongs && CheckEntryCondition("BUY") ) { if (GridCount == 0 && currentOpen != GridSteps) { NewLongGrid(); haveLongGrid = true; } else { if (GridCount != GridSteps && ExtendGrid) AddToLongGrid(); } } if ( myWantShorts && CheckEntryCondition("SELL")) { if ( GridCount == 0 && currentOpen != GridSteps) { NewShortGrid(); haveShortGrid = true; } else { if (GridCount != GridSteps && ExtendGrid) AddToShortGrid(); } } return(0); } //+------------------------------------------------------------------+
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:
Checks for the total of open orders
It Closes Orders by itself
It can change open orders parameters, due to possible stepping strategy
It automatically opens orders when conditions are reached
Other Features: