diff --git a/README.md b/README.md
index 089e69e..ad12523 100644
--- a/README.md
+++ b/README.md
@@ -7,6 +7,7 @@
- [2. RSI MidPoint Hijack XAU/USD](#2-rsi-midpoint-hijack-xauusd)
- [3. RSI Reversal Asian EUR/USD](#3-rsi-reversal-asian-eurusd)
- [4. RSI CrossOver Reversal XAU/USD](#4-rsi-crossover-reversal-xauusd)
+ - [5. RSI Follow Reverse EMA CrossOver BTC/USD](#5-rsi-follow-reverse-ema-crossover-btcusd)
- [Strategy Rationale](#strategy-rationale)
- [RSI Reversal Strategy](#rsi-reversal-strategy)
- [RSI MidPoint Hijack Strategy](#rsi-midpoint-hijack-strategy)
@@ -141,6 +142,47 @@ TrailingStop = 295; // Trailing stop in pips
+### 5. RSI Follow Reverse EMA CrossOver BTC/USD
+- **Strategy**: Multi-strategy approach combining RSI Follow, RSI Reverse, and EMA crossovers
+- **Key Features**:
+ - Implements three distinct strategies:
+ 1. RSI Follow Strategy
+ 2. RSI Reverse Strategy
+ 3. EMA Cross Strategy
+ - Optimized for Bitcoin (BTC/USD) trading
+ - Includes strategy locking mechanism to protect profits
+ - Features cooldown periods after losses
+ - Time-based trading windows for each strategy
+ - Adaptive position sizing based on volatility
+
+**Core Parameters:**
+```mql5
+// RSI Follow Strategy
+InpRSIPeriod = 14; // RSI Period
+InpRSIOverbought = 70; // RSI Overbought Level
+InpRSIOversold = 30; // RSI Oversold Level
+
+// RSI Reverse Strategy
+InpRSIReversePeriod = 14; // RSI Period
+InpRSIReverseOverbought = 80; // RSI Overbought Level
+InpRSIReverseOversold = 20; // RSI Oversold Level
+
+// EMA Settings
+InpEMAPeriod = 200; // EMA Period
+InpEMASlopeThreshold = 0.1; // EMA Slope Threshold
+InpEMADistanceThreshold = 100; // EMA Distance Threshold
+
+// Strategy Management
+InpEnableStrategyLock = true; // Enable Strategy Lock
+InpLockProfitThreshold = 1000; // Lock Profit Threshold (pips)
+InpCooldownPeriod = 24; // Cooldown Period in hours
+```
+
+**Test Balance Results:**
+
+

+
+
## Strategy Rationale
### RSI Reversal Strategy
diff --git a/RSIFollowReverseEMACrossOverBTCUSD/main.mq5 b/RSIFollowReverseEMACrossOverBTCUSD/main.mq5
new file mode 100644
index 0000000..7a76130
--- /dev/null
+++ b/RSIFollowReverseEMACrossOverBTCUSD/main.mq5
@@ -0,0 +1,586 @@
+//+------------------------------------------------------------------+
+//| RSIFollowReverseEMACrossOver.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
+#include
+
+// Input Parameters
+input group "General Settings"
+input ENUM_TIMEFRAMES InpTimeframe = PERIOD_CURRENT; // 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 = true; // Enable RSI Follow Strategy
+input bool InpEnableRSIReverse = true; // Enable RSI Reverse Strategy
+input bool InpEnableEMACross = true; // Enable EMA Cross Strategy
+input bool InpEnableStrategyLock = false; // Enable Strategy Lock
+input double InpLockProfitThreshold = 120.0; // Lock Profit Threshold (pips)
+input bool InpCloseOppositeTrades = true; // Close Opposite Trades When Profiting
+
+input group "RSI Follow Strategy"
+input int InpRSIPeriod = 49; // RSI Period
+input int InpRSIOverbought = 81; // RSI Overbought Level
+input int InpRSIOversold = 41; // RSI Oversold Level
+input int InpRSIExitLevel = 48; // RSI Exit Level
+input int InpRSIFollowStartHour = 24; // RSI Follow Start Hour (0-23)
+input int InpRSIFollowEndHour = 8; // RSI Follow End Hour (0-23)
+input bool InpRSIFollowCloseOutsideHours = false; // Close trades outside trading hours
+
+input group "RSI Reverse Strategy"
+input int InpRSIReversePeriod = 159; // RSI Period
+input int InpRSIReverseOverbought = 51; // RSI Overbought Level
+input int InpRSIReverseOversold = 49; // RSI Oversold Level
+input int InpRSIReverseCrossLevel = 54; // RSI Cross Level
+input int InpRSIReverseExitLevel = 49; // RSI Exit Level
+input int InpRSIReverseStartHour = 12; // RSI Reverse Start Hour (0-23)
+input int InpRSIReverseEndHour = 22; // RSI Reverse End Hour (0-23)
+input bool InpRSIReverseCloseOutsideHours = false; // Close trades outside trading hours
+input int InpRSIReverseCooldownBars = 11; // RSI Reverse Cooldown (bars)
+input bool InpRSIReverseCooldownOnLoss = true; // Apply cooldown only on loss
+
+input group "EMA Cross Strategy"
+input int InpEMAPeriod = 175; // EMA Period
+input int InpEMACrossStartHour = 22; // EMA Cross Start Hour (0-23)
+input int InpEMACrossEndHour = 12; // EMA Cross End Hour (0-23)
+input bool InpEMACrossCloseOutsideHours = false; // Close trades outside trading hours
+input bool InpUseEMADistanceEntry = true; // Use EMA Distance Entry
+input double InpEMADistancePips = 8440.0; // EMA Distance Threshold (pips)
+input int InpEMADistancePeriod = 30; // EMA Distance Period (bars)
+
+// Global Variables
+int rsiHandle;
+int rsiReverseHandle;
+int emaHandle;
+bool rsiOverbought = false;
+bool rsiOversold = false;
+bool rsiReverseOverbought = false;
+bool rsiReverseOversold = false;
+CTrade trade;
+CPositionInfo positionInfo;
+bool emaCrossBuySignal = false;
+bool emaCrossSellSignal = false;
+int emaCrossSignalBar = 0;
+datetime lastBarTime = 0;
+datetime rsiReverseLastCloseTime = 0;
+bool rsiReverseInCooldown = false;
+
+//+------------------------------------------------------------------+
+//| Expert initialization function |
+//+------------------------------------------------------------------+
+int OnInit()
+{
+ // Initialize indicators
+ rsiHandle = iRSI(_Symbol, InpTimeframe, InpRSIPeriod, PRICE_CLOSE);
+ rsiReverseHandle = iRSI(_Symbol, InpTimeframe, InpRSIReversePeriod, PRICE_CLOSE);
+ emaHandle = iMA(_Symbol, InpTimeframe, InpEMAPeriod, 0, MODE_EMA, PRICE_CLOSE);
+
+ if(rsiHandle == INVALID_HANDLE || rsiReverseHandle == INVALID_HANDLE || emaHandle == INVALID_HANDLE)
+ {
+ Print("Error creating indicators");
+ return INIT_FAILED;
+ }
+
+ // Initialize trade settings
+ trade.SetExpertMagicNumber(InpMagicNumberRSIFollow);
+ trade.SetMarginMode();
+ trade.SetTypeFillingBySymbol(_Symbol);
+ trade.SetDeviationInPoints(10);
+
+ // Initialize last bar time
+ datetime time[];
+ if(CopyTime(_Symbol, InpTimeframe, 0, 1, time) > 0)
+ {
+ lastBarTime = time[0];
+ }
+
+ return(INIT_SUCCEEDED);
+}
+
+//+------------------------------------------------------------------+
+//| 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;
+}
+
+//+------------------------------------------------------------------+
+//| Expert deinitialization function |
+//+------------------------------------------------------------------+
+void OnDeinit(const int reason)
+{
+ // Release indicator handles
+ IndicatorRelease(rsiHandle);
+ IndicatorRelease(rsiReverseHandle);
+ IndicatorRelease(emaHandle);
+}
+
+//+------------------------------------------------------------------+
+//| Check if current time is within trading hours |
+//+------------------------------------------------------------------+
+bool IsWithinTradingHours(int startHour, int endHour)
+{
+ MqlDateTime currentTime;
+ TimeToStruct(TimeCurrent(), currentTime);
+
+ if(startHour <= endHour)
+ {
+ return (currentTime.hour >= startHour && currentTime.hour < endHour);
+ }
+ else
+ {
+ return (currentTime.hour >= startHour || currentTime.hour < endHour);
+ }
+}
+
+//+------------------------------------------------------------------+
+//| Check if position exists for given magic number |
+//+------------------------------------------------------------------+
+bool HasPosition(int magic)
+{
+ for(int i = PositionsTotal() - 1; i >= 0; i--)
+ {
+ if(positionInfo.SelectByIndex(i))
+ {
+ if(positionInfo.Magic() == magic)
+ return true;
+ }
+ }
+ return false;
+}
+
+//+------------------------------------------------------------------+
+//| Check if any strategy has profitable position |
+//+------------------------------------------------------------------+
+bool HasProfitablePosition(int excludeMagic)
+{
+ bool hasProfitable = false;
+ for(int i = PositionsTotal() - 1; i >= 0; i--)
+ {
+ if(positionInfo.SelectByIndex(i))
+ {
+ if(positionInfo.Magic() != excludeMagic)
+ {
+ double profit = positionInfo.Profit();
+ if(profit > InpLockProfitThreshold * _Point)
+ {
+ hasProfitable = true;
+ // If enabled, close opposite trades
+ if(InpCloseOppositeTrades)
+ {
+ // Check if this is an opposite trade to the excluded magic number
+ if((excludeMagic == InpMagicNumberRSIFollow && positionInfo.Magic() == InpMagicNumberRSIReverse) ||
+ (excludeMagic == InpMagicNumberRSIReverse && positionInfo.Magic() == InpMagicNumberRSIFollow) ||
+ (excludeMagic == InpMagicNumberEMACross && (positionInfo.Magic() == InpMagicNumberRSIReverse || positionInfo.Magic() == InpMagicNumberRSIFollow)) ||
+ ((excludeMagic == InpMagicNumberRSIFollow || excludeMagic == InpMagicNumberRSIReverse) && positionInfo.Magic() == InpMagicNumberEMACross))
+ {
+ ClosePosition(positionInfo.Magic());
+ }
+ }
+ }
+ }
+ }
+ }
+ return hasProfitable;
+}
+
+//+------------------------------------------------------------------+
+//| Check for RSI Follow Strategy signals |
+//+------------------------------------------------------------------+
+void CheckRSIFollowStrategy()
+{
+ // Check if within trading hours
+ if(!IsWithinTradingHours(InpRSIFollowStartHour, InpRSIFollowEndHour))
+ {
+ if(InpRSIFollowCloseOutsideHours)
+ {
+ if(HasPosition(InpMagicNumberRSIFollow))
+ {
+ ClosePosition(InpMagicNumberRSIFollow);
+ }
+ }
+ return;
+ }
+
+ // Check strategy lock
+ if(InpEnableStrategyLock && HasProfitablePosition(InpMagicNumberRSIFollow))
+ return;
+
+ double rsi[];
+ ArraySetAsSeries(rsi, true);
+ CopyBuffer(rsiHandle, 0, 0, 3, rsi);
+
+ if(ArraySize(rsi) < 3) return;
+
+ // Check for overbought condition
+ if(rsi[1] > InpRSIOverbought)
+ rsiOverbought = true;
+ else if(rsi[1] < InpRSIOversold)
+ rsiOversold = true;
+
+ // Check for entry signals
+ if(rsiOverbought && rsi[1] < rsi[0] && rsi[1] < InpRSIExitLevel)
+ {
+ // Sell signal
+ if(!HasPosition(InpMagicNumberRSIFollow))
+ {
+ trade.SetExpertMagicNumber(InpMagicNumberRSIFollow);
+ trade.Sell(InpLotSize, _Symbol, 0, 0, 0, "RSI Follow");
+ }
+ rsiOverbought = false;
+ }
+ else if(rsiOversold && rsi[1] > rsi[0] && rsi[1] > InpRSIExitLevel)
+ {
+ // Buy signal
+ if(!HasPosition(InpMagicNumberRSIFollow))
+ {
+ trade.SetExpertMagicNumber(InpMagicNumberRSIFollow);
+ trade.Buy(InpLotSize, _Symbol, 0, 0, 0, "RSI Follow");
+ }
+ rsiOversold = false;
+ }
+}
+
+//+------------------------------------------------------------------+
+//| Check if RSI Reverse is in cooldown |
+//+------------------------------------------------------------------+
+bool IsRSIReverseInCooldown()
+{
+ if(InpRSIReverseCooldownBars <= 0)
+ return false;
+
+ if(!rsiReverseInCooldown)
+ return false;
+
+ datetime time[];
+ if(CopyTime(_Symbol, InpTimeframe, 0, 1, time) > 0)
+ {
+ datetime currentBarTime = time[0];
+ datetime cooldownEndTime = rsiReverseLastCloseTime + InpRSIReverseCooldownBars * PeriodSeconds(InpTimeframe);
+
+ if(currentBarTime >= cooldownEndTime)
+ {
+ rsiReverseInCooldown = false;
+ return false;
+ }
+ }
+
+ return true;
+}
+
+//+------------------------------------------------------------------+
+//| Check for RSI Reverse Strategy signals |
+//+------------------------------------------------------------------+
+void CheckRSIReverseStrategy()
+{
+ // Check if within trading hours
+ if(!IsWithinTradingHours(InpRSIReverseStartHour, InpRSIReverseEndHour))
+ {
+ if(InpRSIReverseCloseOutsideHours)
+ {
+ if(HasPosition(InpMagicNumberRSIReverse))
+ {
+ ClosePosition(InpMagicNumberRSIReverse);
+ }
+ }
+ return;
+ }
+
+ // Check strategy lock
+ if(InpEnableStrategyLock && HasProfitablePosition(InpMagicNumberRSIReverse))
+ return;
+
+ // Check cooldown
+ if(IsRSIReverseInCooldown())
+ return;
+
+ double rsi[];
+ ArraySetAsSeries(rsi, true);
+ CopyBuffer(rsiReverseHandle, 0, 0, 3, rsi);
+
+ if(ArraySize(rsi) < 3) return;
+
+ // Check for overbought/oversold conditions
+ if(rsi[1] > InpRSIReverseOverbought)
+ rsiReverseOverbought = true;
+ else if(rsi[1] < InpRSIReverseOversold)
+ rsiReverseOversold = true;
+
+ // Check for entry signals
+ if(rsiReverseOverbought && rsi[1] < InpRSIReverseCrossLevel)
+ {
+ // Sell signal
+ if(!HasPosition(InpMagicNumberRSIReverse))
+ {
+ trade.SetExpertMagicNumber(InpMagicNumberRSIReverse);
+ trade.Sell(InpLotSize, _Symbol, 0, 0, 0, "RSI Reverse");
+ }
+ rsiReverseOverbought = false;
+ }
+ else if(rsiReverseOversold && rsi[1] > InpRSIReverseCrossLevel)
+ {
+ // Buy signal
+ if(!HasPosition(InpMagicNumberRSIReverse))
+ {
+ trade.SetExpertMagicNumber(InpMagicNumberRSIReverse);
+ trade.Buy(InpLotSize, _Symbol, 0, 0, 0, "RSI Reverse");
+ }
+ rsiReverseOversold = false;
+ }
+}
+
+//+------------------------------------------------------------------+
+//| Check for EMA Cross Strategy signals |
+//+------------------------------------------------------------------+
+void CheckEMACrossStrategy()
+{
+ // Check if within trading hours
+ if(!IsWithinTradingHours(InpEMACrossStartHour, InpEMACrossEndHour))
+ {
+ if(InpEMACrossCloseOutsideHours)
+ {
+ if(HasPosition(InpMagicNumberEMACross))
+ {
+ ClosePosition(InpMagicNumberEMACross);
+ }
+ }
+ return;
+ }
+
+ // Check strategy lock
+ if(InpEnableStrategyLock && HasProfitablePosition(InpMagicNumberEMACross))
+ return;
+
+ double ema[], close[];
+ ArraySetAsSeries(ema, true);
+ ArraySetAsSeries(close, true);
+
+ CopyBuffer(emaHandle, 0, 0, InpEMADistancePeriod + 2, ema);
+ CopyClose(_Symbol, InpTimeframe, 0, InpEMADistancePeriod + 2, close);
+
+ if(ArraySize(ema) < InpEMADistancePeriod + 2 || ArraySize(close) < InpEMADistancePeriod + 2) return;
+
+ // Check for cross signals
+ if(ema[1] < close[1] && ema[0] > close[0])
+ {
+ // Buy cross signal
+ emaCrossBuySignal = true;
+ emaCrossSellSignal = false;
+ emaCrossSignalBar = 0;
+ }
+ else if(ema[1] > close[1] && ema[0] < close[0])
+ {
+ // Sell cross signal
+ emaCrossSellSignal = true;
+ emaCrossBuySignal = false;
+ emaCrossSignalBar = 0;
+ }
+
+ // Check for distance entry conditions
+ if(InpUseEMADistanceEntry)
+ {
+ if(emaCrossBuySignal)
+ {
+ // Check if price has moved above EMA by the required distance for the required period
+ bool distanceConditionMet = true;
+ for(int i = 0; i < InpEMADistancePeriod; i++)
+ {
+ double distance = (close[i] - ema[i]) / _Point;
+ if(distance < InpEMADistancePips)
+ {
+ distanceConditionMet = false;
+ break;
+ }
+ }
+
+ if(distanceConditionMet && !HasPosition(InpMagicNumberEMACross))
+ {
+ trade.SetExpertMagicNumber(InpMagicNumberEMACross);
+ trade.Buy(InpLotSize, _Symbol, 0, 0, 0, "EMA Cross Distance");
+ emaCrossBuySignal = false;
+ }
+ }
+ else if(emaCrossSellSignal)
+ {
+ // Check if price has moved below EMA by the required distance for the required period
+ bool distanceConditionMet = true;
+ for(int i = 0; i < InpEMADistancePeriod; i++)
+ {
+ double distance = (ema[i] - close[i]) / _Point;
+ if(distance < InpEMADistancePips)
+ {
+ distanceConditionMet = false;
+ break;
+ }
+ }
+
+ if(distanceConditionMet && !HasPosition(InpMagicNumberEMACross))
+ {
+ trade.SetExpertMagicNumber(InpMagicNumberEMACross);
+ trade.Sell(InpLotSize, _Symbol, 0, 0, 0, "EMA Cross Distance");
+ emaCrossSellSignal = false;
+ }
+ }
+ }
+ else
+ {
+ // Original cross entry logic
+ if(ema[1] < close[1] && ema[0] > close[0])
+ {
+ // Buy signal
+ if(!HasPosition(InpMagicNumberEMACross))
+ {
+ trade.SetExpertMagicNumber(InpMagicNumberEMACross);
+ trade.Buy(InpLotSize, _Symbol, 0, 0, 0, "EMA Cross");
+ }
+ }
+ else if(ema[1] > close[1] && ema[0] < close[0])
+ {
+ // Sell signal
+ if(!HasPosition(InpMagicNumberEMACross))
+ {
+ trade.SetExpertMagicNumber(InpMagicNumberEMACross);
+ trade.Sell(InpLotSize, _Symbol, 0, 0, 0, "EMA Cross");
+ }
+ }
+ }
+
+ // Increment signal bar counter
+ if(emaCrossBuySignal || emaCrossSellSignal)
+ {
+ emaCrossSignalBar++;
+ // Reset signals if they're too old (optional, can be removed if not needed)
+ if(emaCrossSignalBar > InpEMADistancePeriod * 2)
+ {
+ emaCrossBuySignal = false;
+ emaCrossSellSignal = false;
+ }
+ }
+}
+
+//+------------------------------------------------------------------+
+//| Expert tick function |
+//+------------------------------------------------------------------+
+void OnTick()
+{
+ // Only process on new bar
+ if(!IsNewBar())
+ return;
+
+ // Check for new signals
+ if(InpEnableRSIFollow)
+ CheckRSIFollowStrategy();
+ if(InpEnableRSIReverse)
+ CheckRSIReverseStrategy();
+ if(InpEnableEMACross)
+ CheckEMACrossStrategy();
+
+ // Check for exit conditions
+ CheckExitConditions();
+}
+
+//+------------------------------------------------------------------+
+//| Check exit conditions for all strategies |
+//+------------------------------------------------------------------+
+void CheckExitConditions()
+{
+ double rsi[], rsiReverse[], ema[], close[];
+ ArraySetAsSeries(rsi, true);
+ ArraySetAsSeries(rsiReverse, true);
+ ArraySetAsSeries(ema, true);
+ ArraySetAsSeries(close, true);
+
+ if(InpEnableRSIFollow)
+ {
+ CopyBuffer(rsiHandle, 0, 0, 1, rsi);
+ // Check RSI Follow exit conditions
+ if(HasPosition(InpMagicNumberRSIFollow))
+ {
+ if((positionInfo.PositionType() == POSITION_TYPE_BUY && rsi[0] < InpRSIExitLevel) ||
+ (positionInfo.PositionType() == POSITION_TYPE_SELL && rsi[0] > InpRSIExitLevel))
+ {
+ ClosePosition(InpMagicNumberRSIFollow);
+ }
+ }
+ }
+
+ if(InpEnableRSIReverse)
+ {
+ CopyBuffer(rsiReverseHandle, 0, 0, 1, rsiReverse);
+ // Check RSI Reverse exit conditions
+ if(HasPosition(InpMagicNumberRSIReverse))
+ {
+ if((positionInfo.PositionType() == POSITION_TYPE_BUY && rsiReverse[0] < InpRSIReverseExitLevel) ||
+ (positionInfo.PositionType() == POSITION_TYPE_SELL && rsiReverse[0] > InpRSIReverseExitLevel))
+ {
+ ClosePosition(InpMagicNumberRSIReverse);
+ }
+ }
+ }
+
+ if(InpEnableEMACross)
+ {
+ CopyBuffer(emaHandle, 0, 0, 2, ema);
+ CopyClose(_Symbol, InpTimeframe, 0, 2, close);
+ // Check EMA Cross exit conditions
+ if(HasPosition(InpMagicNumberEMACross))
+ {
+ if((positionInfo.PositionType() == POSITION_TYPE_BUY && ema[0] > close[0]) ||
+ (positionInfo.PositionType() == POSITION_TYPE_SELL && ema[0] < close[0]))
+ {
+ ClosePosition(InpMagicNumberEMACross);
+ }
+ }
+ }
+}
+
+//+------------------------------------------------------------------+
+//| Close position by magic number |
+//+------------------------------------------------------------------+
+void ClosePosition(int magic)
+{
+ for(int i = PositionsTotal() - 1; i >= 0; i--)
+ {
+ if(positionInfo.SelectByIndex(i))
+ {
+ if(positionInfo.Magic() == magic)
+ {
+ // Check if this is RSI Reverse position and update cooldown
+ if(magic == InpMagicNumberRSIReverse)
+ {
+ datetime time[];
+ if(CopyTime(_Symbol, InpTimeframe, 0, 1, time) > 0)
+ {
+ rsiReverseLastCloseTime = time[0];
+ // Only enter cooldown if it's a loss or if cooldown on loss is disabled
+ if(!InpRSIReverseCooldownOnLoss || positionInfo.Profit() < 0)
+ {
+ rsiReverseInCooldown = true;
+ }
+ }
+ }
+
+ trade.PositionClose(positionInfo.Ticket());
+ break;
+ }
+ }
+ }
+}
diff --git a/RSIFollowReverseEMACrossOverBTCUSD/test-balance.jpg b/RSIFollowReverseEMACrossOverBTCUSD/test-balance.jpg
new file mode 100644
index 0000000..fc511d7
Binary files /dev/null and b/RSIFollowReverseEMACrossOverBTCUSD/test-balance.jpg differ