Hi Marci and Forex Friends,
Following (bellow this message) is some code that my friend put together according to my specific suggestions (new code lines are noted by "Added by rc ======"
I am leaving it as an open discussion especially for Marci to decide if it will be added or not to current Flyer! Ea
1. Early exit: the exit is determined once the time frame 5 crosses the time frame 8 and not the 28 (It showed better results at least in my testing).
After watching the visual mode of testing I noticed many times that the original exit strategy of Flyer was missing many opportunities I think this strategy works better.
I noticed Marci you mentioned something about a new EA maybe this is what you had in mind?
2. No Farm News: on days of No Farm News all opened positions are closed.
ALSO two day before no positions are opened until after the news day
the idea is to eliminate opening new positions before the big news day that have a big risk of getting washed out. Testing this at least in the last few months has shown increase in pips. this definitely works with the big NoFarm but if we start eliminating all news periods we wont be left with trading days
3. Settings for stop loss (100) and trailing stop (80) are different. My testing showed better results but please
do your own testing
Bottom Line on my end
Testing on the last 1 month with 90% modeling quality is giving a 1.97 profit factor but then again this is only for one month and only Euro/Dollar
I would be interested in everyone's input. If you want to test these suggested changes you can just copy paste the code to a new ea.
by the way news is a nice vehicle to make money (at least my testing shows potential on the "NoFarm")
check out www.fxengines.com they have a nice automated system that does the job for you.
Good Luck to all,
Reuven
=======================================
suggested code for Flyer added by rc (Reuven)
=======================================
//+------------------------------------------------------------------+
//| FLYER! A Moving Average EA.mq4 |
//| (GirlFlyer) Marci Dunn |
//| email: [email protected] |
//+------------------------------------------------------------------+
// Version 1.04;
/* Please see accompanying documentation now for description and other information. Thanks for using Flyer!
*/
#property copyright "Marci Dunn"
#property link ""
//---- input parameters
// Parameters are set for EUR/USD. Adjust for any other pairs.
extern int barsDistance = 2;
extern bool closeOnlyOnProfit = true;
extern double LotPercentage =10; // Percentage of equity to be used for each position.
extern double MinVal=5000; //Don't Let Equity drop below 5000 (example, can be set to whatever value you want.
extern int StopLossVal = 100; //use ranges of 75-80*-100 for GBP/JPY, 35-40*-50 for USD/CHF, 45-50*-60 for GBP/USD, 40-45*-50 for EUR/USD
// 30-35*-40 for USD/CAD, 35-38*-45 for USD/JPY, 35-40*-45 for AUD/USD, 40-45*-50 for EUR/JPY
//The stoploss value here is key to the success rate of the EA... adjust as needed, but the values given are optimal.
// Values marked by (*)asterisk are the best setting I found in the range given to achieve best profit with least Relative Drawdown %.
extern int TimePeriod = 30; // Key Timeframe to base buy/sell decisions on!! Can be modified, but 30 min seems to be optimal;
extern double PointAdjust = -0.0001; // This factor will help filter price static out on the timeframes for volatile pairs, especially GBP/JPY.
// Use 0.0 for USD/JPY, -0.0001 (negative) for USD/CAD, and 0.0001 USD/CHF, .02 for GBP/JPY, 0.0001 for GBP/USD, and -0.0001 for EUR/USD. Yes, that is a negative!
// -0.01 EUR/JPY (also negative), 0.0 FOR AUD/USD
// Different values will help change entry points/profit levels and drawdowns... but do not adjust in increments larger than .0001 or .01 for JPY pairs.
extern int TrailingStopLevel = 80; //For the trailing stop routine... I recommend using a value slightly larger than the StopLossVal, but try variations.
//For me, 50 was best on EUR/USD.
extern double BrokerMinLotSize = 0.01; //This is the minimum lotsize your broker can accept. If your broker uses 0.1 lots or 1 lot as
// minimum, set it to that value.
extern int FixedLots = 0; //Set to zero (0) if you want the EA to adjust your lot size automatically each trade
//based on the equity in your account. Set to one (1) to trade the same size all the time.
extern double MyLotSize = 1; //If Fixed Lots = 1, Use this size for each lot size. Set to the value you prefer.
extern int LotValue = 0; //If lots are standard value of 1 = 100000, set to zero (0). If mini-account where lots are 10000, set to one (1).
extern int MarginVal = 100; //Set your margin ratio. Default is 100 to 1.
//*** IMPORTANT - DO NOT MODIFY ANY OPEN ORDERS OPENED BY THE EA MANUALLY AS THIS WILL LIKELY TO CAUSE PROBLEMS WITH EXECUTION
//*** Do not modify anything below ****
int OpenOrder; // DO NOT MODIFY!
int OrderFlag = 0; // DO NOT MODIFY!
datetime TimeofCross; // DO NOT MODIFY!
int CrossFlag = 0; // DO NOT MODIFY!
int WaitTime = 150; // Modify at your own risk! Waiting Time (in seconds) for placing orders after signal valid.
// Keeps transient spikes from causing orders.
// Added by rc ==================================================
bool pausedStart = EMPTY_VALUE;
bool pausedStop = EMPTY_VALUE;
// ==============================================================
double ILotVal;
datetime AlertTimer;
//+------------------------------------------------------------------+
//| expert initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
AlertTimer = CurTime();
if(LotValue==0)
{
ILotVal = 100000 / MarginVal;
}
else
if(LotValue==1)
{
ILotVal = 10000 / MarginVal;
}
//----
return(0);
}
//+------------------------------------------------------------------+
//| expert deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
//----
return(0);
}
void CheckToOpenBuy(double LotSize2) // Checks to Open a Buy Position
{
int x,flag,TicketNum;
double EMA18[6];
double EMA28[6];
double WMA5[6];
double WMA8[6];
datetime TimeNow;
int MaxBars = 5;
if(OrderFlag>0)
return;
for(x=0;x<MaxBars+1;x++)
{
EMA18[x]=iMA(NULL,TimePeriod,18,0,MODE_EMA,PRICE_CLOSE,MaxBars-x);
EMA28[x]=iMA(NULL,TimePeriod,28,0,MODE_EMA,PRICE_CLOSE,MaxBars-x);
WMA5[x]=iMA(NULL,TimePeriod,5,0,MODE_LWMA,PRICE_CLOSE,MaxBars-x);
WMA8[x]=iMA(NULL,TimePeriod,8,0,MODE_LWMA,PRICE_CLOSE,MaxBars-x);
}
flag = 0;
if(WMA5[MaxBars]>EMA18[MaxBars]+PointAdjust && WMA5[MaxBars]>EMA28[MaxBars]+PointAdjust && WMA8[MaxBars]>EMA18[MaxBars]+PointAdjust && WMA8[MaxBars]>EMA28[MaxBars]+PointAdjust)
{
for(x=0;x<MaxBars;x++) //Make sure the wma's have crossed the ema's completely within recent time frame so that flat markets don't cause trades..
{
if(WMA5[x]<=EMA18[x] && WMA5[x]<=EMA28[x] && WMA8[x]<=EMA18[x] && WMA8[x]<=EMA28[x])
flag=1; //Yes, they crossed within the last few periods.
}
if(flag==1)
{
if(CrossFlag==0)
{
TimeofCross = CurTime();
CrossFlag = 1;
}
else
{
TimeNow = CurTime();
if(TimeNow-TimeofCross>WaitTime) //waiting period on orders... to prevent transient spikes in price from causing orders.
{
CrossFlag = 0;
if(Ask-(TrailingStopLevel*0.25)*Point<EMA28[MaxBars]) // Final check -- if price has jumped, don't order.
{
TicketNum = OrderSend(Symbol(),OP_BUY,LotSize2,Ask,3,Ask-StopLossVal*Point,0,Symbol(),0,0,Green); //Open the order.
if(TicketNum<0)
{
Print("Error Opening Trade: Error Code = ",GetLastError(),", Lotsize: ",LotSize2);
}
else
{
if(OrderSelect(TicketNum,SELECT_BY_TICKET))
{
Print("Buy Order Opened at Price: ",OrderOpenPrice());
OpenOrder = TicketNum;
OrderFlag = 1;
}
}
}
}
}
}
}
}
void CheckToOpenSell(double LotSize2) //See comments in Open Buy routine for explanations.
{
int x,flag,TicketNum;
double EMA18[6];
double EMA28[6];
double WMA5[6];
double WMA8[6];
datetime TimeNow;
int MaxBars = 5;
if(OrderFlag>0)
return;
for(x=0;x<MaxBars+1;x++)
{
EMA18[x]=iMA(NULL,TimePeriod,18,0,MODE_EMA,PRICE_CLOSE,MaxBars-x);
EMA28[x]=iMA(NULL,TimePeriod,28,0,MODE_EMA,PRICE_CLOSE,MaxBars-x);
WMA5[x]=iMA(NULL,TimePeriod,5,0,MODE_LWMA,PRICE_CLOSE,MaxBars-x);
WMA8[x]=iMA(NULL,TimePeriod,8,0,MODE_LWMA,PRICE_CLOSE,MaxBars-x);
}
flag = 0;
if(WMA5[MaxBars]<EMA18[MaxBars]-PointAdjust && WMA5[MaxBars]<EMA28[MaxBars]-PointAdjust && WMA8[MaxBars]<EMA18[MaxBars]-PointAdjust && WMA8[MaxBars]<EMA28[MaxBars]-PointAdjust)
{
for(x=0;x<MaxBars;x++) //Check to see if the wma's have crossed the ema's recently for an entry point.
{
if(WMA5[x]>=EMA18[x] && WMA5[x]>=EMA28[x] && WMA8[x]>=EMA18[x] && WMA8[x]>=EMA28[x])
flag=1;
}
if(flag==1)
{
if(CrossFlag==0)
{
TimeofCross = CurTime();
CrossFlag = 1;
}
else
{
TimeNow = CurTime();
if(TimeNow-TimeofCross>WaitTime) //Waiting period on orders... to prevent transient spikes in price from causing orders.
{
CrossFlag = 0;
if(Bid+(TrailingStopLevel*0.25)*Point>EMA28[MaxBars]) // Final check -- if price has jumped, don't order.
{
TicketNum = OrderSend(Symbol(),OP_SELL,LotSize2,Bid,3,Bid+StopLossVal*Point,0,Symbol(),0,0,Green); //Open the order.
if(TicketNum<0)
{
Print("Error Opening Trade: Error Code = ",GetLastError(),", Lotsize: ",LotSize2);
}
else
{
if(OrderSelect(TicketNum,SELECT_BY_TICKET))
{
Print("Buy Order Opened at Price: ",OrderOpenPrice());
OpenOrder = TicketNum;
OrderFlag = 2;
}
}
}
}
}
}
}
}
void CheckToOpen() //Procedure to start the process to see if a trade can be opened.
{
double LotSize;
double R1,R2,R3;
double x;
int flag;
if(FixedLots==0)
{
LotSize = (LotPercentage/100) * AccountEquity();
LotSize = LotSize / ILotVal;
R1 = MathCeil(LotSize); // Got to now round the lot size so that error 131 does not occur on some brokers.
R2 = MathFloor(LotSize);
for(x=R2,flag=0;x<=R1 && flag==0;x+=BrokerMinLotSize)
{
if(x>LotSize)
{
LotSize = x-BrokerMinLotSize; // Round lot size to the smaller lot size value.
flag = 1;
}
}
}
else
{
if(FixedLots==1)
LotSize = MyLotSize;
}
if(LotSize>100) //Check to see if lots have exceeded 100... good when account hits high enough equity to max out trade size.
LotSize = 100;
if(!OrderFlag) //If we haven't got an open order, then proceed.
{
if(AccountEquity()>MinVal) //if equity is lower than the amount specified by user, don't trade.
{
if(LotSize*ILotVal<AccountFreeMargin()) //do we have enough margin to open our trade? Should always be true unless errors.
{
CheckToOpenBuy(LotSize);
CheckToOpenSell(LotSize);
}
else
{
Print("Not Enough Free Margin: ",LotSize,", ",AccountFreeMargin());
}
}
else
{
Print("Equity Value Lower than Minimum Account Value Setting");
}
}
}
void CheckToCloseBuy() //Check to close any Long trades.
{
int TicketNum;
datetime TimeOpened,Now;
TicketNum = OpenOrder;
//Check to see if WMA 5 has crossed EMA 28 for exit signal.
//Original if(iMA(NULL,TimePeriod,5,0,MODE_LWMA,PRICE_CLOSE,0)<iMA(NULL,TimePeriod,28,0,MODE_EMA,PRICE_CLOSE,0))
//Added by rc ==========================================
if(iMA(NULL,TimePeriod,5,0,MODE_LWMA,PRICE_CLOSE,0)<iMA(NULL,TimePeriod,8,0,MODE_LWMA,PRICE_CLOSE,0))
// ===================================================
{
if(OrderSelect(TicketNum,SELECT_BY_TICKET))
{
TimeOpened = OrderOpenTime();
Now = CurTime();
if(Now-TimeOpened > TimePeriod*60*barsDistance) //if position was opened within the last 2 periods, don't close.
{
if(Bid>OrderOpenPrice() || !closeOnlyOnProfit) // Important to prevent being whipsawed all over the place, stoploss will close losing positions.
{
if(OrderClose(TicketNum,OrderLots(),Bid,3,Red))
{
Print("Order#",TicketNum," Closed at ",OrderClosePrice());
OrderFlag = 0;
}
}
}
}
else
{
Print("Error Closing Ticket#",TicketNum);
OrderFlag = 0;
}
}
}
void CheckToCloseSell() //Check to close short positions. See CloseBuy procedure for details.
{
int TicketNum;
datetime TimeOpened,Now;
TicketNum = OpenOrder;
//Original if(iMA(NULL,TimePeriod,5,0,MODE_LWMA,PRICE_CLOSE,0)>iMA(NULL,TimePeriod,28,0,MODE_EMA,PRICE_CLOSE,0))
//Following Added by rc ==========================================
if(iMA(NULL,TimePeriod,5,0,MODE_LWMA,PRICE_CLOSE,0)>iMA(NULL,TimePeriod,8,0,MODE_LWMA,PRICE_CLOSE,0))
//==========================================
{
if(OrderSelect(TicketNum,SELECT_BY_TICKET))
{
TimeOpened = OrderOpenTime();
Now = CurTime();
if(Now-TimeOpened > TimePeriod*60*barsDistance)
{
if(Ask<OrderOpenPrice() || !closeOnlyOnProfit) // Important to prevent being whipsawed all over the place, stoploss will close losing positions.
{
if(OrderClose(TicketNum,OrderLots(),Ask,3,Red))
{
Print("Order#",TicketNum," Closed at ",OrderClosePrice());
OrderFlag = 0;
}
}
}
}
else
{
Print("Error Closing Ticket#",TicketNum);
OrderFlag = 0;
}
}
}
void CheckForStops() // This checks to see if the open order was stopped out. Needed to reset the open order flag.
{
datetime X;
if(OrderFlag>0) // Do/Did we have an open order?
{
if(OrderSelect(OpenOrder,SELECT_BY_TICKET))
{
X = OrderCloseTime();
if(X>0) //Is there a close time? if so, order was stopped out.
{
OrderFlag = 0; // reset open order flag. Allows next order to be placed.
Print("Order# ",OpenOrder," StopLoss Close at price: ",OrderClosePrice());
}
}
}
}
void CheckToClose() //Calls the procedures to close positions if necessary.
{
if(OrderFlag==1)
{
CheckToCloseBuy();
}
if(OrderFlag==2)
{
CheckToCloseSell();
}
}
void CheckForModify() // Adjust Stoploss upwards as profit increases.
{
if(OrderFlag==0)
return;
if(OrderFlag==1) //modify long position
{
if(OrderSelect(OpenOrder,SELECT_BY_TICKET))
{
if(OrderStopLoss()<OrderOpenPrice())
{
if(Bid>OrderOpenPrice()+TrailingStopLevel*Point)
{
//modify order for new stop loss. Set a bogus T/P level. Needed for the Ordermodify call.
if(OrderModify(OpenOrder,OrderOpenPrice(),OrderOpenPrice()+10*Point,OrderOpenPrice()+700*Point,0,Yellow)==false)
{
Print("Error Modifying Order! Code: ",GetLastError());
}
}
}
else
{
if(Bid>(OrderStopLoss()-10*Point)+(TrailingStopLevel*Point*2))
{
if(OrderModify(OpenOrder,OrderOpenPrice(),OrderStopLoss()+(TrailingStopLevel)*Point,OrderStopLoss()+700*Point,0,Yellow)==false)
{
Print("Error Modifying Order! Code: ",GetLastError());
}
}
}
}
}
if(OrderFlag==2) // modify short position
{
if(OrderSelect(OpenOrder,SELECT_BY_TICKET))
{
if(OrderStopLoss()>OrderOpenPrice())
{
if(Bid<OrderOpenPrice()-(TrailingStopLevel*Point))
{
//modify order for new stop loss. Set a bogus T/P level. Needed for the Ordermodify call.
if(OrderModify(OpenOrder,OrderOpenPrice(),OrderOpenPrice()-(10*Point),OrderOpenPrice()-700*Point,0,Yellow)==false)
{
Print("Error Modifying Order! Code: ",GetLastError());
}
}
}
else
{
if(Bid<(OrderStopLoss()+10*Point)-(TrailingStopLevel*Point*2))
{
if(OrderModify(OpenOrder,OrderOpenPrice(),OrderStopLoss()-(TrailingStopLevel)*Point,OrderStopLoss()-700*Point,0,Yellow)==false)
{
Print("Error Modifying Order! Code: ",GetLastError());
}
}
}
}
}
}
void CheckForOpenOrders()
{
//This routine becomes necessary in the event of power failures, program interruption, or chart change.
int x,TotalOrders;
TotalOrders = OrdersTotal();
for(x=0;x<TotalOrders;x++)
{
if (OrderSelect(x, SELECT_BY_POS, MODE_TRADES))
{
if(StringFind(OrderComment(),Symbol(),0)>=0)
{
if(OrderType()==OP_BUY)
OrderFlag = 1;
else
OrderFlag = 2;
OpenOrder = OrderTicket();
break;
}
}
}
}
void log(string s) {
int h = FileOpen("Flyer.log", FILE_BIN|FILE_WRITE|FILE_READ);
if (h > 0) {
FileSeek(h, 0, SEEK_END);
string wrap = "";
if (FileSize(h) > 0) wrap = "\n";
FileWriteString(h, wrap + s, StringLen(wrap + s));
FileClose(h);
}
}
void setPause() {
int TWO_DAYS = 2 * 24 * 60 * 60;
datetime time = CurTime() + TWO_DAYS;
int dayOfTheNonth = TimeDay(time);
int dayOfTheWeek = TimeDayOfWeek(time);
if (dayOfTheWeek == 5 && dayOfTheNonth <= 7) {
pausedStart = CurTime();
pausedStop = time;
}
}
// Added by rc =================================================================
bool paused(){
if (pausedStart == EMPTY_VALUE || pausedStop == EMPTY_VALUE) return (false);
return (CurTime() >= pausedStart && CurTime() <= pausedStop);
}
bool isNewsDay(){
if (pausedStart == EMPTY_VALUE || pausedStop == EMPTY_VALUE) return (false);
return (TimeDay(CurTime()) == TimeDay(pausedStop));
}
void closeAll(){
int total = OrdersTotal();
for (int i = 0; i < total; i++) {
if (OrderSelect(i, SELECT_BY_POS) && OrderSymbol() == Symbol()) {
if (OrderType() == OP_BUY) OrderClose(OrderTicket(), OrderLots(), Bid, 3);
if (OrderType() == OP_BUYSTOP) OrderDelete(OrderTicket());
if (OrderType() == OP_SELL) OrderClose(OrderTicket(), OrderLots(), Ask, 3);
if (OrderType() == OP_SELLSTOP) OrderDelete(OrderTicket());
}
}
OrderFlag = 0;
}
//==============================================================================
//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
//----
HideTestIndicators(false);
// Added by rc =================================================================
setPause();
if (isNewsDay()) closeAll();
if (!paused()) {
// =============================================================================
CheckForOpenOrders();
CheckToOpen();
CheckToClose();
CheckForModify();
CheckForStops();
if(CurTime()>=AlertTimer+300)
{
AlertTimer += 300;
Print("Account Equity = ",AccountEquity()," Bid = ",Bid," Ask = ",Ask," OrderStat = ",OrderFlag);
}
if(OrderFlag>0)
Comment("1 Open Order, Equity = ",AccountEquity());
else
Comment("No Open Orders! Waiting for Entry.");
}
//----
return(0);
}
//+------------------------------------------------------------------+