/Three grades take profit Grid System, use it on weak market and fluctuating market, may need close all positions at some time.
//+------------------------------------------------------------------+
//| 204060.mq4 |
//| Robbie Ruan |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|History:
//|Ver 0.01 2009.08.01
//|Ver 0.02 2012.02.18
//| 1. Modified CloseAllWithEquityIncrease's EquityIncreasePercentage Control
//+------------------------------------------------------------------+
#property copyright "Robbie Ruan ver0.02 2012.02.18"
#property link "robbie.ruan@gmail.com"
string GridName = "AIGrid"; // identifies the grid. allows for several co-existing grids
extern int MagicNumberGrid = 10001; // Magic number of the trades. must be unique to identify the trades of one grid
extern double Lots = 0.01; //
extern bool ConsiderSpread = false;
extern double GridSize = 20; // pips between orders - grid or mesh size
extern double BaseTakeProfit = 50; // number of ticks to take profit. normally is = grid size but u can override
extern double Slippage = 2.5;
extern double GridSteps = 10; // total number of orders to place
extern double GridMaxOpenEachSide = 0; // maximum number of open positions either long or short side, not the sum of both
extern double StopLoss = 0; // if u want to add a stop loss. normal grids dont use stop losses
extern double Grid_High = 0; //define a regione that the price wave in
extern double Grid_Low = 0; //
extern int TrailStop = 0;
extern double FixedAllLongStopLoss = 0; //All long orders use the same StopLoss
extern double FixedAllShortStopLoss = 0; //All Short orders use the same StopLoss
extern double UpdateInterval = 0; // update orders every x minutes
extern bool wantLongs = true; // do we want long positions
extern bool wantShorts = true; // do we want short positions
extern bool wantBreakout = true; // do we want longs above price, shorts below price
extern bool wantCounter = true; // do we want longs below price, shorts above price
extern bool ProfitRank1 = true; // Control Profit Rank, if ProfitRank2,3 both false, then it's equals to 20 program
extern bool ProfitRank2 = false;
extern bool ProfitRank3 = false;
extern bool unEquLongShortControlLots = false;
extern bool EquityControlLots = false;
extern double BaseLots = 0.01;
extern double BaseEquity = 2000;
double Equity_Old;
extern bool CloseAllWithEquityIncrease = false;
extern bool CloseAllWithEquityDecrease = false;
extern double EquityIncreasePercentage = 10.0;
extern double EquityDecreasePercentage = 10.0;
extern string Note1 = "Equity Increase Decrease Percentage xx%";
extern bool StopTradeAfterEquityIncreased = false;
extern bool StopTradeAfterEquityDecreased = false;
bool StopTradeFlag = false;
extern bool LimitEMA60 = false; // do we want longs above ema only, shorts below ema only
extern bool UseMACD = false; // if true, will use macd >0 for longs only, macd >0 for shorts only
// on crossover, will cancel all pending orders. This will override any
// wantLongs and wantShort settings - at least for now.
extern bool UseMAGroup=false; // if all fast ma > slow ma,do not make short;
// if all fast ma < slow ma, do not make long;
extern bool UseStochastic=false;
extern bool UseSAR = false;
extern double SAR_Step = 0.02;
extern double SAR_Maximum = 0.2;
extern bool CloseOpenPositions = false;// if UseMACD or UseMAGroup, do we also close open positions with a loss?
extern bool ClosePendingPositions = false; // Close Pending Positions Far Away From Present Price
double LastUpdate = 0; // counter used to note time of last update
//int LisenceStartTime = D'31.12.2009 11:30';
//int LisenceEndTime = D'31.12.2011 11:30';
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
#property show_inputs // shows the parameters - thanks Slawa...
Equity_Old = AccountEquity();
if (MarketInfo("EURUSD",MODE_DIGITS)==5)
{
GridSize *= 10;
BaseTakeProfit *= 10;
Slippage *= 10;
StopLoss *= 10;
TrailStop *= 10;
}
//double spread = MarketInfo(Symbol(),MODE_SPREAD);
//if ( BaseTakeProfit <= 0 ) //
// { BaseTakeProfit = GridSize-spread; }
// Print("BaseTakeProfit......................",BaseTakeProfit);
//----
// GridName = StringConcatenate( "AIGrid", Symbol() );
return(0);
}
//+------------------------------------------------------------------------+
//| tests if there is an open position or order in the region of atRate |
//| will check for longs if checkLongs is true, else will check |
//| for shorts |
//+------------------------------------------------------------------------+
int IsPosition(double atRate, double inRange, bool checkLongs )
{
int CheckPositionRank = 0; // check how many rank profit is made in the specified rate and return to the function
int totalorders = OrdersTotal();
int type;
double CurrentOrderTakeProfit;
double point = MarketInfo(Symbol(),MODE_POINT);
for(int j=0;j<totalorders;j++) // scan all orders and positions...
{
OrderSelect(j, SELECT_BY_POS);
if ( ( OrderSymbol()==Symbol() ) && ( OrderMagicNumber() == MagicNumberGrid ) ) // only look if mygrid and symbol...
{
///////////////////////////////////////////////////////////////////////////////////////////////////////
// don't reset order near the present price
if( wantBreakout != wantCounter) // if only long order up, short order down, or only short order up, long order down
{
if ( ( checkLongs && (MathAbs(Ask-atRate) < (inRange*0.9999)) ) || ( !checkLongs && (MathAbs(Bid-atRate) < (inRange*0.9999)) ) )
{
CheckPositionRank |= 7;
return(CheckPositionRank); // if price near present price, direct return true
}
}
if(MathAbs( OrderOpenPrice() - atRate ) < (inRange*0.9999 - point*Slippage))// dont look for exact price but price proximity (less than gridsize)
{
type = OrderType();
if ( ( checkLongs && ( type == OP_BUY || type == OP_BUYLIMIT || type == OP_BUYSTOP ) ) || (!checkLongs && ( type == OP_SELL || type == OP_SELLLIMIT || type == OP_SELLSTOP ) ) )
{
CurrentOrderTakeProfit = NormalizeDouble( ( OrderTakeProfit() - OrderOpenPrice() ),Digits );
CurrentOrderTakeProfit = MathAbs( CurrentOrderTakeProfit );
if( ProfitRank1 && ( MathAbs( CurrentOrderTakeProfit - point*BaseTakeProfit ) < point* Slippage ) )
{
CheckPositionRank |= 1;
//Print("CheckPositionRank",CheckPositionRank);
}
else if( ProfitRank2 && ( MathAbs( CurrentOrderTakeProfit - point*(GridSize+BaseTakeProfit) ) < point* Slippage ) )
{
CheckPositionRank |= 2;
//Print("CheckPositionRank",CheckPositionRank);
}
else if( ProfitRank3 && ( MathAbs( CurrentOrderTakeProfit - point*(GridSize*2+BaseTakeProfit) ) < point* Slippage ) )
{
CheckPositionRank |= 4;
//Print("CheckPositionRank",CheckPositionRank);
}
}
} // if MathAbs end here
} // if loop end here
} // for loop end here
// Print("CheckPositionRank::::::::::::::::::::::",CheckPositionRank);
return(CheckPositionRank);
}
//+------------------------------------------------------------------------+
//| close all open orders
//+------------------------------------------------------------------------+
void CloseAllOpenOrders()
{
int total = OrdersTotal();
for(int i=total-1;i>=0;i--)
{
OrderSelect(i, SELECT_BY_POS);
int type = OrderType();
bool result = false;
if ( ( OrderSymbol()==Symbol() ) && ( OrderMagicNumber() == MagicNumberGrid ) ) // only look if mygrid and symbol...
{
//Print("Closing 2 ",type);
switch(type)
{
//Close opened long positions
case OP_BUY : result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), Slippage, Red );
break;
//Close opened short positions
case OP_SELL : result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), Slippage, Red );
break;
//Close pending orders
case OP_BUYLIMIT : result = true ;
case OP_BUYSTOP : result = true ;
case OP_SELLLIMIT : result = true ;
case OP_SELLSTOP : result = true ;
}
}
if(result == false)
{
//Alert("Order " , OrderTicket() , " failed to close. Error:" , GetLastError() );
//Sleep(3000);
}
}
return;
}
//+------------------------------------------------------------------------+
//| cancel all pending orders |
//+------------------------------------------------------------------------+
void CloseAllPendingOrders()
{
int totalorders = OrdersTotal();
for(int j=totalorders-1;j>=0;j--) // scan all orders and positions...
{
OrderSelect(j, SELECT_BY_POS);
if ( ( OrderSymbol()==Symbol() ) && ( OrderMagicNumber() == MagicNumberGrid ) ) // only look if mygrid and symbol...
{
int type = OrderType();
bool result = false;
switch(type)
{
case OP_BUYLIMIT : result = OrderDelete( OrderTicket() ); break;
case OP_BUYSTOP : result = OrderDelete( OrderTicket() ); break;
case OP_SELLLIMIT : result = OrderDelete( OrderTicket() ); break;
case OP_SELLSTOP : result = OrderDelete( OrderTicket() ); break;
case OP_BUY : result = true ;
case OP_SELL : result = true ;
//Close pending orders
}
}
}
return;
}
//+------------------------------------------------------------------------+
//| cancel pending long orders |
//+------------------------------------------------------------------------+
void ClosePendingLongOrders( )
{
int totalorders = OrdersTotal();
for(int j=totalorders-1;j>=0;j--) // scan all orders and positions...
{
OrderSelect(j, SELECT_BY_POS);
if ( ( OrderSymbol()==Symbol() ) && ( OrderMagicNumber() == MagicNumberGrid ) ) // only look if mygrid and symbol...
{
int type = OrderType();
bool result = false;
switch(type)
{
case OP_BUYLIMIT : result = OrderDelete( OrderTicket() ); break;
case OP_BUYSTOP : result = OrderDelete( OrderTicket() ); break;
case OP_BUY : result = true;
case OP_SELL : result = true;
//Close pending orders
case OP_SELLLIMIT : result = true;
case OP_SELLSTOP : result = true;
}
}
}
return;
}
//+------------------------------------------------------------------------+
//| cancel pending short orders |
//+------------------------------------------------------------------------+
void ClosePendingShortOrders( )
{
int totalorders = OrdersTotal();
for(int j=totalorders-1;j>=0;j--) // scan all orders and positions...
{
OrderSelect(j, SELECT_BY_POS);
if ( ( OrderSymbol()==Symbol() ) && ( OrderMagicNumber() == MagicNumberGrid ) ) // only look if mygrid and symbol...
{
int type = OrderType();
bool result = false;
switch(type)
{
case OP_SELLLIMIT : result = OrderDelete( OrderTicket() ); break;
case OP_SELLSTOP : result = OrderDelete( OrderTicket() ); break;
case OP_BUY : result = true;
case OP_SELL : result = true;
//Close pending orders
case OP_BUYLIMIT : result = true;
case OP_BUYSTOP : result = true;
}
}
}
return;
}
//+------------------------------------------------------------------------+
//| cancel all pending orders and close open positions |
//+------------------------------------------------------------------------+
void CloseAllOrders()
{
int total = OrdersTotal();
for(int i=total-1;i>=0;i--)
{
OrderSelect(i, SELECT_BY_POS);
int type = OrderType();
bool result = false;
if ( ( OrderSymbol()==Symbol() ) && ( OrderMagicNumber() == MagicNumberGrid ) ) // only look if mygrid and symbol...
{
// Print("Closing 2 ",type);
switch(type)
{
//Close opened long positions
case OP_BUY : result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), Slippage, Red );
break;
//Close opened short positions
case OP_SELL : result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), Slippage, Red );
break;
//Close pending orders
case OP_BUYLIMIT : result = OrderDelete( OrderTicket() ); break;
case OP_BUYSTOP : result = OrderDelete( OrderTicket() ); break;
case OP_SELLLIMIT : result = OrderDelete( OrderTicket() ); break;
case OP_SELLSTOP : result = OrderDelete( OrderTicket() ); break;
}
}
if(result == false)
{
// Alert("Order " , OrderTicket() , " failed to close. Error:" , GetLastError() );
// Sleep(3000);
}
}
return;
}
//+------------------------------------------------------------------------+
//| cancel pending long orders and close open long positions |
//+------------------------------------------------------------------------+
void CloseLongOrders()
{
int total = OrdersTotal();
for(int i=total-1;i>=0;i--)
{
OrderSelect(i, SELECT_BY_POS);
int type = OrderType();
bool result = false;
if ( ( OrderSymbol()==Symbol() ) && ( OrderMagicNumber() == MagicNumberGrid ) ) // only look if mygrid and symbol...
{
// Print("Closing 2 ",type);
switch(type)
{
//Close opened long positions
case OP_BUY : result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), Slippage, Red ); break;
case OP_BUYLIMIT : result = OrderDelete( OrderTicket() ); break;
case OP_BUYSTOP : result = OrderDelete( OrderTicket() ); break;
//Reserve opened short positions
case OP_SELL : result = true;
case OP_SELLLIMIT : result = true;
case OP_SELLSTOP : result = true;
}
}
if(result == false)
{
// Alert("Order " , OrderTicket() , " failed to close. Error:" , GetLastError() );
// Sleep(3000);
}
}
return;
}
//+------------------------------------------------------------------------+
//| cancel pending short orders and close open short positions |
//+------------------------------------------------------------------------+
void CloseShortOrders()
{
int total = OrdersTotal();
for(int i=total-1;i>=0;i--)
{
OrderSelect(i, SELECT_BY_POS);
int type = OrderType();
bool result = false;
if ( ( OrderSymbol()==Symbol() ) && ( OrderMagicNumber() == MagicNumberGrid ) ) // only look if mygrid and symbol...
{
// Print("Closing 2 ",type);
switch(type)
{
//Close opened short positions
case OP_SELL : result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), Slippage, Red ); break;
case OP_SELLLIMIT : result = OrderDelete( OrderTicket() ); break;
case OP_SELLSTOP : result = OrderDelete( OrderTicket() ); break;
//Reserve opened long positions
case OP_BUY : result = true;
case OP_BUYLIMIT : result = true;
case OP_BUYSTOP : result = true;
}
}
if(result == false)
{
// Alert("Order " , OrderTicket() , " failed to close. Error:" , GetLastError() );
// Sleep(3000);
}
}
return;
}
//+------------------------------------------------------------------+
//| script program start function |
//+------------------------------------------------------------------+
int start()
{
//----
int i, k, type, ticket, entermode;
int totalorders,LongOpenOrders,ShortOpenOrders;
bool doit;
double point, startrate, traderate,spread,traderate_Long;
double LongLots,ShortLots;
double Equity_New;
// if (TimeCurrent() >= LisenceEndTime )
// {
// Print("Time Expired, please contact robbie.ruan@gmail.com");
// return(0);
// }
// Parameters defined here are initialized every time, while diefined as extern type initialize just once.
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//if Equity increased EquityIncreasePercentage%, close all
if(CloseAllWithEquityIncrease)
{
Equity_New = AccountEquity();
if( (Equity_New - Equity_Old)/Equity_Old >= EquityIncreasePercentage/100 )
{
Print("Close All With Equity Increased: ", EquityIncreasePercentage, "%");
Equity_Old = Equity_New;
CloseAllOpenOrders();
CloseAllPendingOrders();
if(StopTradeAfterEquityIncreased == true)
{
StopTradeFlag = true;
Print("Stop Trade With Equity Increased, to restart trade, exit and run the EA again");
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//if Equity Decreased EquityIncreasePercentage%, close all
if(CloseAllWithEquityDecrease)
{
Equity_New = AccountEquity();
if( (Equity_Old - Equity_New)/Equity_Old >= EquityDecreasePercentage/100 )
{
Print("Close All With Equity Decreased: ", EquityDecreasePercentage, "%");
Equity_Old = Equity_New;
CloseAllOpenOrders();
CloseAllPendingOrders();
if(StopTradeAfterEquityDecreased == true)
{
StopTradeFlag = true;
Print("Stop Trade With Equity Decreased, to restart trade, exit and run the EA again");
}
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// if(StopTradeAfterEquityIncreased == true)
// {
// if (StopTradeFlag == true)
// {
// Print("EquityIncreased, Stop Trade, to restart trade, exit and reset the EA");
// return(0);
// }
// }
string ScreenString = "DateOfTrade";
ObjectDelete(ScreenString);
ObjectCreate(ScreenString, OBJ_LABEL, 0, 0, 0);
ObjectSetText(ScreenString, ""+TimeToStr(CurTime( ))+" Day"+DayOfWeek(), 12, "Arial Bold", Lime);
ObjectSet(ScreenString, OBJPROP_CORNER, 3);
ObjectSet(ScreenString, OBJPROP_XDISTANCE, 5);
ObjectSet(ScreenString, OBJPROP_YDISTANCE, 5);
//----
if ( (MathAbs(CurTime()-LastUpdate)> UpdateInterval*60) && (StopTradeFlag == false) ) // we update the first time it is called and every UpdateInterval minutes
{
LastUpdate = CurTime();
point = MarketInfo(Symbol(),MODE_POINT);
if(ConsiderSpread == true)
{
spread = MarketInfo(Symbol(),MODE_SPREAD);
spread = point*spread;
}
else
{
spread = 0;
}
LongLots = Lots;
ShortLots = Lots;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Equity Control Lots
if(EquityControlLots)
{
//Print("Account equity ================== ",AccountEquity());
double EquityPercentage = AccountEquity()/AccountBalance();
//Print("===========================EquityPercentage=====",EquityPercentage);
int EquityTimes = MathFloor( (AccountEquity()/BaseEquity) * EquityPercentage ); // how many time is present equity times BaseEquity
//Print("EquityTimes===========",EquityTimes);
if(EquityTimes >= 1)
{
Lots = BaseLots*EquityTimes; // total new open Lots
LongLots = Lots;
ShortLots = Lots;
}
//Print("NewLots====================================", Lots);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
//calulate total open order quantiies
totalorders = OrdersTotal();
LongOpenOrders = 0;
ShortOpenOrders = 0;
for(i=0;i<totalorders;i++)
{
OrderSelect(i,SELECT_BY_POS);
type = OrderType();
if(type == OP_BUY)
LongOpenOrders++;
else if(type == OP_SELL)
ShortOpenOrders++;
}
////////////////////////////////////////////////////////////////////////////////////////////
//Unbalanced OpenOrders ControlLots, the smaller long short ratio, the more long lots and less short lots, vice visa
if(unEquLongShortControlLots)
{
if( (LongOpenOrders >=10 || ShortOpenOrders >= 10) && Lots > 0.1)
{
LongLots = Lots * (2.0*ShortOpenOrders/(LongOpenOrders+ShortOpenOrders));
LongLots = NormalizeDouble(LongLots,2);
ShortLots = Lots*2-LongLots;
if(LongLots == 0)
{
LongLots += BaseLots;
ShortLots -= BaseLots;
}
else if(ShortLots == 0)
{
ShortLots += BaseLots;
LongLots -= BaseLots;
}
}
//Print("LongOpenOrders::::::::::::::",LongOpenOrders);
//Print(":::::::ShortOpenOrders::::::::::::::",ShortOpenOrders);
}
//Print("LongLots============================================", LongLots);
//Print("=========ShortLots========================================", ShortLots);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Trailing stop
if (TrailStop > 0) TrailingStop(TrailStop);
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// default base value is low price, if Low value is 0, then check if High value also 0, if both 0, then use market price as base value.
if( Grid_Low > 0 )
startrate=Grid_Low;
else if( (Grid_Low == 0) && Grid_High>0 )
startrate=Grid_High;
else
{
startrate = ( Bid + point*GridSize/2 ) / point / GridSize; // round to a number of ticks divisible by GridSize
k = startrate ;
k = k * GridSize ;
startrate = k * point - GridSize*GridSteps/2*point ; // calculate the lowest entry point
}
// Print("startrate::::::::::",startrate);
double EMA60=iMA(NULL,PERIOD_H1,60,0,MODE_EMA,PRICE_CLOSE,0);
/////////////////////////////////////////////////////////////////////////////////////////////////////
// if use MACD
if ( UseMACD ) {
double Macd0=iMACD(NULL,PERIOD_H4,12,26,9,PRICE_CLOSE,MODE_MAIN,0);
double Macd1=iMACD(NULL,PERIOD_H4,12,26,9,PRICE_CLOSE,MODE_MAIN,1);
double Macd2=iMACD(NULL,PERIOD_H4,12,26,9,PRICE_CLOSE,MODE_MAIN,2);
if( Macd0>0 && Macd1>0 && Macd2<0) // cross up
{
CloseAllPendingOrders();
if ( CloseOpenPositions == true ) { CloseAllOrders(); }
}
if( Macd0<0 && Macd1<0 && Macd2>0) // cross down
{
CloseAllPendingOrders();
if ( CloseOpenPositions == true ) { CloseAllOrders(); }
}
wantLongs = false;
wantShorts = false;
if( Macd0>0 && Macd1>0 && Macd2>0) // is well above zero
{
wantLongs = true;
}
if( Macd0<0 && Macd1<0 && Macd2<0) // is well below zero
{
wantShorts = true;
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
// if Use SAR
if ( UseSAR )
{
wantLongs = false;
wantShorts = false;
double CLOSE0 = iClose(NULL, PERIOD_W1, 0);
double SAR0 = iSAR(NULL, PERIOD_W1, SAR_Step, SAR_Maximum, 0);
if(SAR0 < CLOSE0)
{
wantLongs = true;
}
if(SAR0 > CLOSE0)
{
wantShorts = true;
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// when use MA Group, ADX must be used
if(UseMAGroup)
{
double SMA5=iMA(NULL,PERIOD_M15,5,0,MODE_SMA,PRICE_CLOSE,0);
double SMA13=iMA(NULL,PERIOD_M15,13,0,MODE_SMA,PRICE_CLOSE,0);
double SMA21=iMA(NULL,PERIOD_M15,21,0,MODE_SMA,PRICE_CLOSE,0);
double SMA60=iMA(NULL,PERIOD_M15,60,0,MODE_SMA,PRICE_CLOSE,0);
double SMA200=iMA(NULL,PERIOD_M15,200,0,MODE_SMA,PRICE_CLOSE,0);
// MA Group Divergent Trend Up
if(SMA5>SMA13 && SMA13>SMA21 && SMA21>SMA60 && SMA60>SMA200 && (SMA5-SMA21>0.0040))
{
//KD Cross Up
if( (!UseStochastic || ((iStochastic(NULL,PERIOD_H1,5,3,3,MODE_SMA,0,MODE_MAIN,0)-iStochastic(NULL,PERIOD_H1,5,3,3,MODE_SMA,0,MODE_SIGNAL,0))) > 2) )
{
//Print("Cross Up MAIN:::::::::::::::::::::::::::",iStochastic(NULL,PERIOD_H1,5,3,3,MODE_SMA,0,MODE_MAIN,0));
//Print("Signal::::",iStochastic(NULL,PERIOD_H1,5,3,3,MODE_SMA,0,MODE_SIGNAL,0));
//Sleep(5000);
ClosePendingShortOrders();
if(CloseOpenPositions==true) { CloseShortOrders(); }
wantLongs=true;
wantShorts=false;
}
}
//MA Group Divergent Trend Down
else if(SMA5<SMA13 && SMA13<SMA21 && SMA21<SMA60 && SMA60<SMA200 && (SMA21-SMA5>0.0040))
{
//KD Cross Down
if( (!UseStochastic || ((iStochastic(NULL,PERIOD_H1,5,3,3,MODE_SMA,0,MODE_SIGNAL,0)-iStochastic(NULL,PERIOD_H1,5,3,3,MODE_SMA,0,MODE_MAIN,0))) > 2) )
{
//Print("Cross Down MAIN...............................",iStochastic(NULL,PERIOD_H1,5,3,3,MODE_SMA,0,MODE_MAIN,0));
//Print("Signal::::",iStochastic(NULL,PERIOD_H1,5,3,3,MODE_SMA,0,MODE_SIGNAL,0));
//Sleep(5000);
ClosePendingLongOrders();
if(CloseOpenPositions==true) { CloseLongOrders(); }
wantLongs=false;
wantShorts=true;
}
}
else
{
wantLongs=false;
wantShorts=false;
PlaySound("alert2.wav");
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////
for( i=0;i<GridSteps;i++)
{
if( (Grid_Low == 0) && Grid_High > 0 )
traderate = startrate - i*point*GridSize;
else
traderate = startrate + i*point*GridSize; // Whether Grid_Low >0 or =0, both put net from bottom up
traderate_Long = traderate+spread;
if((Grid_Low > 0 && traderate < Grid_Low) || (Grid_High > 0 && traderate > Grid_High))
break;
// all pending orders will not exeed order high low limit
if ( wantLongs && (!LimitEMA60 || traderate > EMA60) && (LongLots > 0) && (((GridMaxOpenEachSide > 0) && (LongOpenOrders < GridMaxOpenEachSide)) || (GridMaxOpenEachSide == 0)) )
{
int CheckPositionRank=255;
CheckPositionRank=IsPosition(traderate_Long,point*GridSize,true);
// Print("CheckPositionRank>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>",CheckPositionRank);
// Print("CheckPositionRank & 1:::::::::::",CheckPositionRank & 1);
// Print("CheckPositionRank & 2:::::::::::",CheckPositionRank & 2);
// Print("CheckPositionRank & 4:::::::::::",CheckPositionRank & 4);
//check profit rank 1
if ( ProfitRank1 && ((CheckPositionRank & 1) == 0) ) // test if i have no open orders profit rank 1 close to my price: if so, put one on
{
double myStopLoss = 0;
if(FixedAllLongStopLoss>0)
myStopLoss=FixedAllLongStopLoss;
else if( StopLoss > 0 )
{
myStopLoss = traderate_Long-point*StopLoss;
}
if( traderate_Long > Ask )
{ entermode = OP_BUYSTOP; }
else
{ entermode = OP_BUYLIMIT ; }
if( ((traderate_Long > Ask ) && (wantBreakout)) || ((traderate_Long <= Ask ) && (wantCounter)) )
{
ticket=OrderSend(Symbol(),entermode,LongLots,traderate_Long,0,myStopLoss,traderate_Long+point*BaseTakeProfit,GridName,MagicNumberGrid,0,Green);
}
}
//check profit rank 2
if ( ProfitRank2 && ((CheckPositionRank & 2) == 0) ) // test if i have no open orders profit rank 2 close to my price: if so, put one on
{
myStopLoss = 0;
if(FixedAllLongStopLoss>0)
myStopLoss=FixedAllLongStopLoss;
else if( StopLoss > 0 )
{
myStopLoss = traderate_Long-point*StopLoss;
}
if( traderate_Long > Ask )
{ entermode = OP_BUYSTOP; }
else
{ entermode = OP_BUYLIMIT ; }
if( ((traderate_Long > Ask ) && (wantBreakout)) || ((traderate_Long <= Ask ) && (wantCounter)) )
{
ticket=OrderSend(Symbol(),entermode,LongLots,traderate_Long,0,myStopLoss,traderate_Long+point*(GridSize+BaseTakeProfit),GridName,MagicNumberGrid,0,Green);
}
}
//check profit rank 3
if ( ProfitRank3 && ((CheckPositionRank & 4) == 0) ) // test if i have no open orders profit rank 3 close to my price: if so, put one on
{
myStopLoss = 0;
if(FixedAllLongStopLoss>0)
myStopLoss=FixedAllLongStopLoss;
else if( StopLoss > 0 )
{
myStopLoss = traderate_Long-point*StopLoss;
}
if( traderate_Long > Ask )
{ entermode = OP_BUYSTOP; }
else
{ entermode = OP_BUYLIMIT ; }
if( ((traderate_Long > Ask ) && (wantBreakout)) || ((traderate_Long <= Ask ) && (wantCounter)) )
{
ticket=OrderSend(Symbol(),entermode,LongLots,traderate_Long,0,myStopLoss,traderate_Long+point*(GridSize*2+BaseTakeProfit),GridName,MagicNumberGrid,0,Green);
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
if( wantShorts && (!LimitEMA60 || traderate < EMA60) && (ShortLots > 0) && (((GridMaxOpenEachSide > 0) && (ShortOpenOrders < GridMaxOpenEachSide)) || (GridMaxOpenEachSide == 0)) )
{
CheckPositionRank = 255;
CheckPositionRank = IsPosition(traderate,point*GridSize,false);
// Print("CheckPositionRank..................................................................",CheckPositionRank);
// Print("CheckPositionRank & 1:::::::::::",CheckPositionRank & 1);
// Print("CheckPositionRank & 2:::::::::::",CheckPositionRank & 2);
// Print("CheckPositionRank & 4:::::::::::",CheckPositionRank & 4);
//check profit rank 1
if ( ProfitRank1 && ((CheckPositionRank & 1) == 0) ) // test if i have no open orders profit rank 1 close to my price: if so, put one on
{
myStopLoss = 0;
if( FixedAllShortStopLoss > 0 )
myStopLoss=FixedAllShortStopLoss;
else if ( StopLoss > 0 )
{
myStopLoss = traderate+point*StopLoss;
}
if( traderate > Bid )
{ entermode = OP_SELLLIMIT; }
else
{ entermode = OP_SELLSTOP ; }
if( ((traderate < Bid ) && (wantBreakout)) || ((traderate >= Bid ) && (wantCounter)) )
{
ticket=OrderSend(Symbol(),entermode,ShortLots,traderate,0,myStopLoss,traderate-point*BaseTakeProfit,GridName,MagicNumberGrid,0,Red);
}
}
//check profit rank 2
if ( ProfitRank2 && ((CheckPositionRank & 2) == 0) ) // test if i have no open orders profit rank 2 close to my price: if so, put one on
{
myStopLoss = 0;
if( FixedAllShortStopLoss > 0 )
myStopLoss=FixedAllShortStopLoss;
else if ( StopLoss > 0 )
{
myStopLoss = traderate+point*StopLoss;
}
if( traderate > Bid )
{ entermode = OP_SELLLIMIT; }
else
{ entermode = OP_SELLSTOP ; }
if( ((traderate < Bid ) && (wantBreakout)) || ((traderate >= Bid ) && (wantCounter)) )
{
ticket=OrderSend(Symbol(),entermode,ShortLots,traderate,0,myStopLoss,traderate-point*(GridSize+BaseTakeProfit),GridName,MagicNumberGrid,0,Red);
}
}
//check profit rank 3
if ( ProfitRank3 && ((CheckPositionRank & 4) == 0) ) // test if i have no open orders profit rank 3 close to my price: if so, put one on
{
myStopLoss = 0;
if( FixedAllShortStopLoss > 0 )
myStopLoss=FixedAllShortStopLoss;
else if ( StopLoss > 0 )
{
myStopLoss = traderate+point*StopLoss;
}
if( traderate > Bid )
{ entermode = OP_SELLLIMIT; }
else
{ entermode = OP_SELLSTOP ; }
if( ((traderate < Bid ) && (wantBreakout)) || ((traderate >= Bid ) && (wantCounter)) )
{
ticket=OrderSend(Symbol(),entermode,ShortLots,traderate,0,myStopLoss,traderate-point*(GridSize*2+BaseTakeProfit),GridName,MagicNumberGrid,0,Red);
}
}
} //short "if" end here
}// Grid "for" end here
if(ClosePendingPositions) // close pending orders far away from present price
{
for(i=0;i<OrdersTotal();i++)
{
OrderSelect(i, SELECT_BY_POS);
type=OrderType();
if( ( (type==OP_BUYLIMIT || type==OP_BUYSTOP) && MathAbs(OrderOpenPrice()-Ask) > point*GridSize*(GridSteps*0.5) ) || ( (type==OP_SELLLIMIT || type==OP_SELLSTOP) && MathAbs(OrderOpenPrice()-Bid) > point*GridSize*(GridSteps*0.5) ) )// Orders outside the GridSize
{
OrderDelete(OrderTicket());
}
}
} //close pending order if end here
}// time check "if" end here
return(0);
}
//+------------------------------------------------------------------+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//Trailing Stop function
void TrailingStop(int TrailStop)
{
if (TrailStop >= 5)
{
int total = OrdersTotal();
for (int i = 0; i < total; i++)
{
OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
if ( OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumberGrid )
{
if (OrderType() == OP_BUY)
{
if ( Bid - OrderOpenPrice() > TrailStop * MarketInfo(OrderSymbol(), MODE_POINT) )
{
if (OrderStopLoss() < Bid - TrailStop * MarketInfo(OrderSymbol(), MODE_POINT) )
{
OrderModify(OrderTicket(), OrderOpenPrice(), Bid - TrailStop * MarketInfo(OrderSymbol(), MODE_POINT), OrderTakeProfit(), OrderExpiration(),CLR_NONE);
}
}
}
else if (OrderType() == OP_SELL)
{
if (OrderOpenPrice() - Ask > TrailStop * MarketInfo(OrderSymbol(), MODE_POINT))
{
if (OrderStopLoss() > Ask + TrailStop * MarketInfo(OrderSymbol(), MODE_POINT) || OrderStopLoss() == 0.0)
{
OrderModify(OrderTicket(), OrderOpenPrice(), Ask + TrailStop * MarketInfo(OrderSymbol(), MODE_POINT), OrderTakeProfit(), OrderExpiration(),CLR_NONE);
}
}
} //else end
}// magic end
} // for total end
}// if TrailStop >=5 end
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//---- input parameters ---------------------------------------------+
extern int INCREMENT=35;
extern double LOTS=0.1;
extern int LEVELS=3;
extern double MAX_LOTS=99;
extern int MAGIC=1803;
extern bool CONTINUE=true;
extern bool MONEY_MANAGEMENT=false;
extern int RISK_RATIO=2;
//+------------------------------------------------------------------+
bool UseProfitTarget=false;
bool UsePartialProfitTarget=false;
int Target_Increment = 50;
int First_Target = 20;
bool UseEntryTime=false;
int EntryTime=0;
//+------------------------------------------------------------------+
bool Enter=true;
int nextTP;
int init()
{
//+------------------------------------------------------------------+
nextTP = First_Target;
//+------------------------------------------------------------------+
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
return(0);
}
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
int ticket, cpt, profit, total=0, BuyGoalProfit, SellGoalProfit, PipsLot;
double ProfitTarget=INCREMENT*2, BuyGoal=0, SellGoal=0, spread=(Ask-Bid)/Point, InitialPrice=0;
//----
if(INCREMENT<MarketInfo(Symbol(),MODE_STOPLEVEL)+spread) INCREMENT=1+MarketInfo(Symbol(),MODE_STOPLEVEL)+spread;
if(MONEY_MANAGEMENT) LOTS=NormalizeDouble(AccountBalance()*AccountLeverage()/1000000*RISK_RATIO,0)*MarketInfo(Symbol(),MODE_MINLOT);
if(LOTS<MarketInfo(Symbol(),MODE_MINLOT))
{
Comment("Not Enough Free Margin to begin");
return(0);
}
for(cpt=1;cpt<LEVELS;cpt++) PipsLot+=cpt*INCREMENT;
for(cpt=0;cpt<OrdersTotal();cpt++)
{
OrderSelect(cpt,SELECT_BY_POS,MODE_TRADES);
if(OrderMagicNumber()==MAGIC && OrderSymbol()==Symbol())
{
total++;
if(!InitialPrice) InitialPrice=StrToDouble(OrderComment());
if(UsePartialProfitTarget && UseProfitTarget && OrderType()<2)
{
double val=getPipValue(OrderOpenPrice(),OrderType());
takeProfit(val,OrderTicket());
}
}
}
if(total<1 && Enter && (!UseEntryTime || (UseEntryTime && Hour()==EntryTime)))
{
if(AccountFreeMargin()<(100*LOTS))
{
Print("Not enough free margin to begin");
return(0);
}
// - Open Check - Start Cycle
InitialPrice=Ask;
SellGoal=InitialPrice-(LEVELS+1)*INCREMENT*Point;
BuyGoal=InitialPrice+(LEVELS+1)*INCREMENT*Point;
for(cpt=1;cpt<=LEVELS;cpt++)
{
OrderSend(Symbol(),OP_BUYSTOP,LOTS,InitialPrice+cpt*INCREMENT*Point,2,SellGoal,BuyGoal,DoubleToStr(InitialPrice,MarketInfo(Symbol(),MODE_DIGITS)),MAGIC,0);
OrderSend(Symbol(),OP_SELLSTOP,LOTS,InitialPrice-cpt*INCREMENT*Point,2,BuyGoal+spread*Point,SellGoal+spread*Point,DoubleToStr(InitialPrice,MarketInfo(Symbol(),MODE_DIGITS)),MAGIC,0);
}
} // initial setup done - all channels are set up
else // We have open Orders
{
BuyGoal=InitialPrice+INCREMENT*(LEVELS+1)*Point;
SellGoal=InitialPrice-INCREMENT*(LEVELS+1)*Point;
total=OrdersHistoryTotal();
for(cpt=0;cpt<total;cpt++)
{
OrderSelect(cpt,SELECT_BY_POS,MODE_HISTORY);
if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGIC && StrToDouble(OrderComment())==InitialPrice){EndSession();return(0);}
}
if(UseProfitTarget && CheckProfits(LOTS,OP_SELL,true,InitialPrice)>ProfitTarget) {EndSession();return(0);}
BuyGoalProfit=CheckProfits(LOTS,OP_BUY,false,InitialPrice);
SellGoalProfit=CheckProfits(LOTS,OP_SELL,false,InitialPrice);
if(BuyGoalProfit<ProfitTarget)
// - Incriment Lots Buy
{
for(cpt=LEVELS;cpt>=1 && BuyGoalProfit<ProfitTarget;cpt--)
{
if(Ask<=(InitialPrice+(cpt*INCREMENT-MarketInfo(Symbol(),MODE_STOPLEVEL))*Point))
{
ticket=OrderSend(Symbol(),OP_BUYSTOP,cpt*LOTS,InitialPrice+cpt*INCREMENT*Point,2,SellGoal,BuyGoal,DoubleToStr(InitialPrice,MarketInfo(Symbol(),MODE_DIGITS)),MAGIC,0);
}
if(ticket>0) BuyGoalProfit+=LOTS*(BuyGoal-InitialPrice-cpt*INCREMENT*Point)/Point;
}
}
if(SellGoalProfit<ProfitTarget)
// - Increment Lots Sell
{
for(cpt=LEVELS;cpt>=1 && SellGoalProfit<ProfitTarget;cpt--)
{
if(Bid>=(InitialPrice-(cpt*INCREMENT-MarketInfo(Symbol(),MODE_STOPLEVEL))*Point))
{
ticket=OrderSend(Symbol(),OP_SELLSTOP,cpt*LOTS,InitialPrice-cpt*INCREMENT*Point,2,BuyGoal+spread*Point,SellGoal+spread*Point,DoubleToStr(InitialPrice,MarketInfo(Symbol(),MODE_DIGITS)),MAGIC,0);
}
if(ticket>0) SellGoalProfit+=LOTS*(InitialPrice-cpt*INCREMENT*Point-SellGoal-spread*Point)/Point;
}
}
}
//+------------------------------------------------------------------+
Comment("mGRID EXPERT ADVISOR ver 2.0\n",
"FX Acc Server:",AccountServer(),"\n",
"Date: ",Month(),"-",Day(),"-",Year()," Server Time: ",Hour(),":",Minute(),":",Seconds(),"\n",
"Minimum Lot Sizing: ",MarketInfo(Symbol(),MODE_MINLOT),"\n",
"Account Balance: $",AccountBalance(),"\n",
"Symbol: ", Symbol(),"\n",
"Price: ",NormalizeDouble(Bid,4),"\n",
"Pip Spread: ",MarketInfo("EURUSD",MODE_SPREAD),"\n",
"Increment=" + INCREMENT,"\n",
"Lots: ",LOTS,"\n",
"Levels: " + LEVELS,"\n");
return(0);
}
//+------------------------------------------------------------------+
int CheckProfits(double LOTS, int Goal, bool Current, double InitialPrice)
{
int profit=0, cpt;
if(Current)//return current profit
{
for(cpt=0;cpt<OrdersTotal();cpt++)
{
OrderSelect(cpt, SELECT_BY_POS, MODE_TRADES);
if(OrderSymbol()==Symbol() && StrToDouble(OrderComment())==InitialPrice)
{
if(OrderType()==OP_BUY) profit+=(Bid-OrderOpenPrice())/Point*OrderLots()/LOTS;
if(OrderType()==OP_SELL) profit+=(OrderOpenPrice()-Ask)/Point*OrderLots()/LOTS;
}
}
return(profit);
}
else
{
if(Goal==OP_BUY)
{
for(cpt=0;cpt<OrdersTotal();cpt++)
{
OrderSelect(cpt, SELECT_BY_POS, MODE_TRADES);
if(OrderSymbol()==Symbol() && StrToDouble(OrderComment())==InitialPrice)
{
if(OrderType()==OP_BUY) profit+=(OrderTakeProfit()-OrderOpenPrice())/Point*OrderLots()/LOTS;
if(OrderType()==OP_SELL) profit-=(OrderStopLoss()-OrderOpenPrice())/Point*OrderLots()/LOTS;
if(OrderType()==OP_BUYSTOP) profit+=(OrderTakeProfit()-OrderOpenPrice())/Point*OrderLots()/LOTS;
}
}
return(profit);
}
else
{
for(cpt=0;cpt<OrdersTotal();cpt++)
{
OrderSelect(cpt, SELECT_BY_POS, MODE_TRADES);
if(OrderSymbol()==Symbol() && StrToDouble(OrderComment())==InitialPrice)
{
if(OrderType()==OP_BUY) profit-=(OrderOpenPrice()-OrderStopLoss())/Point*OrderLots()/LOTS;
if(OrderType()==OP_SELL) profit+=(OrderOpenPrice()-OrderTakeProfit())/Point*OrderLots()/LOTS;
if(OrderType()==OP_SELLSTOP) profit+=(OrderOpenPrice()-OrderTakeProfit())/Point*OrderLots()/LOTS;
}
}
return(profit);
}
}
}
bool EndSession()
{
int cpt, total=OrdersTotal();
for(cpt=0;cpt<total;cpt++)
{
Sleep(3000);
OrderSelect(cpt,SELECT_BY_POS,MODE_TRADES);
if(OrderSymbol()==Symbol() && OrderType()>1) OrderDelete(OrderTicket());
else if(OrderSymbol()==Symbol() && OrderType()==OP_BUY) OrderClose(OrderTicket(),OrderLots(),Bid,3);
else if(OrderSymbol()==Symbol() && OrderType()==OP_SELL) OrderClose(OrderTicket(),OrderLots(),Ask,3);
}
if(!CONTINUE) Enter=false;
return(true);
}
double getPipValue(double ord,int dir)
{
double val;
RefreshRates();
if(dir == 1) val=(NormalizeDouble(ord,Digits) - NormalizeDouble(Ask,Digits));
else val=(NormalizeDouble(Bid,Digits) - NormalizeDouble(ord,Digits));
val = val/Point;
return(val);
}
//========== FUNCTION takeProfit
void takeProfit(int current_pips, int ticket)
{
if(OrderSelect(ticket, SELECT_BY_TICKET))
{
if(current_pips >= nextTP && current_pips < (nextTP + Target_Increment))
{
if(OrderType()==1)
{
if(OrderClose(ticket, MAX_LOTS, Ask, 3))
nextTP+=Target_Increment;
else
Print("Error closing order : ",GetLastError());
}
else
{
if(OrderClose(ticket, MAX_LOTS, Bid, 3))
nextTP+=Target_Increment;
else
Print("Error closing order : ",GetLastError());
}
}
}
}
//+------------------------------------------------------------------+
//| Copyright ฉ 2010, Bernd Kreuss |
//| PayPal donations go here -> 7bit@arcor.de |
//+------------------------------------------------------------------+
#property copyright "ฉ Bernd Kreuss, Version 2010.6.11.1"
#property link "http://sites.google.com/site/prof7bit/"
#include <common_functions.mqh>
#include <offline_charts.mqh>
//#include <oanda.mqh>
extern double lots = 0.01; // lots to use per trade
//extern double oanda_factor = 25000;
extern int stop_distance = 20;
extern int auto_tp = 2; // auto-takeprofit this many levels (roughly) above the BE point
extern bool is_ecn_broker = false; // different market order procedure when resuming after pause
extern color clr_breakeven_level = Lime;
extern color clr_buy = Blue;
extern color clr_sell = Red;
extern color clr_gridline = Lime;
extern color clr_stopline_active = Magenta;
extern color clr_stopline_triggered = Aqua;
extern string sound_grid_trail = "";
extern string sound_grid_step = "";
extern string sound_order_triggered = "";
extern string sound_stop_all = "";
string name = "snow";
double pip;
double points_per_pip;
string comment;
int magic;
bool running;
int direction;
double last_line;
int level; // current level, signed, minus=short, calculated in trade()
double realized; // total realized (all time) (calculated in info())
double cycle_total_profit; // total profit since cycle started (calculated in info())
double stop_value; // dollars (account) per single level (calculated in info())
double auto_tp_price; // the price where auto_tp should trigger, calculated during break even calc.
double auto_tp_profit; // rough estimation of auto_tp profit, calculated during break even calc.
#define SP " "
// trading direction
#define BIDIR 0
#define LONG 1
#define SHORT 2
void defaults(){
/*
IS_ECN_BROKER = true;
//auto_tp = 2;
if (IsTesting()){
return(0);
}
if (Symbol6() == "GBPUSD"){
lots = 0.1;
oanda_factor = 900;
stop_distance = 30;
}
if (Symbol6() == "EURUSD"){
lots = 0.1;
oanda_factor = 1800;
stop_distance = 30;
}
if (Symbol6() == "USDCHF"){
lots = 0.1;
oanda_factor = 1800;
stop_distance = 20;
}
if (Symbol6() == "USDJPY"){
lots = 0.1;
oanda_factor = 1800;
stop_distance = 30;
}
sound_grid_step = "expert.wav";
sound_grid_trail = "alert2.wav";
sound_stop_all = "alert.wav";
sound_order_triggered = "alert.wav";
*/
}
int init(){
if (!IsDllsAllowed()){
MessageBox("DLL imports must be allowed!", "Snowball");
return(-1);
}
IS_ECN_BROKER = is_ecn_broker;
CLR_BUY_ARROW = clr_buy;
CLR_SELL_ARROW = clr_sell;
CLR_CROSSLINE_ACTIVE = clr_stopline_active;
CLR_CROSSLINE_TRIGGERED = clr_stopline_triggered;
defaults();
points_per_pip = pointsPerPip();
pip = Point * points_per_pip;
comment = name + "_" + Symbol6();
magic = makeMagicNumber(name + "_" + Symbol());
if (last_line == 0){
last_line = getLine();
}
if (IsTesting()){
setGlobal("realized", 0);
setGlobal("running", 0);
}
readVariables();
if (IsTesting() && !IsVisualMode()){
Print("!!! This is not an automated strategy! Automated backtesting is nonsense! Starting in bidirectional mode!");
running = true;
direction = BIDIR;
placeLine(Bid);
}
info();
}
int deinit(){
deleteStartButtons();
deleteStopButtons();
storeVariables();
if (UninitializeReason() == REASON_PARAMETERS){
Comment("Parameters changed, pending orders deleted, will be replaced with the next tick");
closeOpenOrders(OP_SELLSTOP, magic);
closeOpenOrders(OP_BUYSTOP, magic);
}else{
Comment("EA removed, open orders, trades and status untouched!");
}
}
void onTick(){
recordEquity(name+Symbol6(), PERIOD_H1, magic);
//checkOanda(magic, oanda_factor);
checkLines();
checkButtons();
trade();
info();
checkAutoTP();
if(!IsTesting()){
plotNewOpenTrades(magic);
plotNewClosedTrades(magic);
}
}
void onOpen(){
}
void storeVariables(){
setGlobal("running", running);
setGlobal("direction", direction);
}
void readVariables(){
running = getGlobal("running");
direction = getGlobal("direction");
}
void deleteStartButtons(){
ObjectDelete("start_long");
ObjectDelete("start_short");
ObjectDelete("start_bidir");
}
void deleteStopButtons(){
ObjectDelete("stop");
ObjectDelete("pause");
}
/**
* mark the start (or resume) of the cycle in the chart
*/
void startArrow(){
string aname = "cycle_start_" + TimeToStr(TimeCurrent());
ObjectCreate(aname, OBJ_ARROW, 0, TimeCurrent(), Close[0]);
ObjectSet(aname, OBJPROP_ARROWCODE, 5);
ObjectSet(aname, OBJPROP_COLOR, clr_gridline);
ObjectSet(aname, OBJPROP_BACK, true);
}
/**
* mark the end (or pause) of the cycle in the chart
*/
void endArrow(){
string aname = "cycle_end_" + TimeToStr(Time[0]);
ObjectCreate(aname, OBJ_ARROW, 0, TimeCurrent(), Close[0]);
ObjectSet(aname, OBJPROP_ARROWCODE, 6);
ObjectSet(aname, OBJPROP_COLOR, clr_gridline);
ObjectSet(aname, OBJPROP_BACK, true);
}
void stop(){
endArrow();
deleteStopButtons();
closeOpenOrders(-1, magic);
running = false;
storeVariables();
setGlobal("realized", getProfitRealized(magic)); // store this only on pyramid close
//checkOanda(magic, oanda_factor);
if (sound_stop_all != ""){
PlaySound(sound_stop_all);
}
}
void go(int mode){
startArrow();
deleteStartButtons();
running = true;
direction = mode;
storeVariables();
resume();
}
void pause(){
endArrow();
deleteStopButtons();
label("paused_level", 15, 100, 1, level, Yellow);
closeOpenOrders(-1, magic);
running = false;
storeVariables();
//checkOanda(magic, oanda_factor);
if (sound_stop_all != ""){
PlaySound(sound_stop_all);
}
}
/**
* resume trading after we paused it.
* Find the text label containing the level where we hit pause
* and re-open the corresponding amounts of lots, then delete the label.
*/
void resume(){
int i;
double sl;
double line = getLine();
level = StrToInteger(ObjectDescription("paused_level"));
if (direction == LONG){
level = MathAbs(level);
}
if (direction == SHORT){
level = -MathAbs(level);
}
if (level > 0){
for (i=1; i<=level; i++){
sl = line - pip * i * stop_distance;
buy(lots, sl, 0, magic, comment);
}
}
if (level < 0){
for (i=1; i<=-level; i++){
sl = line + pip * i * stop_distance;
sell(lots, sl, 0, magic, comment);
}
}
ObjectDelete("paused_level");
}
void checkLines(){
if (crossedLine("stop")){
stop();
}
if (crossedLine("pause")){
pause();
}
if (crossedLine("start long")){
go(LONG);
}
if (crossedLine("start short")){
go(SHORT);
}
if (crossedLine("start bidir")){
go(BIDIR);
}
}
void checkButtons(){
if(!running){
deleteStopButtons();
if (labelButton("start_long", 15, 15, 1, "start long", Lime)){
go(LONG);
}
if (labelButton("start_short", 15, 30, 1, "start short", Lime)){
go(SHORT);
}
if (labelButton("start_bidir", 15, 45, 1, "start bidirectional", Lime)){
go(BIDIR);
}
}
if (running){
deleteStartButtons();
if (labelButton("stop", 15, 15, 1, "stop", Red)){
stop();
}
if (labelButton("pause", 15, 30, 1, "pause", Yellow)){
pause();
}
}
}
void checkAutoTP(){
if (auto_tp > 0 && auto_tp_price > 0){
if (level > 0 && Close[0] >= auto_tp_price){
stop();
}
if (level < 0 && Close[0] <= auto_tp_price){
stop();
}
}
}
void placeLine(double price){
horizLine("last_order", price, clr_gridline, SP + "grid position");
last_line = price;
WindowRedraw();
}
double getLine(){
return(ObjectGet("last_order", OBJPROP_PRICE1));
}
bool lineMoved(){
double line = getLine();
if (line != last_line){
// line has been moved by external forces (hello wb ;-)
if (MathAbs(line - last_line) < stop_distance * pip){
// minor adjustment by user
last_line = line;
return(true);
}else{
// something strange (gap? crash? line deleted?)
if (MathAbs(Bid - last_line) < stop_distance * pip){
// last_line variable still near price and thus is valid.
placeLine(last_line); // simply replace line
return(false); // no action needed
}else{
// line is far off or completely missing and last_line doesn't help also
// make a completely new line at Bid
placeLine(Bid);
return(true);
}
}
return(true);
}else{
return(false);
}
}
/**
* manage all the entry order placement
*/
void trade(){
double start;
static int last_level;
if (lineMoved()){
closeOpenOrders(OP_SELLSTOP, magic);
closeOpenOrders(OP_BUYSTOP, magic);
}
start = getLine();
// calculate global variable level here // FIXME: global variable side-effect hell.
level = getNumOpenOrders(OP_BUY, magic) - getNumOpenOrders(OP_SELL, magic);
if (running){
// are we flat?
if (level == 0){
if (direction == SHORT && Ask > start){
if (getNumOpenOrders(OP_SELLSTOP, magic) != 2){
closeOpenOrders(OP_SELLSTOP, magic);
}else{
moveOrders(Ask - start);
}
placeLine(Ask);
start = Ask;
plotBreakEven();
if (sound_grid_trail != ""){
PlaySound(sound_grid_trail);
}
}
if (direction == LONG && Bid < start){
if (getNumOpenOrders(OP_BUYSTOP, magic) != 2){
closeOpenOrders(OP_BUYSTOP, magic);
}else{
moveOrders(Bid - start);
}
placeLine(Bid);
start = Bid;
plotBreakEven();
if (sound_grid_trail != ""){
PlaySound(sound_grid_trail);
}
}
// make sure first long orders are in place
if (direction == BIDIR || direction == LONG){
longOrders(start);
}
// make sure first short orders are in place
if (direction == BIDIR || direction == SHORT){
shortOrders(start);
}
}
// are we already long?
if (level > 0){
// make sure the next long orders are in place
longOrders(start);
}
// are we short?
if (level < 0){
// make sure the next short orders are in place
shortOrders(start);
}
// we have two different models how to move the grid line.
// If we are *not* flat we can snap it to the nearest grid level,
// ths is better for handling situations where the order is triggered
// by the exact pip and price is immediately reversing.
// If we are currently flat we *must* move it only when we have reached
// it *exactly*, because otherwise this would badly interfere with
// the trailing of the grid in the unidirectional modes. Also in
// bidirectional mode this would have some unwanted effects.
if (level != 0){
// snap to grid
if (Ask + (pip * stop_distance / 6) >= start + stop_distance*pip){
jumpGrid(1);
}
// snap to grid
if (Bid - (pip * stop_distance / 6) <= start - stop_distance*pip){
jumpGrid(-1);
}
}else{
// grid reached exactly
if (Ask >= start + stop_distance*pip){
jumpGrid(1);
}
// grid reached exactly
if (Bid <= start - stop_distance*pip){
jumpGrid(-1);
}
}
// alert on level change (order triggered, not line moved)
if (level != last_level){
if (sound_order_triggered != ""){
PlaySound(sound_order_triggered);
}
last_level = level;
}
}else{ // not running
placeLine(Bid);
}
}
/**
* move the line 1 stop_didtance up or down.
* 1 means up, -1 means down.
*/
void jumpGrid(int dir){
placeLine(getLine() + pip * stop_distance * dir);
if (sound_grid_step != ""){
PlaySound(sound_grid_step);
}
}
/**
* do we need to place a new entry order at this price?
* This is done by looking for a stoploss below or above the price
* where=-1 searches for stoploss below, where=1 for stoploss above price
* return false if there is already an order (open or pending)
*/
bool needsOrder(double price, int where){
//return(false);
int i;
int total = OrdersTotal();
int type;
// search for a stoploss at exactly one grid distance away from price
for (i=0; i<total; i++){
OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
type = OrderType();
if (where < 0){ // look only for buy orders (stop below)
if (OrderMagicNumber() == magic && (type == OP_BUY || type == OP_BUYSTOP)){
if (isEqualPrice(OrderStopLoss(), price + where * pip * stop_distance)){
return(false);
}
}
}
if (where > 0){ // look only for sell orders (stop above)
if (OrderMagicNumber() == magic && (type == OP_SELL || type == OP_SELLSTOP)){
if (isEqualPrice(OrderStopLoss(), price + where * pip * stop_distance)){
return(false);
}
}
}
}
return(true);
}
/**
* Make sure there are the next two long orders above start in place.
* If they are already there do nothing, else replace the missing ones.
*/
void longOrders(double start){
double a = start + stop_distance * pip;
double b = start + 2 * stop_distance * pip;
if (needsOrder(a, -1)){
buyStop(lots, a, start, 0, magic, comment);
}
if (needsOrder(b, -1)){
buyStop(lots, b, a, 0, magic, comment);
}
}
/**
* Make sure there are the next two short orders below start in place.
* If they are already there do nothing, else replace the missing ones.
*/
void shortOrders(double start){
double a = start - stop_distance * pip;
double b = start - 2 * stop_distance * pip;
if (needsOrder(a, 1)){
sellStop(lots, a, start, 0, magic, comment);
}
if (needsOrder(b, 1)){
sellStop(lots, b, a, 0, magic, comment);
}
}
/**
* move all entry orders by the amount of d
*/
void moveOrders(double d){
int i;
for(i=0; i<OrdersTotal(); i++){
OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
if (OrderMagicNumber() == magic){
if (MathAbs(OrderOpenPrice() - getLine()) > 3 * stop_distance * pip){
orderDeleteReliable(OrderTicket());
}else{
orderModifyReliable(
OrderTicket(),
OrderOpenPrice() + d,
OrderStopLoss() + d,
0,
0,
CLR_NONE
);
}
}
}
}
void info(){
double floating;
double pb, lp, tp;
static int last_ticket;
static datetime last_be_plot = 0;
int ticket;
string dir;
OrderSelect(OrdersHistoryTotal()-1, SELECT_BY_POS, MODE_HISTORY);
ticket = OrderTicket();
if (ticket != last_ticket){
// history changed, need to recalculate realized profit
realized = getProfitRealized(magic);
last_ticket = ticket;
// enforce a new break-even arrow plot immediately
last_be_plot = 0;
}
floating = getProfit(magic);
// the variable realized is the total realized of all time.
// the MT4-global variable _realized is a snapshot of this value when
// the EA was reset the last time. The difference is what we made
// during the current cycle. Add floating to it and we have the
// profit of the current cycle.
cycle_total_profit = realized - getGlobal("realized") + floating;
if (running == false){
dir = "trading stopped";
}else{
switch(direction){
case LONG:
dir = "trading long";
break;
case SHORT:
dir = "trading short";
break;
default:
dir = "trading both directions";
}
}
int level_abs = MathAbs(getNumOpenOrders(OP_BUY, magic) - getNumOpenOrders(OP_SELL, magic));
stop_value = MarketInfo(Symbol(), MODE_TICKVALUE) * lots * stop_distance * points_per_pip;
Comment("\n" + SP + name + magic + ", " + dir +
"\n" + SP + "1 pip is " + DoubleToStr(pip, Digits) + " " + Symbol6() +
"\n" + SP + "stop distance: " + stop_distance + " pip, lot-size: " + DoubleToStr(lots, 2) +
"\n" + SP + "every stop equals " + DoubleToStr(stop_value, 2) + " " + AccountCurrency() +
"\n" + SP + "realized: " + DoubleToStr(realized - getGlobal("realized"), 2) + " floating: " + DoubleToStr(floating, 2) +
"\n" + SP + "profit: " + DoubleToStr(cycle_total_profit, 2) + " " + AccountCurrency() + " current level: " + level_abs +
"\n" + SP + "auto-tp: " + auto_tp + " levels (" + DoubleToStr(auto_tp_price, Digits) + ", " + DoubleToStr(auto_tp_profit, 2) + " " + AccountCurrency() + ")");
if (last_be_plot == 0 || TimeCurrent() - last_be_plot > 300){ // every 5 minutes
plotBreakEven();
last_be_plot = TimeCurrent();
}
// If you put a text object (not a label!) with the name "profit",
// anywhere on the chart then this can be used as a profit calculator.
// The following code will find the position of this text object
// and calculate your profit, should price reach this position
// and then write this number into the text object. You can
// move it around on the chart to get profit projections for
// any price level you want.
if (ObjectFind("profit") != -1){
pb = getPyramidBase();
lp = ObjectGet("profit", OBJPROP_PRICE1);
if (pb ==0){
if (direction == SHORT){
pb = getLine() - stop_distance * pip;
}
if (direction == LONG){
pb = getLine() + stop_distance * pip;
}
if (direction == BIDIR){
if (lp < getLine()){
pb = getLine() - stop_distance * pip;
}
if (lp >= getLine()){
pb = getLine() + stop_distance * pip;
}
}
}
tp = getTheoreticProfit(MathAbs(lp - pb));
ObjectSetText("profit", "ฏฏฏ " + DoubleToStr(MathRound(realized - getGlobal("realized") + tp), 0) + " " + AccountCurrency() + " profit projection ฏฏฏ");
}
}
/**
* Plot an arrow. Default is the price-exact dash symbol
* This function might be moved into common_functions soon
*/
string arrow(string name="", double price=0, datetime time=0, color clr=Red, int arrow_code=4){
if (time == 0){
time = TimeCurrent();
}
if (name == ""){
name = "arrow_" + time;
}
if (price == 0){
price = Bid;
}
if (ObjectFind(name) < 0){
ObjectCreate(name, OBJ_ARROW, 0, time, price);
}else{
ObjectSet(name, OBJPROP_PRICE1, price);
ObjectSet(name, OBJPROP_TIME1, time);
}
ObjectSet(name, OBJPROP_ARROWCODE, arrow_code);
ObjectSet(name, OBJPROP_SCALE, 1);
ObjectSet(name, OBJPROP_COLOR, clr);
ObjectSet(name, OBJPROP_BACK, true);
return(name);
}
/**
* plot the break even price into the chart
*/
void plotBreakEvenArrow(string arrow_name, double price){
arrow(arrow_name + TimeCurrent(), price, 0, clr_breakeven_level);
}
/**
* plot the break-even Point (only a rough estimate plusminus less than one stop_distance,
* it will be most inaccurate just before hitting a stoploss (last trade negative).
* and this will be more obvious at the beginning of a new cycle when losses are still small
* and break even steps increments are still be big.
*
* Side effects: This function will also calculate auto-tp price and profit.
*
* FIXME: This whole break even calculation sucks comets through drinking straws!
* FIXME: Isn't there a more elegant way to calculate break even?
*/
void plotBreakEven(){
double base = getPyramidBase();
double be = 0;
// loss is roughly the amount of realized stop hits. But I can't use this number
// directly because after resuming a paused pyramid this number is wrong. So
// I have to estimate it with the (always accurate) total profit and the current
// distance from base. In mose cases the outcome of this calculation is equal
// to the realized losses as displayed on the screen, only when resuming a pyramid
// it will differ and have the value it would have if the pyramid never had been paused.
double distance = MathAbs(Close[0] - base);
if ((level > 0 && Close[0] < base) || (level < 0 && Close[0] > base) || level == 0){
distance = 0;
}
double loss = -(cycle_total_profit - getTheoreticProfit(distance));
// this value should always be positive
// or 0 (or slightly below (rounding error)) in case we have a fresh pyramid.
// If it is not positive (no loss yet) then we dont need to plot break even.
if (loss <= 0 || !running){
auto_tp_price = 0;
auto_tp_profit = 0;
return(0);
}
if (direction == LONG){
if (base==0){
base = getLine() + stop_distance * pip;
}
be = base + getBreakEven(loss);
plotBreakEvenArrow("breakeven_long", be);
auto_tp_price = be + pip * stop_distance * auto_tp;
auto_tp_profit = getTheoreticProfit(MathAbs(auto_tp_price - base)) - loss;
}
if (direction == SHORT){
if (base==0){
base = getLine() - stop_distance * pip;
}
be = base - getBreakEven(loss);
plotBreakEvenArrow("breakeven_short", be);
auto_tp_price = be - pip * stop_distance * auto_tp;
auto_tp_profit = getTheoreticProfit(MathAbs(auto_tp_price - base)) - loss;
}
if (direction == BIDIR){
if (base == 0){
base = getLine() + stop_distance * pip;
plotBreakEvenArrow("breakeven_long", base + getBreakEven(loss));
base = getLine() - stop_distance * pip;
plotBreakEvenArrow("breakeven_short", base - getBreakEven(loss));
auto_tp_price = 0;
auto_tp_profit = 0;
}else{
if (getLotsOnTableSigned(magic) > 0){
be = base + getBreakEven(loss);
plotBreakEvenArrow("breakeven_long", be);
auto_tp_price = be + pip * stop_distance * auto_tp;
auto_tp_profit = getTheoreticProfit(MathAbs(auto_tp_price - base)) - loss;
}else{
be = base - getBreakEven(loss);
plotBreakEvenArrow("breakeven_short", be);
auto_tp_price = be - pip * stop_distance * auto_tp;
auto_tp_profit = getTheoreticProfit(MathAbs(auto_tp_price - base)) - loss;
}
}
}
if (auto_tp < 1){
auto_tp_price = 0;
auto_tp_profit = 0;
}
}
/**
* return the entry price of the first order of the pyramid.
* return 0 if we are flat.
*/
double getPyramidBase(){
double d, max_d, sl;
int i;
int type=-1;
// find the stoploss that is farest away from current price
// we cannot just use the order open price because we might
// be in resume mode and then all trades would be opened at
// the same price. the only thing that works reliable is
// looking at the stoplossses
for (i=0; i<OrdersTotal(); i++){
OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
if (OrderMagicNumber() == magic && OrderType() < 2){
d = MathAbs(Close[0] - OrderStopLoss());
if (d > max_d){
max_d = d;
sl = OrderStopLoss();
type = OrderType();
}
}
}
if (type == OP_BUY){
return(sl + pip * stop_distance);
}
if (type == OP_SELL){
return(sl - pip * stop_distance);
}
return(0);
}
double getPyramidBase1(){
int i;
double pmax = -999999;
double base = 0;
for (i=0; i<OrdersTotal(); i++){
OrderSelect(i, SELECT_BY_POS, MODE_TRADES);
if (OrderMagicNumber() == magic && OrderType() < 2){
if (OrderProfit() > pmax){
base = OrderOpenPrice();
pmax = OrderProfit();
}
}
}
return(base);
}
/**
* return the floating profit that would result if
* price would be the specified distance away from
* the base of the pyramid
*/
double getTheoreticProfit(double distance){
int n = MathFloor(distance / (stop_distance * pip));
double remain = distance - n * stop_distance * pip;
int mult = n * (n + 1) / 2;
double profit = MarketInfo(Symbol(), MODE_TICKVALUE) * lots * stop_distance * points_per_pip * mult;
profit = profit + MarketInfo(Symbol(), MODE_TICKVALUE) * lots * (remain/Point) * (n + 1);
return(profit);
}
/**
* return the price move relative to base required to compensate realized losses
* FIXME: This algorithm does not qualify as "elegant", not even remotely.
*/
double getBreakEven(double loss){
double i = 0;
while(true){
if (getTheoreticProfit(pip * i) > loss){
break;
}
i += stop_distance;
}
i -= stop_distance;
while(true){
if (getTheoreticProfit(pip * i) > loss){
break;
}
i += 0.1;
}
return(pip * i);
}
int start(){
static int numbars;
onTick();
if (Bars == numbars){
return(0);
}
numbars = Bars;
onOpen();
return(0);
}
void setGlobal(string key, double value){
GlobalVariableSet(name + magic + "_" + key, value);
}
double getGlobal(string key){
return(GlobalVariableGet(name + magic + "_" + key));
}
ไม่มีความคิดเห็น:
แสดงความคิดเห็น