@@ -11,6 +11,7 @@
|
|||||||
#include <Trade\Trade.mqh>
|
#include <Trade\Trade.mqh>
|
||||||
#include <Indicators\Trend.mqh>
|
#include <Indicators\Trend.mqh>
|
||||||
#include <Indicators\Volumes.mqh>
|
#include <Indicators\Volumes.mqh>
|
||||||
|
#include "../_united/MagicNumberHelpers.mqh"
|
||||||
|
|
||||||
// Input parameters
|
// Input parameters
|
||||||
input int BoxPeriod = 165; // Period for Darvas Box calculation
|
input int BoxPeriod = 165; // Period for Darvas Box calculation
|
||||||
@@ -33,6 +34,9 @@ input double TrendThreshold = 4.94; // Trend strength threshold
|
|||||||
input int VolumeMA_Period = 110; // Period for Volume MA
|
input int VolumeMA_Period = 110; // Period for Volume MA
|
||||||
input double VolumeThresholdMultiplier = 1.5; // Volume spike threshold
|
input double VolumeThresholdMultiplier = 1.5; // Volume spike threshold
|
||||||
|
|
||||||
|
// Magic Number
|
||||||
|
input int MagicNumber = 135790; // Magic Number for Trades
|
||||||
|
|
||||||
// Global variables
|
// Global variables
|
||||||
double boxHigh = 0;
|
double boxHigh = 0;
|
||||||
double boxLow = 0;
|
double boxLow = 0;
|
||||||
@@ -42,7 +46,6 @@ string boxName = "DarvasBox_";
|
|||||||
double minStopLevel = 0;
|
double minStopLevel = 0;
|
||||||
double point = 0;
|
double point = 0;
|
||||||
CTrade trade;
|
CTrade trade;
|
||||||
ulong magicNumber = 135790;
|
|
||||||
|
|
||||||
// Indicator handles
|
// Indicator handles
|
||||||
int maHandle;
|
int maHandle;
|
||||||
@@ -77,7 +80,7 @@ int OnInit()
|
|||||||
trade.SetDeviationInPoints(10);
|
trade.SetDeviationInPoints(10);
|
||||||
trade.SetTypeFilling(ORDER_FILLING_IOC);
|
trade.SetTypeFilling(ORDER_FILLING_IOC);
|
||||||
trade.SetAsyncMode(false);
|
trade.SetAsyncMode(false);
|
||||||
trade.SetExpertMagicNumber(magicNumber);
|
trade.SetExpertMagicNumber(MagicNumber);
|
||||||
|
|
||||||
if(EnableLogging)
|
if(EnableLogging)
|
||||||
{
|
{
|
||||||
@@ -343,7 +346,7 @@ void OnTick()
|
|||||||
Print("Breakout Signal Detected - Price above box high");
|
Print("Breakout Signal Detected - Price above box high");
|
||||||
|
|
||||||
// Buy signal
|
// Buy signal
|
||||||
if(PositionsTotal() == 0) // No existing positions
|
if(!PositionExistsByMagic(_Symbol, MagicNumber)) // No existing positions with our magic number
|
||||||
{
|
{
|
||||||
double sl = currentPrice - StopLoss * _Point;
|
double sl = currentPrice - StopLoss * _Point;
|
||||||
double tp = currentPrice + TakeProfit * _Point;
|
double tp = currentPrice + TakeProfit * _Point;
|
||||||
@@ -364,7 +367,7 @@ void OnTick()
|
|||||||
Print("Breakdown Signal Detected - Price below box low");
|
Print("Breakdown Signal Detected - Price below box low");
|
||||||
|
|
||||||
// Sell signal
|
// Sell signal
|
||||||
if(PositionsTotal() == 0) // No existing positions
|
if(!PositionExistsByMagic(_Symbol, MagicNumber)) // No existing positions with our magic number
|
||||||
{
|
{
|
||||||
double sl = currentPrice + StopLoss * _Point;
|
double sl = currentPrice + StopLoss * _Point;
|
||||||
double tp = currentPrice - TakeProfit * _Point;
|
double tp = currentPrice - TakeProfit * _Point;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#property link "https://www.mql5.com"
|
#property link "https://www.mql5.com"
|
||||||
#property version "1.00"
|
#property version "1.00"
|
||||||
#include <Trade\Trade.mqh>
|
#include <Trade\Trade.mqh>
|
||||||
|
#include "../_united/MagicNumberHelpers.mqh"
|
||||||
//--- Eingabeparameter (Input Parameters) - Optimized Profitable Parameters
|
//--- Eingabeparameter (Input Parameters) - Optimized Profitable Parameters
|
||||||
input int EMA_Periode = 46; // EMA Periode
|
input int EMA_Periode = 46; // EMA Periode
|
||||||
input double PreisSchwelle = 600.0; // Preisbewegung Schwelle in Pips
|
input double PreisSchwelle = 600.0; // Preisbewegung Schwelle in Pips
|
||||||
@@ -127,7 +128,7 @@ void OnTick()
|
|||||||
Print("Differenz Close-EMA: ", aktueller_close - ema_aktuell);
|
Print("Differenz Close-EMA: ", aktueller_close - ema_aktuell);
|
||||||
Print("Preis-Trigger: ", preis_trigger_aktiv, " Steigungs-Trigger: ", steigung_trigger_aktiv);
|
Print("Preis-Trigger: ", preis_trigger_aktiv, " Steigungs-Trigger: ", steigung_trigger_aktiv);
|
||||||
Print("Überwachung aktiv: ", überwachung_aktiv);
|
Print("Überwachung aktiv: ", überwachung_aktiv);
|
||||||
Print("Position offen: ", PositionSelect(_Symbol));
|
Print("Position offen: ", PositionExistsByMagic(_Symbol, MagicNumber));
|
||||||
Print("Trades im aktuellen Crossover: ", trades_in_current_crossover, "/", MaxTradesPerCrossover);
|
Print("Trades im aktuellen Crossover: ", trades_in_current_crossover, "/", MaxTradesPerCrossover);
|
||||||
Print("==================");
|
Print("==================");
|
||||||
}
|
}
|
||||||
@@ -289,7 +290,7 @@ void PrüfeTrigger()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bullish_signal && !PositionSelect(_Symbol))
|
if(bullish_signal && !PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
Print("TRACE: Versuche KAUF-Trade zu platzieren (Trade #", trades_in_current_crossover + 1, ")");
|
Print("TRACE: Versuche KAUF-Trade zu platzieren (Trade #", trades_in_current_crossover + 1, ")");
|
||||||
if(PlatziereTrade(ORDER_TYPE_BUY))
|
if(PlatziereTrade(ORDER_TYPE_BUY))
|
||||||
@@ -297,7 +298,7 @@ void PrüfeTrigger()
|
|||||||
trades_in_current_crossover++;
|
trades_in_current_crossover++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(bearish_signal && !PositionSelect(_Symbol))
|
else if(bearish_signal && !PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
Print("TRACE: Versuche VERKAUF-Trade zu platzieren (Trade #", trades_in_current_crossover + 1, ")");
|
Print("TRACE: Versuche VERKAUF-Trade zu platzieren (Trade #", trades_in_current_crossover + 1, ")");
|
||||||
if(PlatziereTrade(ORDER_TYPE_SELL))
|
if(PlatziereTrade(ORDER_TYPE_SELL))
|
||||||
@@ -305,7 +306,7 @@ void PrüfeTrigger()
|
|||||||
trades_in_current_crossover++;
|
trades_in_current_crossover++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(PositionSelect(_Symbol))
|
else if(PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
Print("TRACE: Position bereits offen - kein neuer Trade");
|
Print("TRACE: Position bereits offen - kein neuer Trade");
|
||||||
}
|
}
|
||||||
@@ -361,7 +362,7 @@ bool PlatziereTrade(ENUM_ORDER_TYPE order_type)
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void VerwalteTrades()
|
void VerwalteTrades()
|
||||||
{
|
{
|
||||||
if(!PositionSelect(_Symbol))
|
if(!PositionSelectByMagic(_Symbol, MagicNumber))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
double position_profit = PositionGetDouble(POSITION_PROFIT);
|
double position_profit = PositionGetDouble(POSITION_PROFIT);
|
||||||
@@ -417,7 +418,7 @@ void VerwalteTrades()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//--- Profit-Prüfung nach X Bars (Profit check after X bars)
|
//--- Profit-Prüfung nach X Bars (Profit check after X bars)
|
||||||
if(CloseUnprofitableTrades && trade_open_time != 0 && PositionSelect(_Symbol))
|
if(CloseUnprofitableTrades && trade_open_time != 0 && PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
Print("TRACE: Profit-Prüfung aktiviert - CloseUnprofitableTrades: ", CloseUnprofitableTrades);
|
Print("TRACE: Profit-Prüfung aktiviert - CloseUnprofitableTrades: ", CloseUnprofitableTrades);
|
||||||
PrüfeProfitNachBars();
|
PrüfeProfitNachBars();
|
||||||
@@ -433,7 +434,7 @@ void VerwalteTrades()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void PrüfeProfitNachBars()
|
void PrüfeProfitNachBars()
|
||||||
{
|
{
|
||||||
if(!PositionSelect(_Symbol))
|
if(!PositionSelectByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
return; // Keine Position offen
|
return; // Keine Position offen
|
||||||
}
|
}
|
||||||
@@ -479,7 +480,7 @@ void ÄndereStopLoss(double new_stop_loss)
|
|||||||
{
|
{
|
||||||
Print("TRACE: Versuche Stop Loss zu ändern auf: ", new_stop_loss);
|
Print("TRACE: Versuche Stop Loss zu ändern auf: ", new_stop_loss);
|
||||||
|
|
||||||
bool success = trade.PositionModify(_Symbol, new_stop_loss, PositionGetDouble(POSITION_TP));
|
bool success = ModifyPositionByMagic(trade, _Symbol, MagicNumber, new_stop_loss, PositionGetDouble(POSITION_TP));
|
||||||
|
|
||||||
if(success)
|
if(success)
|
||||||
{
|
{
|
||||||
@@ -499,7 +500,7 @@ void SchließePosition(string reason = "Unbekannt")
|
|||||||
{
|
{
|
||||||
Print("TRACE: Versuche Position zu schließen - Grund: ", reason);
|
Print("TRACE: Versuche Position zu schließen - Grund: ", reason);
|
||||||
|
|
||||||
bool success = trade.PositionClose(_Symbol);
|
bool success = ClosePositionByMagic(trade, _Symbol, MagicNumber);
|
||||||
|
|
||||||
if(success)
|
if(success)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,82 @@
|
|||||||
|
# MQL5 EA Improvements - Magic Number Isolation
|
||||||
|
|
||||||
|
## Problem
|
||||||
|
When multiple EAs run together on the same symbol, they interfere with each other because magic numbers are not properly checked in all position-related functions.
|
||||||
|
|
||||||
|
## Solution
|
||||||
|
1. Created `MagicNumberHelpers.mqh` with magic-aware helper functions
|
||||||
|
2. Updated EAs to use these helper functions
|
||||||
|
3. Created `_united/main.mq5` - a unified EA that runs multiple strategies together
|
||||||
|
|
||||||
|
## Fixed Functions
|
||||||
|
|
||||||
|
### Helper Functions (MagicNumberHelpers.mqh)
|
||||||
|
- `PositionSelectByMagic()` - Select position by symbol AND magic number
|
||||||
|
- `PositionSelectByTicketAndMagic()` - Verify ticket has correct magic number
|
||||||
|
- `PositionExistsByMagic()` - Check if position exists with magic number
|
||||||
|
- `GetPositionTicketByMagic()` - Get ticket by symbol and magic number
|
||||||
|
- `ClosePositionByMagic()` - Close position with magic number verification
|
||||||
|
- `ModifyPositionByMagic()` - Modify position with magic number verification
|
||||||
|
- `GetPositionProfitByMagic()` - Get profit with magic number check
|
||||||
|
- `GetPositionTypeByMagic()` - Get position type with magic number check
|
||||||
|
- `CountPositionsByMagic()` - Count positions with specific magic number
|
||||||
|
|
||||||
|
## Fixed EAs
|
||||||
|
|
||||||
|
### RSIScalpingXAUUSD
|
||||||
|
- ✅ Fixed `CheckExistingPosition()` to use `PositionSelectByTicketAndMagic()`
|
||||||
|
- ✅ Fixed `ClosePosition()` to verify magic number before closing
|
||||||
|
- ✅ Fixed entry signal check to use `PositionExistsByMagic()`
|
||||||
|
|
||||||
|
### MeanReversionXAUUSD
|
||||||
|
- ✅ Fixed all `PositionSelect(_Symbol)` calls to use `PositionSelectByMagic()`
|
||||||
|
- ✅ Fixed `SchließePosition()` to use `ClosePositionByMagic()`
|
||||||
|
- ✅ Fixed `ÄndereStopLoss()` to use `ModifyPositionByMagic()`
|
||||||
|
- ✅ Fixed all position existence checks to use `PositionExistsByMagic()`
|
||||||
|
|
||||||
|
## United EA
|
||||||
|
|
||||||
|
The `_united/main.mq5` EA allows running multiple strategies together:
|
||||||
|
- Each strategy has its own unique magic number
|
||||||
|
- Strategies operate independently without interference
|
||||||
|
- Can enable/disable individual strategies via input parameters
|
||||||
|
- Currently implements:
|
||||||
|
- RSI Scalping Strategy
|
||||||
|
- Mean Reversion Strategy
|
||||||
|
- Framework for additional strategies (DarvasBox, RSICrossOver, RSIMidPoint)
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
### For Individual EAs
|
||||||
|
Simply include the helper file:
|
||||||
|
```mql5
|
||||||
|
#include "../_united/MagicNumberHelpers.mqh"
|
||||||
|
```
|
||||||
|
|
||||||
|
Then replace:
|
||||||
|
- `PositionSelect(_Symbol)` → `PositionSelectByMagic(_Symbol, MagicNumber)`
|
||||||
|
- `PositionSelectByTicket(ticket)` → `PositionSelectByTicketAndMagic(ticket, MagicNumber)`
|
||||||
|
- `trade.PositionClose(_Symbol)` → `ClosePositionByMagic(trade, _Symbol, MagicNumber)`
|
||||||
|
- `trade.PositionModify(_Symbol, ...)` → `ModifyPositionByMagic(trade, _Symbol, MagicNumber, ...)`
|
||||||
|
|
||||||
|
### For United EA
|
||||||
|
1. Set unique magic numbers for each strategy
|
||||||
|
2. Enable/disable strategies via input parameters
|
||||||
|
3. Configure strategy-specific parameters
|
||||||
|
4. Run on chart - all enabled strategies will operate independently
|
||||||
|
|
||||||
|
## Remaining EAs to Fix
|
||||||
|
|
||||||
|
The following EAs should be updated similarly:
|
||||||
|
- DarvasBoxXAUUSD
|
||||||
|
- RSICrossOverReversalXAUUSD
|
||||||
|
- RSIMidPointHijackXAUUSD
|
||||||
|
- EMASlopeDistanceCocktailXAUUSD
|
||||||
|
- All RSIScalping variants (APPL, BTCUSD, MSFT, NVDA, TSLA)
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Always use magic-aware functions** when checking/modifying positions
|
||||||
|
2. **Set unique magic numbers** for each EA instance
|
||||||
|
3. **Verify magic number** before any position operation
|
||||||
|
4. **Use United EA** when running multiple strategies on same symbol
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||||||
#property version "1.00"
|
#property version "1.00"
|
||||||
#include <Trade\Trade.mqh>
|
#include <Trade\Trade.mqh>
|
||||||
|
#include "../_united/MagicNumberHelpers.mqh"
|
||||||
//--- Eingabeparameter (Input Parameters) - Optimized Profitable Parameters
|
//--- Eingabeparameter (Input Parameters) - Optimized Profitable Parameters
|
||||||
input int EMA_Periode = 46; // EMA Periode
|
input int EMA_Periode = 46; // EMA Periode
|
||||||
input double PreisSchwelle = 600.0; // Preisbewegung Schwelle in Pips
|
input double PreisSchwelle = 600.0; // Preisbewegung Schwelle in Pips
|
||||||
@@ -127,7 +128,7 @@ void OnTick()
|
|||||||
Print("Differenz Close-EMA: ", aktueller_close - ema_aktuell);
|
Print("Differenz Close-EMA: ", aktueller_close - ema_aktuell);
|
||||||
Print("Preis-Trigger: ", preis_trigger_aktiv, " Steigungs-Trigger: ", steigung_trigger_aktiv);
|
Print("Preis-Trigger: ", preis_trigger_aktiv, " Steigungs-Trigger: ", steigung_trigger_aktiv);
|
||||||
Print("Überwachung aktiv: ", überwachung_aktiv);
|
Print("Überwachung aktiv: ", überwachung_aktiv);
|
||||||
Print("Position offen: ", PositionSelect(_Symbol));
|
Print("Position offen: ", PositionExistsByMagic(_Symbol, MagicNumber));
|
||||||
Print("Trades im aktuellen Crossover: ", trades_in_current_crossover, "/", MaxTradesPerCrossover);
|
Print("Trades im aktuellen Crossover: ", trades_in_current_crossover, "/", MaxTradesPerCrossover);
|
||||||
Print("==================");
|
Print("==================");
|
||||||
}
|
}
|
||||||
@@ -289,7 +290,7 @@ void PrüfeTrigger()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(bullish_signal && !PositionSelect(_Symbol))
|
if(bullish_signal && !PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
Print("TRACE: Versuche KAUF-Trade zu platzieren (Trade #", trades_in_current_crossover + 1, ")");
|
Print("TRACE: Versuche KAUF-Trade zu platzieren (Trade #", trades_in_current_crossover + 1, ")");
|
||||||
if(PlatziereTrade(ORDER_TYPE_BUY))
|
if(PlatziereTrade(ORDER_TYPE_BUY))
|
||||||
@@ -297,7 +298,7 @@ void PrüfeTrigger()
|
|||||||
trades_in_current_crossover++;
|
trades_in_current_crossover++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(bearish_signal && !PositionSelect(_Symbol))
|
else if(bearish_signal && !PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
Print("TRACE: Versuche VERKAUF-Trade zu platzieren (Trade #", trades_in_current_crossover + 1, ")");
|
Print("TRACE: Versuche VERKAUF-Trade zu platzieren (Trade #", trades_in_current_crossover + 1, ")");
|
||||||
if(PlatziereTrade(ORDER_TYPE_SELL))
|
if(PlatziereTrade(ORDER_TYPE_SELL))
|
||||||
@@ -305,7 +306,7 @@ void PrüfeTrigger()
|
|||||||
trades_in_current_crossover++;
|
trades_in_current_crossover++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if(PositionSelect(_Symbol))
|
else if(PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
Print("TRACE: Position bereits offen - kein neuer Trade");
|
Print("TRACE: Position bereits offen - kein neuer Trade");
|
||||||
}
|
}
|
||||||
@@ -361,7 +362,7 @@ bool PlatziereTrade(ENUM_ORDER_TYPE order_type)
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void VerwalteTrades()
|
void VerwalteTrades()
|
||||||
{
|
{
|
||||||
if(!PositionSelect(_Symbol))
|
if(!PositionSelectByMagic(_Symbol, MagicNumber))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
double position_profit = PositionGetDouble(POSITION_PROFIT);
|
double position_profit = PositionGetDouble(POSITION_PROFIT);
|
||||||
@@ -417,7 +418,7 @@ void VerwalteTrades()
|
|||||||
}
|
}
|
||||||
|
|
||||||
//--- Profit-Prüfung nach X Bars (Profit check after X bars)
|
//--- Profit-Prüfung nach X Bars (Profit check after X bars)
|
||||||
if(CloseUnprofitableTrades && trade_open_time != 0 && PositionSelect(_Symbol))
|
if(CloseUnprofitableTrades && trade_open_time != 0 && PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
Print("TRACE: Profit-Prüfung aktiviert - CloseUnprofitableTrades: ", CloseUnprofitableTrades);
|
Print("TRACE: Profit-Prüfung aktiviert - CloseUnprofitableTrades: ", CloseUnprofitableTrades);
|
||||||
PrüfeProfitNachBars();
|
PrüfeProfitNachBars();
|
||||||
@@ -433,7 +434,7 @@ void VerwalteTrades()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void PrüfeProfitNachBars()
|
void PrüfeProfitNachBars()
|
||||||
{
|
{
|
||||||
if(!PositionSelect(_Symbol))
|
if(!PositionSelectByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
return; // Keine Position offen
|
return; // Keine Position offen
|
||||||
}
|
}
|
||||||
@@ -479,7 +480,7 @@ void ÄndereStopLoss(double new_stop_loss)
|
|||||||
{
|
{
|
||||||
Print("TRACE: Versuche Stop Loss zu ändern auf: ", new_stop_loss);
|
Print("TRACE: Versuche Stop Loss zu ändern auf: ", new_stop_loss);
|
||||||
|
|
||||||
bool success = trade.PositionModify(_Symbol, new_stop_loss, PositionGetDouble(POSITION_TP));
|
bool success = ModifyPositionByMagic(trade, _Symbol, MagicNumber, new_stop_loss, PositionGetDouble(POSITION_TP));
|
||||||
|
|
||||||
if(success)
|
if(success)
|
||||||
{
|
{
|
||||||
@@ -499,7 +500,7 @@ void SchließePosition(string reason = "Unbekannt")
|
|||||||
{
|
{
|
||||||
Print("TRACE: Versuche Position zu schließen - Grund: ", reason);
|
Print("TRACE: Versuche Position zu schließen - Grund: ", reason);
|
||||||
|
|
||||||
bool success = trade.PositionClose(_Symbol);
|
bool success = ClosePositionByMagic(trade, _Symbol, MagicNumber);
|
||||||
|
|
||||||
if(success)
|
if(success)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// Input Parameters
|
// Input Parameters
|
||||||
#include <Trade\Trade.mqh>
|
#include <Trade\Trade.mqh>
|
||||||
|
#include "../_united/MagicNumberHelpers.mqh"
|
||||||
|
|
||||||
input group "Trade Management"
|
input group "Trade Management"
|
||||||
input int MagicNumber = 7;
|
input int MagicNumber = 7;
|
||||||
@@ -125,7 +126,7 @@ void OnTick() {
|
|||||||
|
|
||||||
|
|
||||||
// Ensure there is at least one position
|
// Ensure there is at least one position
|
||||||
bool hasPosition = (PositionsTotal() > 0);
|
bool hasPosition = PositionExistsByMagic(_Symbol, MagicNumber);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -157,7 +158,7 @@ void OnTick() {
|
|||||||
bool isBuyPosition = false;
|
bool isBuyPosition = false;
|
||||||
bool isSellPosition = false;
|
bool isSellPosition = false;
|
||||||
if (hasPosition) {
|
if (hasPosition) {
|
||||||
if (PositionSelect(_Symbol)) {
|
if (PositionSelectByMagic(_Symbol, MagicNumber)) {
|
||||||
int positionType = PositionGetInteger(POSITION_TYPE);
|
int positionType = PositionGetInteger(POSITION_TYPE);
|
||||||
if (positionType == POSITION_TYPE_BUY) {
|
if (positionType == POSITION_TYPE_BUY) {
|
||||||
isBuyPosition = true;
|
isBuyPosition = true;
|
||||||
@@ -237,77 +238,56 @@ void OnDeinit(const int reason) {
|
|||||||
|
|
||||||
void Close_Position_MN(ulong magicNumber)
|
void Close_Position_MN(ulong magicNumber)
|
||||||
{
|
{
|
||||||
int total = PositionsTotal();
|
// Use helper function to close position by magic number
|
||||||
for(int i = total - 1; i >= 0; i--)
|
ClosePositionByMagic(trade, _Symbol, (int)magicNumber);
|
||||||
{
|
|
||||||
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()
|
void ApplyTrailingStop()
|
||||||
{
|
{
|
||||||
Print("Scanning for trailing stop");
|
Print("Scanning for trailing stop");
|
||||||
for(int i=PositionsTotal()-1; i>=0; i--)
|
|
||||||
|
// Check if position exists with our magic number
|
||||||
|
if(!PositionSelectByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
string symbol = PositionGetSymbol(i);
|
return; // No position with our magic number
|
||||||
ulong PositionTicket = PositionGetTicket(i);
|
}
|
||||||
long trade_type = PositionGetInteger(POSITION_TYPE);
|
|
||||||
|
ulong PositionTicket = PositionGetInteger(POSITION_TICKET);
|
||||||
|
long trade_type = PositionGetInteger(POSITION_TYPE);
|
||||||
|
string symbol = _Symbol;
|
||||||
|
|
||||||
if(!PositionGetInteger(POSITION_MAGIC) == MagicNumber) {
|
double POINT = SymbolInfoDouble(symbol, SYMBOL_POINT);
|
||||||
return;
|
int DIGIT = (int) SymbolInfoInteger(symbol, SYMBOL_DIGITS);
|
||||||
}
|
|
||||||
|
|
||||||
double POINT = SymbolInfoDouble( symbol, SYMBOL_POINT );
|
|
||||||
int DIGIT = (int) SymbolInfoInteger( symbol, SYMBOL_DIGITS );
|
|
||||||
|
|
||||||
|
if(trade_type == POSITION_TYPE_BUY)
|
||||||
if(trade_type == 0)
|
{
|
||||||
{
|
double Bid = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_BID), DIGIT);
|
||||||
double Bid = NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_BID),DIGIT);
|
|
||||||
|
|
||||||
if(Bid-PositionGetDouble(POSITION_PRICE_OPEN) > NormalizeDouble(POINT * TrailingStop,DIGIT))
|
if(Bid - PositionGetDouble(POSITION_PRICE_OPEN) > NormalizeDouble(POINT * TrailingStop, DIGIT))
|
||||||
{
|
{
|
||||||
if(PositionGetDouble(POSITION_SL) < NormalizeDouble(Bid - POINT * TrailingStop,DIGIT))
|
if(PositionGetDouble(POSITION_SL) < NormalizeDouble(Bid - POINT * TrailingStop, DIGIT))
|
||||||
{
|
{
|
||||||
trade.PositionModify(PositionTicket,NormalizeDouble(Bid - POINT * TrailingStop,DIGIT),PositionGetDouble(POSITION_TP));
|
ModifyPositionByMagic(trade, symbol, MagicNumber,
|
||||||
}
|
NormalizeDouble(Bid - POINT * TrailingStop, DIGIT),
|
||||||
}
|
PositionGetDouble(POSITION_TP));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if(trade_type == 1)
|
}
|
||||||
{
|
else if(trade_type == POSITION_TYPE_SELL)
|
||||||
double Ask = NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_ASK),DIGIT);
|
{
|
||||||
|
double Ask = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_ASK), DIGIT);
|
||||||
|
|
||||||
if((PositionGetDouble(POSITION_PRICE_OPEN) - Ask) > NormalizeDouble( POINT * TrailingStop,DIGIT))
|
if((PositionGetDouble(POSITION_PRICE_OPEN) - Ask) > NormalizeDouble(POINT * TrailingStop, DIGIT))
|
||||||
{
|
{
|
||||||
if((PositionGetDouble(POSITION_SL) > NormalizeDouble(Ask + POINT * TrailingStop,DIGIT)) || (PositionGetDouble(POSITION_SL)==0))
|
if((PositionGetDouble(POSITION_SL) > NormalizeDouble(Ask + POINT * TrailingStop, DIGIT)) ||
|
||||||
{
|
(PositionGetDouble(POSITION_SL) == 0))
|
||||||
trade.PositionModify(PositionTicket,NormalizeDouble(Ask + POINT * TrailingStop,DIGIT),PositionGetDouble(POSITION_TP));
|
{
|
||||||
}
|
ModifyPositionByMagic(trade, symbol, MagicNumber,
|
||||||
}
|
NormalizeDouble(Ask + POINT * TrailingStop, DIGIT),
|
||||||
|
PositionGetDouble(POSITION_TP));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int TimeHour(datetime when=0){ if(when == 0) when = TimeCurrent();
|
int TimeHour(datetime when=0){ if(when == 0) when = TimeCurrent();
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include <Trade\Trade.mqh>
|
#include <Trade\Trade.mqh>
|
||||||
#include <Trade\PositionInfo.mqh>
|
#include <Trade\PositionInfo.mqh>
|
||||||
|
#include "../_united/MagicNumberHelpers.mqh"
|
||||||
|
|
||||||
// Input Parameters
|
// Input Parameters
|
||||||
input group "General Settings"
|
input group "General Settings"
|
||||||
@@ -158,19 +159,12 @@ bool IsWithinTradingHours(int startHour, int endHour)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
//| Check if position exists for given magic number |
|
//| Check if position exists for given magic number AND symbol |
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
bool HasPosition(int magic)
|
bool HasPosition(int magic)
|
||||||
{
|
{
|
||||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
// Use helper function that verifies BOTH symbol AND magic number for THIS EA
|
||||||
{
|
return PositionExistsByMagic(_Symbol, magic);
|
||||||
if(positionInfo.SelectByIndex(i))
|
|
||||||
{
|
|
||||||
if(positionInfo.Magic() == magic)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
@@ -572,30 +566,39 @@ void CheckExitConditions()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void ClosePosition(int magic)
|
void ClosePosition(int magic)
|
||||||
{
|
{
|
||||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
// Close position using helper that verifies symbol AND magic number for THIS EA
|
||||||
|
// First check if position exists for this EA on this symbol
|
||||||
|
if(!PositionExistsByMagic(_Symbol, magic))
|
||||||
{
|
{
|
||||||
if(positionInfo.SelectByIndex(i))
|
return; // No position for this EA on this symbol
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the position ticket for this EA on this symbol
|
||||||
|
ulong ticket = GetPositionTicketByMagic(_Symbol, magic);
|
||||||
|
if(ticket == 0)
|
||||||
|
{
|
||||||
|
return; // No valid ticket found
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this is RSI Reverse position and update cooldown
|
||||||
|
if(magic == InpMagicNumberRSIReverse)
|
||||||
|
{
|
||||||
|
if(PositionSelectByTicketSymbolAndMagic(ticket, _Symbol, magic))
|
||||||
{
|
{
|
||||||
if(positionInfo.Magic() == magic)
|
datetime time[];
|
||||||
|
if(CopyTime(_Symbol, InpTimeframe, 0, 1, time) > 0)
|
||||||
{
|
{
|
||||||
// Check if this is RSI Reverse position and update cooldown
|
rsiReverseLastCloseTime = time[0];
|
||||||
if(magic == InpMagicNumberRSIReverse)
|
// Only enter cooldown if it's a loss or if cooldown on loss is disabled
|
||||||
|
double profit = PositionGetDouble(POSITION_PROFIT);
|
||||||
|
if(!InpRSIReverseCooldownOnLoss || profit < 0)
|
||||||
{
|
{
|
||||||
datetime time[];
|
rsiReverseInCooldown = true;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close the position using helper function
|
||||||
|
ClosePositionByMagic(trade, _Symbol, magic);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#property version "1.00"
|
#property version "1.00"
|
||||||
|
|
||||||
#include <Trade\Trade.mqh>
|
#include <Trade\Trade.mqh>
|
||||||
|
#include "../_united/MagicNumberHelpers.mqh"
|
||||||
|
|
||||||
//--- Input parameters
|
//--- Input parameters
|
||||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_M10; // Timeframe for Analysis
|
input ENUM_TIMEFRAMES TimeFrame = PERIOD_M10; // Timeframe for Analysis
|
||||||
@@ -95,8 +96,8 @@ void OnTick()
|
|||||||
// Check for existing position
|
// Check for existing position
|
||||||
CheckExistingPosition();
|
CheckExistingPosition();
|
||||||
|
|
||||||
// Check for new entry signals
|
// Check for new entry signals - only if no position exists for THIS EA (magic number) on THIS symbol
|
||||||
if(!position_open)
|
if(!position_open && !PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
CheckEntrySignals();
|
CheckEntrySignals();
|
||||||
}
|
}
|
||||||
@@ -129,8 +130,8 @@ void CheckExistingPosition()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if position still exists
|
// Check if position still exists with correct magic number AND symbol for THIS EA
|
||||||
if(!PositionSelectByTicket(position_ticket))
|
if(!PositionSelectByTicketSymbolAndMagic(position_ticket, _Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
position_open = false;
|
position_open = false;
|
||||||
position_ticket = 0;
|
position_ticket = 0;
|
||||||
@@ -241,13 +242,31 @@ void CheckEntrySignals()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void OpenBuyPosition()
|
void OpenBuyPosition()
|
||||||
{
|
{
|
||||||
|
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
|
||||||
|
if(PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
return; // Position already exists for this EA
|
||||||
|
}
|
||||||
|
|
||||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||||
|
|
||||||
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
|
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
|
||||||
{
|
{
|
||||||
position_ticket = trade.ResultOrder();
|
ulong new_ticket = trade.ResultOrder();
|
||||||
position_open = true;
|
if(new_ticket > 0)
|
||||||
current_position_type = POSITION_TYPE_BUY;
|
{
|
||||||
|
// Verify position was opened for THIS EA (magic number) on THIS symbol
|
||||||
|
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
position_ticket = new_ticket;
|
||||||
|
position_open = true;
|
||||||
|
current_position_type = POSITION_TYPE_BUY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Error: Position opened but doesn't match EA magic number or symbol");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,13 +275,31 @@ void OpenBuyPosition()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void OpenSellPosition()
|
void OpenSellPosition()
|
||||||
{
|
{
|
||||||
|
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
|
||||||
|
if(PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
return; // Position already exists for this EA
|
||||||
|
}
|
||||||
|
|
||||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||||
|
|
||||||
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
|
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
|
||||||
{
|
{
|
||||||
position_ticket = trade.ResultOrder();
|
ulong new_ticket = trade.ResultOrder();
|
||||||
position_open = true;
|
if(new_ticket > 0)
|
||||||
current_position_type = POSITION_TYPE_SELL;
|
{
|
||||||
|
// Verify position was opened for THIS EA (magic number) on THIS symbol
|
||||||
|
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
position_ticket = new_ticket;
|
||||||
|
position_open = true;
|
||||||
|
current_position_type = POSITION_TYPE_SELL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Error: Position opened but doesn't match EA magic number or symbol");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,11 +308,20 @@ void OpenSellPosition()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void ClosePosition()
|
void ClosePosition()
|
||||||
{
|
{
|
||||||
if(trade.PositionClose(position_ticket))
|
// Close position using helper that verifies symbol AND magic number for THIS EA
|
||||||
|
if(ClosePositionByMagic(trade, _Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
position_open = false;
|
position_open = false;
|
||||||
position_ticket = 0;
|
position_ticket = 0;
|
||||||
rsi_against_position = false;
|
rsi_against_position = false;
|
||||||
bars_against_count = 0;
|
bars_against_count = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Position doesn't exist or wrong magic number - reset tracking
|
||||||
|
position_open = false;
|
||||||
|
position_ticket = 0;
|
||||||
|
rsi_against_position = false;
|
||||||
|
bars_against_count = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#property version "1.00"
|
#property version "1.00"
|
||||||
|
|
||||||
#include <Trade\Trade.mqh>
|
#include <Trade\Trade.mqh>
|
||||||
|
#include "../_united/MagicNumberHelpers.mqh"
|
||||||
|
|
||||||
//--- Input parameters
|
//--- Input parameters
|
||||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1; // Timeframe for Analysis
|
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1; // Timeframe for Analysis
|
||||||
@@ -95,8 +96,8 @@ void OnTick()
|
|||||||
// Check for existing position
|
// Check for existing position
|
||||||
CheckExistingPosition();
|
CheckExistingPosition();
|
||||||
|
|
||||||
// Check for new entry signals
|
// Check for new entry signals - only if no position exists for THIS EA (magic number) on THIS symbol
|
||||||
if(!position_open)
|
if(!position_open && !PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
CheckEntrySignals();
|
CheckEntrySignals();
|
||||||
}
|
}
|
||||||
@@ -129,8 +130,8 @@ void CheckExistingPosition()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if position still exists
|
// Check if position still exists with correct magic number AND symbol for THIS EA
|
||||||
if(!PositionSelectByTicket(position_ticket))
|
if(!PositionSelectByTicketSymbolAndMagic(position_ticket, _Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
position_open = false;
|
position_open = false;
|
||||||
position_ticket = 0;
|
position_ticket = 0;
|
||||||
@@ -241,13 +242,31 @@ void CheckEntrySignals()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void OpenBuyPosition()
|
void OpenBuyPosition()
|
||||||
{
|
{
|
||||||
|
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
|
||||||
|
if(PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
return; // Position already exists for this EA
|
||||||
|
}
|
||||||
|
|
||||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||||
|
|
||||||
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
|
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
|
||||||
{
|
{
|
||||||
position_ticket = trade.ResultOrder();
|
ulong new_ticket = trade.ResultOrder();
|
||||||
position_open = true;
|
if(new_ticket > 0)
|
||||||
current_position_type = POSITION_TYPE_BUY;
|
{
|
||||||
|
// Verify position was opened for THIS EA (magic number) on THIS symbol
|
||||||
|
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
position_ticket = new_ticket;
|
||||||
|
position_open = true;
|
||||||
|
current_position_type = POSITION_TYPE_BUY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Error: Position opened but doesn't match EA magic number or symbol");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,13 +275,31 @@ void OpenBuyPosition()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void OpenSellPosition()
|
void OpenSellPosition()
|
||||||
{
|
{
|
||||||
|
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
|
||||||
|
if(PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
return; // Position already exists for this EA
|
||||||
|
}
|
||||||
|
|
||||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||||
|
|
||||||
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
|
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
|
||||||
{
|
{
|
||||||
position_ticket = trade.ResultOrder();
|
ulong new_ticket = trade.ResultOrder();
|
||||||
position_open = true;
|
if(new_ticket > 0)
|
||||||
current_position_type = POSITION_TYPE_SELL;
|
{
|
||||||
|
// Verify position was opened for THIS EA (magic number) on THIS symbol
|
||||||
|
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
position_ticket = new_ticket;
|
||||||
|
position_open = true;
|
||||||
|
current_position_type = POSITION_TYPE_SELL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Error: Position opened but doesn't match EA magic number or symbol");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,11 +308,20 @@ void OpenSellPosition()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void ClosePosition()
|
void ClosePosition()
|
||||||
{
|
{
|
||||||
if(trade.PositionClose(position_ticket))
|
// Close position using helper that verifies symbol AND magic number for THIS EA
|
||||||
|
if(ClosePositionByMagic(trade, _Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
position_open = false;
|
position_open = false;
|
||||||
position_ticket = 0;
|
position_ticket = 0;
|
||||||
rsi_against_position = false;
|
rsi_against_position = false;
|
||||||
bars_against_count = 0;
|
bars_against_count = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Position doesn't exist or wrong magic number - reset tracking
|
||||||
|
position_open = false;
|
||||||
|
position_ticket = 0;
|
||||||
|
rsi_against_position = false;
|
||||||
|
bars_against_count = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#property version "1.00"
|
#property version "1.00"
|
||||||
|
|
||||||
#include <Trade\Trade.mqh>
|
#include <Trade\Trade.mqh>
|
||||||
|
#include "../_united/MagicNumberHelpers.mqh"
|
||||||
|
|
||||||
//--- Input parameters
|
//--- Input parameters
|
||||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H3; // Timeframe for Analysis
|
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H3; // Timeframe for Analysis
|
||||||
@@ -95,8 +96,8 @@ void OnTick()
|
|||||||
// Check for existing position
|
// Check for existing position
|
||||||
CheckExistingPosition();
|
CheckExistingPosition();
|
||||||
|
|
||||||
// Check for new entry signals
|
// Check for new entry signals - only if no position exists for THIS EA (magic number) on THIS symbol
|
||||||
if(!position_open)
|
if(!position_open && !PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
CheckEntrySignals();
|
CheckEntrySignals();
|
||||||
}
|
}
|
||||||
@@ -129,8 +130,8 @@ void CheckExistingPosition()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if position still exists
|
// Check if position still exists with correct magic number AND symbol for THIS EA
|
||||||
if(!PositionSelectByTicket(position_ticket))
|
if(!PositionSelectByTicketSymbolAndMagic(position_ticket, _Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
position_open = false;
|
position_open = false;
|
||||||
position_ticket = 0;
|
position_ticket = 0;
|
||||||
@@ -241,13 +242,31 @@ void CheckEntrySignals()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void OpenBuyPosition()
|
void OpenBuyPosition()
|
||||||
{
|
{
|
||||||
|
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
|
||||||
|
if(PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
return; // Position already exists for this EA
|
||||||
|
}
|
||||||
|
|
||||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||||
|
|
||||||
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
|
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
|
||||||
{
|
{
|
||||||
position_ticket = trade.ResultOrder();
|
ulong new_ticket = trade.ResultOrder();
|
||||||
position_open = true;
|
if(new_ticket > 0)
|
||||||
current_position_type = POSITION_TYPE_BUY;
|
{
|
||||||
|
// Verify position was opened for THIS EA (magic number) on THIS symbol
|
||||||
|
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
position_ticket = new_ticket;
|
||||||
|
position_open = true;
|
||||||
|
current_position_type = POSITION_TYPE_BUY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Error: Position opened but doesn't match EA magic number or symbol");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,13 +275,31 @@ void OpenBuyPosition()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void OpenSellPosition()
|
void OpenSellPosition()
|
||||||
{
|
{
|
||||||
|
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
|
||||||
|
if(PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
return; // Position already exists for this EA
|
||||||
|
}
|
||||||
|
|
||||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||||
|
|
||||||
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
|
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
|
||||||
{
|
{
|
||||||
position_ticket = trade.ResultOrder();
|
ulong new_ticket = trade.ResultOrder();
|
||||||
position_open = true;
|
if(new_ticket > 0)
|
||||||
current_position_type = POSITION_TYPE_SELL;
|
{
|
||||||
|
// Verify position was opened for THIS EA (magic number) on THIS symbol
|
||||||
|
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
position_ticket = new_ticket;
|
||||||
|
position_open = true;
|
||||||
|
current_position_type = POSITION_TYPE_SELL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Error: Position opened but doesn't match EA magic number or symbol");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,11 +308,20 @@ void OpenSellPosition()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void ClosePosition()
|
void ClosePosition()
|
||||||
{
|
{
|
||||||
if(trade.PositionClose(position_ticket))
|
// Close position using helper that verifies symbol AND magic number for THIS EA
|
||||||
|
if(ClosePositionByMagic(trade, _Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
position_open = false;
|
position_open = false;
|
||||||
position_ticket = 0;
|
position_ticket = 0;
|
||||||
rsi_against_position = false;
|
rsi_against_position = false;
|
||||||
bars_against_count = 0;
|
bars_against_count = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Position doesn't exist or wrong magic number - reset tracking
|
||||||
|
position_open = false;
|
||||||
|
position_ticket = 0;
|
||||||
|
rsi_against_position = false;
|
||||||
|
bars_against_count = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#property version "1.00"
|
#property version "1.00"
|
||||||
|
|
||||||
#include <Trade\Trade.mqh>
|
#include <Trade\Trade.mqh>
|
||||||
|
#include "../_united/MagicNumberHelpers.mqh"
|
||||||
|
|
||||||
//--- Input parameters
|
//--- Input parameters
|
||||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_M15; // Timeframe for Analysis
|
input ENUM_TIMEFRAMES TimeFrame = PERIOD_M15; // Timeframe for Analysis
|
||||||
@@ -95,8 +96,8 @@ void OnTick()
|
|||||||
// Check for existing position
|
// Check for existing position
|
||||||
CheckExistingPosition();
|
CheckExistingPosition();
|
||||||
|
|
||||||
// Check for new entry signals
|
// Check for new entry signals - only if no position exists for THIS EA (magic number) on THIS symbol
|
||||||
if(!position_open)
|
if(!position_open && !PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
CheckEntrySignals();
|
CheckEntrySignals();
|
||||||
}
|
}
|
||||||
@@ -129,8 +130,8 @@ void CheckExistingPosition()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if position still exists
|
// Check if position still exists with correct magic number AND symbol for THIS EA
|
||||||
if(!PositionSelectByTicket(position_ticket))
|
if(!PositionSelectByTicketSymbolAndMagic(position_ticket, _Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
position_open = false;
|
position_open = false;
|
||||||
position_ticket = 0;
|
position_ticket = 0;
|
||||||
@@ -241,13 +242,31 @@ void CheckEntrySignals()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void OpenBuyPosition()
|
void OpenBuyPosition()
|
||||||
{
|
{
|
||||||
|
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
|
||||||
|
if(PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
return; // Position already exists for this EA
|
||||||
|
}
|
||||||
|
|
||||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||||
|
|
||||||
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
|
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
|
||||||
{
|
{
|
||||||
position_ticket = trade.ResultOrder();
|
ulong new_ticket = trade.ResultOrder();
|
||||||
position_open = true;
|
if(new_ticket > 0)
|
||||||
current_position_type = POSITION_TYPE_BUY;
|
{
|
||||||
|
// Verify position was opened for THIS EA (magic number) on THIS symbol
|
||||||
|
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
position_ticket = new_ticket;
|
||||||
|
position_open = true;
|
||||||
|
current_position_type = POSITION_TYPE_BUY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Error: Position opened but doesn't match EA magic number or symbol");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,13 +275,31 @@ void OpenBuyPosition()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void OpenSellPosition()
|
void OpenSellPosition()
|
||||||
{
|
{
|
||||||
|
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
|
||||||
|
if(PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
return; // Position already exists for this EA
|
||||||
|
}
|
||||||
|
|
||||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||||
|
|
||||||
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
|
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
|
||||||
{
|
{
|
||||||
position_ticket = trade.ResultOrder();
|
ulong new_ticket = trade.ResultOrder();
|
||||||
position_open = true;
|
if(new_ticket > 0)
|
||||||
current_position_type = POSITION_TYPE_SELL;
|
{
|
||||||
|
// Verify position was opened for THIS EA (magic number) on THIS symbol
|
||||||
|
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
position_ticket = new_ticket;
|
||||||
|
position_open = true;
|
||||||
|
current_position_type = POSITION_TYPE_SELL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Error: Position opened but doesn't match EA magic number or symbol");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,11 +308,20 @@ void OpenSellPosition()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void ClosePosition()
|
void ClosePosition()
|
||||||
{
|
{
|
||||||
if(trade.PositionClose(position_ticket))
|
// Close position using helper that verifies symbol AND magic number for THIS EA
|
||||||
|
if(ClosePositionByMagic(trade, _Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
position_open = false;
|
position_open = false;
|
||||||
position_ticket = 0;
|
position_ticket = 0;
|
||||||
rsi_against_position = false;
|
rsi_against_position = false;
|
||||||
bars_against_count = 0;
|
bars_against_count = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Position doesn't exist or wrong magic number - reset tracking
|
||||||
|
position_open = false;
|
||||||
|
position_ticket = 0;
|
||||||
|
rsi_against_position = false;
|
||||||
|
bars_against_count = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#property version "1.00"
|
#property version "1.00"
|
||||||
|
|
||||||
#include <Trade\Trade.mqh>
|
#include <Trade\Trade.mqh>
|
||||||
|
#include "../_united/MagicNumberHelpers.mqh"
|
||||||
|
|
||||||
//--- Input parameters
|
//--- Input parameters
|
||||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1; // Timeframe for Analysis
|
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1; // Timeframe for Analysis
|
||||||
@@ -95,8 +96,8 @@ void OnTick()
|
|||||||
// Check for existing position
|
// Check for existing position
|
||||||
CheckExistingPosition();
|
CheckExistingPosition();
|
||||||
|
|
||||||
// Check for new entry signals
|
// Check for new entry signals - only if no position exists for THIS EA (magic number) on THIS symbol
|
||||||
if(!position_open)
|
if(!position_open && !PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
CheckEntrySignals();
|
CheckEntrySignals();
|
||||||
}
|
}
|
||||||
@@ -129,8 +130,8 @@ void CheckExistingPosition()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if position still exists
|
// Check if position still exists with correct magic number AND symbol for THIS EA
|
||||||
if(!PositionSelectByTicket(position_ticket))
|
if(!PositionSelectByTicketSymbolAndMagic(position_ticket, _Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
position_open = false;
|
position_open = false;
|
||||||
position_ticket = 0;
|
position_ticket = 0;
|
||||||
@@ -241,13 +242,31 @@ void CheckEntrySignals()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void OpenBuyPosition()
|
void OpenBuyPosition()
|
||||||
{
|
{
|
||||||
|
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
|
||||||
|
if(PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
return; // Position already exists for this EA
|
||||||
|
}
|
||||||
|
|
||||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||||
|
|
||||||
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
|
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
|
||||||
{
|
{
|
||||||
position_ticket = trade.ResultOrder();
|
ulong new_ticket = trade.ResultOrder();
|
||||||
position_open = true;
|
if(new_ticket > 0)
|
||||||
current_position_type = POSITION_TYPE_BUY;
|
{
|
||||||
|
// Verify position was opened for THIS EA (magic number) on THIS symbol
|
||||||
|
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
position_ticket = new_ticket;
|
||||||
|
position_open = true;
|
||||||
|
current_position_type = POSITION_TYPE_BUY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Error: Position opened but doesn't match EA magic number or symbol");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,13 +275,31 @@ void OpenBuyPosition()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void OpenSellPosition()
|
void OpenSellPosition()
|
||||||
{
|
{
|
||||||
|
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
|
||||||
|
if(PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
return; // Position already exists for this EA
|
||||||
|
}
|
||||||
|
|
||||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||||
|
|
||||||
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
|
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
|
||||||
{
|
{
|
||||||
position_ticket = trade.ResultOrder();
|
ulong new_ticket = trade.ResultOrder();
|
||||||
position_open = true;
|
if(new_ticket > 0)
|
||||||
current_position_type = POSITION_TYPE_SELL;
|
{
|
||||||
|
// Verify position was opened for THIS EA (magic number) on THIS symbol
|
||||||
|
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, MagicNumber))
|
||||||
|
{
|
||||||
|
position_ticket = new_ticket;
|
||||||
|
position_open = true;
|
||||||
|
current_position_type = POSITION_TYPE_SELL;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Error: Position opened but doesn't match EA magic number or symbol");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -271,11 +308,20 @@ void OpenSellPosition()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void ClosePosition()
|
void ClosePosition()
|
||||||
{
|
{
|
||||||
if(trade.PositionClose(position_ticket))
|
// Close position using helper that verifies symbol AND magic number for THIS EA
|
||||||
|
if(ClosePositionByMagic(trade, _Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
position_open = false;
|
position_open = false;
|
||||||
position_ticket = 0;
|
position_ticket = 0;
|
||||||
rsi_against_position = false;
|
rsi_against_position = false;
|
||||||
bars_against_count = 0;
|
bars_against_count = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Position doesn't exist or wrong magic number - reset tracking
|
||||||
|
position_open = false;
|
||||||
|
position_ticket = 0;
|
||||||
|
rsi_against_position = false;
|
||||||
|
bars_against_count = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#property version "1.00"
|
#property version "1.00"
|
||||||
|
|
||||||
#include <Trade\Trade.mqh>
|
#include <Trade\Trade.mqh>
|
||||||
|
#include "../_united/MagicNumberHelpers.mqh"
|
||||||
|
|
||||||
//--- Input parameters
|
//--- Input parameters
|
||||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1; // Timeframe for Analysis
|
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1; // Timeframe for Analysis
|
||||||
@@ -95,8 +96,8 @@ void OnTick()
|
|||||||
// Check for existing position
|
// Check for existing position
|
||||||
CheckExistingPosition();
|
CheckExistingPosition();
|
||||||
|
|
||||||
// Check for new entry signals
|
// Check for new entry signals (also verify no position exists with our magic number)
|
||||||
if(!position_open)
|
if(!position_open && !PositionExistsByMagic(_Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
CheckEntrySignals();
|
CheckEntrySignals();
|
||||||
}
|
}
|
||||||
@@ -129,8 +130,8 @@ void CheckExistingPosition()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if position still exists
|
// Check if position still exists with correct magic number
|
||||||
if(!PositionSelectByTicket(position_ticket))
|
if(!PositionSelectByTicketAndMagic(position_ticket, MagicNumber))
|
||||||
{
|
{
|
||||||
position_open = false;
|
position_open = false;
|
||||||
position_ticket = 0;
|
position_ticket = 0;
|
||||||
@@ -271,11 +272,20 @@ void OpenSellPosition()
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
void ClosePosition()
|
void ClosePosition()
|
||||||
{
|
{
|
||||||
if(trade.PositionClose(position_ticket))
|
// Close position using helper function that verifies symbol AND magic number
|
||||||
|
if(ClosePositionByMagic(trade, _Symbol, MagicNumber))
|
||||||
{
|
{
|
||||||
position_open = false;
|
position_open = false;
|
||||||
position_ticket = 0;
|
position_ticket = 0;
|
||||||
rsi_against_position = false;
|
rsi_against_position = false;
|
||||||
bars_against_count = 0;
|
bars_against_count = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Position doesn't exist or wrong magic number - reset tracking anyway
|
||||||
|
position_open = false;
|
||||||
|
position_ticket = 0;
|
||||||
|
rsi_against_position = false;
|
||||||
|
bars_against_count = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,159 @@
|
|||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| MagicNumberHelpers.mqh |
|
||||||
|
//| Copyright 2025, MetaQuotes Ltd. |
|
||||||
|
//| https://www.mql5.com |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||||||
|
#property link "https://www.mql5.com"
|
||||||
|
#property version "1.00"
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Select position by symbol and magic number |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
bool PositionSelectByMagic(string symbol, ulong magic_number)
|
||||||
|
{
|
||||||
|
// First try to find position by symbol
|
||||||
|
if(!PositionSelect(symbol))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Check if the selected position has the correct magic number
|
||||||
|
if(PositionGetInteger(POSITION_MAGIC) != magic_number)
|
||||||
|
{
|
||||||
|
// Position exists but wrong magic number, search all positions
|
||||||
|
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if(PositionGetTicket(i) > 0)
|
||||||
|
{
|
||||||
|
if(PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||||
|
PositionGetInteger(POSITION_MAGIC) == magic_number)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Select position by ticket and verify magic number and symbol |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
bool PositionSelectByTicketAndMagic(ulong ticket, ulong magic_number)
|
||||||
|
{
|
||||||
|
if(!PositionSelectByTicket(ticket))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (PositionGetInteger(POSITION_MAGIC) == magic_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Select position by ticket and verify symbol, magic number |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
bool PositionSelectByTicketSymbolAndMagic(ulong ticket, string symbol, ulong magic_number)
|
||||||
|
{
|
||||||
|
if(!PositionSelectByTicket(ticket))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||||
|
PositionGetInteger(POSITION_MAGIC) == magic_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Check if position exists with correct magic number |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
bool PositionExistsByMagic(string symbol, ulong magic_number)
|
||||||
|
{
|
||||||
|
return PositionSelectByMagic(symbol, magic_number);
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Get position ticket by symbol and magic number |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
ulong GetPositionTicketByMagic(string symbol, ulong magic_number)
|
||||||
|
{
|
||||||
|
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
ulong ticket = PositionGetTicket(i);
|
||||||
|
if(ticket > 0)
|
||||||
|
{
|
||||||
|
if(PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||||
|
PositionGetInteger(POSITION_MAGIC) == magic_number)
|
||||||
|
{
|
||||||
|
return ticket;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Close position by symbol and magic number |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
bool ClosePositionByMagic(CTrade &trade_obj, string symbol, ulong magic_number)
|
||||||
|
{
|
||||||
|
ulong ticket = GetPositionTicketByMagic(symbol, magic_number);
|
||||||
|
if(ticket == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return trade_obj.PositionClose(ticket);
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Modify position by symbol and magic number |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
bool ModifyPositionByMagic(CTrade &trade_obj, string symbol, ulong magic_number,
|
||||||
|
double sl, double tp)
|
||||||
|
{
|
||||||
|
ulong ticket = GetPositionTicketByMagic(symbol, magic_number);
|
||||||
|
if(ticket == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return trade_obj.PositionModify(ticket, sl, tp);
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Get position profit by symbol and magic number |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
double GetPositionProfitByMagic(string symbol, ulong magic_number)
|
||||||
|
{
|
||||||
|
if(!PositionSelectByMagic(symbol, magic_number))
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
return PositionGetDouble(POSITION_PROFIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Get position type by symbol and magic number |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
ENUM_POSITION_TYPE GetPositionTypeByMagic(string symbol, ulong magic_number)
|
||||||
|
{
|
||||||
|
if(!PositionSelectByMagic(symbol, magic_number))
|
||||||
|
return WRONG_VALUE;
|
||||||
|
|
||||||
|
return (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Count positions by symbol and magic number |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
int CountPositionsByMagic(string symbol, ulong magic_number)
|
||||||
|
{
|
||||||
|
int count = 0;
|
||||||
|
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
ulong ticket = PositionGetTicket(i);
|
||||||
|
if(ticket > 0)
|
||||||
|
{
|
||||||
|
if(PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||||
|
PositionGetInteger(POSITION_MAGIC) == magic_number)
|
||||||
|
{
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
@@ -0,0 +1,962 @@
|
|||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| UnitedEA.mq5 |
|
||||||
|
//| Copyright 2025, MetaQuotes Ltd. |
|
||||||
|
//| https://www.mql5.com |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||||||
|
#property link "https://www.mql5.com"
|
||||||
|
#property version "1.00"
|
||||||
|
#property description "United EA - Runs multiple strategies on multiple instruments with instrument-specific parameters"
|
||||||
|
|
||||||
|
#include <Trade\Trade.mqh>
|
||||||
|
#include "MagicNumberHelpers.mqh"
|
||||||
|
|
||||||
|
//--- Strategy Selection
|
||||||
|
input bool EnableRSIScalping = true; // Enable RSI Scalping Strategy
|
||||||
|
input bool EnableMeanReversion = true; // Enable Mean Reversion Strategy
|
||||||
|
input bool EnableDarvasBox = true; // Enable Darvas Box Strategy
|
||||||
|
input bool EnableRSICrossOver = true; // Enable RSI Crossover Strategy
|
||||||
|
input bool EnableRSIMidPoint = true; // Enable RSI Midpoint Strategy
|
||||||
|
|
||||||
|
//--- Instrument Selection for RSI Scalping (each with its own parameters)
|
||||||
|
input bool EnableRSI_XAUUSD = true; // Enable RSI Scalping on XAUUSD
|
||||||
|
input bool EnableRSI_APPL = true; // Enable RSI Scalping on APPL
|
||||||
|
input bool EnableRSI_BTCUSD = true; // Enable RSI Scalping on BTCUSD
|
||||||
|
input bool EnableRSI_MSFT = true; // Enable RSI Scalping on MSFT
|
||||||
|
input bool EnableRSI_NVDA = true; // Enable RSI Scalping on NVDA
|
||||||
|
input bool EnableRSI_TSLA = true; // Enable RSI Scalping on TSLA
|
||||||
|
|
||||||
|
//--- Magic Numbers for RSI Scalping (one per instrument)
|
||||||
|
input int MagicNumber_RSI_XAUUSD = 129102315; // Magic Number for RSI Scalping XAUUSD
|
||||||
|
input int MagicNumber_RSI_APPL = 123457; // Magic Number for RSI Scalping APPL
|
||||||
|
input int MagicNumber_RSI_BTCUSD = 123459123; // Magic Number for RSI Scalping BTCUSD
|
||||||
|
input int MagicNumber_RSI_MSFT = 123456; // Magic Number for RSI Scalping MSFT
|
||||||
|
input int MagicNumber_RSI_NVDA = 12345; // Magic Number for RSI Scalping NVDA
|
||||||
|
input int MagicNumber_RSI_TSLA = 125421321; // Magic Number for RSI Scalping TSLA
|
||||||
|
|
||||||
|
//--- Magic Numbers for Other Strategies
|
||||||
|
input int MagicNumber_MeanReversion = 12351; // Magic Number for Mean Reversion
|
||||||
|
input int MagicNumber_DarvasBox = 135790; // Magic Number for Darvas Box
|
||||||
|
input int MagicNumber_RSICrossOver = 123456; // Magic Number for RSI Crossover
|
||||||
|
input int MagicNumber_RSIMidPoint = 123457; // Magic Number for RSI Midpoint
|
||||||
|
|
||||||
|
//--- RSI Scalping Parameters: XAUUSD
|
||||||
|
input ENUM_TIMEFRAMES RSI_XAUUSD_TimeFrame = PERIOD_H1;
|
||||||
|
input int RSI_XAUUSD_Period = 14;
|
||||||
|
input double RSI_XAUUSD_Overbought = 71;
|
||||||
|
input double RSI_XAUUSD_Oversold = 57;
|
||||||
|
input double RSI_XAUUSD_Target_Buy = 80;
|
||||||
|
input double RSI_XAUUSD_Target_Sell = 57;
|
||||||
|
input int RSI_XAUUSD_BarsToWait = 4;
|
||||||
|
input double RSI_XAUUSD_LotSize = 0.1;
|
||||||
|
|
||||||
|
//--- RSI Scalping Parameters: APPL
|
||||||
|
input ENUM_TIMEFRAMES RSI_APPL_TimeFrame = PERIOD_M10;
|
||||||
|
input int RSI_APPL_Period = 14;
|
||||||
|
input double RSI_APPL_Overbought = 80;
|
||||||
|
input double RSI_APPL_Oversold = 78;
|
||||||
|
input double RSI_APPL_Target_Buy = 94;
|
||||||
|
input double RSI_APPL_Target_Sell = 44;
|
||||||
|
input int RSI_APPL_BarsToWait = 7;
|
||||||
|
input double RSI_APPL_LotSize = 25;
|
||||||
|
|
||||||
|
//--- RSI Scalping Parameters: BTCUSD
|
||||||
|
input ENUM_TIMEFRAMES RSI_BTCUSD_TimeFrame = PERIOD_H1;
|
||||||
|
input int RSI_BTCUSD_Period = 14;
|
||||||
|
input double RSI_BTCUSD_Overbought = 90;
|
||||||
|
input double RSI_BTCUSD_Oversold = 73;
|
||||||
|
input double RSI_BTCUSD_Target_Buy = 88;
|
||||||
|
input double RSI_BTCUSD_Target_Sell = 48;
|
||||||
|
input int RSI_BTCUSD_BarsToWait = 6;
|
||||||
|
input double RSI_BTCUSD_LotSize = 0.1;
|
||||||
|
|
||||||
|
//--- RSI Scalping Parameters: MSFT
|
||||||
|
input ENUM_TIMEFRAMES RSI_MSFT_TimeFrame = PERIOD_H3;
|
||||||
|
input int RSI_MSFT_Period = 14;
|
||||||
|
input double RSI_MSFT_Overbought = 19;
|
||||||
|
input double RSI_MSFT_Oversold = 50;
|
||||||
|
input double RSI_MSFT_Target_Buy = 71;
|
||||||
|
input double RSI_MSFT_Target_Sell = 70;
|
||||||
|
input int RSI_MSFT_BarsToWait = 1;
|
||||||
|
input double RSI_MSFT_LotSize = 50;
|
||||||
|
|
||||||
|
//--- RSI Scalping Parameters: NVDA
|
||||||
|
input ENUM_TIMEFRAMES RSI_NVDA_TimeFrame = PERIOD_M15;
|
||||||
|
input int RSI_NVDA_Period = 8;
|
||||||
|
input double RSI_NVDA_Overbought = 36;
|
||||||
|
input double RSI_NVDA_Oversold = 38;
|
||||||
|
input double RSI_NVDA_Target_Buy = 90;
|
||||||
|
input double RSI_NVDA_Target_Sell = 70;
|
||||||
|
input int RSI_NVDA_BarsToWait = 5;
|
||||||
|
input double RSI_NVDA_LotSize = 50;
|
||||||
|
|
||||||
|
//--- RSI Scalping Parameters: TSLA
|
||||||
|
input ENUM_TIMEFRAMES RSI_TSLA_TimeFrame = PERIOD_H1;
|
||||||
|
input int RSI_TSLA_Period = 14;
|
||||||
|
input double RSI_TSLA_Overbought = 54;
|
||||||
|
input double RSI_TSLA_Oversold = 73;
|
||||||
|
input double RSI_TSLA_Target_Buy = 87;
|
||||||
|
input double RSI_TSLA_Target_Sell = 33;
|
||||||
|
input int RSI_TSLA_BarsToWait = 1;
|
||||||
|
input double RSI_TSLA_LotSize = 50;
|
||||||
|
|
||||||
|
//--- Mean Reversion Parameters
|
||||||
|
input int EMA_Periode = 46;
|
||||||
|
input double PreisSchwelle = 600.0;
|
||||||
|
input double SteigungSchwelle = 80.0;
|
||||||
|
input int ÜberwachungTimeout = 800;
|
||||||
|
input double TrailingStop = 260.0;
|
||||||
|
input double MeanRev_LotSize = 0.03;
|
||||||
|
input ENUM_TIMEFRAMES MeanRev_Timeframe = PERIOD_H1;
|
||||||
|
|
||||||
|
//--- Structure for RSI Scalping Strategy Instance
|
||||||
|
struct RSIScalpingStrategy
|
||||||
|
{
|
||||||
|
string symbol;
|
||||||
|
int magic_number;
|
||||||
|
ENUM_TIMEFRAMES timeframe;
|
||||||
|
int period;
|
||||||
|
double overbought;
|
||||||
|
double oversold;
|
||||||
|
double target_buy;
|
||||||
|
double target_sell;
|
||||||
|
int bars_to_wait;
|
||||||
|
double lot_size;
|
||||||
|
int rsi_handle;
|
||||||
|
double rsi_buffer[];
|
||||||
|
ulong position_ticket;
|
||||||
|
bool position_open;
|
||||||
|
bool buy_position_open;
|
||||||
|
bool sell_position_open;
|
||||||
|
datetime last_bar_time;
|
||||||
|
bool rsi_against_position;
|
||||||
|
int bars_against_count;
|
||||||
|
ENUM_POSITION_TYPE current_position_type;
|
||||||
|
};
|
||||||
|
|
||||||
|
//--- Global variables
|
||||||
|
CTrade trade;
|
||||||
|
RSIScalpingStrategy rsi_strategies[6]; // Array for 6 instruments
|
||||||
|
int rsi_strategy_count = 0;
|
||||||
|
|
||||||
|
int ema_handle_meanrev = INVALID_HANDLE;
|
||||||
|
double ema_array[];
|
||||||
|
ulong meanrev_ticket = 0;
|
||||||
|
bool meanrev_position_open = false;
|
||||||
|
datetime last_bar_time_meanrev = 0;
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Expert initialization function |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
int OnInit()
|
||||||
|
{
|
||||||
|
// Initialize trade object
|
||||||
|
trade.SetDeviationInPoints(10);
|
||||||
|
trade.SetTypeFilling(ORDER_FILLING_FOK);
|
||||||
|
|
||||||
|
// Initialize RSI Scalping strategies for each enabled instrument
|
||||||
|
if(EnableRSIScalping)
|
||||||
|
{
|
||||||
|
if(EnableRSI_XAUUSD)
|
||||||
|
{
|
||||||
|
InitializeRSIStrategy("XAUUSD", MagicNumber_RSI_XAUUSD,
|
||||||
|
RSI_XAUUSD_TimeFrame, RSI_XAUUSD_Period,
|
||||||
|
RSI_XAUUSD_Overbought, RSI_XAUUSD_Oversold,
|
||||||
|
RSI_XAUUSD_Target_Buy, RSI_XAUUSD_Target_Sell,
|
||||||
|
RSI_XAUUSD_BarsToWait, RSI_XAUUSD_LotSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(EnableRSI_APPL)
|
||||||
|
{
|
||||||
|
// Try different symbol variations for Apple (Pepperstone typically uses AAPL without suffix)
|
||||||
|
// Try: AAPL, AAPL.US, APPL (in case of typo in broker)
|
||||||
|
string appl_symbol = GetValidSymbol("AAPL", "AAPL.US");
|
||||||
|
if(appl_symbol != "")
|
||||||
|
{
|
||||||
|
InitializeRSIStrategy(appl_symbol, MagicNumber_RSI_APPL,
|
||||||
|
RSI_APPL_TimeFrame, RSI_APPL_Period,
|
||||||
|
RSI_APPL_Overbought, RSI_APPL_Oversold,
|
||||||
|
RSI_APPL_Target_Buy, RSI_APPL_Target_Sell,
|
||||||
|
RSI_APPL_BarsToWait, RSI_APPL_LotSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Skipping AAPL strategy - symbol not available");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(EnableRSI_BTCUSD)
|
||||||
|
{
|
||||||
|
InitializeRSIStrategy("BTCUSD", MagicNumber_RSI_BTCUSD,
|
||||||
|
RSI_BTCUSD_TimeFrame, RSI_BTCUSD_Period,
|
||||||
|
RSI_BTCUSD_Overbought, RSI_BTCUSD_Oversold,
|
||||||
|
RSI_BTCUSD_Target_Buy, RSI_BTCUSD_Target_Sell,
|
||||||
|
RSI_BTCUSD_BarsToWait, RSI_BTCUSD_LotSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(EnableRSI_MSFT)
|
||||||
|
{
|
||||||
|
// Pepperstone typically uses MSFT without suffix
|
||||||
|
string msft_symbol = GetValidSymbol("MSFT", "MSFT.US");
|
||||||
|
if(msft_symbol != "")
|
||||||
|
{
|
||||||
|
InitializeRSIStrategy(msft_symbol, MagicNumber_RSI_MSFT,
|
||||||
|
RSI_MSFT_TimeFrame, RSI_MSFT_Period,
|
||||||
|
RSI_MSFT_Overbought, RSI_MSFT_Oversold,
|
||||||
|
RSI_MSFT_Target_Buy, RSI_MSFT_Target_Sell,
|
||||||
|
RSI_MSFT_BarsToWait, RSI_MSFT_LotSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Skipping MSFT strategy - symbol not available");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(EnableRSI_NVDA)
|
||||||
|
{
|
||||||
|
// Pepperstone typically uses NVDA without suffix
|
||||||
|
string nvda_symbol = GetValidSymbol("NVDA", "NVDA.US");
|
||||||
|
if(nvda_symbol != "")
|
||||||
|
{
|
||||||
|
InitializeRSIStrategy(nvda_symbol, MagicNumber_RSI_NVDA,
|
||||||
|
RSI_NVDA_TimeFrame, RSI_NVDA_Period,
|
||||||
|
RSI_NVDA_Overbought, RSI_NVDA_Oversold,
|
||||||
|
RSI_NVDA_Target_Buy, RSI_NVDA_Target_Sell,
|
||||||
|
RSI_NVDA_BarsToWait, RSI_NVDA_LotSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Skipping NVDA strategy - symbol not available");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(EnableRSI_TSLA)
|
||||||
|
{
|
||||||
|
// Pepperstone typically uses TSLA without suffix
|
||||||
|
string tsla_symbol = GetValidSymbol("TSLA", "TSLA.US");
|
||||||
|
if(tsla_symbol != "")
|
||||||
|
{
|
||||||
|
InitializeRSIStrategy(tsla_symbol, MagicNumber_RSI_TSLA,
|
||||||
|
RSI_TSLA_TimeFrame, RSI_TSLA_Period,
|
||||||
|
RSI_TSLA_Overbought, RSI_TSLA_Oversold,
|
||||||
|
RSI_TSLA_Target_Buy, RSI_TSLA_Target_Sell,
|
||||||
|
RSI_TSLA_BarsToWait, RSI_TSLA_LotSize);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Skipping TSLA strategy - symbol not available");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize Mean Reversion indicator
|
||||||
|
if(EnableMeanReversion)
|
||||||
|
{
|
||||||
|
ema_handle_meanrev = iMA(_Symbol, MeanRev_Timeframe, EMA_Periode, 0, MODE_EMA, PRICE_CLOSE);
|
||||||
|
if(ema_handle_meanrev == INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
Print("Error: Failed to create EMA indicator for Mean Reversion");
|
||||||
|
return(INIT_FAILED);
|
||||||
|
}
|
||||||
|
ArraySetAsSeries(ema_array, true);
|
||||||
|
trade.SetExpertMagicNumber(MagicNumber_MeanReversion);
|
||||||
|
Print("Mean Reversion Strategy initialized with Magic: ", MagicNumber_MeanReversion);
|
||||||
|
}
|
||||||
|
|
||||||
|
Print("United EA initialized successfully");
|
||||||
|
Print("Active RSI Scalping Strategies: ", rsi_strategy_count);
|
||||||
|
for(int i = 0; i < rsi_strategy_count; i++)
|
||||||
|
{
|
||||||
|
Print(" - ", rsi_strategies[i].symbol, " (Magic: ", rsi_strategies[i].magic_number,
|
||||||
|
", TF: ", EnumToString(rsi_strategies[i].timeframe), ")");
|
||||||
|
}
|
||||||
|
if(EnableMeanReversion) Print(" - Mean Reversion (Magic: ", MagicNumber_MeanReversion, ")");
|
||||||
|
|
||||||
|
return(INIT_SUCCEEDED);
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Get valid symbol name (try variations) |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
string GetValidSymbol(string preferred, string fallback)
|
||||||
|
{
|
||||||
|
string symbols_to_try[];
|
||||||
|
ArrayResize(symbols_to_try, 0);
|
||||||
|
|
||||||
|
// Build list of symbols to try
|
||||||
|
ArrayResize(symbols_to_try, 1);
|
||||||
|
symbols_to_try[0] = preferred;
|
||||||
|
|
||||||
|
if(fallback != preferred)
|
||||||
|
{
|
||||||
|
ArrayResize(symbols_to_try, 2);
|
||||||
|
symbols_to_try[1] = fallback;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If preferred has .US, also try without it
|
||||||
|
if(StringFind(preferred, ".US") >= 0)
|
||||||
|
{
|
||||||
|
string without_suffix = preferred;
|
||||||
|
StringReplace(without_suffix, ".US", "");
|
||||||
|
if(without_suffix != fallback)
|
||||||
|
{
|
||||||
|
int size = ArraySize(symbols_to_try);
|
||||||
|
ArrayResize(symbols_to_try, size + 1);
|
||||||
|
symbols_to_try[size] = without_suffix;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try each symbol variation
|
||||||
|
for(int i = 0; i < ArraySize(symbols_to_try); i++)
|
||||||
|
{
|
||||||
|
string test_symbol = symbols_to_try[i];
|
||||||
|
|
||||||
|
// Try to select the symbol
|
||||||
|
if(!SymbolSelect(test_symbol, true))
|
||||||
|
{
|
||||||
|
// Symbol might already be selected, check if it exists
|
||||||
|
if(!SymbolInfoInteger(test_symbol, SYMBOL_SELECT))
|
||||||
|
{
|
||||||
|
continue; // Symbol doesn't exist, try next
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify symbol is visible
|
||||||
|
if(SymbolInfoInteger(test_symbol, SYMBOL_VISIBLE))
|
||||||
|
{
|
||||||
|
// Check if we can get price data (symbol is really available)
|
||||||
|
// During initialization, prices might be 0 if symbol is still synchronizing
|
||||||
|
// So we'll be lenient and accept the symbol if it's visible
|
||||||
|
double bid = SymbolInfoDouble(test_symbol, SYMBOL_BID);
|
||||||
|
double ask = SymbolInfoDouble(test_symbol, SYMBOL_ASK);
|
||||||
|
|
||||||
|
// Accept symbol if it has valid prices OR if it's visible (might be syncing)
|
||||||
|
if((bid > 0 && ask > 0) || SymbolInfoInteger(test_symbol, SYMBOL_VISIBLE))
|
||||||
|
{
|
||||||
|
if(bid > 0 && ask > 0)
|
||||||
|
{
|
||||||
|
Print("Using symbol: ", test_symbol, " (Bid: ", bid, ", Ask: ", ask, ")");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Using symbol: ", test_symbol, " (synchronizing, prices not yet available)");
|
||||||
|
}
|
||||||
|
return test_symbol;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Print("Error: Could not find valid symbol for ", preferred, " or ", fallback);
|
||||||
|
Print("Tried ", ArraySize(symbols_to_try), " symbol variations:");
|
||||||
|
for(int i = 0; i < ArraySize(symbols_to_try); i++)
|
||||||
|
{
|
||||||
|
Print(" ", (i+1), ". ", symbols_to_try[i]);
|
||||||
|
}
|
||||||
|
Print("These symbols may not be available in your broker's symbol list.");
|
||||||
|
Print("Please add the symbol to Market Watch or disable this strategy.");
|
||||||
|
|
||||||
|
return ""; // Return empty string to indicate failure
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Initialize RSI Scalping Strategy for an instrument |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
void InitializeRSIStrategy(string symbol, int magic, ENUM_TIMEFRAMES tf, int period,
|
||||||
|
double overbought, double oversold, double target_buy,
|
||||||
|
double target_sell, int bars_wait, double lot_size)
|
||||||
|
{
|
||||||
|
if(rsi_strategy_count >= 6)
|
||||||
|
{
|
||||||
|
Print("Error: Maximum 6 RSI strategies allowed");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Work directly with array element (no reference)
|
||||||
|
rsi_strategies[rsi_strategy_count].symbol = symbol;
|
||||||
|
rsi_strategies[rsi_strategy_count].magic_number = magic;
|
||||||
|
rsi_strategies[rsi_strategy_count].timeframe = tf;
|
||||||
|
rsi_strategies[rsi_strategy_count].period = period;
|
||||||
|
rsi_strategies[rsi_strategy_count].overbought = overbought;
|
||||||
|
rsi_strategies[rsi_strategy_count].oversold = oversold;
|
||||||
|
rsi_strategies[rsi_strategy_count].target_buy = target_buy;
|
||||||
|
rsi_strategies[rsi_strategy_count].target_sell = target_sell;
|
||||||
|
rsi_strategies[rsi_strategy_count].bars_to_wait = bars_wait;
|
||||||
|
rsi_strategies[rsi_strategy_count].lot_size = lot_size;
|
||||||
|
rsi_strategies[rsi_strategy_count].position_ticket = 0;
|
||||||
|
rsi_strategies[rsi_strategy_count].position_open = false;
|
||||||
|
rsi_strategies[rsi_strategy_count].buy_position_open = false;
|
||||||
|
rsi_strategies[rsi_strategy_count].sell_position_open = false;
|
||||||
|
rsi_strategies[rsi_strategy_count].last_bar_time = 0;
|
||||||
|
rsi_strategies[rsi_strategy_count].rsi_against_position = false;
|
||||||
|
rsi_strategies[rsi_strategy_count].bars_against_count = 0;
|
||||||
|
rsi_strategies[rsi_strategy_count].current_position_type = WRONG_VALUE;
|
||||||
|
|
||||||
|
// Ensure symbol is selected before creating indicator
|
||||||
|
if(!SymbolSelect(symbol, true))
|
||||||
|
{
|
||||||
|
// Symbol might already be selected, check if it exists
|
||||||
|
if(!SymbolInfoInteger(symbol, SYMBOL_SELECT))
|
||||||
|
{
|
||||||
|
Print("Error: Failed to select symbol ", symbol, " for RSI indicator");
|
||||||
|
Print("Please ensure the symbol exists in Market Watch or add it manually");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify symbol is visible (prices might be 0 during synchronization)
|
||||||
|
if(!SymbolInfoInteger(symbol, SYMBOL_VISIBLE))
|
||||||
|
{
|
||||||
|
Print("Error: Symbol ", symbol, " is not visible");
|
||||||
|
Print("Please add the symbol to Market Watch");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check prices (but don't fail if they're 0 - symbol might be syncing)
|
||||||
|
double bid = SymbolInfoDouble(symbol, SYMBOL_BID);
|
||||||
|
double ask = SymbolInfoDouble(symbol, SYMBOL_ASK);
|
||||||
|
if(bid <= 0 || ask <= 0)
|
||||||
|
{
|
||||||
|
Print("Warning: Symbol ", symbol, " has no prices yet (Bid: ", bid, ", Ask: ", ask, ")");
|
||||||
|
Print("Symbol may be synchronizing. Will attempt to create indicator anyway...");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create RSI indicator for this symbol
|
||||||
|
rsi_strategies[rsi_strategy_count].rsi_handle = iRSI(symbol, tf, period, PRICE_CLOSE);
|
||||||
|
if(rsi_strategies[rsi_strategy_count].rsi_handle == INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
int error = GetLastError();
|
||||||
|
Print("Error: Failed to create RSI indicator for ", symbol, " (Error: ", error, ")");
|
||||||
|
Print("Symbol: ", symbol, ", Timeframe: ", EnumToString(tf), ", Period: ", period);
|
||||||
|
Print("Please check if the symbol is available in your broker's symbol list");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArraySetAsSeries(rsi_strategies[rsi_strategy_count].rsi_buffer, true);
|
||||||
|
rsi_strategy_count++;
|
||||||
|
|
||||||
|
Print("RSI Scalping Strategy initialized for ", symbol,
|
||||||
|
" (Magic: ", magic, ", TF: ", EnumToString(tf), ")");
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Expert deinitialization function |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
void OnDeinit(const int reason)
|
||||||
|
{
|
||||||
|
// Release all RSI indicators
|
||||||
|
for(int i = 0; i < rsi_strategy_count; i++)
|
||||||
|
{
|
||||||
|
if(rsi_strategies[i].rsi_handle != INVALID_HANDLE)
|
||||||
|
IndicatorRelease(rsi_strategies[i].rsi_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(ema_handle_meanrev != INVALID_HANDLE)
|
||||||
|
IndicatorRelease(ema_handle_meanrev);
|
||||||
|
|
||||||
|
Print("United EA deinitialized");
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Expert tick function |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
void OnTick()
|
||||||
|
{
|
||||||
|
// Run RSI Scalping Strategies for all enabled instruments
|
||||||
|
if(EnableRSIScalping)
|
||||||
|
{
|
||||||
|
for(int i = 0; i < rsi_strategy_count; i++)
|
||||||
|
{
|
||||||
|
RunRSIScalpingStrategy(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run Mean Reversion Strategy
|
||||||
|
if(EnableMeanReversion)
|
||||||
|
{
|
||||||
|
RunMeanReversionStrategy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| RSI Scalping Strategy for a specific instrument (by index) |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
void RunRSIScalpingStrategy(int strategy_index)
|
||||||
|
{
|
||||||
|
// Access strategy by index (no reference needed)
|
||||||
|
// Check if we have enough bars
|
||||||
|
if(Bars(rsi_strategies[strategy_index].symbol, rsi_strategies[strategy_index].timeframe) <
|
||||||
|
rsi_strategies[strategy_index].period + 2)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Check if this is a new bar
|
||||||
|
datetime current_bar_time = iTime(rsi_strategies[strategy_index].symbol,
|
||||||
|
rsi_strategies[strategy_index].timeframe, 0);
|
||||||
|
if(current_bar_time == rsi_strategies[strategy_index].last_bar_time)
|
||||||
|
return;
|
||||||
|
|
||||||
|
rsi_strategies[strategy_index].last_bar_time = current_bar_time;
|
||||||
|
|
||||||
|
// Update RSI values
|
||||||
|
if(CopyBuffer(rsi_strategies[strategy_index].rsi_handle, 0, 0, 3,
|
||||||
|
rsi_strategies[strategy_index].rsi_buffer) < 3)
|
||||||
|
return;
|
||||||
|
|
||||||
|
double rsi_current = rsi_strategies[strategy_index].rsi_buffer[0];
|
||||||
|
double rsi_prev = rsi_strategies[strategy_index].rsi_buffer[1];
|
||||||
|
double rsi_two_bars_ago = rsi_strategies[strategy_index].rsi_buffer[2];
|
||||||
|
|
||||||
|
// Set magic number for this strategy
|
||||||
|
trade.SetExpertMagicNumber(rsi_strategies[strategy_index].magic_number);
|
||||||
|
|
||||||
|
// Check if position exists (regardless of flag state - handles EA restart)
|
||||||
|
bool position_exists = PositionExistsByMagic(rsi_strategies[strategy_index].symbol,
|
||||||
|
rsi_strategies[strategy_index].magic_number);
|
||||||
|
|
||||||
|
if(position_exists)
|
||||||
|
{
|
||||||
|
// Get actual position type and ticket
|
||||||
|
ulong ticket = GetPositionTicketByMagic(rsi_strategies[strategy_index].symbol,
|
||||||
|
rsi_strategies[strategy_index].magic_number);
|
||||||
|
ENUM_POSITION_TYPE pos_type = GetPositionTypeByMagic(rsi_strategies[strategy_index].symbol,
|
||||||
|
rsi_strategies[strategy_index].magic_number);
|
||||||
|
|
||||||
|
if(ticket == 0 || pos_type == WRONG_VALUE)
|
||||||
|
{
|
||||||
|
// Position doesn't exist or invalid
|
||||||
|
rsi_strategies[strategy_index].position_open = false;
|
||||||
|
rsi_strategies[strategy_index].buy_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].sell_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].position_ticket = 0;
|
||||||
|
rsi_strategies[strategy_index].rsi_against_position = false;
|
||||||
|
rsi_strategies[strategy_index].bars_against_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update position tracking with fine-grained flags
|
||||||
|
rsi_strategies[strategy_index].position_ticket = ticket;
|
||||||
|
rsi_strategies[strategy_index].position_open = true;
|
||||||
|
rsi_strategies[strategy_index].current_position_type = pos_type;
|
||||||
|
|
||||||
|
if(pos_type == POSITION_TYPE_BUY)
|
||||||
|
{
|
||||||
|
rsi_strategies[strategy_index].buy_position_open = true;
|
||||||
|
rsi_strategies[strategy_index].sell_position_open = false;
|
||||||
|
}
|
||||||
|
else if(pos_type == POSITION_TYPE_SELL)
|
||||||
|
{
|
||||||
|
rsi_strategies[strategy_index].buy_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].sell_position_open = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify position still exists with correct ticket, symbol, and magic number
|
||||||
|
if(!PositionSelectByTicketSymbolAndMagic(rsi_strategies[strategy_index].position_ticket,
|
||||||
|
rsi_strategies[strategy_index].symbol,
|
||||||
|
rsi_strategies[strategy_index].magic_number))
|
||||||
|
{
|
||||||
|
// Position was closed externally or doesn't match this instrument, reset tracking
|
||||||
|
rsi_strategies[strategy_index].position_open = false;
|
||||||
|
rsi_strategies[strategy_index].buy_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].sell_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].position_ticket = 0;
|
||||||
|
rsi_strategies[strategy_index].rsi_against_position = false;
|
||||||
|
rsi_strategies[strategy_index].bars_against_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Double-check position type matches our tracking (instrument-specific verification)
|
||||||
|
ENUM_POSITION_TYPE actual_pos_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||||
|
string actual_symbol = PositionGetString(POSITION_SYMBOL);
|
||||||
|
|
||||||
|
if(actual_symbol != rsi_strategies[strategy_index].symbol)
|
||||||
|
{
|
||||||
|
Print("Warning: Position symbol mismatch for ", rsi_strategies[strategy_index].symbol,
|
||||||
|
" - Found: ", actual_symbol, ". Resetting tracking.");
|
||||||
|
rsi_strategies[strategy_index].position_open = false;
|
||||||
|
rsi_strategies[strategy_index].buy_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].sell_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].position_ticket = 0;
|
||||||
|
rsi_strategies[strategy_index].rsi_against_position = false;
|
||||||
|
rsi_strategies[strategy_index].bars_against_count = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update position type if it changed (shouldn't happen, but safety check)
|
||||||
|
if(actual_pos_type != pos_type)
|
||||||
|
{
|
||||||
|
Print("Warning: Position type changed for ", rsi_strategies[strategy_index].symbol,
|
||||||
|
" - Updating from ", EnumToString(pos_type), " to ", EnumToString(actual_pos_type));
|
||||||
|
pos_type = actual_pos_type;
|
||||||
|
rsi_strategies[strategy_index].current_position_type = pos_type;
|
||||||
|
|
||||||
|
if(pos_type == POSITION_TYPE_BUY)
|
||||||
|
{
|
||||||
|
rsi_strategies[strategy_index].buy_position_open = true;
|
||||||
|
rsi_strategies[strategy_index].sell_position_open = false;
|
||||||
|
}
|
||||||
|
else if(pos_type == POSITION_TYPE_SELL)
|
||||||
|
{
|
||||||
|
rsi_strategies[strategy_index].buy_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].sell_position_open = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(pos_type == POSITION_TYPE_BUY)
|
||||||
|
{
|
||||||
|
// Check if RSI is against the position (below oversold)
|
||||||
|
if(rsi_current < rsi_strategies[strategy_index].oversold)
|
||||||
|
{
|
||||||
|
if(!rsi_strategies[strategy_index].rsi_against_position)
|
||||||
|
{
|
||||||
|
rsi_strategies[strategy_index].rsi_against_position = true;
|
||||||
|
rsi_strategies[strategy_index].bars_against_count = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rsi_strategies[strategy_index].bars_against_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close position if RSI has been against for Y bars
|
||||||
|
if(rsi_strategies[strategy_index].bars_against_count >=
|
||||||
|
rsi_strategies[strategy_index].bars_to_wait)
|
||||||
|
{
|
||||||
|
if(ClosePositionByMagic(trade, rsi_strategies[strategy_index].symbol,
|
||||||
|
rsi_strategies[strategy_index].magic_number))
|
||||||
|
{
|
||||||
|
rsi_strategies[strategy_index].position_open = false;
|
||||||
|
rsi_strategies[strategy_index].buy_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].sell_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].position_ticket = 0;
|
||||||
|
rsi_strategies[strategy_index].rsi_against_position = false;
|
||||||
|
rsi_strategies[strategy_index].bars_against_count = 0;
|
||||||
|
Print("Closed ", rsi_strategies[strategy_index].symbol, " BUY position - RSI against for ",
|
||||||
|
rsi_strategies[strategy_index].bars_to_wait, " bars");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Failed to close ", rsi_strategies[strategy_index].symbol, " BUY position - will retry");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// RSI is no longer against the position, reset counter
|
||||||
|
if(rsi_strategies[strategy_index].rsi_against_position)
|
||||||
|
{
|
||||||
|
rsi_strategies[strategy_index].rsi_against_position = false;
|
||||||
|
rsi_strategies[strategy_index].bars_against_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit long position when RSI reaches buy target
|
||||||
|
if(rsi_current >= rsi_strategies[strategy_index].target_buy)
|
||||||
|
{
|
||||||
|
if(ClosePositionByMagic(trade, rsi_strategies[strategy_index].symbol,
|
||||||
|
rsi_strategies[strategy_index].magic_number))
|
||||||
|
{
|
||||||
|
rsi_strategies[strategy_index].position_open = false;
|
||||||
|
rsi_strategies[strategy_index].buy_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].sell_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].position_ticket = 0;
|
||||||
|
rsi_strategies[strategy_index].rsi_against_position = false;
|
||||||
|
rsi_strategies[strategy_index].bars_against_count = 0;
|
||||||
|
Print("Closed ", rsi_strategies[strategy_index].symbol, " BUY position - RSI reached target: ",
|
||||||
|
rsi_strategies[strategy_index].target_buy);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Failed to close ", rsi_strategies[strategy_index].symbol, " BUY position - will retry");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(pos_type == POSITION_TYPE_SELL)
|
||||||
|
{
|
||||||
|
// Check if RSI is against the position (above overbought)
|
||||||
|
if(rsi_current > rsi_strategies[strategy_index].overbought)
|
||||||
|
{
|
||||||
|
if(!rsi_strategies[strategy_index].rsi_against_position)
|
||||||
|
{
|
||||||
|
rsi_strategies[strategy_index].rsi_against_position = true;
|
||||||
|
rsi_strategies[strategy_index].bars_against_count = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rsi_strategies[strategy_index].bars_against_count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close position if RSI has been against for Y bars
|
||||||
|
if(rsi_strategies[strategy_index].bars_against_count >=
|
||||||
|
rsi_strategies[strategy_index].bars_to_wait)
|
||||||
|
{
|
||||||
|
if(ClosePositionByMagic(trade, rsi_strategies[strategy_index].symbol,
|
||||||
|
rsi_strategies[strategy_index].magic_number))
|
||||||
|
{
|
||||||
|
rsi_strategies[strategy_index].position_open = false;
|
||||||
|
rsi_strategies[strategy_index].buy_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].sell_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].position_ticket = 0;
|
||||||
|
rsi_strategies[strategy_index].rsi_against_position = false;
|
||||||
|
rsi_strategies[strategy_index].bars_against_count = 0;
|
||||||
|
Print("Closed ", rsi_strategies[strategy_index].symbol, " SELL position - RSI against for ",
|
||||||
|
rsi_strategies[strategy_index].bars_to_wait, " bars");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Failed to close ", rsi_strategies[strategy_index].symbol, " SELL position - will retry");
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// RSI is no longer against the position, reset counter
|
||||||
|
if(rsi_strategies[strategy_index].rsi_against_position)
|
||||||
|
{
|
||||||
|
rsi_strategies[strategy_index].rsi_against_position = false;
|
||||||
|
rsi_strategies[strategy_index].bars_against_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit short position when RSI reaches sell target
|
||||||
|
if(rsi_current <= rsi_strategies[strategy_index].target_sell)
|
||||||
|
{
|
||||||
|
if(ClosePositionByMagic(trade, rsi_strategies[strategy_index].symbol,
|
||||||
|
rsi_strategies[strategy_index].magic_number))
|
||||||
|
{
|
||||||
|
rsi_strategies[strategy_index].position_open = false;
|
||||||
|
rsi_strategies[strategy_index].buy_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].sell_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].position_ticket = 0;
|
||||||
|
rsi_strategies[strategy_index].rsi_against_position = false;
|
||||||
|
rsi_strategies[strategy_index].bars_against_count = 0;
|
||||||
|
Print("Closed ", rsi_strategies[strategy_index].symbol, " SELL position - RSI reached target: ",
|
||||||
|
rsi_strategies[strategy_index].target_sell);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Failed to close ", rsi_strategies[strategy_index].symbol, " SELL position - will retry");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// No position exists - reset all tracking flags
|
||||||
|
rsi_strategies[strategy_index].position_open = false;
|
||||||
|
rsi_strategies[strategy_index].buy_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].sell_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].position_ticket = 0;
|
||||||
|
rsi_strategies[strategy_index].rsi_against_position = false;
|
||||||
|
rsi_strategies[strategy_index].bars_against_count = 0;
|
||||||
|
|
||||||
|
// Check for new entry signals (only if no position exists)
|
||||||
|
if(!PositionExistsByMagic(rsi_strategies[strategy_index].symbol,
|
||||||
|
rsi_strategies[strategy_index].magic_number))
|
||||||
|
{
|
||||||
|
// Buy signal: RSI crosses from oversold to above oversold
|
||||||
|
// Only enter if we don't already have a buy position for THIS EA (magic number) on THIS INSTRUMENT
|
||||||
|
if(!rsi_strategies[strategy_index].buy_position_open)
|
||||||
|
{
|
||||||
|
if(rsi_two_bars_ago <= rsi_strategies[strategy_index].oversold &&
|
||||||
|
rsi_prev > rsi_strategies[strategy_index].oversold)
|
||||||
|
{
|
||||||
|
double ask = SymbolInfoDouble(rsi_strategies[strategy_index].symbol, SYMBOL_ASK);
|
||||||
|
if(trade.Buy(rsi_strategies[strategy_index].lot_size,
|
||||||
|
rsi_strategies[strategy_index].symbol, ask, 0, 0,
|
||||||
|
"RSI Scalping Buy " + rsi_strategies[strategy_index].symbol))
|
||||||
|
{
|
||||||
|
ulong new_ticket = trade.ResultOrder();
|
||||||
|
if(new_ticket > 0)
|
||||||
|
{
|
||||||
|
// Verify the position was actually opened for THIS SPECIFIC INSTRUMENT
|
||||||
|
if(PositionSelectByTicketSymbolAndMagic(new_ticket,
|
||||||
|
rsi_strategies[strategy_index].symbol,
|
||||||
|
rsi_strategies[strategy_index].magic_number))
|
||||||
|
{
|
||||||
|
rsi_strategies[strategy_index].position_ticket = new_ticket;
|
||||||
|
rsi_strategies[strategy_index].position_open = true;
|
||||||
|
rsi_strategies[strategy_index].buy_position_open = true;
|
||||||
|
rsi_strategies[strategy_index].sell_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].current_position_type = POSITION_TYPE_BUY;
|
||||||
|
Print("Opened BUY position for ", rsi_strategies[strategy_index].symbol,
|
||||||
|
" (Ticket: ", rsi_strategies[strategy_index].position_ticket,
|
||||||
|
", Magic: ", rsi_strategies[strategy_index].magic_number, ")");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Error: Position opened but doesn't match instrument ",
|
||||||
|
rsi_strategies[strategy_index].symbol, " - resetting tracking");
|
||||||
|
rsi_strategies[strategy_index].position_ticket = 0;
|
||||||
|
rsi_strategies[strategy_index].position_open = false;
|
||||||
|
rsi_strategies[strategy_index].buy_position_open = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sell signal: RSI crosses from overbought to below overbought
|
||||||
|
// Only enter if we don't already have a sell position for THIS EA (magic number) on THIS INSTRUMENT
|
||||||
|
if(!rsi_strategies[strategy_index].sell_position_open)
|
||||||
|
{
|
||||||
|
if(rsi_two_bars_ago >= rsi_strategies[strategy_index].overbought &&
|
||||||
|
rsi_prev < rsi_strategies[strategy_index].overbought)
|
||||||
|
{
|
||||||
|
double bid = SymbolInfoDouble(rsi_strategies[strategy_index].symbol, SYMBOL_BID);
|
||||||
|
if(trade.Sell(rsi_strategies[strategy_index].lot_size,
|
||||||
|
rsi_strategies[strategy_index].symbol, bid, 0, 0,
|
||||||
|
"RSI Scalping Sell " + rsi_strategies[strategy_index].symbol))
|
||||||
|
{
|
||||||
|
ulong new_ticket = trade.ResultOrder();
|
||||||
|
if(new_ticket > 0)
|
||||||
|
{
|
||||||
|
// Verify the position was actually opened for THIS SPECIFIC INSTRUMENT
|
||||||
|
if(PositionSelectByTicketSymbolAndMagic(new_ticket,
|
||||||
|
rsi_strategies[strategy_index].symbol,
|
||||||
|
rsi_strategies[strategy_index].magic_number))
|
||||||
|
{
|
||||||
|
rsi_strategies[strategy_index].position_ticket = new_ticket;
|
||||||
|
rsi_strategies[strategy_index].position_open = true;
|
||||||
|
rsi_strategies[strategy_index].buy_position_open = false;
|
||||||
|
rsi_strategies[strategy_index].sell_position_open = true;
|
||||||
|
rsi_strategies[strategy_index].current_position_type = POSITION_TYPE_SELL;
|
||||||
|
Print("Opened SELL position for ", rsi_strategies[strategy_index].symbol,
|
||||||
|
" (Ticket: ", rsi_strategies[strategy_index].position_ticket,
|
||||||
|
", Magic: ", rsi_strategies[strategy_index].magic_number, ")");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Print("Error: Position opened but doesn't match instrument ",
|
||||||
|
rsi_strategies[strategy_index].symbol, " - resetting tracking");
|
||||||
|
rsi_strategies[strategy_index].position_ticket = 0;
|
||||||
|
rsi_strategies[strategy_index].position_open = false;
|
||||||
|
rsi_strategies[strategy_index].sell_position_open = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Mean Reversion Strategy |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
void RunMeanReversionStrategy()
|
||||||
|
{
|
||||||
|
// Check if this is a new bar
|
||||||
|
datetime current_bar_time = iTime(_Symbol, MeanRev_Timeframe, 0);
|
||||||
|
if(current_bar_time == last_bar_time_meanrev)
|
||||||
|
return;
|
||||||
|
|
||||||
|
last_bar_time_meanrev = current_bar_time;
|
||||||
|
|
||||||
|
// Update EMA values
|
||||||
|
if(CopyBuffer(ema_handle_meanrev, 0, 0, 3, ema_array) < 3)
|
||||||
|
return;
|
||||||
|
|
||||||
|
double ema_current = ema_array[0];
|
||||||
|
double ema_prev = ema_array[1];
|
||||||
|
double current_close = iClose(_Symbol, MeanRev_Timeframe, 0);
|
||||||
|
|
||||||
|
// Set magic number for this strategy
|
||||||
|
trade.SetExpertMagicNumber(MagicNumber_MeanReversion);
|
||||||
|
|
||||||
|
// Check existing position
|
||||||
|
if(PositionExistsByMagic(_Symbol, MagicNumber_MeanReversion))
|
||||||
|
{
|
||||||
|
// Manage existing position (trailing stop, exit conditions, etc.)
|
||||||
|
ManageMeanReversionPosition(ema_current, current_close);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Check for new entry signals
|
||||||
|
CheckMeanReversionEntry(ema_current, ema_prev, current_close);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Manage Mean Reversion Position |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
void ManageMeanReversionPosition(double ema_current, double current_close)
|
||||||
|
{
|
||||||
|
if(!PositionSelectByMagic(_Symbol, MagicNumber_MeanReversion))
|
||||||
|
return;
|
||||||
|
|
||||||
|
double position_profit = PositionGetDouble(POSITION_PROFIT);
|
||||||
|
double current_price = PositionGetDouble(POSITION_PRICE_CURRENT);
|
||||||
|
ENUM_POSITION_TYPE position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||||
|
|
||||||
|
double pips_multiplier = (_Digits == 3 || _Digits == 5) ? 10.0 : 1.0;
|
||||||
|
|
||||||
|
// Trailing stop
|
||||||
|
if(position_profit > 0)
|
||||||
|
{
|
||||||
|
if(position_type == POSITION_TYPE_BUY)
|
||||||
|
{
|
||||||
|
double new_stop_loss = current_price - (TrailingStop * _Point * pips_multiplier);
|
||||||
|
double current_stop_loss = PositionGetDouble(POSITION_SL);
|
||||||
|
if(new_stop_loss > current_stop_loss)
|
||||||
|
{
|
||||||
|
ModifyPositionByMagic(trade, _Symbol, MagicNumber_MeanReversion,
|
||||||
|
new_stop_loss, PositionGetDouble(POSITION_TP));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(position_type == POSITION_TYPE_SELL)
|
||||||
|
{
|
||||||
|
double new_stop_loss = current_price + (TrailingStop * _Point * pips_multiplier);
|
||||||
|
double current_stop_loss = PositionGetDouble(POSITION_SL);
|
||||||
|
if(new_stop_loss < current_stop_loss || current_stop_loss == 0)
|
||||||
|
{
|
||||||
|
ModifyPositionByMagic(trade, _Symbol, MagicNumber_MeanReversion,
|
||||||
|
new_stop_loss, PositionGetDouble(POSITION_TP));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exit when price crosses EMA
|
||||||
|
bool exit_bullish = (position_type == POSITION_TYPE_SELL && current_close > ema_current);
|
||||||
|
bool exit_bearish = (position_type == POSITION_TYPE_BUY && current_close < ema_current);
|
||||||
|
|
||||||
|
if(exit_bullish || exit_bearish)
|
||||||
|
{
|
||||||
|
ClosePositionByMagic(trade, _Symbol, MagicNumber_MeanReversion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
//| Check Mean Reversion Entry Signals |
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
|
void CheckMeanReversionEntry(double ema_current, double ema_prev, double current_close)
|
||||||
|
{
|
||||||
|
// Simplified entry logic - can be expanded
|
||||||
|
double pips_multiplier = (_Digits == 3 || _Digits == 5) ? 10.0 : 1.0;
|
||||||
|
double preis_abstand = MathAbs(current_close - ema_current) / _Point / pips_multiplier;
|
||||||
|
double steigung = (ema_current - ema_prev) / _Point / pips_multiplier;
|
||||||
|
|
||||||
|
// Entry conditions
|
||||||
|
bool bullish_signal = (current_close > ema_current && preis_abstand > PreisSchwelle &&
|
||||||
|
MathAbs(steigung) > SteigungSchwelle);
|
||||||
|
bool bearish_signal = (current_close < ema_current && preis_abstand > PreisSchwelle &&
|
||||||
|
MathAbs(steigung) > SteigungSchwelle);
|
||||||
|
|
||||||
|
if(bullish_signal)
|
||||||
|
{
|
||||||
|
if(trade.Buy(MeanRev_LotSize, _Symbol, 0, 0, 0, "Mean Reversion Buy"))
|
||||||
|
{
|
||||||
|
meanrev_ticket = trade.ResultOrder();
|
||||||
|
meanrev_position_open = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(bearish_signal)
|
||||||
|
{
|
||||||
|
if(trade.Sell(MeanRev_LotSize, _Symbol, 0, 0, 0, "Mean Reversion Sell"))
|
||||||
|
{
|
||||||
|
meanrev_ticket = trade.ResultOrder();
|
||||||
|
meanrev_position_open = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//+------------------------------------------------------------------+
|
||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user