This commit is contained in:
zhutoutoutousan
2026-05-27 14:59:00 +02:00
parent b5acd37754
commit 3f75a08848
122 changed files with 5259 additions and 12459 deletions
@@ -0,0 +1,173 @@
//+------------------------------------------------------------------+
//| 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)
{
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0)
continue;
if(!PositionSelectByTicket(ticket))
continue;
if(PositionGetString(POSITION_SYMBOL) == symbol &&
(ulong)PositionGetInteger(POSITION_MAGIC) == magic_number)
return true;
}
return false;
}
//+------------------------------------------------------------------+
//| 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)
continue;
if(!PositionSelectByTicket(ticket))
continue;
if(PositionGetString(POSITION_SYMBOL) == symbol &&
(ulong)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)
continue;
if(!PositionSelectByTicket(ticket))
continue;
if(PositionGetString(POSITION_SYMBOL) == symbol &&
(ulong)PositionGetInteger(POSITION_MAGIC) == magic_number)
count++;
}
return count;
}
//+------------------------------------------------------------------+
//| Align volume to SYMBOL_VOLUME_STEP / min / max (avoids Invalid volume) |
//+------------------------------------------------------------------+
double United_NormalizeVolume(const string symbol, double volume)
{
double minLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
double lotStep = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
if(lotStep <= 0.0)
lotStep = 0.01;
double v = MathFloor(volume / lotStep) * lotStep;
if(v < minLot)
v = minLot;
if(v > maxLot)
v = maxLot;
int digits = (int)MathCeil(-MathLog10(lotStep));
if(digits < 0)
digits = 0;
if(digits > 8)
digits = 8;
return NormalizeDouble(v, digits);
}
//+------------------------------------------------------------------+
@@ -0,0 +1,327 @@
//+------------------------------------------------------------------+
//| RSIScalping.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"
#include <Trade\Trade.mqh>
#include "../_united/MagicNumberHelpers.mqh"
//--- Input parameters — synced with Desktop 123.set (2026.05.13)
input ENUM_TIMEFRAMES TimeFrame = PERIOD_M20; // Timeframe for Analysis
input int RSI_Period = 14; // RSI Period
input ENUM_APPLIED_PRICE RSI_Applied_Price = PRICE_CLOSE; // RSI Applied Price
input double RSI_Overbought = 32; // RSI Overbought Level
input double RSI_Oversold = 86; // RSI Oversold Level
input double RSI_Target_Buy = 100; // RSI Target for Buy Exit
input double RSI_Target_Sell = 24; // RSI Target for Sell Exit
input int BarsToWait = 34; // Bars to wait when RSI goes against position
input double LotSize = 5; // Lot Size
input int MagicNumber = 129102315; // Magic Number
input int Slippage = 3; // Slippage in points
//--- Global variables
CTrade trade;
int rsi_handle;
double rsi_buffer[];
double rsi_prev, rsi_current, rsi_two_bars_ago;
bool position_open = false;
int position_ticket = 0;
ENUM_POSITION_TYPE current_position_type = POSITION_TYPE_BUY;
datetime last_bar_time = 0;
bool rsi_against_position = false;
int bars_against_count = 0;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// Initialize RSI indicator
rsi_handle = iRSI(_Symbol, TimeFrame, RSI_Period, RSI_Applied_Price);
if(rsi_handle == INVALID_HANDLE)
{
return(INIT_FAILED);
}
// Initialize trade object
trade.SetExpertMagicNumber(MagicNumber);
trade.SetDeviationInPoints(Slippage);
trade.SetTypeFilling(ORDER_FILLING_FOK);
// Allocate arrays
ArraySetAsSeries(rsi_buffer, true);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(rsi_handle != INVALID_HANDLE)
IndicatorRelease(rsi_handle);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Check if we have enough bars
if(Bars(_Symbol, TimeFrame) < RSI_Period + 2)
{
return;
}
// Check if this is a new bar
datetime current_bar_time = iTime(_Symbol, TimeFrame, 0);
if(current_bar_time == last_bar_time)
{
return; // Still the same bar, don't process
}
last_bar_time = current_bar_time;
// Update RSI values
if(!UpdateRSI())
{
return;
}
// Check for existing position
CheckExistingPosition();
// Check for new entry signals - only if no position exists for THIS EA (magic number) on THIS symbol
if(!position_open && !PositionExistsByMagic(_Symbol, MagicNumber))
{
CheckEntrySignals();
}
}
//+------------------------------------------------------------------+
//| Update RSI values |
//+------------------------------------------------------------------+
bool UpdateRSI()
{
if(CopyBuffer(rsi_handle, 0, 0, 3, rsi_buffer) < 3)
{
return false;
}
rsi_current = rsi_buffer[0]; // Current bar
rsi_prev = rsi_buffer[1]; // Previous bar
rsi_two_bars_ago = rsi_buffer[2]; // Two bars ago
return true;
}
//+------------------------------------------------------------------+
//| Check existing position for exit conditions |
//+------------------------------------------------------------------+
void CheckExistingPosition()
{
if(!position_open)
{
return;
}
// Check if position still exists with correct magic number AND symbol for THIS EA
if(!PositionSelectByTicketSymbolAndMagic(position_ticket, _Symbol, MagicNumber))
{
position_open = false;
position_ticket = 0;
rsi_against_position = false;
bars_against_count = 0;
return;
}
// Exit conditions based on RSI target
if(current_position_type == POSITION_TYPE_BUY)
{
// Check if RSI is against the position (below oversold)
if(rsi_current < RSI_Oversold)
{
if(!rsi_against_position)
{
rsi_against_position = true;
bars_against_count = 1;
}
else
{
bars_against_count++;
}
// Close position if RSI has been against for Y bars
if(bars_against_count >= BarsToWait)
{
ClosePosition();
return;
}
}
else
{
// RSI is no longer against the position, reset counter
if(rsi_against_position)
{
rsi_against_position = false;
bars_against_count = 0;
}
// Exit long position when RSI reaches buy target
if(rsi_current >= RSI_Target_Buy)
{
ClosePosition();
}
}
}
else if(current_position_type == POSITION_TYPE_SELL)
{
// Check if RSI is against the position (above overbought)
if(rsi_current > RSI_Overbought)
{
if(!rsi_against_position)
{
rsi_against_position = true;
bars_against_count = 1;
}
else
{
bars_against_count++;
}
// Close position if RSI has been against for Y bars
if(bars_against_count >= BarsToWait)
{
ClosePosition();
return;
}
}
else
{
// RSI is no longer against the position, reset counter
if(rsi_against_position)
{
rsi_against_position = false;
bars_against_count = 0;
}
// Exit short position when RSI reaches sell target
if(rsi_current <= RSI_Target_Sell)
{
ClosePosition();
}
}
}
}
//+------------------------------------------------------------------+
//| Check for entry signals |
//+------------------------------------------------------------------+
void CheckEntrySignals()
{
// Buy signal: RSI crosses from oversold to above oversold (checking the actual crossover)
if(rsi_two_bars_ago <= RSI_Oversold && rsi_prev > RSI_Oversold)
{
OpenBuyPosition();
}
// Sell signal: RSI crosses from overbought to below overbought (checking the actual crossover)
if(rsi_two_bars_ago >= RSI_Overbought && rsi_prev < RSI_Overbought)
{
OpenSellPosition();
}
}
//+------------------------------------------------------------------+
//| Open buy position |
//+------------------------------------------------------------------+
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);
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
{
ulong new_ticket = trade.ResultOrder();
if(new_ticket > 0)
{
// 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");
}
}
}
}
//+------------------------------------------------------------------+
//| Open sell position |
//+------------------------------------------------------------------+
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);
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
{
ulong new_ticket = trade.ResultOrder();
if(new_ticket > 0)
{
// 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");
}
}
}
}
//+------------------------------------------------------------------+
//| Close current position |
//+------------------------------------------------------------------+
void ClosePosition()
{
// Close position using helper that verifies symbol AND magic number for THIS EA
if(ClosePositionByMagic(trade, _Symbol, MagicNumber))
{
position_open = false;
position_ticket = 0;
rsi_against_position = false;
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;
}
}
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

@@ -0,0 +1,76 @@
# United EA Strategy Configuration Summary
## Strategy Symbols and Magic Numbers
### Strategy 1: DarvasBox
- **Symbol**: XAUUSD (Gold/USD)
- **Magic Number**: 135790
### Strategy 2: EMASlopeDistance
- **Symbol**: XAUUSD (Gold/USD)
- **Magic Number**: 12350
### Strategy 3: RSICrossOverReversal
- **Symbol**: XAUUSD (Gold/USD)
- **Magic Number**: 7
### Strategy 4: RSIMidPointHijack
- **Symbol**: XAUUSD (Gold/USD)
- **Magic Numbers**:
- RSIFollow: 1001
- RSIReverse: 1002
- EMACross: 1003
### Strategy 5: RSI Scalping APPL (Apple)
- **Symbol**: AAPL (Apple stock)
- **Magic Number**: 20001
- **Note**: Changed from "APPL" to "AAPL" (correct ticker symbol)
### Strategy 6: RSI Scalping BTCUSD
- **Symbol**: BTCUSD (Bitcoin/USD)
- **Magic Number**: 123459123
### Strategy 7: RSI Scalping MSFT
- **Symbol**: MSFT (Microsoft stock)
- **Magic Number**: 20002
### Strategy 8: RSI Scalping NVDA
- **Symbol**: NVDA (NVIDIA stock)
- **Magic Number**: 20003
### Strategy 9: RSI Scalping TSLA
- **Symbol**: TSLA (Tesla stock)
- **Magic Number**: 125421321
### Strategy 10: RSI Scalping XAUUSD
- **Symbol**: XAUUSD (Gold/USD)
- **Magic Number**: 129102315
## Important Notes
1. **Stock Symbols**: Stock symbols (AAPL, MSFT, NVDA, TSLA) must be:
- Added to Market Watch in MetaTrader 5
- Available from your broker
- Use the correct ticker symbol (e.g., "AAPL" not "APPL")
2. **Magic Numbers**: All strategies have unique magic numbers to prevent interference:
- Each strategy can be identified by its magic number
- RSIMidPointHijack uses 3 magic numbers (one for each sub-strategy)
3. **Symbol Configuration**: Each strategy trades on its own symbol:
- You can change symbols in the input parameters
- The EA will log warnings if a symbol is not available
- Strategies with unavailable symbols will be skipped (EA continues running)
4. **RSI Scalping Strategies**:
- Each RSI Scalping variant trades on a different symbol
- They all use the same strategy logic but with different parameters
- Buy and sell signals are generated based on RSI levels for each symbol
## Troubleshooting
If stock symbols are not working:
1. Check if the symbol exists in your broker's symbol list
2. Add the symbol to Market Watch in MetaTrader 5
3. Verify the symbol name matches your broker's naming convention
4. Some brokers use prefixes/suffixes (e.g., "NASDAQ:AAPL" or "AAPL.US")
@@ -0,0 +1,328 @@
//+------------------------------------------------------------------+
//| DarvasBoxStrategy.mqh |
//+------------------------------------------------------------------+
// MQL5: no #if — use #ifdef only (no defined() / || in one #if)
#ifdef UNITED_V2_DYNAMIC_LOTS
extern double g_DB_LotSize;
#define DARVAS_TRADE_LOT (g_DB_LotSize)
#else
#ifdef CLUSTER0_ORCHESTRATOR
extern double g_DB_LotSize;
#define DARVAS_TRADE_LOT (g_DB_LotSize)
#else
#define DARVAS_TRADE_LOT 0.01
#endif
#endif
bool InitDarvasBox(string symbol)
{
dbData.symbol = symbol;
dbData.boxHigh = 0;
dbData.boxLow = 0;
dbData.boxFormed = false;
dbData.lastBoxTime = 0;
dbData.boxName = "DarvasBox_" + IntegerToString(DB_MagicNumber) + "_";
// Check if symbol exists
if(!SymbolSelect(symbol, true))
{
Print("DarvasBox: Symbol '", symbol, "' not available in Market Watch. Please add it to Market Watch or check symbol name.");
return false;
}
Sleep(100); // Wait for symbol to be ready
dbData.point = SymbolInfoDouble(symbol, SYMBOL_POINT);
dbData.minStopLevel = SymbolInfoInteger(symbol, SYMBOL_TRADE_STOPS_LEVEL) * dbData.point;
dbData.maHandle = iMA(symbol, DB_TrendTimeframe, DB_MA_Period, 0, DB_MA_Method, DB_MA_Price);
// Same TF as box highs/lows (H1 loop in CalculateDarvasBox). PERIOD_CURRENT breaks when United EA
// runs on a chart timeframe other than H1 (volume/breakout no longer match the box).
dbData.volumeHandle = iVolumes(symbol, PERIOD_H1, VOLUME_TICK);
if(dbData.maHandle == INVALID_HANDLE || dbData.volumeHandle == INVALID_HANDLE)
{
Print("DarvasBox: Error creating indicators for '", symbol, "'");
return false;
}
dbData.trade.SetDeviationInPoints(10);
dbData.trade.SetTypeFilling(ORDER_FILLING_IOC);
dbData.trade.SetAsyncMode(false);
dbData.trade.SetExpertMagicNumber(DB_MagicNumber);
ObjectsDeleteAll(0, dbData.boxName);
dbData.isInitialized = true;
Print("DarvasBox: Successfully initialized for symbol '", symbol, "'");
return true;
}
void DeinitDarvasBox()
{
if(dbData.maHandle != INVALID_HANDLE) IndicatorRelease(dbData.maHandle);
if(dbData.volumeHandle != INVALID_HANDLE) IndicatorRelease(dbData.volumeHandle);
ObjectsDeleteAll(0, dbData.boxName);
}
void DrawDarvasBox()
{
if(!dbData.boxFormed) return;
datetime time1 = iTime(dbData.symbol, PERIOD_H1, DB_BoxPeriod);
datetime time2 = iTime(dbData.symbol, PERIOD_H1, 0);
ObjectsDeleteAll(0, dbData.boxName);
ObjectCreate(0, dbData.boxName + "Top", OBJ_TREND, 0, time1, dbData.boxHigh, time2, dbData.boxHigh);
ObjectCreate(0, dbData.boxName + "Bottom", OBJ_TREND, 0, time1, dbData.boxLow, time2, dbData.boxLow);
ObjectSetInteger(0, dbData.boxName + "Top", OBJPROP_COLOR, DB_BoxColor);
ObjectSetInteger(0, dbData.boxName + "Bottom", OBJPROP_COLOR, DB_BoxColor);
ObjectSetInteger(0, dbData.boxName + "Top", OBJPROP_WIDTH, DB_BoxWidth);
ObjectSetInteger(0, dbData.boxName + "Bottom", OBJPROP_WIDTH, DB_BoxWidth);
ObjectSetInteger(0, dbData.boxName + "Top", OBJPROP_RAY_RIGHT, true);
ObjectSetInteger(0, dbData.boxName + "Bottom", OBJPROP_RAY_RIGHT, true);
}
void CalculateDarvasBox()
{
double high = 0;
double low = DBL_MAX;
// Find highest high and lowest low in the period - EXACTLY like original
for(int i = 0; i < DB_BoxPeriod; i++)
{
high = MathMax(high, iHigh(dbData.symbol, PERIOD_H1, i));
low = MathMin(low, iLow(dbData.symbol, PERIOD_H1, i));
}
double range = high - low;
double allowedRange = DB_BoxDeviation * dbData.point; // Use dbData.point instead of _Point
if(DB_EnableLogging)
{
Print("DarvasBox: Box Calculation - High: ", high, " Low: ", low, " Range: ", range, " Allowed Range: ", allowedRange);
}
// Check if box is formed - EXACTLY like original
if(range <= allowedRange)
{
dbData.boxHigh = high;
dbData.boxLow = low;
dbData.boxFormed = true;
dbData.lastBoxTime = iTime(dbData.symbol, PERIOD_CURRENT, 0);
// Draw the box
DrawDarvasBox();
if(DB_EnableLogging)
Print("DarvasBox: Box Formed - High: ", dbData.boxHigh, " Low: ", dbData.boxLow, " Time: ", dbData.lastBoxTime);
}
else
{
dbData.boxFormed = false;
// Delete box if it exists
ObjectsDeleteAll(0, dbData.boxName);
}
}
bool ValidateStopLevels(double price, double &sl, double &tp, ENUM_ORDER_TYPE orderType)
{
double minSlDistance = MathMax(dbData.minStopLevel, DB_StopLoss * dbData.point);
double minTpDistance = MathMax(dbData.minStopLevel, DB_TakeProfit * dbData.point);
if(orderType == ORDER_TYPE_BUY)
{
sl = price - minSlDistance;
tp = price + minTpDistance;
}
else
{
sl = price + minSlDistance;
tp = price - minTpDistance;
}
return true;
}
bool IsTrendFavorable(ENUM_ORDER_TYPE orderType)
{
if(!DB_UseTrendFilter)
return true;
double ma[];
ArraySetAsSeries(ma, true);
if(CopyBuffer(dbData.maHandle, 0, 0, 2, ma) <= 0)
return false;
double currentPrice = SymbolInfoDouble(dbData.symbol, SYMBOL_ASK);
double trendStrength = MathAbs(currentPrice - ma[0]) / dbData.point;
if(orderType == ORDER_TYPE_BUY)
return (currentPrice > ma[0] && trendStrength > DB_TrendThreshold);
else
return (currentPrice < ma[0] && trendStrength > DB_TrendThreshold);
}
bool CheckVolumeConditions()
{
if(!DB_UseVolumeSpikeFilter)
return true;
double volumes[];
ArraySetAsSeries(volumes, true);
if(CopyBuffer(dbData.volumeHandle, 0, 0, DB_VolumeMA_Period + 1, volumes) <= 0)
return false;
double volumeMA = 0;
for(int i = 1; i <= DB_VolumeMA_Period; i++)
volumeMA += volumes[i];
volumeMA /= DB_VolumeMA_Period;
double currentVolume = volumes[0];
if(volumeMA <= 0.0)
return (currentVolume > 0.0);
double volumeRatio = currentVolume / volumeMA;
return (volumeRatio > DB_VolumeThresholdMultiplier);
}
bool PlaceOrder(ENUM_ORDER_TYPE orderType, double price, double sl, double tp)
{
if(!ValidateStopLevels(price, sl, tp, orderType))
{
if(DB_EnableLogging)
Print("DarvasBox: Order rejected - Stop levels validation failed");
return false;
}
if(!IsTrendFavorable(orderType))
{
if(DB_EnableLogging)
Print("DarvasBox: Order rejected - Trend not favorable for ", EnumToString(orderType));
return false;
}
if(!CheckVolumeConditions())
{
if(DB_EnableLogging)
Print("DarvasBox: Order rejected - Volume conditions not met");
return false;
}
bool result = false;
const double lot = United_NormalizeVolume(dbData.symbol, DARVAS_TRADE_LOT);
if(lot <= 0.0)
{
Print("DarvasBox: Order rejected - invalid lot after normalize (raw=", DARVAS_TRADE_LOT, ")");
return false;
}
// Use market price (0) instead of explicit price - this ensures market order execution
// In backtesting, explicit price might fail if price has moved
if(orderType == ORDER_TYPE_BUY)
result = dbData.trade.Buy(lot, dbData.symbol, 0, sl, tp, "Darvas Box Breakout");
else
result = dbData.trade.Sell(lot, dbData.symbol, 0, sl, tp, "Darvas Box Breakdown");
// Always log errors, success only if logging enabled
if(result)
{
if(DB_EnableLogging)
Print("DarvasBox: ", (orderType == ORDER_TYPE_BUY ? "Buy" : "Sell"), " Order Placed Successfully");
}
else
{
// Always log failures with detailed info
uint retcode_uint = dbData.trade.ResultRetcode();
int retcode = (int)retcode_uint;
string desc = dbData.trade.ResultRetcodeDescription();
ulong deal = dbData.trade.ResultDeal();
ulong order = dbData.trade.ResultOrder();
Print("DarvasBox: ", (orderType == ORDER_TYPE_BUY ? "Buy" : "Sell"),
" Order Failed - Retcode: ", retcode,
", Description: ", desc,
", Deal: ", deal,
", Order: ", order,
", Symbol: ", dbData.symbol,
", Requested Price: ", price,
", SL: ", sl,
", TP: ", tp);
}
return result;
}
void ProcessDarvasBox(string symbol)
{
// Skip if not initialized (symbol not available)
if(!dbData.isInitialized)
return;
dbData.symbol = symbol; // Update symbol in case it changed
// Calculate new box levels - EXACTLY like original (called every tick)
CalculateDarvasBox();
// Check for trading signals - EXACTLY like original (checked every tick)
if(dbData.boxFormed)
{
double currentPrice = SymbolInfoDouble(dbData.symbol, SYMBOL_ASK);
long currentVolume_long = iVolume(dbData.symbol, PERIOD_H1, 0);
double currentVolume = (double)currentVolume_long;
if(DB_EnableLogging)
{
Print("DarvasBox: Current Price: ", currentPrice, " Box High: ", dbData.boxHigh, " Box Low: ", dbData.boxLow);
Print("DarvasBox: Current Volume: ", currentVolume, " Volume Threshold: ", DB_VolumeThreshold);
}
// Check for breakout above box - EXACTLY like original
if(currentPrice > dbData.boxHigh && currentVolume > DB_VolumeThreshold)
{
if(DB_EnableLogging)
Print("DarvasBox: Breakout Signal Detected - Price above box high");
// Buy signal
if(!PositionExistsByMagic(dbData.symbol, (ulong)DB_MagicNumber)) // No existing positions with our magic number
{
double sl = currentPrice - DB_StopLoss * dbData.point;
double tp = currentPrice + DB_TakeProfit * dbData.point;
if(DB_EnableLogging)
Print("DarvasBox: Preparing Buy Order - Price: ", currentPrice, " SL: ", sl, " TP: ", tp);
PlaceOrder(ORDER_TYPE_BUY, currentPrice, sl, tp);
}
else if(DB_EnableLogging)
Print("DarvasBox: Skipping Buy Signal - Position already exists");
}
// Check for breakdown below box - EXACTLY like original
if(currentPrice < dbData.boxLow && currentVolume > DB_VolumeThreshold)
{
if(DB_EnableLogging)
Print("DarvasBox: Breakdown Signal Detected - Price below box low");
// Sell signal
if(!PositionExistsByMagic(dbData.symbol, (ulong)DB_MagicNumber)) // No existing positions with our magic number
{
double sl = currentPrice + DB_StopLoss * dbData.point;
double tp = currentPrice - DB_TakeProfit * dbData.point;
if(DB_EnableLogging)
Print("DarvasBox: Preparing Sell Order - Price: ", currentPrice, " SL: ", sl, " TP: ", tp);
PlaceOrder(ORDER_TYPE_SELL, currentPrice, sl, tp);
}
else if(DB_EnableLogging)
Print("DarvasBox: Skipping Sell Signal - Position already exists");
}
}
else if(DB_EnableLogging)
Print("DarvasBox: No Box Formed - Waiting for consolidation");
}
//+------------------------------------------------------------------+
@@ -0,0 +1,576 @@
//+------------------------------------------------------------------+
//| EMASlopeDistanceStrategy.mqh |
//+------------------------------------------------------------------+
bool InitEMASlopeDistance(string symbol)
{
esData.symbol = symbol;
esData.letzte_überwachung_zeit = 0;
esData.überwachung_aktiv = false;
esData.preis_trigger_aktiv = false;
esData.steigung_trigger_aktiv = false;
esData.ticket = 0;
esData.trades_in_current_crossover = 0;
esData.crossover_detected = false;
esData.trade_open_time = 0;
esData.last_bar_time = 0;
esData.es_last_sl_adjust_success_time = 0;
// Check if symbol exists
if(!SymbolSelect(symbol, true))
{
Print("EMASlopeDistance: Symbol '", symbol, "' not available in Market Watch. Please add it to Market Watch or check symbol name.");
return false;
}
Sleep(100); // Wait for symbol to be ready
esData.trade.SetExpertMagicNumber(ES_MagicNumber);
esData.trade.SetDeviationInPoints(10);
esData.trade.SetTypeFilling(ORDER_FILLING_IOC);
esData.ema_handle = iMA(symbol, ES_Timeframe, ES_EMA_Periode, 0, MODE_EMA, PRICE_CLOSE);
if(esData.ema_handle == INVALID_HANDLE)
{
Print("EMASlopeDistance: Error creating EMA indicator for '", symbol, "'");
return false;
}
ArraySetAsSeries(esData.ema_array, true);
esData.isInitialized = true;
Print("EMASlopeDistance: Successfully initialized for symbol '", symbol, "'");
return true;
}
void DeinitEMASlopeDistance()
{
if(esData.ema_handle != INVALID_HANDLE)
IndicatorRelease(esData.ema_handle);
}
bool ES_IsWeeklyADXTrendFavorable(const ENUM_ORDER_TYPE order_type)
{
if(!ES_UseWeeklyADXFilter)
return true;
int adxShift = ES_WeeklyADXBarShift;
if(adxShift < 0)
adxShift = 0;
int adx_handle = iADX(esData.symbol, PERIOD_W1, ES_WeeklyADXPeriod);
if(adx_handle == INVALID_HANDLE)
return false;
double adx_buf[], plus_di_buf[], minus_di_buf[];
ArraySetAsSeries(adx_buf, true);
ArraySetAsSeries(plus_di_buf, true);
ArraySetAsSeries(minus_di_buf, true);
bool ok_adx = (CopyBuffer(adx_handle, 0, adxShift, 1, adx_buf) > 0);
bool ok_plus = (CopyBuffer(adx_handle, 1, adxShift, 1, plus_di_buf) > 0);
bool ok_minus = (CopyBuffer(adx_handle, 2, adxShift, 1, minus_di_buf) > 0);
IndicatorRelease(adx_handle);
if(!ok_adx || !ok_plus || !ok_minus)
return false;
double adx_value = adx_buf[0];
double plus_di = plus_di_buf[0];
double minus_di = minus_di_buf[0];
bool strength_ok = (adx_value >= ES_WeeklyADXMin);
bool direction_ok = true;
if(ES_WeeklyADXUseDirection)
{
if(order_type == ORDER_TYPE_BUY)
direction_ok = (plus_di > minus_di);
else
direction_ok = (minus_di > plus_di);
}
return strength_ok && direction_ok;
}
bool ES_TrailingActivationReached(const double position_profit, const ENUM_POSITION_TYPE position_type,
const double pips_multiplier)
{
if(ES_TrailingActivationPips <= 0.0)
return (position_profit > 0.0);
const double open_px = PositionGetDouble(POSITION_PRICE_OPEN);
if(position_type == POSITION_TYPE_BUY)
{
const double bid = SymbolInfoDouble(esData.symbol, SYMBOL_BID);
return ((bid - open_px) / SymbolInfoDouble(esData.symbol, SYMBOL_POINT) / pips_multiplier >= ES_TrailingActivationPips);
}
const double ask = SymbolInfoDouble(esData.symbol, SYMBOL_ASK);
return ((open_px - ask) / SymbolInfoDouble(esData.symbol, SYMBOL_POINT) / pips_multiplier >= ES_TrailingActivationPips);
}
//+------------------------------------------------------------------+
//| EMA Berechnung (EMA Calculation) |
//+------------------------------------------------------------------+
void BerechneEMA()
{
//--- EMA Werte vom Indicator kopieren (Copy EMA values from indicator)
int copied = CopyBuffer(esData.ema_handle, 0, 0, 3, esData.ema_array);
if(copied <= 0)
{
Print("TRACE: Fehler beim Kopieren der EMA Werte - Copied: ", copied);
return;
}
Print("TRACE: EMA Werte kopiert: ", copied, " Bars");
Print("TRACE: EMA [0]: ", esData.ema_array[0], " [1]: ", esData.ema_array[1], " [2]: ", esData.ema_array[2]);
}
//+------------------------------------------------------------------+
//| Trigger-Bedingungen prüfen (Check trigger conditions) |
//+------------------------------------------------------------------+
void PrüfeTrigger()
{
if(ArraySize(esData.ema_array) < 2)
{
Print("TRACE: Array zu klein - Größe: ", ArraySize(esData.ema_array));
return;
}
//--- Aktuelle Werte (Current values)
double aktueller_preis = SymbolInfoDouble(esData.symbol, SYMBOL_BID);
double aktueller_ask = SymbolInfoDouble(esData.symbol, SYMBOL_ASK);
double aktueller_close = iClose(esData.symbol, ES_Timeframe, 0);
int digits = (int)SymbolInfoInteger(esData.symbol, SYMBOL_DIGITS);
double point = SymbolInfoDouble(esData.symbol, SYMBOL_POINT);
double pips_multiplier = (digits == 3 || digits == 5) ? 10.0 : 1.0;
//--- EMA Werte in Variablen (EMA values in variables)
double ema_aktuell = esData.ema_array[0];
double ema_vorher = esData.ema_array[1];
//--- EMA Crossover Erkennung (EMA Crossover Detection)
// Prüfe ob Preis die EMA kreuzt (Check if price crosses EMA)
static double last_close = 0;
static double last_ema = 0;
if(last_close != 0 && last_ema != 0)
{
bool crossover_bullish = (last_close <= last_ema) && (aktueller_close > ema_aktuell);
bool crossover_bearish = (last_close >= last_ema) && (aktueller_close < ema_aktuell);
//--- Neues Crossover-Ereignis erkannt (New crossover event detected)
if(crossover_bullish || crossover_bearish)
{
esData.trades_in_current_crossover = 0; // Reset trade counter
Print("TRACE: EMA Crossover erkannt - ", (crossover_bullish ? "BULLISH" : "BEARISH"), " - Trade-Counter zurückgesetzt");
Print("TRACE: Vorher: Close=", last_close, " EMA=", last_ema, " Jetzt: Close=", aktueller_close, " EMA=", ema_aktuell);
}
}
//--- Aktuelle Werte für nächsten Vergleich speichern (Save current values for next comparison)
last_close = aktueller_close;
last_ema = ema_aktuell;
//--- Preisbewegung zur EMA prüfen (Check price action to EMA)
double preis_abstand = MathAbs(aktueller_close - ema_aktuell) / point / pips_multiplier;
Print("TRACE: Preis-Abstand: ", preis_abstand, " Pips (Schwelle: ", ES_PreisSchwelle, ")");
Print("TRACE: Close: ", aktueller_close, " EMA: ", ema_aktuell);
Print("TRACE: Trades im aktuellen Crossover: ", esData.trades_in_current_crossover, "/", ES_MaxTradesPerCrossover);
if(preis_abstand > ES_PreisSchwelle && !esData.preis_trigger_aktiv)
{
esData.preis_trigger_aktiv = true;
Print("TRACE: Preis-Trigger aktiviert: ", preis_abstand, " Pips");
}
//--- EMA Steigung prüfen (Check EMA slope)
double steigung = (ema_aktuell - ema_vorher) / point / pips_multiplier;
Print("TRACE: EMA Steigung: ", steigung, " Pips (Schwelle: ", ES_SteigungSchwelle, ")");
if(MathAbs(steigung) > ES_SteigungSchwelle && !esData.steigung_trigger_aktiv)
{
esData.steigung_trigger_aktiv = true;
Print("TRACE: Steigungs-Trigger aktiviert: ", steigung, " Pips");
}
//--- Überwachung starten wenn beide Trigger aktiv sind (Start monitoring when both triggers are active)
if(esData.preis_trigger_aktiv && esData.steigung_trigger_aktiv && !esData.überwachung_aktiv)
{
esData.überwachung_aktiv = true;
if(ES_UseBarData)
{
esData.letzte_überwachung_zeit = iTime(esData.symbol, ES_Timeframe, 0); // Aktuelle Bar-Zeit
Print("TRACE: Überwachung gestartet - Beide Trigger aktiv (Bar: ", TimeToString(esData.letzte_überwachung_zeit), ")");
}
else
{
esData.letzte_überwachung_zeit = TimeCurrent(); // Aktuelle Tick-Zeit
Print("TRACE: Überwachung gestartet - Beide Trigger aktiv (Tick)");
}
}
//--- Trade platzieren wenn Überwachung aktiv und Preis über/unter EMA (Place trade when monitoring active and price above/below EMA)
if(esData.überwachung_aktiv)
{
bool bullish_signal = aktueller_close > ema_aktuell;
bool bearish_signal = aktueller_close < ema_aktuell;
Print("TRACE: Signal Check - Bullish: ", bullish_signal, " Bearish: ", bearish_signal);
Print("TRACE: Close: ", aktueller_close, " EMA: ", ema_aktuell);
Print("TRACE: Differenz: ", aktueller_close - ema_aktuell);
//--- Trade-Limit prüfen (Check trade limit)
if(esData.trades_in_current_crossover >= ES_MaxTradesPerCrossover)
{
Print("TRACE: Trade-Limit erreicht (", ES_MaxTradesPerCrossover, ") - Kein neuer Trade");
return;
}
if(bullish_signal && !PositionExistsByMagic(esData.symbol, (ulong)ES_MagicNumber))
{
if(!ES_IsWeeklyADXTrendFavorable(ORDER_TYPE_BUY))
{
Print("TRACE: Weekly ADX blockiert BUY-Entry");
return;
}
Print("TRACE: Versuche KAUF-Trade zu platzieren (Trade #", esData.trades_in_current_crossover + 1, ")");
if(PlatziereTrade(ORDER_TYPE_BUY))
{
esData.trades_in_current_crossover++;
}
}
else if(bearish_signal && !PositionExistsByMagic(esData.symbol, (ulong)ES_MagicNumber))
{
if(!ES_IsWeeklyADXTrendFavorable(ORDER_TYPE_SELL))
{
Print("TRACE: Weekly ADX blockiert SELL-Entry");
return;
}
Print("TRACE: Versuche VERKAUF-Trade zu platzieren (Trade #", esData.trades_in_current_crossover + 1, ")");
if(PlatziereTrade(ORDER_TYPE_SELL))
{
esData.trades_in_current_crossover++;
}
}
else if(PositionExistsByMagic(esData.symbol, (ulong)ES_MagicNumber))
{
Print("TRACE: Position bereits offen - kein neuer Trade");
}
}
}
//+------------------------------------------------------------------+
//| Trade platzieren (Place trade) |
//+------------------------------------------------------------------+
bool PlatziereTrade(ENUM_ORDER_TYPE order_type)
{
Print("TRACE: Versuche Trade zu platzieren - Typ: ", (order_type == ORDER_TYPE_BUY) ? "KAUF" : "VERKAUF");
const double lot = United_NormalizeVolume(esData.symbol, g_ES_LotSize);
Print("TRACE: Lot (raw): ", g_ES_LotSize, " normalized: ", lot);
if(lot <= 0.0)
{
Print("TRACE: Abbruch — Lot nach Normalisierung ungültig");
return false;
}
bool success = false;
if(order_type == ORDER_TYPE_BUY)
{
success = esData.trade.Buy(lot, esData.symbol, 0, 0, 0, "EMA Crossover Trade");
}
else
{
success = esData.trade.Sell(lot, esData.symbol, 0, 0, 0, "EMA Crossover Trade");
}
if(success)
{
esData.ticket = (int)esData.trade.ResultOrder();
Print("TRACE: Trade erfolgreich platziert: ", (order_type == ORDER_TYPE_BUY) ? "KAUF" : "VERKAUF", " Ticket: ", esData.ticket);
//--- Trade-Öffnungszeit speichern (Save trade opening time)
esData.trade_open_time = iTime(esData.symbol, ES_Timeframe, 0);
esData.es_last_sl_adjust_success_time = 0;
Print("TRACE: Trade-Öffnungszeit: ", TimeToString(esData.trade_open_time));
//--- Überwachung zurücksetzen (Reset monitoring)
esData.überwachung_aktiv = false;
esData.preis_trigger_aktiv = false;
esData.steigung_trigger_aktiv = false;
return true;
}
else
{
Print("TRACE: Fehler beim Platzieren des Trades - Retcode: ", esData.trade.ResultRetcode());
Print("TRACE: Fehlerbeschreibung: ", esData.trade.ResultRetcodeDescription());
return false;
}
}
//+------------------------------------------------------------------+
//| Trades verwalten (Manage trades) |
//+------------------------------------------------------------------+
void VerwalteTrades()
{
if(!PositionSelectByMagic(esData.symbol, (ulong)ES_MagicNumber))
return;
if(ES_UseStaleStopLossExit && ES_StaleStopLossSeconds > 0)
{
const datetime stale_ref = (esData.es_last_sl_adjust_success_time > 0)
? esData.es_last_sl_adjust_success_time
: (datetime)PositionGetInteger(POSITION_TIME);
if(TimeCurrent() - stale_ref >= ES_StaleStopLossSeconds)
{
SchließePosition("Stale stop loss - keine SL-Anpassung");
return;
}
}
double position_profit = PositionGetDouble(POSITION_PROFIT);
ENUM_POSITION_TYPE position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
int digits = (int)SymbolInfoInteger(esData.symbol, SYMBOL_DIGITS);
double point = SymbolInfoDouble(esData.symbol, SYMBOL_POINT);
double pips_multiplier = (digits == 3 || digits == 5) ? 10.0 : 1.0;
const double trail_dist = ES_TrailingStop * point * pips_multiplier;
const long stops_level = SymbolInfoInteger(esData.symbol, SYMBOL_TRADE_STOPS_LEVEL);
const double min_dist = (double)stops_level * point;
if(ES_UseTrailingStop && ES_TrailingStop > 0.0 && ES_TrailingActivationReached(position_profit, position_type, pips_multiplier))
{
if(position_type == POSITION_TYPE_BUY)
{
const double bid = SymbolInfoDouble(esData.symbol, SYMBOL_BID);
double new_stop_loss = NormalizeDouble(bid - trail_dist, digits);
if(min_dist > 0.0 && bid - new_stop_loss < min_dist)
new_stop_loss = NormalizeDouble(bid - min_dist, digits);
const double current_stop_loss = PositionGetDouble(POSITION_SL);
if(new_stop_loss < bid && new_stop_loss > 0.0 && new_stop_loss > current_stop_loss)
ÄndereStopLoss(new_stop_loss);
}
else if(position_type == POSITION_TYPE_SELL)
{
const double ask = SymbolInfoDouble(esData.symbol, SYMBOL_ASK);
double new_stop_loss = NormalizeDouble(ask + trail_dist, digits);
if(min_dist > 0.0 && new_stop_loss - ask < min_dist)
new_stop_loss = NormalizeDouble(ask + min_dist, digits);
const double current_stop_loss = PositionGetDouble(POSITION_SL);
if(new_stop_loss > ask && new_stop_loss > 0.0 &&
(new_stop_loss < current_stop_loss || current_stop_loss == 0.0))
ÄndereStopLoss(new_stop_loss);
}
}
//--- Ausstieg bei Preis unter/über EMA (Exit when price below/above EMA)
if(ArraySize(esData.ema_array) >= 1)
{
double aktueller_close = iClose(esData.symbol, ES_Timeframe, 0);
double ema_aktuell = esData.ema_array[0];
bool exit_bullish = (position_type == POSITION_TYPE_SELL && aktueller_close > ema_aktuell);
bool exit_bearish = (position_type == POSITION_TYPE_BUY && aktueller_close < ema_aktuell);
if(exit_bullish || exit_bearish)
{
Print("TRACE: Ausstiegssignal - Close: ", aktueller_close, " EMA: ", ema_aktuell);
SchließePosition("EMA Crossover Exit");
Print("TRACE: Position geschlossen - Trade-Counter bleibt bei ", esData.trades_in_current_crossover);
}
}
//--- Profit-Prüfung nach X Bars (Profit check after X bars)
if(ES_CloseUnprofitableTrades && esData.trade_open_time != 0 && PositionExistsByMagic(esData.symbol, (ulong)ES_MagicNumber))
{
Print("TRACE: Profit-Prüfung aktiviert - CloseUnprofitableTrades: ", ES_CloseUnprofitableTrades);
PrüfeProfitNachBars();
}
else if(!ES_CloseUnprofitableTrades)
{
Print("TRACE: Profit-Prüfung deaktiviert - CloseUnprofitableTrades: ", ES_CloseUnprofitableTrades);
}
}
//+------------------------------------------------------------------+
//| Profit-Prüfung nach X Bars (Profit check after X bars) |
//+------------------------------------------------------------------+
void PrüfeProfitNachBars()
{
if(!PositionSelectByMagic(esData.symbol, (ulong)ES_MagicNumber))
{
return; // Keine Position offen
}
datetime current_bar_time = iTime(esData.symbol, ES_Timeframe, 0);
int bars_since_trade_open = iBarShift(esData.symbol, ES_Timeframe, esData.trade_open_time);
Print("TRACE: Bars seit Trade-Öffnung: ", bars_since_trade_open, "/", ES_ProfitCheckBars);
//--- Prüfe ob genügend Bars vergangen sind (Check if enough bars have passed)
if(bars_since_trade_open >= ES_ProfitCheckBars)
{
double position_profit = PositionGetDouble(POSITION_PROFIT);
double position_volume = PositionGetDouble(POSITION_VOLUME);
ENUM_POSITION_TYPE position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
Print("TRACE: Profit-Prüfung nach ", ES_ProfitCheckBars, " Bars");
Print("TRACE: Position Profit: ", position_profit, " USD");
//--- Schließe Position wenn nicht im Profit (Close position if not in profit)
if(position_profit <= 0)
{
Print("TRACE: Position nicht im Profit - Schließe Position");
SchließePosition("Profit Check - Unprofitable");
//--- Trade-Öffnungszeit zurücksetzen (Reset trade opening time)
esData.trade_open_time = 0;
Print("TRACE: Trade-Öffnungszeit zurückgesetzt");
}
else
{
Print("TRACE: Position im Profit - Behalte Position");
//--- Trade-Öffnungszeit zurücksetzen um weitere Prüfungen zu vermeiden (Reset to avoid further checks)
esData.trade_open_time = 0;
}
}
}
//+------------------------------------------------------------------+
//| Stop Loss ändern (Modify Stop Loss) |
//+------------------------------------------------------------------+
void ÄndereStopLoss(double new_stop_loss)
{
Print("TRACE: Versuche Stop Loss zu ändern auf: ", new_stop_loss);
bool success = ModifyPositionByMagic(esData.trade, esData.symbol, (ulong)ES_MagicNumber, new_stop_loss, PositionGetDouble(POSITION_TP));
if(success)
{
esData.es_last_sl_adjust_success_time = TimeCurrent();
Print("TRACE: Stop Loss erfolgreich geändert auf: ", new_stop_loss);
}
else
{
Print("TRACE: Fehler beim Ändern des Stop Loss - Retcode: ", esData.trade.ResultRetcode());
Print("TRACE: Fehlerbeschreibung: ", esData.trade.ResultRetcodeDescription());
}
}
//+------------------------------------------------------------------+
//| Position schließen (Close position) |
//+------------------------------------------------------------------+
void SchließePosition(string reason = "Unbekannt")
{
Print("TRACE: Versuche Position zu schließen - Grund: ", reason);
bool success = ClosePositionByMagic(esData.trade, esData.symbol, (ulong)ES_MagicNumber);
if(success)
{
esData.es_last_sl_adjust_success_time = 0;
Print("TRACE: Position erfolgreich geschlossen - Grund: ", reason);
}
else
{
Print("TRACE: Fehler beim Schließen der Position - Retcode: ", esData.trade.ResultRetcode());
Print("TRACE: Fehlerbeschreibung: ", esData.trade.ResultRetcodeDescription());
}
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void ProcessEMASlopeDistance(string symbol)
{
if(!esData.isInitialized)
return;
esData.symbol = symbol;
const datetime current_bar_time = iTime(esData.symbol, ES_Timeframe, 0);
const bool new_bar = (current_bar_time != esData.last_bar_time);
const bool has_position = PositionExistsByMagic(esData.symbol, (ulong)ES_MagicNumber);
if(ES_UseBarData && !new_bar && !has_position)
return;
if(new_bar)
esData.last_bar_time = current_bar_time;
BerechneEMA();
const bool run_signals = (!ES_UseBarData || new_bar);
if(run_signals && ArraySize(esData.ema_array) > 0)
{
double aktueller_close = iClose(esData.symbol, ES_Timeframe, 0);
double ema_aktuell = esData.ema_array[0];
double ema_vorher = esData.ema_array[1];
double point = SymbolInfoDouble(esData.symbol, SYMBOL_POINT);
double preis_abstand = MathAbs(aktueller_close - ema_aktuell) / point;
double steigung = (ema_aktuell - ema_vorher) / point;
if(ES_UseBarData)
{
Print("=== DEBUG INFO (Neuer Bar) ===");
Print("Bar Zeit: ", TimeToString(iTime(esData.symbol, ES_Timeframe, 0)));
}
else
{
Print("=== DEBUG INFO (Tick) ===");
}
Print("Aktueller Close: ", aktueller_close);
Print("EMA: ", ema_aktuell);
Print("Preis-Abstand: ", preis_abstand, " Pips");
Print("EMA Steigung: ", steigung, " Pips");
Print("Differenz Close-EMA: ", aktueller_close - ema_aktuell);
Print("Preis-Trigger: ", esData.preis_trigger_aktiv, " Steigungs-Trigger: ", esData.steigung_trigger_aktiv);
Print("Überwachung aktiv: ", esData.überwachung_aktiv);
Print("Position offen: ", PositionExistsByMagic(esData.symbol, (ulong)ES_MagicNumber));
Print("Trades im aktuellen Crossover: ", esData.trades_in_current_crossover, "/", ES_MaxTradesPerCrossover);
Print("==================");
}
if(run_signals)
{
if(esData.überwachung_aktiv)
{
if(ES_UseBarData)
{
int bars_since_monitoring = iBarShift(esData.symbol, ES_Timeframe, esData.letzte_überwachung_zeit);
int timeout_bars = (int)(ES_ÜberwachungTimeout / PeriodSeconds(ES_Timeframe));
if(bars_since_monitoring > timeout_bars)
{
esData.überwachung_aktiv = false;
esData.preis_trigger_aktiv = false;
esData.steigung_trigger_aktiv = false;
Print("Überwachung beendet - Bar-basierte Zeitüberschreitung (", bars_since_monitoring, " Bars)");
}
}
else
{
if(TimeCurrent() - esData.letzte_überwachung_zeit > ES_ÜberwachungTimeout)
{
esData.überwachung_aktiv = false;
esData.preis_trigger_aktiv = false;
esData.steigung_trigger_aktiv = false;
Print("Überwachung beendet - Tick-basierte Zeitüberschreitung");
}
}
}
PrüfeTrigger();
}
VerwalteTrades();
}
//+------------------------------------------------------------------+
@@ -0,0 +1,387 @@
//+------------------------------------------------------------------+
//| RSIConsolidationStrategy.mqh |
//| Ported from cluster-0/RSIConsolidation/RSIConsolidation.mq5 |
//+------------------------------------------------------------------+
#ifndef RSI_CONSOLIDATION_STRATEGY_MQH
#define RSI_CONSOLIDATION_STRATEGY_MQH
struct RSIConsolidationData
{
string symbol;
bool isInitialized;
CTrade trade;
ENUM_TIMEFRAMES signalTF;
bool entryOnNewBarOnly;
int adxPeriod;
double adxMax;
bool useATRRatioFilter;
int atrPeriod;
int atrSmaPeriod;
double atrRatioMax;
bool useFlatEMAFilter;
int emaFast;
int emaSlow;
double emaSeparationMaxPct;
int rsiPeriod;
ENUM_APPLIED_PRICE rsiPrice;
double rsiOversold;
double rsiOverbought;
bool useRSIMeanExit;
double rsiExitLong;
double rsiExitShort;
double slAtrMult;
double tpAtrMult;
int maxBarsInTrade;
ulong magic;
int slippage;
int maxSpreadPoints;
int h_rsi;
int h_adx;
int h_atr;
int h_ema_fast;
int h_ema_slow;
datetime lastBar;
};
bool RCO_Copy1(const int handle, double &v)
{
double b[];
ArraySetAsSeries(b, true);
if(CopyBuffer(handle, 0, 0, 1, b) < 1)
return false;
v = b[0];
return true;
}
bool RCO_RsiBuffers(RSIConsolidationData &d, double &cur, double &prev, double &twoAgo)
{
double b[];
ArraySetAsSeries(b, true);
if(CopyBuffer(d.h_rsi, 0, 0, 3, b) < 3)
return false;
cur = b[0];
prev = b[1];
twoAgo = b[2];
return true;
}
double RCO_NormalizeVolume(const string sym, double vol)
{
double minLot = SymbolInfoDouble(sym, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(sym, SYMBOL_VOLUME_MAX);
double step = SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP);
if(step > 0.0)
vol = MathFloor(vol / step) * step;
if(vol < minLot)
vol = minLot;
if(vol > maxLot)
vol = maxLot;
return vol;
}
int RCO_CurrentSpreadPoints(const string sym)
{
long spread = 0;
if(!SymbolInfoInteger(sym, SYMBOL_SPREAD, spread))
return 999999;
return (int)spread;
}
double RCO_MinStopsDistancePrice(const string sym)
{
long lvl = 0;
if(!SymbolInfoInteger(sym, SYMBOL_TRADE_STOPS_LEVEL, lvl))
return 0;
double pt = SymbolInfoDouble(sym, SYMBOL_POINT);
if(pt <= 0)
return 0;
return (double)lvl * pt;
}
bool RCO_RegimeIsConsolidation(RSIConsolidationData &d)
{
double adx = 0;
if(!RCO_Copy1(d.h_adx, adx))
return false;
if(adx >= d.adxMax)
return false;
if(d.useATRRatioFilter)
{
double atrArr[];
ArraySetAsSeries(atrArr, true);
if(CopyBuffer(d.h_atr, 0, 0, d.atrSmaPeriod + 1, atrArr) < d.atrSmaPeriod + 1)
return false;
double sum = 0;
for(int i = 1; i <= d.atrSmaPeriod; i++)
sum += atrArr[i];
double smaAtr = sum / (double)d.atrSmaPeriod;
if(smaAtr <= 0.0)
return false;
double ratio = atrArr[0] / smaAtr;
if(ratio > d.atrRatioMax)
return false;
}
if(d.useFlatEMAFilter)
{
double ef[], es[];
ArraySetAsSeries(ef, true);
ArraySetAsSeries(es, true);
if(CopyBuffer(d.h_ema_fast, 0, 0, 1, ef) < 1)
return false;
if(CopyBuffer(d.h_ema_slow, 0, 0, 1, es) < 1)
return false;
double c = SymbolInfoDouble(d.symbol, SYMBOL_BID);
if(c <= 0)
return false;
double sep = MathAbs(ef[0] - es[0]) / c * 100.0;
if(sep > d.emaSeparationMaxPct)
return false;
}
return true;
}
bool RCO_EntryBuyCross(RSIConsolidationData &d, const double twoAgo, const double prev)
{
return (twoAgo <= d.rsiOversold && prev > d.rsiOversold);
}
bool RCO_EntrySellCross(RSIConsolidationData &d, const double twoAgo, const double prev)
{
return (twoAgo >= d.rsiOverbought && prev < d.rsiOverbought);
}
void RCO_TryCloseByRSI(RSIConsolidationData &d, const ENUM_POSITION_TYPE typ, const double rsi)
{
ulong tk = GetPositionTicketByMagic(d.symbol, d.magic);
if(tk == 0 || !PositionSelectByTicketSymbolAndMagic(tk, d.symbol, d.magic))
return;
if(!d.useRSIMeanExit)
return;
if(typ == POSITION_TYPE_BUY && rsi >= d.rsiExitLong)
d.trade.PositionClose(tk);
else if(typ == POSITION_TYPE_SELL && rsi <= d.rsiExitShort)
d.trade.PositionClose(tk);
}
void RCO_ManageOpenPosition(RSIConsolidationData &d, const double rsi)
{
ulong tk = GetPositionTicketByMagic(d.symbol, d.magic);
if(tk == 0 || !PositionSelectByTicketSymbolAndMagic(tk, d.symbol, d.magic))
return;
ENUM_POSITION_TYPE typ = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
datetime openT = (datetime)PositionGetInteger(POSITION_TIME);
int barsAgo = iBarShift(d.symbol, d.signalTF, openT, false);
if(barsAgo >= 0 && barsAgo >= d.maxBarsInTrade)
{
d.trade.PositionClose(tk);
return;
}
RCO_TryCloseByRSI(d, typ, rsi);
}
bool InitRSIConsolidation(RSIConsolidationData &d,
const string inpSymbol,
const ENUM_TIMEFRAMES signalTF,
const bool entryOnNewBarOnly,
const int adxPeriod,
const double adxMax,
const bool useATRRatioFilter,
const int atrPeriod,
const int atrSmaPeriod,
const double atrRatioMax,
const bool useFlatEMAFilter,
const int emaFast,
const int emaSlow,
const double emaSeparationMaxPct,
const int rsiPeriod,
const ENUM_APPLIED_PRICE rsiPrice,
const double rsiOversold,
const double rsiOverbought,
const bool useRSIMeanExit,
const double rsiExitLong,
const double rsiExitShort,
const double slAtrMult,
const double tpAtrMult,
const int maxBarsInTrade,
const ulong magic,
const int slippage,
const int maxSpreadPoints)
{
d.isInitialized = false;
d.symbol = inpSymbol;
StringTrimLeft(d.symbol);
StringTrimRight(d.symbol);
if(StringLen(d.symbol) == 0)
d.symbol = _Symbol;
d.signalTF = signalTF;
d.entryOnNewBarOnly = entryOnNewBarOnly;
d.adxPeriod = adxPeriod;
d.adxMax = adxMax;
d.useATRRatioFilter = useATRRatioFilter;
d.atrPeriod = atrPeriod;
d.atrSmaPeriod = atrSmaPeriod;
d.atrRatioMax = atrRatioMax;
d.useFlatEMAFilter = useFlatEMAFilter;
d.emaFast = emaFast;
d.emaSlow = emaSlow;
d.emaSeparationMaxPct = emaSeparationMaxPct;
d.rsiPeriod = rsiPeriod;
d.rsiPrice = rsiPrice;
d.rsiOversold = rsiOversold;
d.rsiOverbought = rsiOverbought;
d.useRSIMeanExit = useRSIMeanExit;
d.rsiExitLong = rsiExitLong;
d.rsiExitShort = rsiExitShort;
d.slAtrMult = slAtrMult;
d.tpAtrMult = tpAtrMult;
d.maxBarsInTrade = maxBarsInTrade;
d.magic = magic;
d.slippage = slippage;
d.maxSpreadPoints = maxSpreadPoints;
d.lastBar = 0;
d.h_rsi = INVALID_HANDLE;
d.h_adx = INVALID_HANDLE;
d.h_atr = INVALID_HANDLE;
d.h_ema_fast = INVALID_HANDLE;
d.h_ema_slow = INVALID_HANDLE;
d.isInitialized = false;
if(!SymbolSelect(d.symbol, true))
{
Print("RSIConsolidation: SymbolSelect failed: ", d.symbol);
return false;
}
d.trade.SetExpertMagicNumber((long)d.magic);
d.trade.SetDeviationInPoints(d.slippage);
d.trade.SetTypeFillingBySymbol(d.symbol);
d.h_rsi = iRSI(d.symbol, d.signalTF, d.rsiPeriod, d.rsiPrice);
d.h_adx = iADX(d.symbol, d.signalTF, d.adxPeriod);
d.h_atr = iATR(d.symbol, d.signalTF, d.atrPeriod);
d.h_ema_fast = iMA(d.symbol, d.signalTF, d.emaFast, 0, MODE_EMA, PRICE_CLOSE);
d.h_ema_slow = iMA(d.symbol, d.signalTF, d.emaSlow, 0, MODE_EMA, PRICE_CLOSE);
if(d.h_rsi == INVALID_HANDLE || d.h_adx == INVALID_HANDLE || d.h_atr == INVALID_HANDLE
|| d.h_ema_fast == INVALID_HANDLE || d.h_ema_slow == INVALID_HANDLE)
{
Print("RSIConsolidation: indicator init failed");
DeinitRSIConsolidation(d);
return false;
}
d.isInitialized = true;
Print("RSIConsolidation: symbol=", d.symbol, " TF=", EnumToString(d.signalTF));
return true;
}
void DeinitRSIConsolidation(RSIConsolidationData &d)
{
if(d.h_rsi != INVALID_HANDLE)
IndicatorRelease(d.h_rsi);
if(d.h_adx != INVALID_HANDLE)
IndicatorRelease(d.h_adx);
if(d.h_atr != INVALID_HANDLE)
IndicatorRelease(d.h_atr);
if(d.h_ema_fast != INVALID_HANDLE)
IndicatorRelease(d.h_ema_fast);
if(d.h_ema_slow != INVALID_HANDLE)
IndicatorRelease(d.h_ema_slow);
d.h_rsi = INVALID_HANDLE;
d.h_adx = INVALID_HANDLE;
d.h_atr = INVALID_HANDLE;
d.h_ema_fast = INVALID_HANDLE;
d.h_ema_slow = INVALID_HANDLE;
d.isInitialized = false;
}
bool RCO_EnoughHistory(RSIConsolidationData &d)
{
int need = MathMax(d.rsiPeriod + 3, MathMax(d.adxPeriod + 2, d.atrSmaPeriod + 3));
if(Bars(d.symbol, d.signalTF) < need)
return false;
return true;
}
void ProcessRSIConsolidation(RSIConsolidationData &d, const double lots)
{
if(!d.isInitialized)
return;
if(!RCO_EnoughHistory(d))
return;
if(d.maxSpreadPoints > 0 && RCO_CurrentSpreadPoints(d.symbol) > d.maxSpreadPoints)
return;
double rsi, rsiPrev, rsi2;
if(!RCO_RsiBuffers(d, rsi, rsiPrev, rsi2))
return;
datetime barTime = iTime(d.symbol, d.signalTF, 0);
bool isNew = (barTime != d.lastBar);
if(PositionExistsByMagic(d.symbol, d.magic))
{
RCO_ManageOpenPosition(d, rsi);
if(isNew)
d.lastBar = barTime;
return;
}
if(d.entryOnNewBarOnly && !isNew)
return;
d.lastBar = barTime;
if(!RCO_RegimeIsConsolidation(d))
return;
double atrArr[];
ArraySetAsSeries(atrArr, true);
if(CopyBuffer(d.h_atr, 0, 0, 1, atrArr) < 1)
return;
double atr = atrArr[0];
int dig = (int)SymbolInfoInteger(d.symbol, SYMBOL_DIGITS);
double slDist = atr * d.slAtrMult;
double tpDist = atr * d.tpAtrMult;
double minD = RCO_MinStopsDistancePrice(d.symbol);
if(slDist < minD)
slDist = minD;
if(tpDist < minD)
tpDist = minD;
double vol = RCO_NormalizeVolume(d.symbol, lots);
if(RCO_EntryBuyCross(d, rsi2, rsiPrev))
{
if(!United_MayOpenNewEntry(d.symbol, d.magic, true))
return;
double ask = SymbolInfoDouble(d.symbol, SYMBOL_ASK);
double sl = ask - slDist;
double tp = ask + tpDist;
sl = NormalizeDouble(sl, dig);
tp = NormalizeDouble(tp, dig);
if(!d.trade.Buy(vol, d.symbol, ask, sl, tp, "RSIConsolidation BUY"))
Print("RSIConsolidation BUY failed | retcode=", d.trade.ResultRetcode(), " ", d.trade.ResultRetcodeDescription());
}
else if(RCO_EntrySellCross(d, rsi2, rsiPrev))
{
if(!United_MayOpenNewEntry(d.symbol, d.magic, false))
return;
double bid = SymbolInfoDouble(d.symbol, SYMBOL_BID);
double sl = bid + slDist;
double tp = bid - tpDist;
sl = NormalizeDouble(sl, dig);
tp = NormalizeDouble(tp, dig);
if(!d.trade.Sell(vol, d.symbol, bid, sl, tp, "RSIConsolidation SELL"))
Print("RSIConsolidation SELL failed | retcode=", d.trade.ResultRetcode(), " ", d.trade.ResultRetcodeDescription());
}
}
#endif // RSI_CONSOLIDATION_STRATEGY_MQH
@@ -0,0 +1,269 @@
//+------------------------------------------------------------------+
//| RSICrossOverReversalStrategy.mqh |
//+------------------------------------------------------------------+
void WeekDays_Init()
{
rcData.WeekDays[0] = RC_Sunday;
rcData.WeekDays[1] = RC_Monday;
rcData.WeekDays[2] = RC_Tuesday;
rcData.WeekDays[3] = RC_Wednesday;
rcData.WeekDays[4] = RC_Thursday;
rcData.WeekDays[5] = RC_Friday;
rcData.WeekDays[6] = RC_Saturday;
}
bool WeekDays_Check(datetime aTime)
{
MqlDateTime stm;
TimeToStruct(aTime, stm);
return(rcData.WeekDays[stm.day_of_week]);
}
bool RC_HourInWindow(const int h, const int beginRaw, const int endRaw)
{
const int b = beginRaw % 24;
const int e = endRaw % 24;
if(b == e)
return false;
if(b < e)
return (h >= b && h < e);
return (h >= b || h < e);
}
bool RC_TradingHoursAllow(const int currentHour)
{
return RC_HourInWindow(currentHour, RC_tradingHourOneBegin, RC_tradingHourOneEnd)
|| RC_HourInWindow(currentHour, RC_tradingHourTwoBegin, RC_tradingHourTwoEnd);
}
int TimeHour(datetime when = 0)
{
if(when == 0) when = TimeCurrent();
MqlDateTime dt;
TimeToStruct(when, dt);
return dt.hour;
}
bool InitRSICrossOverReversal(string symbol)
{
WeekDays_Init();
rcData.symbol = symbol;
rcData.previousRSIDef = 0;
rcData.lastTradeTime = 0;
rcData.bartime = 0;
rcData.lastBarTime = 0;
// Check if symbol exists
if(!SymbolSelect(symbol, true))
{
Print("RSICrossOverReversal: Symbol '", symbol, "' not available in Market Watch. Please add it to Market Watch or check symbol name.");
return false;
}
Sleep(100); // Wait for symbol to be ready
rcData.rsiHandle = iRSI(symbol, RC_TimeFrame1, RC_rsiPeriod, PRICE_CLOSE);
if(rcData.rsiHandle == INVALID_HANDLE)
{
Print("RSICrossOverReversal: Error creating RSI handle for '", symbol, "'");
return false;
}
rcData.emaHandle = iMA(symbol, RC_TimeFrame2, RC_emaPeriod, 0, MODE_EMA, PRICE_CLOSE);
if(rcData.emaHandle == INVALID_HANDLE)
{
Print("RSICrossOverReversal: Error creating EMA handle for '", symbol, "'");
return false;
}
rcData.trade.SetExpertMagicNumber(RC_MagicNumber);
rcData.trade.SetDeviationInPoints(RC_slippage);
rcData.isInitialized = true;
Print("RSICrossOverReversal: Successfully initialized for symbol '", symbol, "'");
return true;
}
void DeinitRSICrossOverReversal()
{
if(rcData.rsiHandle != INVALID_HANDLE)
IndicatorRelease(rcData.rsiHandle);
if(rcData.emaHandle != INVALID_HANDLE)
IndicatorRelease(rcData.emaHandle);
}
void Close_Position_MN(ulong magicNumber)
{
ClosePositionByMagic(rcData.trade, rcData.symbol, (int)magicNumber);
}
void ApplyTrailingStop()
{
if(!PositionSelectByMagic(rcData.symbol, RC_MagicNumber))
return;
ulong PositionTicket = PositionGetInteger(POSITION_TICKET);
ENUM_POSITION_TYPE trade_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
string symbol = rcData.symbol;
double POINT = SymbolInfoDouble(symbol, SYMBOL_POINT);
int DIGIT = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);
if(trade_type == POSITION_TYPE_BUY)
{
double Bid = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_BID), DIGIT);
if(Bid - PositionGetDouble(POSITION_PRICE_OPEN) > NormalizeDouble(POINT * RC_TrailingStop, DIGIT))
{
if(PositionGetDouble(POSITION_SL) < NormalizeDouble(Bid - POINT * RC_TrailingStop, DIGIT))
{
ModifyPositionByMagic(rcData.trade, symbol, RC_MagicNumber,
NormalizeDouble(Bid - POINT * RC_TrailingStop, DIGIT),
PositionGetDouble(POSITION_TP));
}
}
}
else if(trade_type == POSITION_TYPE_SELL)
{
double Ask = NormalizeDouble(SymbolInfoDouble(symbol, SYMBOL_ASK), DIGIT);
if((PositionGetDouble(POSITION_PRICE_OPEN) - Ask) > NormalizeDouble(POINT * RC_TrailingStop, DIGIT))
{
if((PositionGetDouble(POSITION_SL) > NormalizeDouble(Ask + POINT * RC_TrailingStop, DIGIT)) ||
(PositionGetDouble(POSITION_SL) == 0))
{
ModifyPositionByMagic(rcData.trade, symbol, RC_MagicNumber,
NormalizeDouble(Ask + POINT * RC_TrailingStop, DIGIT),
PositionGetDouble(POSITION_TP));
}
}
}
}
void ProcessRSICrossOverReversal(string symbol)
{
// Skip if not initialized (symbol not available)
if(!rcData.isInitialized)
return;
rcData.symbol = symbol; // Update symbol in case it changed
if(rcData.bartime == iTime(rcData.symbol, RC_BarTimeFrame, 0))
return;
rcData.bartime = iTime(rcData.symbol, RC_BarTimeFrame, 0);
double rsi[];
if(CopyBuffer(rcData.rsiHandle, 0, 0, 2, rsi) <= 0)
return;
double ema[];
if(CopyBuffer(rcData.emaHandle, 0, 0, 2, ema) <= 0)
return;
datetime currentTime = TimeCurrent();
int currentHour = TimeHour(TimeCurrent());
if(!WeekDays_Check(TimeTradeServer()))
{
Close_Position_MN(RC_MagicNumber);
return;
}
if(!RC_TradingHoursAllow(currentHour))
{
Close_Position_MN(RC_MagicNumber);
return;
}
bool hasPosition = PositionExistsByMagic(rcData.symbol, RC_MagicNumber);
double currentRSI = rsi[0];
double previousRSI = rsi[1];
if(rcData.previousRSIDef == 0)
{
rcData.previousRSIDef = currentRSI;
return;
}
double currentEMA = ema[0];
double previousEMA = ema[1];
double emaSlope = (currentEMA - previousEMA) * 100;
const double closeCurr = iClose(rcData.symbol, RC_TimeFrame1, 0);
// Raw (close-EMA)*10 blows past threshold on XAUUSD (~2600) almost every bar — blocks all entries.
// Compare distance in pips so RC_emaDistanceThreshold matches intent across symbols.
const double point = SymbolInfoDouble(rcData.symbol, SYMBOL_POINT);
const int symDig = (int)SymbolInfoInteger(rcData.symbol, SYMBOL_DIGITS);
const double pipMult = (symDig == 3 || symDig == 5) ? 10.0 : 1.0;
const double pipSize = (point > 0.0 ? point * pipMult : point);
const double priceToEmaPips = (pipSize > 0.0 ? MathAbs(closeCurr - currentEMA) / pipSize : 0.0);
bool isBuyPosition = false;
bool isSellPosition = false;
if(hasPosition)
{
if(PositionSelectByMagic(rcData.symbol, RC_MagicNumber))
{
ENUM_POSITION_TYPE positionType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
if(positionType == POSITION_TYPE_BUY)
isBuyPosition = true;
else if(positionType == POSITION_TYPE_SELL)
isSellPosition = true;
}
}
ApplyTrailingStop();
bool cooldownPassed = (currentTime - rcData.lastTradeTime) >= RC_cooldownSeconds;
const bool isTrendStrong = RC_UseTrendStrengthFilter &&
(MathAbs(emaSlope) > RC_emaSlopeThreshold || priceToEmaPips > RC_emaDistanceThreshold);
if(isBuyPosition && currentRSI > RC_exitBuyRSI)
{
Close_Position_MN(RC_MagicNumber);
rcData.lastTradeTime = currentTime;
}
if(isSellPosition && currentRSI < RC_exitSellRSI)
{
Close_Position_MN(RC_MagicNumber);
rcData.lastTradeTime = currentTime;
}
if(isTrendStrong)
{
Close_Position_MN(RC_MagicNumber);
rcData.lastTradeTime = currentTime;
}
if(!isTrendStrong &&
currentRSI < RC_overboughtLevel - RC_entryRSISellSpread && rcData.previousRSIDef >= RC_overboughtLevel &&
!isSellPosition && !hasPosition && cooldownPassed)
{
const double vol = United_NormalizeVolume(rcData.symbol, g_RC_LotSize);
if(vol > 0.0)
{
rcData.trade.SetExpertMagicNumber(RC_MagicNumber);
if(rcData.trade.Sell(vol, rcData.symbol, 0.0, 0.0, 0.0, "Sell Order"))
rcData.lastTradeTime = currentTime;
}
}
if(!isTrendStrong &&
currentRSI > RC_oversoldLevel + RC_entryRSIBuySpread && rcData.previousRSIDef <= RC_oversoldLevel &&
!isBuyPosition && !hasPosition && cooldownPassed)
{
const double vol = United_NormalizeVolume(rcData.symbol, g_RC_LotSize);
if(vol > 0.0)
{
rcData.trade.SetExpertMagicNumber(RC_MagicNumber);
if(rcData.trade.Buy(vol, rcData.symbol, 0.0, 0.0, 0.0, "Buy Order"))
rcData.lastTradeTime = currentTime;
}
}
rcData.previousRSIDef = currentRSI;
}
//+------------------------------------------------------------------+
@@ -0,0 +1,492 @@
//+------------------------------------------------------------------+
//| RSIMidPointHijackStrategy.mqh |
//+------------------------------------------------------------------+
double RM_NormalizedLot(const string sym)
{
return United_NormalizeVolume(sym, g_RM_LotSize);
}
bool IsNewBar(string symbol)
{
datetime time[];
if(CopyTime(symbol, RM_InpTimeframe, 0, 1, time) > 0)
{
if(time[0] != rmData.lastBarTime)
{
rmData.lastBarTime = time[0];
return true;
}
}
return false;
}
bool IsWithinTradingHours(int startHour, int endHour)
{
MqlDateTime currentTime;
TimeToStruct(TimeCurrent(), currentTime);
if(startHour <= endHour)
return (currentTime.hour >= startHour && currentTime.hour < endHour);
else
return (currentTime.hour >= startHour || currentTime.hour < endHour);
}
bool HasPosition(string symbol, int magic)
{
return PositionExistsByMagic(symbol, magic);
}
bool HasProfitablePosition(int excludeMagic)
{
bool hasProfitable = false;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(rmData.positionInfo.SelectByIndex(i))
{
if(rmData.positionInfo.Magic() != excludeMagic)
{
double profit = rmData.positionInfo.Profit();
if(profit > RM_InpLockProfitThreshold * _Point)
{
hasProfitable = true;
if(RM_InpCloseOppositeTrades)
{
if((excludeMagic == RM_InpMagicNumberRSIFollow && rmData.positionInfo.Magic() == RM_InpMagicNumberRSIReverse) ||
(excludeMagic == RM_InpMagicNumberRSIReverse && rmData.positionInfo.Magic() == RM_InpMagicNumberRSIFollow) ||
(excludeMagic == RM_InpMagicNumberEMACross && (rmData.positionInfo.Magic() == RM_InpMagicNumberRSIReverse || rmData.positionInfo.Magic() == RM_InpMagicNumberRSIFollow)) ||
((excludeMagic == RM_InpMagicNumberRSIFollow || excludeMagic == RM_InpMagicNumberRSIReverse) && rmData.positionInfo.Magic() == RM_InpMagicNumberEMACross))
{
ClosePosition(rmData.symbol, (int)rmData.positionInfo.Magic());
}
}
}
}
}
}
return hasProfitable;
}
bool IsRSIReverseInCooldown(string symbol)
{
if(RM_InpRSIReverseCooldownBars <= 0)
return false;
if(!rmData.rsiReverseInCooldown)
return false;
datetime time[];
if(CopyTime(symbol, RM_InpTimeframe, 0, 1, time) > 0)
{
datetime currentBarTime = time[0];
datetime cooldownEndTime = rmData.rsiReverseLastCloseTime + RM_InpRSIReverseCooldownBars * PeriodSeconds(RM_InpTimeframe);
if(currentBarTime >= cooldownEndTime)
{
rmData.rsiReverseInCooldown = false;
return false;
}
}
return true;
}
void CheckRSIFollowStrategy(string symbol)
{
if(!IsWithinTradingHours(RM_InpRSIFollowStartHour, RM_InpRSIFollowEndHour))
{
if(RM_InpRSIFollowCloseOutsideHours)
{
if(HasPosition(symbol, RM_InpMagicNumberRSIFollow))
ClosePosition(symbol, RM_InpMagicNumberRSIFollow);
}
return;
}
if(RM_InpEnableStrategyLock && HasProfitablePosition(RM_InpMagicNumberRSIFollow))
return;
if(rmData.lastBarRSI > RM_InpRSIOverbought)
rmData.rsiOverbought = true;
else if(rmData.lastBarRSI < RM_InpRSIOversold)
rmData.rsiOversold = true;
if(rmData.rsiOverbought && rmData.lastBarRSI < RM_InpRSIExitLevel)
{
if(!HasPosition(symbol, RM_InpMagicNumberRSIFollow))
{
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberRSIFollow);
const double vol = RM_NormalizedLot(symbol);
if(vol > 0.0)
rmData.trade.Sell(vol, symbol, 0, 0, 0, "RSI Follow");
}
rmData.rsiOverbought = false;
}
else if(rmData.rsiOversold && rmData.lastBarRSI > RM_InpRSIExitLevel)
{
if(!HasPosition(symbol, RM_InpMagicNumberRSIFollow))
{
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberRSIFollow);
const double vol = RM_NormalizedLot(symbol);
if(vol > 0.0)
rmData.trade.Buy(vol, symbol, 0, 0, 0, "RSI Follow");
}
rmData.rsiOversold = false;
}
}
void CheckRSIReverseStrategy(string symbol)
{
if(!IsWithinTradingHours(RM_InpRSIReverseStartHour, RM_InpRSIReverseEndHour))
{
if(RM_InpRSIReverseCloseOutsideHours)
{
if(HasPosition(symbol, RM_InpMagicNumberRSIReverse))
ClosePosition(symbol, RM_InpMagicNumberRSIReverse);
}
return;
}
if(RM_InpEnableStrategyLock && HasProfitablePosition(RM_InpMagicNumberRSIReverse))
return;
if(IsRSIReverseInCooldown(symbol))
return;
if(rmData.lastBarRSIReverse > RM_InpRSIReverseOverbought)
rmData.rsiReverseOverbought = true;
else if(rmData.lastBarRSIReverse < RM_InpRSIReverseOversold)
rmData.rsiReverseOversold = true;
if(rmData.rsiReverseOverbought && rmData.lastBarRSIReverse < RM_InpRSIReverseCrossLevel)
{
if(!HasPosition(symbol, RM_InpMagicNumberRSIReverse))
{
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberRSIReverse);
const double vol = RM_NormalizedLot(symbol);
if(vol > 0.0)
rmData.trade.Sell(vol, symbol, 0, 0, 0, "RSI Reverse");
}
rmData.rsiReverseOverbought = false;
}
else if(rmData.rsiReverseOversold && rmData.lastBarRSIReverse > RM_InpRSIReverseCrossLevel)
{
if(!HasPosition(symbol, RM_InpMagicNumberRSIReverse))
{
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberRSIReverse);
const double vol = RM_NormalizedLot(symbol);
if(vol > 0.0)
rmData.trade.Buy(vol, symbol, 0, 0, 0, "RSI Reverse");
}
rmData.rsiReverseOversold = false;
}
}
void CheckEMACrossStrategy(string symbol)
{
if(!IsWithinTradingHours(RM_InpEMACrossStartHour, RM_InpEMACrossEndHour))
{
if(RM_InpEMACrossCloseOutsideHours)
{
if(HasPosition(symbol, RM_InpMagicNumberEMACross))
ClosePosition(symbol, RM_InpMagicNumberEMACross);
}
return;
}
if(RM_InpEnableStrategyLock && HasProfitablePosition(RM_InpMagicNumberEMACross))
return;
if(rmData.lastBarEMAPrev < rmData.lastBarClosePrev && rmData.lastBarEMA > rmData.lastBarClose)
{
rmData.emaCrossBuySignal = true;
rmData.emaCrossSellSignal = false;
rmData.emaCrossSignalBar = 0;
}
else if(rmData.lastBarEMAPrev > rmData.lastBarClosePrev && rmData.lastBarEMA < rmData.lastBarClose)
{
rmData.emaCrossSellSignal = true;
rmData.emaCrossBuySignal = false;
rmData.emaCrossSignalBar = 0;
}
if(RM_InpUseEMADistanceEntry)
{
if(rmData.emaCrossBuySignal)
{
bool distanceConditionMet = true;
double emaHistory[], closeHistory[];
ArraySetAsSeries(emaHistory, true);
ArraySetAsSeries(closeHistory, true);
if(CopyBuffer(rmData.emaHandle, 0, 0, RM_InpEMADistancePeriod, emaHistory) > 0 &&
CopyClose(symbol, RM_InpTimeframe, 0, RM_InpEMADistancePeriod, closeHistory) > 0)
{
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
for(int i = 0; i < RM_InpEMADistancePeriod; i++)
{
double distance = (closeHistory[i] - emaHistory[i]) / point;
if(distance < RM_InpEMADistancePips)
{
distanceConditionMet = false;
break;
}
}
if(distanceConditionMet && !HasPosition(symbol, RM_InpMagicNumberEMACross))
{
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberEMACross);
const double vol = RM_NormalizedLot(symbol);
if(vol > 0.0)
rmData.trade.Buy(vol, symbol, 0, 0, 0, "EMA Cross Distance");
rmData.emaCrossBuySignal = false;
}
}
}
else if(rmData.emaCrossSellSignal)
{
bool distanceConditionMet = true;
double emaHistory[], closeHistory[];
ArraySetAsSeries(emaHistory, true);
ArraySetAsSeries(closeHistory, true);
if(CopyBuffer(rmData.emaHandle, 0, 0, RM_InpEMADistancePeriod, emaHistory) > 0 &&
CopyClose(symbol, RM_InpTimeframe, 0, RM_InpEMADistancePeriod, closeHistory) > 0)
{
double point = SymbolInfoDouble(symbol, SYMBOL_POINT);
for(int i = 0; i < RM_InpEMADistancePeriod; i++)
{
double distance = (emaHistory[i] - closeHistory[i]) / point;
if(distance < RM_InpEMADistancePips)
{
distanceConditionMet = false;
break;
}
}
if(distanceConditionMet && !HasPosition(symbol, RM_InpMagicNumberEMACross))
{
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberEMACross);
const double vol = RM_NormalizedLot(symbol);
if(vol > 0.0)
rmData.trade.Sell(vol, symbol, 0, 0, 0, "EMA Cross Distance");
rmData.emaCrossSellSignal = false;
}
}
}
}
else
{
if(rmData.lastBarEMAPrev < rmData.lastBarClosePrev && rmData.lastBarEMA > rmData.lastBarClose)
{
if(!HasPosition(symbol, RM_InpMagicNumberEMACross))
{
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberEMACross);
const double vol = RM_NormalizedLot(symbol);
if(vol > 0.0)
rmData.trade.Buy(vol, symbol, 0, 0, 0, "EMA Cross");
}
}
else if(rmData.lastBarEMAPrev > rmData.lastBarClosePrev && rmData.lastBarEMA < rmData.lastBarClose)
{
if(!HasPosition(symbol, RM_InpMagicNumberEMACross))
{
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberEMACross);
const double vol = RM_NormalizedLot(symbol);
if(vol > 0.0)
rmData.trade.Sell(vol, symbol, 0, 0, 0, "EMA Cross");
}
}
}
if(rmData.emaCrossBuySignal || rmData.emaCrossSellSignal)
{
rmData.emaCrossSignalBar++;
if(rmData.emaCrossSignalBar > RM_InpEMADistancePeriod * 2)
{
rmData.emaCrossBuySignal = false;
rmData.emaCrossSellSignal = false;
}
}
}
void CheckExitConditions(string symbol)
{
if(RM_InpEnableRSIFollow)
{
if(HasPosition(symbol, RM_InpMagicNumberRSIFollow))
{
if(PositionSelectByMagic(symbol, RM_InpMagicNumberRSIFollow))
{
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
if((posType == POSITION_TYPE_BUY && rmData.lastBarRSI < RM_InpRSIExitLevel) ||
(posType == POSITION_TYPE_SELL && rmData.lastBarRSI > RM_InpRSIExitLevel))
{
ClosePosition(symbol, RM_InpMagicNumberRSIFollow);
}
}
}
}
if(RM_InpEnableRSIReverse)
{
if(HasPosition(symbol, RM_InpMagicNumberRSIReverse))
{
if(PositionSelectByMagic(symbol, RM_InpMagicNumberRSIReverse))
{
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
if((posType == POSITION_TYPE_BUY && rmData.lastBarRSIReverse < RM_InpRSIReverseExitLevel) ||
(posType == POSITION_TYPE_SELL && rmData.lastBarRSIReverse > RM_InpRSIReverseExitLevel))
{
ClosePosition(symbol, RM_InpMagicNumberRSIReverse);
}
}
}
}
if(RM_InpEnableEMACross)
{
if(HasPosition(symbol, RM_InpMagicNumberEMACross))
{
if(PositionSelectByMagic(symbol, RM_InpMagicNumberEMACross))
{
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
if((posType == POSITION_TYPE_BUY && rmData.lastBarEMA > rmData.lastBarClose) ||
(posType == POSITION_TYPE_SELL && rmData.lastBarEMA < rmData.lastBarClose))
{
ClosePosition(symbol, RM_InpMagicNumberEMACross);
}
}
}
}
}
void ClosePosition(string symbol, int magic)
{
if(!PositionExistsByMagic(symbol, magic))
return;
ulong ticket = GetPositionTicketByMagic(symbol, magic);
if(ticket == 0)
return;
if(magic == RM_InpMagicNumberRSIReverse)
{
if(PositionSelectByTicketSymbolAndMagic(ticket, symbol, magic))
{
datetime time[];
if(CopyTime(symbol, RM_InpTimeframe, 0, 1, time) > 0)
{
rmData.rsiReverseLastCloseTime = time[0];
double profit = PositionGetDouble(POSITION_PROFIT);
if(!RM_InpRSIReverseCooldownOnLoss || profit < 0)
{
rmData.rsiReverseInCooldown = true;
}
}
}
}
ClosePositionByMagic(rmData.trade, symbol, magic);
}
bool InitRSIMidPointHijack(string symbol)
{
rmData.symbol = symbol;
rmData.rsiOverbought = false;
rmData.rsiOversold = false;
rmData.rsiReverseOverbought = false;
rmData.rsiReverseOversold = false;
rmData.emaCrossBuySignal = false;
rmData.emaCrossSellSignal = false;
rmData.emaCrossSignalBar = 0;
rmData.rsiReverseInCooldown = false;
rmData.lastBarRSI = 0;
rmData.lastBarRSIReverse = 0;
rmData.lastBarEMA = 0;
rmData.lastBarClose = 0;
rmData.lastBarEMAPrev = 0;
rmData.lastBarClosePrev = 0;
// Check if symbol exists
if(!SymbolSelect(symbol, true))
{
Print("RSIMidPointHijack: Symbol '", symbol, "' not available in Market Watch. Please add it to Market Watch or check symbol name.");
return false;
}
Sleep(100); // Wait for symbol to be ready
rmData.rsiHandle = iRSI(symbol, RM_InpTimeframe, RM_InpRSIPeriod, PRICE_CLOSE);
rmData.rsiReverseHandle = iRSI(symbol, RM_InpTimeframe, RM_InpRSIReversePeriod, PRICE_CLOSE);
rmData.emaHandle = iMA(symbol, RM_InpTimeframe, RM_InpEMAPeriod, 0, MODE_EMA, PRICE_CLOSE);
if(rmData.rsiHandle == INVALID_HANDLE || rmData.rsiReverseHandle == INVALID_HANDLE || rmData.emaHandle == INVALID_HANDLE)
{
Print("RSIMidPointHijack: Error creating indicators for '", symbol, "'");
return false;
}
rmData.trade.SetExpertMagicNumber(RM_InpMagicNumberRSIFollow);
rmData.trade.SetMarginMode();
rmData.trade.SetTypeFillingBySymbol(symbol);
rmData.trade.SetDeviationInPoints(10);
datetime time[];
if(CopyTime(symbol, RM_InpTimeframe, 0, 1, time) > 0)
rmData.lastBarTime = time[0];
rmData.isInitialized = true;
Print("RSIMidPointHijack: Successfully initialized for symbol '", symbol, "'");
return true;
}
void DeinitRSIMidPointHijack()
{
if(rmData.rsiHandle != INVALID_HANDLE) IndicatorRelease(rmData.rsiHandle);
if(rmData.rsiReverseHandle != INVALID_HANDLE) IndicatorRelease(rmData.rsiReverseHandle);
if(rmData.emaHandle != INVALID_HANDLE) IndicatorRelease(rmData.emaHandle);
}
void ProcessRSIMidPointHijack(string symbol)
{
// Skip if not initialized (symbol not available)
if(!rmData.isInitialized)
return;
rmData.symbol = symbol; // Update symbol in case it changed
if(!IsNewBar(rmData.symbol))
return;
double rsi[], rsiReverse[], ema[], close[];
ArraySetAsSeries(rsi, true);
ArraySetAsSeries(rsiReverse, true);
ArraySetAsSeries(ema, true);
ArraySetAsSeries(close, true);
rmData.lastBarEMAPrev = rmData.lastBarEMA;
rmData.lastBarClosePrev = rmData.lastBarClose;
if(CopyBuffer(rmData.rsiHandle, 0, 0, 1, rsi) > 0)
rmData.lastBarRSI = rsi[0];
if(CopyBuffer(rmData.rsiReverseHandle, 0, 0, 1, rsiReverse) > 0)
rmData.lastBarRSIReverse = rsiReverse[0];
if(CopyBuffer(rmData.emaHandle, 0, 0, 1, ema) > 0)
rmData.lastBarEMA = ema[0];
if(CopyClose(rmData.symbol, RM_InpTimeframe, 0, 1, close) > 0)
rmData.lastBarClose = close[0];
if(RM_InpEnableRSIFollow)
CheckRSIFollowStrategy(rmData.symbol);
if(RM_InpEnableRSIReverse)
CheckRSIReverseStrategy(rmData.symbol);
if(RM_InpEnableEMACross)
CheckEMACrossStrategy(rmData.symbol);
CheckExitConditions(rmData.symbol);
}
//+------------------------------------------------------------------+
@@ -0,0 +1,488 @@
//+------------------------------------------------------------------+
//| RSIReversalAsianStrategy.mqh |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| RSI Reversal Asian Strategy Data Structure |
//+------------------------------------------------------------------+
struct RSIReversalAsianData {
string symbol;
bool isInitialized;
int rsiHandle;
CTrade trade;
bool isPositionOpen;
double positionOpenPrice;
datetime positionOpenTime;
ENUM_POSITION_TYPE lastPositionType;
bool sessionCloseAttempted;
// RSI crossover variables
double rsiCurrent;
double rsiPrevious;
double rsiPrevious2;
bool rsiCrossedOverbought;
bool rsiCrossedOversold;
bool rsiCrossedExitLevel;
// Strategy parameters
int RSIPeriod;
double OverboughtLevel;
double OversoldLevel;
int TakeProfitPips;
int StopLossPips;
double MaxLotSize;
int MaxSpread;
int MaxDuration;
bool UseStopLoss;
bool UseTakeProfit;
bool UseRSIExit;
double RSIExitLevel;
bool CloseOutsideSession;
ENUM_TIMEFRAMES TimeFrame;
int MagicNumber;
int Slippage;
double point;
};
// Session times (UTC)
const int AsianSessionStart = 0; // 00:00 UTC
const int AsianSessionEnd = 8; // 08:00 UTC
//+------------------------------------------------------------------+
//| Check if current time is in Asian session |
//+------------------------------------------------------------------+
bool IsAsianSession()
{
datetime currentTime = TimeCurrent();
MqlDateTime timeStruct;
TimeToStruct(currentTime, timeStruct);
return (timeStruct.hour >= AsianSessionStart && timeStruct.hour < AsianSessionEnd);
}
//+------------------------------------------------------------------+
//| Check if trading is allowed for symbol |
//+------------------------------------------------------------------+
bool IsTradingAllowed(RSIReversalAsianData& data)
{
// Do not require SYMBOL_TRADE_MODE_FULL: many symbols allow one side only (long/short).
const long tradeMode = SymbolInfoInteger(data.symbol, SYMBOL_TRADE_MODE);
if(tradeMode == SYMBOL_TRADE_MODE_DISABLED || tradeMode == SYMBOL_TRADE_MODE_CLOSEONLY)
return false;
if(AccountInfoDouble(ACCOUNT_MARGIN_FREE) <= 0)
return false;
return true;
}
//+------------------------------------------------------------------+
//| Check RSI crossover conditions |
//+------------------------------------------------------------------+
void CheckRSICrossover(RSIReversalAsianData& data)
{
// Reset crossover flags
data.rsiCrossedOverbought = false;
data.rsiCrossedOversold = false;
data.rsiCrossedExitLevel = false;
// Check for overbought crossover (RSI crosses above overbought level)
if(data.rsiPrevious < data.OverboughtLevel && data.rsiCurrent >= data.OverboughtLevel)
{
data.rsiCrossedOverbought = true;
}
// Check for oversold crossover (RSI crosses below oversold level)
if(data.rsiPrevious > data.OversoldLevel && data.rsiCurrent <= data.OversoldLevel)
{
data.rsiCrossedOversold = true;
}
// Check for exit level crossover
if(data.rsiPrevious < data.RSIExitLevel && data.rsiCurrent >= data.RSIExitLevel)
{
data.rsiCrossedExitLevel = true;
}
else if(data.rsiPrevious > data.RSIExitLevel && data.rsiCurrent <= data.RSIExitLevel)
{
data.rsiCrossedExitLevel = true;
}
}
//+------------------------------------------------------------------+
//| Close all trades for the symbol |
//+------------------------------------------------------------------+
bool CloseAllTrades(RSIReversalAsianData& data, string reason = "")
{
bool allClosed = true;
int totalPositions = PositionsTotal();
if(totalPositions == 0)
return true;
for(int i = totalPositions - 1; i >= 0; i--)
{
if(PositionGetSymbol(i) == data.symbol)
{
ulong ticket = PositionGetTicket(i);
if(ticket > 0 && PositionSelectByTicket(ticket))
{
if(PositionGetInteger(POSITION_MAGIC) == (ulong)data.MagicNumber)
{
// Try to close position with retry logic
int retryCount = 0;
bool positionClosed = false;
while(retryCount < 3 && !positionClosed)
{
if(data.trade.PositionClose(ticket))
{
data.isPositionOpen = false;
positionClosed = true;
}
else
{
int error = GetLastError();
// If error is 4756 (Trade disabled), wait longer before retry
if(error == 4756)
{
Sleep(5000); // Wait 5 seconds before retry
retryCount++;
}
else
{
// For other errors, break the loop
break;
}
}
}
if(!positionClosed)
{
allClosed = false;
}
}
}
}
}
return allClosed;
}
//+------------------------------------------------------------------+
//| Initialize RSI Reversal Asian Strategy |
//+------------------------------------------------------------------+
bool InitRSIReversalAsian(RSIReversalAsianData& data, string symbol,
int RSIPeriod, double OverboughtLevel, double OversoldLevel,
int TakeProfitPips, int StopLossPips, double MaxLotSize,
int MaxSpread, int MaxDuration, bool UseStopLoss,
bool UseTakeProfit, bool UseRSIExit, double RSIExitLevel,
bool CloseOutsideSession, ENUM_TIMEFRAMES TimeFrame,
int MagicNumber, int Slippage)
{
data.symbol = symbol;
data.isInitialized = false;
// Check if symbol exists
if(!SymbolSelect(symbol, true))
{
Print("RSIReversalAsian: Symbol '", symbol, "' not available in Market Watch. Please add it to Market Watch or check symbol name.");
return false;
}
// Wait a bit for symbol to be ready
Sleep(100);
// Get symbol point
data.point = SymbolInfoDouble(symbol, SYMBOL_POINT);
// Store parameters
data.RSIPeriod = RSIPeriod;
data.OverboughtLevel = OverboughtLevel;
data.OversoldLevel = OversoldLevel;
data.TakeProfitPips = TakeProfitPips;
data.StopLossPips = StopLossPips;
data.MaxLotSize = MaxLotSize;
data.MaxSpread = MaxSpread;
data.MaxDuration = MaxDuration;
data.UseStopLoss = UseStopLoss;
data.UseTakeProfit = UseTakeProfit;
data.UseRSIExit = UseRSIExit;
data.RSIExitLevel = RSIExitLevel;
data.CloseOutsideSession = CloseOutsideSession;
data.TimeFrame = TimeFrame;
data.MagicNumber = MagicNumber;
data.Slippage = Slippage;
// Initialize RSI indicator with retry logic (for insufficient history in backtesting)
data.rsiHandle = INVALID_HANDLE;
int retryCount = 0;
int maxRetries = 5;
while(retryCount < maxRetries && data.rsiHandle == INVALID_HANDLE)
{
data.rsiHandle = iRSI(symbol, TimeFrame, RSIPeriod, PRICE_CLOSE);
if(data.rsiHandle == INVALID_HANDLE)
{
int error = GetLastError();
// Error 4805 = insufficient history - wait longer and retry
if(error == 4805 && retryCount < maxRetries - 1)
{
Sleep(1000); // Wait 1 second for history to load
retryCount++;
continue;
}
Print("RSIReversalAsian: Error creating RSI indicator for '", symbol, "' - Error: ", error, " (", error == 4805 ? "Insufficient history data" : "Unknown", ")");
return false;
}
}
if(data.rsiHandle == INVALID_HANDLE)
{
Print("RSIReversalAsian: Failed to create RSI indicator for '", symbol, "' after ", maxRetries, " retries");
return false;
}
// Wait a bit for the indicator to be ready
Sleep(100);
// Initialize RSI values with retry logic
double rsi[];
ArraySetAsSeries(rsi, true);
retryCount = 0;
bool rsiInitialized = false;
while(retryCount < 10 && !rsiInitialized)
{
int copied = CopyBuffer(data.rsiHandle, 0, 0, 3, rsi);
if(copied >= 3)
{
data.rsiCurrent = rsi[0];
data.rsiPrevious = rsi[1];
data.rsiPrevious2 = rsi[2];
rsiInitialized = true;
}
else
{
retryCount++;
Sleep(100);
}
}
if(!rsiInitialized)
{
// Don't fail initialization, just set default values
data.rsiCurrent = 50.0;
data.rsiPrevious = 50.0;
data.rsiPrevious2 = 50.0;
}
// Set trade parameters
data.trade.SetExpertMagicNumber(MagicNumber);
data.trade.SetDeviationInPoints(Slippage);
data.trade.SetTypeFillingBySymbol(symbol);
// Initialize state
data.isPositionOpen = false;
data.positionOpenPrice = 0;
data.positionOpenTime = 0;
data.lastPositionType = POSITION_TYPE_BUY;
data.sessionCloseAttempted = false;
data.rsiCrossedOverbought = false;
data.rsiCrossedOversold = false;
data.rsiCrossedExitLevel = false;
data.isInitialized = true;
Print("RSIReversalAsian: Successfully initialized for symbol '", symbol, "'");
return true;
}
//+------------------------------------------------------------------+
//| Deinitialize RSI Reversal Asian Strategy |
//+------------------------------------------------------------------+
void DeinitRSIReversalAsian(RSIReversalAsianData& data)
{
if(data.rsiHandle != INVALID_HANDLE)
IndicatorRelease(data.rsiHandle);
}
//+------------------------------------------------------------------+
//| Process RSI Reversal Asian Strategy |
//+------------------------------------------------------------------+
void ProcessRSIReversalAsian(RSIReversalAsianData& data, double lotSize)
{
if(!data.isInitialized)
return;
// Check if trading is allowed
if(!IsTradingAllowed(data))
{
return;
}
// Check if we're in Asian session
if(!IsAsianSession())
{
// Close all positions if outside Asian session and CloseOutsideSession is true
if(data.CloseOutsideSession && !data.sessionCloseAttempted)
{
CloseAllTrades(data, "Outside Asian session");
data.sessionCloseAttempted = true;
}
return;
}
else
{
// Reset the session close attempt flag when we enter Asian session
data.sessionCloseAttempted = false;
}
// Get current spread
double spread = SymbolInfoDouble(data.symbol, SYMBOL_ASK) - SymbolInfoDouble(data.symbol, SYMBOL_BID);
int spreadInPips = (int)(spread / data.point);
// Check if spread is too high
if(spreadInPips > data.MaxSpread)
{
return;
}
// Get RSI values from bar data
double rsi[];
ArraySetAsSeries(rsi, true);
int copied = CopyBuffer(data.rsiHandle, 0, 0, 3, rsi);
if(copied < 3)
{
return;
}
// Update RSI values
data.rsiPrevious2 = data.rsiPrevious;
data.rsiPrevious = data.rsiCurrent;
data.rsiCurrent = rsi[0];
// Validate RSI values
if(data.rsiCurrent == 0 || data.rsiPrevious == 0)
{
return;
}
// Check for RSI crossovers
CheckRSICrossover(data);
// Get current prices
double currentBid = SymbolInfoDouble(data.symbol, SYMBOL_BID);
double currentAsk = SymbolInfoDouble(data.symbol, SYMBOL_ASK);
// Check for open position
bool hasOpenPosition = PositionExistsByMagic(data.symbol, (ulong)data.MagicNumber);
if(hasOpenPosition)
{
// Get position details
ulong ticket = GetPositionTicketByMagic(data.symbol, (ulong)data.MagicNumber);
if(ticket > 0 && PositionSelectByTicket(ticket))
{
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
datetime openTime = (datetime)PositionGetInteger(POSITION_TIME);
// Check for RSI exit if enabled
if(data.UseRSIExit && data.rsiCrossedExitLevel)
{
bool shouldExit = false;
// For long positions, exit when RSI crosses above exit level
if(posType == POSITION_TYPE_BUY && data.rsiCurrent >= data.RSIExitLevel && data.rsiPrevious < data.RSIExitLevel)
{
shouldExit = true;
}
// For short positions, exit when RSI crosses below exit level
else if(posType == POSITION_TYPE_SELL && data.rsiCurrent <= data.RSIExitLevel && data.rsiPrevious > data.RSIExitLevel)
{
shouldExit = true;
}
if(shouldExit)
{
CloseAllTrades(data, "RSI Exit Crossover");
return;
}
}
// Check for timeout
if(TimeCurrent() - openTime > data.MaxDuration * 3600)
{
CloseAllTrades(data, "Timeout");
return;
}
}
}
// If no position is open, look for entry signals based on RSI crossover
if(!hasOpenPosition)
{
// Place buy order if RSI crosses below oversold level (oversold crossover)
if(data.rsiCrossedOversold)
{
double sl = data.UseStopLoss ? currentBid - data.StopLossPips * data.point : 0;
double tp = data.UseTakeProfit ? currentBid + data.TakeProfitPips * data.point : 0;
if(data.UseStopLoss && sl >= currentBid)
return;
if(data.UseTakeProfit && tp <= currentBid)
return;
data.trade.SetDeviationInPoints(data.Slippage);
data.trade.SetTypeFillingBySymbol(data.symbol);
data.trade.SetExpertMagicNumber(data.MagicNumber);
double tradeLotSize = lotSize > 0 ? lotSize : data.MaxLotSize;
const double vol = United_NormalizeVolume(data.symbol, tradeLotSize);
if(vol <= 0.0)
return;
if(data.trade.Buy(vol, data.symbol, currentAsk, sl, tp, "RSI Oversold Crossover Buy"))
{
data.isPositionOpen = true;
data.positionOpenPrice = currentAsk;
data.positionOpenTime = TimeCurrent();
data.lastPositionType = POSITION_TYPE_BUY;
}
}
// Place sell order if RSI crosses above overbought level (overbought crossover)
else if(data.rsiCrossedOverbought)
{
double sl = data.UseStopLoss ? currentAsk + data.StopLossPips * data.point : 0;
double tp = data.UseTakeProfit ? currentAsk - data.TakeProfitPips * data.point : 0;
if(data.UseStopLoss && sl <= currentAsk)
return;
if(data.UseTakeProfit && tp >= currentAsk)
return;
data.trade.SetDeviationInPoints(data.Slippage);
data.trade.SetTypeFillingBySymbol(data.symbol);
data.trade.SetExpertMagicNumber(data.MagicNumber);
double tradeLotSize = lotSize > 0 ? lotSize : data.MaxLotSize;
const double vol = United_NormalizeVolume(data.symbol, tradeLotSize);
if(vol <= 0.0)
return;
if(data.trade.Sell(vol, data.symbol, currentBid, sl, tp, "RSI Overbought Crossover Sell"))
{
data.isPositionOpen = true;
data.positionOpenPrice = currentBid;
data.positionOpenTime = TimeCurrent();
data.lastPositionType = POSITION_TYPE_SELL;
}
}
}
}
@@ -0,0 +1,615 @@
//+------------------------------------------------------------------+
//| RSIScalpingStrategy.mqh |
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| RSI Scalping Strategy Data Structure |
//+------------------------------------------------------------------+
struct RSIScalpingData {
string symbol;
bool isInitialized;
CTrade trade;
int rsi_handle;
double rsi_buffer[];
double rsi_prev;
double rsi_current;
double rsi_two_bars_ago;
bool position_open;
ulong position_ticket;
ENUM_POSITION_TYPE current_position_type;
datetime last_bar_time;
bool rsi_against_position;
int bars_against_count;
};
void ClosePosition(RSIScalpingData& data, int MagicNumber);
double RS_ATRPriceOnTF(const string symbol, const ENUM_TIMEFRAMES tf, const int period)
{
if(period < 1)
return 0.0;
MqlRates rates[];
const int need = period + 2;
if(CopyRates(symbol, tf, 0, need, rates) < need)
return 0.0;
ArraySetAsSeries(rates, true);
double sum = 0.0;
for(int i = 1; i <= period; i++)
{
const double hl = rates[i].high - rates[i].low;
const double hc = MathAbs(rates[i].high - rates[i + 1].close);
const double lc = MathAbs(rates[i].low - rates[i + 1].close);
sum += MathMax(hl, MathMax(hc, lc));
}
return sum / (double)period;
}
int RS_CountReversalEscapeSigns(RSIScalpingData& data, const ENUM_TIMEFRAMES tf,
const ENUM_POSITION_TYPE ptype, const double atr,
const double adverseAtrMult, const double rsiVelocity,
const double bodyAtrMult)
{
if(atr <= 0.0)
return 0;
const double entry = PositionGetDouble(POSITION_PRICE_OPEN);
const double bid = SymbolInfoDouble(data.symbol, SYMBOL_BID);
const double ask = SymbolInfoDouble(data.symbol, SYMBOL_ASK);
int signs = 0;
if(ptype == POSITION_TYPE_BUY)
{
if(entry - bid >= adverseAtrMult * atr)
signs++;
if(data.rsi_prev - data.rsi_current >= rsiVelocity)
signs++;
}
else if(ptype == POSITION_TYPE_SELL)
{
if(ask - entry >= adverseAtrMult * atr)
signs++;
if(data.rsi_current - data.rsi_prev >= rsiVelocity)
signs++;
}
else
return 0;
MqlRates r[];
if(CopyRates(data.symbol, tf, 0, 4, r) >= 4)
{
ArraySetAsSeries(r, true);
const double body = MathAbs(r[1].close - r[1].open);
if(body >= bodyAtrMult * atr)
{
if(ptype == POSITION_TYPE_BUY && r[1].close < r[1].open)
signs++;
else if(ptype == POSITION_TYPE_SELL && r[1].close > r[1].open)
signs++;
}
if(ptype == POSITION_TYPE_BUY)
{
if(r[1].close < r[2].close && r[2].close < r[3].close)
signs++;
}
else
{
if(r[1].close > r[2].close && r[2].close > r[3].close)
signs++;
}
}
return signs;
}
void RS_TryReversalEscape(RSIScalpingData& data, const ENUM_TIMEFRAMES tf, const int MagicNumber,
const int atrPeriod, const double adverseAtrMult, const int signsRequired,
const double rsiVelocity, const double bodyAtrMult)
{
if(!PositionSelectByMagic(data.symbol, (ulong)MagicNumber))
return;
const ENUM_POSITION_TYPE ptype = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
const double atr = RS_ATRPriceOnTF(data.symbol, tf, atrPeriod);
if(atr <= 0.0)
return;
const int n = RS_CountReversalEscapeSigns(data, tf, ptype, atr, adverseAtrMult, rsiVelocity, bodyAtrMult);
if(n < signsRequired)
return;
ClosePosition(data, MagicNumber);
Print("RSIScalping: reversal escape symbol=", data.symbol, " signs=", n, " need=", signsRequired,
" ATR=", DoubleToString(atr, (int)SymbolInfoInteger(data.symbol, SYMBOL_DIGITS)));
}
void RS_ApplyTrailingStop(RSIScalpingData& data, const int MagicNumber,
const bool useTrailingStop,
const double trailingStopDistancePoints,
const double trailingActivationPoints)
{
if(!useTrailingStop || trailingStopDistancePoints <= 0.0)
return;
if(!PositionSelectByMagic(data.symbol, (ulong)MagicNumber))
return;
const double point = SymbolInfoDouble(data.symbol, SYMBOL_POINT);
if(point <= 0.0)
return;
const int digits = (int)SymbolInfoInteger(data.symbol, SYMBOL_DIGITS);
const double trail_dist = trailingStopDistancePoints * point;
const double activation_pts = (trailingActivationPoints > 0.0)
? trailingActivationPoints
: trailingStopDistancePoints;
const double activation = activation_pts * point;
const long stops_level = SymbolInfoInteger(data.symbol, SYMBOL_TRADE_STOPS_LEVEL);
const double min_dist = (double)stops_level * point;
const ENUM_POSITION_TYPE ptype = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
const double entry = PositionGetDouble(POSITION_PRICE_OPEN);
const double cur_sl = PositionGetDouble(POSITION_SL);
const double cur_tp = PositionGetDouble(POSITION_TP);
if(ptype == POSITION_TYPE_BUY)
{
const double bid = SymbolInfoDouble(data.symbol, SYMBOL_BID);
if(bid - entry <= activation)
return;
double new_sl = NormalizeDouble(bid - trail_dist, digits);
if(min_dist > 0.0 && bid - new_sl < min_dist)
new_sl = NormalizeDouble(bid - min_dist, digits);
if(new_sl >= bid || new_sl <= 0.0)
return;
if(cur_sl > 0.0 && new_sl <= cur_sl)
return;
ModifyPositionByMagic(data.trade, data.symbol, (ulong)MagicNumber, new_sl, cur_tp);
}
else if(ptype == POSITION_TYPE_SELL)
{
const double ask = SymbolInfoDouble(data.symbol, SYMBOL_ASK);
if(entry - ask <= activation)
return;
double new_sl = NormalizeDouble(ask + trail_dist, digits);
if(min_dist > 0.0 && new_sl - ask < min_dist)
new_sl = NormalizeDouble(ask + min_dist, digits);
if(new_sl <= ask || new_sl <= 0.0)
return;
if(cur_sl > 0.0 && new_sl >= cur_sl)
return;
ModifyPositionByMagic(data.trade, data.symbol, (ulong)MagicNumber, new_sl, cur_tp);
}
}
string ErrorDescription(int errorCode)
{
switch(errorCode)
{
case 4801: return "Symbol not found";
case 4802: return "Symbol not selected";
case 4803: return "Symbol not visible";
case 4804: return "Symbol not available";
case 4805: return "Cannot load indicator - insufficient history data";
default: return "Unknown error " + IntegerToString(errorCode);
}
}
bool InitRSIScalping(RSIScalpingData& data, string symbol, ENUM_TIMEFRAMES TimeFrame, int RSI_Period,
ENUM_APPLIED_PRICE RSI_Applied_Price, int MagicNumber, int Slippage)
{
data.symbol = symbol;
data.isInitialized = false;
// Check if symbol exists
if(!SymbolSelect(symbol, true))
{
Print("RSIScalping: Symbol '", symbol, "' not available in Market Watch. Please add it to Market Watch or check symbol name.");
return false; // Return false but don't fail entire EA
}
// Wait a bit for symbol to be ready
Sleep(100);
// Try to create RSI indicator with retry logic (for insufficient history in backtesting)
data.rsi_handle = INVALID_HANDLE;
int retryCount = 0;
int maxRetries = 5;
while(retryCount < maxRetries && data.rsi_handle == INVALID_HANDLE)
{
data.rsi_handle = iRSI(symbol, TimeFrame, RSI_Period, RSI_Applied_Price);
if(data.rsi_handle == INVALID_HANDLE)
{
int error = GetLastError();
// Error 4805 = insufficient history - wait longer and retry
if(error == 4805 && retryCount < maxRetries - 1)
{
Sleep(1000); // Wait 1 second for history to load
retryCount++;
continue;
}
Print("RSIScalping: Error creating RSI indicator for '", symbol, "' - Error: ", error, " (", ErrorDescription(error), ")");
return false; // Return false but don't fail entire EA
}
}
if(data.rsi_handle == INVALID_HANDLE)
{
Print("RSIScalping: Failed to create RSI indicator for '", symbol, "' after ", maxRetries, " retries");
return false;
}
data.trade.SetExpertMagicNumber(MagicNumber);
data.trade.SetDeviationInPoints(Slippage);
data.trade.SetTypeFilling(ORDER_FILLING_FOK);
ArraySetAsSeries(data.rsi_buffer, true);
data.position_open = false;
data.position_ticket = 0;
data.rsi_against_position = false;
data.bars_against_count = 0;
data.isInitialized = true;
Print("RSIScalping: Successfully initialized for symbol '", symbol, "'");
return true;
}
void DeinitRSIScalping(RSIScalpingData& data)
{
if(data.rsi_handle != INVALID_HANDLE)
IndicatorRelease(data.rsi_handle);
}
bool UpdateRSI(RSIScalpingData& data)
{
if(CopyBuffer(data.rsi_handle, 0, 0, 3, data.rsi_buffer) < 3)
return false;
data.rsi_current = data.rsi_buffer[0];
data.rsi_prev = data.rsi_buffer[1];
data.rsi_two_bars_ago = data.rsi_buffer[2];
return true;
}
void CheckExistingPosition(RSIScalpingData& data, ENUM_TIMEFRAMES TimeFrame, int MagicNumber,
double RSI_Oversold, double RSI_Overbought, double RSI_Target_Buy,
double RSI_Target_Sell, int BarsToWait)
{
// Always check if position exists, even if tracking says it doesn't
bool positionExists = PositionExistsByMagic(data.symbol, MagicNumber);
if(!positionExists && data.position_open)
{
// Position was closed externally, reset tracking
data.position_open = false;
data.position_ticket = 0;
data.rsi_against_position = false;
data.bars_against_count = 0;
return;
}
if(!positionExists)
return;
// Update tracking if we have a position but tracking was lost
if(!data.position_open && positionExists)
{
ulong ticket = GetPositionTicketByMagic(data.symbol, MagicNumber);
if(ticket > 0 && PositionSelectByTicketSymbolAndMagic(ticket, data.symbol, MagicNumber))
{
data.position_ticket = ticket;
data.position_open = true;
data.current_position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
}
}
// Verify our tracked position still exists
if(data.position_open && data.position_ticket > 0)
{
if(!PositionSelectByTicketSymbolAndMagic(data.position_ticket, data.symbol, MagicNumber))
{
// Try to find the position again
ulong ticket = GetPositionTicketByMagic(data.symbol, MagicNumber);
if(ticket > 0 && PositionSelectByTicketSymbolAndMagic(ticket, data.symbol, MagicNumber))
{
data.position_ticket = ticket;
data.current_position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
}
else
{
// Position doesn't exist, reset tracking
data.position_open = false;
data.position_ticket = 0;
data.rsi_against_position = false;
data.bars_against_count = 0;
return;
}
}
else
{
// Update position type in case it changed (shouldn't happen, but be safe)
data.current_position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
}
}
if(data.current_position_type == POSITION_TYPE_BUY)
{
if(data.rsi_current < RSI_Oversold)
{
if(!data.rsi_against_position)
{
data.rsi_against_position = true;
data.bars_against_count = 1;
}
else
{
data.bars_against_count++;
}
if(data.bars_against_count >= BarsToWait)
{
ClosePosition(data, MagicNumber);
return;
}
}
else
{
if(data.rsi_against_position)
{
data.rsi_against_position = false;
data.bars_against_count = 0;
}
if(data.rsi_current >= RSI_Target_Buy)
{
ClosePosition(data, MagicNumber);
}
}
}
else if(data.current_position_type == POSITION_TYPE_SELL)
{
if(data.rsi_current > RSI_Overbought)
{
if(!data.rsi_against_position)
{
data.rsi_against_position = true;
data.bars_against_count = 1;
}
else
{
data.bars_against_count++;
}
if(data.bars_against_count >= BarsToWait)
{
ClosePosition(data, MagicNumber);
return;
}
}
else
{
if(data.rsi_against_position)
{
data.rsi_against_position = false;
data.bars_against_count = 0;
}
if(data.rsi_current <= RSI_Target_Sell)
{
ClosePosition(data, MagicNumber);
}
}
}
}
void CheckEntrySignals(RSIScalpingData& data, ENUM_TIMEFRAMES TimeFrame, int MagicNumber,
double RSI_Oversold, double RSI_Overbought, double LotSize)
{
if(data.rsi_two_bars_ago <= RSI_Oversold && data.rsi_prev > RSI_Oversold)
{
OpenBuyPosition(data, MagicNumber, LotSize);
}
if(data.rsi_two_bars_ago >= RSI_Overbought && data.rsi_prev < RSI_Overbought)
{
OpenSellPosition(data, MagicNumber, LotSize);
}
}
//+------------------------------------------------------------------+
//| Normalize Lot Size According to Symbol Properties |
//+------------------------------------------------------------------+
double NormalizeLotSize(string symbol, double lotSize)
{
return United_NormalizeVolume(symbol, lotSize);
}
void OpenBuyPosition(RSIScalpingData& data, int MagicNumber, double LotSize)
{
if(PositionExistsByMagic(data.symbol, MagicNumber))
return;
// Normalize lot size according to symbol properties
double normalizedLot = NormalizeLotSize(data.symbol, LotSize);
double ask = SymbolInfoDouble(data.symbol, SYMBOL_ASK);
if(data.trade.Buy(normalizedLot, data.symbol, ask, 0, 0, "RSI Scalping Buy"))
{
ulong new_ticket = data.trade.ResultOrder();
if(new_ticket > 0)
{
if(PositionSelectByTicketSymbolAndMagic(new_ticket, data.symbol, MagicNumber))
{
data.position_ticket = new_ticket;
data.position_open = true;
data.current_position_type = POSITION_TYPE_BUY;
}
}
}
}
void OpenSellPosition(RSIScalpingData& data, int MagicNumber, double LotSize)
{
if(PositionExistsByMagic(data.symbol, MagicNumber))
return;
// Normalize lot size according to symbol properties
double normalizedLot = NormalizeLotSize(data.symbol, LotSize);
double bid = SymbolInfoDouble(data.symbol, SYMBOL_BID);
if(data.trade.Sell(normalizedLot, data.symbol, bid, 0, 0, "RSI Scalping Sell"))
{
ulong new_ticket = data.trade.ResultOrder();
if(new_ticket > 0)
{
if(PositionSelectByTicketSymbolAndMagic(new_ticket, data.symbol, MagicNumber))
{
data.position_ticket = new_ticket;
data.position_open = true;
data.current_position_type = POSITION_TYPE_SELL;
}
}
}
}
void ClosePosition(RSIScalpingData& data, int MagicNumber)
{
// First verify position still exists
if(!PositionExistsByMagic(data.symbol, MagicNumber))
{
// Position doesn't exist, reset tracking
data.position_open = false;
data.position_ticket = 0;
data.rsi_against_position = false;
data.bars_against_count = 0;
return;
}
// Try to close by ticket first (more reliable)
bool closed = false;
if(data.position_ticket > 0)
{
if(PositionSelectByTicket(data.position_ticket))
{
// Verify it's our position
if(PositionGetString(POSITION_SYMBOL) == data.symbol &&
PositionGetInteger(POSITION_MAGIC) == MagicNumber)
{
closed = data.trade.PositionClose(data.position_ticket);
if(!closed)
{
Print("RSIScalping: Failed to close position by ticket ", data.position_ticket,
" - Error: ", data.trade.ResultRetcode(), " (", data.trade.ResultRetcodeDescription(), ")");
}
}
}
}
// If ticket method failed, try magic number method
if(!closed)
{
closed = ClosePositionByMagic(data.trade, data.symbol, MagicNumber);
if(!closed)
{
Print("RSIScalping: Failed to close position by magic number for '", data.symbol,
"' - Error: ", data.trade.ResultRetcode(), " (", data.trade.ResultRetcodeDescription(), ")");
}
}
// Verify position is actually closed
if(closed)
{
// Wait a moment and verify
Sleep(50);
if(!PositionExistsByMagic(data.symbol, MagicNumber))
{
data.position_open = false;
data.position_ticket = 0;
data.rsi_against_position = false;
data.bars_against_count = 0;
Print("RSIScalping: Position successfully closed for '", data.symbol, "'");
}
else
{
Print("RSIScalping: Warning - Close returned success but position still exists for '", data.symbol, "'");
// Try one more time
Sleep(100);
if(PositionExistsByMagic(data.symbol, MagicNumber))
{
ClosePositionByMagic(data.trade, data.symbol, MagicNumber);
}
// Reset tracking anyway to prevent getting stuck
data.position_open = false;
data.position_ticket = 0;
data.rsi_against_position = false;
data.bars_against_count = 0;
}
}
else
{
// Close failed, but reset tracking to prevent getting stuck
// The position might have been closed externally
data.position_open = false;
data.position_ticket = 0;
data.rsi_against_position = false;
data.bars_against_count = 0;
}
}
void ProcessRSIScalping(RSIScalpingData& data, string symbol, ENUM_TIMEFRAMES TimeFrame, int RSI_Period,
ENUM_APPLIED_PRICE RSI_Applied_Price, double RSI_Overbought,
double RSI_Oversold, double RSI_Target_Buy, double RSI_Target_Sell,
int BarsToWait, double LotSize, int MagicNumber,
bool UseReversalEscape, int ReversalATRPeriod, double ReversalAdverseAtrMult,
int ReversalSignsRequired, double ReversalRsiVelocity, double ReversalBodyAtrMult,
bool UseTrailingStop, double TrailingStopDistancePoints, double TrailingActivationPoints)
{
// Skip if not initialized (symbol not available)
if(!data.isInitialized)
return;
data.symbol = symbol; // Update symbol in case it changed
if(Bars(data.symbol, TimeFrame) < RSI_Period + 2)
return;
const datetime current_bar_time = iTime(data.symbol, TimeFrame, 0);
const bool new_bar = (current_bar_time != data.last_bar_time);
const bool in_pos = data.position_open || PositionExistsByMagic(data.symbol, MagicNumber);
if(!in_pos && !new_bar)
return;
if(!UpdateRSI(data))
return;
if(in_pos && UseReversalEscape)
RS_TryReversalEscape(data, TimeFrame, MagicNumber, ReversalATRPeriod, ReversalAdverseAtrMult,
ReversalSignsRequired, ReversalRsiVelocity, ReversalBodyAtrMult);
if(in_pos)
RS_ApplyTrailingStop(data, MagicNumber, UseTrailingStop,
TrailingStopDistancePoints, TrailingActivationPoints);
if(!new_bar)
return;
data.last_bar_time = current_bar_time;
CheckExistingPosition(data, TimeFrame, MagicNumber, RSI_Oversold, RSI_Overbought,
RSI_Target_Buy, RSI_Target_Sell, BarsToWait);
if(!data.position_open && !PositionExistsByMagic(data.symbol, MagicNumber))
{
CheckEntrySignals(data, TimeFrame, MagicNumber, RSI_Oversold, RSI_Overbought, LotSize);
}
}
//+------------------------------------------------------------------+
@@ -0,0 +1,336 @@
//+------------------------------------------------------------------+
//| RSISecretSauceStrategy.mqh |
//| Cluster-0 orchestrator: RSI leave extreme then peak/bottom entry |
//+------------------------------------------------------------------+
#ifndef RSI_SECRET_SAUCE_STRATEGY_MQH
#define RSI_SECRET_SAUCE_STRATEGY_MQH
#include <Trade/Trade.mqh>
#include <Trade/PositionInfo.mqh>
struct RSISecretSauceOrcData
{
string actualSymbol;
bool isInitialized;
CTrade trade;
CPositionInfo positionInfo;
int rsiHandle;
int atrHandle;
double rsiBuffer[];
double atrBuffer[];
double highBuffer[];
double lowBuffer[];
bool rsiWasOverbought;
bool rsiWasOversold;
bool rsiBackInRange;
datetime lastRSIExitTime;
datetime lastRSIReentryTime;
datetime lastTradeTime;
datetime lastBarTime;
};
bool RSS_UpdateIndicators(RSISecretSauceOrcData &d)
{
int rsiBarsNeeded = RSS_RSILookback + 5;
if(CopyBuffer(d.rsiHandle, 0, 0, rsiBarsNeeded, d.rsiBuffer) < rsiBarsNeeded)
return false;
if(CopyBuffer(d.atrHandle, 0, 0, 2, d.atrBuffer) < 2)
return false;
if(CopyHigh(d.actualSymbol, RSS_Timeframe, 0, RSS_SwingLookback + 5, d.highBuffer) < RSS_SwingLookback + 5)
return false;
if(CopyLow(d.actualSymbol, RSS_Timeframe, 0, RSS_SwingLookback + 5, d.lowBuffer) < RSS_SwingLookback + 5)
return false;
return true;
}
void RSS_UpdateRSIState(RSISecretSauceOrcData &d)
{
double rsiCurrent = d.rsiBuffer[0];
double rsiPrev = d.rsiBuffer[1];
if(rsiPrev >= RSS_RSIOverbought && rsiCurrent < RSS_RSIOverbought)
{
d.rsiWasOverbought = true;
d.rsiBackInRange = true;
d.lastRSIExitTime = TimeCurrent();
d.lastRSIReentryTime = TimeCurrent();
}
if(rsiPrev <= RSS_RSIOversold && rsiCurrent > RSS_RSIOversold)
{
d.rsiWasOversold = true;
d.rsiBackInRange = true;
d.lastRSIExitTime = TimeCurrent();
d.lastRSIReentryTime = TimeCurrent();
}
if(rsiCurrent >= RSS_RSIOverbought)
{
d.rsiWasOverbought = false;
d.rsiBackInRange = false;
}
if(rsiCurrent <= RSS_RSIOversold)
{
d.rsiWasOversold = false;
d.rsiBackInRange = false;
}
}
bool RSS_IsRSIPeak(RSISecretSauceOrcData &d)
{
if(ArraySize(d.rsiBuffer) < RSS_PeakBars + 2)
return false;
double currentRSI = d.rsiBuffer[0];
bool isPeak = true;
for(int i = 1; i <= RSS_PeakBars; i++)
{
if(d.rsiBuffer[i] >= currentRSI)
{
isPeak = false;
break;
}
}
if(d.rsiBuffer[1] >= currentRSI)
isPeak = false;
return isPeak;
}
bool RSS_IsRSIBottom(RSISecretSauceOrcData &d)
{
if(ArraySize(d.rsiBuffer) < RSS_PeakBars + 2)
return false;
double currentRSI = d.rsiBuffer[0];
bool isBottom = true;
for(int i = 1; i <= RSS_PeakBars; i++)
{
if(d.rsiBuffer[i] <= currentRSI)
{
isBottom = false;
break;
}
}
if(d.rsiBuffer[1] <= currentRSI)
isBottom = false;
return isBottom;
}
double RSS_GetSwingStopLoss(RSISecretSauceOrcData &d, double currentPrice, ENUM_POSITION_TYPE type)
{
if(type == POSITION_TYPE_BUY)
{
double lowestLow = d.lowBuffer[0];
for(int i = 1; i < RSS_SwingLookback && i < ArraySize(d.lowBuffer); i++)
{
if(d.lowBuffer[i] < lowestLow)
lowestLow = d.lowBuffer[i];
}
return lowestLow;
}
double highestHigh = d.highBuffer[0];
for(int i = 1; i < RSS_SwingLookback && i < ArraySize(d.highBuffer); i++)
{
if(d.highBuffer[i] > highestHigh)
highestHigh = d.highBuffer[i];
}
return highestHigh;
}
bool RSS_CalculateStops(RSISecretSauceOrcData &d, double price, ENUM_POSITION_TYPE type, double &sl, double &tp)
{
double atrValue = d.atrBuffer[0];
if(atrValue <= 0)
atrValue = price * 0.01;
double slDistance = atrValue * RSS_StopLossATR;
double tpDistance = atrValue * RSS_TakeProfitATR;
int digits = (int)SymbolInfoInteger(d.actualSymbol, SYMBOL_DIGITS);
double point = SymbolInfoDouble(d.actualSymbol, SYMBOL_POINT);
int stopsLevel = (int)SymbolInfoInteger(d.actualSymbol, SYMBOL_TRADE_STOPS_LEVEL);
double minStopDistance = MathMax(stopsLevel * point, point * 10);
if(RSS_UseSwingStopLoss)
{
double swingStop = RSS_GetSwingStopLoss(d, price, type);
if(swingStop > 0)
{
if(type == POSITION_TYPE_BUY)
{
if(swingStop < price && (price - swingStop) > minStopDistance)
slDistance = price - swingStop;
}
else
{
if(swingStop > price && (swingStop - price) > minStopDistance)
slDistance = swingStop - price;
}
}
}
if(slDistance < minStopDistance)
slDistance = minStopDistance;
if(tpDistance < minStopDistance)
tpDistance = minStopDistance;
if(type == POSITION_TYPE_BUY)
{
sl = NormalizeDouble(price - slDistance, digits);
tp = NormalizeDouble(price + tpDistance, digits);
}
else
{
sl = NormalizeDouble(price + slDistance, digits);
tp = NormalizeDouble(price - tpDistance, digits);
}
return true;
}
bool RSS_CanOpenNewPosition(RSISecretSauceOrcData &d)
{
int positionCount = 0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
if(d.positionInfo.SelectByIndex(i))
{
if(d.positionInfo.Symbol() == d.actualSymbol && d.positionInfo.Magic() == RSS_MagicNumber)
positionCount++;
}
}
if(positionCount >= RSS_MaxPositions)
return false;
if(d.lastTradeTime > 0)
{
int barsSince = Bars(d.actualSymbol, RSS_Timeframe, d.lastTradeTime, TimeCurrent());
if(barsSince < RSS_MinBarsBetweenTrades)
return false;
}
return true;
}
void RSS_OpenPosition(RSISecretSauceOrcData &d, ENUM_POSITION_TYPE type, const double lotSize)
{
double price = (type == POSITION_TYPE_BUY) ?
SymbolInfoDouble(d.actualSymbol, SYMBOL_ASK) :
SymbolInfoDouble(d.actualSymbol, SYMBOL_BID);
if(price <= 0)
return;
double sl = 0.0, tp = 0.0;
if(!RSS_CalculateStops(d, price, type, sl, tp))
return;
string comment = "RSI_Secret_" + (type == POSITION_TYPE_BUY ? "LONG" : "SHORT");
bool result = false;
if(type == POSITION_TYPE_BUY)
result = d.trade.Buy(lotSize, d.actualSymbol, 0, sl, tp, comment);
else
result = d.trade.Sell(lotSize, d.actualSymbol, 0, sl, tp, comment);
if(result)
{
d.lastTradeTime = TimeCurrent();
if(type == POSITION_TYPE_BUY)
d.rsiWasOverbought = false;
else
d.rsiWasOversold = false;
d.rsiBackInRange = false;
}
}
void RSS_CheckEntrySignals(RSISecretSauceOrcData &d, const double lotSize)
{
if(d.rsiWasOverbought && d.rsiBackInRange)
{
if(d.rsiBuffer[0] < RSS_RSIOverbought && RSS_IsRSIPeak(d))
RSS_OpenPosition(d, POSITION_TYPE_BUY, lotSize);
}
if(d.rsiWasOversold && d.rsiBackInRange)
{
if(d.rsiBuffer[0] > RSS_RSIOversold && RSS_IsRSIBottom(d))
RSS_OpenPosition(d, POSITION_TYPE_SELL, lotSize);
}
}
bool InitRSISecretSauce(RSISecretSauceOrcData &d, const string symbol)
{
d.isInitialized = false;
d.rsiHandle = INVALID_HANDLE;
d.atrHandle = INVALID_HANDLE;
d.rsiWasOverbought = false;
d.rsiWasOversold = false;
d.rsiBackInRange = false;
d.lastRSIExitTime = 0;
d.lastRSIReentryTime = 0;
d.lastTradeTime = 0;
d.lastBarTime = 0;
d.actualSymbol = symbol;
StringTrimLeft(d.actualSymbol);
StringTrimRight(d.actualSymbol);
if(StringLen(d.actualSymbol) == 0)
d.actualSymbol = _Symbol;
if(!SymbolSelect(d.actualSymbol, true))
{
Print("RSISecretSauce: symbol not available '", d.actualSymbol, "'");
return false;
}
d.rsiHandle = iRSI(d.actualSymbol, RSS_Timeframe, RSS_RSIPeriod, PRICE_CLOSE);
d.atrHandle = iATR(d.actualSymbol, RSS_Timeframe, RSS_ATRPeriod);
if(d.rsiHandle == INVALID_HANDLE || d.atrHandle == INVALID_HANDLE)
return false;
ArraySetAsSeries(d.rsiBuffer, true);
ArraySetAsSeries(d.atrBuffer, true);
ArraySetAsSeries(d.highBuffer, true);
ArraySetAsSeries(d.lowBuffer, true);
d.trade.SetExpertMagicNumber(RSS_MagicNumber);
d.trade.SetDeviationInPoints(RSS_Slippage);
d.trade.SetTypeFilling(ORDER_FILLING_FOK);
d.isInitialized = true;
return true;
}
void DeinitRSISecretSauce(RSISecretSauceOrcData &d)
{
if(d.rsiHandle != INVALID_HANDLE)
IndicatorRelease(d.rsiHandle);
if(d.atrHandle != INVALID_HANDLE)
IndicatorRelease(d.atrHandle);
d.rsiHandle = INVALID_HANDLE;
d.atrHandle = INVALID_HANDLE;
d.isInitialized = false;
}
void ProcessRSISecretSauce(RSISecretSauceOrcData &d, const double lotSize)
{
if(!d.isInitialized)
return;
int requiredBars = MathMax(RSS_RSILookback, RSS_SwingLookback) + 10;
if(Bars(d.actualSymbol, RSS_Timeframe) < requiredBars)
return;
datetime currentBarTime = iTime(d.actualSymbol, RSS_Timeframe, 0);
if(currentBarTime == d.lastBarTime)
return;
d.lastBarTime = currentBarTime;
if(!RSS_UpdateIndicators(d))
return;
RSS_UpdateRSIState(d);
if(RSS_CanOpenNewPosition(d))
RSS_CheckEntrySignals(d, lotSize);
}
#endif
@@ -0,0 +1,318 @@
//+------------------------------------------------------------------+
//| SimpleTrendlineStrategy.mqh |
//+------------------------------------------------------------------+
#ifndef SIMPLE_TRENDLINE_STRATEGY_MQH
#define SIMPLE_TRENDLINE_STRATEGY_MQH
struct SimpleTrendlineModel
{
datetime t1;
datetime t2;
datetime t3;
double a;
double b;
bool valid;
};
struct SimpleTrendlineData
{
string symbol;
bool isInitialized;
CTrade trade;
ENUM_TIMEFRAMES signalTF;
ENUM_TIMEFRAMES higherTF;
int maPeriod;
ENUM_MA_METHOD maMethod;
ENUM_APPLIED_PRICE appliedPrice;
int htfBarsToScan;
double touchTolerancePoints;
double breakBufferPoints;
ulong magic;
bool drawTrendline;
int maHandle;
datetime lastSignalBarTime;
string lineName;
};
double ST_NormalizeVolume(const string sym, double vol)
{
double minLot = SymbolInfoDouble(sym, SYMBOL_VOLUME_MIN);
double maxLot = SymbolInfoDouble(sym, SYMBOL_VOLUME_MAX);
double step = SymbolInfoDouble(sym, SYMBOL_VOLUME_STEP);
if(step > 0.0)
vol = MathFloor(vol / step) * step;
if(vol < minLot)
vol = minLot;
if(vol > maxLot)
vol = maxLot;
return vol;
}
bool ST_GetPosition(const string sym, const ulong magic, ENUM_POSITION_TYPE &type, double &volume)
{
if(!PositionSelectByMagic(sym, magic))
return false;
type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
volume = PositionGetDouble(POSITION_VOLUME);
return true;
}
int ST_FindRecentCrossPoints(SimpleTrendlineData &d, datetime &times[], double &prices[])
{
ArrayResize(times, 0);
ArrayResize(prices, 0);
if(d.maHandle == INVALID_HANDLE)
return 0;
int needBars = MathMax(d.htfBarsToScan, d.maPeriod + 20);
MqlRates rates[];
double maBuf[];
ArraySetAsSeries(rates, true);
ArraySetAsSeries(maBuf, true);
int copiedRates = CopyRates(d.symbol, d.higherTF, 0, needBars, rates);
int copiedMa = CopyBuffer(d.maHandle, 0, 0, needBars, maBuf);
if(copiedRates <= 5 || copiedMa <= 5)
return 0;
int bars = MathMin(copiedRates, copiedMa);
for(int i = 2; i < bars - 1; i++)
{
double d0 = rates[i].close - maBuf[i];
double d1 = rates[i + 1].close - maBuf[i + 1];
if(d0 == 0.0 || d1 == 0.0 || (d0 * d1 < 0.0))
{
int n = ArraySize(times);
ArrayResize(times, n + 1);
ArrayResize(prices, n + 1);
times[n] = rates[i].time;
prices[n] = rates[i].close;
if(ArraySize(times) >= 3)
break;
}
}
return ArraySize(times);
}
bool ST_BuildTrendline(SimpleTrendlineData &d, SimpleTrendlineModel &m)
{
m.valid = false;
datetime ts[];
double ps[];
if(ST_FindRecentCrossPoints(d, ts, ps) < 3)
return false;
datetime tOld[3];
double pOld[3];
for(int i = 0; i < 3; i++)
{
tOld[i] = ts[2 - i];
pOld[i] = ps[2 - i];
}
long t0 = (long)tOld[0];
double x1 = 0.0;
double x2 = (double)((long)tOld[1] - t0);
double x3 = (double)((long)tOld[2] - t0);
double y1 = pOld[0];
double y2 = pOld[1];
double y3 = pOld[2];
double sx = x1 + x2 + x3;
double sy = y1 + y2 + y3;
double sxx = x1 * x1 + x2 * x2 + x3 * x3;
double sxy = x1 * y1 + x2 * y2 + x3 * y3;
double den = 3.0 * sxx - sx * sx;
if(MathAbs(den) < 1e-10)
return false;
m.a = (3.0 * sxy - sx * sy) / den;
m.b = (sy - m.a * sx) / 3.0;
m.t1 = tOld[0];
m.t2 = tOld[1];
m.t3 = tOld[2];
m.valid = true;
return true;
}
double ST_LinePriceAt(const SimpleTrendlineModel &m, const datetime t)
{
if(!m.valid)
return 0.0;
double x = (double)((long)t - (long)m.t1);
return m.a * x + m.b;
}
void ST_DrawTrendline(SimpleTrendlineData &d, const SimpleTrendlineModel &m)
{
if(!d.drawTrendline || !m.valid || d.symbol != _Symbol)
return;
datetime tStart = m.t1;
datetime tEnd = iTime(d.symbol, d.signalTF, 0);
if(tEnd <= tStart)
tEnd = m.t3 + PeriodSeconds(d.signalTF) * 20;
double pStart = ST_LinePriceAt(m, tStart);
double pEnd = ST_LinePriceAt(m, tEnd);
if(ObjectFind(0, d.lineName) < 0)
ObjectCreate(0, d.lineName, OBJ_TREND, 0, tStart, pStart, tEnd, pEnd);
else
{
ObjectMove(0, d.lineName, 0, tStart, pStart);
ObjectMove(0, d.lineName, 1, tEnd, pEnd);
}
ObjectSetInteger(0, d.lineName, OBJPROP_RAY_RIGHT, true);
ObjectSetInteger(0, d.lineName, OBJPROP_COLOR, clrGold);
ObjectSetInteger(0, d.lineName, OBJPROP_WIDTH, 2);
}
void ST_TryExitOnBreak(SimpleTrendlineData &d, const SimpleTrendlineModel &m)
{
ENUM_POSITION_TYPE posType;
double vol;
if(!ST_GetPosition(d.symbol, d.magic, posType, vol))
return;
double close1 = iClose(d.symbol, d.signalTF, 1);
datetime t1 = iTime(d.symbol, d.signalTF, 1);
double line1 = ST_LinePriceAt(m, t1);
double buf = d.breakBufferPoints * SymbolInfoDouble(d.symbol, SYMBOL_POINT);
bool closePos = false;
if(posType == POSITION_TYPE_BUY && close1 < (line1 - buf))
closePos = true;
if(posType == POSITION_TYPE_SELL && close1 > (line1 + buf))
closePos = true;
if(closePos)
ClosePositionByMagic(d.trade, d.symbol, d.magic);
}
void ST_TryPullbackEntry(SimpleTrendlineData &d, const SimpleTrendlineModel &m, const double lots)
{
if(PositionExistsByMagic(d.symbol, d.magic))
return;
MqlRates b1[], b2[];
ArraySetAsSeries(b1, true);
ArraySetAsSeries(b2, true);
if(CopyRates(d.symbol, d.signalTF, 1, 1, b1) != 1)
return;
if(CopyRates(d.symbol, d.signalTF, 2, 1, b2) != 1)
return;
if(ArraySize(b1) < 1 || ArraySize(b2) < 1)
return;
double line1 = ST_LinePriceAt(m, b1[0].time);
double tol = d.touchTolerancePoints * SymbolInfoDouble(d.symbol, SYMBOL_POINT);
bool upTrend = (m.a > 0.0);
bool downTrend = (m.a < 0.0);
double vol = ST_NormalizeVolume(d.symbol, lots);
if(upTrend)
{
bool touched = (b1[0].low <= (line1 + tol));
bool reclaim = (b1[0].close > line1);
bool bullish = (b1[0].close > b1[0].open);
bool stillHealthy = (b2[0].close >= ST_LinePriceAt(m, b2[0].time) - tol);
if(touched && reclaim && bullish && stillHealthy)
{
if(!d.trade.Buy(vol, d.symbol, 0.0, 0.0, 0.0, "SimpleTrendline BUY"))
Print("SimpleTrendline BUY failed [", d.symbol, "] retcode=", d.trade.ResultRetcode(), " ", d.trade.ResultRetcodeDescription());
}
}
else if(downTrend)
{
bool touched = (b1[0].high >= (line1 - tol));
bool reject = (b1[0].close < line1);
bool bearish = (b1[0].close < b1[0].open);
bool stillWeak = (b2[0].close <= ST_LinePriceAt(m, b2[0].time) + tol);
if(touched && reject && bearish && stillWeak)
{
if(!d.trade.Sell(vol, d.symbol, 0.0, 0.0, 0.0, "SimpleTrendline SELL"))
Print("SimpleTrendline SELL failed [", d.symbol, "] retcode=", d.trade.ResultRetcode(), " ", d.trade.ResultRetcodeDescription());
}
}
}
bool InitSimpleTrendline(SimpleTrendlineData &d,
const string symbol,
const ENUM_TIMEFRAMES signalTF,
const ENUM_TIMEFRAMES higherTF,
const int maPeriod,
const ENUM_MA_METHOD maMethod,
const ENUM_APPLIED_PRICE appliedPrice,
const int htfBarsToScan,
const double touchTolerancePoints,
const double breakBufferPoints,
const ulong magic,
const bool drawTrendline)
{
d.isInitialized = false;
d.symbol = symbol;
StringTrimLeft(d.symbol);
StringTrimRight(d.symbol);
if(StringLen(d.symbol) == 0)
d.symbol = _Symbol;
if(!SymbolSelect(d.symbol, true))
return false;
d.signalTF = signalTF;
d.higherTF = higherTF;
d.maPeriod = maPeriod;
d.maMethod = maMethod;
d.appliedPrice = appliedPrice;
d.htfBarsToScan = htfBarsToScan;
d.touchTolerancePoints = touchTolerancePoints;
d.breakBufferPoints = breakBufferPoints;
d.magic = magic;
d.drawTrendline = drawTrendline;
d.lastSignalBarTime = 0;
d.lineName = "SimpleTrendline_" + d.symbol + "_" + IntegerToString((int)d.magic);
d.trade.SetExpertMagicNumber((long)d.magic);
d.trade.SetTypeFillingBySymbol(d.symbol);
d.trade.SetDeviationInPoints(20);
d.maHandle = iMA(d.symbol, d.higherTF, d.maPeriod, 0, d.maMethod, d.appliedPrice);
if(d.maHandle == INVALID_HANDLE)
return false;
d.isInitialized = true;
return true;
}
void DeinitSimpleTrendline(SimpleTrendlineData &d)
{
if(d.maHandle != INVALID_HANDLE)
IndicatorRelease(d.maHandle);
d.maHandle = INVALID_HANDLE;
if(ObjectFind(0, d.lineName) >= 0)
ObjectDelete(0, d.lineName);
d.isInitialized = false;
}
void ProcessSimpleTrendline(SimpleTrendlineData &d, const double lots)
{
if(!d.isInitialized)
return;
datetime bar0 = iTime(d.symbol, d.signalTF, 0);
if(bar0 == 0 || bar0 == d.lastSignalBarTime)
return;
d.lastSignalBarTime = bar0;
SimpleTrendlineModel m;
if(!ST_BuildTrendline(d, m))
return;
ST_DrawTrendline(d, m);
ST_TryExitOnBreak(d, m);
ST_TryPullbackEntry(d, m, lots);
}
#endif // SIMPLE_TRENDLINE_STRATEGY_MQH
@@ -0,0 +1,509 @@
//+------------------------------------------------------------------+
//| SuperEMAStrategy.mqh — EMA + CCI + MACD (United EA module) |
//+------------------------------------------------------------------+
#ifndef SUPER_EMA_STRATEGY_MQH
#define SUPER_EMA_STRATEGY_MQH
#include <Trade/Trade.mqh>
enum ENUM_SE_ENTRY_STYLE
{
SE_ENTRY_CCIZERO_MACD = 0,
SE_ENTRY_LAMBERT = 1,
SE_ENTRY_PULLBACK = 2
};
struct SuperEMAData
{
string symbol;
ENUM_TIMEFRAMES tf;
datetime lastBarTime;
CTrade trade;
bool isInitialized;
int slippagePoints;
int magic;
int emaFast;
int emaMid;
int emaSlow;
int emaTrendBars;
int cciPeriod;
double cciOverbought;
double cciOversold;
int pullbackCciLookback;
int macdFast;
int macdSlow;
int macdSignal;
ENUM_SE_ENTRY_STYLE entryStyle;
bool oneTradeOnly;
bool useStructuralSL;
double slBufferPoints;
bool exitOnTrendFlip;
bool exitOnMacdFlip;
bool exitOnCciZeroCross;
int maxHoldingBars;
bool exitBelowMidEma;
bool debugLogs;
};
void SuperEMA_Log(SuperEMAData &d, const string s)
{
if(d.debugLogs)
Print("[SuperEMA] ", s);
}
double SuperEMA_Point(const SuperEMAData &d)
{
double pt = SymbolInfoDouble(d.symbol, SYMBOL_POINT);
return (pt > 0.0 ? pt : _Point);
}
bool SuperEMA_IsNewBar(SuperEMAData &d)
{
datetime t = iTime(d.symbol, d.tf, 0);
if(t <= 0 || t == d.lastBarTime)
return false;
d.lastBarTime = t;
return true;
}
double SuperEMA_EmaAt(SuperEMAData &d, const int period, const int shift)
{
int h = iMA(d.symbol, d.tf, period, 0, MODE_EMA, PRICE_CLOSE);
if(h == INVALID_HANDLE)
return 0.0;
double b[1];
if(CopyBuffer(h, 0, shift, 1, b) <= 0)
{
IndicatorRelease(h);
return 0.0;
}
IndicatorRelease(h);
return b[0];
}
double SuperEMA_CciAt(SuperEMAData &d, const int shift)
{
int h = iCCI(d.symbol, d.tf, d.cciPeriod, PRICE_TYPICAL);
if(h == INVALID_HANDLE)
return 0.0;
double b[1];
if(CopyBuffer(h, 0, shift, 1, b) <= 0)
{
IndicatorRelease(h);
return 0.0;
}
IndicatorRelease(h);
return b[0];
}
bool SuperEMA_MacdHistAt(SuperEMAData &d, const int shift, double &hist)
{
int h = iMACD(d.symbol, d.tf, d.macdFast, d.macdSlow, d.macdSignal, PRICE_CLOSE);
if(h == INVALID_HANDLE)
return false;
double mainLine[1], sigLine[1];
if(CopyBuffer(h, 0, shift, 1, mainLine) <= 0 || CopyBuffer(h, 1, shift, 1, sigLine) <= 0)
{
IndicatorRelease(h);
return false;
}
IndicatorRelease(h);
hist = mainLine[0] - sigLine[0];
return true;
}
bool SuperEMA_TrendUp(SuperEMAData &d, const int sh)
{
double c = iClose(d.symbol, d.tf, sh);
double emaS = SuperEMA_EmaAt(d, d.emaSlow, sh);
return (emaS > 0.0 && c > emaS);
}
bool SuperEMA_TrendDown(SuperEMAData &d, const int sh)
{
double c = iClose(d.symbol, d.tf, sh);
double emaS = SuperEMA_EmaAt(d, d.emaSlow, sh);
return (emaS > 0.0 && c < emaS);
}
bool SuperEMA_CciCrossAboveZero(SuperEMAData &d)
{
double c1 = SuperEMA_CciAt(d, 1);
double c2 = SuperEMA_CciAt(d, 2);
return (c2 <= 0.0 && c1 > 0.0);
}
bool SuperEMA_CciCrossBelowZero(SuperEMAData &d)
{
double c1 = SuperEMA_CciAt(d, 1);
double c2 = SuperEMA_CciAt(d, 2);
return (c2 >= 0.0 && c1 < 0.0);
}
bool SuperEMA_CciCrossAbove100(SuperEMAData &d)
{
double c1 = SuperEMA_CciAt(d, 1);
double c2 = SuperEMA_CciAt(d, 2);
return (c2 < d.cciOverbought && c1 > d.cciOverbought);
}
bool SuperEMA_CciCrossBelowMinus100(SuperEMAData &d)
{
double c1 = SuperEMA_CciAt(d, 1);
double c2 = SuperEMA_CciAt(d, 2);
return (c2 > d.cciOversold && c1 < d.cciOversold);
}
bool SuperEMA_HadCciOversoldRecently(SuperEMAData &d)
{
for(int i = 2; i <= d.pullbackCciLookback + 1; i++)
{
double v = SuperEMA_CciAt(d, i);
if(v <= d.cciOversold)
return true;
}
return false;
}
bool SuperEMA_HadCciOverboughtRecently(SuperEMAData &d)
{
for(int i = 2; i <= d.pullbackCciLookback + 1; i++)
{
double v = SuperEMA_CciAt(d, i);
if(v >= d.cciOverbought)
return true;
}
return false;
}
bool SuperEMA_PullbackNearFastEmaLong(SuperEMAData &d)
{
double emaF = SuperEMA_EmaAt(d, d.emaFast, 1);
double lo = iLow(d.symbol, d.tf, 1);
if(emaF <= 0.0)
return false;
const double pt = SuperEMA_Point(d);
return (lo <= emaF + d.slBufferPoints * pt * 3.0);
}
bool SuperEMA_PullbackNearFastEmaShort(SuperEMAData &d)
{
double emaF = SuperEMA_EmaAt(d, d.emaFast, 1);
double hi = iHigh(d.symbol, d.tf, 1);
if(emaF <= 0.0)
return false;
const double pt = SuperEMA_Point(d);
return (hi >= emaF - d.slBufferPoints * pt * 3.0);
}
int SuperEMA_PositionsByMagic(SuperEMAData &d)
{
int n = 0;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong t = PositionGetTicket(i);
if(t == 0)
continue;
if(!PositionSelectByTicket(t))
continue;
if(PositionGetString(POSITION_SYMBOL) == d.symbol && (int)PositionGetInteger(POSITION_MAGIC) == d.magic)
n++;
}
return n;
}
void SuperEMA_ComputeSLTP(SuperEMAData &d, const bool isBuy, double &sl, double &tp)
{
sl = 0.0;
tp = 0.0;
if(!d.useStructuralSL)
return;
double emaM = SuperEMA_EmaAt(d, d.emaMid, d.emaTrendBars);
double buf = d.slBufferPoints * SuperEMA_Point(d);
if(isBuy)
sl = emaM - buf;
else
sl = emaM + buf;
}
int SuperEMA_BarsSinceOpen(SuperEMAData &d, const datetime openTime)
{
if(openTime <= 0)
return 0;
int sh = iBarShift(d.symbol, d.tf, openTime, false);
if(sh < 0)
return 999999;
return sh;
}
void SuperEMA_CloseTicket(SuperEMAData &d, const ulong ticket, const string reason)
{
#ifdef UNITED_MARTINGALE_NO_SELF_CLOSE
return;
#endif
d.trade.SetExpertMagicNumber(d.magic);
if(d.trade.PositionClose(ticket))
SuperEMA_Log(d, "Close: " + reason);
}
void SuperEMA_ManageExits(SuperEMAData &d)
{
#ifdef UNITED_MARTINGALE_NO_SELF_CLOSE
return;
#endif
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0)
continue;
if(!PositionSelectByTicket(ticket))
continue;
if(PositionGetString(POSITION_SYMBOL) != d.symbol)
continue;
if((int)PositionGetInteger(POSITION_MAGIC) != d.magic)
continue;
ENUM_POSITION_TYPE ptype = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
datetime openTime = (datetime)PositionGetInteger(POSITION_TIME);
double h1 = 0.0;
if(!SuperEMA_MacdHistAt(d, 1, h1))
continue;
bool closeLong = false;
bool closeShort = false;
string reason = "";
if(d.maxHoldingBars > 0)
{
int held = SuperEMA_BarsSinceOpen(d, openTime);
if(held >= d.maxHoldingBars)
{
if(ptype == POSITION_TYPE_BUY)
closeLong = true;
else
closeShort = true;
reason = "time stop (max bars)";
}
}
if(ptype == POSITION_TYPE_BUY)
{
if(d.exitOnTrendFlip && SuperEMA_TrendDown(d, d.emaTrendBars))
{
closeLong = true;
reason = "trend flip (below slow EMA)";
}
if(d.exitOnMacdFlip && h1 < 0.0)
{
closeLong = true;
reason = "MACD histogram < 0";
}
if(d.exitOnCciZeroCross && SuperEMA_CciCrossBelowZero(d))
{
closeLong = true;
reason = "CCI crossed below zero";
}
if(d.exitBelowMidEma)
{
double c = iClose(d.symbol, d.tf, 1);
double emaM = SuperEMA_EmaAt(d, d.emaMid, 1);
if(emaM > 0.0 && c < emaM)
{
closeLong = true;
reason = "close below mid EMA";
}
}
if(closeLong)
SuperEMA_CloseTicket(d, ticket, reason);
}
else if(ptype == POSITION_TYPE_SELL)
{
if(d.exitOnTrendFlip && SuperEMA_TrendUp(d, d.emaTrendBars))
{
closeShort = true;
reason = "trend flip (above slow EMA)";
}
if(d.exitOnMacdFlip && h1 > 0.0)
{
closeShort = true;
reason = "MACD histogram > 0";
}
if(d.exitOnCciZeroCross && SuperEMA_CciCrossAboveZero(d))
{
closeShort = true;
reason = "CCI crossed above zero";
}
if(d.exitBelowMidEma)
{
double c = iClose(d.symbol, d.tf, 1);
double emaM = SuperEMA_EmaAt(d, d.emaMid, 1);
if(emaM > 0.0 && c > emaM)
{
closeShort = true;
reason = "close above mid EMA";
}
}
if(closeShort)
SuperEMA_CloseTicket(d, ticket, reason);
}
}
}
bool InitSuperEMA(SuperEMAData &d,
const string symbol,
const ENUM_TIMEFRAMES tf,
const int slippagePoints,
const int magic,
const int emaFast,
const int emaMid,
const int emaSlow,
const int emaTrendBars,
const int cciPeriod,
const double cciOverbought,
const double cciOversold,
const int pullbackCciLookback,
const int macdFast,
const int macdSlow,
const int macdSignal,
const ENUM_SE_ENTRY_STYLE entryStyle,
const bool oneTradeOnly,
const bool useStructuralSL,
const double slBufferPoints,
const bool exitOnTrendFlip,
const bool exitOnMacdFlip,
const bool exitOnCciZeroCross,
const int maxHoldingBars,
const bool exitBelowMidEma,
const bool debugLogs)
{
d.symbol = symbol;
if(StringLen(d.symbol) == 0)
d.symbol = _Symbol;
d.tf = tf;
d.lastBarTime = 0;
d.isInitialized = false;
d.slippagePoints = slippagePoints;
d.magic = magic;
d.emaFast = emaFast;
d.emaMid = emaMid;
d.emaSlow = emaSlow;
d.emaTrendBars = emaTrendBars;
d.cciPeriod = cciPeriod;
d.cciOverbought = cciOverbought;
d.cciOversold = cciOversold;
d.pullbackCciLookback = pullbackCciLookback;
d.macdFast = macdFast;
d.macdSlow = macdSlow;
d.macdSignal = macdSignal;
d.entryStyle = entryStyle;
d.oneTradeOnly = oneTradeOnly;
d.useStructuralSL = useStructuralSL;
d.slBufferPoints = slBufferPoints;
d.exitOnTrendFlip = exitOnTrendFlip;
d.exitOnMacdFlip = exitOnMacdFlip;
d.exitOnCciZeroCross = exitOnCciZeroCross;
d.maxHoldingBars = maxHoldingBars;
d.exitBelowMidEma = exitBelowMidEma;
d.debugLogs = debugLogs;
if(!SymbolSelect(d.symbol, true))
{
Print("SuperEMA: symbol not available: ", d.symbol);
return false;
}
d.trade.SetExpertMagicNumber(d.magic);
d.trade.SetDeviationInPoints(d.slippagePoints);
d.isInitialized = true;
return true;
}
void ProcessSuperEMA(SuperEMAData &d, const double lots)
{
if(!d.isInitialized)
return;
if(!SuperEMA_IsNewBar(d))
return;
SuperEMA_ManageExits(d);
// Same order as standalone SuperEMAXAUUSD: skip entry logic when flat is not allowed.
if(d.oneTradeOnly && SuperEMA_PositionsByMagic(d) > 0)
return;
const int sh = d.emaTrendBars;
double h1 = 0.0;
if(!SuperEMA_MacdHistAt(d, 1, h1))
return;
bool up = SuperEMA_TrendUp(d, sh);
bool dn = SuperEMA_TrendDown(d, sh);
bool wantBuy = false;
bool wantSell = false;
switch(d.entryStyle)
{
case SE_ENTRY_CCIZERO_MACD:
if(up && SuperEMA_CciCrossAboveZero(d) && h1 > 0.0)
wantBuy = true;
if(dn && SuperEMA_CciCrossBelowZero(d) && h1 < 0.0)
wantSell = true;
break;
case SE_ENTRY_LAMBERT:
if(up && SuperEMA_CciCrossAbove100(d) && h1 > 0.0)
wantBuy = true;
if(dn && SuperEMA_CciCrossBelowMinus100(d) && h1 < 0.0)
wantSell = true;
break;
case SE_ENTRY_PULLBACK:
if(up && SuperEMA_HadCciOversoldRecently(d) && SuperEMA_CciCrossAboveZero(d) && h1 > 0.0 && SuperEMA_PullbackNearFastEmaLong(d))
wantBuy = true;
if(dn && SuperEMA_HadCciOverboughtRecently(d) && SuperEMA_CciCrossBelowZero(d) && h1 < 0.0 && SuperEMA_PullbackNearFastEmaShort(d))
wantSell = true;
break;
}
if(!wantBuy && !wantSell)
return;
const double vol = United_NormalizeVolume(d.symbol, lots);
if(vol <= 0.0)
{
SuperEMA_Log(d, "Skip entry: normalized volume <= 0");
return;
}
MqlTick tick;
if(!SymbolInfoTick(d.symbol, tick))
return;
double sl = 0.0, tp = 0.0;
if(wantBuy && !wantSell)
{
#ifndef UNITED_MARTINGALE_NO_SELF_CLOSE
SuperEMA_ComputeSLTP(d, true, sl, tp);
#endif
if(d.trade.Buy(vol, d.symbol, tick.ask, sl, tp, "United SuperEMA long"))
SuperEMA_Log(d, StringFormat("BUY ask=%.5f sl=%.5f", tick.ask, sl));
}
else if(wantSell && !wantBuy)
{
#ifndef UNITED_MARTINGALE_NO_SELF_CLOSE
SuperEMA_ComputeSLTP(d, false, sl, tp);
#endif
if(d.trade.Sell(vol, d.symbol, tick.bid, sl, tp, "United SuperEMA short"))
SuperEMA_Log(d, StringFormat("SELL bid=%.5f sl=%.5f", tick.bid, sl));
}
}
void DeinitSuperEMA(SuperEMAData &d)
{
d.isInitialized = false;
}
#endif // SUPER_EMA_STRATEGY_MQH
+965
View File
@@ -0,0 +1,965 @@
//+------------------------------------------------------------------+
//| 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.21"
#property strict
#property description "LOT_* nominal at ORCH_ReferenceBalance; scale = balance/equity ÷ reference (clamped). No performance-evaluator ranking."
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Indicators\Trend.mqh>
#include <Indicators\Volumes.mqh>
#include "MagicNumberHelpers.mqh"
#define UNITED_V2_DYNAMIC_LOTS
double g_DB_LotSize;
// Include strategy implementations early so structs are available
#include "Strategies/DarvasBoxStrategy.mqh"
#include "Strategies/EMASlopeDistanceStrategy.mqh"
#include "Strategies/RSICrossOverReversalStrategy.mqh"
#include "Strategies/RSIMidPointHijackStrategy.mqh"
#include "Strategies/RSIScalpingStrategy.mqh"
#include "Strategies/SuperEMAStrategy.mqh"
#include "Strategies/RSIReversalAsianStrategy.mqh"
#include "Strategies/RSIConsolidationStrategy.mqh"
#include "Strategies/SimpleTrendlineStrategy.mqh"
#include "Strategies/RSISecretSauceStrategy.mqh"
//+------------------------------------------------------------------+
//| Global Lot Size Variables (for dynamic lot sizing) |
//+------------------------------------------------------------------+
double g_ES_LotSize; // EMA Slope Distance lot size
double g_RC_LotSize; // RSI CrossOver Reversal lot size
double g_RM_LotSize; // RSI MidPoint Hijack lot size
double g_Pos_RS_APPL;
double g_Pos_RS_BTCUSD;
double g_Pos_RS_NVDA;
double g_Pos_RS_TSLA;
double g_Pos_RS_XAUUSD;
double g_Pos_RS_MU;
double g_Pos_RRA_EURUSD;
double g_Pos_RRA_AUDUSD;
double g_Pos_SE;
double g_Pos_RCO;
double g_Pos_ST_BTCUSD;
double g_Pos_ST_XAUUSD;
double g_Pos_ST_GER40;
double g_RSS_LotSize;
bool United_MayOpenNewEntry(const string symbol, const ulong magic, const bool isBuy)
{
if(PositionExistsByMagic(symbol, magic))
return false;
return true;
}
//+------------------------------------------------------------------+
//| Strategy Enable/Disable Switches |
//+------------------------------------------------------------------+
input group "=== Strategy Enable/Disable ==="
input bool EnableDarvasBox = true;
input bool EnableEMASlopeDistance = true;
input bool EnableRSICrossOverReversal = true;
input bool EnableRSIMidPointHijack = true;
input bool EnableRSIScalpingAPPL = true;
input bool EnableRSIScalpingBTCUSD = false;
input bool EnableRSIScalpingNVDA = true;
input bool EnableRSIScalpingTSLA = true;
input bool EnableRSIScalpingXAUUSD = false;
input bool EnableRSIScalpingMU = true;
input bool EnableSuperEMA = false;
input bool EnableRSIConsolidation = false;
input bool EnableRSIReversalAsianEURUSD = true;
input bool EnableRSIReversalAsianAUDUSD = true;
input bool EnableSimpleTrendlineBTCUSD = false;
input bool EnableSimpleTrendlineXAUUSD = false;
input bool EnableSimpleTrendlineGER40 = false;
input bool EnableRSISecretSauce = false;
input bool OPT_GuardOptimizationMode = true; // legacy compatibility with 123.set
input group "=== Centralized Lot Size (Granular Per Robot) ==="
input double LOT_DB_DarvasBox = 0.01;
input double LOT_ES_EMASlopeDistance = 0.02;
input double LOT_RC_RSICrossOver = 0.01;
input double LOT_RM_RSIMidPointHijack = 0.01;
input double LOT_RS_APPL = 25.0;
input double LOT_RS_BTCUSD = 0.1;
input double LOT_RS_NVDA = 25.0;
input double LOT_RS_TSLA = 5.0;
input double LOT_RS_XAUUSD = 0.27;
input double LOT_RS_MU = 5.0;
input double LOT_RRA_EURUSD = 0.1;
input double LOT_RRA_AUDUSD = 0.1;
input double LOT_SE_SuperEMA = 0.01;
input double LOT_RCO_RSIConsolidation = 0.1;
input double LOT_ST_BTCUSD = 0.1;
input double LOT_ST_XAUUSD = 0.1;
input double LOT_ST_GER40 = 0.10;
input double LOT_RSS_SecretSauce = 0.1;
input group "=== Balance-based position sizing ==="
input bool ORCH_ScaleLotsByBalance = true;
input bool ORCH_UseEquityInsteadOfBalance = false;
input double ORCH_ReferenceBalance = 1000.0;
input double ORCH_MinBalanceScale = 0.1;
input double ORCH_MaxBalanceScale = 100000.0;
//+------------------------------------------------------------------+
//| Strategy 1: DarvasBoxXAUUSD |
//+------------------------------------------------------------------+
input group "=== DarvasBox Strategy ==="
input string DB_Symbol = "XAUUSD";
input int DB_BoxPeriod = 165;
input double DB_BoxDeviation = 30000; // Increased to allow larger ranges (was 25140)
input int DB_VolumeThreshold = 0; // Set to 0 to disable volume threshold check. Volume data from indicator used instead.
input double DB_StopLoss = 1665;
input double DB_TakeProfit = 3685;
input bool DB_EnableLogging = false;
input color DB_BoxColor = (color)16711680;
input int DB_BoxWidth = 1;
input ENUM_TIMEFRAMES DB_TrendTimeframe = PERIOD_H2;
input int DB_MA_Period = 125;
input ENUM_MA_METHOD DB_MA_Method = MODE_EMA;
input ENUM_APPLIED_PRICE DB_MA_Price = PRICE_WEIGHTED;
input double DB_TrendThreshold = 4.94;
input int DB_VolumeMA_Period = 110;
input double DB_VolumeThresholdMultiplier = 1.5;
input bool DB_UseVolumeSpikeFilter = true;
input bool DB_UseTrendFilter = true;
input int DB_MagicNumber = 135790;
//+------------------------------------------------------------------+
//| Strategy 2: EMASlopeDistanceCocktailXAUUSD |
//| PEPPERSTONE US: Gold symbol is typically "XAUUSD" or "GOLD" |
//+------------------------------------------------------------------+
input group "=== EMA Slope Distance Strategy ==="
input string ES_Symbol = "XAUUSD";
input int ES_EMA_Periode = 46;
input double ES_PreisSchwelle = 600.0;
input double ES_SteigungSchwelle = 80.0;
input int ES_ÜberwachungTimeout = 800;
input double ES_TrailingStop = 370.0;
input bool ES_UseTrailingStop = true;
input double ES_TrailingActivationPips = 0.0;
input bool ES_UseStaleStopLossExit = false;
input int ES_StaleStopLossSeconds = 33800;
input double ES_LotGröße = 0.07;
input int ES_MagicNumber = 12350;
input bool ES_UseSpreadAdjustment = true;
input ENUM_TIMEFRAMES ES_Timeframe = PERIOD_H1;
input bool ES_UseBarData = true;
input int ES_MaxTradesPerCrossover = 9;
input int ES_ProfitCheckBars = 18;
input bool ES_CloseUnprofitableTrades = true;
input bool ES_UseWeeklyADXFilter = true;
input int ES_WeeklyADXPeriod = 15;
input double ES_WeeklyADXMin = 40.0;
input int ES_WeeklyADXBarShift = 2;
input bool ES_WeeklyADXUseDirection = true;
//+------------------------------------------------------------------+
//| Strategy 3: RSICrossOverReversalXAUUSD |
//| PEPPERSTONE US: Gold symbol is typically "XAUUSD" or "GOLD" |
//+------------------------------------------------------------------+
input group "=== RSI CrossOver Reversal Strategy ==="
input string RC_Symbol = "XAUUSD";
input int RC_MagicNumber = 7;
input int RC_rsiPeriod = 19;
input int RC_overboughtLevel = 93;
input int RC_oversoldLevel = 22;
input double RC_entryRSIBuySpread = 0;
input double RC_entryRSISellSpread = 0;
input double RC_lotSize = 0.1;
input int RC_slippage = 3;
input int RC_cooldownSeconds = 209;
input ENUM_TIMEFRAMES RC_TimeFrame1 = PERIOD_M1;
input ENUM_TIMEFRAMES RC_TimeFrame2 = PERIOD_M1;
input ENUM_TIMEFRAMES RC_BarTimeFrame = PERIOD_M12;
input int RC_emaPeriod = 140;
input double RC_emaSlopeThreshold = 105;
input double RC_exitBuyRSI = 86;
input double RC_exitSellRSI = 10;
input double RC_TrailingStop = 295;
input double RC_emaDistanceThreshold = 165;
input bool RC_UseTrendStrengthFilter = true;
input int RC_tradingHourOneBegin = 24;
input int RC_tradingHourOneEnd = 22;
input int RC_tradingHourTwoBegin = 6;
input int RC_tradingHourTwoEnd = 19;
input bool RC_Sunday = false;
input bool RC_Monday = false;
input bool RC_Tuesday = true;
input bool RC_Wednesday = true;
input bool RC_Thursday = true;
input bool RC_Friday = false;
input bool RC_Saturday = false;
//+------------------------------------------------------------------+
//| Strategy 4: RSIMidPointHijackXAUUSD |
//| PEPPERSTONE US: Gold symbol is typically "XAUUSD" or "GOLD" |
//+------------------------------------------------------------------+
input group "=== RSI MidPoint Hijack Strategy ==="
input string RM_Symbol = "XAUUSD";
input ENUM_TIMEFRAMES RM_InpTimeframe = PERIOD_H1;
input double RM_InpLotSize = 0.1;
input int RM_InpMagicNumberRSIFollow = 1001;
input int RM_InpMagicNumberRSIReverse = 1002;
input int RM_InpMagicNumberEMACross = 1003;
input bool RM_InpEnableRSIFollow = true;
input bool RM_InpEnableRSIReverse = true;
input bool RM_InpEnableEMACross = true;
input bool RM_InpEnableStrategyLock = false;
input double RM_InpLockProfitThreshold = 0.0;
input bool RM_InpCloseOppositeTrades = false;
input int RM_InpRSIPeriod = 32;
input int RM_InpRSIOverbought = 78;
input int RM_InpRSIOversold = 46;
input int RM_InpRSIExitLevel = 44;
input int RM_InpRSIFollowStartHour = 23;
input int RM_InpRSIFollowEndHour = 8;
input bool RM_InpRSIFollowCloseOutsideHours = false;
input int RM_InpRSIReversePeriod = 59;
input int RM_InpRSIReverseOverbought = 51;
input int RM_InpRSIReverseOversold = 49;
input int RM_InpRSIReverseCrossLevel = 53;
input int RM_InpRSIReverseExitLevel = 48;
input int RM_InpRSIReverseStartHour = 7;
input int RM_InpRSIReverseEndHour = 13;
input bool RM_InpRSIReverseCloseOutsideHours = false;
input int RM_InpRSIReverseCooldownBars = 15;
input bool RM_InpRSIReverseCooldownOnLoss = true;
input int RM_InpEMAPeriod = 120;
input int RM_InpEMACrossStartHour = 8;
input int RM_InpEMACrossEndHour = 14;
input bool RM_InpEMACrossCloseOutsideHours = true;
input bool RM_InpUseEMADistanceEntry = true;
input double RM_InpEMADistancePips = 160.0;
input int RM_InpEMADistancePeriod = 26;
//+------------------------------------------------------------------+
//| Strategy 5-10: RSI Scalping Strategies |
//| Each RSI Scalping strategy trades on its own symbol: |
//| - APPL: Apple stock (AAPL) |
//| - BTCUSD: Bitcoin/USD |
//| - NVDA: NVIDIA stock |
//| - TSLA: Tesla stock |
//| - XAUUSD: Gold/USD |
//| |
//| PEPPERSTONE US SYMBOL FORMATS: |
//| - Stocks may use: "AAPL.US", "NASDAQ:AAPL", or just "AAPL" |
//| - To find correct symbols: |
//| 1. Open Market Watch (Ctrl+M) |
//| 2. Right-click > Show All |
//| 3. Search for the stock name |
//| 4. Use the exact symbol name shown |
//+------------------------------------------------------------------+
input group "=== RSI Scalping APPL (AAPL) - Pepperstone US ==="
input string RS_APPL_Symbol = "AAPL";
input ENUM_TIMEFRAMES RS_APPL_TimeFrame = PERIOD_M10;
input int RS_APPL_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_APPL_RSI_Applied_Price = PRICE_CLOSE;
input double RS_APPL_RSI_Overbought = 80;
input double RS_APPL_RSI_Oversold = 78;
input double RS_APPL_RSI_Target_Buy = 94;
input double RS_APPL_RSI_Target_Sell = 44;
input int RS_APPL_BarsToWait = 7;
input double RS_APPL_LotSize = 25;
input int RS_APPL_MagicNumber = 20001;
input int RS_APPL_Slippage = 3;
input group "=== RSI Scalping BTCUSD ==="
input string RS_BTCUSD_Symbol = "BTCUSD"; // Pepperstone may use: "BTCUSD", "BTC/USD", or "BTCUSD.c"
input ENUM_TIMEFRAMES RS_BTCUSD_TimeFrame = PERIOD_H1;
input int RS_BTCUSD_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_BTCUSD_RSI_Applied_Price = PRICE_CLOSE;
input double RS_BTCUSD_RSI_Overbought = 90;
input double RS_BTCUSD_RSI_Oversold = 73;
input double RS_BTCUSD_RSI_Target_Buy = 88;
input double RS_BTCUSD_RSI_Target_Sell = 48;
input int RS_BTCUSD_BarsToWait = 6;
input double RS_BTCUSD_LotSize = 0.1;
input int RS_BTCUSD_MagicNumber = 123459123;
input int RS_BTCUSD_Slippage = 3;
input group "=== RSI Scalping NVDA - Pepperstone US ==="
input string RS_NVDA_Symbol = "NVDA";
input ENUM_TIMEFRAMES RS_NVDA_TimeFrame = PERIOD_M15;
input int RS_NVDA_RSI_Period = 8;
input ENUM_APPLIED_PRICE RS_NVDA_RSI_Applied_Price = PRICE_CLOSE;
input double RS_NVDA_RSI_Overbought = 36;
input double RS_NVDA_RSI_Oversold = 38;
input double RS_NVDA_RSI_Target_Buy = 90;
input double RS_NVDA_RSI_Target_Sell = 70;
input int RS_NVDA_BarsToWait = 5;
input double RS_NVDA_LotSize = 5;
input int RS_NVDA_MagicNumber = 20003;
input int RS_NVDA_Slippage = 3;
input group "=== RSI Scalping TSLA - Pepperstone US ==="
input string RS_TSLA_Symbol = "TSLA";
input ENUM_TIMEFRAMES RS_TSLA_TimeFrame = PERIOD_H1;
input int RS_TSLA_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_TSLA_RSI_Applied_Price = PRICE_CLOSE;
input double RS_TSLA_RSI_Overbought = 54;
input double RS_TSLA_RSI_Oversold = 73;
input double RS_TSLA_RSI_Target_Buy = 87;
input double RS_TSLA_RSI_Target_Sell = 33;
input int RS_TSLA_BarsToWait = 1;
input double RS_TSLA_LotSize = 5;
input int RS_TSLA_MagicNumber = 125421321;
input int RS_TSLA_Slippage = 3;
input group "=== RSI Scalping XAUUSD ==="
input string RS_XAUUSD_Symbol = "XAUUSD";
input ENUM_TIMEFRAMES RS_XAUUSD_TimeFrame = PERIOD_H1;
input int RS_XAUUSD_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_XAUUSD_RSI_Applied_Price = PRICE_CLOSE;
input double RS_XAUUSD_RSI_Overbought = 71;
input double RS_XAUUSD_RSI_Oversold = 57;
input double RS_XAUUSD_RSI_Target_Buy = 80;
input double RS_XAUUSD_RSI_Target_Sell = 57;
input int RS_XAUUSD_BarsToWait = 4;
input double RS_XAUUSD_LotSize = 0.1;
input int RS_XAUUSD_MagicNumber = 129102315;
input int RS_XAUUSD_Slippage = 3;
input group "=== RSI Scalping MU ==="
input string RS_MU_Symbol = "MU";
input ENUM_TIMEFRAMES RS_MU_TimeFrame = PERIOD_M20;
input int RS_MU_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_MU_RSI_Applied_Price = PRICE_CLOSE;
input double RS_MU_RSI_Overbought = 32;
input double RS_MU_RSI_Oversold = 86;
input double RS_MU_RSI_Target_Buy = 100;
input double RS_MU_RSI_Target_Sell = 24;
input int RS_MU_BarsToWait = 34;
input double RS_MU_LotSize = 5.0;
input int RS_MU_MagicNumber = 129102316;
input int RS_MU_Slippage = 3;
input group "=== RSI Scalping Reversal Escape (XAUUSD only) ==="
input bool RS_UseReversalEscape = true;
input int RS_ReversalATRPeriod = 14;
input double RS_ReversalAdverseAtrMult = 5.25;
input int RS_ReversalSignsRequired = 2;
input double RS_ReversalRsiVelocity = 16.0;
input double RS_ReversalBodyAtrMult = 5.1;
input group "=== RSI Scalping APPL — Trailing (cluster-fuck BTC-style defaults) ==="
input bool RS_APPL_UseTrailingStop = true;
input double RS_APPL_TrailDistancePoints = 120.0;
input double RS_APPL_TrailActivationPoints = 0.0;
input group "=== RSI Scalping BTCUSD — Trailing ==="
input bool RS_BTCUSD_UseTrailingStop = true;
input double RS_BTCUSD_TrailDistancePoints = 120.0;
input double RS_BTCUSD_TrailActivationPoints = 0.0;
input group "=== RSI Scalping NVDA — Trailing ==="
input bool RS_NVDA_UseTrailingStop = true;
input double RS_NVDA_TrailDistancePoints = 375.0;
input double RS_NVDA_TrailActivationPoints = 75.0;
input group "=== RSI Scalping TSLA — Trailing ==="
input bool RS_TSLA_UseTrailingStop = true;
input double RS_TSLA_TrailDistancePoints = 900.0;
input double RS_TSLA_TrailActivationPoints = 950.0;
input group "=== RSI Scalping XAUUSD — Trailing ==="
input bool RS_XAUUSD_UseTrailingStop = true;
input double RS_XAUUSD_TrailDistancePoints = 71.0;
input double RS_XAUUSD_TrailActivationPoints = 41.0;
//+------------------------------------------------------------------+
//| Strategy 11-12: RSI Reversal Asian Strategies |
//| Each RSI Reversal Asian strategy trades on its own symbol: |
//| - EURUSD: Euro/USD |
//| - AUDUSD: Australian Dollar/USD |
//+------------------------------------------------------------------+
input group "=== RSI Reversal Asian EURUSD ==="
input string RRA_EURUSD_Symbol = "EURUSD";
input int RRA_EURUSD_RSIPeriod = 28;
input double RRA_EURUSD_OverboughtLevel = 60;
input double RRA_EURUSD_OversoldLevel = 8;
input int RRA_EURUSD_TakeProfitPips = 175;
input int RRA_EURUSD_StopLossPips = 5;
input double RRA_EURUSD_MaxLotSize = 0.1;
input int RRA_EURUSD_MaxSpread = 1000;
input int RRA_EURUSD_MaxDuration = 270;
input bool RRA_EURUSD_UseStopLoss = false;
input bool RRA_EURUSD_UseTakeProfit = false;
input bool RRA_EURUSD_UseRSIExit = true;
input double RRA_EURUSD_RSIExitLevel = 55;
input bool RRA_EURUSD_CloseOutsideSession = false;
input ENUM_TIMEFRAMES RRA_EURUSD_TimeFrame = PERIOD_M15;
input int RRA_EURUSD_MagicNumber = 30001;
input int RRA_EURUSD_Slippage = 3;
input group "=== RSI Reversal Asian AUDUSD ==="
input string RRA_AUDUSD_Symbol = "AUDUSD";
input int RRA_AUDUSD_RSIPeriod = 28;
input double RRA_AUDUSD_OverboughtLevel = 68;
input double RRA_AUDUSD_OversoldLevel = 30;
input int RRA_AUDUSD_TakeProfitPips = 175;
input int RRA_AUDUSD_StopLossPips = 5;
input double RRA_AUDUSD_MaxLotSize = 0.2;
input int RRA_AUDUSD_MaxSpread = 1000;
input int RRA_AUDUSD_MaxDuration = 340;
input bool RRA_AUDUSD_UseStopLoss = false;
input bool RRA_AUDUSD_UseTakeProfit = false;
input bool RRA_AUDUSD_UseRSIExit = true;
input double RRA_AUDUSD_RSIExitLevel = 48;
input bool RRA_AUDUSD_CloseOutsideSession = true;
input ENUM_TIMEFRAMES RRA_AUDUSD_TimeFrame = PERIOD_M15;
input int RRA_AUDUSD_MagicNumber = 30002;
input int RRA_AUDUSD_Slippage = 3;
input group "=== SuperEMA (EMA + CCI + MACD) ==="
input string SE_Symbol = "XAUUSD";
input ENUM_TIMEFRAMES SE_Timeframe = PERIOD_M15;
input double SE_LotSize = 0.01;
input int SE_SlippagePoints = 55;
input int SE_MagicNumber = 940001;
input int SE_EmaFast = 40;
input int SE_EmaMid = 180;
input int SE_EmaSlow = 125;
input int SE_EmaTrendBars = 3;
input int SE_CciPeriod = 17;
input double SE_CciOverbought = 80.0;
input double SE_CciOversold = -140.0;
input int SE_PullbackCciLookback = 20;
input int SE_MacdFast = 14;
input int SE_MacdSlow = 38;
input int SE_MacdSignal = 9;
input ENUM_SE_ENTRY_STYLE SE_EntryStyle = SE_ENTRY_LAMBERT;
input bool SE_OneTradeOnly = true;
input bool SE_UseStructuralSL = false;
input double SE_SlBufferPoints = 110;
input bool SE_ExitOnTrendFlip = false;
input bool SE_ExitOnMacdFlip = false;
input bool SE_ExitOnCciZeroCross = true;
input int SE_MaxHoldingBars = 168;
input bool SE_ExitBelowMidEma = false;
input bool SE_DebugLogs = false;
input group "=== RSI Consolidation (ranging / mean-reversion) ==="
input string RCO_Symbol = "XAUUSD";
input ENUM_TIMEFRAMES RCO_SignalTF = PERIOD_M15;
input bool RCO_EntryOnNewBarOnly = true;
input int RCO_ADX_Period = 23;
input double RCO_ADX_Max = 29.0;
input bool RCO_UseATRRatioFilter = true;
input int RCO_ATR_Period = 8;
input int RCO_ATR_SMA_Period = 35;
input double RCO_ATR_Ratio_Max = 1.36;
input bool RCO_UseFlatEMAFilter = true;
input int RCO_EMA_Fast = 13;
input int RCO_EMA_Slow = 17;
input double RCO_EMA_Separation_MaxPct = 0.26;
input int RCO_RSI_Period = 8;
input ENUM_APPLIED_PRICE RCO_RSI_Price = PRICE_OPEN;
input double RCO_RSI_Oversold = 22.0;
input double RCO_RSI_Overbought = 63.0;
input bool RCO_UseRSI_MeanExit = true;
input double RCO_RSI_Exit_Long = 48.0;
input double RCO_RSI_Exit_Short = 52.0;
input double RCO_SL_ATR_Mult = 2.15;
input double RCO_TP_ATR_Mult = 2.40;
input int RCO_MaxBarsInTrade = 54;
input double RCO_Lots = 0.10;
input ulong RCO_MagicNumber = 20250420;
input int RCO_Slippage = 10;
input int RCO_MaxSpreadPoints = 28;
input group "=== SimpleTrendline BTCUSD ==="
input string ST_BTC_Symbol = "BTCUSD";
input ENUM_TIMEFRAMES ST_BTC_SignalTF = PERIOD_H1;
input ENUM_TIMEFRAMES ST_BTC_HigherTF = PERIOD_H4;
input int ST_BTC_MAPeriod = 150;
input ENUM_MA_METHOD ST_BTC_MAMethod = MODE_SMMA;
input ENUM_APPLIED_PRICE ST_BTC_AppliedPrice = PRICE_OPEN;
input int ST_BTC_HTFBarsToScan = 1200;
input double ST_BTC_LineTouchTolerance = 170.0;
input double ST_BTC_BreakBuffer = 90.0;
input ulong ST_BTC_MagicNumber = 26042501;
input bool ST_BTC_DrawTrendline = true;
input group "=== SimpleTrendline XAUUSD ==="
input string ST_XAU_Symbol = "XAUUSD";
input ENUM_TIMEFRAMES ST_XAU_SignalTF = PERIOD_H1;
input ENUM_TIMEFRAMES ST_XAU_HigherTF = PERIOD_M10;
input int ST_XAU_MAPeriod = 65;
input ENUM_MA_METHOD ST_XAU_MAMethod = MODE_EMA;
input ENUM_APPLIED_PRICE ST_XAU_AppliedPrice = PRICE_OPEN;
input int ST_XAU_HTFBarsToScan = 500;
input double ST_XAU_LineTouchTolerance = 220.0;
input double ST_XAU_BreakBuffer = 110.0;
input ulong ST_XAU_MagicNumber = 26042501;
input bool ST_XAU_DrawTrendline = true;
input group "=== SimpleTrendline GER40 ==="
input string ST_GER_Symbol = "GER40";
input ENUM_TIMEFRAMES ST_GER_SignalTF = PERIOD_M15;
input ENUM_TIMEFRAMES ST_GER_HigherTF = PERIOD_M15;
input int ST_GER_MAPeriod = 65;
input ENUM_MA_METHOD ST_GER_MAMethod = MODE_LWMA;
input ENUM_APPLIED_PRICE ST_GER_AppliedPrice = PRICE_OPEN;
input int ST_GER_HTFBarsToScan = 1200;
input double ST_GER_LineTouchTolerance = 100.0;
input double ST_GER_BreakBuffer = 80.0;
input ulong ST_GER_MagicNumber = 26042502;
input bool ST_GER_DrawTrendline = true;
input group "=== RSI Secret Sauce XAUUSD ==="
input string RSS_Symbol = "XAUUSD";
input int RSS_MagicNumber = 789012;
input int RSS_Slippage = 10;
input ENUM_TIMEFRAMES RSS_Timeframe = PERIOD_M30;
input int RSS_RSIPeriod = 16;
input double RSS_RSIOverbought = 72.5;
input double RSS_RSIOversold = 32.5;
input int RSS_RSILookback = 60;
input int RSS_PeakBars = 2;
input double RSS_StopLossATR = 2.75;
input double RSS_TakeProfitATR = 5.0;
input int RSS_ATRPeriod = 14;
input bool RSS_UseSwingStopLoss = false;
input int RSS_SwingLookback = 30;
input int RSS_MaxPositions = 1;
input int RSS_MinBarsBetweenTrades = 7;
//+------------------------------------------------------------------+
//| Balance scaling: LOT_* = nominal size at ORCH_ReferenceBalance |
//+------------------------------------------------------------------+
double United_BalanceScaleFactor()
{
if(!ORCH_ScaleLotsByBalance || ORCH_ReferenceBalance <= 0.0)
return 1.0;
const double money = ORCH_UseEquityInsteadOfBalance
? AccountInfoDouble(ACCOUNT_EQUITY)
: AccountInfoDouble(ACCOUNT_BALANCE);
double raw = money / ORCH_ReferenceBalance;
if(raw < ORCH_MinBalanceScale)
raw = ORCH_MinBalanceScale;
if(raw > ORCH_MaxBalanceScale)
raw = ORCH_MaxBalanceScale;
return raw;
}
double United_ScaledLot(const double baseLot)
{
const double lot = baseLot * United_BalanceScaleFactor();
return (lot > 0.0 ? lot : 0.0);
}
void United_RefreshScaledLots()
{
g_DB_LotSize = United_ScaledLot(LOT_DB_DarvasBox);
g_ES_LotSize = United_ScaledLot(LOT_ES_EMASlopeDistance);
g_RC_LotSize = United_ScaledLot(LOT_RC_RSICrossOver);
g_RM_LotSize = United_ScaledLot(LOT_RM_RSIMidPointHijack);
g_Pos_RS_APPL = United_ScaledLot(LOT_RS_APPL);
g_Pos_RS_BTCUSD = United_ScaledLot(LOT_RS_BTCUSD);
g_Pos_RS_NVDA = United_ScaledLot(LOT_RS_NVDA);
g_Pos_RS_TSLA = United_ScaledLot(LOT_RS_TSLA);
g_Pos_RS_XAUUSD = United_ScaledLot(LOT_RS_XAUUSD);
g_Pos_RS_MU = United_ScaledLot(LOT_RS_MU);
g_Pos_RRA_EURUSD = United_ScaledLot(LOT_RRA_EURUSD);
g_Pos_RRA_AUDUSD = United_ScaledLot(LOT_RRA_AUDUSD);
g_Pos_SE = United_ScaledLot(LOT_SE_SuperEMA);
g_Pos_RCO = United_ScaledLot(LOT_RCO_RSIConsolidation);
g_Pos_ST_BTCUSD = United_ScaledLot(LOT_ST_BTCUSD);
g_Pos_ST_XAUUSD = United_ScaledLot(LOT_ST_XAUUSD);
g_Pos_ST_GER40 = United_ScaledLot(LOT_ST_GER40);
g_RSS_LotSize = United_ScaledLot(LOT_RSS_SecretSauce);
}
//+------------------------------------------------------------------+
//| Global Variables - DarvasBox |
//+------------------------------------------------------------------+
struct DarvasBoxData {
string symbol;
bool isInitialized;
double boxHigh;
double boxLow;
bool boxFormed;
datetime lastBoxTime;
string boxName;
double minStopLevel;
double point;
CTrade trade;
int maHandle;
int volumeHandle;
datetime lastBarTime;
};
//+------------------------------------------------------------------+
//| Global Variables - EMA Slope Distance |
//+------------------------------------------------------------------+
struct EMASlopeData {
string symbol;
bool isInitialized;
int ema_handle;
double ema_array[];
datetime letzte_überwachung_zeit;
bool überwachung_aktiv;
bool preis_trigger_aktiv;
bool steigung_trigger_aktiv;
int ticket;
CTrade trade;
int trades_in_current_crossover;
bool crossover_detected;
datetime trade_open_time;
datetime last_bar_time;
datetime es_last_sl_adjust_success_time;
};
//+------------------------------------------------------------------+
//| Global Variables - RSI CrossOver Reversal |
//+------------------------------------------------------------------+
struct RSICrossOverData {
string symbol;
bool isInitialized;
int rsiHandle;
int emaHandle;
double previousRSIDef;
CTrade trade;
datetime lastTradeTime;
datetime bartime;
bool WeekDays[7];
datetime lastBarTime;
};
//+------------------------------------------------------------------+
//| Global Variables - RSI MidPoint Hijack |
//+------------------------------------------------------------------+
struct RSIMidPointData {
string symbol;
bool isInitialized;
int rsiHandle;
int rsiReverseHandle;
int emaHandle;
bool rsiOverbought;
bool rsiOversold;
bool rsiReverseOverbought;
bool rsiReverseOversold;
CTrade trade;
CPositionInfo positionInfo;
bool emaCrossBuySignal;
bool emaCrossSellSignal;
int emaCrossSignalBar;
datetime lastBarTime;
datetime rsiReverseLastCloseTime;
bool rsiReverseInCooldown;
double lastBarRSI;
double lastBarRSIReverse;
double lastBarEMA;
double lastBarClose;
double lastBarEMAPrev;
double lastBarClosePrev;
};
//+------------------------------------------------------------------+
//| Global Strategy Instances |
//+------------------------------------------------------------------+
DarvasBoxData dbData;
EMASlopeData esData;
RSICrossOverData rcData;
RSIMidPointData rmData;
RSIScalpingData rsAPPLData;
RSIScalpingData rsBTCUSDData;
RSIScalpingData rsNVDAData;
RSIScalpingData rsTSLAData;
RSIScalpingData rsXAUUSDData;
RSIScalpingData rsMUData;
SuperEMAData seData;
RSIConsolidationData rcoData;
SimpleTrendlineData stBTCData;
SimpleTrendlineData stXAUData;
SimpleTrendlineData stGERData;
RSISecretSauceOrcData rssData;
//+------------------------------------------------------------------+
//| Global Variables - RSI Reversal Asian |
//+------------------------------------------------------------------+
RSIReversalAsianData rraEURUSDData;
RSIReversalAsianData rraAUDUSDData;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
int initResult = INIT_SUCCEEDED;
United_RefreshScaledLots();
// Initialize strategies - log warnings but don't fail entire EA if symbol unavailable
if(EnableDarvasBox)
if(!InitDarvasBox(DB_Symbol))
Print("Warning: DarvasBox strategy failed to initialize for symbol '", DB_Symbol, "'");
if(EnableEMASlopeDistance)
if(!InitEMASlopeDistance(ES_Symbol))
Print("Warning: EMASlopeDistance strategy failed to initialize for symbol '", ES_Symbol, "'");
if(EnableRSICrossOverReversal)
if(!InitRSICrossOverReversal(RC_Symbol))
Print("Warning: RSICrossOverReversal strategy failed to initialize for symbol '", RC_Symbol, "'");
if(EnableRSIMidPointHijack)
if(!InitRSIMidPointHijack(RM_Symbol))
Print("Warning: RSIMidPointHijack strategy failed to initialize for symbol '", RM_Symbol, "'");
// Initialize RSI Scalping strategies - don't fail entire EA if symbol unavailable
if(EnableRSIScalpingAPPL)
InitRSIScalping(rsAPPLData, RS_APPL_Symbol, RS_APPL_TimeFrame, RS_APPL_RSI_Period, RS_APPL_RSI_Applied_Price, RS_APPL_MagicNumber, RS_APPL_Slippage);
if(EnableRSIScalpingBTCUSD)
InitRSIScalping(rsBTCUSDData, RS_BTCUSD_Symbol, RS_BTCUSD_TimeFrame, RS_BTCUSD_RSI_Period, RS_BTCUSD_RSI_Applied_Price, RS_BTCUSD_MagicNumber, RS_BTCUSD_Slippage);
if(EnableRSIScalpingNVDA)
InitRSIScalping(rsNVDAData, RS_NVDA_Symbol, RS_NVDA_TimeFrame, RS_NVDA_RSI_Period, RS_NVDA_RSI_Applied_Price, RS_NVDA_MagicNumber, RS_NVDA_Slippage);
if(EnableRSIScalpingTSLA)
InitRSIScalping(rsTSLAData, RS_TSLA_Symbol, RS_TSLA_TimeFrame, RS_TSLA_RSI_Period, RS_TSLA_RSI_Applied_Price, RS_TSLA_MagicNumber, RS_TSLA_Slippage);
if(EnableRSIScalpingXAUUSD)
InitRSIScalping(rsXAUUSDData, RS_XAUUSD_Symbol, RS_XAUUSD_TimeFrame, RS_XAUUSD_RSI_Period, RS_XAUUSD_RSI_Applied_Price, RS_XAUUSD_MagicNumber, RS_XAUUSD_Slippage);
if(EnableRSIScalpingMU)
InitRSIScalping(rsMUData, RS_MU_Symbol, RS_MU_TimeFrame, RS_MU_RSI_Period, RS_MU_RSI_Applied_Price, RS_MU_MagicNumber, RS_MU_Slippage);
if(EnableRSISecretSauce)
if(!InitRSISecretSauce(rssData, RSS_Symbol))
Print("Warning: RSI Secret Sauce failed to initialize for symbol '", RSS_Symbol, "'");
if(EnableSuperEMA)
if(!InitSuperEMA(seData, SE_Symbol, SE_Timeframe, SE_SlippagePoints, SE_MagicNumber,
SE_EmaFast, SE_EmaMid, SE_EmaSlow, SE_EmaTrendBars,
SE_CciPeriod, SE_CciOverbought, SE_CciOversold, SE_PullbackCciLookback,
SE_MacdFast, SE_MacdSlow, SE_MacdSignal,
SE_EntryStyle, SE_OneTradeOnly, SE_UseStructuralSL, SE_SlBufferPoints,
SE_ExitOnTrendFlip, SE_ExitOnMacdFlip, SE_ExitOnCciZeroCross,
SE_MaxHoldingBars, SE_ExitBelowMidEma, SE_DebugLogs))
Print("Warning: SuperEMA failed to initialize for symbol '", SE_Symbol, "'");
if(EnableRSIConsolidation)
if(!InitRSIConsolidation(rcoData, RCO_Symbol, RCO_SignalTF, RCO_EntryOnNewBarOnly,
RCO_ADX_Period, RCO_ADX_Max, RCO_UseATRRatioFilter, RCO_ATR_Period, RCO_ATR_SMA_Period, RCO_ATR_Ratio_Max,
RCO_UseFlatEMAFilter, RCO_EMA_Fast, RCO_EMA_Slow, RCO_EMA_Separation_MaxPct,
RCO_RSI_Period, RCO_RSI_Price, RCO_RSI_Oversold, RCO_RSI_Overbought,
RCO_UseRSI_MeanExit, RCO_RSI_Exit_Long, RCO_RSI_Exit_Short, RCO_SL_ATR_Mult, RCO_TP_ATR_Mult,
RCO_MaxBarsInTrade, RCO_MagicNumber, RCO_Slippage, RCO_MaxSpreadPoints))
Print("Warning: RSIConsolidation failed to initialize for symbol '", RCO_Symbol, "'");
// Initialize RSI Reversal Asian strategies
if(EnableRSIReversalAsianEURUSD)
if(!InitRSIReversalAsian(rraEURUSDData, RRA_EURUSD_Symbol, RRA_EURUSD_RSIPeriod, RRA_EURUSD_OverboughtLevel, RRA_EURUSD_OversoldLevel,
RRA_EURUSD_TakeProfitPips, RRA_EURUSD_StopLossPips, LOT_RRA_EURUSD,
RRA_EURUSD_MaxSpread, RRA_EURUSD_MaxDuration, RRA_EURUSD_UseStopLoss,
RRA_EURUSD_UseTakeProfit, RRA_EURUSD_UseRSIExit, RRA_EURUSD_RSIExitLevel,
RRA_EURUSD_CloseOutsideSession, RRA_EURUSD_TimeFrame, RRA_EURUSD_MagicNumber, RRA_EURUSD_Slippage))
Print("Warning: RSIReversalAsianEURUSD strategy failed to initialize for symbol '", RRA_EURUSD_Symbol, "'");
if(EnableRSIReversalAsianAUDUSD)
if(!InitRSIReversalAsian(rraAUDUSDData, RRA_AUDUSD_Symbol, RRA_AUDUSD_RSIPeriod, RRA_AUDUSD_OverboughtLevel, RRA_AUDUSD_OversoldLevel,
RRA_AUDUSD_TakeProfitPips, RRA_AUDUSD_StopLossPips, LOT_RRA_AUDUSD,
RRA_AUDUSD_MaxSpread, RRA_AUDUSD_MaxDuration, RRA_AUDUSD_UseStopLoss,
RRA_AUDUSD_UseTakeProfit, RRA_AUDUSD_UseRSIExit, RRA_AUDUSD_RSIExitLevel,
RRA_AUDUSD_CloseOutsideSession, RRA_AUDUSD_TimeFrame, RRA_AUDUSD_MagicNumber, RRA_AUDUSD_Slippage))
Print("Warning: RSIReversalAsianAUDUSD strategy failed to initialize for symbol '", RRA_AUDUSD_Symbol, "'");
if(EnableSimpleTrendlineBTCUSD)
if(!InitSimpleTrendline(stBTCData, ST_BTC_Symbol, ST_BTC_SignalTF, ST_BTC_HigherTF, ST_BTC_MAPeriod,
ST_BTC_MAMethod, ST_BTC_AppliedPrice, ST_BTC_HTFBarsToScan,
ST_BTC_LineTouchTolerance, ST_BTC_BreakBuffer, ST_BTC_MagicNumber, ST_BTC_DrawTrendline))
Print("Warning: SimpleTrendlineBTCUSD failed to initialize for symbol '", ST_BTC_Symbol, "'");
if(EnableSimpleTrendlineXAUUSD)
if(!InitSimpleTrendline(stXAUData, ST_XAU_Symbol, ST_XAU_SignalTF, ST_XAU_HigherTF, ST_XAU_MAPeriod,
ST_XAU_MAMethod, ST_XAU_AppliedPrice, ST_XAU_HTFBarsToScan,
ST_XAU_LineTouchTolerance, ST_XAU_BreakBuffer, ST_XAU_MagicNumber, ST_XAU_DrawTrendline))
Print("Warning: SimpleTrendlineXAUUSD failed to initialize for symbol '", ST_XAU_Symbol, "'");
if(EnableSimpleTrendlineGER40)
if(!InitSimpleTrendline(stGERData, ST_GER_Symbol, ST_GER_SignalTF, ST_GER_HigherTF, ST_GER_MAPeriod,
ST_GER_MAMethod, ST_GER_AppliedPrice, ST_GER_HTFBarsToScan,
ST_GER_LineTouchTolerance, ST_GER_BreakBuffer, ST_GER_MagicNumber, ST_GER_DrawTrendline))
Print("Warning: SimpleTrendlineGER40 failed to initialize for symbol '", ST_GER_Symbol, "'");
Print("United EA initialized. Active strategies: ",
(EnableDarvasBox ? "DarvasBox " : ""),
(EnableEMASlopeDistance ? "EMASlope " : ""),
(EnableRSICrossOverReversal ? "RSICrossOver " : ""),
(EnableRSIMidPointHijack ? "RSIMidPoint " : ""),
(EnableRSIScalpingAPPL ? "RSIScalpingAPPL " : ""),
(EnableRSIScalpingBTCUSD ? "RSIScalpingBTCUSD " : ""),
(EnableRSIScalpingNVDA ? "RSIScalpingNVDA " : ""),
(EnableRSIScalpingTSLA ? "RSIScalpingTSLA " : ""),
(EnableRSIScalpingXAUUSD ? "RSIScalpingXAUUSD " : ""),
(EnableRSIScalpingMU ? "RSIScalpingMU " : ""),
(EnableRSISecretSauce ? "RSISecretSauce " : ""),
(EnableSuperEMA ? "SuperEMA " : ""),
(EnableRSIConsolidation ? "RSIConsolidation " : ""),
(EnableRSIReversalAsianEURUSD ? "RSIReversalAsianEURUSD " : ""),
(EnableRSIReversalAsianAUDUSD ? "RSIReversalAsianAUDUSD " : ""),
(EnableSimpleTrendlineBTCUSD ? "SimpleTrendlineBTCUSD " : ""),
(EnableSimpleTrendlineXAUUSD ? "SimpleTrendlineXAUUSD " : ""),
(EnableSimpleTrendlineGER40 ? "SimpleTrendlineGER40 " : ""));
return initResult;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(EnableDarvasBox)
DeinitDarvasBox();
if(EnableEMASlopeDistance)
DeinitEMASlopeDistance();
if(EnableRSICrossOverReversal)
DeinitRSICrossOverReversal();
if(EnableRSIMidPointHijack)
DeinitRSIMidPointHijack();
if(EnableRSIScalpingAPPL)
DeinitRSIScalping(rsAPPLData);
if(EnableRSIScalpingBTCUSD)
DeinitRSIScalping(rsBTCUSDData);
if(EnableRSIScalpingNVDA)
DeinitRSIScalping(rsNVDAData);
if(EnableRSIScalpingTSLA)
DeinitRSIScalping(rsTSLAData);
if(EnableRSIScalpingXAUUSD)
DeinitRSIScalping(rsXAUUSDData);
if(EnableRSIScalpingMU)
DeinitRSIScalping(rsMUData);
if(EnableRSISecretSauce)
DeinitRSISecretSauce(rssData);
if(EnableSuperEMA)
DeinitSuperEMA(seData);
if(EnableRSIConsolidation)
DeinitRSIConsolidation(rcoData);
if(EnableRSIReversalAsianEURUSD)
DeinitRSIReversalAsian(rraEURUSDData);
if(EnableRSIReversalAsianAUDUSD)
DeinitRSIReversalAsian(rraAUDUSDData);
if(EnableSimpleTrendlineBTCUSD)
DeinitSimpleTrendline(stBTCData);
if(EnableSimpleTrendlineXAUUSD)
DeinitSimpleTrendline(stXAUData);
if(EnableSimpleTrendlineGER40)
DeinitSimpleTrendline(stGERData);
Print("United EA deinitialized. Reason: ", reason);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
United_RefreshScaledLots();
if(EnableDarvasBox)
ProcessDarvasBox(DB_Symbol);
if(EnableEMASlopeDistance)
ProcessEMASlopeDistance(ES_Symbol);
if(EnableRSICrossOverReversal)
ProcessRSICrossOverReversal(RC_Symbol);
if(EnableRSIMidPointHijack)
ProcessRSIMidPointHijack(RM_Symbol);
if(EnableRSIScalpingAPPL)
ProcessRSIScalping(rsAPPLData, RS_APPL_Symbol, RS_APPL_TimeFrame, RS_APPL_RSI_Period, RS_APPL_RSI_Applied_Price,
RS_APPL_RSI_Overbought, RS_APPL_RSI_Oversold, RS_APPL_RSI_Target_Buy, RS_APPL_RSI_Target_Sell,
RS_APPL_BarsToWait, g_Pos_RS_APPL, RS_APPL_MagicNumber,
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult,
RS_APPL_UseTrailingStop, RS_APPL_TrailDistancePoints, RS_APPL_TrailActivationPoints);
if(EnableRSIScalpingBTCUSD)
ProcessRSIScalping(rsBTCUSDData, RS_BTCUSD_Symbol, RS_BTCUSD_TimeFrame, RS_BTCUSD_RSI_Period, RS_BTCUSD_RSI_Applied_Price,
RS_BTCUSD_RSI_Overbought, RS_BTCUSD_RSI_Oversold, RS_BTCUSD_RSI_Target_Buy, RS_BTCUSD_RSI_Target_Sell,
RS_BTCUSD_BarsToWait, g_Pos_RS_BTCUSD, RS_BTCUSD_MagicNumber,
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult,
RS_BTCUSD_UseTrailingStop, RS_BTCUSD_TrailDistancePoints, RS_BTCUSD_TrailActivationPoints);
if(EnableRSIScalpingNVDA)
ProcessRSIScalping(rsNVDAData, RS_NVDA_Symbol, RS_NVDA_TimeFrame, RS_NVDA_RSI_Period, RS_NVDA_RSI_Applied_Price,
RS_NVDA_RSI_Overbought, RS_NVDA_RSI_Oversold, RS_NVDA_RSI_Target_Buy, RS_NVDA_RSI_Target_Sell,
RS_NVDA_BarsToWait, g_Pos_RS_NVDA, RS_NVDA_MagicNumber,
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult,
RS_NVDA_UseTrailingStop, RS_NVDA_TrailDistancePoints, RS_NVDA_TrailActivationPoints);
if(EnableRSIScalpingTSLA)
ProcessRSIScalping(rsTSLAData, RS_TSLA_Symbol, RS_TSLA_TimeFrame, RS_TSLA_RSI_Period, RS_TSLA_RSI_Applied_Price,
RS_TSLA_RSI_Overbought, RS_TSLA_RSI_Oversold, RS_TSLA_RSI_Target_Buy, RS_TSLA_RSI_Target_Sell,
RS_TSLA_BarsToWait, g_Pos_RS_TSLA, RS_TSLA_MagicNumber,
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult,
RS_TSLA_UseTrailingStop, RS_TSLA_TrailDistancePoints, RS_TSLA_TrailActivationPoints);
if(EnableRSIScalpingXAUUSD)
ProcessRSIScalping(rsXAUUSDData, RS_XAUUSD_Symbol, RS_XAUUSD_TimeFrame, RS_XAUUSD_RSI_Period, RS_XAUUSD_RSI_Applied_Price,
RS_XAUUSD_RSI_Overbought, RS_XAUUSD_RSI_Oversold, RS_XAUUSD_RSI_Target_Buy, RS_XAUUSD_RSI_Target_Sell,
RS_XAUUSD_BarsToWait, g_Pos_RS_XAUUSD, RS_XAUUSD_MagicNumber,
RS_UseReversalEscape, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult,
RS_XAUUSD_UseTrailingStop, RS_XAUUSD_TrailDistancePoints, RS_XAUUSD_TrailActivationPoints);
if(EnableRSIScalpingMU)
ProcessRSIScalping(rsMUData, RS_MU_Symbol, RS_MU_TimeFrame, RS_MU_RSI_Period, RS_MU_RSI_Applied_Price,
RS_MU_RSI_Overbought, RS_MU_RSI_Oversold, RS_MU_RSI_Target_Buy, RS_MU_RSI_Target_Sell,
RS_MU_BarsToWait, g_Pos_RS_MU, RS_MU_MagicNumber,
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult,
false, 0.0, 0.0);
if(EnableRSISecretSauce)
ProcessRSISecretSauce(rssData, g_RSS_LotSize);
if(EnableRSIReversalAsianEURUSD)
ProcessRSIReversalAsian(rraEURUSDData, g_Pos_RRA_EURUSD);
if(EnableRSIReversalAsianAUDUSD)
ProcessRSIReversalAsian(rraAUDUSDData, g_Pos_RRA_AUDUSD);
if(EnableSuperEMA)
ProcessSuperEMA(seData, g_Pos_SE);
if(EnableRSIConsolidation)
ProcessRSIConsolidation(rcoData, g_Pos_RCO);
if(EnableSimpleTrendlineBTCUSD)
ProcessSimpleTrendline(stBTCData, g_Pos_ST_BTCUSD);
if(EnableSimpleTrendlineXAUUSD)
ProcessSimpleTrendline(stXAUData, g_Pos_ST_XAUUSD);
if(EnableSimpleTrendlineGER40)
ProcessSimpleTrendline(stGERData, g_Pos_ST_GER40);
}
//+------------------------------------------------------------------+
Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

+613
View File
@@ -0,0 +1,613 @@
//+------------------------------------------------------------------+
//| 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 strict
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Indicators\Trend.mqh>
#include <Indicators\Volumes.mqh>
#include "MagicNumberHelpers.mqh"
//+------------------------------------------------------------------+
//| Strategy Enable/Disable Switches |
//+------------------------------------------------------------------+
input group "=== Strategy Enable/Disable ==="
input bool EnableDarvasBox = true;
input bool EnableEMASlopeDistance = true;
input bool EnableRSICrossOverReversal = true;
input bool EnableRSIMidPointHijack = true;
input bool EnableRSIScalpingAPPL = true;
input bool EnableRSIScalpingBTCUSD = true;
input bool EnableRSIScalpingMSFT = true;
input bool EnableRSIScalpingNVDA = true;
input bool EnableRSIScalpingTSLA = true;
input bool EnableRSIScalpingXAUUSD = true;
//+------------------------------------------------------------------+
//| Strategy 1: DarvasBoxXAUUSD |
//+------------------------------------------------------------------+
input group "=== DarvasBox Strategy ==="
input string DB_Symbol = "XAUUSD";
input int DB_BoxPeriod = 165;
input double DB_BoxDeviation = 30000; // Increased to allow larger ranges (was 25140)
input int DB_VolumeThreshold = 0; // Set to 0 to disable volume threshold check. Volume data from indicator used instead.
input double DB_StopLoss = 1665;
input double DB_TakeProfit = 3685;
input bool DB_EnableLogging = false;
input color DB_BoxColor = clrBlue;
input int DB_BoxWidth = 1;
input ENUM_TIMEFRAMES DB_TrendTimeframe = PERIOD_H2;
input int DB_MA_Period = 125;
input ENUM_MA_METHOD DB_MA_Method = MODE_EMA;
input ENUM_APPLIED_PRICE DB_MA_Price = PRICE_WEIGHTED;
input double DB_TrendThreshold = 4.94;
input int DB_VolumeMA_Period = 110;
input double DB_VolumeThresholdMultiplier = 1.5;
input int DB_MagicNumber = 135790;
//+------------------------------------------------------------------+
//| Strategy 2: EMASlopeDistanceCocktailXAUUSD |
//| PEPPERSTONE US: Gold symbol is typically "XAUUSD" or "GOLD" |
//+------------------------------------------------------------------+
input group "=== EMA Slope Distance Strategy ==="
input string ES_Symbol = "XAUUSD";
input int ES_EMA_Periode = 46;
input double ES_PreisSchwelle = 600.0;
input double ES_SteigungSchwelle = 80.0;
input int ES_ÜberwachungTimeout = 800;
input double ES_TrailingStop = 370.0;
input bool ES_UseTrailingStop = true;
input double ES_TrailingActivationPips = 0.0;
input bool ES_UseStaleStopLossExit = false;
input int ES_StaleStopLossSeconds = 33800;
input double ES_LotGröße = 0.03;
input int ES_MagicNumber = 12350;
input bool ES_UseSpreadAdjustment = true;
input ENUM_TIMEFRAMES ES_Timeframe = PERIOD_H1;
input bool ES_UseBarData = true;
input int ES_MaxTradesPerCrossover = 9;
input int ES_ProfitCheckBars = 18;
input bool ES_CloseUnprofitableTrades = true;
input bool ES_UseWeeklyADXFilter = true;
input int ES_WeeklyADXPeriod = 15;
input double ES_WeeklyADXMin = 40.0;
input int ES_WeeklyADXBarShift = 2;
input bool ES_WeeklyADXUseDirection = true;
//+------------------------------------------------------------------+
//| Strategy 3: RSICrossOverReversalXAUUSD |
//| PEPPERSTONE US: Gold symbol is typically "XAUUSD" or "GOLD" |
//+------------------------------------------------------------------+
input group "=== RSI CrossOver Reversal Strategy ==="
input string RC_Symbol = "XAUUSD";
input int RC_MagicNumber = 7;
input int RC_rsiPeriod = 19;
input int RC_overboughtLevel = 93;
input int RC_oversoldLevel = 22;
input double RC_entryRSIBuySpread = 0;
input double RC_entryRSISellSpread = 0;
input double RC_lotSize = 0.01;
input int RC_slippage = 3;
input int RC_cooldownSeconds = 209;
input ENUM_TIMEFRAMES RC_TimeFrame1 = PERIOD_M1;
input ENUM_TIMEFRAMES RC_TimeFrame2 = PERIOD_M1;
input ENUM_TIMEFRAMES RC_BarTimeFrame = PERIOD_M12;
input int RC_emaPeriod = 140;
input double RC_emaSlopeThreshold = 105;
input double RC_exitBuyRSI = 86;
input double RC_exitSellRSI = 10;
input double RC_TrailingStop = 295;
input double RC_emaDistanceThreshold = 165;
input int RC_tradingHourOneBegin = 24;
input int RC_tradingHourOneEnd = 22;
input int RC_tradingHourTwoBegin = 6;
input int RC_tradingHourTwoEnd = 19;
input bool RC_Sunday = false;
input bool RC_Monday = false;
input bool RC_Tuesday = true;
input bool RC_Wednesday = true;
input bool RC_Thursday = true;
input bool RC_Friday = false;
input bool RC_Saturday = false;
//+------------------------------------------------------------------+
//| Strategy 4: RSIMidPointHijackXAUUSD |
//| PEPPERSTONE US: Gold symbol is typically "XAUUSD" or "GOLD" |
//+------------------------------------------------------------------+
input group "=== RSI MidPoint Hijack Strategy ==="
input string RM_Symbol = "XAUUSD";
input ENUM_TIMEFRAMES RM_InpTimeframe = PERIOD_H1;
input double RM_InpLotSize = 0.02;
input int RM_InpMagicNumberRSIFollow = 1001;
input int RM_InpMagicNumberRSIReverse = 1002;
input int RM_InpMagicNumberEMACross = 1003;
input bool RM_InpEnableRSIFollow = true;
input bool RM_InpEnableRSIReverse = true;
input bool RM_InpEnableEMACross = true;
input bool RM_InpEnableStrategyLock = false;
input double RM_InpLockProfitThreshold = 0.0;
input bool RM_InpCloseOppositeTrades = false;
input int RM_InpRSIPeriod = 32;
input int RM_InpRSIOverbought = 78;
input int RM_InpRSIOversold = 46;
input int RM_InpRSIExitLevel = 44;
input int RM_InpRSIFollowStartHour = 23;
input int RM_InpRSIFollowEndHour = 8;
input bool RM_InpRSIFollowCloseOutsideHours = false;
input int RM_InpRSIReversePeriod = 59;
input int RM_InpRSIReverseOverbought = 51;
input int RM_InpRSIReverseOversold = 49;
input int RM_InpRSIReverseCrossLevel = 53;
input int RM_InpRSIReverseExitLevel = 48;
input int RM_InpRSIReverseStartHour = 7;
input int RM_InpRSIReverseEndHour = 13;
input bool RM_InpRSIReverseCloseOutsideHours = false;
input int RM_InpRSIReverseCooldownBars = 15;
input bool RM_InpRSIReverseCooldownOnLoss = true;
input int RM_InpEMAPeriod = 120;
input int RM_InpEMACrossStartHour = 8;
input int RM_InpEMACrossEndHour = 14;
input bool RM_InpEMACrossCloseOutsideHours = true;
input bool RM_InpUseEMADistanceEntry = true;
input double RM_InpEMADistancePips = 160.0;
input int RM_InpEMADistancePeriod = 26;
//+------------------------------------------------------------------+
//| Strategy 5-10: RSI Scalping Strategies |
//| Each RSI Scalping strategy trades on its own symbol: |
//| - APPL: Apple stock (AAPL) |
//| - BTCUSD: Bitcoin/USD |
//| - MSFT: Microsoft stock |
//| - NVDA: NVIDIA stock |
//| - TSLA: Tesla stock |
//| - XAUUSD: Gold/USD |
//| |
//| PEPPERSTONE US SYMBOL FORMATS: |
//| - Stocks may use: "AAPL.US", "NASDAQ:AAPL", or just "AAPL" |
//| - To find correct symbols: |
//| 1. Open Market Watch (Ctrl+M) |
//| 2. Right-click > Show All |
//| 3. Search for the stock name |
//| 4. Use the exact symbol name shown |
//+------------------------------------------------------------------+
input group "=== RSI Scalping APPL (AAPL) - Pepperstone US ==="
input string RS_APPL_Symbol = "AAPL.US"; // Try: "AAPL.US", "NASDAQ:AAPL", or "AAPL"
input ENUM_TIMEFRAMES RS_APPL_TimeFrame = PERIOD_M10;
input int RS_APPL_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_APPL_RSI_Applied_Price = PRICE_CLOSE;
input double RS_APPL_RSI_Overbought = 80;
input double RS_APPL_RSI_Oversold = 78;
input double RS_APPL_RSI_Target_Buy = 94;
input double RS_APPL_RSI_Target_Sell = 44;
input int RS_APPL_BarsToWait = 7;
input double RS_APPL_LotSize = 25;
input int RS_APPL_MagicNumber = 20001;
input int RS_APPL_Slippage = 3;
input group "=== RSI Scalping BTCUSD ==="
input string RS_BTCUSD_Symbol = "BTCUSD"; // Pepperstone may use: "BTCUSD", "BTC/USD", or "BTCUSD.c"
input ENUM_TIMEFRAMES RS_BTCUSD_TimeFrame = PERIOD_H1;
input int RS_BTCUSD_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_BTCUSD_RSI_Applied_Price = PRICE_CLOSE;
input double RS_BTCUSD_RSI_Overbought = 90;
input double RS_BTCUSD_RSI_Oversold = 73;
input double RS_BTCUSD_RSI_Target_Buy = 88;
input double RS_BTCUSD_RSI_Target_Sell = 48;
input int RS_BTCUSD_BarsToWait = 6;
input double RS_BTCUSD_LotSize = 0.1;
input int RS_BTCUSD_MagicNumber = 123459123;
input int RS_BTCUSD_Slippage = 3;
input group "=== RSI Scalping MSFT - Pepperstone US ==="
input string RS_MSFT_Symbol = "MSFT.US"; // Try: "MSFT.US", "NASDAQ:MSFT", or "MSFT"
input ENUM_TIMEFRAMES RS_MSFT_TimeFrame = PERIOD_H3;
input int RS_MSFT_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_MSFT_RSI_Applied_Price = PRICE_CLOSE;
input double RS_MSFT_RSI_Overbought = 19;
input double RS_MSFT_RSI_Oversold = 50;
input double RS_MSFT_RSI_Target_Buy = 71;
input double RS_MSFT_RSI_Target_Sell = 70;
input int RS_MSFT_BarsToWait = 1;
input double RS_MSFT_LotSize = 50;
input int RS_MSFT_MagicNumber = 20002;
input int RS_MSFT_Slippage = 3;
input group "=== RSI Scalping NVDA - Pepperstone US ==="
input string RS_NVDA_Symbol = "NVDA.US"; // Try: "NVDA.US", "NASDAQ:NVDA", or "NVDA"
input ENUM_TIMEFRAMES RS_NVDA_TimeFrame = PERIOD_M15;
input int RS_NVDA_RSI_Period = 8;
input ENUM_APPLIED_PRICE RS_NVDA_RSI_Applied_Price = PRICE_CLOSE;
input double RS_NVDA_RSI_Overbought = 36;
input double RS_NVDA_RSI_Oversold = 38;
input double RS_NVDA_RSI_Target_Buy = 90;
input double RS_NVDA_RSI_Target_Sell = 70;
input int RS_NVDA_BarsToWait = 5;
input double RS_NVDA_LotSize = 50;
input int RS_NVDA_MagicNumber = 20003;
input int RS_NVDA_Slippage = 3;
input group "=== RSI Scalping TSLA - Pepperstone US ==="
input string RS_TSLA_Symbol = "TSLA.US"; // Try: "TSLA.US", "NASDAQ:TSLA", or "TSLA"
input ENUM_TIMEFRAMES RS_TSLA_TimeFrame = PERIOD_H1;
input int RS_TSLA_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_TSLA_RSI_Applied_Price = PRICE_CLOSE;
input double RS_TSLA_RSI_Overbought = 54;
input double RS_TSLA_RSI_Oversold = 73;
input double RS_TSLA_RSI_Target_Buy = 87;
input double RS_TSLA_RSI_Target_Sell = 33;
input int RS_TSLA_BarsToWait = 1;
input double RS_TSLA_LotSize = 50;
input int RS_TSLA_MagicNumber = 125421321;
input int RS_TSLA_Slippage = 3;
input group "=== RSI Scalping XAUUSD ==="
input string RS_XAUUSD_Symbol = "XAUUSD";
input ENUM_TIMEFRAMES RS_XAUUSD_TimeFrame = PERIOD_H1;
input int RS_XAUUSD_RSI_Period = 14;
input ENUM_APPLIED_PRICE RS_XAUUSD_RSI_Applied_Price = PRICE_CLOSE;
input double RS_XAUUSD_RSI_Overbought = 71;
input double RS_XAUUSD_RSI_Oversold = 57;
input double RS_XAUUSD_RSI_Target_Buy = 80;
input double RS_XAUUSD_RSI_Target_Sell = 57;
input int RS_XAUUSD_BarsToWait = 4;
input double RS_XAUUSD_LotSize = 0.1;
input int RS_XAUUSD_MagicNumber = 129102315;
input int RS_XAUUSD_Slippage = 3;
input group "=== RSI Scalping Reversal escape (XAUUSD) ==="
input bool RS_UseReversalEscape = false;
input int RS_ReversalATRPeriod = 14;
input double RS_ReversalAdverseAtrMult = 5.25;
input int RS_ReversalSignsRequired = 2;
input double RS_ReversalRsiVelocity = 16.0;
input double RS_ReversalBodyAtrMult = 5.1;
input group "=== RSI Scalping APPL — Trailing ==="
input bool RS_APPL_UseTrailingStop = true;
input double RS_APPL_TrailDistancePoints = 120.0;
input double RS_APPL_TrailActivationPoints = 0.0;
input group "=== RSI Scalping BTCUSD — Trailing ==="
input bool RS_BTCUSD_UseTrailingStop = true;
input double RS_BTCUSD_TrailDistancePoints = 120.0;
input double RS_BTCUSD_TrailActivationPoints = 0.0;
input group "=== RSI Scalping MSFT — Trailing ==="
input bool RS_MSFT_UseTrailingStop = true;
input double RS_MSFT_TrailDistancePoints = 375.0;
input double RS_MSFT_TrailActivationPoints = 75.0;
input group "=== RSI Scalping NVDA — Trailing ==="
input bool RS_NVDA_UseTrailingStop = true;
input double RS_NVDA_TrailDistancePoints = 375.0;
input double RS_NVDA_TrailActivationPoints = 75.0;
input group "=== RSI Scalping TSLA — Trailing ==="
input bool RS_TSLA_UseTrailingStop = true;
input double RS_TSLA_TrailDistancePoints = 900.0;
input double RS_TSLA_TrailActivationPoints = 950.0;
input group "=== RSI Scalping XAUUSD — Trailing ==="
input bool RS_XAUUSD_UseTrailingStop = true;
input double RS_XAUUSD_TrailDistancePoints = 71.0;
input double RS_XAUUSD_TrailActivationPoints = 41.0;
//+------------------------------------------------------------------+
//| Global Variables - DarvasBox |
//+------------------------------------------------------------------+
struct DarvasBoxData {
string symbol;
bool isInitialized;
double boxHigh;
double boxLow;
bool boxFormed;
datetime lastBoxTime;
string boxName;
double minStopLevel;
double point;
CTrade trade;
int maHandle;
int volumeHandle;
datetime lastBarTime;
};
//+------------------------------------------------------------------+
//| Global Variables - EMA Slope Distance |
//+------------------------------------------------------------------+
struct EMASlopeData {
string symbol;
bool isInitialized;
int ema_handle;
double ema_array[];
datetime letzte_überwachung_zeit;
bool überwachung_aktiv;
bool preis_trigger_aktiv;
bool steigung_trigger_aktiv;
int ticket;
CTrade trade;
int trades_in_current_crossover;
bool crossover_detected;
datetime trade_open_time;
datetime last_bar_time;
datetime es_last_sl_adjust_success_time;
};
//+------------------------------------------------------------------+
//| Global Variables - RSI CrossOver Reversal |
//+------------------------------------------------------------------+
struct RSICrossOverData {
string symbol;
bool isInitialized;
int rsiHandle;
int emaHandle;
double previousRSIDef;
CTrade trade;
datetime lastTradeTime;
datetime bartime;
bool WeekDays[7];
datetime lastBarTime;
};
//+------------------------------------------------------------------+
//| Global Variables - RSI MidPoint Hijack |
//+------------------------------------------------------------------+
struct RSIMidPointData {
string symbol;
bool isInitialized;
int rsiHandle;
int rsiReverseHandle;
int emaHandle;
bool rsiOverbought;
bool rsiOversold;
bool rsiReverseOverbought;
bool rsiReverseOversold;
CTrade trade;
CPositionInfo positionInfo;
bool emaCrossBuySignal;
bool emaCrossSellSignal;
int emaCrossSignalBar;
datetime lastBarTime;
datetime rsiReverseLastCloseTime;
bool rsiReverseInCooldown;
double lastBarRSI;
double lastBarRSIReverse;
double lastBarEMA;
double lastBarClose;
double lastBarEMAPrev;
double lastBarClosePrev;
};
//+------------------------------------------------------------------+
//| Global Variables - RSI Scalping |
//+------------------------------------------------------------------+
struct RSIScalpingData {
string symbol;
bool isInitialized;
CTrade trade;
int rsi_handle;
double rsi_buffer[];
double rsi_prev;
double rsi_current;
double rsi_two_bars_ago;
bool position_open;
ulong position_ticket;
ENUM_POSITION_TYPE current_position_type;
datetime last_bar_time;
bool rsi_against_position;
int bars_against_count;
};
//+------------------------------------------------------------------+
//| Global Strategy Instances |
//+------------------------------------------------------------------+
DarvasBoxData dbData;
EMASlopeData esData;
RSICrossOverData rcData;
RSIMidPointData rmData;
RSIScalpingData rsAPPLData;
RSIScalpingData rsBTCUSDData;
RSIScalpingData rsMSFTData;
RSIScalpingData rsNVDAData;
RSIScalpingData rsTSLAData;
RSIScalpingData rsXAUUSDData;
//+------------------------------------------------------------------+
//| Global Variables for lot sizes (from inputs below) |
//+------------------------------------------------------------------+
double g_DB_LotSize = 0.01;
double g_ES_LotSize;
double g_RC_LotSize;
double g_RM_LotSize;
double g_RS_APPL_LotSize;
double g_RS_BTCUSD_LotSize;
double g_RS_MSFT_LotSize;
double g_RS_NVDA_LotSize;
double g_RS_TSLA_LotSize;
double g_RS_XAUUSD_LotSize;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
int initResult = INIT_SUCCEEDED;
g_ES_LotSize = ES_LotGröße;
g_RC_LotSize = RC_lotSize;
g_RM_LotSize = RM_InpLotSize;
g_RS_APPL_LotSize = RS_APPL_LotSize;
g_RS_BTCUSD_LotSize = RS_BTCUSD_LotSize;
g_RS_MSFT_LotSize = RS_MSFT_LotSize;
g_RS_NVDA_LotSize = RS_NVDA_LotSize;
g_RS_TSLA_LotSize = RS_TSLA_LotSize;
g_RS_XAUUSD_LotSize = RS_XAUUSD_LotSize;
if(EnableDarvasBox)
if(!InitDarvasBox(DB_Symbol))
Print("Warning: DarvasBox strategy failed to initialize for symbol '", DB_Symbol, "'");
if(EnableEMASlopeDistance)
if(!InitEMASlopeDistance(ES_Symbol))
Print("Warning: EMASlopeDistance strategy failed to initialize for symbol '", ES_Symbol, "'");
if(EnableRSICrossOverReversal)
if(!InitRSICrossOverReversal(RC_Symbol))
Print("Warning: RSICrossOverReversal strategy failed to initialize for symbol '", RC_Symbol, "'");
if(EnableRSIMidPointHijack)
if(!InitRSIMidPointHijack(RM_Symbol))
Print("Warning: RSIMidPointHijack strategy failed to initialize for symbol '", RM_Symbol, "'");
if(EnableRSIScalpingAPPL)
InitRSIScalping(rsAPPLData, RS_APPL_Symbol, RS_APPL_TimeFrame, RS_APPL_RSI_Period, RS_APPL_RSI_Applied_Price, RS_APPL_MagicNumber, RS_APPL_Slippage);
if(EnableRSIScalpingBTCUSD)
InitRSIScalping(rsBTCUSDData, RS_BTCUSD_Symbol, RS_BTCUSD_TimeFrame, RS_BTCUSD_RSI_Period, RS_BTCUSD_RSI_Applied_Price, RS_BTCUSD_MagicNumber, RS_BTCUSD_Slippage);
if(EnableRSIScalpingMSFT)
InitRSIScalping(rsMSFTData, RS_MSFT_Symbol, RS_MSFT_TimeFrame, RS_MSFT_RSI_Period, RS_MSFT_RSI_Applied_Price, RS_MSFT_MagicNumber, RS_MSFT_Slippage);
if(EnableRSIScalpingNVDA)
InitRSIScalping(rsNVDAData, RS_NVDA_Symbol, RS_NVDA_TimeFrame, RS_NVDA_RSI_Period, RS_NVDA_RSI_Applied_Price, RS_NVDA_MagicNumber, RS_NVDA_Slippage);
if(EnableRSIScalpingTSLA)
InitRSIScalping(rsTSLAData, RS_TSLA_Symbol, RS_TSLA_TimeFrame, RS_TSLA_RSI_Period, RS_TSLA_RSI_Applied_Price, RS_TSLA_MagicNumber, RS_TSLA_Slippage);
if(EnableRSIScalpingXAUUSD)
InitRSIScalping(rsXAUUSDData, RS_XAUUSD_Symbol, RS_XAUUSD_TimeFrame, RS_XAUUSD_RSI_Period, RS_XAUUSD_RSI_Applied_Price, RS_XAUUSD_MagicNumber, RS_XAUUSD_Slippage);
Print("United EA (self-evaluate build) initialized. Active strategies: ",
(EnableDarvasBox ? "DarvasBox " : ""),
(EnableEMASlopeDistance ? "EMASlope " : ""),
(EnableRSICrossOverReversal ? "RSICrossOver " : ""),
(EnableRSIMidPointHijack ? "RSIMidPoint " : ""),
(EnableRSIScalpingAPPL ? "RSIScalpingAPPL " : ""),
(EnableRSIScalpingBTCUSD ? "RSIScalpingBTCUSD " : ""),
(EnableRSIScalpingMSFT ? "RSIScalpingMSFT " : ""),
(EnableRSIScalpingNVDA ? "RSIScalpingNVDA " : ""),
(EnableRSIScalpingTSLA ? "RSIScalpingTSLA " : ""),
(EnableRSIScalpingXAUUSD ? "RSIScalpingXAUUSD " : ""));
return initResult;
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
if(EnableDarvasBox)
DeinitDarvasBox();
if(EnableEMASlopeDistance)
DeinitEMASlopeDistance();
if(EnableRSICrossOverReversal)
DeinitRSICrossOverReversal();
if(EnableRSIMidPointHijack)
DeinitRSIMidPointHijack();
if(EnableRSIScalpingAPPL)
DeinitRSIScalping(rsAPPLData);
if(EnableRSIScalpingBTCUSD)
DeinitRSIScalping(rsBTCUSDData);
if(EnableRSIScalpingMSFT)
DeinitRSIScalping(rsMSFTData);
if(EnableRSIScalpingNVDA)
DeinitRSIScalping(rsNVDAData);
if(EnableRSIScalpingTSLA)
DeinitRSIScalping(rsTSLAData);
if(EnableRSIScalpingXAUUSD)
DeinitRSIScalping(rsXAUUSDData);
Print("United EA deinitialized. Reason: ", reason);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
if(EnableDarvasBox)
ProcessDarvasBox(DB_Symbol);
if(EnableEMASlopeDistance)
ProcessEMASlopeDistance(ES_Symbol);
if(EnableRSICrossOverReversal)
ProcessRSICrossOverReversal(RC_Symbol);
if(EnableRSIMidPointHijack)
ProcessRSIMidPointHijack(RM_Symbol);
if(EnableRSIScalpingAPPL)
ProcessRSIScalping(rsAPPLData, RS_APPL_Symbol, RS_APPL_TimeFrame, RS_APPL_RSI_Period, RS_APPL_RSI_Applied_Price,
RS_APPL_RSI_Overbought, RS_APPL_RSI_Oversold, RS_APPL_RSI_Target_Buy, RS_APPL_RSI_Target_Sell,
RS_APPL_BarsToWait, g_RS_APPL_LotSize, RS_APPL_MagicNumber,
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult,
RS_APPL_UseTrailingStop, RS_APPL_TrailDistancePoints, RS_APPL_TrailActivationPoints);
if(EnableRSIScalpingBTCUSD)
ProcessRSIScalping(rsBTCUSDData, RS_BTCUSD_Symbol, RS_BTCUSD_TimeFrame, RS_BTCUSD_RSI_Period, RS_BTCUSD_RSI_Applied_Price,
RS_BTCUSD_RSI_Overbought, RS_BTCUSD_RSI_Oversold, RS_BTCUSD_RSI_Target_Buy, RS_BTCUSD_RSI_Target_Sell,
RS_BTCUSD_BarsToWait, g_RS_BTCUSD_LotSize, RS_BTCUSD_MagicNumber,
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult,
RS_BTCUSD_UseTrailingStop, RS_BTCUSD_TrailDistancePoints, RS_BTCUSD_TrailActivationPoints);
if(EnableRSIScalpingMSFT)
ProcessRSIScalping(rsMSFTData, RS_MSFT_Symbol, RS_MSFT_TimeFrame, RS_MSFT_RSI_Period, RS_MSFT_RSI_Applied_Price,
RS_MSFT_RSI_Overbought, RS_MSFT_RSI_Oversold, RS_MSFT_RSI_Target_Buy, RS_MSFT_RSI_Target_Sell,
RS_MSFT_BarsToWait, g_RS_MSFT_LotSize, RS_MSFT_MagicNumber,
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult,
RS_MSFT_UseTrailingStop, RS_MSFT_TrailDistancePoints, RS_MSFT_TrailActivationPoints);
if(EnableRSIScalpingNVDA)
ProcessRSIScalping(rsNVDAData, RS_NVDA_Symbol, RS_NVDA_TimeFrame, RS_NVDA_RSI_Period, RS_NVDA_RSI_Applied_Price,
RS_NVDA_RSI_Overbought, RS_NVDA_RSI_Oversold, RS_NVDA_RSI_Target_Buy, RS_NVDA_RSI_Target_Sell,
RS_NVDA_BarsToWait, g_RS_NVDA_LotSize, RS_NVDA_MagicNumber,
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult,
RS_NVDA_UseTrailingStop, RS_NVDA_TrailDistancePoints, RS_NVDA_TrailActivationPoints);
if(EnableRSIScalpingTSLA)
ProcessRSIScalping(rsTSLAData, RS_TSLA_Symbol, RS_TSLA_TimeFrame, RS_TSLA_RSI_Period, RS_TSLA_RSI_Applied_Price,
RS_TSLA_RSI_Overbought, RS_TSLA_RSI_Oversold, RS_TSLA_RSI_Target_Buy, RS_TSLA_RSI_Target_Sell,
RS_TSLA_BarsToWait, g_RS_TSLA_LotSize, RS_TSLA_MagicNumber,
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult,
RS_TSLA_UseTrailingStop, RS_TSLA_TrailDistancePoints, RS_TSLA_TrailActivationPoints);
if(EnableRSIScalpingXAUUSD)
ProcessRSIScalping(rsXAUUSDData, RS_XAUUSD_Symbol, RS_XAUUSD_TimeFrame, RS_XAUUSD_RSI_Period, RS_XAUUSD_RSI_Applied_Price,
RS_XAUUSD_RSI_Overbought, RS_XAUUSD_RSI_Oversold, RS_XAUUSD_RSI_Target_Buy, RS_XAUUSD_RSI_Target_Sell,
RS_XAUUSD_BarsToWait, g_RS_XAUUSD_LotSize, RS_XAUUSD_MagicNumber,
RS_UseReversalEscape, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult,
RS_XAUUSD_UseTrailingStop, RS_XAUUSD_TrailDistancePoints, RS_XAUUSD_TrailActivationPoints);
}
//+------------------------------------------------------------------+
//| Include strategy implementations |
//+------------------------------------------------------------------+
#include "Strategies/DarvasBoxStrategy.mqh"
#include "Strategies/EMASlopeDistanceStrategy.mqh"
#include "Strategies/RSICrossOverReversalStrategy.mqh"
#include "Strategies/RSIMidPointHijackStrategy.mqh"
#include "Strategies/RSIScalpingStrategy.mqh"
//+------------------------------------------------------------------+