Merge pull request #11 from zhutoutoutousan/develop

Develop
This commit is contained in:
zhutoutoutousan
2025-04-22 04:47:41 +08:00
committed by GitHub
28 changed files with 562 additions and 4163 deletions
-426
View File
@@ -1,426 +0,0 @@
//+------------------------------------------------------------------+
//| ScoringTrade.mq5 |
//| Generated by ChatGPT |
//| |
//+------------------------------------------------------------------+
#property strict
#include <Trade\Trade.mqh>
// Input parameters
input int MagicNumber = 42; // Unique identifier for this EA's trades
input int scoreThreshold = 15000; // Minimum score required to enter a trade (increased for BTC's larger price movements)
input int slopeThreshold = 3500; // Minimum EMA slope value to consider trend significant (increased for BTC's steeper trends)
input double maxScore = 25000; // Maximum allowed score before clamping (prevents excessive trade signals)
input int cooldownMinutes = 18; // Minimum time between crossover signals (prevents over-trading)
input int tradeCooldownMinutes = 44; // Minimum time between consecutive trades (trade debounce period)
input ENUM_TIMEFRAMES emaTimeFrame = PERIOD_H1; // Timeframe for EMA calculation (1-hour candles)
input double delayClampAbsolute = 5000; // Score threshold for applying decay (prevents score from growing too large)
input int emaPeriod = 139; // Number of periods for EMA calculation (longer period for smoother trend)
input double crossOverStep = 2500; // Score adjustment when price crosses EMA (increased for BTC's larger moves)
input double slopeThresholdStep = 2000; // Score adjustment for significant slope changes (increased for BTC)
input double emaDistanceStep = 500; // Score adjustment for price distance from EMA (increased for BTC)
input double emaDecayStep = 0; // Score decay rate when no significant signals (0 means no decay)
input double decayMultiplier = 0.08; // Multiplier applied to score when above delayClampAbsolute
input double distanceThreshold = 7100; // Minimum price-EMA distance to trigger score adjustment (increased for BTC)
input double atrMultiplier = 3.9; // Multiplier for dynamic stop loss calculation based on ATR
input double TrailingStop = 10; // Distance in points for trailing stop loss
input bool ApplyTrailingStop = true; // Enable/disable trailing stop functionality
input int maxCrossoverTrades = 14; // Maximum number of trades allowed per crossover signal
input double max_drawdown = 0.1; // Maximum allowed drawdown as percentage of account balance
input bool resetCrossoverTradeOnDistance = false; // Reset trade count when price moves beyond distance threshold
input int resetCrossoverNumber = 0; // Number of trades to reset to when resetCrossoverTradeOnDistance is true
input double minimumLotSize = 0.01; // Minimum trade size allowed
input int maxTimeInPosition = 1; // Maximum time in hours to hold a position
input int tradeLengthThreshold = 31; // Time in minutes before considering a reverse trade
input int reverseTP = 707; // Take profit level for reverse trades (increased for BTC)
input int reverseLotSizeMultiplier = 4; // Multiplier for lot size in reverse trades
input int secondaryPositionHoldTime = 75; // Maximum time in minutes to hold a secondary position
// Global variables
int emaHandle; // EMA handle
double prevScore = 0; // Previous score
double currentScore = 0; // Current score
double emaPrevValue = 0; // Previous EMA value
double emaCurrentValue = 0; // Current EMA value
double emaSlope = 0; // EMA slope value
CTrade trade; // Trading object
datetime lastCrossoverTime = 0; // Time of last crossover
datetime lastTradeTime = 0; // Time of last trade
int crossoverTradeCount = 0; // Count of trades after each crossover
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit() {
// Create EMA handle (e.g., 14-period EMA on the closing price)
emaHandle = iMA(Symbol(), emaTimeFrame, emaPeriod, 0, MODE_EMA, PRICE_CLOSE);
if (emaHandle == INVALID_HANDLE) {
Print("Failed to create EMA handle");
return INIT_FAILED;
}
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
// Release the EMA handle
if (emaHandle != INVALID_HANDLE) {
ExpertRemove();
}
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick() {
// Buffer to hold the EMA values
double emaBuffer[];
// Get dynamic lot size based on current balance and max drawdown
double lotSize = CalculateLotSize();
if(lotSize < minimumLotSize) {
lotSize = minimumLotSize;
}
// Get the current Ask and Bid prices
double Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
double Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
// Copy the last 2 EMA values (current and previous)
int copied = CopyBuffer(emaHandle, 0, 0, 2, emaBuffer);
if (copied < 2) {
return;
}
// Get the current and previous EMA values
emaPrevValue = emaBuffer[1]; // Previous EMA value (index 1)
emaCurrentValue = emaBuffer[0]; // Current EMA value (index 0)
// Calculate the EMA slope (change in EMA values)
emaSlope = - (emaCurrentValue - emaPrevValue) * 100;
Print("EMA Slope: ", emaSlope);
// Check for price action crossover with EMA
double closePrev = iClose(Symbol(), Period(), 1); // Close of previous bar
double closeCurr = iClose(Symbol(), Period(), 0); // Close of current bar
// Check if enough time has passed for the cooldown (cooldownMinutes)
if (TimeCurrent() - lastCrossoverTime >= cooldownMinutes * 60) {
if (closePrev < emaPrevValue && closeCurr > emaCurrentValue) { // Bullish crossover
currentScore += crossOverStep;
crossoverTradeCount = 0; // Reset trade count after new crossover
lastCrossoverTime = TimeCurrent(); // Update the last crossover time
}
else if (closePrev > emaPrevValue && closeCurr < emaCurrentValue) { // Bearish crossover
currentScore -= crossOverStep;
crossoverTradeCount = 0; // Reset trade count after new crossover
lastCrossoverTime = TimeCurrent(); // Update the last crossover time
}
}
// Check EMA slope
if (emaSlope > slopeThreshold) { // Positive slope
currentScore += slopeThresholdStep;
}
else if (emaSlope < -slopeThreshold) { // Negative slope
currentScore -= slopeThresholdStep;
}
else {
if (MathAbs(currentScore) > delayClampAbsolute) {
currentScore *= decayMultiplier;
}
}
if(ApplyTrailingStop) {
ApplyTrailingStop();
}
// Calculate distance to EMA and adjust score
double priceToEmaDistance = closeCurr - emaCurrentValue; // Distance between the current price and the EMA
Print("Price to EMA Distance: ", priceToEmaDistance);
if (MathAbs(priceToEmaDistance) > distanceThreshold) {
if (priceToEmaDistance > 0) { // Bullish (price above EMA)
currentScore += emaDistanceStep;
}
else if (priceToEmaDistance < 0) { // Bearish (price below EMA)
currentScore -= emaDistanceStep;
}
}
else {
if (currentScore > 0) {
currentScore -= emaDecayStep;
}
else {
currentScore += emaDecayStep;
}
}
// Close all positions if score crosses zero
if ((prevScore > 0 && currentScore <= 0) || (prevScore < 0 && currentScore >= 0)) {
Close_Position_MN(MagicNumber);
}
// Update the previous score
prevScore = currentScore;
if (crossoverTradeCount > maxCrossoverTrades) {
return;
}
// Debounce check: Ensure enough time has passed since the last trade
if (TimeCurrent() - lastTradeTime >= tradeCooldownMinutes * 60) {
// Calculate ATR (Average True Range) for stop loss calculation
double atrArray[];
int atrPeriod = 14; // ATR period (can be adjusted)
int copied = CopyBuffer(iATR(Symbol(), Period(), atrPeriod), 0, 0, 1, atrArray);
if (copied < 1) {
return;
}
// Get the current price (using Bid price)
double currentPrice = Bid;
// Get ATR value
double atrValue = atrArray[0]; // Latest ATR value
// Get the minimum stop level and freeze level for the symbol
int stopLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL);
int freezeLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_FREEZE_LEVEL);
// Calculate the minimum stop loss in price units (converted from pips)
double minStopLoss = stopLevel * SymbolInfoDouble(Symbol(), SYMBOL_POINT);
double minFreezeLevel = freezeLevel * SymbolInfoDouble(Symbol(), SYMBOL_POINT);
// Dynamic Stop Loss and Take Profit calculation based on ATR
double dynamicSL = atrValue * atrMultiplier;
double dynamicTP = atrValue * atrMultiplier;
// Adjust SL and TP if they are smaller than the minimum stop level
dynamicSL = MathMax(dynamicSL, minStopLoss);
dynamicTP = MathMax(dynamicTP, dynamicSL); // Ensure TP is at least the same as SL
// Trade logic based on the score
if (currentScore > scoreThreshold) { // Buy signal
if (PositionSelect(Symbol()) == false || !PositionGetInteger(POSITION_MAGIC) == MagicNumber && crossoverTradeCount < maxCrossoverTrades) {
// Open buy position with dynamic SL and TP
trade.SetExpertMagicNumber(MagicNumber);
if (trade.Buy(lotSize, Symbol(), currentPrice, Bid - dynamicSL, 0)) {
crossoverTradeCount++; // Increment trade count
lastTradeTime = TimeCurrent(); // Update the last trade time
}
}
}
else if (currentScore < -scoreThreshold) { // Sell signal
if (PositionSelect(Symbol()) == false || !PositionGetInteger(POSITION_MAGIC) == MagicNumber && crossoverTradeCount < maxCrossoverTrades) {
// Open sell position with dynamic SL and TP
trade.SetExpertMagicNumber(MagicNumber);
if (trade.Sell(lotSize, Symbol(), currentPrice, Ask + dynamicSL, 0)) {
crossoverTradeCount++; // Increment trade count
lastTradeTime = TimeCurrent(); // Update the last trade time
}
}
}
}
// Check existing positions for profit and place reverse trade if needed
CheckPositions();
}
//+------------------------------------------------------------------+
//| Check existing positions for profit and place reverse trade if needed |
//+------------------------------------------------------------------+
void CheckPositions() {
// Check if there are any open positions
if (PositionsTotal() > 0) {
// Check if there are exactly 2 open positions
if (PositionsTotal() == 2) {
for (int i = 0; i < PositionsTotal(); i++) {
ulong ticket = PositionGetTicket(i);
if (PositionSelectByTicket(ticket)) {
datetime openTime = PositionGetInteger(POSITION_TIME);
int tradeLength = TimeCurrent() - openTime; // Trade duration in seconds
// Check if the trade has been open for more than the secondaryPositionHoldTime
if (tradeLength > secondaryPositionHoldTime * 60) { // Convert threshold to seconds
// Close all positions
CloseAllPositions();
return; // Exit the function after closing all positions
}
}
}
} else if (PositionsTotal() < 2) {
for (int i = 0; i < PositionsTotal(); i++) {
ulong ticket = PositionGetTicket(i);
if (PositionSelectByTicket(ticket)) {
double profit = PositionGetDouble(POSITION_PROFIT);
datetime openTime = PositionGetInteger(POSITION_TIME);
int tradeLength = TimeCurrent() - openTime; // Trade duration in seconds
// Check if the trade has been open for more than the tradeLengthThreshold
if (tradeLength > tradeLengthThreshold * 60) { // Convert threshold to seconds
double lotSize = PositionGetDouble(POSITION_VOLUME);
double newLotSize = lotSize * reverseLotSizeMultiplier; // 10 times the original lot size
crossoverTradeCount = maxCrossoverTrades + 1;
// Place a reverse trade
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
trade.SetExpertMagicNumber(MagicNumber);
if (trade.Sell(newLotSize, Symbol(), SymbolInfoDouble(Symbol(), SYMBOL_BID))) {
} else {
Print("Failed to execute reversal sell order");
}
} else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
trade.SetExpertMagicNumber(MagicNumber);
if (trade.Buy(newLotSize, Symbol(), SymbolInfoDouble(Symbol(), SYMBOL_ASK))) {
} else {
Print("Failed to execute reversal buy order");
}
}
}
// Close the trade if profit meets the take profit level
if (profit >= reverseTP) {
Close_Position_MN(MagicNumber);
CloseAllPositions();
}
// Check if there is only one position and its volume is lotSize * reverseLotSizeMultiplier
if (PositionsTotal() == 1 && PositionGetDouble(POSITION_VOLUME) == minimumLotSize * reverseLotSizeMultiplier) {
trade.PositionClose(ticket);
}
// Get the current Ask and Bid prices
double Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
double Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
// Check if the double down trade is exited by stop loss
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && PositionGetDouble(POSITION_SL) > 0 && Bid <= PositionGetDouble(POSITION_SL)) {
// Close the original trade
CloseOriginalTrade();
} else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && PositionGetDouble(POSITION_SL) > 0 && Ask >= PositionGetDouble(POSITION_SL)) {
// Close the original trade
CloseOriginalTrade();
}
}
}
}
}
}
// Function to close the original trade
void CloseOriginalTrade() {
for (int i = PositionsTotal() - 1; i >= 0; i--) {
ulong ticket = PositionGetTicket(i);
if (PositionSelectByTicket(ticket)) {
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
trade.PositionClose(ticket);
} else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
trade.PositionClose(ticket);
}
}
}
}
//+------------------------------------------------------------------+
//| Function to close all positions |
//+------------------------------------------------------------------+
void CloseAllPositions() {
// Loop through all positions and close them
for (int i = PositionsTotal() - 1; i >= 0; i--) {
ulong ticket = PositionGetTicket(i);
if (PositionSelectByTicket(ticket)) {
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
trade.PositionClose(ticket);
}
else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
trade.PositionClose(ticket);
}
}
}
}
void ApplyTrailingStop()
{
for(int i=PositionsTotal()-1; i>=0; i--)
{
string symbol = PositionGetSymbol(i);
ulong PositionTicket = PositionGetTicket(i);
long trade_type = PositionGetInteger(POSITION_TYPE);
if(!PositionGetInteger(POSITION_MAGIC) == MagicNumber) {
return;
}
double POINT = SymbolInfoDouble( symbol, SYMBOL_POINT );
int DIGIT = (int) SymbolInfoInteger( symbol, SYMBOL_DIGITS );
if(trade_type == 0)
{
double Bid = NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_BID),DIGIT);
if(Bid-PositionGetDouble(POSITION_PRICE_OPEN) > NormalizeDouble(POINT * TrailingStop,DIGIT))
{
if(PositionGetDouble(POSITION_SL) < NormalizeDouble(Bid - POINT * TrailingStop,DIGIT))
{
trade.PositionModify(PositionTicket,NormalizeDouble(Bid - POINT * TrailingStop,DIGIT),PositionGetDouble(POSITION_TP));
}
}
}
if(trade_type == 1)
{
double Ask = NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_ASK),DIGIT);
if((PositionGetDouble(POSITION_PRICE_OPEN) - Ask) > NormalizeDouble( POINT * TrailingStop,DIGIT))
{
if((PositionGetDouble(POSITION_SL) > NormalizeDouble(Ask + POINT * TrailingStop,DIGIT)) || (PositionGetDouble(POSITION_SL)==0))
{
trade.PositionModify(PositionTicket,NormalizeDouble(Ask + POINT * TrailingStop,DIGIT),PositionGetDouble(POSITION_TP));
}
}
}
}
}
void Close_Position_MN(ulong magicNumber)
{
int total = PositionsTotal();
for(int i = total - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
// Use PositionSelect by symbol instead of ticket
string symbol = PositionGetSymbol(i);
if(PositionSelect(symbol))
{
if (PositionGetInteger(POSITION_MAGIC) == magicNumber && PositionGetInteger(POSITION_TICKET) == ticket)
{
if(symbol == _Symbol) // Verify the symbol
{
trade.PositionClose(ticket);
}
}
}
}
}
//+------------------------------------------------------------------+
//| Calculate the dynamic lot size based on max drawdown |
//+------------------------------------------------------------------+
double CalculateLotSize()
{
double balance = AccountInfoDouble(ACCOUNT_BALANCE); // Get account balance
double allowedDrawdown = balance * max_drawdown; // Calculate allowed drawdown in account currency
double baseDrawdownPerLot = 150; // Assumed drawdown per 0.01 lots as per backtest
// Calculate lot size based on maximum drawdown
double lotSize = (allowedDrawdown / baseDrawdownPerLot) * 0.01;
return NormalizeDouble(lotSize, 2); // Normalize lot size to 2 decimal places
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 KiB

-456
View File
@@ -1,456 +0,0 @@
//+------------------------------------------------------------------+
//| ScoringTrade.mq5 |
//| Generated by ChatGPT |
//| |
//+------------------------------------------------------------------+
#property strict
#include <Trade\Trade.mqh>
// Input parameters
input int MagicNumber = 42;
input int scoreThreshold = 5200; // Score threshold for trade entry
input int slopeThreshold = 93; // EMA slope threshold
input double maxScore = 7900; // Max score value for clamping
input int cooldownMinutes = 18; // Cooldown period in minutes (37 minutes)
input int tradeCooldownMinutes = 24; // Trade debounce cooldown period (5 minutes)
input ENUM_TIMEFRAMES emaTimeFrame = PERIOD_H1; // EMA Timeframe
input double delayClampAbsolute = 1690;
input int emaPeriod = 64; // EMA period
input double crossOverStep = 950;
input double slopeThresholdStep = 635;
input double emaDistanceStep = 150;
input double emaDecayStep = 0;
input double decayMultiplier = 0.08; // Decay multiplier
input double distanceThreshold = 28.5; // Set your distance threshold (adjust as necessary)
input double atrMultiplier = 7.6; // Multiplier for dynamic SL and TP calculation
input double TrailingStop = 5;
input bool ApplyTrailingStop = true;
input int maxCrossoverTrades = 4; // Maximum number of trades per crossover
input double max_drawdown = 0.1; // Maximum drawdown percentage
input bool resetCrossoverTradeOnDistance = false;
input int resetCrossoverNumber = 0;
input double minimumLotSize = 0.01;
input int maxTimeInPosition = 9;
input int tradeLengthThreshold = 98;
input int reverseTP = 32;
input int reverseLotSizeMultiplier = 15;
input int secondaryPositionHoldTime = 32;
// Global variables
int emaHandle; // EMA handle
double prevScore = 0; // Previous score
double currentScore = 0; // Current score
double emaPrevValue = 0; // Previous EMA value
double emaCurrentValue = 0; // Current EMA value
double emaSlope = 0; // EMA slope value
CTrade trade; // Trading object
datetime lastCrossoverTime = 0; // Time of last crossover
datetime lastTradeTime = 0; // Time of last trade
int crossoverTradeCount = 0; // Count of trades after each crossover
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit() {
// Create EMA handle (e.g., 14-period EMA on the closing price)
emaHandle = iMA(Symbol(), emaTimeFrame, emaPeriod, 0, MODE_EMA, PRICE_CLOSE);
if (emaHandle == INVALID_HANDLE) {
Print("Failed to create EMA handle");
return INIT_FAILED;
}
return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
// Release the EMA handle
if (emaHandle != INVALID_HANDLE) {
ExpertRemove();
}
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick() {
// Buffer to hold the EMA values
double emaBuffer[];
// Get dynamic lot size based on current balance and max drawdown
double lotSize = CalculateLotSize();
if(lotSize < minimumLotSize) {
lotSize = minimumLotSize;
}
// Get the current Ask and Bid prices
double Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
double Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
// Copy the last 2 EMA values (current and previous)
int copied = CopyBuffer(emaHandle, 0, 0, 2, emaBuffer);
if (copied < 2) {
Print("Failed to copy EMA values. Error code: ", GetLastError());
return;
}
// Get the current and previous EMA values
emaPrevValue = emaBuffer[1]; // Previous EMA value (index 1)
emaCurrentValue = emaBuffer[0]; // Current EMA value (index 0)
// Calculate the EMA slope (change in EMA values)
emaSlope = - (emaCurrentValue - emaPrevValue) * 100;
// Check for price action crossover with EMA
double closePrev = iClose(Symbol(), Period(), 1); // Close of previous bar
double closeCurr = iClose(Symbol(), Period(), 0); // Close of current bar
// Check if enough time has passed for the cooldown (cooldownMinutes)
if (TimeCurrent() - lastCrossoverTime >= cooldownMinutes * 60) {
if (closePrev < emaPrevValue && closeCurr > emaCurrentValue) { // Bullish crossover
Print("Bullish crossover");
currentScore += crossOverStep;
crossoverTradeCount = 0; // Reset trade count after new crossover
lastCrossoverTime = TimeCurrent(); // Update the last crossover time
}
else if (closePrev > emaPrevValue && closeCurr < emaCurrentValue) { // Bearish crossover
Print("Bearish crossover");
currentScore -= crossOverStep;
crossoverTradeCount = 0; // Reset trade count after new crossover
lastCrossoverTime = TimeCurrent(); // Update the last crossover time
}
}
// Check EMA slope
if (emaSlope > slopeThreshold) { // Positive slope
currentScore += slopeThresholdStep;
}
else if (emaSlope < -slopeThreshold) { // Negative slope
currentScore -= slopeThresholdStep;
}
else {
if (MathAbs(currentScore) > delayClampAbsolute) {
currentScore *= decayMultiplier;
}
}
if(ApplyTrailingStop) {
ApplyTrailingStop();
}
// Calculate distance to EMA and adjust score
double priceToEmaDistance = closeCurr - emaCurrentValue; // Distance between the current price and the EMA
if (MathAbs(priceToEmaDistance) > distanceThreshold) {
if (priceToEmaDistance > 0) { // Bullish (price above EMA)
currentScore += emaDistanceStep;
Print("Bullish distance score added. Price: ", closeCurr, " EMA: ", emaCurrentValue);
}
else if (priceToEmaDistance < 0) { // Bearish (price below EMA)
currentScore -= emaDistanceStep;
Print("Bearish distance score added. Price: ", closeCurr, " EMA: ", emaCurrentValue);
}
}
else {
if (currentScore > 0) {
currentScore -= emaDecayStep;
}
else {
currentScore += emaDecayStep;
}
}
// Close all positions if score crosses zero
if ((prevScore > 0 && currentScore <= 0) || (prevScore < 0 && currentScore >= 0)) {
Close_Position_MN(MagicNumber);
}
// Update the previous score
prevScore = currentScore;
if (crossoverTradeCount > maxCrossoverTrades) {
return;
}
// Debounce check: Ensure enough time has passed since the last trade
if (TimeCurrent() - lastTradeTime >= tradeCooldownMinutes * 60) {
// Calculate ATR (Average True Range) for stop loss calculation
double atrArray[];
int atrPeriod = 14; // ATR period (can be adjusted)
int copied = CopyBuffer(iATR(Symbol(), Period(), atrPeriod), 0, 0, 1, atrArray);
if (copied < 1) {
Print("Failed to get ATR values. Error code: ", GetLastError());
return;
}
// Get the current price (using Bid price)
double currentPrice = Bid;
// Get ATR value
double atrValue = atrArray[0]; // Latest ATR value
// Get the minimum stop level and freeze level for the symbol
int stopLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL);
int freezeLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_FREEZE_LEVEL);
// Calculate the minimum stop loss in price units (converted from pips)
double minStopLoss = stopLevel * SymbolInfoDouble(Symbol(), SYMBOL_POINT);
double minFreezeLevel = freezeLevel * SymbolInfoDouble(Symbol(), SYMBOL_POINT);
// Dynamic Stop Loss and Take Profit calculation based on ATR
double dynamicSL = atrValue * atrMultiplier;
double dynamicTP = atrValue * atrMultiplier;
// Adjust SL and TP if they are smaller than the minimum stop level
dynamicSL = MathMax(dynamicSL, minStopLoss);
dynamicTP = MathMax(dynamicTP, dynamicSL); // Ensure TP is at least the same as SL
// Trade logic based on the score
if (currentScore > scoreThreshold) { // Buy signal
if (PositionSelect(Symbol()) == false || !PositionGetInteger(POSITION_MAGIC) == MagicNumber && crossoverTradeCount < maxCrossoverTrades) {
Print("maxCrossover");
Print(crossoverTradeCount);
// Open buy position with dynamic SL and TP
trade.SetExpertMagicNumber(MagicNumber);
if (trade.Buy(lotSize, Symbol(), currentPrice, Bid - dynamicSL, 0)) {
Print("Buy order executed with score: ", currentScore);
crossoverTradeCount++; // Increment trade count
lastTradeTime = TimeCurrent(); // Update the last trade time
}
}
}
else if (currentScore < -scoreThreshold) { // Sell signal
if (PositionSelect(Symbol()) == false || !PositionGetInteger(POSITION_MAGIC) == MagicNumber && crossoverTradeCount < maxCrossoverTrades) {
Print("maxCrossover");
Print(crossoverTradeCount);
// Open sell position with dynamic SL and TP
trade.SetExpertMagicNumber(MagicNumber);
if (trade.Sell(lotSize, Symbol(), currentPrice, Ask + dynamicSL, 0)) {
Print("Sell order executed with score: ", currentScore);
crossoverTradeCount++; // Increment trade count
lastTradeTime = TimeCurrent(); // Update the last trade time
}
}
}
} else {
Print("Trade skipped due to debounce: ", currentScore);
}
// Check existing positions for profit and place reverse trade if needed
CheckPositions();
}
//+------------------------------------------------------------------+
//| Check existing positions for profit and place reverse trade if needed |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Check existing positions for duration and place reverse trade if needed |
//+------------------------------------------------------------------+
void CheckPositions() {
// Check if there are any open positions
if (PositionsTotal() > 0) {
// Check if there are exactly 2 open positions
if (PositionsTotal() == 2) {
for (int i = 0; i < PositionsTotal(); i++) {
ulong ticket = PositionGetTicket(i);
if (PositionSelectByTicket(ticket)) {
datetime openTime = PositionGetInteger(POSITION_TIME);
int tradeLength = TimeCurrent() - openTime; // Trade duration in seconds
// Check if the trade has been open for more than the secondaryPositionHoldTime
if (tradeLength > secondaryPositionHoldTime * 60) { // Convert threshold to seconds
// Close all positions
CloseAllPositions();
Print("All positions closed due to exceeding secondaryPositionHoldTime");
return; // Exit the function after closing all positions
}
}
}
} else if (PositionsTotal() < 2) {
for (int i = 0; i < PositionsTotal(); i++) {
ulong ticket = PositionGetTicket(i);
if (PositionSelectByTicket(ticket)) {
double profit = PositionGetDouble(POSITION_PROFIT);
datetime openTime = PositionGetInteger(POSITION_TIME);
int tradeLength = TimeCurrent() - openTime; // Trade duration in seconds
// Check if the trade has been open for more than the tradeLengthThreshold
if (tradeLength > tradeLengthThreshold * 60) { // Convert threshold to seconds
double lotSize = PositionGetDouble(POSITION_VOLUME);
double newLotSize = lotSize * reverseLotSizeMultiplier; // 10 times the original lot size
crossoverTradeCount = maxCrossoverTrades + 1;
// Place a reverse trade
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
trade.SetExpertMagicNumber(MagicNumber);
if (trade.Sell(newLotSize, Symbol(), SymbolInfoDouble(Symbol(), SYMBOL_BID))) {
Print("Reversal sell order executed with increased lot size");
} else {
Print("Failed to execute reversal sell order");
}
} else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
trade.SetExpertMagicNumber(MagicNumber);
if (trade.Buy(newLotSize, Symbol(), SymbolInfoDouble(Symbol(), SYMBOL_ASK))) {
Print("Reversal buy order executed with increased lot size");
} else {
Print("Failed to execute reversal buy order");
}
}
}
// Close the trade if profit meets the take profit level
if (profit >= reverseTP) {
Close_Position_MN(MagicNumber);
CloseAllPositions();
}
// Check if there is only one position and its volume is lotSize * reverseLotSizeMultiplier
if (PositionsTotal() == 1 && PositionGetDouble(POSITION_VOLUME) == minimumLotSize * reverseLotSizeMultiplier) {
trade.PositionClose(ticket);
Print("Single position with volume equal to lotSize * reverseLotSizeMultiplier closed");
}
// Get the current Ask and Bid prices
double Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
double Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
// Check if the double down trade is exited by stop loss
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && PositionGetDouble(POSITION_SL) > 0 && Bid <= PositionGetDouble(POSITION_SL)) {
// Close the original trade
CloseOriginalTrade();
} else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && PositionGetDouble(POSITION_SL) > 0 && Ask >= PositionGetDouble(POSITION_SL)) {
// Close the original trade
CloseOriginalTrade();
}
}
}
}
}
}
// Function to close the original trade
void CloseOriginalTrade() {
for (int i = PositionsTotal() - 1; i >= 0; i--) {
ulong ticket = PositionGetTicket(i);
if (PositionSelectByTicket(ticket)) {
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
trade.PositionClose(ticket);
Print("Original buy position closed due to double down stop loss.");
} else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
trade.PositionClose(ticket);
Print("Original sell position closed due to double down stop loss.");
}
}
}
}
//+------------------------------------------------------------------+
//| Function to close all positions |
//+------------------------------------------------------------------+
void CloseAllPositions() {
// Loop through all positions and close them
for (int i = PositionsTotal() - 1; i >= 0; i--) {
ulong ticket = PositionGetTicket(i);
if (PositionSelectByTicket(ticket)) {
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
trade.PositionClose(ticket);
Print("Buy position closed at score crossover.");
}
else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
trade.PositionClose(ticket);
Print("Sell position closed at score crossover.");
}
}
}
}
void ApplyTrailingStop()
{
for(int i=PositionsTotal()-1; i>=0; i--)
{
string symbol = PositionGetSymbol(i);
ulong PositionTicket = PositionGetTicket(i);
long trade_type = PositionGetInteger(POSITION_TYPE);
if(!PositionGetInteger(POSITION_MAGIC) == MagicNumber) {
return;
}
double POINT = SymbolInfoDouble( symbol, SYMBOL_POINT );
int DIGIT = (int) SymbolInfoInteger( symbol, SYMBOL_DIGITS );
if(trade_type == 0)
{
double Bid = NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_BID),DIGIT);
if(Bid-PositionGetDouble(POSITION_PRICE_OPEN) > NormalizeDouble(POINT * TrailingStop,DIGIT))
{
if(PositionGetDouble(POSITION_SL) < NormalizeDouble(Bid - POINT * TrailingStop,DIGIT))
{
trade.PositionModify(PositionTicket,NormalizeDouble(Bid - POINT * TrailingStop,DIGIT),PositionGetDouble(POSITION_TP));
}
}
}
if(trade_type == 1)
{
double Ask = NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_ASK),DIGIT);
if((PositionGetDouble(POSITION_PRICE_OPEN) - Ask) > NormalizeDouble( POINT * TrailingStop,DIGIT))
{
if((PositionGetDouble(POSITION_SL) > NormalizeDouble(Ask + POINT * TrailingStop,DIGIT)) || (PositionGetDouble(POSITION_SL)==0))
{
trade.PositionModify(PositionTicket,NormalizeDouble(Ask + POINT * TrailingStop,DIGIT),PositionGetDouble(POSITION_TP));
}
}
}
}
}
void Close_Position_MN(ulong magicNumber)
{
int total = PositionsTotal();
for(int i = total - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
// Use PositionSelect by symbol instead of ticket
string symbol = PositionGetSymbol(i);
if(PositionSelect(symbol))
{
if (PositionGetInteger(POSITION_MAGIC) == magicNumber && PositionGetInteger(POSITION_TICKET) == ticket)
{
if(symbol == _Symbol) // Verify the symbol
{
Print("MN " + magicNumber);
trade.PositionClose(ticket);
}
}
}
else
{
int errorCode = GetLastError();
Print("aaaa PositionSelect failed with error code: ", errorCode);
}
}
}
//+------------------------------------------------------------------+
//| Calculate the dynamic lot size based on max drawdown |
//+------------------------------------------------------------------+
double CalculateLotSize()
{
double balance = AccountInfoDouble(ACCOUNT_BALANCE); // Get account balance
double allowedDrawdown = balance * max_drawdown; // Calculate allowed drawdown in account currency
double baseDrawdownPerLot = 150; // Assumed drawdown per 0.01 lots as per backtest
// Calculate lot size based on maximum drawdown
double lotSize = (allowedDrawdown / baseDrawdownPerLot) * 0.01;
return NormalizeDouble(lotSize, 2); // Normalize lot size to 2 decimal places
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 KiB

+191 -654
View File
@@ -1,661 +1,198 @@
# Table of Contents
- [Table of Contents](#table-of-contents)
- [Profitable Expert Advisors Collection](#profitable-expert-advisors-collection)
- [Project Overview](#project-overview)
- [Available Expert Advisors](#available-expert-advisors)
- [1. RSI Divergence Rebound](#1-rsi-divergence-rebound)
- [2. EMA Crossover Skirmish](#2-ema-crossover-skirmish)
- [3. RSI Divergence Extrema AUDUSD](#3-rsi-divergence-extrema-audusd)
- [4. RSI Divergence Extrema EURUSD](#4-rsi-divergence-extrema-eurusd)
- [5. RSI Reversal Asian AUDUSD](#5-rsi-reversal-asian-audusd)
- [6. RSI Reversal Asian EURUSD](#6-rsi-reversal-asian-eurusd)
- [7. EMA Crossover BTC](#7-ema-crossover-btc)
- [8. Smart RSI BTC](#8-smart-rsi-btc)
- [9. RSI MidPoint Hijack](#9-rsi-midpoint-hijack)
- [Technical Details](#technical-details)
- [Requirements](#requirements)
- [Installation](#installation)
- [Profitable Expert Advisors (EAs)](#profitable-expert-advisors-eas)
- [Available EAs](#available-eas)
- [1. RSI Reversal Asian AUD/USD](#1-rsi-reversal-asian-audusd)
- [2. RSI MidPoint Hijack XAU/USD](#2-rsi-midpoint-hijack-xauusd)
- [3. RSI Reversal Asian EUR/USD](#3-rsi-reversal-asian-eurusd)
- [4. RSI CrossOver Reversal XAU/USD](#4-rsi-crossover-reversal-xauusd)
- [Strategy Rationale](#strategy-rationale)
- [RSI Reversal Strategy](#rsi-reversal-strategy)
- [RSI MidPoint Hijack Strategy](#rsi-midpoint-hijack-strategy)
- [Profitability Factors](#profitability-factors)
- [Usage](#usage)
- [Disclaimer](#disclaimer)
# Profitable Expert Advisors Collection
## Project Overview
This repository contains a collection of profitable MetaTrader 5 (MT5) Expert Advisors, each implementing different trading strategies. These EAs have been developed and tested for optimal performance in various market conditions.
## Available Expert Advisors
### 1. RSI Divergence Rebound
A strategy that combines RSI (Relative Strength Index) divergence detection with price action analysis to identify potential reversal points in the market.
**Key Features:**
- RSI divergence patterns detection (bullish and bearish)
- Price rebound confirmation
- Risk management through stop loss and take profit levels
**Strategy Settings:**
- Symbol: XAUUSD
- Period: H1 (2021.01.01 - 2025.01.01)
- RSI Period: 14
- RSI Overbought: 70
- RSI Oversold: 30
- Base Lot Size: 0.01
- ATR Period: 14
- ATR SL Multiplier: 3
- ATR TP Multiplier: 10
- Max Spread: 50
- Divergence Lookback: 9
- Min Trade Interval: 30
- Max Risk Percent: 2%
- Max Drawdown Percent: 10%
- Max Consecutive Losses: 3
- Max Lot Size: 0.1
**Performance Metrics (2021-2025):**
| Metric | Value |
|--------|-------|
| Total Net Profit | $1,344.74 |
| Gross Profit | $4,410.51 |
| Gross Loss | -$3,065.77 |
| Profit Factor | 1.44 |
| Recovery Factor | 4.91 |
| Expected Payoff | $4.87 |
| Sharpe Ratio | 1.69 |
| AHPR | 1.0033 (0.33%) |
| GHPR | 1.0031 (0.31%) |
**Trade Statistics (2021-2025):**
| Statistic | Value |
|-----------|-------|
| Total Trades | 276 |
| Total Deals | 552 |
| Profit Trades | 81 (29.35%) |
| Loss Trades | 195 (70.65%) |
| Short Trades Won | 26.28% |
| Long Trades Won | 32.37% |
| Largest Profit Trade | $144.46 |
| Largest Loss Trade | -$46.66 |
| Average Profit Trade | $54.45 |
| Average Loss Trade | -$15.72 |
| Max Consecutive Wins | 3 ($179.71) |
| Max Consecutive Losses | 15 (-$159.89) |
**Drawdown Analysis (2021-2025):**
| Metric | Value |
|--------|-------|
| Balance Drawdown Absolute | $18.62 |
| Equity Drawdown Absolute | $19.45 |
| Balance Drawdown Maximal | $231.79 (10.21%) |
| Equity Drawdown Maximal | $273.75 (11.93%) |
| Balance Drawdown Relative | 13.47% ($210.14) |
| Equity Drawdown Relative | 15.85% ($250.78) |
**Balance Sheet (2021-2025):**
![RSI Balance Sheet](RSIDivergenceRebound/test-balance.jpg)
### 2. EMA Crossover Skirmish
A strategy that uses Exponential Moving Average (EMA) crossovers with advanced scoring and position management.
**Key Features:**
- EMA crossover detection
- Advanced scoring system
- Trailing stop management
- Position scaling and reversal capabilities
**Strategy Settings:**
- Symbol: XAUUSD
- Period: H1 (2021.01.01 - 2025.04.11)
- Magic Number: 42
- Score Threshold: 5200
- Slope Threshold: 93
- Max Score: 7900.0
- Cooldown Minutes: 18
- Trade Cooldown Minutes: 24
- EMA Time Frame: 16385
- EMA Period: 64
- Cross Over Step: 950.0
- Slope Threshold Step: 635.0
- EMA Distance Step: 150.0
- ATR Multiplier: 7.6
- Trailing Stop: 5.0
- Max Crossover Trades: 4
- Max Drawdown: 10%
- Minimum Lot Size: 0.01
- Max Time in Position: 9 hours
- Trade Length Threshold: 98
- Reverse TP: 32
- Reverse Lot Size Multiplier: 15
- Secondary Position Hold Time: 32
**Performance Metrics (2021-2025):**
| Metric | Value |
|--------|-------|
| Total Net Profit | $388.52 |
| Gross Profit | $391.65 |
| Gross Loss | -$3.13 |
| Profit Factor | 125.13 |
| Recovery Factor | 11.66 |
| Expected Payoff | $0.72 |
| Sharpe Ratio | 41.49 |
| AHPR | 1.0006 (0.06%) |
| GHPR | 1.0006 (0.06%) |
**Trade Statistics (2021-2025):**
| Statistic | Value |
|-----------|-------|
| History Quality | 82% real ticks |
| Total Bars | 25,283 |
| Total Ticks | 165,999,507 |
| Balance Drawdown Absolute | $0.00 |
| Equity Drawdown Absolute | $0.10 |
| Balance Drawdown Maximal | $0.69 (0.05%) |
| Equity Drawdown Maximal | $33.32 (2.56%) |
| Balance Drawdown Relative | 0.05% ($0.69) |
| Equity Drawdown Relative | 2.92% ($30.23) |
**Balance Sheet (2021-2025):**
![EMA Balance Sheet](EMACrossOverSkirmish/test-balance.jpg)
### 3. RSI Divergence Extrema AUDUSD
A strategy that combines RSI divergence with extreme price points detection for enhanced market reversal signals.
**Key Features:**
- RSI divergence patterns detection
- Extreme price points identification
- Dynamic exit based on RSI thresholds
- Advanced risk management
**Strategy Settings:**
- Symbol: AUDUSD
- Period: H1 (2021.01.01 - 2025.04.11)
- RSI Period: 14
- RSI Overbought: 70
- RSI Oversold: 30
- Base Lot Size: 0.01
- Exit Buy RSI Threshold: 60.0
- Exit Sell RSI Threshold: 40.0
- Bar Time Frame: 16385
**Performance Metrics (2021-2025):**
| Metric | Value |
|--------|-------|
| Total Net Profit | $141.61 |
| Gross Profit | $508.54 |
| Gross Loss | -$366.93 |
| Profit Factor | 1.39 |
| Recovery Factor | 3.37 |
| Expected Payoff | $0.59 |
| Sharpe Ratio | 1.72 |
| AHPR | 1.0009 (0.09%) |
| GHPR | 1.0009 (0.09%) |
**Trade Statistics (2021-2025):**
| Statistic | Value |
|-----------|-------|
| History Quality | 82% real ticks |
| Total Bars | 26,604 |
| Total Ticks | 116,467,811 |
| Total Trades | 240 |
| Total Deals | 480 |
| Profit Trades | 158 (65.83%) |
| Loss Trades | 82 (34.17%) |
| Short Trades Won | 70.73% |
| Long Trades Won | 60.68% |
| Largest Profit Trade | $12.35 |
| Largest Loss Trade | -$18.76 |
| Average Profit Trade | $3.22 |
| Average Loss Trade | -$4.47 |
| Max Consecutive Wins | 11 ($35.96) |
| Max Consecutive Losses | 4 (-$26.61) |
**Drawdown Analysis (2021-2025):**
| Metric | Value |
|--------|-------|
| Balance Drawdown Absolute | $6.16 |
| Equity Drawdown Absolute | $14.13 |
| Balance Drawdown Maximal | $34.06 (4.50%) |
| Equity Drawdown Maximal | $42.06 (5.54%) |
| Balance Drawdown Relative | 4.55% ($32.84) |
| Equity Drawdown Relative | 5.54% ($42.06) |
**Balance Sheet (2021-2025):**
![RSI Extrema Balance Sheet](RSIDivergenceExtremaAUDUSD/test-balance.jpg)
### 4. RSI Divergence Extrema EURUSD
A strategy that combines RSI divergence with extreme price points detection for enhanced market reversal signals on EURUSD.
**Key Features:**
- RSI divergence patterns detection
- Extreme price points identification
- Dynamic exit based on RSI thresholds
- Advanced risk management with hedging
- Stuck trade detection and management
**Strategy Settings:**
- Symbol: EURUSD
- Period: H6 (2021.01.01 - 2025.04.11)
- RSI Period: 14
- RSI Overbought: 71
- RSI Oversold: 33
- Base Lot Size: 0.01
- Exit Buy RSI Threshold: 60
- Exit Sell RSI Threshold: 40
- Bar Time Frame: 16390
- Extrema Expiry Bars: 45
- Stuck Trade Bars: 6
- Hedge Lot Multiplier: 6
**Performance Metrics (2021-2025):**
| Metric | Value |
|--------|-------|
| Total Net Profit | $510.13 |
| Gross Profit | $1,033.91 |
| Gross Loss | -$523.78 |
| Profit Factor | 1.97 |
| Recovery Factor | 2.87 |
| Expected Payoff | $4.15 |
| Sharpe Ratio | 2.80 |
| AHPR | 1.0053 (0.53%) |
| GHPR | 1.0050 (0.50%) |
**Trade Statistics (2021-2025):**
| Statistic | Value |
|-----------|-------|
| History Quality | 82% real ticks |
| Total Bars | 4,436 |
| Total Ticks | 107,013,176 |
| Total Trades | 123 |
| Total Deals | 246 |
| Profit Trades | 66 (53.66%) |
| Loss Trades | 57 (46.34%) |
| Short Trades Won | 69.49% |
| Long Trades Won | 39.06% |
| Largest Profit Trade | $76.90 |
| Largest Loss Trade | -$71.89 |
| Average Profit Trade | $15.67 |
| Average Loss Trade | -$9.19 |
| Max Consecutive Wins | 4 ($32.75) |
| Max Consecutive Losses | 3 (-$85.50) |
**Drawdown Analysis (2021-2025):**
| Metric | Value |
|--------|-------|
| Balance Drawdown Absolute | $0.00 |
| Equity Drawdown Absolute | $14.91 |
| Balance Drawdown Maximal | $85.50 (8.28%) |
| Equity Drawdown Maximal | $177.46 (16.45%) |
| Balance Drawdown Relative | 8.28% ($85.50) |
| Equity Drawdown Relative | 16.45% ($177.46) |
**Balance Sheet (2021-2025):**
![RSI Extrema EURUSD Balance Sheet](RSIDivergenceExtremaEURUSD/test-balance.jpg)
### 5. RSI Reversal Asian AUDUSD
A strategy specifically designed for the Asian session on AUDUSD, using RSI reversals with optimized parameters for this market condition.
**Key Features:**
- RSI reversal patterns detection
- Asian session optimization
- Dynamic exit based on RSI thresholds
- Advanced position management
- Session-based trading rules
**Strategy Settings:**
- Symbol: AUDUSD
- Period: M15 (2021.01.01 - 2025.04.03)
- RSI Period: 14
- RSI Overbought: 67
- RSI Oversold: 17
- Take Profit: 253 pips
- Stop Loss: 429 pips
- Max Lot Size: 0.1
- Max Spread: 1000
- Max Duration: 81
- RSI Exit Level: 49
- Use Stop Loss: false
- Use Take Profit: true
- Use RSI Exit: true
**Performance Metrics (2021-2025):**
| Metric | Value |
|--------|-------|
| Total Net Profit | $1,521.11 |
| Gross Profit | $6,147.84 |
| Gross Loss | -$4,626.73 |
| Profit Factor | 1.33 |
| Recovery Factor | 4.30 |
| Expected Payoff | $2.32 |
| Sharpe Ratio | 2.14 |
| AHPR | 1.0022 (0.22%) |
| GHPR | 1.0019 (0.19%) |
**Trade Statistics (2021-2025):**
| Statistic | Value |
|-----------|-------|
| History Quality | 100% |
| Total Bars | 105,824 |
| Total Ticks | 6,215,660 |
| Total Trades | 657 |
| Total Deals | 1,314 |
| Profit Trades | 491 (74.73%) |
| Loss Trades | 166 (25.27%) |
| Short Trades Won | 75.52% |
| Long Trades Won | 61.11% |
| Largest Profit Trade | $24.20 |
| Largest Loss Trade | -$106.60 |
| Average Profit Trade | $12.52 |
| Average Loss Trade | -$27.87 |
| Max Consecutive Wins | 17 ($266.30) |
| Max Consecutive Losses | 4 (-$124.19) |
**Drawdown Analysis (2021-2025):**
| Metric | Value |
|--------|-------|
| Balance Drawdown Absolute | $158.27 |
| Equity Drawdown Absolute | $189.77 |
| Balance Drawdown Maximal | $302.68 (16.43%) |
| Equity Drawdown Maximal | $353.92 (20.63%) |
| Balance Drawdown Relative | 26.38% ($158.27) |
| Equity Drawdown Relative | 31.97% ($192.77) |
**Balance Sheet (2021-2025):**
![RSI Reversal Asian Balance Sheet](RSIReversalAsianAUDUSD/test-balance.jpg)
### 6. RSI Reversal Asian EURUSD
A strategy specifically designed for the Asian session on EURUSD, using RSI reversals with optimized parameters for this market condition.
**Key Features:**
- RSI reversal patterns detection
- Asian session optimization
- Dynamic exit based on RSI thresholds
- Advanced position management
- Session-based trading rules
**Strategy Settings:**
- Symbol: EURUSD
- Period: M15 (2021.01.01 - 2025.04.03)
- RSI Period: 14
- RSI Overbought: 77
- RSI Oversold: 10
- Take Profit: 116 pips
- Stop Loss: 247 pips
- Max Lot Size: 0.1
- Max Spread: 1000
- Max Duration: 67
- RSI Exit Level: 40
- Use Stop Loss: true
- Use Take Profit: false
- Use RSI Exit: true
**Performance Metrics (2021-2025):**
| Metric | Value |
|--------|-------|
| Total Net Profit | $955.26 |
| Gross Profit | $1,961.62 |
| Gross Loss | -$1,006.36 |
| Profit Factor | 1.95 |
| Recovery Factor | 6.70 |
| Expected Payoff | $12.09 |
| Sharpe Ratio | 6.99 |
| AHPR | 1.0132 (1.32%) |
| GHPR | 1.0121 (1.21%) |
**Trade Statistics (2021-2025):**
| Statistic | Value |
|-----------|-------|
| History Quality | 100% |
| Total Bars | 105,824 |
| Total Ticks | 6,218,391 |
| Total Trades | 79 |
| Total Deals | 158 |
| Profit Trades | 40 (50.63%) |
| Loss Trades | 39 (49.37%) |
| Short Trades Won | 50.00% |
| Long Trades Won | 100.00% |
| Largest Profit Trade | $129.78 |
| Largest Loss Trade | -$30.90 |
| Average Profit Trade | $49.04 |
| Average Loss Trade | -$25.80 |
| Max Consecutive Wins | 5 ($223.98) |
| Max Consecutive Losses | 3 (-$79.60) |
**Drawdown Analysis (2021-2025):**
| Metric | Value |
|--------|-------|
| Balance Drawdown Absolute | $0.00 |
| Equity Drawdown Absolute | $2.51 |
| Balance Drawdown Maximal | $113.91 (7.03%) |
| Equity Drawdown Maximal | $142.61 (8.74%) |
| Balance Drawdown Relative | 13.81% ($98.24) |
| Equity Drawdown Relative | 16.97% ($122.14) |
**Balance Sheet (2021-2025):**
![RSI Reversal Asian EURUSD Balance Sheet](RSIReversalAsianEURUSD/test-balance.jpg)
### 7. EMA Crossover BTC
A strategy specifically designed for Bitcoin (BTCUSD) using EMA crossovers with advanced scoring and position management.
**Key Features:**
- EMA crossover detection
- Advanced scoring system
- Trailing stop management
- Position scaling and reversal capabilities
- Dynamic distance thresholds
- Decay multiplier for trend strength
**Strategy Settings:**
- Symbol: BTCUSD
- Period: H1 (2021.01.01 - 2025.04.03)
- Magic Number: 42
- Score Threshold: 15000
- Slope Threshold: 3500
- Max Score: 25000
- Cooldown Minutes: 18
- Trade Cooldown Minutes: 44
- EMA Time Frame: 16385
- Delay Clamp Absolute: 5000
- EMA Period: 139
- Cross Over Step: 2500
- Slope Threshold Step: 2000
- EMA Distance Step: 500
- EMA Decay Step: 0
- Decay Multiplier: 0.08
- Distance Threshold: 7100
- ATR Multiplier: 3.9
- Trailing Stop: 10
- Apply Trailing Stop: true
- Max Crossover Trades: 14
- Max Drawdown: 10%
- Minimum Lot Size: 0.01
- Max Time in Position: 1 hour
- Trade Length Threshold: 31
- Reverse TP: 707
- Reverse Lot Size Multiplier: 4
- Secondary Position Hold Time: 75
**Performance Metrics (2021-2025):**
| Metric | Value |
|--------|-------|
| Total Net Profit | $632.96 |
| Gross Profit | $849.93 |
| Gross Loss | -$216.97 |
| Profit Factor | 3.92 |
| Recovery Factor | 7.47 |
| Expected Payoff | $0.58 |
| Sharpe Ratio | 7.57 |
| AHPR | 1.0007 (0.07%) |
| GHPR | 1.0007 (0.07%) |
**Trade Statistics (2021-2025):**
| Statistic | Value |
|-----------|-------|
| History Quality | 98% |
| Total Bars | 35,791 |
| Total Ticks | 8,380,510 |
| Balance Drawdown Absolute | $0.00 |
| Equity Drawdown Absolute | $2.72 |
| Balance Drawdown Maximal | $41.94 (3.52%) |
| Equity Drawdown Maximal | $84.72 (7.13%) |
| Balance Drawdown Relative | 3.52% ($41.94) |
| Equity Drawdown Relative | 7.13% ($84.72) |
**Balance Sheet (2021-2025):**
![EMA Crossover BTC Balance Sheet](EMACrossOverBTC/test-balance.jpg)
### 8. Smart RSI BTC
A strategy that implements a smart RSI-based trading system specifically optimized for Bitcoin trading.
**Key Features:**
- Advanced RSI-based entry and exit signals
- Dynamic position sizing
- Risk management through stop loss and take profit levels
- Optimized for Bitcoin market conditions
**Strategy Settings:**
- Symbol: BTCUSD
- Period: H1
- RSI Period: 14
- RSI Overbought: 70
- RSI Oversold: 30
- Base Lot Size: 0.01
- Max Spread: 50
- Max Risk Percent: 2%
- Max Drawdown Percent: 10%
- Max Consecutive Losses: 3
- Max Lot Size: 0.1
**Performance Metrics:**
| Metric | Value |
|--------|-------|
| Total Net Profit | $1,344.74 |
| Gross Profit | $4,410.51 |
| Gross Loss | -$3,065.77 |
| Profit Factor | 1.44 |
| Recovery Factor | 4.91 |
| Expected Payoff | $4.87 |
| Sharpe Ratio | 1.69 |
| AHPR | 1.0033 (0.33%) |
| GHPR | 1.0031 (0.31%) |
**Trade Statistics:**
| Statistic | Value |
|-----------|-------|
| Total Trades | 276 |
| Total Deals | 552 |
| Profit Trades | 81 (29.35%) |
| Loss Trades | 195 (70.65%) |
| Short Trades Won | 26.28% |
| Long Trades Won | 32.37% |
| Largest Profit Trade | $144.46 |
| Largest Loss Trade | -$46.66 |
| Average Profit Trade | $54.45 |
| Average Loss Trade | -$15.72 |
| Max Consecutive Wins | 3 ($179.71) |
| Max Consecutive Losses | 15 (-$159.89) |
**Drawdown Analysis:**
| Metric | Value |
|--------|-------|
| Balance Drawdown Absolute | $18.62 |
| Equity Drawdown Absolute | $19.45 |
| Balance Drawdown Maximal | $231.79 (10.21%) |
| Equity Drawdown Maximal | $273.75 (11.93%) |
| Balance Drawdown Relative | 13.47% ($210.14) |
| Equity Drawdown Relative | 15.85% ($250.78) |
**Balance Sheet:**
![Smart RSI BTC Balance Sheet](SmartRSIBTC/test-balance.jpg)
### 9. RSI MidPoint Hijack
A strategy that combines RSI analysis with midpoint-based entry and exit signals for enhanced trading performance.
**Key Features:**
- RSI-based trend analysis
- Midpoint-based entry and exit signals
- Dynamic position sizing
- Advanced risk management
**Strategy Settings:**
- Symbol: XAUUSD
- Period: H1
- RSI Period: 14
- RSI Overbought: 70
- RSI Oversold: 30
- Base Lot Size: 0.01
- Max Spread: 50
- Max Risk Percent: 2%
- Max Drawdown Percent: 10%
- Max Consecutive Losses: 3
- Max Lot Size: 0.1
**Performance Metrics:**
| Metric | Value |
|--------|-------|
| Total Net Profit | $1,344.74 |
| Gross Profit | $4,410.51 |
| Gross Loss | -$3,065.77 |
| Profit Factor | 1.44 |
| Recovery Factor | 4.91 |
| Expected Payoff | $4.87 |
| Sharpe Ratio | 1.69 |
| AHPR | 1.0033 (0.33%) |
| GHPR | 1.0031 (0.31%) |
**Trade Statistics:**
| Statistic | Value |
|-----------|-------|
| Total Trades | 276 |
| Total Deals | 552 |
| Profit Trades | 81 (29.35%) |
| Loss Trades | 195 (70.65%) |
| Short Trades Won | 26.28% |
| Long Trades Won | 32.37% |
| Largest Profit Trade | $144.46 |
| Largest Loss Trade | -$46.66 |
| Average Profit Trade | $54.45 |
| Average Loss Trade | -$15.72 |
| Max Consecutive Wins | 3 ($179.71) |
| Max Consecutive Losses | 15 (-$159.89) |
**Drawdown Analysis:**
| Metric | Value |
|--------|-------|
| Balance Drawdown Absolute | $18.62 |
| Equity Drawdown Absolute | $19.45 |
| Balance Drawdown Maximal | $231.79 (10.21%) |
| Equity Drawdown Maximal | $273.75 (11.93%) |
| Balance Drawdown Relative | 13.47% ($210.14) |
| Equity Drawdown Relative | 15.85% ($250.78) |
**Balance Sheet:**
![RSI MidPoint Hijack Balance Sheet](RSIMidPointHijack/test-balance.jpg)
## Technical Details
Each EA is implemented in MQL5 and includes:
- Custom strategy implementation
- Entry/exit logic
- Risk management parameters
- Position sizing rules
## Requirements
- MetaTrader 5 platform
- MQL5 programming language support
- Sufficient historical data for backtesting
## Installation
1. Copy the desired EA file to your MT5 Experts folder
2. Compile the EA in MetaEditor
3. Attach the EA to a chart with appropriate settings
# Profitable Expert Advisors (EAs)
This repository contains a collection of profitable Expert Advisors (EAs) designed for MetaTrader 5. Each EA implements different trading strategies optimized for specific currency pairs and market conditions.
## Available EAs
### 1. RSI Reversal Asian AUD/USD
- **Strategy**: RSI-based reversal trading during Asian session
- **Key Features**:
- Uses RSI (Relative Strength Index) for entry and exit signals
- Specifically optimized for AUD/USD pair during Asian session (00:00-08:00 UTC)
- Implements strict risk management with configurable stop loss and take profit
- Includes spread monitoring to avoid trading during high spread conditions
- Features a visual panel showing real-time trading metrics
**Core Parameters:**
```mql5
// RSI Settings
RSIPeriod = 28; // RSI period
OverboughtLevel = 64; // Overbought level
OversoldLevel = 13; // Oversold level
// Risk Management
TakeProfitPips = 175; // Take profit in pips
StopLossPips = 5; // Stop loss in pips
MaxLotSize = 0.1; // Maximum lot size
MaxSpread = 1000; // Maximum allowed spread in pips
MaxDuration = 140; // Maximum trade duration in hours
```
**Test Balance Results:**
<div align="center">
<img src="RSIReversalAsianAUDUSD/test-balance.jpg" alt="RSI Reversal Asian AUD/USD Test Balance" width="600"/>
</div>
### 2. RSI MidPoint Hijack XAU/USD
- **Strategy**: Multi-strategy approach combining RSI and EMA crossovers
- **Key Features**:
- Implements three distinct strategies:
1. RSI Follow Strategy
2. RSI Reverse Strategy
3. EMA Cross Strategy
- Optimized for Gold (XAU/USD) trading
- Includes strategy locking mechanism to protect profits
- Features cooldown periods after losses
- Time-based trading windows for each strategy
**Core Parameters:**
```mql5
// RSI Follow Strategy
InpRSIPeriod = 87; // RSI Period
InpRSIOverbought = 72; // RSI Overbought Level
InpRSIOversold = 50; // RSI Oversold Level
// RSI Reverse Strategy
InpRSIReversePeriod = 59; // RSI Period
InpRSIReverseOverbought = 51; // RSI Overbought Level
InpRSIReverseOversold = 49; // RSI Oversold Level
// Strategy Management
InpEnableStrategyLock = false; // Enable Strategy Lock
InpLockProfitThreshold = 0.0; // Lock Profit Threshold (pips)
```
**Test Balance Results:**
<div align="center">
<img src="RSIMidPointHijackXAUUSD/test-balance.jpg" alt="RSI MidPoint Hijack XAU/USD Test Balance" width="600"/>
</div>
### 3. RSI Reversal Asian EUR/USD
- **Strategy**: Similar to AUD/USD version but optimized for EUR/USD
- **Key Features**:
- RSI-based reversal strategy during Asian session
- Customized parameters for EUR/USD pair
- Risk management features
- Session-based trading
**Core Parameters:**
```mql5
// RSI Settings
RSIPeriod = 14; // RSI period
OverboughtLevel = 78; // Overbought level
OversoldLevel = 20; // Oversold level
// Risk Management
TakeProfitPips = 635; // Take profit in pips
StopLossPips = 290; // Stop loss in pips
MaxLotSize = 0.1; // Maximum lot size
MaxDuration = 22; // Maximum trade duration in hours
RSIExitLevel = 57; // RSI level to exit
```
**Test Balance Results:**
<div align="center">
<img src="RSIReversalAsianEURUSD/test-balance.jpg" alt="RSI Reversal Asian EUR/USD Test Balance" width="600"/>
</div>
### 4. RSI CrossOver Reversal XAU/USD
- **Strategy**: RSI crossover strategy for Gold trading
- **Key Features**:
- Uses RSI crossovers for entry and exit signals
- Optimized for Gold market conditions
- Includes multiple timeframe analysis
- Risk management features
**Core Parameters:**
```mql5
// RSI Settings
rsiPeriod = 19; // RSI period
overboughtLevel = 93; // Overbought level
oversoldLevel = 22; // Oversold level
// EMA Settings
emaPeriod = 140; // EMA period
emaSlopeThreshold = 105; // EMA slope threshold
emaDistanceThreshold = 165; // EMA distance threshold
// Risk Management
TrailingStop = 295; // Trailing stop in pips
```
**Test Balance Results:**
<div align="center">
<img src="RSICrossOverReversalXAUUSD/test-balance.jpg" alt="RSI CrossOver Reversal XAU/USD Test Balance" width="600"/>
</div>
## Strategy Rationale
### RSI Reversal Strategy
The RSI Reversal strategy is based on the principle that markets tend to revert to their mean after reaching extreme conditions. The strategy:
- Enters trades when RSI reaches overbought/oversold levels
- Uses Asian session timing to capitalize on specific market conditions
- Implements strict risk management to protect capital
- Takes advantage of mean reversion tendencies in currency pairs
### RSI MidPoint Hijack Strategy
This advanced strategy combines multiple approaches:
- RSI Follow: Capitalizes on strong trends
- RSI Reverse: Takes advantage of market reversals
- EMA Cross: Provides additional confirmation signals
- Strategy locking: Protects profits during favorable conditions
- Cooldown periods: Prevents over-trading after losses
## Profitability Factors
These EAs are designed to be profitable in the long run due to:
1. **Risk Management**
- Strict stop loss implementation
- Take profit targets
- Spread monitoring
- Position sizing control
2. **Market Timing**
- Session-based trading
- Time-specific entry and exit rules
- Avoidance of high volatility periods
3. **Strategy Diversification**
- Multiple entry and exit conditions
- Different timeframes
- Various technical indicators
4. **Adaptive Features**
- Strategy locking during profitable periods
- Cooldown periods after losses
- Spread-based trade filtering
## Usage
Each EA comes with configurable parameters that can be adjusted based on:
- Market conditions
- Risk tolerance
- Trading style
- Account size
Please refer to the individual EA files for specific parameter descriptions and recommended settings.
## Disclaimer
These Expert Advisors are for educational and research purposes only. Past performance does not guarantee future results. Always test thoroughly before using in live trading.
Trading involves substantial risk of loss. These EAs are provided for educational purposes only. Always test thoroughly on a demo account before using with real money. Past performance does not guarantee future results.
+315
View File
@@ -0,0 +1,315 @@
// Input Parameters
#include <Trade\Trade.mqh>
input group "Trade Management"
input int MagicNumber = 7;
input int rsiPeriod = 19; // RSI period
input int overboughtLevel = 93; // Overbought level (RSI > 70 for sell)
input int oversoldLevel = 22; // Oversold level (RSI < 30 for buy)
input double entryRSIBuySpread = 0;
input double entryRSISellSpread = 0;
input double lotSize = 0.01; // Trade lot size
input int slippage = 3; // Slippage for orders
input int cooldownSeconds = 209; // Cooldown period in seconds
input ENUM_TIMEFRAMES TimeFrame1 = PERIOD_M1; // RSI Timeframe
input ENUM_TIMEFRAMES TimeFrame2 = PERIOD_M1; // EMA Timeframe
input ENUM_TIMEFRAMES BarTimeFrame = PERIOD_M12; // EMA Timeframe
input int emaPeriod = 140; // EMA period
input double emaSlopeThreshold = 105; // EMA slope threshold for trend strength
input double exitBuyRSI = 86;
input double exitSellRSI = 10;
input double TrailingStop = 295;
input double emaDistanceThreshold = 165;
input int tradingHourOneBegin = 24;
input int tradingHourOneEnd = 22;
input int tradingHourTwoBegin = 6;
input int tradingHourTwoEnd = 19;
datetime bartime;
// RSI Handle
int rsiHandle;
input bool Sunday =false; // Sunday
input bool Monday =false; // Monday
input bool Tuesday =true; // Tuesday
input bool Wednesday=true; // Wednesday
input bool Thursday =true; // Thursday
input bool Friday =false; // Friday
input bool Saturday =false; // Saturday
bool WeekDays[7];
void WeekDays_Init()
{
WeekDays[0]=Sunday;
WeekDays[1]=Monday;
WeekDays[2]=Tuesday;
WeekDays[3]=Wednesday;
WeekDays[4]=Thursday;
WeekDays[5]=Friday;
WeekDays[6]=Saturday;
}
bool WeekDays_Check(datetime aTime)
{
MqlDateTime stm;
TimeToStruct(aTime,stm);
return(WeekDays[stm.day_of_week]);
}
// EMA Handle
int emaHandle;
double previousRSIDef = 0;
// Create CTrade object for executing trades
CTrade trade;
// Track the last trade time
datetime lastTradeTime = 0;
void OnInit() {
WeekDays_Init();
// Create RSI handle
rsiHandle = iRSI(_Symbol, TimeFrame1, rsiPeriod, PRICE_CLOSE);
if (rsiHandle == INVALID_HANDLE) {
Print("Error creating RSI handle: ", GetLastError());
return;
}
// Create EMA handle
emaHandle = iMA(_Symbol, TimeFrame2, emaPeriod, 0, MODE_EMA, PRICE_CLOSE);
if (emaHandle == INVALID_HANDLE) {
Print("Error creating EMA handle: ", GetLastError());
return;
}
// Initialization successful
Print("RSI and EMA Reversal Strategy Initialized.");
}
void OnTick() {
if(bartime==iTime(_Symbol,BarTimeFrame,0))return;
bartime=iTime(_Symbol,BarTimeFrame,0);
// Check if RSI data is available
double rsi[];
if (CopyBuffer(rsiHandle, 0, 0, 2, rsi) <= 0) {
Print("Error copying RSI data: ", GetLastError());
return;
}
// Check if EMA data is available
double ema[];
if (CopyBuffer(emaHandle, 0, 0, 2, ema) <= 0) {
Print("Error copying EMA data: ", GetLastError());
return;
}
// Get the current time
datetime currentTime = TimeCurrent();
int currentHour = TimeHour(TimeCurrent());
if(!WeekDays_Check(TimeTradeServer())) {
Close_Position_MN(MagicNumber);
return;
}
if (!(currentHour < tradingHourOneEnd && currentHour > tradingHourOneBegin || currentHour < tradingHourTwoEnd && currentHour > tradingHourTwoBegin))
{
Close_Position_MN(MagicNumber);
return; // Prevent further trading during this time
}
// Ensure there is at least one position
bool hasPosition = (PositionsTotal() > 0);
// Get the current and previous RSI values
double currentRSI = rsi[0];
double previousRSI = rsi[1];
if(previousRSIDef == 0) {
previousRSIDef = currentRSI;
return;
}
// Get the current and previous EMA values
double currentEMA = ema[0];
double previousEMA = ema[1];
// Calculate the EMA slope (difference between current and previous EMA values)
double emaSlope = (currentEMA - previousEMA) * 100;
Print(emaSlope);
double closeCurr = iClose(Symbol(), Period(), 0); // Close of current bar
// ** NEW CODE: Calculate distance to EMA and adjust score **
double priceToEmaDistance = (closeCurr - currentEMA) * 10; // Distance between the current price and the EMA
Print("priceToEmaDistance");
Print(priceToEmaDistance);
// Determine if there are existing buy or sell positions
bool isBuyPosition = false;
bool isSellPosition = false;
if (hasPosition) {
if (PositionSelect(_Symbol)) {
int positionType = PositionGetInteger(POSITION_TYPE);
if (positionType == POSITION_TYPE_BUY) {
isBuyPosition = true;
} else if (positionType == POSITION_TYPE_SELL) {
isSellPosition = true;
}
}
}
ApplyTrailingStop();
// Check if the cooldown period has elapsed since the last trade
bool cooldownPassed = (currentTime - lastTradeTime) >= cooldownSeconds;
// Check if EMA slope is above the threshold (indicating strong trend)
bool isTrendStrong = MathAbs(emaSlope) > emaSlopeThreshold || MathAbs(priceToEmaDistance) > emaDistanceThreshold;
// Close trade logic when RSI crosses 50
if (isBuyPosition && currentRSI > exitBuyRSI) {
// Close buy position
Close_Position_MN(MagicNumber);
lastTradeTime = currentTime; // Update last trade time
}
if (isSellPosition && currentRSI < exitSellRSI) {
Close_Position_MN(MagicNumber);
lastTradeTime = currentTime; // Update last trade time
}
// If the EMA slope is strong, do not place new trades
if (isTrendStrong) {
Close_Position_MN(MagicNumber);
lastTradeTime = currentTime; // Update last trade time
Print("Strong trend detected (EMA slope), skipping new trade.");
return;
}
// SELL logic (RSI crosses over the overbought level)
if (currentRSI < overboughtLevel - entryRSISellSpread && previousRSIDef >= overboughtLevel && !isSellPosition && !hasPosition && cooldownPassed) {
trade.SetExpertMagicNumber(MagicNumber);
if (trade.Sell(lotSize, _Symbol, 0, 0, "Sell Order")) {
Print("Sell order placed.");
lastTradeTime = currentTime; // Update last trade time
} else {
Print("Error placing sell order: ", GetLastError());
}
}
// BUY logic (RSI crosses below the oversold level)
if (currentRSI > oversoldLevel + entryRSIBuySpread && previousRSIDef <= oversoldLevel && !isBuyPosition && !hasPosition && cooldownPassed) {
trade.SetExpertMagicNumber(MagicNumber);
if (trade.Buy(lotSize, _Symbol, 0, 0, "Buy Order")) {
Print("Buy order placed.");
lastTradeTime = currentTime; // Update last trade time
} else {
Print("Error placing buy order: ", GetLastError());
}
}
previousRSIDef = currentRSI;
}
void OnDeinit(const int reason) {
// Release RSI and EMA handles on deinitialization
if (rsiHandle != INVALID_HANDLE) {
IndicatorRelease(rsiHandle);
Print("RSI handle released.");
}
if (emaHandle != INVALID_HANDLE) {
IndicatorRelease(emaHandle);
Print("EMA handle released.");
}
}
void Close_Position_MN(ulong magicNumber)
{
int total = PositionsTotal();
for(int i = total - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
// Use PositionSelect by symbol instead of ticket
string symbol = PositionGetSymbol(i);
if(PositionSelect(symbol))
{
if (PositionGetInteger(POSITION_MAGIC) == magicNumber && PositionGetInteger(POSITION_TICKET) == ticket)
{
if(symbol == _Symbol) // Verify the symbol
{
Print("MN " + magicNumber);
trade.PositionClose(ticket);
}
}
}
else
{
int errorCode = GetLastError();
Print("aaaa PositionSelect failed with error code: ", errorCode);
}
}
}
void ApplyTrailingStop()
{
Print("Scanning for trailing stop");
for(int i=PositionsTotal()-1; i>=0; i--)
{
string symbol = PositionGetSymbol(i);
ulong PositionTicket = PositionGetTicket(i);
long trade_type = PositionGetInteger(POSITION_TYPE);
if(!PositionGetInteger(POSITION_MAGIC) == MagicNumber) {
return;
}
double POINT = SymbolInfoDouble( symbol, SYMBOL_POINT );
int DIGIT = (int) SymbolInfoInteger( symbol, SYMBOL_DIGITS );
if(trade_type == 0)
{
double Bid = NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_BID),DIGIT);
if(Bid-PositionGetDouble(POSITION_PRICE_OPEN) > NormalizeDouble(POINT * TrailingStop,DIGIT))
{
if(PositionGetDouble(POSITION_SL) < NormalizeDouble(Bid - POINT * TrailingStop,DIGIT))
{
trade.PositionModify(PositionTicket,NormalizeDouble(Bid - POINT * TrailingStop,DIGIT),PositionGetDouble(POSITION_TP));
}
}
}
if(trade_type == 1)
{
double Ask = NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_ASK),DIGIT);
if((PositionGetDouble(POSITION_PRICE_OPEN) - Ask) > NormalizeDouble( POINT * TrailingStop,DIGIT))
{
if((PositionGetDouble(POSITION_SL) > NormalizeDouble(Ask + POINT * TrailingStop,DIGIT)) || (PositionGetDouble(POSITION_SL)==0))
{
trade.PositionModify(PositionTicket,NormalizeDouble(Ask + POINT * TrailingStop,DIGIT),PositionGetDouble(POSITION_TP));
}
}
}
}
}
int TimeHour(datetime when=0){ if(when == 0) when = TimeCurrent();
return when / 3600 % 24;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 233 KiB

-347
View File
@@ -1,347 +0,0 @@
//+------------------------------------------------------------------+
//| RSIDivergenceRebound.mq5 |
//| Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
#include <Trade\Trade.mqh> // Include CTrade class
// Input Parameters
input int RSI_Period = 14; // RSI Period
input int RSI_Overbought = 70; // RSI Overbought Level
input int RSI_Oversold = 30; // RSI Oversold Level
input double BaseLotSize = 0.01; // Base Lot Size
input ENUM_TIMEFRAMES BarTimeFrame = PERIOD_H1; // Timeframe for bar updates
input double ExitBuyRSIThreshold = 60; // RSI level to exit buy positions
input double ExitSellRSIThreshold = 40; // RSI level to exit sell positions
// Global Variables
int rsiHandle; // RSI indicator handle
CTrade trade; // Trade object
datetime lastBarTime = 0; // Last bar time
double RSILastThree = 0; // Third last RSI value
double RSILastTwo = 0; // Second last RSI value
double RSILast = 0; // Last RSI value
bool hasFirstExtrema = false; // Flag for first extrema
bool hasSecondExtrema = false; // Flag for second extrema
bool hasThirdExtrema = false; // Flag for third extrema
bool isOverboughtExtrema = false; // Flag for extrema type
double priceFirstExtrema = 0; // Price at first extrema
double rsiFirstExtrema = 0; // RSI at first extrema
double priceSecondExtrema = 0; // Price at second extrema
double rsiSecondExtrema = 0; // RSI at second extrema
double priceThirdExtrema = 0; // Price at third extrema
double rsiThirdExtrema = 0; // RSI at third extrema
string extremaPrefix = "Ext_"; // Prefix for extrema objects
datetime firstExtremaTime = 0; // Time of first extrema
datetime secondExtremaTime = 0; // Time of second extrema
datetime thirdExtremaTime = 0; // Time of third extrema
//+------------------------------------------------------------------+
//| Draw extrema point |
//+------------------------------------------------------------------+
void DrawExtremaPoint(string name, datetime time, double price, color clr, int shape, string label)
{
// Create the point
ObjectCreate(0, name, OBJ_ARROW, 0, time, price);
ObjectSetInteger(0, name, OBJPROP_ARROWCODE, shape);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, false);
ObjectSetInteger(0, name, OBJPROP_BACK, true);
// Add label
string labelName = name + "_Label";
ObjectCreate(0, labelName, OBJ_TEXT, 0, time, price);
ObjectSetString(0, labelName, OBJPROP_TEXT, label);
ObjectSetInteger(0, labelName, OBJPROP_COLOR, clr);
ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 8);
ObjectSetInteger(0, labelName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, labelName, OBJPROP_HIDDEN, false);
ObjectSetInteger(0, labelName, OBJPROP_BACK, true);
}
//+------------------------------------------------------------------+
//| Clean up extrema objects |
//+------------------------------------------------------------------+
void CleanupExtremaObjects()
{
for(int i = ObjectsTotal(0, 0, -1) - 1; i >= 0; i--)
{
string name = ObjectName(0, i, 0, -1);
if(StringFind(name, extremaPrefix) == 0)
{
ObjectDelete(0, name);
}
}
}
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Initialize RSI indicator
rsiHandle = iRSI(_Symbol, BarTimeFrame, RSI_Period, PRICE_CLOSE);
if(rsiHandle == INVALID_HANDLE)
{
Print("Error creating RSI indicator");
return(INIT_FAILED);
}
// Initialize trade object
trade.SetExpertMagicNumber(123456);
Print("RSI Divergence Rebound Strategy Initialized");
Print("RSI Period: ", RSI_Period);
Print("Overbought Level: ", RSI_Overbought);
Print("Oversold Level: ", RSI_Oversold);
// Clean up any existing extrema objects
CleanupExtremaObjects();
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Clean up extrema objects
CleanupExtremaObjects();
IndicatorRelease(rsiHandle);
}
//+------------------------------------------------------------------+
//| Check for local extrema in RSI |
//+------------------------------------------------------------------+
bool IsLocalExtrema(double rsi1, double rsi2, double rsi3, bool& isMaxima)
{
if(rsi2 > rsi1 && rsi2 > rsi3)
{
isMaxima = true;
return true;
}
else if(rsi2 < rsi1 && rsi2 < rsi3)
{
isMaxima = false;
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Check for divergence patterns |
//+------------------------------------------------------------------+
bool CheckDivergence(double price1, double rsi1, double price2, double rsi2, bool isOverbought)
{
if(isOverbought)
{
// Bearish divergence (price makes higher high, RSI makes lower high)
if(price2 > price1 && rsi2 < rsi1)
return true;
// Hidden bearish divergence (price makes lower high, RSI makes higher high)
if(price2 < price1 && rsi2 > rsi1)
return true;
}
else
{
// Bullish divergence (price makes lower low, RSI makes higher low)
if(price2 < price1 && rsi2 > rsi1)
return true;
// Hidden bullish divergence (price makes higher low, RSI makes lower low)
if(price2 > price1 && rsi2 < rsi1)
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Check if market is open |
//+------------------------------------------------------------------+
bool IsMarketOpen()
{
MqlDateTime dt;
TimeCurrent(dt);
// Check if it's a weekend
if(dt.day_of_week == 0 || dt.day_of_week == 6)
return false;
// Check if it's within trading hours (assuming 24/5 market)
// You can modify these hours based on your broker's trading hours
int hour = dt.hour;
int minute = dt.min;
// Market is open 24/5 except weekends
return true;
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Check if market is open
if(!IsMarketOpen())
{
Print("Market is closed - resetting extrema");
ResetExtrema();
return;
}
// Check for new bar
datetime currentBarTime = iTime(_Symbol, BarTimeFrame, 0);
if(currentBarTime == lastBarTime)
return;
lastBarTime = currentBarTime;
// Get current RSI value
double rsiBuffer[];
ArraySetAsSeries(rsiBuffer, true);
if(CopyBuffer(rsiHandle, 0, 0, 1, rsiBuffer) != 1)
{
Print("Error copying RSI buffer");
return;
}
// Update RSI queue
RSILastThree = RSILastTwo;
RSILastTwo = RSILast;
RSILast = rsiBuffer[0];
// Check if we have enough RSI values
if(RSILastThree == 0 || RSILastTwo == 0)
return;
// Check for local extrema
bool isMaxima;
if(IsLocalExtrema(RSILastThree, RSILastTwo, RSILast, isMaxima))
{
// First extrema (must be overbought/oversold)
if(!hasFirstExtrema)
{
if((isMaxima && RSILastTwo >= RSI_Overbought) || (!isMaxima && RSILastTwo <= RSI_Oversold))
{
hasFirstExtrema = true;
isOverboughtExtrema = isMaxima;
priceFirstExtrema = iClose(_Symbol, BarTimeFrame, 1);
rsiFirstExtrema = RSILastTwo;
firstExtremaTime = iTime(_Symbol, BarTimeFrame, 1);
// Draw first extrema
string firstExtremaName = extremaPrefix + "First_" + TimeToString(firstExtremaTime);
DrawExtremaPoint(firstExtremaName, firstExtremaTime, priceFirstExtrema,
isMaxima ? clrRed : clrGreen, 234, "1st " + (isMaxima ? "OB" : "OS"));
Print("First extrema detected - Type: ", isMaxima ? "Overbought" : "Oversold",
", RSI: ", rsiFirstExtrema, ", Price: ", priceFirstExtrema);
}
}
// Second extrema (check for divergence)
else if(!hasSecondExtrema)
{
priceSecondExtrema = iClose(_Symbol, BarTimeFrame, 1);
rsiSecondExtrema = RSILastTwo;
secondExtremaTime = iTime(_Symbol, BarTimeFrame, 1);
if(CheckDivergence(priceFirstExtrema, rsiFirstExtrema, priceSecondExtrema, rsiSecondExtrema, isOverboughtExtrema))
{
hasSecondExtrema = true;
// Draw second extrema
string secondExtremaName = extremaPrefix + "Second_" + TimeToString(secondExtremaTime);
DrawExtremaPoint(secondExtremaName, secondExtremaTime, priceSecondExtrema,
clrBlue, 233, "2nd Div");
Print("Second extrema detected - Divergence found",
", RSI: ", rsiSecondExtrema, ", Price: ", priceSecondExtrema);
}
}
// Third extrema (must be between overbought/oversold levels)
else if(!hasThirdExtrema)
{
if(RSILastTwo > RSI_Oversold && RSILastTwo < RSI_Overbought)
{
hasThirdExtrema = true;
priceThirdExtrema = iClose(_Symbol, BarTimeFrame, 1);
rsiThirdExtrema = RSILastTwo;
thirdExtremaTime = iTime(_Symbol, BarTimeFrame, 1);
// Draw third extrema
string thirdExtremaName = extremaPrefix + "Third_" + TimeToString(thirdExtremaTime);
DrawExtremaPoint(thirdExtremaName, thirdExtremaTime, priceThirdExtrema,
clrMagenta, 232, "3rd Entry");
Print("Third extrema detected - Trade signal",
", RSI: ", rsiThirdExtrema, ", Price: ", priceThirdExtrema);
// Enter trade
if(isOverboughtExtrema)
{
if(!trade.Sell(BaseLotSize, _Symbol, 0, 0, 0, "RSI Divergence Sell"))
{
Print("Failed to execute sell order - resetting extrema");
ResetExtrema();
}
}
else
{
if(!trade.Buy(BaseLotSize, _Symbol, 0, 0, 0, "RSI Divergence Buy"))
{
Print("Failed to execute buy order - resetting extrema");
ResetExtrema();
}
}
}
}
}
// Check for exit conditions
if(PositionSelect(_Symbol))
{
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
if(posType == POSITION_TYPE_BUY && RSILast >= ExitBuyRSIThreshold)
{
trade.PositionClose(_Symbol);
ResetExtrema();
}
else if(posType == POSITION_TYPE_SELL && RSILast <= ExitSellRSIThreshold)
{
trade.PositionClose(_Symbol);
ResetExtrema();
}
}
}
//+------------------------------------------------------------------+
//| Reset extrema flags and values |
//+------------------------------------------------------------------+
void ResetExtrema()
{
// Clean up existing objects
CleanupExtremaObjects();
hasFirstExtrema = false;
hasSecondExtrema = false;
hasThirdExtrema = false;
isOverboughtExtrema = false;
priceFirstExtrema = 0;
rsiFirstExtrema = 0;
priceSecondExtrema = 0;
rsiSecondExtrema = 0;
priceThirdExtrema = 0;
rsiThirdExtrema = 0;
firstExtremaTime = 0;
secondExtremaTime = 0;
thirdExtremaTime = 0;
}
//+------------------------------------------------------------------+
Binary file not shown.

Before

Width:  |  Height:  |  Size: 246 KiB

-655
View File
@@ -1,655 +0,0 @@
//+------------------------------------------------------------------+
//| RSIDivergenceRebound.mq5 |
//| Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
#include <Trade\Trade.mqh> // Include CTrade class
// Input Parameters
input int RSI_Period = 14; // RSI Period
input int RSI_Overbought = 71; // RSI Overbought Level
input int RSI_Oversold = 33; // RSI Oversold Level
input double BaseLotSize = 0.01; // Base Lot Size
input ENUM_TIMEFRAMES BarTimeFrame = PERIOD_H6; // Timeframe for bar updates
input double ExitBuyRSIThreshold = 60; // RSI level to exit buy positions
input double ExitSellRSIThreshold = 40; // RSI level to exit sell positions
input int ExtremaExpiryBars = 45; // Number of bars before extrema expire
input int StuckTradeBars = 6; // Number of bars before considering trade stuck
input double HedgeLotMultiplier = 6.0; // Multiplier for hedge position lot size
// Global Variables
int rsiHandle; // RSI indicator handle
CTrade trade; // Trade object
datetime lastBarTime = 0; // Last bar time
double RSILastThree = 0; // Third last RSI value
double RSILastTwo = 0; // Second last RSI value
double RSILast = 0; // Last RSI value
bool hasFirstExtrema = false; // Flag for first extrema
bool hasSecondExtrema = false; // Flag for second extrema
bool hasThirdExtrema = false; // Flag for third extrema
bool isOverboughtExtrema = false; // Flag for extrema type
double priceFirstExtrema = 0; // Price at first extrema
double rsiFirstExtrema = 0; // RSI at first extrema
double priceSecondExtrema = 0; // Price at second extrema
double rsiSecondExtrema = 0; // RSI at second extrema
double priceThirdExtrema = 0; // Price at third extrema
double rsiThirdExtrema = 0; // RSI at third extrema
string extremaPrefix = "Ext_"; // Prefix for extrema objects
datetime firstExtremaTime = 0; // Time of first extrema
datetime secondExtremaTime = 0; // Time of second extrema
datetime thirdExtremaTime = 0; // Time of third extrema
datetime extremaStartTime = 0; // Time when first extrema was detected
datetime positionOpenTime = 0; // Time when position was opened
bool isHedged = false; // Flag for hedge position
//+------------------------------------------------------------------+
//| Draw extrema point |
//+------------------------------------------------------------------+
void DrawExtremaPoint(string name, datetime time, double price, color clr, int shape, string label)
{
// Create the point
ObjectCreate(0, name, OBJ_ARROW, 0, time, price);
ObjectSetInteger(0, name, OBJPROP_ARROWCODE, shape);
ObjectSetInteger(0, name, OBJPROP_COLOR, clr);
ObjectSetInteger(0, name, OBJPROP_WIDTH, 2);
ObjectSetInteger(0, name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, name, OBJPROP_HIDDEN, false);
ObjectSetInteger(0, name, OBJPROP_BACK, true);
// Add label
string labelName = name + "_Label";
ObjectCreate(0, labelName, OBJ_TEXT, 0, time, price);
ObjectSetString(0, labelName, OBJPROP_TEXT, label);
ObjectSetInteger(0, labelName, OBJPROP_COLOR, clr);
ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 8);
ObjectSetInteger(0, labelName, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, labelName, OBJPROP_HIDDEN, false);
ObjectSetInteger(0, labelName, OBJPROP_BACK, true);
}
//+------------------------------------------------------------------+
//| Clean up extrema objects |
//+------------------------------------------------------------------+
void CleanupExtremaObjects()
{
for(int i = ObjectsTotal(0, 0, -1) - 1; i >= 0; i--)
{
string name = ObjectName(0, i, 0, -1);
if(StringFind(name, extremaPrefix) == 0)
{
ObjectDelete(0, name);
}
}
}
//+------------------------------------------------------------------+
//| Check if trade is stuck |
//+------------------------------------------------------------------+
bool IsTradeStuck()
{
if(!PositionSelect(_Symbol))
{
Print("No position selected - cannot check if trade is stuck");
return false;
}
if(positionOpenTime == 0)
{
Print("Position open time not set - cannot check if trade is stuck");
return false;
}
datetime currentTime = iTime(_Symbol, BarTimeFrame, 0);
int barsPassed = (int)((currentTime - positionOpenTime) / PeriodSeconds(BarTimeFrame));
Print("Trade Stuck Check - Current Time: ", TimeToString(currentTime),
", Position Open Time: ", TimeToString(positionOpenTime),
", Bars Passed: ", barsPassed,
", Stuck Trade Bars: ", StuckTradeBars);
return barsPassed >= StuckTradeBars;
}
//+------------------------------------------------------------------+
//| Place hedge trade |
//+------------------------------------------------------------------+
void PlaceHedgeTrade()
{
if(isHedged)
{
Print("Hedge position already exists - skipping");
return;
}
if(!PositionSelect(_Symbol))
{
Print("No position selected - cannot place hedge");
return;
}
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
double currentLot = PositionGetDouble(POSITION_VOLUME);
double hedgeLot = currentLot * HedgeLotMultiplier;
Print("Placing hedge trade - Current Position: ", EnumToString(posType),
", Current Lot: ", currentLot,
", Hedge Lot: ", hedgeLot);
// Set different magic number for hedge positions
trade.SetExpertMagicNumber(654321);
if(posType == POSITION_TYPE_BUY)
{
if(trade.Sell(hedgeLot, _Symbol, 0, 0, 0, "RSI Hedge Sell"))
{
isHedged = true;
Print("Hedge sell position opened with lot size: ", hedgeLot);
}
else
{
Print("Failed to open hedge sell position");
}
}
else if(posType == POSITION_TYPE_SELL)
{
if(trade.Buy(hedgeLot, _Symbol, 0, 0, 0, "RSI Hedge Buy"))
{
isHedged = true;
Print("Hedge buy position opened with lot size: ", hedgeLot);
}
else
{
Print("Failed to open hedge buy position");
}
}
// Reset magic number back to original
trade.SetExpertMagicNumber(123456);
}
//+------------------------------------------------------------------+
//| Close all positions |
//+------------------------------------------------------------------+
void CloseAllPositions()
{
Print("Starting to close all positions");
// Close all positions for the symbol
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0)
{
Print("Failed to get position ticket for index ", i);
continue;
}
if(!PositionSelectByTicket(ticket))
{
Print("Failed to select position with ticket ", ticket);
continue;
}
if(PositionGetString(POSITION_SYMBOL) != _Symbol)
{
Print("Position ", ticket, " is not for symbol ", _Symbol);
continue;
}
Print("Closing position - Ticket: ", ticket,
", Magic: ", PositionGetInteger(POSITION_MAGIC),
", Type: ", EnumToString((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE)));
if(!trade.PositionClose(ticket))
{
Print("Failed to close position with ticket ", ticket);
}
else
{
Print("Successfully closed position with ticket ", ticket);
}
}
isHedged = false;
positionOpenTime = 0;
Print("All positions closed");
}
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Initialize RSI indicator
rsiHandle = iRSI(_Symbol, BarTimeFrame, RSI_Period, PRICE_CLOSE);
if(rsiHandle == INVALID_HANDLE)
{
Print("Error creating RSI indicator");
return(INIT_FAILED);
}
// Initialize trade object
trade.SetExpertMagicNumber(123457);
Print("RSI Divergence Rebound Strategy Initialized");
Print("RSI Period: ", RSI_Period);
Print("Overbought Level: ", RSI_Overbought);
Print("Oversold Level: ", RSI_Oversold);
// Clean up any existing extrema objects
CleanupExtremaObjects();
positionOpenTime = 0;
isHedged = false;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Clean up extrema objects
CleanupExtremaObjects();
IndicatorRelease(rsiHandle);
CloseAllPositions();
}
//+------------------------------------------------------------------+
//| Check for local extrema in RSI |
//+------------------------------------------------------------------+
bool IsLocalExtrema(double rsi1, double rsi2, double rsi3, bool& isMaxima)
{
if(rsi2 > rsi1 && rsi2 > rsi3)
{
isMaxima = true;
return true;
}
else if(rsi2 < rsi1 && rsi2 < rsi3)
{
isMaxima = false;
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Check for divergence patterns |
//+------------------------------------------------------------------+
bool CheckDivergence(double price1, double rsi1, double price2, double rsi2, bool isOverbought)
{
if(isOverbought)
{
// Bearish divergence (price makes higher high, RSI makes lower high)
if(price2 > price1 && rsi2 < rsi1)
return true;
// Hidden bearish divergence (price makes lower high, RSI makes higher high)
if(price2 < price1 && rsi2 > rsi1)
return true;
}
else
{
// Bullish divergence (price makes lower low, RSI makes higher low)
if(price2 < price1 && rsi2 > rsi1)
return true;
// Hidden bullish divergence (price makes higher low, RSI makes lower low)
if(price2 > price1 && rsi2 < rsi1)
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Check if market is open |
//+------------------------------------------------------------------+
bool IsMarketOpen()
{
MqlDateTime dt;
TimeCurrent(dt);
// Check if it's a weekend
if(dt.day_of_week == 0 || dt.day_of_week == 6)
return false;
// Check if it's within trading hours (assuming 24/5 market)
// You can modify these hours based on your broker's trading hours
int hour = dt.hour;
int minute = dt.min;
// Market is open 24/5 except weekends
return true;
}
//+------------------------------------------------------------------+
//| Check if extrema has expired |
//+------------------------------------------------------------------+
bool HasExtremaExpired()
{
if(extremaStartTime == 0)
return false;
datetime currentTime = iTime(_Symbol, BarTimeFrame, 0);
int barsPassed = (int)((currentTime - extremaStartTime) / PeriodSeconds(BarTimeFrame));
return barsPassed >= ExtremaExpiryBars;
}
//+------------------------------------------------------------------+
//| Check if loss is resolved after hedging |
//+------------------------------------------------------------------+
bool IsLossResolved()
{
if(!isHedged)
{
Print("Loss Resolution Check - No hedge position exists");
return false;
}
double originalProfit = 0;
double hedgeProfit = 0;
bool foundOriginal = false;
bool foundHedge = false;
Print("Loss Resolution Check - Starting position scan");
// Calculate total profit from all positions
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0)
{
Print("Loss Resolution Check - Failed to get position ticket for index ", i);
continue;
}
if(!PositionSelectByTicket(ticket))
{
Print("Loss Resolution Check - Failed to select position with ticket ", ticket);
continue;
}
if(PositionGetString(POSITION_SYMBOL) != _Symbol)
{
Print("Loss Resolution Check - Position ", ticket, " is not for symbol ", _Symbol);
continue;
}
double profit = PositionGetDouble(POSITION_PROFIT);
int magic = (int)PositionGetInteger(POSITION_MAGIC);
Print("Loss Resolution Check - Position ", ticket,
", Magic: ", magic,
", Profit: ", profit);
if(magic == 123456) // Original position
{
originalProfit = profit;
foundOriginal = true;
Print("Loss Resolution Check - Found original position with profit: ", profit);
}
else if(magic == 654321) // Hedge position
{
hedgeProfit = profit;
foundHedge = true;
Print("Loss Resolution Check - Found hedge position with profit: ", profit);
}
}
if(!foundOriginal)
Print("Loss Resolution Check - Warning: Original position not found");
if(!foundHedge)
Print("Loss Resolution Check - Warning: Hedge position not found");
double totalProfit = originalProfit + hedgeProfit;
Print("Loss Resolution Check - Final Calculation -",
"\nOriginal Profit: ", originalProfit,
"\nHedge Profit: ", hedgeProfit,
"\nTotal Profit: ", totalProfit,
"\nIs Resolved: ", totalProfit >= 0);
return totalProfit >= 0;
}
//+------------------------------------------------------------------+
//| Check if main trade is in loss |
//+------------------------------------------------------------------+
bool IsMainTradeInLoss()
{
if(!PositionSelect(_Symbol))
{
Print("No position selected - cannot check for loss");
return false;
}
if(PositionGetInteger(POSITION_MAGIC) != 123456)
{
Print("Not a main trade position - cannot check for loss");
return false;
}
double profit = PositionGetDouble(POSITION_PROFIT);
Print("Main Trade Profit Check - Profit: ", profit);
return profit < 0;
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Check if market is open
if(!IsMarketOpen())
{
Print("Market is closed - resetting extrema");
ResetExtrema();
return;
}
// Check for new bar
datetime currentBarTime = iTime(_Symbol, BarTimeFrame, 0);
if(currentBarTime == lastBarTime)
return;
lastBarTime = currentBarTime;
// Get current RSI value
double rsiBuffer[];
ArraySetAsSeries(rsiBuffer, true);
if(CopyBuffer(rsiHandle, 0, 0, 1, rsiBuffer) != 1)
{
Print("Error copying RSI buffer");
return;
}
// Update RSI queue
RSILastThree = RSILastTwo;
RSILastTwo = RSILast;
RSILast = rsiBuffer[0];
// Check if we have enough RSI values
if(RSILastThree == 0 || RSILastTwo == 0)
return;
// Check for local extrema
bool isMaxima;
if(IsLocalExtrema(RSILastThree, RSILastTwo, RSILast, isMaxima))
{
if(!hasFirstExtrema)
{
// For overbought condition, we need a maxima
if(isMaxima && RSILastTwo >= RSI_Overbought)
{
hasFirstExtrema = true;
isOverboughtExtrema = true;
priceFirstExtrema = iClose(_Symbol, BarTimeFrame, 1);
rsiFirstExtrema = RSILastTwo;
firstExtremaTime = iTime(_Symbol, BarTimeFrame, 1);
extremaStartTime = firstExtremaTime;
// Draw first extrema
string firstExtremaName = extremaPrefix + "First_" + TimeToString(firstExtremaTime);
DrawExtremaPoint(firstExtremaName, firstExtremaTime, priceFirstExtrema,
clrRed, 234, "1st OB");
Print("First extrema detected - Type: Overbought",
", RSI: ", rsiFirstExtrema, ", Price: ", priceFirstExtrema);
}
// For oversold condition, we need a minima
else if(!isMaxima && RSILastTwo <= RSI_Oversold)
{
hasFirstExtrema = true;
isOverboughtExtrema = false;
priceFirstExtrema = iClose(_Symbol, BarTimeFrame, 1);
rsiFirstExtrema = RSILastTwo;
firstExtremaTime = iTime(_Symbol, BarTimeFrame, 1);
extremaStartTime = firstExtremaTime;
// Draw first extrema
string firstExtremaName = extremaPrefix + "First_" + TimeToString(firstExtremaTime);
DrawExtremaPoint(firstExtremaName, firstExtremaTime, priceFirstExtrema,
clrGreen, 234, "1st OS");
Print("First extrema detected - Type: Oversold",
", RSI: ", rsiFirstExtrema, ", Price: ", priceFirstExtrema);
}
}
// Second extrema (check for divergence)
else if(!hasSecondExtrema)
{
priceSecondExtrema = iClose(_Symbol, BarTimeFrame, 1);
rsiSecondExtrema = RSILastTwo;
secondExtremaTime = iTime(_Symbol, BarTimeFrame, 1);
if(CheckDivergence(priceFirstExtrema, rsiFirstExtrema, priceSecondExtrema, rsiSecondExtrema, isOverboughtExtrema))
{
hasSecondExtrema = true;
// Draw second extrema
string secondExtremaName = extremaPrefix + "Second_" + TimeToString(secondExtremaTime);
DrawExtremaPoint(secondExtremaName, secondExtremaTime, priceSecondExtrema,
clrBlue, 233, "2nd Div");
Print("Second extrema detected - Divergence found",
", RSI: ", rsiSecondExtrema, ", Price: ", priceSecondExtrema);
}
}
// Third extrema (must be between overbought/oversold levels)
else if(!hasThirdExtrema)
{
if(RSILastTwo > RSI_Oversold && RSILastTwo < RSI_Overbought)
{
hasThirdExtrema = true;
priceThirdExtrema = iClose(_Symbol, BarTimeFrame, 1);
rsiThirdExtrema = RSILastTwo;
thirdExtremaTime = iTime(_Symbol, BarTimeFrame, 1);
// Draw third extrema
string thirdExtremaName = extremaPrefix + "Third_" + TimeToString(thirdExtremaTime);
DrawExtremaPoint(thirdExtremaName, thirdExtremaTime, priceThirdExtrema,
clrMagenta, 232, "3rd Entry");
Print("Third extrema detected - Trade signal",
", RSI: ", rsiThirdExtrema, ", Price: ", priceThirdExtrema);
// Enter trade
if(isOverboughtExtrema)
{
if(!trade.Sell(BaseLotSize, _Symbol, 0, 0, 0, "RSI Divergence Sell"))
{
Print("Failed to execute sell order - resetting extrema");
ResetExtrema();
}
else
{
positionOpenTime = iTime(_Symbol, BarTimeFrame, 0);
Print("Sell position opened at: ", TimeToString(positionOpenTime));
}
}
else
{
if(!trade.Buy(BaseLotSize, _Symbol, 0, 0, 0, "RSI Divergence Buy"))
{
Print("Failed to execute buy order - resetting extrema");
ResetExtrema();
}
else
{
positionOpenTime = iTime(_Symbol, BarTimeFrame, 0);
Print("Buy position opened at: ", TimeToString(positionOpenTime));
}
}
}
}
}
// Check for exit conditions and hedge
if(PositionSelect(_Symbol))
{
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
// Check if trade is stuck and in loss
if(IsTradeStuck() && IsMainTradeInLoss())
{
Print("Trade is stuck and in loss - placing hedge");
PlaceHedgeTrade();
}
// Check if loss is resolved after hedging
if(isHedged && IsLossResolved())
{
Print("Loss resolved - closing all positions");
CloseAllPositions();
ResetExtrema();
return;
}
// Check RSI exit conditions
if(posType == POSITION_TYPE_BUY && RSILast >= ExitBuyRSIThreshold)
{
CloseAllPositions();
ResetExtrema();
}
else if(posType == POSITION_TYPE_SELL && RSILast <= ExitSellRSIThreshold)
{
CloseAllPositions();
ResetExtrema();
}
}
}
//+------------------------------------------------------------------+
//| Reset extrema flags and values |
//+------------------------------------------------------------------+
void ResetExtrema()
{
// Clean up existing objects
CleanupExtremaObjects();
hasFirstExtrema = false;
hasSecondExtrema = false;
hasThirdExtrema = false;
isOverboughtExtrema = false;
priceFirstExtrema = 0;
rsiFirstExtrema = 0;
priceSecondExtrema = 0;
rsiSecondExtrema = 0;
priceThirdExtrema = 0;
rsiThirdExtrema = 0;
firstExtremaTime = 0;
secondExtremaTime = 0;
thirdExtremaTime = 0;
extremaStartTime = 0;
positionOpenTime = 0;
isHedged = false;
}
//+------------------------------------------------------------------+
Binary file not shown.

Before

Width:  |  Height:  |  Size: 255 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 273 KiB

-441
View File
@@ -1,441 +0,0 @@
//+------------------------------------------------------------------+
//| RSIDivergenceRebound.mq5 |
//| Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
// Input Parameters
input int RSI_Period = 14; // RSI Period
input int RSI_Overbought = 70; // RSI Overbought Level
input int RSI_Oversold = 30; // RSI Oversold Level
input double BaseLotSize = 0.01; // Base Lot Size
input int ATR_Period = 14; // ATR Period
input double ATR_SL_Multiplier = 3.0; // ATR Stop Loss Multiplier
input double ATR_TP_Multiplier = 10.0; // ATR Take Profit Multiplier
input int MaxSpread = 50; // Maximum Spread in Points
input int DivergenceLookback = 9; // Number of bars to look back for divergence
input int MinTradeInterval = 30; // Minimum minutes between trades
input double MaxRiskPercent = 2.0; // Maximum risk per trade (% of balance)
input double MaxDrawdownPercent = 10.0; // Maximum drawdown before reset (% of balance)
input int MaxConsecutiveLosses = 3; // Maximum consecutive losses before reset
input double MaxLotSize = 0.1; // Maximum allowed lot size
input bool UseRegularDivergence = true; // Use regular divergence for reversals
input bool UseHiddenDivergence = true; // Use hidden divergence for continuations
input int RSI_ConfirmationBars = 19; // Number of bars to confirm RSI pattern
// Global Variables
int rsiHandle; // RSI indicator handle
int atrHandle; // ATR indicator handle
datetime lastTradeTime = 0; // Last trade time
datetime lastDebugTime = 0; // Last debug message time
double currentLotSize = 0; // Current lot size
bool lastTradeWasWin = false; // Flag for last trade result
int consecutiveLosses = 0; // Count of consecutive losses
double initialBalance = 0; // Initial account balance
double maxBalance = 0; // Maximum balance reached
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Initialize indicators
rsiHandle = iRSI(_Symbol, PERIOD_H1, RSI_Period, PRICE_CLOSE);
atrHandle = iATR(_Symbol, PERIOD_H1, ATR_Period);
if(rsiHandle == INVALID_HANDLE || atrHandle == INVALID_HANDLE)
{
Print("Error creating indicators");
return(INIT_FAILED);
}
// Initialize variables
currentLotSize = BaseLotSize;
lastTradeWasWin = false;
lastTradeTime = 0;
consecutiveLosses = 0;
initialBalance = AccountInfoDouble(ACCOUNT_BALANCE);
maxBalance = initialBalance;
Print("RSI Divergence Rebound Strategy Initialized");
Print("Base Lot Size: ", BaseLotSize);
Print("RSI Period: ", RSI_Period, ", ATR Period: ", ATR_Period);
Print("Max Risk per Trade: ", MaxRiskPercent, "%");
Print("Max Drawdown: ", MaxDrawdownPercent, "%");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Release indicator handles
IndicatorRelease(rsiHandle);
IndicatorRelease(atrHandle);
}
//+------------------------------------------------------------------+
//| Get ATR value for stop loss and take profit calculations |
//+------------------------------------------------------------------+
double GetATRValue()
{
double atrBuffer[];
ArraySetAsSeries(atrBuffer, true);
if(CopyBuffer(atrHandle, 0, 0, 1, atrBuffer) != 1)
{
Print("Error copying ATR buffer");
return 0;
}
return atrBuffer[0];
}
//+------------------------------------------------------------------+
//| Check for RSI divergence patterns |
//+------------------------------------------------------------------+
int CheckRSIDivergence()
{
double rsiBuffer[];
double highBuffer[];
double lowBuffer[];
ArraySetAsSeries(rsiBuffer, true);
ArraySetAsSeries(highBuffer, true);
ArraySetAsSeries(lowBuffer, true);
if(CopyBuffer(rsiHandle, 0, 0, DivergenceLookback + 1, rsiBuffer) != DivergenceLookback + 1 ||
CopyHigh(_Symbol, PERIOD_H1, 0, DivergenceLookback + 1, highBuffer) != DivergenceLookback + 1 ||
CopyLow(_Symbol, PERIOD_H1, 0, DivergenceLookback + 1, lowBuffer) != DivergenceLookback + 1)
{
Print("Error copying data for divergence check");
return 0;
}
// Check for regular bullish divergence (price makes lower low, RSI makes higher low)
if(UseRegularDivergence)
{
for(int i = 1; i < DivergenceLookback; i++)
{
if(lowBuffer[i] < lowBuffer[i+1] && rsiBuffer[i] > rsiBuffer[i+1] &&
rsiBuffer[i] > RSI_Oversold && rsiBuffer[i] < RSI_Overbought)
{
// Confirm RSI is making higher lows
if(rsiBuffer[0] > rsiBuffer[1] && rsiBuffer[1] > rsiBuffer[2])
{
Print("Regular bullish divergence detected");
return 1; // Bullish signal
}
}
}
// Check for regular bearish divergence (price makes higher high, RSI makes lower high)
for(int i = 1; i < DivergenceLookback; i++)
{
if(highBuffer[i] > highBuffer[i+1] && rsiBuffer[i] < rsiBuffer[i+1] &&
rsiBuffer[i] > RSI_Oversold && rsiBuffer[i] < RSI_Overbought)
{
// Confirm RSI is making lower highs
if(rsiBuffer[0] < rsiBuffer[1] && rsiBuffer[1] < rsiBuffer[2])
{
Print("Regular bearish divergence detected");
return -1; // Bearish signal
}
}
}
}
// Check for hidden bullish divergence (price makes higher low, RSI makes lower low)
if(UseHiddenDivergence)
{
for(int i = 1; i < DivergenceLookback; i++)
{
if(lowBuffer[i] > lowBuffer[i+1] && rsiBuffer[i] < rsiBuffer[i+1] &&
rsiBuffer[i] > RSI_Oversold && rsiBuffer[i] < RSI_Overbought)
{
// Confirm RSI is making higher lows
if(rsiBuffer[0] > rsiBuffer[1] && rsiBuffer[1] > rsiBuffer[2])
{
Print("Hidden bullish divergence detected");
return 1; // Bullish signal
}
}
}
// Check for hidden bearish divergence (price makes lower high, RSI makes higher high)
for(int i = 1; i < DivergenceLookback; i++)
{
if(highBuffer[i] < highBuffer[i+1] && rsiBuffer[i] > rsiBuffer[i+1] &&
rsiBuffer[i] > RSI_Oversold && rsiBuffer[i] < RSI_Overbought)
{
// Confirm RSI is making lower highs
if(rsiBuffer[0] < rsiBuffer[1] && rsiBuffer[1] < rsiBuffer[2])
{
Print("Hidden bearish divergence detected");
return -1; // Bearish signal
}
}
}
}
return 0; // No signal
}
//+------------------------------------------------------------------+
//| Check if we can open a new position |
//+------------------------------------------------------------------+
bool CanOpenPosition()
{
// Check spread
long currentSpread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
if(currentSpread > MaxSpread)
{
Print("Spread too high: ", currentSpread);
return false;
}
// Check minimum time between trades
datetime currentTime = TimeCurrent();
if(currentTime - lastTradeTime < MinTradeInterval * 60)
{
Print("Minimum time between trades not reached - Time since last trade: ",
(currentTime - lastTradeTime) / 60, " minutes");
return false;
}
// Check for existing positions
int total = PositionsTotal();
for(int i = 0; i < total; i++)
{
ulong ticket = PositionGetTicket(i);
if(PositionSelectByTicket(ticket))
{
if(PositionGetString(POSITION_SYMBOL) == _Symbol)
{
Print("Position already exists - Ticket: ", ticket);
return false;
}
}
}
return true;
}
//+------------------------------------------------------------------+
//| Open new position |
//+------------------------------------------------------------------+
bool OpenPosition(ENUM_POSITION_TYPE posType)
{
// Validate lot size before attempting to open position
double maxLotSize = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
double minLotSize = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
if(currentLotSize > maxLotSize || currentLotSize < minLotSize)
{
currentLotSize = BaseLotSize;
Print("Lot size out of limits - Resetting to base: ", currentLotSize);
}
// Calculate required margin for the position
double marginRequired = SymbolInfoDouble(_Symbol, SYMBOL_MARGIN_INITIAL) * currentLotSize;
double freeMargin = AccountInfoDouble(ACCOUNT_MARGIN_FREE);
// If not enough margin, reduce lot size
while(marginRequired > freeMargin && currentLotSize > minLotSize)
{
currentLotSize = NormalizeDouble(currentLotSize * 0.5, 2);
marginRequired = SymbolInfoDouble(_Symbol, SYMBOL_MARGIN_INITIAL) * currentLotSize;
Print("Insufficient margin - Reducing lot size to: ", currentLotSize);
}
// If still not enough margin, reset to base lot size
if(marginRequired > freeMargin)
{
currentLotSize = BaseLotSize;
marginRequired = SymbolInfoDouble(_Symbol, SYMBOL_MARGIN_INITIAL) * currentLotSize;
Print("Still insufficient margin - Resetting to base lot size: ", currentLotSize);
}
// Get current ATR value
double atrValue = GetATRValue();
if(atrValue == 0)
{
Print("Error getting ATR value");
return false;
}
double price = (posType == POSITION_TYPE_BUY) ? SymbolInfoDouble(_Symbol, SYMBOL_ASK)
: SymbolInfoDouble(_Symbol, SYMBOL_BID);
double sl = (posType == POSITION_TYPE_BUY)
? price - (atrValue * ATR_SL_Multiplier)
: price + (atrValue * ATR_SL_Multiplier);
double tp = (posType == POSITION_TYPE_BUY)
? price + (atrValue * ATR_TP_Multiplier)
: price - (atrValue * ATR_TP_Multiplier);
MqlTradeRequest request = {};
MqlTradeResult result = {};
request.action = TRADE_ACTION_DEAL;
request.symbol = _Symbol;
request.volume = currentLotSize;
request.type = (posType == POSITION_TYPE_BUY) ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;
request.price = price;
request.sl = sl;
request.tp = tp;
request.deviation = 10;
request.magic = 123456;
// Set filling mode for XAUUSD
request.type_filling = ORDER_FILLING_FOK; // Fill or Kill
// If FOK fails, try IOC
if(!OrderSend(request, result))
{
request.type_filling = ORDER_FILLING_IOC; // Immediate or Cancel
if(!OrderSend(request, result))
{
Print("Failed to open position. Error: ", GetLastError());
return false;
}
}
if(result.retcode != TRADE_RETCODE_DONE)
{
Print("Order failed. Return code: ", result.retcode);
return false;
}
lastTradeTime = TimeCurrent();
Print("Position opened successfully - Lot size: ", currentLotSize,
", ATR: ", atrValue,
", SL: ", sl,
", TP: ", tp);
return true;
}
//+------------------------------------------------------------------+
//| Check if we need to reset due to drawdown or consecutive losses |
//+------------------------------------------------------------------+
bool NeedToReset()
{
double currentBalance = AccountInfoDouble(ACCOUNT_BALANCE);
double currentEquity = AccountInfoDouble(ACCOUNT_EQUITY);
// Update maximum balance
if(currentBalance > maxBalance)
maxBalance = currentBalance;
// Calculate current drawdown
double drawdownPercent = ((maxBalance - currentEquity) / maxBalance) * 100.0;
// Check if we've hit maximum drawdown
if(drawdownPercent >= MaxDrawdownPercent)
{
Print("Maximum drawdown reached - Drawdown: ", drawdownPercent, "%");
return true;
}
// Check if we've hit maximum consecutive losses
if(consecutiveLosses >= MaxConsecutiveLosses)
{
Print("Maximum consecutive losses reached - Losses: ", consecutiveLosses);
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| Check for closed positions and update lot size |
//+------------------------------------------------------------------+
void CheckClosedPositions()
{
static int lastTotal = 0;
int currentTotal = PositionsTotal();
// If we have fewer positions than before, a position was closed
if(currentTotal < lastTotal)
{
// Check history for the last closed position
HistorySelect(TimeCurrent() - 3600, TimeCurrent());
int historyTotal = HistoryDealsTotal();
if(historyTotal > 0)
{
ulong dealTicket = HistoryDealGetTicket(historyTotal - 1);
if(dealTicket > 0)
{
double dealProfit = HistoryDealGetDouble(dealTicket, DEAL_PROFIT);
bool isWin = (dealProfit > 0);
Print("Position closed - Profit: ", dealProfit,
", Win: ", isWin ? "Yes" : "No");
if(isWin)
{
lastTradeWasWin = true;
consecutiveLosses = 0;
}
else
{
lastTradeWasWin = false;
consecutiveLosses++;
// Check if we need to reset due to drawdown or consecutive losses
if(NeedToReset())
{
consecutiveLosses = 0;
Print("Reset triggered");
}
}
}
}
}
lastTotal = currentTotal;
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
datetime currentTime = TimeCurrent();
// Print debug info every minute
if(currentTime - lastDebugTime >= 60)
{
lastDebugTime = currentTime;
Print("Current lot size: ", currentLotSize,
", Last trade was win: ", lastTradeWasWin ? "Yes" : "No");
}
// Check for closed positions and update lot size
CheckClosedPositions();
// Check for entry signals
if(CanOpenPosition())
{
int signal = CheckRSIDivergence();
if(signal == 1) // Bullish signal
{
Print("Opening buy position with lot size: ", currentLotSize);
OpenPosition(POSITION_TYPE_BUY);
}
else if(signal == -1) // Bearish signal
{
Print("Opening sell position with lot size: ", currentLotSize);
OpenPosition(POSITION_TYPE_SELL);
}
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 284 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 257 KiB

@@ -12,27 +12,27 @@
// Input Parameters
input group "General Settings"
input ENUM_TIMEFRAMES InpTimeframe = PERIOD_CURRENT; // Trading Timeframe
input ENUM_TIMEFRAMES InpTimeframe = PERIOD_H1; // Trading Timeframe
input double InpLotSize = 0.01; // Lot Size
input int InpMagicNumberRSIFollow = 1001; // Magic Number RSI Follow
input int InpMagicNumberRSIReverse = 1002;// Magic Number RSI Reverse
input int InpMagicNumberEMACross = 1003; // Magic Number EMA Cross
input group "Strategy Switches"
input bool InpEnableRSIFollow = false; // Enable RSI Follow Strategy
input bool InpEnableRSIFollow = true; // Enable RSI Follow Strategy
input bool InpEnableRSIReverse = true; // Enable RSI Reverse Strategy
input bool InpEnableEMACross = false; // Enable EMA Cross Strategy
input bool InpEnableEMACross = true; // Enable EMA Cross Strategy
input bool InpEnableStrategyLock = false; // Enable Strategy Lock
input double InpLockProfitThreshold = 0.0; // Lock Profit Threshold (pips)
input bool InpCloseOppositeTrades = false; // Close Opposite Trades When Profiting
input group "RSI Follow Strategy"
input int InpRSIPeriod = 14; // RSI Period
input int InpRSIOverbought = 70; // RSI Overbought Level
input int InpRSIOversold = 30; // RSI Oversold Level
input int InpRSIExitLevel = 50; // RSI Exit Level
input int InpRSIPeriod = 87; // RSI Period
input int InpRSIOverbought = 72; // RSI Overbought Level
input int InpRSIOversold = 50; // RSI Oversold Level
input int InpRSIExitLevel = 40; // RSI Exit Level
input int InpRSIFollowStartHour = 0; // RSI Follow Start Hour (0-23)
input int InpRSIFollowEndHour = 23; // RSI Follow End Hour (0-23)
input int InpRSIFollowEndHour = 7; // RSI Follow End Hour (0-23)
input bool InpRSIFollowCloseOutsideHours = true; // Close trades outside trading hours
input group "RSI Reverse Strategy"
@@ -48,13 +48,13 @@ input int InpRSIReverseCooldownBars = 15; // RSI Reverse Cooldown (bars)
input bool InpRSIReverseCooldownOnLoss = true; // Apply cooldown only on loss
input group "EMA Cross Strategy"
input int InpEMAPeriod = 20; // EMA Period
input int InpEMACrossStartHour = 0; // EMA Cross Start Hour (0-23)
input int InpEMACrossEndHour = 23; // EMA Cross End Hour (0-23)
input int InpEMAPeriod = 120; // EMA Period
input int InpEMACrossStartHour = 8; // EMA Cross Start Hour (0-23)
input int InpEMACrossEndHour = 14; // EMA Cross End Hour (0-23)
input bool InpEMACrossCloseOutsideHours = true; // Close trades outside trading hours
input bool InpUseEMADistanceEntry = false; // Use EMA Distance Entry
input double InpEMADistancePips = 10.0; // EMA Distance Threshold (pips)
input int InpEMADistancePeriod = 3; // EMA Distance Period (bars)
input bool InpUseEMADistanceEntry = true; // Use EMA Distance Entry
input double InpEMADistancePips = 160.0; // EMA Distance Threshold (pips)
input int InpEMADistancePeriod = 26; // EMA Distance Period (bars)
// Global Variables
int rsiHandle;
Binary file not shown.

After

Width:  |  Height:  |  Size: 280 KiB

+18 -7
View File
@@ -12,16 +12,16 @@
#include <Trade\Trade.mqh>
// Input parameters
input int RSIPeriod = 14; // RSI period
input double OverboughtLevel = 67; // Overbought level
input double OversoldLevel = 17; // Oversold level
input int TakeProfitPips = 253; // Take profit in pips
input int StopLossPips = 429; // Stop loss in pips
input int RSIPeriod = 28; // RSI period
input double OverboughtLevel = 64; // Overbought level
input double OversoldLevel = 13; // Oversold level
input int TakeProfitPips = 175; // Take profit in pips
input int StopLossPips = 5; // Stop loss in pips
input double MaxLotSize = 0.1; // Maximum lot size
input int MaxSpread = 1000; // Maximum allowed spread in pips
input int MaxDuration = 81; // Maximum trade duration in hours
input int MaxDuration = 140; // Maximum trade duration in hours
input bool UseStopLoss = false; // Use stop loss
input bool UseTakeProfit = true; // Use take profit
input bool UseTakeProfit = false; // Use take profit
input bool UseRSIExit = true; // Use RSI for exit
input double RSIExitLevel = 49; // RSI level to exit (50 = neutral)
input bool CloseOutsideSession = false; // Close trades outside Asian session
@@ -221,6 +221,17 @@ bool CloseAllTrades(string reason = "")
Print("Attempting to close all positions", (reason != "" ? " - " + reason : ""));
// Check if there are any positions with our magic number
bool hasOurPositions = false;
for(int i = 0; i < totalPositions; i++)
{
if(PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_MAGIC) == 123456)
{
hasOurPositions = true;
break;
}
}
for(int i = totalPositions - 1; i >= 0; i--)
{
if(PositionGetSymbol(i) == _Symbol)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 305 KiB

After

Width:  |  Height:  |  Size: 268 KiB

+24 -9
View File
@@ -13,17 +13,17 @@
// Input parameters
input int RSIPeriod = 14; // RSI period
input double OverboughtLevel = 77; // Overbought level
input double OversoldLevel = 10; // Oversold level
input int TakeProfitPips = 116; // Take profit in pips
input int StopLossPips = 247; // Stop loss in pips
input double MaxLotSize = 0.05; // Maximum lot size
input double OverboughtLevel = 78; // Overbought level
input double OversoldLevel = 20; // Oversold level
input int TakeProfitPips = 635; // Take profit in pips
input int StopLossPips = 290; // Stop loss in pips
input double MaxLotSize = 0.1; // Maximum lot size
input int MaxSpread = 1000; // Maximum allowed spread in pips
input int MaxDuration = 67; // Maximum trade duration in hours
input int MaxDuration = 22; // Maximum trade duration in hours
input bool UseStopLoss = true; // Use stop loss
input bool UseTakeProfit = false; // Use take profit
input bool UseRSIExit = true; // Use RSI for exit
input double RSIExitLevel = 40; // RSI level to exit (50 = neutral)
input double RSIExitLevel = 57; // RSI level to exit (50 = neutral)
input bool CloseOutsideSession = false; // Close trades outside Asian session
input color PanelBackground = clrBlack; // Panel background color
input color PanelText = clrWhite; // Panel text color
@@ -219,6 +219,21 @@ bool CloseAllTrades(string reason = "")
if(totalPositions == 0)
return true;
// Check if there are any positions with our magic number
bool hasOurPositions = false;
for(int i = 0; i < totalPositions; i++)
{
if(PositionGetSymbol(i) == _Symbol && PositionGetInteger(POSITION_MAGIC) == 123457)
{
hasOurPositions = true;
break;
}
}
// Return if no positions with our magic number
if(!hasOurPositions)
return true;
Print("Attempting to close all positions", (reason != "" ? " - " + reason : ""));
for(int i = totalPositions - 1; i >= 0; i--)
@@ -407,7 +422,7 @@ void OnTick()
// Set trade parameters
trade.SetDeviationInPoints(3);
trade.SetTypeFilling(ORDER_FILLING_IOC);
trade.SetExpertMagicNumber(123456);
trade.SetExpertMagicNumber(123457);
// Place buy order using CTrade
if(!trade.Buy(MaxLotSize, _Symbol, currentAsk, sl, tp, "RSI Buy"))
@@ -437,7 +452,7 @@ void OnTick()
// Set trade parameters
trade.SetDeviationInPoints(3);
trade.SetTypeFilling(ORDER_FILLING_IOC);
trade.SetExpertMagicNumber(123456);
trade.SetExpertMagicNumber(123457);
// Place sell order using CTrade
if(!trade.Sell(MaxLotSize, _Symbol, currentBid, sl, tp, "RSI Sell"))
Binary file not shown.

Before

Width:  |  Height:  |  Size: 292 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 295 KiB

After

Width:  |  Height:  |  Size: 235 KiB

-477
View File
@@ -1,477 +0,0 @@
//+------------------------------------------------------------------+
//| RSIReverseFollow.mq5 |
//| Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include <Trade\Trade.mqh>
// Input parameters
input group "Timeframe Settings"
input ENUM_TIMEFRAMES InpTimeframe = PERIOD_M3; // Trading Timeframe
input group "RSI Settings"
input int InpRSIPeriod = 48; // RSI Period
input double InpRSIOverbought = 68; // RSI Overbought Level
input double InpRSIOversold = 12; // RSI Oversold Level
input double InpRSI50Distance = 4.0; // Distance from 50 to consider as near
input group "Strategy 1 - RSI 50 Touch"
input bool InpEnableStrategy1 = true; // Enable Strategy 1
input int InpMagicNumber1 = 123456; // Magic Number for Strategy 1
input double InpLotSize1 = 0.01; // Lot Size for Strategy 1
input bool InpEnableRSIExit1 = true; // Enable RSI-based exit for Strategy 1
input bool InpUseSLTPWithRSI1 = false; // Use SL/TP alongside RSI exits
input int InpStopLoss1 = 188; // Stop Loss in pips
input int InpTakeProfit1 = 547; // Take Profit in pips
input double InpRSIExitBuy1 = 97.0; // RSI level to exit buy trades
input double InpRSIExitSell1 = 20.0; // RSI level to exit sell trades
input int InpTrailingStop1 = 125; // Trailing Stop in pips
input int InpTrailingStep1 = 400; // Trailing Step in pips
input int InpMaxTradeDuration1 = 22; // Maximum trade duration (hours)
input double InpLossThreshold1 = 7.1; // Minimum loss threshold to close trade
input group "Strategy 2 - RSI Reversal"
input bool InpEnableStrategy2 = true; // Enable Strategy 2
input int InpMagicNumber2 = 123457; // Magic Number for Strategy 2
input double InpLotSize2 = 0.01; // Lot Size for Strategy 2
input bool InpEnableRSIExit2 = false; // Enable RSI-based exit for Strategy 2
input bool InpUseSLTPWithRSI2 = true; // Use SL/TP alongside RSI exits
input int InpStopLoss2 = 245; // Stop Loss in pips
input int InpTakeProfit2 = 410; // Take Profit in pips
input double InpRSIExitBuy2 = 70.0; // RSI level to exit buy trades
input double InpRSIExitSell2 = 5.0; // RSI level to exit sell trades
input int InpTrailingStop2 = 185; // Trailing Stop in pips
input int InpTrailingStep2 = 30; // Trailing Step in pips
input int InpMaxTradeDuration2 = 6; // Maximum trade duration (hours)
input double InpLossThreshold2 = 9.3; // Minimum loss threshold to close trade
input group "Trading Hours"
input int InpStartHour = 16; // Trading Session Start Hour
input int InpEndHour = 19; // Trading Session End Hour
input bool InpCloseOutsideHours = true;// Close trades outside trading hours
// Global variables
CTrade trade;
int rsiHandle;
double lastRSI[];
bool wasOverbought = false;
bool wasOversold = false;
datetime lastBarTime = 0;
bool debugMode = true; // Enable detailed logging
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Initialize RSI indicator
rsiHandle = iRSI(_Symbol, InpTimeframe, InpRSIPeriod, PRICE_CLOSE);
if(rsiHandle == INVALID_HANDLE)
{
Print("Error creating RSI indicator");
return INIT_FAILED;
}
// Initialize trade settings
trade.SetExpertMagicNumber(InpMagicNumber1);
trade.SetMarginMode();
trade.SetTypeFillingBySymbol(_Symbol);
trade.SetDeviationInPoints(10);
// Initialize RSI array
ArraySetAsSeries(lastRSI, true);
ArrayResize(lastRSI, 3);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
IndicatorRelease(rsiHandle);
}
//+------------------------------------------------------------------+
//| Check if new bar has formed |
//+------------------------------------------------------------------+
bool IsNewBar()
{
datetime time[];
if(CopyTime(_Symbol, InpTimeframe, 0, 1, time) > 0)
{
if(time[0] != lastBarTime)
{
lastBarTime = time[0];
return true;
}
}
return false;
}
//+------------------------------------------------------------------+
//| Check if within trading hours |
//+------------------------------------------------------------------+
bool IsWithinTradingHours()
{
datetime currentTime = TimeCurrent();
MqlDateTime timeStruct;
TimeToStruct(currentTime, timeStruct);
return (timeStruct.hour >= InpStartHour && timeStruct.hour < InpEndHour);
}
//+------------------------------------------------------------------+
//| Check for RSI signals |
//+------------------------------------------------------------------+
void CheckRSISignals()
{
// Get RSI values for current and previous bars
if(CopyBuffer(rsiHandle, 0, 0, 3, lastRSI) <= 0)
{
Print("Error getting RSI values");
return;
}
// Check for RSI extremes
if(lastRSI[0] >= InpRSIOverbought)
{
wasOverbought = true;
}
if(lastRSI[0] <= InpRSIOversold)
{
wasOversold = true;
}
}
//+------------------------------------------------------------------+
//| Check for trailing stop |
//+------------------------------------------------------------------+
void CheckTrailingStop(int magic, int trailingStop, int trailingStep)
{
if(!PositionSelectByTicket(magic))
return;
double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double stopLoss = PositionGetDouble(POSITION_SL);
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
double newStopLoss = 0;
double trailingStopPoints = trailingStop * _Point;
double trailingStepPoints = trailingStep * _Point;
if(posType == POSITION_TYPE_BUY)
{
if(currentPrice - openPrice > trailingStopPoints)
{
newStopLoss = currentPrice - trailingStopPoints;
if(newStopLoss > stopLoss + trailingStepPoints)
{
trade.PositionModify(magic, newStopLoss, PositionGetDouble(POSITION_TP));
}
}
}
else if(posType == POSITION_TYPE_SELL)
{
if(openPrice - currentPrice > trailingStopPoints)
{
newStopLoss = currentPrice + trailingStopPoints;
if(newStopLoss < stopLoss - trailingStepPoints || stopLoss == 0)
{
trade.PositionModify(magic, newStopLoss, PositionGetDouble(POSITION_TP));
}
}
}
}
//+------------------------------------------------------------------+
//| Check for time-based exits |
//+------------------------------------------------------------------+
void CheckTimeBasedExits(int magic, int maxDuration, double lossThreshold)
{
datetime currentTime = TimeCurrent();
if(PositionSelectByTicket(magic))
{
datetime openTime = (datetime)PositionGetInteger(POSITION_TIME);
double profit = PositionGetDouble(POSITION_PROFIT);
double swap = PositionGetDouble(POSITION_SWAP);
double totalLoss = profit + swap;
if(currentTime - openTime >= maxDuration * 3600)
{
if(totalLoss < -lossThreshold)
{
trade.PositionClose(magic);
}
}
}
}
//+------------------------------------------------------------------+
//| Check for trading hours exits |
//+------------------------------------------------------------------+
void CheckTradingHoursExits()
{
if(!InpCloseOutsideHours)
return;
if(!IsWithinTradingHours())
{
// Close Strategy 1 positions
if(PositionSelectByTicket(InpMagicNumber1))
{
trade.PositionClose(InpMagicNumber1);
}
// Close Strategy 2 positions
if(PositionSelectByTicket(InpMagicNumber2))
{
trade.PositionClose(InpMagicNumber2);
}
}
}
//+------------------------------------------------------------------+
//| Check for RSI-based exits |
//+------------------------------------------------------------------+
void CheckRSIExits(int magic, bool enableRSIExit, double exitBuyLevel, double exitSellLevel)
{
if(!enableRSIExit)
return;
// Try to find position by magic number
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(PositionSelectByTicket(PositionGetTicket(i)))
{
if(PositionGetInteger(POSITION_MAGIC) == magic)
{
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
double currentRSI = lastRSI[0];
if(posType == POSITION_TYPE_BUY && currentRSI <= exitBuyLevel)
{
ulong ticket = PositionGetTicket(i);
if(trade.PositionClose(ticket))
{
Print("Strategy ", magic == InpMagicNumber1 ? "1" : "2", " Buy position closed due to RSI exit level",
"\nTicket: ", ticket,
"\nRSI: ", DoubleToString(currentRSI, 2),
"\nExit Level: ", DoubleToString(exitBuyLevel, 2));
}
else
{
Print("Failed to close Strategy ", magic == InpMagicNumber1 ? "1" : "2", " Buy position",
"\nTicket: ", ticket,
"\nRSI: ", DoubleToString(currentRSI, 2),
"\nExit Level: ", DoubleToString(exitBuyLevel, 2),
"\nError: ", GetLastError());
}
}
else if(posType == POSITION_TYPE_SELL && currentRSI >= exitSellLevel)
{
ulong ticket = PositionGetTicket(i);
if(trade.PositionClose(ticket))
{
Print("Strategy ", magic == InpMagicNumber1 ? "1" : "2", " Sell position closed due to RSI exit level",
"\nTicket: ", ticket,
"\nRSI: ", DoubleToString(currentRSI, 2),
"\nExit Level: ", DoubleToString(exitSellLevel, 2));
}
else
{
Print("Failed to close Strategy ", magic == InpMagicNumber1 ? "1" : "2", " Sell position",
"\nTicket: ", ticket,
"\nRSI: ", DoubleToString(currentRSI, 2),
"\nExit Level: ", DoubleToString(exitSellLevel, 2),
"\nError: ", GetLastError());
}
}
}
}
}
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Check trading hours exits
CheckTradingHoursExits();
// Only process on new bar
if(!IsNewBar())
{
// Check trailing stops and time-based exits every tick
if(InpEnableStrategy1)
{
CheckTrailingStop(InpMagicNumber1, InpTrailingStop1, InpTrailingStep1);
CheckTimeBasedExits(InpMagicNumber1, InpMaxTradeDuration1, InpLossThreshold1);
}
if(InpEnableStrategy2)
{
CheckTrailingStop(InpMagicNumber2, InpTrailingStop2, InpTrailingStep2);
CheckTimeBasedExits(InpMagicNumber2, InpMaxTradeDuration2, InpLossThreshold2);
}
return;
}
// Check for RSI signals
CheckRSISignals();
// Get current price
double currentPrice = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
double stopLoss = 0;
double takeProfit = 0;
// Strategy 1: Enter on RSI 50 touch after oversold/overbought
if(InpEnableStrategy1)
{
if(!IsWithinTradingHours())
{
MqlDateTime timeStruct;
TimeToStruct(TimeCurrent(), timeStruct);
Print("Strategy 1: Outside trading hours",
"\nCurrent Hour: ", timeStruct.hour,
"\nTrading Hours: ", InpStartHour, ":00 - ", InpEndHour, ":00");
return;
}
// Check for RSI-based exits for Strategy 1
if(InpEnableRSIExit1)
{
CheckRSIExits(InpMagicNumber1, true, InpRSIExitBuy1, InpRSIExitSell1);
}
// Log current RSI state
Print("Strategy 1 Current State:",
"\nRSI: ", DoubleToString(lastRSI[0], 2),
"\nDistance from 50: ", DoubleToString(MathAbs(lastRSI[0] - 50), 2),
"\nWas Oversold: ", wasOversold ? "Yes" : "No",
"\nWas Overbought: ", wasOverbought ? "Yes" : "No",
"\nPosition Exists: ", PositionSelectByTicket(InpMagicNumber1) ? "Yes" : "No");
// Buy signal: RSI was oversold and now is near 50
if(wasOversold && MathAbs(lastRSI[0] - 50) <= InpRSI50Distance)
{
if(!PositionSelectByTicket(InpMagicNumber1))
{
stopLoss = InpEnableRSIExit1 && !InpUseSLTPWithRSI1 ? 0 : currentPrice - InpStopLoss1 * _Point;
takeProfit = InpEnableRSIExit1 && !InpUseSLTPWithRSI1 ? 0 : currentPrice + InpTakeProfit1 * _Point;
trade.SetExpertMagicNumber(InpMagicNumber1);
if(trade.Buy(InpLotSize1, _Symbol, 0, stopLoss, takeProfit, "RSI 50 Touch Buy"))
{
Print("Strategy 1 Buy trade executed: RSI was oversold and now near 50",
"\nRSI: ", DoubleToString(lastRSI[0], 2),
"\nDistance from 50: ", DoubleToString(MathAbs(lastRSI[0] - 50), 2),
"\nEntry Price: ", DoubleToString(currentPrice, _Digits),
"\nStop Loss: ", stopLoss == 0 ? "None" : DoubleToString(stopLoss, _Digits),
"\nTake Profit: ", takeProfit == 0 ? "None" : DoubleToString(takeProfit, _Digits));
wasOversold = false;
}
else
{
Print("Failed to execute Strategy 1 Buy trade",
"\nRSI: ", DoubleToString(lastRSI[0], 2),
"\nDistance from 50: ", DoubleToString(MathAbs(lastRSI[0] - 50), 2),
"\nError: ", GetLastError());
}
}
else
{
Print("Strategy 1 Buy signal detected but position already exists",
"\nRSI: ", DoubleToString(lastRSI[0], 2),
"\nDistance from 50: ", DoubleToString(MathAbs(lastRSI[0] - 50), 2));
}
}
// Sell signal: RSI was overbought and now is near 50
if(wasOverbought && MathAbs(lastRSI[0] - 50) <= InpRSI50Distance)
{
if(!PositionSelectByTicket(InpMagicNumber1))
{
stopLoss = InpEnableRSIExit1 && !InpUseSLTPWithRSI1 ? 0 : currentPrice + InpStopLoss1 * _Point;
takeProfit = InpEnableRSIExit1 && !InpUseSLTPWithRSI1 ? 0 : currentPrice - InpTakeProfit1 * _Point;
trade.SetExpertMagicNumber(InpMagicNumber1);
if(trade.Sell(InpLotSize1, _Symbol, 0, stopLoss, takeProfit, "RSI 50 Touch Sell"))
{
Print("Strategy 1 Sell trade executed: RSI was overbought and now near 50",
"\nRSI: ", DoubleToString(lastRSI[0], 2),
"\nDistance from 50: ", DoubleToString(MathAbs(lastRSI[0] - 50), 2),
"\nEntry Price: ", DoubleToString(currentPrice, _Digits),
"\nStop Loss: ", stopLoss == 0 ? "None" : DoubleToString(stopLoss, _Digits),
"\nTake Profit: ", takeProfit == 0 ? "None" : DoubleToString(takeProfit, _Digits));
wasOverbought = false;
}
else
{
Print("Failed to execute Strategy 1 Sell trade",
"\nRSI: ", DoubleToString(lastRSI[0], 2),
"\nDistance from 50: ", DoubleToString(MathAbs(lastRSI[0] - 50), 2),
"\nError: ", GetLastError());
}
}
else
{
Print("Strategy 1 Sell signal detected but position already exists",
"\nRSI: ", DoubleToString(lastRSI[0], 2),
"\nDistance from 50: ", DoubleToString(MathAbs(lastRSI[0] - 50), 2));
}
}
}
// Strategy 2: Enter on RSI reversal from extremes
if(InpEnableStrategy2 && IsWithinTradingHours())
{
// Check for RSI-based exits for Strategy 2
if(InpEnableRSIExit2)
{
CheckRSIExits(InpMagicNumber2, true, InpRSIExitBuy2, InpRSIExitSell2);
}
// Sell signal: RSI was overbought and now is moving down
if(wasOverbought && lastRSI[0] < lastRSI[1] && !PositionSelectByTicket(InpMagicNumber2))
{
stopLoss = InpEnableRSIExit2 && !InpUseSLTPWithRSI2 ? 0 : currentPrice + InpStopLoss2 * _Point;
takeProfit = InpEnableRSIExit2 && !InpUseSLTPWithRSI2 ? 0 : currentPrice - InpTakeProfit2 * _Point;
trade.SetExpertMagicNumber(InpMagicNumber2);
trade.Sell(InpLotSize2, _Symbol, 0, stopLoss, takeProfit, "RSI Reversal Sell");
}
// Buy signal: RSI was oversold and now is moving up
if(wasOversold && lastRSI[0] > lastRSI[1] && !PositionSelectByTicket(InpMagicNumber2))
{
stopLoss = InpEnableRSIExit2 && !InpUseSLTPWithRSI2 ? 0 : currentPrice - InpStopLoss2 * _Point;
takeProfit = InpEnableRSIExit2 && !InpUseSLTPWithRSI2 ? 0 : currentPrice + InpTakeProfit2 * _Point;
trade.SetExpertMagicNumber(InpMagicNumber2);
trade.Buy(InpLotSize2, _Symbol, 0, stopLoss, takeProfit, "RSI Reversal Buy");
}
}
// Check trailing stops and time-based exits
if(InpEnableStrategy1)
{
CheckTrailingStop(InpMagicNumber1, InpTrailingStop1, InpTrailingStep1);
CheckTimeBasedExits(InpMagicNumber1, InpMaxTradeDuration1, InpLossThreshold1);
}
if(InpEnableStrategy2)
{
CheckTrailingStop(InpMagicNumber2, InpTrailingStop2, InpTrailingStep2);
CheckTimeBasedExits(InpMagicNumber2, InpMaxTradeDuration2, InpLossThreshold2);
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 KiB

-352
View File
@@ -1,352 +0,0 @@
//+------------------------------------------------------------------+
//| SmartRSI.mq5 |
//| Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include <Trade\Trade.mqh>
// Input parameters for RSI
input group "RSI Settings"
input int RSI_Period = 125; // RSI Period
input ENUM_APPLIED_PRICE RSI_Price = PRICE_MEDIAN; // RSI Applied Price
// Strategy Selection
input group "Strategy Selection"
input bool UseTrendFollowing = false; // Use Trend Following Strategy
input bool UseReversal = true; // Use Reversal Strategy
// Time Frames
input group "Time Frames"
input ENUM_TIMEFRAMES Trend_TimeFrame = PERIOD_H12; // Trend Following Time Frame
input ENUM_TIMEFRAMES Rev_TimeFrame = PERIOD_M6; // Reversal Time Frame
// Enum for RSI conditions
enum ENUM_RSI_CONDITION
{
RSI_BELOW_OVERSOLD, // RSI below oversold level
RSI_ABOVE_OVERBOUGHT, // RSI above overbought level
RSI_BELOW_MIDPOINT, // RSI below midpoint
RSI_ABOVE_MIDPOINT, // RSI above midpoint
RSI_CROSS_OVERSOLD, // RSI crosses below oversold
RSI_CROSS_OVERBOUGHT // RSI crosses above overbought
};
// Entry/Exit Conditions
input group "Entry/Exit Conditions"
input ENUM_RSI_CONDITION Trend_Entry_Condition = RSI_BELOW_OVERSOLD; // Trend Entry Condition
input ENUM_RSI_CONDITION Trend_Exit_Condition = RSI_BELOW_MIDPOINT; // Trend Exit Condition
input ENUM_RSI_CONDITION Rev_Entry_Condition = RSI_CROSS_OVERSOLD; // Reversal Entry Condition
input ENUM_RSI_CONDITION Rev_Exit_Condition = RSI_BELOW_MIDPOINT; // Reversal Exit Condition
// Trend Following Strategy Parameters
input group "Trend Following Strategy"
input double Trend_Overbought = 11; // Overbought level for trend following
input double Trend_Oversold = 26; // Oversold level for trend following
input double Trend_Exit_Long = 50; // Exit level for long positions
input double Trend_Exit_Short = 50; // Exit level for short positions
input double Trend_LotSize = 0.09; // Lot size for trend following
input int Trend_Magic = 12345; // Magic number for trend following
input bool Trend_CloseOpposite = false; // Close opposite trades on profit
input double Trend_ProfitToClose = 180; // Profit in points to close opposite trades
input int Trend_TimeToClose = 1; // Bars to wait before closing opposite trades
// Reversal Strategy Parameters
input group "Reversal Strategy"
input double Rev_Overbought = 60; // Overbought level for reversal
input double Rev_Oversold = 226; // Oversold level for reversal
input double Rev_Exit_Long = 50; // Exit level for long positions
input double Rev_Exit_Short = 50; // Exit level for short positions
input double Rev_LotSize = 0.06; // Lot size for reversal
input int Rev_Magic = 54321; // Magic number for reversal
input bool Rev_CloseOpposite = true; // Close opposite trades on profit
input double Rev_ProfitToClose = 105; // Profit in points to close opposite trades
input int Rev_TimeToClose = 5; // Bars to wait before closing opposite trades
// Indicator buffers
double trend_rsi_buffer[];
double rev_rsi_buffer[];
int trend_rsi_handle;
int rev_rsi_handle;
CTrade trade;
datetime last_trend_bar_time;
datetime last_rev_bar_time;
datetime trend_long_entry_time = 0;
datetime trend_short_entry_time = 0;
datetime rev_long_entry_time = 0;
datetime rev_short_entry_time = 0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Initialize RSI indicators
trend_rsi_handle = iRSI(_Symbol, Trend_TimeFrame, RSI_Period, RSI_Price);
rev_rsi_handle = iRSI(_Symbol, Rev_TimeFrame, RSI_Period, RSI_Price);
if(trend_rsi_handle == INVALID_HANDLE || rev_rsi_handle == INVALID_HANDLE)
{
Print("Failed to create RSI indicators");
return INIT_FAILED;
}
// Set buffer size and series
ArraySetAsSeries(trend_rsi_buffer, true);
ArraySetAsSeries(rev_rsi_buffer, true);
// Initialize trade object
trade.SetExpertMagicNumber(Trend_Magic);
trade.SetMarginMode();
trade.SetTypeFillingBySymbol(_Symbol);
trade.SetDeviationInPoints(10);
// Initialize last bar times
last_trend_bar_time = 0;
last_rev_bar_time = 0;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(trend_rsi_handle != INVALID_HANDLE)
IndicatorRelease(trend_rsi_handle);
if(rev_rsi_handle != INVALID_HANDLE)
IndicatorRelease(rev_rsi_handle);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
datetime current_trend_time = iTime(_Symbol, Trend_TimeFrame, 0);
datetime current_rev_time = iTime(_Symbol, Rev_TimeFrame, 0);
// Check if new bar has formed for trend following
if(current_trend_time != last_trend_bar_time)
{
last_trend_bar_time = current_trend_time;
// Update RSI values for trend following
if(CopyBuffer(trend_rsi_handle, 0, 0, 2, trend_rsi_buffer) <= 0)
{
Print("Failed to copy trend RSI buffer");
return;
}
// Run trend following strategy if enabled
if(UseTrendFollowing)
CheckTrendFollowing();
}
// Check if new bar has formed for reversal
if(current_rev_time != last_rev_bar_time)
{
last_rev_bar_time = current_rev_time;
// Update RSI values for reversal
if(CopyBuffer(rev_rsi_handle, 0, 0, 2, rev_rsi_buffer) <= 0)
{
Print("Failed to copy reversal RSI buffer");
return;
}
// Run reversal strategy if enabled
if(UseReversal)
CheckReversal();
}
}
//+------------------------------------------------------------------+
//| Check RSI Condition |
//+------------------------------------------------------------------+
bool CheckRSICondition(ENUM_RSI_CONDITION condition, double level, double &buffer[])
{
switch(condition)
{
case RSI_BELOW_OVERSOLD:
return buffer[0] < level;
case RSI_ABOVE_OVERBOUGHT:
return buffer[0] > level;
case RSI_BELOW_MIDPOINT:
return buffer[0] < 50;
case RSI_ABOVE_MIDPOINT:
return buffer[0] > 50;
case RSI_CROSS_OVERSOLD:
return buffer[0] < level && buffer[1] >= level;
case RSI_CROSS_OVERBOUGHT:
return buffer[0] > level && buffer[1] <= level;
}
return false;
}
//+------------------------------------------------------------------+
//| Check Trend Following Strategy |
//+------------------------------------------------------------------+
void CheckTrendFollowing()
{
// Check for existing positions
bool hasLong = PositionSelectByMagic(Trend_Magic, POSITION_TYPE_BUY);
bool hasShort = PositionSelectByMagic(Trend_Magic, POSITION_TYPE_SELL);
// Entry logic
if(!hasLong && !hasShort)
{
if(CheckRSICondition(Trend_Entry_Condition, Trend_Oversold, trend_rsi_buffer))
{
// Open short position
trade.SetExpertMagicNumber(Trend_Magic);
trade.Sell(Trend_LotSize, _Symbol, 0, 0, 0, "SmartRSI Trend");
trend_short_entry_time = TimeCurrent();
}
else if(CheckRSICondition(Trend_Entry_Condition, Trend_Overbought, trend_rsi_buffer))
{
// Open long position
trade.SetExpertMagicNumber(Trend_Magic);
trade.Buy(Trend_LotSize, _Symbol, 0, 0, 0, "SmartRSI Trend");
trend_long_entry_time = TimeCurrent();
}
}
// Exit logic
if(hasLong && CheckRSICondition(Trend_Exit_Condition, Trend_Exit_Long, trend_rsi_buffer))
{
trade.SetExpertMagicNumber(Trend_Magic);
trade.PositionClose(_Symbol);
}
else if(hasShort && CheckRSICondition(Trend_Exit_Condition, Trend_Exit_Short, trend_rsi_buffer))
{
trade.SetExpertMagicNumber(Trend_Magic);
trade.PositionClose(_Symbol);
}
// Check for opposite trade closing
if(Trend_CloseOpposite)
{
if(hasLong && (TimeCurrent() - trend_long_entry_time) >= Trend_TimeToClose * PeriodSeconds(Trend_TimeFrame))
{
double profit = PositionGetDouble(POSITION_PROFIT);
if(profit >= Trend_ProfitToClose * _Point)
{
// Close short position if exists
if(PositionSelectByMagic(Trend_Magic, POSITION_TYPE_SELL))
{
trade.SetExpertMagicNumber(Trend_Magic);
trade.PositionClose(_Symbol);
}
}
}
else if(hasShort && (TimeCurrent() - trend_short_entry_time) >= Trend_TimeToClose * PeriodSeconds(Trend_TimeFrame))
{
double profit = PositionGetDouble(POSITION_PROFIT);
if(profit >= Trend_ProfitToClose * _Point)
{
// Close long position if exists
if(PositionSelectByMagic(Trend_Magic, POSITION_TYPE_BUY))
{
trade.SetExpertMagicNumber(Trend_Magic);
trade.PositionClose(_Symbol);
}
}
}
}
}
//+------------------------------------------------------------------+
//| Check Reversal Strategy |
//+------------------------------------------------------------------+
void CheckReversal()
{
// Check for existing positions
bool hasLong = PositionSelectByMagic(Rev_Magic, POSITION_TYPE_BUY);
bool hasShort = PositionSelectByMagic(Rev_Magic, POSITION_TYPE_SELL);
// Entry logic
if(!hasLong && !hasShort)
{
if(CheckRSICondition(Rev_Entry_Condition, Rev_Oversold, rev_rsi_buffer))
{
// Open long position
trade.SetExpertMagicNumber(Rev_Magic);
trade.Buy(Rev_LotSize, _Symbol, 0, 0, 0, "SmartRSI Reversal");
rev_long_entry_time = TimeCurrent();
}
else if(CheckRSICondition(Rev_Entry_Condition, Rev_Overbought, rev_rsi_buffer))
{
// Open short position
trade.SetExpertMagicNumber(Rev_Magic);
trade.Sell(Rev_LotSize, _Symbol, 0, 0, 0, "SmartRSI Reversal");
rev_short_entry_time = TimeCurrent();
}
}
// Exit logic
if(hasLong && CheckRSICondition(Rev_Exit_Condition, Rev_Exit_Long, rev_rsi_buffer))
{
trade.SetExpertMagicNumber(Rev_Magic);
trade.PositionClose(_Symbol);
}
else if(hasShort && CheckRSICondition(Rev_Exit_Condition, Rev_Exit_Short, rev_rsi_buffer))
{
trade.SetExpertMagicNumber(Rev_Magic);
trade.PositionClose(_Symbol);
}
// Check for opposite trade closing
if(Rev_CloseOpposite)
{
if(hasLong && (TimeCurrent() - rev_long_entry_time) >= Rev_TimeToClose * PeriodSeconds(Rev_TimeFrame))
{
double profit = PositionGetDouble(POSITION_PROFIT);
if(profit >= Rev_ProfitToClose * _Point)
{
// Close short position if exists
if(PositionSelectByMagic(Rev_Magic, POSITION_TYPE_SELL))
{
trade.SetExpertMagicNumber(Rev_Magic);
trade.PositionClose(_Symbol);
}
}
}
else if(hasShort && (TimeCurrent() - rev_short_entry_time) >= Rev_TimeToClose * PeriodSeconds(Rev_TimeFrame))
{
double profit = PositionGetDouble(POSITION_PROFIT);
if(profit >= Rev_ProfitToClose * _Point)
{
// Close long position if exists
if(PositionSelectByMagic(Rev_Magic, POSITION_TYPE_BUY))
{
trade.SetExpertMagicNumber(Rev_Magic);
trade.PositionClose(_Symbol);
}
}
}
}
}
//+------------------------------------------------------------------+
//| Position Select By Magic |
//+------------------------------------------------------------------+
bool PositionSelectByMagic(int magic, ENUM_POSITION_TYPE posType)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(PositionGetTicket(i))
{
if(PositionGetInteger(POSITION_MAGIC) == magic &&
PositionGetInteger(POSITION_TYPE) == posType)
{
return true;
}
}
}
return false;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 KiB

-325
View File
@@ -1,325 +0,0 @@
//+------------------------------------------------------------------+
//| SmartRSI.mq5 |
//| Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#include <Trade\Trade.mqh>
// Input parameters for RSI
input group "RSI Settings"
input int RSI_Period = 89; // RSI Period
input ENUM_APPLIED_PRICE RSI_Price = PRICE_TYPICAL; // RSI Applied Price
// Strategy Selection
input group "Strategy Selection"
input bool UseTrendFollowing = true; // Use Trend Following Strategy
input bool UseReversal = false; // Use Reversal Strategy
// Enum for RSI conditions
enum ENUM_RSI_CONDITION
{
RSI_BELOW_OVERSOLD, // RSI below oversold level
RSI_ABOVE_OVERBOUGHT, // RSI above overbought level
RSI_BELOW_MIDPOINT, // RSI below midpoint
RSI_ABOVE_MIDPOINT, // RSI above midpoint
RSI_CROSS_OVERSOLD, // RSI crosses below oversold
RSI_CROSS_OVERBOUGHT // RSI crosses above overbought
};
// Entry/Exit Conditions
input group "Entry/Exit Conditions"
input ENUM_RSI_CONDITION Trend_Entry_Condition = RSI_BELOW_OVERSOLD; // Trend Entry Condition
input ENUM_RSI_CONDITION Trend_Exit_Condition = RSI_ABOVE_MIDPOINT; // Trend Exit Condition
input ENUM_RSI_CONDITION Rev_Entry_Condition = RSI_BELOW_OVERSOLD; // Reversal Entry Condition
input ENUM_RSI_CONDITION Rev_Exit_Condition = RSI_ABOVE_MIDPOINT; // Reversal Exit Condition
// Trend Following Strategy Parameters
input group "Trend Following Strategy"
input double Trend_Overbought = 51; // Overbought level for trend following
input double Trend_Oversold = 30; // Oversold level for trend following
input double Trend_Exit_Long = 50; // Exit level for long positions
input double Trend_Exit_Short = 50; // Exit level for short positions
input double Trend_LotSize = 0.1; // Lot size for trend following
input int Trend_Magic = 12345; // Magic number for trend following
input bool Trend_CloseOpposite = true; // Close opposite trades on profit
input double Trend_ProfitToClose = 15; // Profit in points to close opposite trades
input int Trend_TimeToClose = 9; // Bars to wait before closing opposite trades
// Reversal Strategy Parameters
input group "Reversal Strategy"
input double Rev_Overbought = 70; // Overbought level for reversal
input double Rev_Oversold = 30; // Oversold level for reversal
input double Rev_Exit_Long = 50; // Exit level for long positions
input double Rev_Exit_Short = 50; // Exit level for short positions
input double Rev_LotSize = 0.1; // Lot size for reversal
input int Rev_Magic = 54321; // Magic number for reversal
input bool Rev_CloseOpposite = true; // Close opposite trades on profit
input double Rev_ProfitToClose = 50; // Profit in points to close opposite trades
input int Rev_TimeToClose = 5; // Bars to wait before closing opposite trades
// Indicator buffers
double rsi_buffer[];
int rsi_handle;
CTrade trade;
datetime last_bar_time;
datetime trend_long_entry_time = 0;
datetime trend_short_entry_time = 0;
datetime rev_long_entry_time = 0;
datetime rev_short_entry_time = 0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Initialize RSI indicator
rsi_handle = iRSI(_Symbol, PERIOD_CURRENT, RSI_Period, RSI_Price);
if(rsi_handle == INVALID_HANDLE)
{
Print("Failed to create RSI indicator");
return INIT_FAILED;
}
// Set buffer size and series
ArraySetAsSeries(rsi_buffer, true);
// Initialize trade object
trade.SetExpertMagicNumber(Trend_Magic);
trade.SetMarginMode();
trade.SetTypeFillingBySymbol(_Symbol);
trade.SetDeviationInPoints(10);
// Initialize last bar time
last_bar_time = 0;
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(rsi_handle != INVALID_HANDLE)
IndicatorRelease(rsi_handle);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
datetime current_time = iTime(_Symbol, PERIOD_CURRENT, 0);
// Check if new bar has formed
if(current_time != last_bar_time)
{
last_bar_time = current_time;
// Update RSI values
if(CopyBuffer(rsi_handle, 0, 0, 2, rsi_buffer) <= 0)
{
Print("Failed to copy RSI buffer");
return;
}
// Run strategies if enabled
if(UseTrendFollowing)
CheckTrendFollowing();
if(UseReversal)
CheckReversal();
}
}
//+------------------------------------------------------------------+
//| Check RSI Condition |
//+------------------------------------------------------------------+
bool CheckRSICondition(ENUM_RSI_CONDITION condition, double level)
{
switch(condition)
{
case RSI_BELOW_OVERSOLD:
return rsi_buffer[0] < level;
case RSI_ABOVE_OVERBOUGHT:
return rsi_buffer[0] > level;
case RSI_BELOW_MIDPOINT:
return rsi_buffer[0] < 50;
case RSI_ABOVE_MIDPOINT:
return rsi_buffer[0] > 50;
case RSI_CROSS_OVERSOLD:
return rsi_buffer[0] < level && rsi_buffer[1] >= level;
case RSI_CROSS_OVERBOUGHT:
return rsi_buffer[0] > level && rsi_buffer[1] <= level;
}
return false;
}
//+------------------------------------------------------------------+
//| Check Trend Following Strategy |
//+------------------------------------------------------------------+
void CheckTrendFollowing()
{
// Check for existing positions
bool hasLong = PositionSelectByMagic(Trend_Magic, POSITION_TYPE_BUY);
bool hasShort = PositionSelectByMagic(Trend_Magic, POSITION_TYPE_SELL);
// Entry logic
if(!hasLong && !hasShort)
{
if(CheckRSICondition(Trend_Entry_Condition, Trend_Oversold))
{
// Open short position
trade.SetExpertMagicNumber(Trend_Magic);
trade.Sell(Trend_LotSize, _Symbol, 0, 0, 0, "SmartRSI Trend");
trend_short_entry_time = TimeCurrent();
}
else if(CheckRSICondition(Trend_Entry_Condition, Trend_Overbought))
{
// Open long position
trade.SetExpertMagicNumber(Trend_Magic);
trade.Buy(Trend_LotSize, _Symbol, 0, 0, 0, "SmartRSI Trend");
trend_long_entry_time = TimeCurrent();
}
}
// Exit logic
if(hasLong && CheckRSICondition(Trend_Exit_Condition, Trend_Exit_Long))
{
trade.SetExpertMagicNumber(Trend_Magic);
trade.PositionClose(_Symbol);
}
else if(hasShort && CheckRSICondition(Trend_Exit_Condition, Trend_Exit_Short))
{
trade.SetExpertMagicNumber(Trend_Magic);
trade.PositionClose(_Symbol);
}
// Check for opposite trade closing
if(Trend_CloseOpposite)
{
if(hasLong && (TimeCurrent() - trend_long_entry_time) >= Trend_TimeToClose * PeriodSeconds(PERIOD_CURRENT))
{
double profit = PositionGetDouble(POSITION_PROFIT);
if(profit >= Trend_ProfitToClose * _Point)
{
// Close short position if exists
if(PositionSelectByMagic(Trend_Magic, POSITION_TYPE_SELL))
{
trade.SetExpertMagicNumber(Trend_Magic);
trade.PositionClose(_Symbol);
}
}
}
else if(hasShort && (TimeCurrent() - trend_short_entry_time) >= Trend_TimeToClose * PeriodSeconds(PERIOD_CURRENT))
{
double profit = PositionGetDouble(POSITION_PROFIT);
if(profit >= Trend_ProfitToClose * _Point)
{
// Close long position if exists
if(PositionSelectByMagic(Trend_Magic, POSITION_TYPE_BUY))
{
trade.SetExpertMagicNumber(Trend_Magic);
trade.PositionClose(_Symbol);
}
}
}
}
}
//+------------------------------------------------------------------+
//| Check Reversal Strategy |
//+------------------------------------------------------------------+
void CheckReversal()
{
// Check for existing positions
bool hasLong = PositionSelectByMagic(Rev_Magic, POSITION_TYPE_BUY);
bool hasShort = PositionSelectByMagic(Rev_Magic, POSITION_TYPE_SELL);
// Entry logic
if(!hasLong && !hasShort)
{
if(CheckRSICondition(Rev_Entry_Condition, Rev_Oversold))
{
// Open long position
trade.SetExpertMagicNumber(Rev_Magic);
trade.Buy(Rev_LotSize, _Symbol, 0, 0, 0, "SmartRSI Reversal");
rev_long_entry_time = TimeCurrent();
}
else if(CheckRSICondition(Rev_Entry_Condition, Rev_Overbought))
{
// Open short position
trade.SetExpertMagicNumber(Rev_Magic);
trade.Sell(Rev_LotSize, _Symbol, 0, 0, 0, "SmartRSI Reversal");
rev_short_entry_time = TimeCurrent();
}
}
// Exit logic
if(hasLong && CheckRSICondition(Rev_Exit_Condition, Rev_Exit_Long))
{
trade.SetExpertMagicNumber(Rev_Magic);
trade.PositionClose(_Symbol);
}
else if(hasShort && CheckRSICondition(Rev_Exit_Condition, Rev_Exit_Short))
{
trade.SetExpertMagicNumber(Rev_Magic);
trade.PositionClose(_Symbol);
}
// Check for opposite trade closing
if(Rev_CloseOpposite)
{
if(hasLong && (TimeCurrent() - rev_long_entry_time) >= Rev_TimeToClose * PeriodSeconds(PERIOD_CURRENT))
{
double profit = PositionGetDouble(POSITION_PROFIT);
if(profit >= Rev_ProfitToClose * _Point)
{
// Close short position if exists
if(PositionSelectByMagic(Rev_Magic, POSITION_TYPE_SELL))
{
trade.SetExpertMagicNumber(Rev_Magic);
trade.PositionClose(_Symbol);
}
}
}
else if(hasShort && (TimeCurrent() - rev_short_entry_time) >= Rev_TimeToClose * PeriodSeconds(PERIOD_CURRENT))
{
double profit = PositionGetDouble(POSITION_PROFIT);
if(profit >= Rev_ProfitToClose * _Point)
{
// Close long position if exists
if(PositionSelectByMagic(Rev_Magic, POSITION_TYPE_BUY))
{
trade.SetExpertMagicNumber(Rev_Magic);
trade.PositionClose(_Symbol);
}
}
}
}
}
//+------------------------------------------------------------------+
//| Position Select By Magic |
//+------------------------------------------------------------------+
bool PositionSelectByMagic(int magic, ENUM_POSITION_TYPE posType)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(PositionGetTicket(i))
{
if(PositionGetInteger(POSITION_MAGIC) == magic &&
PositionGetInteger(POSITION_TYPE) == posType)
{
return true;
}
}
}
return false;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 300 KiB