Files
2026-06-08 10:36:15 +02:00

169 lines
6.0 KiB
Plaintext

//+------------------------------------------------------------------+
//| SpikeTrader.mq4 |
//| Copyright © 2012-2022, EarnForex.com |
//| https://www.earnforex.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2012-2022, EarnForex"
#property link "https://www.earnforex.com/metatrader-expert-advisors/Spike-Trader/"
#property version "1.01"
#property strict
#property description "Trades on spikes that are:"
#property description "1) Higher/lower than N preceding bars;"
#property description "2) Higher/lower than the previous bar by X percent;"
#property description "3) Close in bottom or upper third/half of the bar."
input group "Main"
input int Hold = 11; // Hold: Position holding time in bars.
input int BarsNumber = 3; // BarsNumber: N preceding bars to check.
input double PercentageDifference = 0.003; // PercentageDifference1: X percentage for bar comparison.
input double ThirdOrHalf = 0.5; // ThirdOrHalf: Top/bottom share of a bar to close in.
input group "Money management"
input double Lots = 0.1;
input group "Miscellaneous"
input int Slippage = 30;
input string OrderCommentary = "Spike Trader";
input int Magic = 173923183;
int LastBars = 0;
int Timer = 0;
void OnTick()
{
if ((!IsTradeAllowed()) || (IsTradeContextBusy()) || (!IsConnected()) || ((!MarketInfo(Symbol(), MODE_TRADEALLOWED)) && (!IsTesting()))) return;
//Wait for the new Bar in a chart.
if (LastBars == Bars) return;
else LastBars = Bars;
if (Timer == 1) ClosePrev();
if (Timer > 0) Timer--;
CheckEntry();
}
//+------------------------------------------------------------------+
//| Check for entry conditions and trade if necessary. |
//+------------------------------------------------------------------+
void CheckEntry()
{
// Empty bar.
if (High[1] - Low[1] == 0) return;
if (CheckSellEntry())
{
// If found a BUY order, close it and open a SELL. Otherwise, only reset timer.
if (ClosePrev(OP_SELL)) fSell();
Timer = Hold;
}
else if (CheckBuyEntry())
{
// If found a SELL order, close it and open a BUY. Otherwise, only reset timer.
if (ClosePrev(OP_BUY)) fBuy();
Timer = Hold;
}
}
bool CheckSellEntry()
{
// If the bar isn't higher than at least one of the previous bars - return false.
for (int i = 2; i < BarsNumber + 2; i++)
if (High[1] <= High[i]) return false;
// If not higher than the previous bar by required percentage difference - return false.
if ((High[1] - High[2]) / High[2] < PercentageDifference) return false;
// If closed above the lower third/half - return false.
if ((Close[1] - Low[1]) / (High[1] - Low[1]) > ThirdOrHalf) return false;
// Passed all tests.
return true;
}
bool CheckBuyEntry()
{
// If the bar isn't lower than at least one of the previous bars - return false.
for (int i = 2; i < BarsNumber + 2; i++)
if (Low[1] >= Low[i]) return false;
// If not lower than the previous bar by required percentage difference - return false.
if ((Low[2] - Low[1]) / Low[2] < PercentageDifference) return false;
// If closed below the upper third/half - return false.
if ((High[1] - Close[1]) / (High[1] - Low[1]) > ThirdOrHalf) return false;
// Passed all tests.
return true;
}
//+------------------------------------------------------------------+
//| Close previous position. |
//| order_type - skip positions of this directions. |
//+------------------------------------------------------------------+
bool ClosePrev(int order_type = -1)
{
int total = OrdersTotal();
for (int i = total - 1; i >= 0; i--)
{
if (OrderSelect(i, SELECT_BY_POS) == false) continue;
if ((OrderSymbol() == Symbol()) && (OrderMagicNumber() == Magic))
{
if (OrderType() == OP_BUY)
{
if (order_type == OP_BUY) return false;
RefreshRates();
if (!OrderClose(OrderTicket(), OrderLots(), Bid, Slippage))
{
int e = GetLastError();
Print("OrderClose Error: ", e);
}
return true;
}
else if (OrderType() == OP_SELL)
{
if (order_type == OP_SELL) return false;
RefreshRates();
if (!OrderClose(OrderTicket(), OrderLots(), Ask, Slippage))
{
int e = GetLastError();
Print("OrderClose Error: ", e);
}
return true;
}
}
}
return true;
}
//+------------------------------------------------------------------+
//| Sell |
//+------------------------------------------------------------------+
int fSell()
{
RefreshRates();
int result = OrderSend(Symbol(), OP_SELL, Lots, Bid, Slippage, 0, 0, OrderCommentary, Magic);
if (result == -1)
{
int e = GetLastError();
Print("OrderSend Error: ", e);
}
else return result;
return 0;
}
//+------------------------------------------------------------------+
//| Buy |
//+------------------------------------------------------------------+
int fBuy()
{
RefreshRates();
int result = OrderSend(Symbol(), OP_BUY, Lots, Ask, Slippage, 0, 0, OrderCommentary, Magic);
if (result == -1)
{
int e = GetLastError();
Print("OrderSend Error: ", e);
}
else return result;
return 0;
}
//+------------------------------------------------------------------+