diff --git a/EMACrossOverBTC/main.mq5 b/EMACrossOverBTC/main.mq5 deleted file mode 100644 index 51f3569..0000000 --- a/EMACrossOverBTC/main.mq5 +++ /dev/null @@ -1,426 +0,0 @@ -//+------------------------------------------------------------------+ -//| ScoringTrade.mq5 | -//| Generated by ChatGPT | -//| | -//+------------------------------------------------------------------+ -#property strict -#include - -// 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 -} diff --git a/EMACrossOverBTC/test-balance.jpg b/EMACrossOverBTC/test-balance.jpg deleted file mode 100644 index 0e51e4f..0000000 Binary files a/EMACrossOverBTC/test-balance.jpg and /dev/null differ diff --git a/EMACrossOverSkirmish/main.mq5 b/EMACrossOverSkirmish/main.mq5 deleted file mode 100644 index 2ecebfe..0000000 --- a/EMACrossOverSkirmish/main.mq5 +++ /dev/null @@ -1,456 +0,0 @@ -//+------------------------------------------------------------------+ -//| ScoringTrade.mq5 | -//| Generated by ChatGPT | -//| | -//+------------------------------------------------------------------+ -#property strict -#include - -// 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 -} diff --git a/EMACrossOverSkirmish/test-balance.jpg b/EMACrossOverSkirmish/test-balance.jpg deleted file mode 100644 index cbff813..0000000 Binary files a/EMACrossOverSkirmish/test-balance.jpg and /dev/null differ diff --git a/RSICrossOverReversalXAUUSD/main.mq5 b/RSICrossOverReversalXAUUSD/main.mq5 new file mode 100644 index 0000000..5c004da --- /dev/null +++ b/RSICrossOverReversalXAUUSD/main.mq5 @@ -0,0 +1,315 @@ +// Input Parameters +#include + +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; +} \ No newline at end of file diff --git a/RSICrossOverReversalXAUUSD/test-balance.jpg b/RSICrossOverReversalXAUUSD/test-balance.jpg new file mode 100644 index 0000000..a78fe1c Binary files /dev/null and b/RSICrossOverReversalXAUUSD/test-balance.jpg differ diff --git a/RSIDivergenceExtremaAUDUSD/main.mq5 b/RSIDivergenceExtremaAUDUSD/main.mq5 deleted file mode 100644 index edde8be..0000000 --- a/RSIDivergenceExtremaAUDUSD/main.mq5 +++ /dev/null @@ -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 // 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; -} -//+------------------------------------------------------------------+ diff --git a/RSIDivergenceExtremaAUDUSD/test-balance.jpg b/RSIDivergenceExtremaAUDUSD/test-balance.jpg deleted file mode 100644 index fcc5804..0000000 Binary files a/RSIDivergenceExtremaAUDUSD/test-balance.jpg and /dev/null differ diff --git a/RSIDivergenceExtremaEURUSD/main.mq5 b/RSIDivergenceExtremaEURUSD/main.mq5 deleted file mode 100644 index f6f6c4a..0000000 --- a/RSIDivergenceExtremaEURUSD/main.mq5 +++ /dev/null @@ -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 // 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; -} -//+------------------------------------------------------------------+ diff --git a/RSIDivergenceExtremaEURUSD/test-balance.jpg b/RSIDivergenceExtremaEURUSD/test-balance.jpg deleted file mode 100644 index 8ff0293..0000000 Binary files a/RSIDivergenceExtremaEURUSD/test-balance.jpg and /dev/null differ diff --git a/RSIDivergenceRebound/balance-2008.jpg b/RSIDivergenceRebound/balance-2008.jpg deleted file mode 100644 index 9674f42..0000000 Binary files a/RSIDivergenceRebound/balance-2008.jpg and /dev/null differ diff --git a/RSIDivergenceRebound/main.mq5 b/RSIDivergenceRebound/main.mq5 deleted file mode 100644 index 741bd8d..0000000 --- a/RSIDivergenceRebound/main.mq5 +++ /dev/null @@ -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); - } - } -} diff --git a/RSIDivergenceRebound/test-balance.jpg b/RSIDivergenceRebound/test-balance.jpg deleted file mode 100644 index 91fe42c..0000000 Binary files a/RSIDivergenceRebound/test-balance.jpg and /dev/null differ diff --git a/RSIMidPointHijack/test-balance.jpg b/RSIMidPointHijack/test-balance.jpg deleted file mode 100644 index 6b96132..0000000 Binary files a/RSIMidPointHijack/test-balance.jpg and /dev/null differ diff --git a/RSIMidPointHijack/main.mq5 b/RSIMidPointHijackXAUUSD/main.mq5 similarity index 95% rename from RSIMidPointHijack/main.mq5 rename to RSIMidPointHijackXAUUSD/main.mq5 index 296d752..f9ebcd8 100644 --- a/RSIMidPointHijack/main.mq5 +++ b/RSIMidPointHijackXAUUSD/main.mq5 @@ -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; diff --git a/RSIMidPointHijackXAUUSD/test-balance.jpg b/RSIMidPointHijackXAUUSD/test-balance.jpg new file mode 100644 index 0000000..b1ef58d Binary files /dev/null and b/RSIMidPointHijackXAUUSD/test-balance.jpg differ diff --git a/RSIReversalAsianAUDUSD/main.mq5 b/RSIReversalAsianAUDUSD/main.mq5 index 96471dc..11057dc 100644 --- a/RSIReversalAsianAUDUSD/main.mq5 +++ b/RSIReversalAsianAUDUSD/main.mq5 @@ -12,16 +12,16 @@ #include // 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) diff --git a/RSIReversalAsianAUDUSD/test-balance.jpg b/RSIReversalAsianAUDUSD/test-balance.jpg index 1255eba..67cce46 100644 Binary files a/RSIReversalAsianAUDUSD/test-balance.jpg and b/RSIReversalAsianAUDUSD/test-balance.jpg differ diff --git a/RSIReversalAsianEURUSD/main.mq5 b/RSIReversalAsianEURUSD/main.mq5 index 414a69b..4b2c919 100644 --- a/RSIReversalAsianEURUSD/main.mq5 +++ b/RSIReversalAsianEURUSD/main.mq5 @@ -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")) diff --git a/RSIReversalAsianEURUSD/test-balance-2016.jpg b/RSIReversalAsianEURUSD/test-balance-2016.jpg deleted file mode 100644 index 7de4e56..0000000 Binary files a/RSIReversalAsianEURUSD/test-balance-2016.jpg and /dev/null differ diff --git a/RSIReversalAsianEURUSD/test-balance.jpg b/RSIReversalAsianEURUSD/test-balance.jpg index c3695c2..605452b 100644 Binary files a/RSIReversalAsianEURUSD/test-balance.jpg and b/RSIReversalAsianEURUSD/test-balance.jpg differ diff --git a/RSIReverseFollowAUDUSD/main.mq5 b/RSIReverseFollowAUDUSD/main.mq5 deleted file mode 100644 index 084ae07..0000000 --- a/RSIReverseFollowAUDUSD/main.mq5 +++ /dev/null @@ -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 - -// 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); - } -} diff --git a/RSIReverseFollowAUDUSD/test-balance.jpg b/RSIReverseFollowAUDUSD/test-balance.jpg deleted file mode 100644 index abdd824..0000000 Binary files a/RSIReverseFollowAUDUSD/test-balance.jpg and /dev/null differ diff --git a/SmartRSIAUDUSD/main.mq5 b/SmartRSIAUDUSD/main.mq5 deleted file mode 100644 index dc3e87a..0000000 --- a/SmartRSIAUDUSD/main.mq5 +++ /dev/null @@ -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 - -// 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; -} diff --git a/SmartRSIAUDUSD/test-balance.jpg b/SmartRSIAUDUSD/test-balance.jpg deleted file mode 100644 index 181e8e1..0000000 Binary files a/SmartRSIAUDUSD/test-balance.jpg and /dev/null differ diff --git a/SmartRSIBTC/main.mq5 b/SmartRSIBTC/main.mq5 deleted file mode 100644 index 78f739b..0000000 --- a/SmartRSIBTC/main.mq5 +++ /dev/null @@ -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 - -// 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; -} diff --git a/SmartRSIBTC/test-balance.jpg b/SmartRSIBTC/test-balance.jpg deleted file mode 100644 index e459c64..0000000 Binary files a/SmartRSIBTC/test-balance.jpg and /dev/null differ