Ditch not profitable EA, add profitable ones

This commit is contained in:
zhutoutoutousan
2025-04-22 04:39:54 +08:00
parent 809f30ba55
commit 7cb09b3c9b
27 changed files with 371 additions and 3509 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

+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