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);
}
}
//+------------------------------------------------------------------+