top of page

Power HOUR Forex EA Specifications

Most of our EAs are created using EA builder, which is third-party software that allows users to develop EAs without writing code. The software is very reasonable, easy to use, and has definitely exceeded my expectations. You can get more information about the software HERE

Also visit the StampsFX YTube page for videos of my building several different EAs.

Strategy:

The EA takes advantage of continued momentum.  During the 17:00th hour GBPUSD,  begins picking up momentum from the New York Session. This EA places a buy or sell based on the previous candle. If the (16th hour) candle is bullish, a buy order is placed. If the 16th hour candle is bearish, a sell order is placed. 

Strategy Tester Results:

From 11/28/2019 to 12/24/2021 the MT4 strategy tester returned a profit of $234.000+. The account started with 10k, and the drawdown was $3,134.54. The EA took 537 Total Trades. The EA Won 175 trades, and Loss 362 Trades. Stop Loss was 5 PIPS, Take Profit was 25 PIPS. Visit the StampsFX YTube channel for details. Past results are not indicative of future results. The strategy test results are nota guarantee of future success. The strategy and EA provided below is not a recommendation to buy or sell a currency pair, currency, or any derivates. 

//CODE

Risk - Warning:

The overall risk is not known. Past results do not indicate future success. This EA is very risky, and the chances of it blowing an account is extremely high, as with any EA. Backtesting and running the EA on a demo account is the safest option. You (as the user) are responsible for any trading losses. Only trade with funds you are prepared to lose. Stampsfx, the creator, nor any affiliated parties are responsible for trading losses.

Live Account Results:

A live account was opened to test this forex EA, however, it is only a test. The live account took the first trade on 12/27/2021 and will run for approximately 2 weeks. The live account test is being utilized with the smallest lot size required. You can see the details on the StampsFX Youtube channel.

Instructions to Save EA:
1. COPY THE CODE ON THIS PAGE.
2. PASTE CODE IN META EDITOR

 

//+------------------------------------------------------------------+
//|                                Strategy: StampsFX Power HOUR.mq4 |
//|                                       Created with EABuilder |
//|                                        
//+------------------------------------------------------------------+
//Copyright "StampsFX"
//Not for resale
#property link      "https://www.StampsFX.com"
#property description ""

#include <stdlib.mqh>
#include <stderror.mqh>

extern double SL_PIPS = 5;
extern double TP_PIPS = 25;
extern double BreakEven_PIPS = 45;
int LotDigits; //initialized in OnInit
int MagicNumber = 1822269;
int NextOpenTradeAfterBars = 3; //next open trade after time
double TradeSize = .01;
int MaxSlippage = 3; //slippage, adjusted in OnInit
datetime NextTime[2]; //initialized to 0, used in function TimeSignal
int MaxOpenTrades = 1;
int MaxLongTrades = 1000;
int MaxShortTrades = 1000;
int MaxPendingOrders = 1000;
int MaxLongPendingOrders = 1000;
int MaxShortPendingOrders = 1000;
bool Hedging = false;
int OrderRetry = 5; //# of retries if sending order returns error
int OrderWait = 5; //# of seconds to wait if sending order returns error
double myPoint; //initialized in OnInit

bool TimeSignal(int i, int hh, int mm, int ss, bool time_repeat, int repeat_interval)

//Property of StampsFX Not for resale
//For Violations please contact StampsFX
  {
   bool ret = false;
   if(!time_repeat)
      repeat_interval = 86400; //24 hours
   datetime ct = TimeCurrent();
   datetime dt = StringToTime(IntegerToString(hh)+":"+IntegerToString(mm))+ss;
   if(ct > dt)
      dt += (datetime)MathCeil((ct - dt) * 1.0 / repeat_interval) * repeat_interval; //move dt to the future
   if(ct == dt)
      dt += repeat_interval;
   if(NextTime[i] == 0)
      NextTime[i] = dt; //set NextTime to the future at first run
   if(ct >= NextTime[i] && NextTime[i] > 0) //reached NextTime
     {
      if(ct - NextTime[i] < 3600) //not too far
         ret = true;
      NextTime[i] = dt; //move NextTime to the future again
     }
   return(ret);
  }

void myAlert(string type, string message)
  {
   if(type == "print")
      Print(message);
   else if(type == "error")
     {
      Print(type+" | StampsFX Power HOUR @ "+Symbol()+","+IntegerToString(Period())+" | "+message);
     }
   else if(type == "order")
     {
     }
   else if(type == "modify")
     {
     }
  }

int TradesCount(int type) //returns # of open trades for order type, current symbol and magic number
  {
   int result = 0;
   int total = OrdersTotal();
   for(int i = 0; i < total; i++)
     {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) continue;
      if(OrderMagicNumber() != MagicNumber || OrderSymbol() != Symbol() || OrderType() != type) continue;
      result++;
     }
   return(result);
  }

datetime LastOpenTradeTime()
  {
   datetime result = 0;
   for(int i = OrdersTotal()-1; i >= 0; i--)
     {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderType() > 1) continue;
      if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
        {
         result = OrderOpenTime();
         break;
        }
     } 
   return(result);
  }

bool SelectLastHistoryTrade()
  {
   int lastOrder = -1;
   int total = OrdersHistoryTotal();
   for(int i = total-1; i >= 0; i--)
     {
      if(!OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) continue;
      if(OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber)
        {
         lastOrder = i;
         break;
        }
     } 
   return(lastOrder >= 0);
  }

datetime LastOpenTime()
  {
   datetime opentime1 = 0, opentime2 = 0;
   if(SelectLastHistoryTrade())
      opentime1 = OrderOpenTime();
   opentime2 = LastOpenTradeTime();
   if (opentime1 > opentime2)
      return opentime1;
   else
      return opentime2;
  }

int myOrderSend(int type, double price, double volume, string ordername) //send order, return ticket ("price" is irrelevant for market orders)
  {
   if(!IsTradeAllowed()) return(-1);
   int ticket = -1;
   int retries = 0;
   int err = 0;
   int long_trades = TradesCount(OP_BUY);
   int short_trades = TradesCount(OP_SELL);
   int long_pending = TradesCount(OP_BUYLIMIT) + TradesCount(OP_BUYSTOP);
   int short_pending = TradesCount(OP_SELLLIMIT) + TradesCount(OP_SELLSTOP);
   string ordername_ = ordername;
   if(ordername != "")
      ordername_ = "("+ordername+")";
   //test Hedging
   if(!Hedging && ((type % 2 == 0 && short_trades + short_pending > 0) || (type % 2 == 1 && long_trades + long_pending > 0)))
     {
      myAlert("print", "Order"+ordername_+" not sent, hedging not allowed");
      return(-1);
     }
   //test maximum trades
   if((type % 2 == 0 && long_trades >= MaxLongTrades)
   || (type % 2 == 1 && short_trades >= MaxShortTrades)
   || (long_trades + short_trades >= MaxOpenTrades)
   || (type > 1 && type % 2 == 0 && long_pending >= MaxLongPendingOrders)
   || (type > 1 && type % 2 == 1 && short_pending >= MaxShortPendingOrders)
   || (type > 1 && long_pending + short_pending >= MaxPendingOrders)
   )
     {
      myAlert("print", "Order"+ordername_+" not sent, maximum reached");
      return(-1);
     }
   //prepare to send order
   while(IsTradeContextBusy()) Sleep(100);
   RefreshRates();
   if(type == OP_BUY)
      price = Ask;
   else if(type == OP_SELL)
      price = Bid;
   else if(price < 0) //invalid price for pending order
     {
      myAlert("order", "Order"+ordername_+" not sent, invalid price for pending order");
     return(-1);
     }
   int clr = (type % 2 == 1) ? clrRed : clrBlue;
   while(ticket < 0 && retries < OrderRetry+1)
     {
      ticket = OrderSend(Symbol(), type, NormalizeDouble(volume, LotDigits), NormalizeDouble(price, Digits()), MaxSlippage, 0, 0, ordername, MagicNumber, 0, clr);
      if(ticket < 0)
        {
         err = GetLastError();
         myAlert("print", "OrderSend"+ordername_+" error #"+IntegerToString(err)+" "+ErrorDescription(err));
         Sleep(OrderWait*1000);
        }
      retries++;
     }
   if(ticket < 0)
     {
      myAlert("error", "OrderSend"+ordername_+" failed "+IntegerToString(OrderRetry+1)+" times; error #"+IntegerToString(err)+" "+ErrorDescription(err));
      return(-1);
     }
   string typestr[6] = {"Buy", "Sell", "Buy Limit", "Sell Limit", "Buy Stop", "Sell Stop"};
   myAlert("order", "Order sent"+ordername_+": "+typestr[type]+" "+Symbol()+" Magic #"+IntegerToString(MagicNumber));
   return(ticket);
  }

int myOrderModify(int ticket, double SL, double TP) //modify SL and TP (absolute price), zero targets do not modify
  {
   if(!IsTradeAllowed()) return(-1);
   bool success = false;
   int retries = 0;
   int err = 0;
   SL = NormalizeDouble(SL, Digits());
   TP = NormalizeDouble(TP, Digits());
   if(SL < 0) SL = 0;
   if(TP < 0) TP = 0;
   //prepare to select order
   while(IsTradeContextBusy()) Sleep(100);
   if(!OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES))
     {
      err = GetLastError();
      myAlert("error", "OrderSelect failed; error #"+IntegerToString(err)+" "+ErrorDescription(err));
      return(-1);
     }
   //prepare to modify order
   while(IsTradeContextBusy()) Sleep(100);
   RefreshRates();
   if(CompareDoubles(SL, 0)) SL = OrderStopLoss(); //not to modify
   if(CompareDoubles(TP, 0)) TP = OrderTakeProfit(); //not to modify
   if(CompareDoubles(SL, OrderStopLoss()) && CompareDoubles(TP, OrderTakeProfit())) return(0); //nothing to do
   while(!success && retries < OrderRetry+1)
     {
      success = OrderModify(ticket, NormalizeDouble(OrderOpenPrice(), Digits()), NormalizeDouble(SL, Digits()), NormalizeDouble(TP, Digits()), OrderExpiration(), CLR_NONE);
      if(!success)
        {
         err = GetLastError();
         myAlert("print", "OrderModify error #"+IntegerToString(err)+" "+ErrorDescription(err));
         Sleep(OrderWait*1000);
        }
      retries++;
     }
   if(!success)
     {
      myAlert("error", "OrderModify failed "+IntegerToString(OrderRetry+1)+" times; error #"+IntegerToString(err)+" "+ErrorDescription(err));
      return(-1);
     }
   string alertstr = "Order modified: ticket="+IntegerToString(ticket);
   if(!CompareDoubles(SL, 0)) alertstr = alertstr+" SL="+DoubleToString(SL);
   if(!CompareDoubles(TP, 0)) alertstr = alertstr+" TP="+DoubleToString(TP);
   myAlert("modify", alertstr);
   return(0);
  }

int myOrderModifyRel(int ticket, double SL, double TP) //modify SL and TP (relative to open price), zero targets do not modify
  {
   if(!IsTradeAllowed()) return(-1);
   bool success = false;
   int retries = 0;
   int err = 0;
   SL = NormalizeDouble(SL, Digits());
   TP = NormalizeDouble(TP, Digits());
   if(SL < 0) SL = 0;
   if(TP < 0) TP = 0;
   //prepare to select order
   while(IsTradeContextBusy()) Sleep(100);
   if(!OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES))
     {
      err = GetLastError();
      myAlert("error", "OrderSelect failed; error #"+IntegerToString(err)+" "+ErrorDescription(err));
      return(-1);
     }
   //prepare to modify order
   while(IsTradeContextBusy()) Sleep(100);
   RefreshRates();
   //convert relative to absolute
   if(OrderType() % 2 == 0) //buy
     {
      if(NormalizeDouble(SL, Digits()) != 0)
         SL = OrderOpenPrice() - SL;
      if(NormalizeDouble(TP, Digits()) != 0)
         TP = OrderOpenPrice() + TP;
     }
   else //sell
     {
      if(NormalizeDouble(SL, Digits()) != 0)
         SL = OrderOpenPrice() + SL;
      if(NormalizeDouble(TP, Digits()) != 0)
         TP = OrderOpenPrice() - TP;
     }
   if(CompareDoubles(SL, 0)) SL = OrderStopLoss(); //not to modify
   if(CompareDoubles(TP, 0)) TP = OrderTakeProfit(); //not to modify
   if(CompareDoubles(SL, OrderStopLoss()) && CompareDoubles(TP, OrderTakeProfit())) return(0); //nothing to do
   while(!success && retries < OrderRetry+1)
     {
      success = OrderModify(ticket, NormalizeDouble(OrderOpenPrice(), Digits()), NormalizeDouble(SL, Digits()), NormalizeDouble(TP, Digits()), OrderExpiration(), CLR_NONE);
      if(!success)
        {
         err = GetLastError();
         myAlert("print", "OrderModify error #"+IntegerToString(err)+" "+ErrorDescription(err));
         Sleep(OrderWait*1000);
        }
      retries++;
     }
   if(!success)
     {
      myAlert("error", "OrderModify failed "+IntegerToString(OrderRetry+1)+" times; error #"+IntegerToString(err)+" "+ErrorDescription(err));
      return(-1);
     }
   string alertstr = "Order modified: ticket="+IntegerToString(ticket);
   if(!CompareDoubles(SL, 0)) alertstr = alertstr+" SL="+DoubleToString(SL);
   if(!CompareDoubles(TP, 0)) alertstr = alertstr+" TP="+DoubleToString(TP);
   myAlert("modify", alertstr);
   return(0);
  }

void TrailingStopBE(int type, double profit, double add) //set Stop Loss to open price if in profit
  {
   int total = OrdersTotal();
   profit = NormalizeDouble(profit, Digits());
   for(int i = total-1; i >= 0; i--)
     {
      while(IsTradeContextBusy()) Sleep(100);
      if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
      if(OrderMagicNumber() != MagicNumber || OrderSymbol() != Symbol() || OrderType() != type) continue;
      RefreshRates();
      if((type == OP_BUY && Bid > OrderOpenPrice() + profit && (NormalizeDouble(OrderStopLoss(), Digits()) <= 0 || OrderOpenPrice() > OrderStopLoss()))
      || (type == OP_SELL && Ask < OrderOpenPrice() - profit && (NormalizeDouble(OrderStopLoss(), Digits()) <= 0 || OrderOpenPrice() < OrderStopLoss())))
         myOrderModify(OrderTicket(), OrderOpenPrice() + add, 0);
     }
  }

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {   
   //initialize myPoint
   myPoint = Point();
   if(Digits() == 5 || Digits() == 3)
     {
      myPoint *= 10;
      MaxSlippage *= 10;
     }
   //initialize LotDigits
   double LotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
   if(NormalizeDouble(LotStep, 3) == round(LotStep))
      LotDigits = 0;
   else if(NormalizeDouble(10*LotStep, 3) == round(10*LotStep))
      LotDigits = 1;
   else if(NormalizeDouble(100*LotStep, 3) == round(100*LotStep))
      LotDigits = 2;
   else LotDigits = 3;
   int i;
   //initialize NextTime
   for (i = 0; i < ArraySize(NextTime); i++)
      NextTime[i] = 0;
   return(INIT_SUCCEEDED);
  }

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   int ticket = -1;
   double price;   
   double SL;
   double TP;
   
   TrailingStopBE(OP_BUY, BreakEven_PIPS * myPoint, 0); //Trailing Stop = go break even
   TrailingStopBE(OP_SELL, BreakEven_PIPS * myPoint, 0); //Trailing Stop = go break even
   
   //Open Buy Order, instant signal is tested first
   if(TimeSignal(0, 17, 00, 03, false, 12 * 3600) //Send order at time
   && Close[1] > Open[1] //Candlestick Close > Candlestick Open
   )
     {
      RefreshRates();
      price = Ask;
      SL = SL_PIPS * myPoint; //Stop Loss = value in points (relative to price)
      TP = TP_PIPS * myPoint; //Take Profit = value in points (relative to price)
      if(TimeCurrent() - LastOpenTime() < NextOpenTradeAfterBars * PeriodSeconds()) return; //next open trade after time after previous trade's open   
      if(IsTradeAllowed())
        {
         ticket = myOrderSend(OP_BUY, price, TradeSize, "");
         if(ticket <= 0) return;
        }
      else //not autotrading => only send alert
         myAlert("order", "");
      myOrderModifyRel(ticket, SL, 0);
      myOrderModifyRel(ticket, 0, TP);
     }
   
   //Open Sell Order, instant signal is tested first
   if(TimeSignal(1, 17, 00, 03, false, 12 * 3600) //Send order at time
   && Close[1] < Open[1] //Candlestick Close < Candlestick Open
   )
     {
      RefreshRates();
      price = Bid;
      SL = SL_PIPS * myPoint; //Stop Loss = value in points (relative to price)
      TP = TP_PIPS * myPoint; //Take Profit = value in points (relative to price)
      if(TimeCurrent() - LastOpenTime() < NextOpenTradeAfterBars * PeriodSeconds()) return; //next open trade after time after previous trade's open   
      if(IsTradeAllowed())
        {
         ticket = myOrderSend(OP_SELL, price, TradeSize, "");
         if(ticket <= 0) return;
        }
      else //not autotrading => only send alert
         myAlert("order", "");
      myOrderModifyRel(ticket, SL, 0);
      myOrderModifyRel(ticket, 0, TP);
     }


  }
//+------------------------------------------------------------------+

bottom of page