|
Before Width: | Height: | Size: 30 KiB |
@@ -1,82 +0,0 @@
|
||||
# MQL5 EA Improvements - Magic Number Isolation
|
||||
|
||||
## Problem
|
||||
When multiple EAs run together on the same symbol, they interfere with each other because magic numbers are not properly checked in all position-related functions.
|
||||
|
||||
## Solution
|
||||
1. Created `MagicNumberHelpers.mqh` with magic-aware helper functions
|
||||
2. Updated EAs to use these helper functions
|
||||
3. Created `_united/main.mq5` - a unified EA that runs multiple strategies together
|
||||
|
||||
## Fixed Functions
|
||||
|
||||
### Helper Functions (MagicNumberHelpers.mqh)
|
||||
- `PositionSelectByMagic()` - Select position by symbol AND magic number
|
||||
- `PositionSelectByTicketAndMagic()` - Verify ticket has correct magic number
|
||||
- `PositionExistsByMagic()` - Check if position exists with magic number
|
||||
- `GetPositionTicketByMagic()` - Get ticket by symbol and magic number
|
||||
- `ClosePositionByMagic()` - Close position with magic number verification
|
||||
- `ModifyPositionByMagic()` - Modify position with magic number verification
|
||||
- `GetPositionProfitByMagic()` - Get profit with magic number check
|
||||
- `GetPositionTypeByMagic()` - Get position type with magic number check
|
||||
- `CountPositionsByMagic()` - Count positions with specific magic number
|
||||
|
||||
## Fixed EAs
|
||||
|
||||
### RSIScalpingXAUUSD
|
||||
- ✅ Fixed `CheckExistingPosition()` to use `PositionSelectByTicketAndMagic()`
|
||||
- ✅ Fixed `ClosePosition()` to verify magic number before closing
|
||||
- ✅ Fixed entry signal check to use `PositionExistsByMagic()`
|
||||
|
||||
### MeanReversionXAUUSD
|
||||
- ✅ Fixed all `PositionSelect(_Symbol)` calls to use `PositionSelectByMagic()`
|
||||
- ✅ Fixed `SchließePosition()` to use `ClosePositionByMagic()`
|
||||
- ✅ Fixed `ÄndereStopLoss()` to use `ModifyPositionByMagic()`
|
||||
- ✅ Fixed all position existence checks to use `PositionExistsByMagic()`
|
||||
|
||||
## United EA
|
||||
|
||||
The `_united/main.mq5` EA allows running multiple strategies together:
|
||||
- Each strategy has its own unique magic number
|
||||
- Strategies operate independently without interference
|
||||
- Can enable/disable individual strategies via input parameters
|
||||
- Currently implements:
|
||||
- RSI Scalping Strategy
|
||||
- Mean Reversion Strategy
|
||||
- Framework for additional strategies (DarvasBox, RSICrossOver, RSIMidPoint)
|
||||
|
||||
## Usage
|
||||
|
||||
### For Individual EAs
|
||||
Simply include the helper file:
|
||||
```mql5
|
||||
#include "../_united/MagicNumberHelpers.mqh"
|
||||
```
|
||||
|
||||
Then replace:
|
||||
- `PositionSelect(_Symbol)` → `PositionSelectByMagic(_Symbol, MagicNumber)`
|
||||
- `PositionSelectByTicket(ticket)` → `PositionSelectByTicketAndMagic(ticket, MagicNumber)`
|
||||
- `trade.PositionClose(_Symbol)` → `ClosePositionByMagic(trade, _Symbol, MagicNumber)`
|
||||
- `trade.PositionModify(_Symbol, ...)` → `ModifyPositionByMagic(trade, _Symbol, MagicNumber, ...)`
|
||||
|
||||
### For United EA
|
||||
1. Set unique magic numbers for each strategy
|
||||
2. Enable/disable strategies via input parameters
|
||||
3. Configure strategy-specific parameters
|
||||
4. Run on chart - all enabled strategies will operate independently
|
||||
|
||||
## Remaining EAs to Fix
|
||||
|
||||
The following EAs should be updated similarly:
|
||||
- DarvasBoxXAUUSD
|
||||
- RSICrossOverReversalXAUUSD
|
||||
- RSIMidPointHijackXAUUSD
|
||||
- EMASlopeDistanceCocktailXAUUSD
|
||||
- All RSIScalping variants (APPL, BTCUSD, MSFT, NVDA, TSLA)
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Always use magic-aware functions** when checking/modifying positions
|
||||
2. **Set unique magic numbers** for each EA instance
|
||||
3. **Verify magic number** before any position operation
|
||||
4. **Use United EA** when running multiple strategies on same symbol
|
||||
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 8.3 KiB |
@@ -1,346 +0,0 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DeepMarkovRegimeModel.mqh |
|
||||
//| Hierarchical latent Markov stack + online regime-conditioned |
|
||||
//| RSI parameter blending and self-tuning from trade feedback. |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2026"
|
||||
#property strict
|
||||
|
||||
#define DMR_NUM_STATES 4
|
||||
|
||||
void DMR_NormalizePi(double &p[])
|
||||
{
|
||||
double s = 0.0;
|
||||
for(int i = 0; i < DMR_NUM_STATES; i++)
|
||||
s += p[i];
|
||||
if(s <= 0.0)
|
||||
{
|
||||
for(int j = 0; j < DMR_NUM_STATES; j++)
|
||||
p[j] = 1.0 / DMR_NUM_STATES;
|
||||
return;
|
||||
}
|
||||
for(int k = 0; k < DMR_NUM_STATES; k++)
|
||||
p[k] /= s;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Two-level "deep" Markov: macro volatility x micro RSI momentum |
|
||||
//| Combined state s in {0..3} = macro*2 + micro. |
|
||||
//| Belief filtered each bar; transitions learned online. |
|
||||
//+------------------------------------------------------------------+
|
||||
class CDeepMarkovRegimeModel
|
||||
{
|
||||
private:
|
||||
int m_seed;
|
||||
double m_learning_trans; // transition matrix EMA
|
||||
double m_learning_emit; // emission center EMA
|
||||
double m_learning_param; // per-state param nudge on wins
|
||||
double m_penalty_param; // nudge on losses
|
||||
|
||||
// Forward belief pi(s), row-stochastic T[s_prev][s_next]
|
||||
double m_pi[DMR_NUM_STATES];
|
||||
double m_T[DMR_NUM_STATES][DMR_NUM_STATES];
|
||||
|
||||
// Gaussian emission centers in feature space (3D): RSI/100, dRSI norm, ATR ratio
|
||||
double m_center[DMR_NUM_STATES][3];
|
||||
double m_emit_sigma; // shared diagonal sigma^2 for simplicity
|
||||
|
||||
// Per-state RSI strategy parameters (learned offsets around base inputs)
|
||||
double m_d_overbought[DMR_NUM_STATES];
|
||||
double m_d_oversold[DMR_NUM_STATES];
|
||||
double m_d_target_buy[DMR_NUM_STATES];
|
||||
double m_d_target_sell[DMR_NUM_STATES];
|
||||
double m_d_bars_scale[DMR_NUM_STATES]; // multiplicative around base BarsToWait
|
||||
|
||||
double m_base_overbought;
|
||||
double m_base_oversold;
|
||||
double m_base_target_buy;
|
||||
double m_base_target_sell;
|
||||
int m_base_bars_wait;
|
||||
|
||||
void NormalizePi()
|
||||
{
|
||||
DMR_NormalizePi(m_pi);
|
||||
}
|
||||
|
||||
void RowNormalizeT()
|
||||
{
|
||||
for(int i = 0; i < DMR_NUM_STATES; i++)
|
||||
{
|
||||
double row = 0.0;
|
||||
for(int j = 0; j < DMR_NUM_STATES; j++)
|
||||
row += m_T[i][j];
|
||||
if(row <= 0.0)
|
||||
{
|
||||
for(int j = 0; j < DMR_NUM_STATES; j++)
|
||||
m_T[i][j] = 1.0 / DMR_NUM_STATES;
|
||||
}
|
||||
else
|
||||
{
|
||||
for(int j = 0; j < DMR_NUM_STATES; j++)
|
||||
m_T[i][j] /= row;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double FeatureDist2(const double f0, const double f1, const double f2, const int state) const
|
||||
{
|
||||
double d0 = f0 - m_center[state][0];
|
||||
double d1 = f1 - m_center[state][1];
|
||||
double d2 = f2 - m_center[state][2];
|
||||
return d0 * d0 + d1 * d1 + d2 * d2;
|
||||
}
|
||||
|
||||
static double Clamp(const double x, const double lo, const double hi)
|
||||
{
|
||||
if(x < lo) return lo;
|
||||
if(x > hi) return hi;
|
||||
return x;
|
||||
}
|
||||
|
||||
public:
|
||||
CDeepMarkovRegimeModel()
|
||||
{
|
||||
m_seed = 0;
|
||||
m_learning_trans = 0.05;
|
||||
m_learning_emit = 0.02;
|
||||
m_learning_param = 0.03;
|
||||
m_penalty_param = 0.015;
|
||||
m_emit_sigma = 0.35;
|
||||
for(int i = 0; i < DMR_NUM_STATES; i++)
|
||||
{
|
||||
m_pi[i] = 1.0 / DMR_NUM_STATES;
|
||||
for(int j = 0; j < DMR_NUM_STATES; j++)
|
||||
m_T[i][j] = (i == j) ? 0.55 : 0.15;
|
||||
m_d_overbought[i] = 0.0;
|
||||
m_d_oversold[i] = 0.0;
|
||||
m_d_target_buy[i] = 0.0;
|
||||
m_d_target_sell[i] = 0.0;
|
||||
m_d_bars_scale[i] = 1.0;
|
||||
// Spread default emission prototypes across feature cube corners
|
||||
m_center[i][0] = ((i & 1) != 0) ? 0.75 : 0.35;
|
||||
m_center[i][1] = ((i & 2) != 0) ? 0.6 : 0.25;
|
||||
m_center[i][2] = (double)(i % 3) * 0.25 + 0.2;
|
||||
}
|
||||
RowNormalizeT();
|
||||
}
|
||||
|
||||
void SetLearningRates(const double lr_trans, const double lr_emit, const double lr_win, const double lr_loss)
|
||||
{
|
||||
m_learning_trans = lr_trans;
|
||||
m_learning_emit = lr_emit;
|
||||
m_learning_param = lr_win;
|
||||
m_penalty_param = lr_loss;
|
||||
}
|
||||
|
||||
void SetBaseThresholds(const double ob, const double os, const double tb, const double ts, const int bars_wait)
|
||||
{
|
||||
m_base_overbought = ob;
|
||||
m_base_oversold = os;
|
||||
m_base_target_buy = tb;
|
||||
m_base_target_sell = ts;
|
||||
m_base_bars_wait = bars_wait;
|
||||
}
|
||||
|
||||
void SetSeed(const int seed) { m_seed = seed; }
|
||||
|
||||
// f0: RSI/100, f1: tanh-like scaled delta RSI, f2: ATR short/long ratio capped
|
||||
void Update(const double f0, const double f1, const double f2)
|
||||
{
|
||||
double emit[DMR_NUM_STATES];
|
||||
double max_ll = -1.0e100;
|
||||
for(int s = 0; s < DMR_NUM_STATES; s++)
|
||||
{
|
||||
double d2 = FeatureDist2(f0, f1, f2, s);
|
||||
emit[s] = MathExp(-0.5 * d2 / (m_emit_sigma * m_emit_sigma + 1.0e-12));
|
||||
if(emit[s] > max_ll) max_ll = emit[s];
|
||||
}
|
||||
// numerical safety
|
||||
for(int s2 = 0; s2 < DMR_NUM_STATES; s2++)
|
||||
if(emit[s2] != emit[s2] || emit[s2] < 1.0e-12)
|
||||
emit[s2] = 1.0e-12;
|
||||
|
||||
double pi_new[DMR_NUM_STATES];
|
||||
for(int j = 0; j < DMR_NUM_STATES; j++)
|
||||
{
|
||||
double sum = 0.0;
|
||||
for(int i = 0; i < DMR_NUM_STATES; i++)
|
||||
sum += m_pi[i] * m_T[i][j];
|
||||
pi_new[j] = sum * emit[j];
|
||||
}
|
||||
DMR_NormalizePi(pi_new);
|
||||
|
||||
int imax_prev = ArgMaxPi();
|
||||
int imax_new = 0;
|
||||
double best = pi_new[0];
|
||||
for(int j = 1; j < DMR_NUM_STATES; j++)
|
||||
if(pi_new[j] > best)
|
||||
{
|
||||
best = pi_new[j];
|
||||
imax_new = j;
|
||||
}
|
||||
|
||||
// Online transition nudge toward observed edge imax_prev -> imax_new
|
||||
for(int j = 0; j < DMR_NUM_STATES; j++)
|
||||
m_T[imax_prev][j] *= (1.0 - m_learning_trans);
|
||||
m_T[imax_prev][imax_new] += m_learning_trans;
|
||||
RowNormalizeT();
|
||||
|
||||
// Pull emission center of dominant new state toward observation
|
||||
for(int d = 0; d < 3; d++)
|
||||
{
|
||||
double obs[3] = {f0, f1, f2};
|
||||
m_center[imax_new][d] = (1.0 - m_learning_emit) * m_center[imax_new][d] + m_learning_emit * obs[d];
|
||||
}
|
||||
|
||||
for(int k = 0; k < DMR_NUM_STATES; k++)
|
||||
m_pi[k] = pi_new[k];
|
||||
NormalizePi();
|
||||
}
|
||||
|
||||
int ArgMaxPi() const
|
||||
{
|
||||
int idx = 0;
|
||||
double best = m_pi[0];
|
||||
for(int i = 1; i < DMR_NUM_STATES; i++)
|
||||
if(m_pi[i] > best)
|
||||
{
|
||||
best = m_pi[i];
|
||||
idx = i;
|
||||
}
|
||||
return idx;
|
||||
}
|
||||
|
||||
double Belief(const int s) const
|
||||
{
|
||||
if(s < 0 || s >= DMR_NUM_STATES) return 0.0;
|
||||
return m_pi[s];
|
||||
}
|
||||
|
||||
// Blended effective thresholds (self-optimized offsets)
|
||||
double EffectiveOverbought() const
|
||||
{
|
||||
double v = 0.0;
|
||||
for(int s = 0; s < DMR_NUM_STATES; s++)
|
||||
v += m_pi[s] * (m_base_overbought + m_d_overbought[s]);
|
||||
return Clamp(v, 50.0, 95.0);
|
||||
}
|
||||
|
||||
double EffectiveOversold() const
|
||||
{
|
||||
double v = 0.0;
|
||||
for(int s = 0; s < DMR_NUM_STATES; s++)
|
||||
v += m_pi[s] * (m_base_oversold + m_d_oversold[s]);
|
||||
return Clamp(v, 5.0, 50.0);
|
||||
}
|
||||
|
||||
double EffectiveTargetBuy() const
|
||||
{
|
||||
double v = 0.0;
|
||||
for(int s = 0; s < DMR_NUM_STATES; s++)
|
||||
v += m_pi[s] * (m_base_target_buy + m_d_target_buy[s]);
|
||||
return Clamp(v, 55.0, 99.0);
|
||||
}
|
||||
|
||||
double EffectiveTargetSell() const
|
||||
{
|
||||
double v = 0.0;
|
||||
for(int s = 0; s < DMR_NUM_STATES; s++)
|
||||
v += m_pi[s] * (m_base_target_sell + m_d_target_sell[s]);
|
||||
return Clamp(v, 1.0, 50.0);
|
||||
}
|
||||
|
||||
int EffectiveBarsToWait() const
|
||||
{
|
||||
double acc = 0.0;
|
||||
for(int s = 0; s < DMR_NUM_STATES; s++)
|
||||
acc += m_pi[s] * m_d_bars_scale[s];
|
||||
acc = Clamp(acc, 0.5, 2.0);
|
||||
int b = (int)MathRound((double)m_base_bars_wait * acc);
|
||||
return (int)Clamp((double)b, 1.0, 20.0);
|
||||
}
|
||||
|
||||
// Reinforce or soften parameters for the regime active at entry
|
||||
void OnTradeClosed(const int dominant_state_at_entry, const double profit_money)
|
||||
{
|
||||
if(dominant_state_at_entry < 0 || dominant_state_at_entry >= DMR_NUM_STATES)
|
||||
return;
|
||||
const int s = dominant_state_at_entry;
|
||||
const double mag = MathMin(1.0, MathAbs(profit_money) / 100.0 + 0.2);
|
||||
if(profit_money > 0.0)
|
||||
{
|
||||
// Slightly widen capture: push targets outward in favorable direction
|
||||
m_d_target_buy[s] += m_learning_param * mag * 0.5;
|
||||
m_d_target_sell[s] -= m_learning_param * mag * 0.5;
|
||||
m_d_overbought[s] += m_learning_param * mag * 0.25;
|
||||
m_d_oversold[s] -= m_learning_param * mag * 0.25;
|
||||
m_d_bars_scale[s] += m_learning_param * 0.05 * mag;
|
||||
}
|
||||
else if(profit_money < 0.0)
|
||||
{
|
||||
// Tighten: mean-revert offsets toward 0 and shorten patience
|
||||
m_d_target_buy[s] *= (1.0 - m_penalty_param * mag);
|
||||
m_d_target_sell[s] *= (1.0 - m_penalty_param * mag);
|
||||
m_d_overbought[s] *= (1.0 - m_penalty_param * mag);
|
||||
m_d_oversold[s] *= (1.0 - m_penalty_param * mag);
|
||||
m_d_bars_scale[s] -= m_penalty_param * 0.05 * mag;
|
||||
}
|
||||
for(int i = 0; i < DMR_NUM_STATES; i++)
|
||||
{
|
||||
m_d_overbought[i] = Clamp(m_d_overbought[i], -15.0, 15.0);
|
||||
m_d_oversold[i] = Clamp(m_d_oversold[i], -15.0, 15.0);
|
||||
m_d_target_buy[i] = Clamp(m_d_target_buy[i], -20.0, 20.0);
|
||||
m_d_target_sell[i] = Clamp(m_d_target_sell[i], -20.0, 20.0);
|
||||
m_d_bars_scale[i] = Clamp(m_d_bars_scale[i], 0.5, 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
string DebugStateLine() const
|
||||
{
|
||||
string t = StringFormat("DMR pi=[%.2f,%.2f,%.2f,%.2f] OB=%.1f OS=%.1f TB=%.1f TS=%.1f BW=%d",
|
||||
m_pi[0], m_pi[1], m_pi[2], m_pi[3],
|
||||
EffectiveOverbought(), EffectiveOversold(),
|
||||
EffectiveTargetBuy(), EffectiveTargetSell(),
|
||||
EffectiveBarsToWait());
|
||||
return t;
|
||||
}
|
||||
|
||||
bool SaveToGlobals(const string prefix) const
|
||||
{
|
||||
string p = prefix + IntegerToString(m_seed) + "_";
|
||||
GlobalVariableSet(p + "pi0", m_pi[0]);
|
||||
GlobalVariableSet(p + "pi1", m_pi[1]);
|
||||
GlobalVariableSet(p + "pi2", m_pi[2]);
|
||||
GlobalVariableSet(p + "pi3", m_pi[3]);
|
||||
for(int i = 0; i < DMR_NUM_STATES; i++)
|
||||
{
|
||||
GlobalVariableSet(p + "dob" + IntegerToString(i), m_d_overbought[i]);
|
||||
GlobalVariableSet(p + "dos" + IntegerToString(i), m_d_oversold[i]);
|
||||
GlobalVariableSet(p + "dtb" + IntegerToString(i), m_d_target_buy[i]);
|
||||
GlobalVariableSet(p + "dts" + IntegerToString(i), m_d_target_sell[i]);
|
||||
GlobalVariableSet(p + "dbs" + IntegerToString(i), m_d_bars_scale[i]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LoadFromGlobals(const string prefix)
|
||||
{
|
||||
string p = prefix + IntegerToString(m_seed) + "_";
|
||||
if(!GlobalVariableCheck(p + "pi0"))
|
||||
return false;
|
||||
m_pi[0] = GlobalVariableGet(p + "pi0");
|
||||
m_pi[1] = GlobalVariableGet(p + "pi1");
|
||||
m_pi[2] = GlobalVariableGet(p + "pi2");
|
||||
m_pi[3] = GlobalVariableGet(p + "pi3");
|
||||
for(int i = 0; i < DMR_NUM_STATES; i++)
|
||||
{
|
||||
m_d_overbought[i] = GlobalVariableGet(p + "dob" + IntegerToString(i));
|
||||
m_d_oversold[i] = GlobalVariableGet(p + "dos" + IntegerToString(i));
|
||||
m_d_target_buy[i] = GlobalVariableGet(p + "dtb" + IntegerToString(i));
|
||||
m_d_target_sell[i] = GlobalVariableGet(p + "dts" + IntegerToString(i));
|
||||
m_d_bars_scale[i] = GlobalVariableGet(p + "dbs" + IntegerToString(i));
|
||||
}
|
||||
NormalizePi();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
@@ -1,350 +0,0 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RSIScalpingXAUUSD_DeepMarkov.mq5 |
|
||||
//| RSI scalping with online deep Markov regime filter + self-tune. |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2026"
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include "MagicNumberHelpers.mqh"
|
||||
#include "DeepMarkovRegimeModel.mqh"
|
||||
|
||||
//--- Input parameters
|
||||
input group "=== Chart / RSI ==="
|
||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1;
|
||||
input int RSI_Period = 14;
|
||||
input ENUM_APPLIED_PRICE RSI_Applied_Price = PRICE_CLOSE;
|
||||
|
||||
input group "=== Base RSI levels (Markov blends & learns offsets) ==="
|
||||
input double RSI_Overbought = 71;
|
||||
input double RSI_Oversold = 57;
|
||||
input double RSI_Target_Buy = 80;
|
||||
input double RSI_Target_Sell = 57;
|
||||
input int BarsToWait = 4;
|
||||
|
||||
input group "=== Execution ==="
|
||||
input double LotSize = 0.1;
|
||||
input int MagicNumber = 129102316;
|
||||
input int Slippage = 3;
|
||||
|
||||
input group "=== Deep Markov self-optimization ==="
|
||||
input double DMR_LearnTransition = 0.05;
|
||||
input double DMR_LearnEmission = 0.02;
|
||||
input double DMR_LearnWin = 0.03;
|
||||
input double DMR_LearnLoss = 0.015;
|
||||
input bool DMR_PersistGlobals = true;
|
||||
input string DMR_GlobalPrefix = "DMR_XAU_";
|
||||
input bool DMR_LogEachBar = false;
|
||||
|
||||
//--- Global variables
|
||||
CTrade trade;
|
||||
CDeepMarkovRegimeModel g_dm;
|
||||
|
||||
int rsi_handle;
|
||||
int atr_fast_handle;
|
||||
int atr_slow_handle;
|
||||
double rsi_buffer[];
|
||||
double rsi_prev, rsi_current, rsi_two_bars_ago;
|
||||
double atr_fast, atr_slow;
|
||||
|
||||
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;
|
||||
|
||||
int entry_regime = 0;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
rsi_handle = iRSI(_Symbol, TimeFrame, RSI_Period, RSI_Applied_Price);
|
||||
if(rsi_handle == INVALID_HANDLE)
|
||||
return(INIT_FAILED);
|
||||
|
||||
atr_fast_handle = iATR(_Symbol, TimeFrame, 8);
|
||||
atr_slow_handle = iATR(_Symbol, TimeFrame, 34);
|
||||
if(atr_fast_handle == INVALID_HANDLE || atr_slow_handle == INVALID_HANDLE)
|
||||
return(INIT_FAILED);
|
||||
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
trade.SetDeviationInPoints(Slippage);
|
||||
trade.SetTypeFilling(ORDER_FILLING_FOK);
|
||||
|
||||
ArraySetAsSeries(rsi_buffer, true);
|
||||
|
||||
g_dm.SetSeed(MagicNumber);
|
||||
g_dm.SetLearningRates(DMR_LearnTransition, DMR_LearnEmission, DMR_LearnWin, DMR_LearnLoss);
|
||||
g_dm.SetBaseThresholds(RSI_Overbought, RSI_Oversold, RSI_Target_Buy, RSI_Target_Sell, BarsToWait);
|
||||
|
||||
if(DMR_PersistGlobals)
|
||||
{
|
||||
if(g_dm.LoadFromGlobals(DMR_GlobalPrefix))
|
||||
Print("RSIScalpingXAUUSD_DeepMarkov: loaded persisted Markov state from globals.");
|
||||
}
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
if(DMR_PersistGlobals)
|
||||
g_dm.SaveToGlobals(DMR_GlobalPrefix);
|
||||
|
||||
if(rsi_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(rsi_handle);
|
||||
if(atr_fast_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(atr_fast_handle);
|
||||
if(atr_slow_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(atr_slow_handle);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
if(Bars(_Symbol, TimeFrame) < RSI_Period + 5)
|
||||
return;
|
||||
|
||||
datetime current_bar_time = iTime(_Symbol, TimeFrame, 0);
|
||||
if(current_bar_time == last_bar_time)
|
||||
return;
|
||||
|
||||
last_bar_time = current_bar_time;
|
||||
|
||||
if(!UpdateRSI())
|
||||
return;
|
||||
|
||||
if(!UpdateATR())
|
||||
return;
|
||||
|
||||
const double f0 = rsi_current / 100.0;
|
||||
const double dr = rsi_current - rsi_prev;
|
||||
const double f1 = MathTanh(dr / 10.0) * 0.5 + 0.5;
|
||||
double ratio = 1.0;
|
||||
if(atr_slow > 1.0e-12)
|
||||
ratio = atr_fast / atr_slow;
|
||||
if(ratio < 0.15)
|
||||
ratio = 0.15;
|
||||
if(ratio > 2.5)
|
||||
ratio = 2.5;
|
||||
const double f2 = ratio / 2.5;
|
||||
|
||||
g_dm.Update(f0, f1, f2);
|
||||
|
||||
if(DMR_LogEachBar)
|
||||
Print(g_dm.DebugStateLine());
|
||||
|
||||
ResyncPositionFromMarket();
|
||||
|
||||
CheckExistingPosition();
|
||||
|
||||
if(!position_open && !PositionExistsByMagic(_Symbol, (ulong)MagicNumber))
|
||||
CheckEntrySignals();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
bool UpdateRSI()
|
||||
{
|
||||
if(CopyBuffer(rsi_handle, 0, 0, 3, rsi_buffer) < 3)
|
||||
return false;
|
||||
|
||||
rsi_current = rsi_buffer[0];
|
||||
rsi_prev = rsi_buffer[1];
|
||||
rsi_two_bars_ago = rsi_buffer[2];
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
bool UpdateATR()
|
||||
{
|
||||
double af[], as[];
|
||||
ArrayResize(af, 1);
|
||||
ArrayResize(as, 1);
|
||||
ArraySetAsSeries(af, true);
|
||||
ArraySetAsSeries(as, true);
|
||||
if(CopyBuffer(atr_fast_handle, 0, 0, 1, af) < 1)
|
||||
return false;
|
||||
if(CopyBuffer(atr_slow_handle, 0, 0, 1, as) < 1)
|
||||
return false;
|
||||
atr_fast = af[0];
|
||||
atr_slow = as[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void ResyncPositionFromMarket()
|
||||
{
|
||||
if(position_open)
|
||||
return;
|
||||
ulong t = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
if(t == 0 || !PositionSelectByTicket(t))
|
||||
return;
|
||||
position_ticket = (int)t;
|
||||
position_open = true;
|
||||
current_position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
entry_regime = g_dm.ArgMaxPi();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
double EffectiveOverbought() { return g_dm.EffectiveOverbought(); }
|
||||
double EffectiveOversold() { return g_dm.EffectiveOversold(); }
|
||||
double EffectiveTargetBuy() { return g_dm.EffectiveTargetBuy(); }
|
||||
double EffectiveTargetSell() { return g_dm.EffectiveTargetSell(); }
|
||||
int EffectiveBarsToWait() { return g_dm.EffectiveBarsToWait(); }
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckExistingPosition()
|
||||
{
|
||||
if(!position_open)
|
||||
return;
|
||||
|
||||
if(!PositionSelectByTicketAndMagic((ulong)position_ticket, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const double ob = EffectiveOverbought();
|
||||
const double os = EffectiveOversold();
|
||||
const double tb = EffectiveTargetBuy();
|
||||
const double ts = EffectiveTargetSell();
|
||||
const int bw = EffectiveBarsToWait();
|
||||
|
||||
if(current_position_type == POSITION_TYPE_BUY)
|
||||
{
|
||||
if(rsi_current < os)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
bars_against_count++;
|
||||
|
||||
if(bars_against_count >= bw)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
if(rsi_current >= tb)
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
else if(current_position_type == POSITION_TYPE_SELL)
|
||||
{
|
||||
if(rsi_current > ob)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
bars_against_count++;
|
||||
|
||||
if(bars_against_count >= bw)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
if(rsi_current <= ts)
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckEntrySignals()
|
||||
{
|
||||
const double os = EffectiveOversold();
|
||||
const double ob = EffectiveOverbought();
|
||||
|
||||
if(rsi_two_bars_ago <= os && rsi_prev > os)
|
||||
OpenBuyPosition();
|
||||
|
||||
if(rsi_two_bars_ago >= ob && rsi_prev < ob)
|
||||
OpenSellPosition();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenBuyPosition()
|
||||
{
|
||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
entry_regime = g_dm.ArgMaxPi();
|
||||
|
||||
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI DM Buy"))
|
||||
{
|
||||
ulong pt = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
position_ticket = (int)pt;
|
||||
position_open = true;
|
||||
current_position_type = POSITION_TYPE_BUY;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenSellPosition()
|
||||
{
|
||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
entry_regime = g_dm.ArgMaxPi();
|
||||
|
||||
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI DM Sell"))
|
||||
{
|
||||
ulong pt = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
position_ticket = (int)pt;
|
||||
position_open = true;
|
||||
current_position_type = POSITION_TYPE_SELL;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
void ClosePosition()
|
||||
{
|
||||
double profit = 0.0;
|
||||
if(PositionSelectByTicket(position_ticket))
|
||||
profit = PositionGetDouble(POSITION_PROFIT);
|
||||
|
||||
const int regime = entry_regime;
|
||||
|
||||
if(ClosePositionByMagic(trade, _Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
g_dm.OnTradeClosed(regime, profit);
|
||||
return;
|
||||
}
|
||||
if(!PositionExistsByMagic(_Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
g_dm.OnTradeClosed(regime, profit);
|
||||
return;
|
||||
}
|
||||
Print("RSIScalpingXAUUSD_DeepMarkov: close failed (will retry). retcode=",
|
||||
trade.ResultRetcode(), " lastError=", GetLastError());
|
||||
}
|
||||
@@ -1,307 +0,0 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RSIScalpingXAUUSD_PlusHours.mq5 |
|
||||
//| Same logic as RSIScalpingXAUUSD + trading session filter |
|
||||
//| (server time), day-of-week filter, and optional close-all when |
|
||||
//| outside allowed hours/days |
|
||||
//+------------------------------------------------------------------+
|
||||
#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 group "=== RSI (same as RSIScalpingXAUUSD) ==="
|
||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1;
|
||||
input int RSI_Period = 14;
|
||||
input ENUM_APPLIED_PRICE RSI_Applied_Price = PRICE_CLOSE;
|
||||
input double RSI_Overbought = 71;
|
||||
input double RSI_Oversold = 57;
|
||||
input double RSI_Target_Buy = 80;
|
||||
input double RSI_Target_Sell = 57;
|
||||
input int BarsToWait = 4;
|
||||
input double LotSize = 0.1;
|
||||
input int MagicNumber = 129102317;
|
||||
input int Slippage = 3;
|
||||
|
||||
input group "=== Trading hours (broker server time) ==="
|
||||
input bool InpUseTradingHours = true;
|
||||
input int InpTradeHourStart = 8;
|
||||
input int InpTradeHourEnd = 22;
|
||||
input bool InpCloseOutsideTradingHours = true;
|
||||
|
||||
input group "=== Trading days (broker server time) ==="
|
||||
input bool InpUseTradingDays = true;
|
||||
input bool InpTradeMonday = true;
|
||||
input bool InpTradeTuesday = true;
|
||||
input bool InpTradeWednesday = true;
|
||||
input bool InpTradeThursday = true;
|
||||
input bool InpTradeFriday = true;
|
||||
input bool InpTradeSaturday = true;
|
||||
input bool InpTradeSunday = true;
|
||||
input bool InpCloseOutsideTradingDays = true;
|
||||
|
||||
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;
|
||||
|
||||
bool IsWithinTradingHours()
|
||||
{
|
||||
if(!InpUseTradingHours)
|
||||
return true;
|
||||
|
||||
MqlDateTime dt;
|
||||
TimeToStruct(TimeCurrent(), dt);
|
||||
const int h = dt.hour;
|
||||
const int hs = MathMax(0, MathMin(23, InpTradeHourStart));
|
||||
const int he = MathMax(0, MathMin(23, InpTradeHourEnd));
|
||||
|
||||
if(hs == he)
|
||||
return true;
|
||||
|
||||
if(hs < he)
|
||||
return (h >= hs && h < he);
|
||||
|
||||
return (h >= hs || h < he);
|
||||
}
|
||||
|
||||
bool IsTradingDayAllowed()
|
||||
{
|
||||
if(!InpUseTradingDays)
|
||||
return true;
|
||||
|
||||
MqlDateTime dt;
|
||||
TimeToStruct(TimeCurrent(), dt);
|
||||
switch(dt.day_of_week)
|
||||
{
|
||||
case 0: return InpTradeSunday;
|
||||
case 1: return InpTradeMonday;
|
||||
case 2: return InpTradeTuesday;
|
||||
case 3: return InpTradeWednesday;
|
||||
case 4: return InpTradeThursday;
|
||||
case 5: return InpTradeFriday;
|
||||
case 6: return InpTradeSaturday;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int OnInit()
|
||||
{
|
||||
rsi_handle = iRSI(_Symbol, TimeFrame, RSI_Period, RSI_Applied_Price);
|
||||
if(rsi_handle == INVALID_HANDLE)
|
||||
return(INIT_FAILED);
|
||||
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
trade.SetDeviationInPoints(Slippage);
|
||||
trade.SetTypeFilling(ORDER_FILLING_FOK);
|
||||
|
||||
ArraySetAsSeries(rsi_buffer, true);
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
if(rsi_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(rsi_handle);
|
||||
}
|
||||
|
||||
void OnTick()
|
||||
{
|
||||
if(Bars(_Symbol, TimeFrame) < RSI_Period + 2)
|
||||
return;
|
||||
|
||||
datetime current_bar_time = iTime(_Symbol, TimeFrame, 0);
|
||||
if(current_bar_time == last_bar_time)
|
||||
return;
|
||||
|
||||
last_bar_time = current_bar_time;
|
||||
|
||||
if(!UpdateRSI())
|
||||
return;
|
||||
|
||||
ResyncPositionFromMarket();
|
||||
|
||||
const bool inHours = IsWithinTradingHours();
|
||||
const bool inDays = IsTradingDayAllowed();
|
||||
const bool inSession = inHours && inDays;
|
||||
|
||||
if(position_open && !inSession &&
|
||||
((InpUseTradingHours && InpCloseOutsideTradingHours && !inHours) ||
|
||||
(InpUseTradingDays && InpCloseOutsideTradingDays && !inDays)))
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
|
||||
CheckExistingPosition();
|
||||
|
||||
if(!position_open && !PositionExistsByMagic(_Symbol, (ulong)MagicNumber) && inSession)
|
||||
CheckEntrySignals();
|
||||
}
|
||||
|
||||
bool UpdateRSI()
|
||||
{
|
||||
if(CopyBuffer(rsi_handle, 0, 0, 3, rsi_buffer) < 3)
|
||||
return false;
|
||||
|
||||
rsi_current = rsi_buffer[0];
|
||||
rsi_prev = rsi_buffer[1];
|
||||
rsi_two_bars_ago = rsi_buffer[2];
|
||||
return true;
|
||||
}
|
||||
|
||||
void ResyncPositionFromMarket()
|
||||
{
|
||||
if(position_open)
|
||||
return;
|
||||
ulong t = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
if(t == 0 || !PositionSelectByTicket(t))
|
||||
return;
|
||||
position_ticket = (int)t;
|
||||
position_open = true;
|
||||
current_position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
}
|
||||
|
||||
void CheckExistingPosition()
|
||||
{
|
||||
if(!position_open)
|
||||
return;
|
||||
|
||||
if(!PositionSelectByTicketAndMagic(position_ticket, MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(current_position_type == POSITION_TYPE_BUY)
|
||||
{
|
||||
if(rsi_current < RSI_Oversold)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
bars_against_count++;
|
||||
|
||||
if(bars_against_count >= BarsToWait)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
|
||||
if(rsi_current >= RSI_Target_Buy)
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
else if(current_position_type == POSITION_TYPE_SELL)
|
||||
{
|
||||
if(rsi_current > RSI_Overbought)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
bars_against_count++;
|
||||
|
||||
if(bars_against_count >= BarsToWait)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
|
||||
if(rsi_current <= RSI_Target_Sell)
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CheckEntrySignals()
|
||||
{
|
||||
if(rsi_two_bars_ago <= RSI_Oversold && rsi_prev > RSI_Oversold)
|
||||
OpenBuyPosition();
|
||||
|
||||
if(rsi_two_bars_ago >= RSI_Overbought && rsi_prev < RSI_Overbought)
|
||||
OpenSellPosition();
|
||||
}
|
||||
|
||||
void OpenBuyPosition()
|
||||
{
|
||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Hours Buy"))
|
||||
{
|
||||
ulong t = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
position_ticket = (int)t;
|
||||
position_open = (position_ticket != 0);
|
||||
current_position_type = POSITION_TYPE_BUY;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenSellPosition()
|
||||
{
|
||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Hours Sell"))
|
||||
{
|
||||
ulong t = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
position_ticket = (int)t;
|
||||
position_open = (position_ticket != 0);
|
||||
current_position_type = POSITION_TYPE_SELL;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void ClosePosition()
|
||||
{
|
||||
if(ClosePositionByMagic(trade, _Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
if(!PositionExistsByMagic(_Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
Print("RSIScalpingXAUUSD_PlusHours: close failed (will retry). retcode=",
|
||||
trade.ResultRetcode(), " lastError=", GetLastError());
|
||||
}
|
||||
@@ -1,367 +0,0 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RSIScalpingXAUUSD_Trailing.mq5 |
|
||||
//| Copyright 2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.06"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include "../_united/MagicNumberHelpers.mqh"
|
||||
|
||||
//--- Input parameters
|
||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1; // 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 = 71; // RSI Overbought Level
|
||||
input double RSI_Oversold = 57; // RSI Oversold Level
|
||||
input double RSI_Target_Buy = 80; // RSI Target for Buy Exit
|
||||
input double RSI_Target_Sell = 57; // RSI Target for Sell Exit
|
||||
input int BarsToWait = 4; // Bars to wait when RSI goes against position
|
||||
input bool UseRSI_StopLoss = true; // Close on RSI stop (separate timeframe below)
|
||||
input ENUM_TIMEFRAMES RSI_StopLoss_TimeFrame = PERIOD_H1; // RSI timeframe for stop-loss only
|
||||
input double RSI_StopLoss_BuyBelow = 30; // Close buy when stop-timeframe RSI drops below this
|
||||
input double RSI_StopLoss_SellAbove = 70; // Close sell when stop-timeframe RSI rises above this
|
||||
input double LotSize = 0.1; // Lot Size
|
||||
input int MagicNumber = 129102316; // Magic Number (distinct from non-trailing EA)
|
||||
input int Slippage = 3; // Slippage in points
|
||||
|
||||
//--- Global variables
|
||||
CTrade trade;
|
||||
int rsi_handle;
|
||||
int rsi_stoploss_handle = INVALID_HANDLE;
|
||||
double rsi_buffer[];
|
||||
double rsi_stoploss_buffer[];
|
||||
double rsi_prev, rsi_current, rsi_two_bars_ago;
|
||||
double rsi_stoploss_current = 0.0;
|
||||
MqlTick rsi_stoploss_last_tick;
|
||||
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()
|
||||
{
|
||||
rsi_handle = iRSI(_Symbol, TimeFrame, RSI_Period, RSI_Applied_Price);
|
||||
if(rsi_handle == INVALID_HANDLE)
|
||||
{
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
|
||||
rsi_stoploss_handle = iRSI(_Symbol, RSI_StopLoss_TimeFrame, RSI_Period, RSI_Applied_Price);
|
||||
if(rsi_stoploss_handle == INVALID_HANDLE)
|
||||
{
|
||||
IndicatorRelease(rsi_handle);
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
trade.SetDeviationInPoints(Slippage);
|
||||
trade.SetTypeFilling(ORDER_FILLING_FOK);
|
||||
|
||||
ArraySetAsSeries(rsi_buffer, true);
|
||||
ArraySetAsSeries(rsi_stoploss_buffer, true);
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
if(rsi_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(rsi_handle);
|
||||
if(rsi_stoploss_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(rsi_stoploss_handle);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
ResyncPositionFromMarket();
|
||||
|
||||
const int min_bars = RSI_Period + 2;
|
||||
if(position_open)
|
||||
{
|
||||
if(UseRSI_StopLoss && Bars(_Symbol, RSI_StopLoss_TimeFrame) >= min_bars)
|
||||
{
|
||||
if(UpdateRSI_StopLoss())
|
||||
CheckRSIStopLossClose();
|
||||
}
|
||||
}
|
||||
|
||||
if(Bars(_Symbol, TimeFrame) < min_bars)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
datetime current_bar_time = iTime(_Symbol, TimeFrame, 0);
|
||||
if(current_bar_time == last_bar_time)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
last_bar_time = current_bar_time;
|
||||
|
||||
if(!UpdateRSI())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ResyncPositionFromMarket();
|
||||
|
||||
CheckExistingPosition();
|
||||
|
||||
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];
|
||||
rsi_prev = rsi_buffer[1];
|
||||
rsi_two_bars_ago = rsi_buffer[2];
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Stop-loss RSI (RSI_StopLoss_TimeFrame) |
|
||||
//| Uses latest MqlTick before CopyBuffer so RSI matches current quote. |
|
||||
//+------------------------------------------------------------------+
|
||||
bool UpdateRSI_StopLoss()
|
||||
{
|
||||
if(rsi_stoploss_handle == INVALID_HANDLE)
|
||||
return false;
|
||||
if(!SymbolInfoTick(_Symbol, rsi_stoploss_last_tick))
|
||||
return false;
|
||||
|
||||
int calc = BarsCalculated(rsi_stoploss_handle);
|
||||
if(calc <= 0)
|
||||
return false;
|
||||
|
||||
if(CopyBuffer(rsi_stoploss_handle, 0, 0, 1, rsi_stoploss_buffer) < 1)
|
||||
return false;
|
||||
rsi_stoploss_current = rsi_stoploss_buffer[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
void ResyncPositionFromMarket()
|
||||
{
|
||||
if(position_open)
|
||||
return;
|
||||
ulong t = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
if(t == 0 || !PositionSelectByTicket(t))
|
||||
return;
|
||||
position_ticket = (int)t;
|
||||
position_open = true;
|
||||
current_position_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| RSI-based stop: RSI_StopLoss_TimeFrame series (independent of TimeFrame) |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckRSIStopLossClose()
|
||||
{
|
||||
if(!UseRSI_StopLoss || !position_open)
|
||||
return;
|
||||
|
||||
if(!PositionSelectByTicketAndMagic(position_ticket, MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(current_position_type == POSITION_TYPE_BUY)
|
||||
{
|
||||
if(rsi_stoploss_current < RSI_StopLoss_BuyBelow)
|
||||
ClosePosition();
|
||||
}
|
||||
else if(current_position_type == POSITION_TYPE_SELL)
|
||||
{
|
||||
if(rsi_stoploss_current > RSI_StopLoss_SellAbove)
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check existing position for exit conditions |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckExistingPosition()
|
||||
{
|
||||
if(!position_open)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if(!PositionSelectByTicketAndMagic(position_ticket, MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(current_position_type == POSITION_TYPE_BUY)
|
||||
{
|
||||
if(rsi_current < RSI_Oversold)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bars_against_count++;
|
||||
}
|
||||
|
||||
if(bars_against_count >= BarsToWait)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
|
||||
if(rsi_current >= RSI_Target_Buy)
|
||||
{
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(current_position_type == POSITION_TYPE_SELL)
|
||||
{
|
||||
if(rsi_current > RSI_Overbought)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bars_against_count++;
|
||||
}
|
||||
|
||||
if(bars_against_count >= BarsToWait)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
|
||||
if(rsi_current <= RSI_Target_Sell)
|
||||
{
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for entry signals |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckEntrySignals()
|
||||
{
|
||||
if(rsi_two_bars_ago <= RSI_Oversold && rsi_prev > RSI_Oversold)
|
||||
OpenBuyPosition();
|
||||
|
||||
if(rsi_two_bars_ago >= RSI_Overbought && rsi_prev < RSI_Overbought)
|
||||
OpenSellPosition();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Open buy position |
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenBuyPosition()
|
||||
{
|
||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
|
||||
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
|
||||
{
|
||||
ulong t = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
if(t != 0)
|
||||
position_ticket = (int)t;
|
||||
position_open = true;
|
||||
current_position_type = POSITION_TYPE_BUY;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Open sell position |
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenSellPosition()
|
||||
{
|
||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
|
||||
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
|
||||
{
|
||||
ulong t = GetPositionTicketByMagic(_Symbol, (ulong)MagicNumber);
|
||||
if(t != 0)
|
||||
position_ticket = (int)t;
|
||||
position_open = true;
|
||||
current_position_type = POSITION_TYPE_SELL;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Close current position |
|
||||
//+------------------------------------------------------------------+
|
||||
void ClosePosition()
|
||||
{
|
||||
if(ClosePositionByMagic(trade, _Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
if(!PositionExistsByMagic(_Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
Print("RSIScalpingXAUUSD: close failed (will retry on next bar). retcode=",
|
||||
trade.ResultRetcode(), " lastError=", GetLastError());
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
# Pepperstone US - Symbol Setup Guide
|
||||
|
||||
## Finding Correct Symbol Names in MetaTrader 5
|
||||
|
||||
### Step-by-Step Instructions:
|
||||
|
||||
1. **Open Market Watch Window**
|
||||
- Press `Ctrl+M` or go to `View > Market Watch`
|
||||
|
||||
2. **Show All Symbols**
|
||||
- Right-click in the Market Watch window
|
||||
- Select `Show All` or `Symbols`
|
||||
- This shows all available symbols from your broker
|
||||
|
||||
3. **Search for Your Symbols**
|
||||
- Use the search box in the Market Watch window
|
||||
- Search for: "AAPL", "MSFT", "NVDA", "TSLA", "BTCUSD", "XAUUSD"
|
||||
|
||||
4. **Note the Exact Symbol Name**
|
||||
- The symbol name shown in Market Watch is what you need to use
|
||||
- Common formats for Pepperstone US:
|
||||
- Stocks: `AAPL.US`, `MSFT.US`, `NVDA.US`, `TSLA.US`
|
||||
- Or: `NASDAQ:AAPL`, `NASDAQ:MSFT`, etc.
|
||||
- Or: Just `AAPL`, `MSFT`, etc. (if available)
|
||||
|
||||
5. **Add to Market Watch**
|
||||
- Double-click the symbol to add it to your Market Watch
|
||||
- Or right-click and select `Show`
|
||||
|
||||
6. **Update EA Inputs**
|
||||
- Open the EA inputs in MetaTrader 5
|
||||
- Update each symbol parameter with the exact name from Market Watch
|
||||
|
||||
## Common Pepperstone US Symbol Formats
|
||||
|
||||
### US Stocks:
|
||||
- **Apple**: `AAPL.US` or `NASDAQ:AAPL` or `AAPL`
|
||||
- **Microsoft**: `MSFT.US` or `NASDAQ:MSFT` or `MSFT`
|
||||
- **NVIDIA**: `NVDA.US` or `NASDAQ:NVDA` or `NVDA`
|
||||
- **Tesla**: `TSLA.US` or `NASDAQ:TSLA` or `TSLA`
|
||||
|
||||
### Cryptocurrencies:
|
||||
- **Bitcoin**: `BTCUSD` or `BTC/USD` or `BTCUSD.c`
|
||||
|
||||
### Precious Metals:
|
||||
- **Gold**: `XAUUSD` or `GOLD` or `XAU/USD`
|
||||
|
||||
## Important Notes:
|
||||
|
||||
1. **Symbol Names are Case-Sensitive**: Use exact capitalization
|
||||
2. **Add Symbols to Market Watch**: Symbols must be in Market Watch for the EA to access them
|
||||
3. **Check Trading Hours**: US stocks trade during US market hours (9:30 AM - 4:00 PM ET)
|
||||
4. **CFD vs Stock**: Pepperstone offers CFDs on stocks, not actual stocks
|
||||
5. **Spread**: Check the spread for each symbol - some may have wider spreads
|
||||
|
||||
## Troubleshooting:
|
||||
|
||||
### If Symbol Not Found:
|
||||
1. Check if you're connected to Pepperstone US server
|
||||
2. Verify your account type supports the symbol
|
||||
3. Contact Pepperstone support for symbol availability
|
||||
4. Check if symbol requires special account permissions
|
||||
|
||||
### If EA Shows "Symbol Not Available":
|
||||
1. Make sure symbol is added to Market Watch
|
||||
2. Verify symbol name matches exactly (including dots, colons, etc.)
|
||||
3. Check broker connection status
|
||||
4. Try different symbol format variations
|
||||
|
||||
## Testing Symbols:
|
||||
|
||||
You can test if a symbol works by:
|
||||
1. Opening a chart with that symbol
|
||||
2. If chart opens successfully, the symbol name is correct
|
||||
3. Use that exact symbol name in the EA inputs
|
||||
@@ -1,639 +0,0 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| AdaptiveMonthlyRegime.mqh |
|
||||
//| Streak unit (input): closed calendar MONTHS or closed DAYS |
|
||||
//| (server time). Losing streak -> optional CANARY (next full month |
|
||||
//| or next full day at InpAdaptiveCanaryLotMult). Canary P/L > 0 -> |
|
||||
//| full size; else HARD PAUSE. CanaryLotMult==0 -> hard pause, no |
|
||||
//| canary. Per-strat DD lot cap still uses last closed *month* P/L. |
|
||||
//| Include after all `input` blocks. |
|
||||
//+------------------------------------------------------------------+
|
||||
#ifndef ADAPTIVE_MONTHLY_REGIME_MQH
|
||||
#define ADAPTIVE_MONTHLY_REGIME_MQH
|
||||
|
||||
#define UNITED_ADAPTIVE_N 13
|
||||
#define UNITED_AD_MAX_DAY_BUCKETS 400
|
||||
|
||||
#define UNITED_AD_DARVAS 0
|
||||
#define UNITED_AD_ES 1
|
||||
#define UNITED_AD_RC 2
|
||||
#define UNITED_AD_RM 3
|
||||
#define UNITED_AD_RS_APPL 4
|
||||
#define UNITED_AD_RS_BTC 5
|
||||
#define UNITED_AD_RS_NVDA 6
|
||||
#define UNITED_AD_RS_TSLA 7
|
||||
#define UNITED_AD_RS_XAU 8
|
||||
#define UNITED_AD_RRA_EUR 9
|
||||
#define UNITED_AD_RRA_AUD 10
|
||||
#define UNITED_AD_RSS 11
|
||||
#define UNITED_AD_SUPEREMA 12
|
||||
|
||||
bool g_adHardPaused[UNITED_ADAPTIVE_N];
|
||||
bool g_adCanaryWaiting[UNITED_ADAPTIVE_N];
|
||||
bool g_adCanaryActive[UNITED_ADAPTIVE_N];
|
||||
datetime g_adCanaryMonthStart[UNITED_ADAPTIVE_N];
|
||||
datetime g_adCanaryMonthEnd[UNITED_ADAPTIVE_N];
|
||||
datetime g_adHardPauseUntil[UNITED_ADAPTIVE_N];
|
||||
datetime g_adPostCanaryCooldownUntil[UNITED_ADAPTIVE_N];
|
||||
|
||||
double g_adLastClosedMonthPl[UNITED_ADAPTIVE_N];
|
||||
|
||||
datetime g_unitedAdaptiveLastUpdate = 0;
|
||||
|
||||
string UnitedAdaptive_StratName(const int s)
|
||||
{
|
||||
const string names[] =
|
||||
{
|
||||
"DarvasBox", "EMASlope", "RSICrossOver", "RM_MidPoint",
|
||||
"RS_Scalp_AAPL", "RS_Scalp_BTC", "RS_Scalp_NVDA", "RS_Scalp_TSLA", "RS_Scalp_XAU",
|
||||
"RRA_EURUSD", "RRA_AUDUSD", "SecretSauce", "SuperEMA"
|
||||
};
|
||||
if(s >= 0 && s < UNITED_ADAPTIVE_N)
|
||||
return names[s];
|
||||
return "?";
|
||||
}
|
||||
|
||||
void UnitedAdaptive_Init()
|
||||
{
|
||||
for(int i = 0; i < UNITED_ADAPTIVE_N; i++)
|
||||
{
|
||||
g_adHardPaused[i] = false;
|
||||
g_adCanaryWaiting[i] = false;
|
||||
g_adCanaryActive[i] = false;
|
||||
g_adCanaryMonthStart[i] = 0;
|
||||
g_adCanaryMonthEnd[i] = 0;
|
||||
g_adHardPauseUntil[i] = 0;
|
||||
g_adPostCanaryCooldownUntil[i] = 0;
|
||||
g_adLastClosedMonthPl[i] = 0.0;
|
||||
}
|
||||
g_unitedAdaptiveLastUpdate = 0;
|
||||
}
|
||||
|
||||
datetime UnitedAdaptive_MonthStartInt(const int y, const int m)
|
||||
{
|
||||
MqlDateTime d;
|
||||
d.year = y;
|
||||
d.mon = m;
|
||||
d.day = 1;
|
||||
d.hour = 0;
|
||||
d.min = 0;
|
||||
d.sec = 0;
|
||||
return StructToTime(d);
|
||||
}
|
||||
|
||||
void UnitedAdaptive_NextYm(int &y, int &m)
|
||||
{
|
||||
m++;
|
||||
if(m > 12)
|
||||
{
|
||||
m = 1;
|
||||
y++;
|
||||
}
|
||||
}
|
||||
|
||||
void UnitedAdaptive_ClosedMonthYm(const int offsetFromLastComplete, int &y, int &m)
|
||||
{
|
||||
MqlDateTime now;
|
||||
TimeToStruct(TimeCurrent(), now);
|
||||
int ly = now.year;
|
||||
int lm = now.mon - 1;
|
||||
if(lm < 1)
|
||||
{
|
||||
lm = 12;
|
||||
ly--;
|
||||
}
|
||||
for(int i = 0; i < offsetFromLastComplete; i++)
|
||||
{
|
||||
lm--;
|
||||
if(lm < 1)
|
||||
{
|
||||
lm = 12;
|
||||
ly--;
|
||||
}
|
||||
}
|
||||
y = ly;
|
||||
m = lm;
|
||||
}
|
||||
|
||||
// Start of calendar day: offset 0 = yesterday 00:00 (last fully closed day), 1 = day before, ...
|
||||
datetime UnitedAdaptive_ClosedDayStart(const int offsetFromLastCompleteDay)
|
||||
{
|
||||
MqlDateTime n;
|
||||
TimeToStruct(TimeCurrent(), n);
|
||||
n.hour = 0;
|
||||
n.min = 0;
|
||||
n.sec = 0;
|
||||
const datetime today0 = StructToTime(n);
|
||||
return today0 - (datetime)((offsetFromLastCompleteDay + 1) * 86400);
|
||||
}
|
||||
|
||||
// Bucket index 0 = yesterday. -1 = today (incomplete) or invalid.
|
||||
int UnitedAdaptive_ClosedDayOffsetFromDealTime(const datetime dt)
|
||||
{
|
||||
MqlDateTime d, n;
|
||||
TimeToStruct(dt, d);
|
||||
d.hour = 0;
|
||||
d.min = 0;
|
||||
d.sec = 0;
|
||||
const datetime dealDay0 = StructToTime(d);
|
||||
TimeToStruct(TimeCurrent(), n);
|
||||
n.hour = 0;
|
||||
n.min = 0;
|
||||
n.sec = 0;
|
||||
const datetime today0 = StructToTime(n);
|
||||
const long deltaSec = (long)(today0 - dealDay0);
|
||||
if(deltaSec < 86400L)
|
||||
return -1;
|
||||
const int daysAgo = (int)(deltaSec / 86400L);
|
||||
return daysAgo - 1;
|
||||
}
|
||||
|
||||
datetime UnitedAdaptive_AddMonthsWallClock(const datetime dt0, const int months)
|
||||
{
|
||||
MqlDateTime t;
|
||||
TimeToStruct(dt0, t);
|
||||
for(int i = 0; i < months; i++)
|
||||
{
|
||||
t.mon++;
|
||||
if(t.mon > 12)
|
||||
{
|
||||
t.mon = 1;
|
||||
t.year++;
|
||||
}
|
||||
}
|
||||
return StructToTime(t);
|
||||
}
|
||||
|
||||
bool UnitedAdaptive_RMDealMatches(const long mg)
|
||||
{
|
||||
if(EnableRSIMidPointHijack)
|
||||
{
|
||||
if(RM_InpEnableRSIFollow && mg == (long)RM_InpMagicNumberRSIFollow)
|
||||
return true;
|
||||
if(RM_InpEnableRSIReverse && mg == (long)RM_InpMagicNumberRSIReverse)
|
||||
return true;
|
||||
if(RM_InpEnableEMACross && mg == (long)RM_InpMagicNumberEMACross)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UnitedAdaptive_DealBelongsToStrat(const int s, const long mg)
|
||||
{
|
||||
if(s == UNITED_AD_DARVAS)
|
||||
return EnableDarvasBox && mg == (long)DB_MagicNumber;
|
||||
if(s == UNITED_AD_ES)
|
||||
return EnableEMASlopeDistance && mg == (long)ES_MagicNumber;
|
||||
if(s == UNITED_AD_RC)
|
||||
return EnableRSICrossOverReversal && mg == (long)RC_MagicNumber;
|
||||
if(s == UNITED_AD_RM)
|
||||
return UnitedAdaptive_RMDealMatches(mg);
|
||||
if(s == UNITED_AD_RS_APPL)
|
||||
return EnableRSIScalpingAPPL && mg == (long)RS_APPL_MagicNumber;
|
||||
if(s == UNITED_AD_RS_BTC)
|
||||
return EnableRSIScalpingBTCUSD && mg == (long)RS_BTCUSD_MagicNumber;
|
||||
if(s == UNITED_AD_RS_NVDA)
|
||||
return EnableRSIScalpingNVDA && mg == (long)RS_NVDA_MagicNumber;
|
||||
if(s == UNITED_AD_RS_TSLA)
|
||||
return EnableRSIScalpingTSLA && mg == (long)RS_TSLA_MagicNumber;
|
||||
if(s == UNITED_AD_RS_XAU)
|
||||
return EnableRSIScalpingXAUUSD && mg == (long)RS_XAUUSD_MagicNumber;
|
||||
if(s == UNITED_AD_RRA_EUR)
|
||||
return EnableRSIReversalEURUSD && mg == (long)RRA_EURUSD_MagicNumber;
|
||||
if(s == UNITED_AD_RRA_AUD)
|
||||
return EnableRSIReversalAUDUSD && mg == (long)RRA_AUDUSD_MagicNumber;
|
||||
if(s == UNITED_AD_RSS)
|
||||
return EnableRSISecretSauceXAUUSD && mg == (long)RSS_XAUUSD_MagicNumber;
|
||||
if(s == UNITED_AD_SUPEREMA)
|
||||
return EnableSuperEMA && mg == (long)SE_MagicNumber;
|
||||
return false;
|
||||
}
|
||||
|
||||
double UnitedAdaptive_SumStratDealsRange(const int s, const datetime from, const datetime to)
|
||||
{
|
||||
if(from >= to)
|
||||
return 0.0;
|
||||
if(!HistorySelect(from, to))
|
||||
return 0.0;
|
||||
double sum = 0.0;
|
||||
const int n = HistoryDealsTotal();
|
||||
for(int i = 0; i < n; i++)
|
||||
{
|
||||
const ulong t = HistoryDealGetTicket(i);
|
||||
if(t == 0)
|
||||
continue;
|
||||
const long mg = (long)HistoryDealGetInteger(t, DEAL_MAGIC);
|
||||
if(!UnitedAdaptive_DealBelongsToStrat(s, mg))
|
||||
continue;
|
||||
sum += HistoryDealGetDouble(t, DEAL_PROFIT);
|
||||
sum += HistoryDealGetDouble(t, DEAL_SWAP);
|
||||
sum += HistoryDealGetDouble(t, DEAL_COMMISSION);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
void UnitedAdaptive_StartCanaryWait(const int s)
|
||||
{
|
||||
if(InpAdaptiveStreakUnit == ADAPTIVE_STREAK_BY_DAY)
|
||||
{
|
||||
MqlDateTime t;
|
||||
TimeToStruct(TimeCurrent(), t);
|
||||
t.hour = 0;
|
||||
t.min = 0;
|
||||
t.sec = 0;
|
||||
const datetime today0 = StructToTime(t);
|
||||
g_adCanaryMonthStart[s] = today0 + 86400;
|
||||
g_adCanaryMonthEnd[s] = g_adCanaryMonthStart[s] + 86400;
|
||||
g_adCanaryWaiting[s] = true;
|
||||
g_adCanaryActive[s] = false;
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s),
|
||||
" -> CANARY WAIT until ", TimeToString(g_adCanaryMonthStart[s], TIME_DATE),
|
||||
" then 1 day at lot x ", DoubleToString(InpAdaptiveCanaryLotMult, 4));
|
||||
return;
|
||||
}
|
||||
MqlDateTime t;
|
||||
TimeToStruct(TimeCurrent(), t);
|
||||
t.mon++;
|
||||
if(t.mon > 12)
|
||||
{
|
||||
t.mon = 1;
|
||||
t.year++;
|
||||
}
|
||||
t.day = 1;
|
||||
t.hour = 0;
|
||||
t.min = 0;
|
||||
t.sec = 0;
|
||||
g_adCanaryMonthStart[s] = StructToTime(t);
|
||||
int ey = t.year;
|
||||
int em = t.mon;
|
||||
UnitedAdaptive_NextYm(ey, em);
|
||||
g_adCanaryMonthEnd[s] = UnitedAdaptive_MonthStartInt(ey, em);
|
||||
g_adCanaryWaiting[s] = true;
|
||||
g_adCanaryActive[s] = false;
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s),
|
||||
" -> CANARY WAIT until ", TimeToString(g_adCanaryMonthStart[s], TIME_DATE),
|
||||
" then 1 month at lot x ", DoubleToString(InpAdaptiveCanaryLotMult, 4));
|
||||
}
|
||||
|
||||
void UnitedAdaptive_TryExpireHardPauses()
|
||||
{
|
||||
if(InpAdaptiveStreakUnit == ADAPTIVE_STREAK_BY_DAY)
|
||||
{
|
||||
if(InpAdaptiveHardRetryDays <= 0)
|
||||
return;
|
||||
}
|
||||
else if(InpAdaptiveHardRetryMonths <= 0)
|
||||
return;
|
||||
|
||||
const datetime now = TimeCurrent();
|
||||
for(int s = 0; s < UNITED_ADAPTIVE_N; s++)
|
||||
{
|
||||
if(!g_adHardPaused[s])
|
||||
continue;
|
||||
if(g_adHardPauseUntil[s] > 0 && now >= g_adHardPauseUntil[s])
|
||||
{
|
||||
g_adHardPaused[s] = false;
|
||||
g_adHardPauseUntil[s] = 0;
|
||||
if(InpAdaptiveStreakUnit == ADAPTIVE_STREAK_BY_DAY)
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s),
|
||||
" hard pause RETRY (after ", InpAdaptiveHardRetryDays, " d)");
|
||||
else
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s),
|
||||
" hard pause RETRY (after ", InpAdaptiveHardRetryMonths, " mo)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnitedAdaptive_ProcessCanaryTransitions()
|
||||
{
|
||||
if(!InpAdaptiveEnable)
|
||||
return;
|
||||
|
||||
UnitedAdaptive_TryExpireHardPauses();
|
||||
|
||||
const datetime now = TimeCurrent();
|
||||
for(int s = 0; s < UNITED_ADAPTIVE_N; s++)
|
||||
{
|
||||
if(g_adCanaryWaiting[s] && !g_adCanaryActive[s] && now >= g_adCanaryMonthStart[s])
|
||||
{
|
||||
g_adCanaryWaiting[s] = false;
|
||||
g_adCanaryActive[s] = true;
|
||||
if(InpAdaptiveStreakUnit == ADAPTIVE_STREAK_BY_DAY)
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s), " CANARY ACTIVE (probation day)");
|
||||
else
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s), " CANARY ACTIVE (probation month)");
|
||||
}
|
||||
|
||||
if(g_adCanaryActive[s] && now >= g_adCanaryMonthEnd[s])
|
||||
{
|
||||
const double pl = UnitedAdaptive_SumStratDealsRange(s, g_adCanaryMonthStart[s], g_adCanaryMonthEnd[s]);
|
||||
g_adCanaryActive[s] = false;
|
||||
g_adCanaryWaiting[s] = false;
|
||||
if(pl > 0.0)
|
||||
{
|
||||
if(InpAdaptivePostCanaryCooldownDays > 0)
|
||||
g_adPostCanaryCooldownUntil[s] = TimeCurrent() + InpAdaptivePostCanaryCooldownDays * 86400;
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s),
|
||||
" canary OK P/L=", DoubleToString(pl, 2), " -> full size");
|
||||
}
|
||||
else
|
||||
{
|
||||
g_adHardPaused[s] = true;
|
||||
if(InpAdaptiveStreakUnit == ADAPTIVE_STREAK_BY_DAY)
|
||||
{
|
||||
if(InpAdaptiveHardRetryDays > 0)
|
||||
g_adHardPauseUntil[s] = now + (datetime)InpAdaptiveHardRetryDays * 86400;
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s),
|
||||
" canary FAIL P/L=", DoubleToString(pl, 2), " -> HARD PAUSE",
|
||||
(InpAdaptiveHardRetryDays > 0 ? " (auto-retry later)" : ""));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(InpAdaptiveHardRetryMonths > 0)
|
||||
g_adHardPauseUntil[s] = UnitedAdaptive_AddMonthsWallClock(now, InpAdaptiveHardRetryMonths);
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s),
|
||||
" canary FAIL P/L=", DoubleToString(pl, 2), " -> HARD PAUSE",
|
||||
(InpAdaptiveHardRetryMonths > 0 ? " (auto-retry later)" : ""));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool UnitedAdaptive_StratLastMonthIsLosing(const int s)
|
||||
{
|
||||
if(s < 0 || s >= UNITED_ADAPTIVE_N)
|
||||
return false;
|
||||
const double thr = MathMax(0.0, InpDdLotCapStratLossThreshold);
|
||||
return g_adLastClosedMonthPl[s] < -thr;
|
||||
}
|
||||
|
||||
void UnitedAdaptive_RecomputeStreaks()
|
||||
{
|
||||
const bool needMonthPlCap = InpDdLotCapEnable && InpDdLotCapPerStratEnable;
|
||||
const bool adaptMonth = InpAdaptiveEnable && InpAdaptiveStreakUnit == ADAPTIVE_STREAK_BY_MONTH;
|
||||
const bool adaptDay = InpAdaptiveEnable && InpAdaptiveStreakUnit == ADAPTIVE_STREAK_BY_DAY;
|
||||
|
||||
int nMonthOff = 0;
|
||||
int streakReqM = 1;
|
||||
if(adaptMonth)
|
||||
{
|
||||
streakReqM = MathMax(1, InpAdaptiveRedStreak);
|
||||
const int L = MathMax(InpAdaptiveLookbackMonths, streakReqM + 1);
|
||||
nMonthOff = MathMin(L, 63);
|
||||
}
|
||||
else if(needMonthPlCap)
|
||||
nMonthOff = 2;
|
||||
|
||||
int nDayOff = 0;
|
||||
int streakReqD = 1;
|
||||
if(adaptDay)
|
||||
{
|
||||
streakReqD = MathMax(1, InpAdaptiveRedStreak);
|
||||
const int L = MathMax(InpAdaptiveLookbackDays, streakReqD + 1);
|
||||
nDayOff = MathMin(L, UNITED_AD_MAX_DAY_BUCKETS);
|
||||
}
|
||||
|
||||
if(nMonthOff == 0 && nDayOff == 0)
|
||||
return;
|
||||
|
||||
const datetime to = TimeCurrent() + 60;
|
||||
datetime from = to;
|
||||
if(nMonthOff > 0)
|
||||
{
|
||||
int oy = 0, om = 0;
|
||||
UnitedAdaptive_ClosedMonthYm(nMonthOff - 1, oy, om);
|
||||
const datetime mf = UnitedAdaptive_MonthStartInt(oy, om);
|
||||
if(mf < from)
|
||||
from = mf;
|
||||
}
|
||||
if(nDayOff > 0)
|
||||
{
|
||||
const datetime df = UnitedAdaptive_ClosedDayStart(nDayOff - 1);
|
||||
if(df < from)
|
||||
from = df;
|
||||
}
|
||||
|
||||
if(from >= to || !HistorySelect(from, to))
|
||||
return;
|
||||
|
||||
double monthBuck[UNITED_ADAPTIVE_N][64];
|
||||
double dayBuck[UNITED_ADAPTIVE_N][UNITED_AD_MAX_DAY_BUCKETS];
|
||||
for(int s = 0; s < UNITED_ADAPTIVE_N; s++)
|
||||
{
|
||||
for(int o = 0; o < 64; o++)
|
||||
monthBuck[s][o] = 0.0;
|
||||
for(int o = 0; o < UNITED_AD_MAX_DAY_BUCKETS; o++)
|
||||
dayBuck[s][o] = 0.0;
|
||||
}
|
||||
|
||||
const int total = HistoryDealsTotal();
|
||||
for(int i = 0; i < total; i++)
|
||||
{
|
||||
const ulong tk = HistoryDealGetTicket(i);
|
||||
if(tk == 0)
|
||||
continue;
|
||||
const long mg = (long)HistoryDealGetInteger(tk, DEAL_MAGIC);
|
||||
const datetime dt = (datetime)HistoryDealGetInteger(tk, DEAL_TIME);
|
||||
const double pl = HistoryDealGetDouble(tk, DEAL_PROFIT)
|
||||
+ HistoryDealGetDouble(tk, DEAL_SWAP)
|
||||
+ HistoryDealGetDouble(tk, DEAL_COMMISSION);
|
||||
|
||||
if(nMonthOff > 0)
|
||||
{
|
||||
for(int o = 0; o < nMonthOff; o++)
|
||||
{
|
||||
int y = 0, m = 0;
|
||||
UnitedAdaptive_ClosedMonthYm(o, y, m);
|
||||
const datetime ms = UnitedAdaptive_MonthStartInt(y, m);
|
||||
int ny = y, nm = m;
|
||||
UnitedAdaptive_NextYm(ny, nm);
|
||||
const datetime me = UnitedAdaptive_MonthStartInt(ny, nm);
|
||||
if(dt < ms || dt >= me)
|
||||
continue;
|
||||
|
||||
if(EnableDarvasBox && mg == (long)DB_MagicNumber)
|
||||
monthBuck[UNITED_AD_DARVAS][o] += pl;
|
||||
if(EnableEMASlopeDistance && mg == (long)ES_MagicNumber)
|
||||
monthBuck[UNITED_AD_ES][o] += pl;
|
||||
if(EnableRSICrossOverReversal && mg == (long)RC_MagicNumber)
|
||||
monthBuck[UNITED_AD_RC][o] += pl;
|
||||
if(UnitedAdaptive_RMDealMatches(mg))
|
||||
monthBuck[UNITED_AD_RM][o] += pl;
|
||||
if(EnableRSIScalpingAPPL && mg == (long)RS_APPL_MagicNumber)
|
||||
monthBuck[UNITED_AD_RS_APPL][o] += pl;
|
||||
if(EnableRSIScalpingBTCUSD && mg == (long)RS_BTCUSD_MagicNumber)
|
||||
monthBuck[UNITED_AD_RS_BTC][o] += pl;
|
||||
if(EnableRSIScalpingNVDA && mg == (long)RS_NVDA_MagicNumber)
|
||||
monthBuck[UNITED_AD_RS_NVDA][o] += pl;
|
||||
if(EnableRSIScalpingTSLA && mg == (long)RS_TSLA_MagicNumber)
|
||||
monthBuck[UNITED_AD_RS_TSLA][o] += pl;
|
||||
if(EnableRSIScalpingXAUUSD && mg == (long)RS_XAUUSD_MagicNumber)
|
||||
monthBuck[UNITED_AD_RS_XAU][o] += pl;
|
||||
if(EnableRSIReversalEURUSD && mg == (long)RRA_EURUSD_MagicNumber)
|
||||
monthBuck[UNITED_AD_RRA_EUR][o] += pl;
|
||||
if(EnableRSIReversalAUDUSD && mg == (long)RRA_AUDUSD_MagicNumber)
|
||||
monthBuck[UNITED_AD_RRA_AUD][o] += pl;
|
||||
if(EnableRSISecretSauceXAUUSD && mg == (long)RSS_XAUUSD_MagicNumber)
|
||||
monthBuck[UNITED_AD_RSS][o] += pl;
|
||||
if(EnableSuperEMA && mg == (long)SE_MagicNumber)
|
||||
monthBuck[UNITED_AD_SUPEREMA][o] += pl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(nDayOff > 0)
|
||||
{
|
||||
const int dOff = UnitedAdaptive_ClosedDayOffsetFromDealTime(dt);
|
||||
if(dOff >= 0 && dOff < nDayOff)
|
||||
{
|
||||
if(EnableDarvasBox && mg == (long)DB_MagicNumber)
|
||||
dayBuck[UNITED_AD_DARVAS][dOff] += pl;
|
||||
if(EnableEMASlopeDistance && mg == (long)ES_MagicNumber)
|
||||
dayBuck[UNITED_AD_ES][dOff] += pl;
|
||||
if(EnableRSICrossOverReversal && mg == (long)RC_MagicNumber)
|
||||
dayBuck[UNITED_AD_RC][dOff] += pl;
|
||||
if(UnitedAdaptive_RMDealMatches(mg))
|
||||
dayBuck[UNITED_AD_RM][dOff] += pl;
|
||||
if(EnableRSIScalpingAPPL && mg == (long)RS_APPL_MagicNumber)
|
||||
dayBuck[UNITED_AD_RS_APPL][dOff] += pl;
|
||||
if(EnableRSIScalpingBTCUSD && mg == (long)RS_BTCUSD_MagicNumber)
|
||||
dayBuck[UNITED_AD_RS_BTC][dOff] += pl;
|
||||
if(EnableRSIScalpingNVDA && mg == (long)RS_NVDA_MagicNumber)
|
||||
dayBuck[UNITED_AD_RS_NVDA][dOff] += pl;
|
||||
if(EnableRSIScalpingTSLA && mg == (long)RS_TSLA_MagicNumber)
|
||||
dayBuck[UNITED_AD_RS_TSLA][dOff] += pl;
|
||||
if(EnableRSIScalpingXAUUSD && mg == (long)RS_XAUUSD_MagicNumber)
|
||||
dayBuck[UNITED_AD_RS_XAU][dOff] += pl;
|
||||
if(EnableRSIReversalEURUSD && mg == (long)RRA_EURUSD_MagicNumber)
|
||||
dayBuck[UNITED_AD_RRA_EUR][dOff] += pl;
|
||||
if(EnableRSIReversalAUDUSD && mg == (long)RRA_AUDUSD_MagicNumber)
|
||||
dayBuck[UNITED_AD_RRA_AUD][dOff] += pl;
|
||||
if(EnableRSISecretSauceXAUUSD && mg == (long)RSS_XAUUSD_MagicNumber)
|
||||
dayBuck[UNITED_AD_RSS][dOff] += pl;
|
||||
if(EnableSuperEMA && mg == (long)SE_MagicNumber)
|
||||
dayBuck[UNITED_AD_SUPEREMA][dOff] += pl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(nMonthOff > 0)
|
||||
{
|
||||
for(int s = 0; s < UNITED_ADAPTIVE_N; s++)
|
||||
g_adLastClosedMonthPl[s] = monthBuck[s][0];
|
||||
}
|
||||
|
||||
if(!InpAdaptiveEnable)
|
||||
return;
|
||||
|
||||
const double thr = MathMax(0.0, InpAdaptiveRedThreshold);
|
||||
const bool useDay = adaptDay;
|
||||
const int streakReq = useDay ? streakReqD : streakReqM;
|
||||
const int nOff = useDay ? nDayOff : nMonthOff;
|
||||
|
||||
for(int s = 0; s < UNITED_ADAPTIVE_N; s++)
|
||||
{
|
||||
if(g_adHardPaused[s])
|
||||
continue;
|
||||
if(g_adCanaryActive[s] || g_adCanaryWaiting[s])
|
||||
{
|
||||
int consecOk = 0;
|
||||
for(int o = 0; o < streakReq && o < nOff; o++)
|
||||
{
|
||||
const double bpl = useDay ? dayBuck[s][o] : monthBuck[s][o];
|
||||
if(bpl < -thr)
|
||||
consecOk++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
const bool streakBad = (consecOk >= streakReq);
|
||||
if(!streakBad && g_adCanaryWaiting[s] && !g_adCanaryActive[s])
|
||||
{
|
||||
g_adCanaryWaiting[s] = false;
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s), " canary wait CANCELLED (streak cleared)");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
int consec = 0;
|
||||
for(int o = 0; o < streakReq && o < nOff; o++)
|
||||
{
|
||||
const double bpl = useDay ? dayBuck[s][o] : monthBuck[s][o];
|
||||
if(bpl < -thr)
|
||||
consec++;
|
||||
else
|
||||
break;
|
||||
}
|
||||
const bool streakBad = (consec >= streakReq);
|
||||
if(!streakBad)
|
||||
continue;
|
||||
|
||||
const bool prevHard = g_adHardPaused[s];
|
||||
if(InpAdaptiveCanaryLotMult > 0.0)
|
||||
{
|
||||
if(!g_adCanaryWaiting[s] && !g_adCanaryActive[s])
|
||||
{
|
||||
if(g_adPostCanaryCooldownUntil[s] > TimeCurrent())
|
||||
continue;
|
||||
UnitedAdaptive_StartCanaryWait(s);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_adHardPaused[s] = true;
|
||||
if(!prevHard && useDay && InpAdaptiveHardRetryDays > 0)
|
||||
g_adHardPauseUntil[s] = TimeCurrent() + (datetime)InpAdaptiveHardRetryDays * 86400;
|
||||
else if(!prevHard && !useDay && InpAdaptiveHardRetryMonths > 0)
|
||||
g_adHardPauseUntil[s] = UnitedAdaptive_AddMonthsWallClock(TimeCurrent(), InpAdaptiveHardRetryMonths);
|
||||
if(!prevHard)
|
||||
Print("AdaptiveRegime: ", UnitedAdaptive_StratName(s),
|
||||
" HARD PAUSE (streak, canary disabled)");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnitedAdaptive_UpdateIfDue()
|
||||
{
|
||||
if(!InpAdaptiveEnable && (!InpDdLotCapEnable || !InpDdLotCapPerStratEnable))
|
||||
{
|
||||
UnitedAdaptive_Init();
|
||||
return;
|
||||
}
|
||||
|
||||
int everySec = 3600;
|
||||
if(InpAdaptiveEnable)
|
||||
everySec = MathMin(everySec, MathMax(60, InpAdaptiveUpdateSeconds));
|
||||
if(InpDdLotCapEnable && InpDdLotCapPerStratEnable)
|
||||
everySec = MathMin(everySec, MathMax(60, InpDdLotCapUpdateSeconds));
|
||||
|
||||
if(g_unitedAdaptiveLastUpdate > 0 && (TimeCurrent() - g_unitedAdaptiveLastUpdate) < everySec)
|
||||
return;
|
||||
|
||||
g_unitedAdaptiveLastUpdate = TimeCurrent();
|
||||
UnitedAdaptive_RecomputeStreaks();
|
||||
}
|
||||
|
||||
double UnitedAdaptive_GetLotMult(const int stratId)
|
||||
{
|
||||
if(stratId < 0 || stratId >= UNITED_ADAPTIVE_N)
|
||||
return 1.0;
|
||||
if(!InpAdaptiveEnable)
|
||||
return 1.0;
|
||||
if(g_adCanaryActive[stratId])
|
||||
return MathMax(0.0, InpAdaptiveCanaryLotMult);
|
||||
return 1.0;
|
||||
}
|
||||
|
||||
bool UnitedAdaptive_StrategyActive(const int stratId)
|
||||
{
|
||||
if(stratId < 0 || stratId >= UNITED_ADAPTIVE_N)
|
||||
return true;
|
||||
if(!InpAdaptiveEnable)
|
||||
return true;
|
||||
if(g_adHardPaused[stratId])
|
||||
return false;
|
||||
if(g_adCanaryWaiting[stratId] && !g_adCanaryActive[stratId])
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,75 +0,0 @@
|
||||
# Pepperstone US - Symbol Setup Guide
|
||||
|
||||
## Finding Correct Symbol Names in MetaTrader 5
|
||||
|
||||
### Step-by-Step Instructions:
|
||||
|
||||
1. **Open Market Watch Window**
|
||||
- Press `Ctrl+M` or go to `View > Market Watch`
|
||||
|
||||
2. **Show All Symbols**
|
||||
- Right-click in the Market Watch window
|
||||
- Select `Show All` or `Symbols`
|
||||
- This shows all available symbols from your broker
|
||||
|
||||
3. **Search for Your Symbols**
|
||||
- Use the search box in the Market Watch window
|
||||
- Search for: "AAPL", "MSFT", "NVDA", "TSLA", "BTCUSD", "XAUUSD"
|
||||
|
||||
4. **Note the Exact Symbol Name**
|
||||
- The symbol name shown in Market Watch is what you need to use
|
||||
- Common formats for Pepperstone US:
|
||||
- Stocks: `AAPL.US`, `MSFT.US`, `NVDA.US`, `TSLA.US`
|
||||
- Or: `NASDAQ:AAPL`, `NASDAQ:MSFT`, etc.
|
||||
- Or: Just `AAPL`, `MSFT`, etc. (if available)
|
||||
|
||||
5. **Add to Market Watch**
|
||||
- Double-click the symbol to add it to your Market Watch
|
||||
- Or right-click and select `Show`
|
||||
|
||||
6. **Update EA Inputs**
|
||||
- Open the EA inputs in MetaTrader 5
|
||||
- Update each symbol parameter with the exact name from Market Watch
|
||||
|
||||
## Common Pepperstone US Symbol Formats
|
||||
|
||||
### US Stocks:
|
||||
- **Apple**: `AAPL.US` or `NASDAQ:AAPL` or `AAPL`
|
||||
- **Microsoft**: `MSFT.US` or `NASDAQ:MSFT` or `MSFT`
|
||||
- **NVIDIA**: `NVDA.US` or `NASDAQ:NVDA` or `NVDA`
|
||||
- **Tesla**: `TSLA.US` or `NASDAQ:TSLA` or `TSLA`
|
||||
|
||||
### Cryptocurrencies:
|
||||
- **Bitcoin**: `BTCUSD` or `BTC/USD` or `BTCUSD.c`
|
||||
|
||||
### Precious Metals:
|
||||
- **Gold**: `XAUUSD` or `GOLD` or `XAU/USD`
|
||||
|
||||
## Important Notes:
|
||||
|
||||
1. **Symbol Names are Case-Sensitive**: Use exact capitalization
|
||||
2. **Add Symbols to Market Watch**: Symbols must be in Market Watch for the EA to access them
|
||||
3. **Check Trading Hours**: US stocks trade during US market hours (9:30 AM - 4:00 PM ET)
|
||||
4. **CFD vs Stock**: Pepperstone offers CFDs on stocks, not actual stocks
|
||||
5. **Spread**: Check the spread for each symbol - some may have wider spreads
|
||||
|
||||
## Troubleshooting:
|
||||
|
||||
### If Symbol Not Found:
|
||||
1. Check if you're connected to Pepperstone US server
|
||||
2. Verify your account type supports the symbol
|
||||
3. Contact Pepperstone support for symbol availability
|
||||
4. Check if symbol requires special account permissions
|
||||
|
||||
### If EA Shows "Symbol Not Available":
|
||||
1. Make sure symbol is added to Market Watch
|
||||
2. Verify symbol name matches exactly (including dots, colons, etc.)
|
||||
3. Check broker connection status
|
||||
4. Try different symbol format variations
|
||||
|
||||
## Testing Symbols:
|
||||
|
||||
You can test if a symbol works by:
|
||||
1. Opening a chart with that symbol
|
||||
2. If chart opens successfully, the symbol name is correct
|
||||
3. Use that exact symbol name in the EA inputs
|
||||
@@ -1,438 +0,0 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RSISecretSauceStrategy.mqh |
|
||||
//| RSI Secret Sauce: leave 70/30 zone, re-enter, peak/bottom entry |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
struct RSISecretSauceData
|
||||
{
|
||||
string symbol;
|
||||
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;
|
||||
ENUM_TIMEFRAMES timeframe;
|
||||
int rsiPeriod;
|
||||
double rsiOverbought;
|
||||
double rsiOversold;
|
||||
int rsiLookback;
|
||||
int peakBars;
|
||||
bool requireDivergence;
|
||||
double stopLossATR;
|
||||
double takeProfitATR;
|
||||
int atrPeriod;
|
||||
bool useSwingStopLoss;
|
||||
int swingLookback;
|
||||
int maxPositions;
|
||||
int minBarsBetweenTrades;
|
||||
int magicNumber;
|
||||
int slippage;
|
||||
};
|
||||
|
||||
bool RSS_UpdateIndicators(RSISecretSauceData& d);
|
||||
void RSS_UpdateRSIState(RSISecretSauceData& d);
|
||||
bool RSS_CanOpenNewPosition(RSISecretSauceData& d);
|
||||
void RSS_CheckEntrySignals(RSISecretSauceData& d, const double lotSize);
|
||||
bool RSS_IsRSIPeak(RSISecretSauceData& d);
|
||||
bool RSS_IsRSIBottom(RSISecretSauceData& d);
|
||||
void RSS_OpenPosition(RSISecretSauceData& d, ENUM_POSITION_TYPE type, const double lotSize);
|
||||
bool RSS_CalculateStops(RSISecretSauceData& d, double price, ENUM_POSITION_TYPE type, double& sl, double& tp);
|
||||
double RSS_GetSwingStopLoss(RSISecretSauceData& d, ENUM_POSITION_TYPE type);
|
||||
|
||||
bool InitRSISecretSauce(RSISecretSauceData& d,
|
||||
const string symbol,
|
||||
const ENUM_TIMEFRAMES timeframe,
|
||||
const int rsiPeriod,
|
||||
const double rsiOverbought,
|
||||
const double rsiOversold,
|
||||
const int rsiLookback,
|
||||
const int peakBars,
|
||||
const bool requireDivergence,
|
||||
const double stopLossATR,
|
||||
const double takeProfitATR,
|
||||
const int atrPeriod,
|
||||
const bool useSwingStopLoss,
|
||||
const int swingLookback,
|
||||
const int maxPositions,
|
||||
const int minBarsBetweenTrades,
|
||||
const int magicNumber,
|
||||
const int slippage)
|
||||
{
|
||||
d.symbol = symbol;
|
||||
if(StringLen(d.symbol) == 0)
|
||||
d.symbol = _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;
|
||||
|
||||
if(!SymbolSelect(d.symbol, true))
|
||||
{
|
||||
Print("RSISecretSauce: Symbol '", d.symbol, "' not available in Market Watch.");
|
||||
return false;
|
||||
}
|
||||
|
||||
d.timeframe = timeframe;
|
||||
d.rsiPeriod = rsiPeriod;
|
||||
d.rsiOverbought = rsiOverbought;
|
||||
d.rsiOversold = rsiOversold;
|
||||
d.rsiLookback = rsiLookback;
|
||||
d.peakBars = peakBars;
|
||||
d.requireDivergence = requireDivergence;
|
||||
d.stopLossATR = stopLossATR;
|
||||
d.takeProfitATR = takeProfitATR;
|
||||
d.atrPeriod = atrPeriod;
|
||||
d.useSwingStopLoss = useSwingStopLoss;
|
||||
d.swingLookback = swingLookback;
|
||||
d.maxPositions = maxPositions;
|
||||
d.minBarsBetweenTrades = minBarsBetweenTrades;
|
||||
d.magicNumber = magicNumber;
|
||||
d.slippage = slippage;
|
||||
|
||||
Sleep(100);
|
||||
int retry = 0;
|
||||
while(retry < 5 && d.rsiHandle == INVALID_HANDLE)
|
||||
{
|
||||
d.rsiHandle = iRSI(d.symbol, d.timeframe, d.rsiPeriod, PRICE_CLOSE);
|
||||
if(d.rsiHandle == INVALID_HANDLE)
|
||||
{
|
||||
if(GetLastError() == 4805 && retry < 4)
|
||||
{
|
||||
Sleep(1000);
|
||||
retry++;
|
||||
continue;
|
||||
}
|
||||
Print("RSISecretSauce: Failed to create RSI for '", d.symbol, "'");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
retry = 0;
|
||||
while(retry < 5 && d.atrHandle == INVALID_HANDLE)
|
||||
{
|
||||
d.atrHandle = iATR(d.symbol, d.timeframe, d.atrPeriod);
|
||||
if(d.atrHandle == INVALID_HANDLE)
|
||||
{
|
||||
if(GetLastError() == 4805 && retry < 4)
|
||||
{
|
||||
Sleep(1000);
|
||||
retry++;
|
||||
continue;
|
||||
}
|
||||
Print("RSISecretSauce: Failed to create ATR for '", d.symbol, "'");
|
||||
IndicatorRelease(d.rsiHandle);
|
||||
d.rsiHandle = INVALID_HANDLE;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
ArraySetAsSeries(d.rsiBuffer, true);
|
||||
ArraySetAsSeries(d.atrBuffer, true);
|
||||
ArraySetAsSeries(d.highBuffer, true);
|
||||
ArraySetAsSeries(d.lowBuffer, true);
|
||||
|
||||
d.trade.SetExpertMagicNumber(d.magicNumber);
|
||||
d.trade.SetDeviationInPoints(d.slippage);
|
||||
d.trade.SetTypeFilling(ORDER_FILLING_FOK);
|
||||
|
||||
d.isInitialized = true;
|
||||
Print("RSISecretSauce: Initialized for '", d.symbol, "' TF=", EnumToString(d.timeframe));
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeinitRSISecretSauce(RSISecretSauceData& 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;
|
||||
}
|
||||
|
||||
bool RSS_UpdateIndicators(RSISecretSauceData& d)
|
||||
{
|
||||
int rsiBarsNeeded = d.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.symbol, d.timeframe, 0, d.swingLookback + 5, d.highBuffer) < d.swingLookback + 5)
|
||||
return false;
|
||||
if(CopyLow(d.symbol, d.timeframe, 0, d.swingLookback + 5, d.lowBuffer) < d.swingLookback + 5)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RSS_UpdateRSIState(RSISecretSauceData& d)
|
||||
{
|
||||
double rsiCurrent = d.rsiBuffer[0];
|
||||
double rsiPrev = d.rsiBuffer[1];
|
||||
|
||||
if(rsiPrev >= d.rsiOverbought && rsiCurrent < d.rsiOverbought)
|
||||
{
|
||||
d.rsiWasOverbought = true;
|
||||
d.rsiBackInRange = true;
|
||||
d.lastRSIExitTime = TimeCurrent();
|
||||
d.lastRSIReentryTime = TimeCurrent();
|
||||
}
|
||||
|
||||
if(rsiPrev <= d.rsiOversold && rsiCurrent > d.rsiOversold)
|
||||
{
|
||||
d.rsiWasOversold = true;
|
||||
d.rsiBackInRange = true;
|
||||
d.lastRSIExitTime = TimeCurrent();
|
||||
d.lastRSIReentryTime = TimeCurrent();
|
||||
}
|
||||
|
||||
if(rsiCurrent >= d.rsiOverbought)
|
||||
{
|
||||
d.rsiWasOverbought = false;
|
||||
d.rsiBackInRange = false;
|
||||
}
|
||||
|
||||
if(rsiCurrent <= d.rsiOversold)
|
||||
{
|
||||
d.rsiWasOversold = false;
|
||||
d.rsiBackInRange = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool RSS_CanOpenNewPosition(RSISecretSauceData& d)
|
||||
{
|
||||
int positionCount = 0;
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||
{
|
||||
if(d.positionInfo.SelectByIndex(i))
|
||||
{
|
||||
if(d.positionInfo.Symbol() == d.symbol && d.positionInfo.Magic() == d.magicNumber)
|
||||
positionCount++;
|
||||
}
|
||||
}
|
||||
|
||||
if(positionCount >= d.maxPositions)
|
||||
return false;
|
||||
|
||||
if(d.lastTradeTime > 0)
|
||||
{
|
||||
int barsSince = Bars(d.symbol, d.timeframe, d.lastTradeTime, TimeCurrent());
|
||||
if(barsSince < d.minBarsBetweenTrades)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RSS_IsRSIPeak(RSISecretSauceData& d)
|
||||
{
|
||||
if(ArraySize(d.rsiBuffer) < d.peakBars + 2)
|
||||
return false;
|
||||
|
||||
double currentRSI = d.rsiBuffer[0];
|
||||
bool isPeak = true;
|
||||
|
||||
for(int i = 1; i <= d.peakBars; i++)
|
||||
{
|
||||
if(d.rsiBuffer[i] >= currentRSI)
|
||||
{
|
||||
isPeak = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(d.rsiBuffer[1] >= currentRSI)
|
||||
isPeak = false;
|
||||
|
||||
return isPeak;
|
||||
}
|
||||
|
||||
bool RSS_IsRSIBottom(RSISecretSauceData& d)
|
||||
{
|
||||
if(ArraySize(d.rsiBuffer) < d.peakBars + 2)
|
||||
return false;
|
||||
|
||||
double currentRSI = d.rsiBuffer[0];
|
||||
bool isBottom = true;
|
||||
|
||||
for(int i = 1; i <= d.peakBars; i++)
|
||||
{
|
||||
if(d.rsiBuffer[i] <= currentRSI)
|
||||
{
|
||||
isBottom = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(d.rsiBuffer[1] <= currentRSI)
|
||||
isBottom = false;
|
||||
|
||||
return isBottom;
|
||||
}
|
||||
|
||||
void RSS_CheckEntrySignals(RSISecretSauceData& d, const double lotSize)
|
||||
{
|
||||
if(d.rsiWasOverbought && d.rsiBackInRange)
|
||||
{
|
||||
if(d.rsiBuffer[0] < d.rsiOverbought)
|
||||
{
|
||||
if(RSS_IsRSIPeak(d))
|
||||
RSS_OpenPosition(d, POSITION_TYPE_BUY, lotSize);
|
||||
}
|
||||
}
|
||||
|
||||
if(d.rsiWasOversold && d.rsiBackInRange)
|
||||
{
|
||||
if(d.rsiBuffer[0] > d.rsiOversold)
|
||||
{
|
||||
if(RSS_IsRSIBottom(d))
|
||||
RSS_OpenPosition(d, POSITION_TYPE_SELL, lotSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool RSS_CalculateStops(RSISecretSauceData& 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 * d.stopLossATR;
|
||||
double tpDistance = atrValue * d.takeProfitATR;
|
||||
|
||||
int digits = (int)SymbolInfoInteger(d.symbol, SYMBOL_DIGITS);
|
||||
double point = SymbolInfoDouble(d.symbol, SYMBOL_POINT);
|
||||
int stopsLevel = (int)SymbolInfoInteger(d.symbol, SYMBOL_TRADE_STOPS_LEVEL);
|
||||
double minStopDistance = MathMax(stopsLevel * point, point * 10);
|
||||
|
||||
if(d.useSwingStopLoss)
|
||||
{
|
||||
double swingStop = RSS_GetSwingStopLoss(d, 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;
|
||||
}
|
||||
|
||||
double RSS_GetSwingStopLoss(RSISecretSauceData& d, ENUM_POSITION_TYPE type)
|
||||
{
|
||||
if(type == POSITION_TYPE_BUY)
|
||||
{
|
||||
double lowestLow = d.lowBuffer[0];
|
||||
for(int i = 1; i < d.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 < d.swingLookback && i < ArraySize(d.highBuffer); i++)
|
||||
{
|
||||
if(d.highBuffer[i] > highestHigh)
|
||||
highestHigh = d.highBuffer[i];
|
||||
}
|
||||
return highestHigh;
|
||||
}
|
||||
|
||||
void RSS_OpenPosition(RSISecretSauceData& d, ENUM_POSITION_TYPE type, const double lotSize)
|
||||
{
|
||||
double price = (type == POSITION_TYPE_BUY) ?
|
||||
SymbolInfoDouble(d.symbol, SYMBOL_ASK) :
|
||||
SymbolInfoDouble(d.symbol, 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.symbol, 0, sl, tp, comment);
|
||||
else
|
||||
result = d.trade.Sell(lotSize, d.symbol, 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 ProcessRSISecretSauce(RSISecretSauceData& d, const double lotSize)
|
||||
{
|
||||
if(!d.isInitialized)
|
||||
return;
|
||||
|
||||
int requiredBars = MathMax(d.rsiLookback, d.swingLookback) + 10;
|
||||
if(Bars(d.symbol, d.timeframe) < requiredBars)
|
||||
return;
|
||||
|
||||
datetime currentBarTime = iTime(d.symbol, d.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);
|
||||
}
|
||||
@@ -1,437 +0,0 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| UnitedProfitPanel.mqh — chart object P&L by strategy / magic |
|
||||
//| One OBJ_LABEL per line (MT5 often ignores \n in a single label). |
|
||||
//| Include only after all United EA `input` declarations. |
|
||||
//+------------------------------------------------------------------+
|
||||
#ifndef UNITED_PROFIT_PANEL_MQH
|
||||
#define UNITED_PROFIT_PANEL_MQH
|
||||
|
||||
#define UNITED_PNL_MAX_LINES 48
|
||||
|
||||
struct UnitedPnLRow
|
||||
{
|
||||
string name;
|
||||
long magic;
|
||||
};
|
||||
|
||||
UnitedPnLRow g_unitedPnLRows[];
|
||||
int g_unitedPnLRowCount = 0;
|
||||
int g_unitedPnL_visibleLineCount = 0;
|
||||
|
||||
string UnitedPnL_Obj(const string suffix) { return "UnitedPnL_" + suffix; }
|
||||
|
||||
long UnitedPnL_ChartId() { return ChartID(); }
|
||||
|
||||
string UnitedPnL_LineObjName(const int idx) { return UnitedPnL_Obj("L") + IntegerToString(idx); }
|
||||
|
||||
datetime UnitedPnL_StartOfYear(const datetime now)
|
||||
{
|
||||
MqlDateTime dt;
|
||||
TimeToStruct(now, dt);
|
||||
dt.mon = 1;
|
||||
dt.day = 1;
|
||||
dt.hour = 0;
|
||||
dt.min = 0;
|
||||
dt.sec = 0;
|
||||
return StructToTime(dt);
|
||||
}
|
||||
|
||||
datetime UnitedPnL_StartOfMonth(const datetime now)
|
||||
{
|
||||
MqlDateTime dt;
|
||||
TimeToStruct(now, dt);
|
||||
dt.day = 1;
|
||||
dt.hour = 0;
|
||||
dt.min = 0;
|
||||
dt.sec = 0;
|
||||
return StructToTime(dt);
|
||||
}
|
||||
|
||||
int UnitedPnL_FindRowIndex(const long magic)
|
||||
{
|
||||
for(int r = 0; r < g_unitedPnLRowCount; r++)
|
||||
{
|
||||
if(g_unitedPnLRows[r].magic == magic)
|
||||
return r;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool UnitedPnL_ScanDealsOnce(double &yearPl[], double &monthPl[], const datetime y0, const datetime m0, const datetime now)
|
||||
{
|
||||
const int R = g_unitedPnLRowCount;
|
||||
ArrayResize(yearPl, R);
|
||||
ArrayResize(monthPl, R);
|
||||
for(int j = 0; j < R; j++)
|
||||
{
|
||||
yearPl[j] = 0.0;
|
||||
monthPl[j] = 0.0;
|
||||
}
|
||||
|
||||
if(R <= 0 || y0 >= now)
|
||||
return true;
|
||||
|
||||
datetime to = now;
|
||||
if(to <= y0)
|
||||
to = y0 + 1;
|
||||
|
||||
if(!HistorySelect(y0, to))
|
||||
return false;
|
||||
|
||||
const int n = HistoryDealsTotal();
|
||||
for(int i = 0; i < n; i++)
|
||||
{
|
||||
const ulong dealTicket = HistoryDealGetTicket(i);
|
||||
if(dealTicket == 0)
|
||||
continue;
|
||||
|
||||
const long mg = (long)HistoryDealGetInteger(dealTicket, DEAL_MAGIC);
|
||||
const int idx = UnitedPnL_FindRowIndex(mg);
|
||||
if(idx < 0)
|
||||
continue;
|
||||
|
||||
const datetime dt = (datetime)HistoryDealGetInteger(dealTicket, DEAL_TIME);
|
||||
const double p = HistoryDealGetDouble(dealTicket, DEAL_PROFIT)
|
||||
+ HistoryDealGetDouble(dealTicket, DEAL_SWAP)
|
||||
+ HistoryDealGetDouble(dealTicket, DEAL_COMMISSION);
|
||||
|
||||
yearPl[idx] += p;
|
||||
if(dt >= m0)
|
||||
monthPl[idx] += p;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
double UnitedPnL_SumFloatingForMagic(const long magic)
|
||||
{
|
||||
double sum = 0.0;
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||
{
|
||||
const ulong ticket = PositionGetTicket(i);
|
||||
if(ticket == 0)
|
||||
continue;
|
||||
if(!PositionSelectByTicket(ticket))
|
||||
continue;
|
||||
if((long)PositionGetInteger(POSITION_MAGIC) != magic)
|
||||
continue;
|
||||
sum += PositionGetDouble(POSITION_PROFIT);
|
||||
sum += PositionGetDouble(POSITION_SWAP);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
void UnitedPnL_CollectRows()
|
||||
{
|
||||
g_unitedPnLRowCount = 0;
|
||||
ArrayResize(g_unitedPnLRows, 24);
|
||||
|
||||
if(EnableDarvasBox)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "DarvasBox";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)DB_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableEMASlopeDistance)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "EMASlope";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)ES_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSICrossOverReversal)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RSICrossOver";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RC_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSIMidPointHijack)
|
||||
{
|
||||
if(RM_InpEnableRSIFollow)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RM_RSIFollow";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RM_InpMagicNumberRSIFollow;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(RM_InpEnableRSIReverse)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RM_RSIRev";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RM_InpMagicNumberRSIReverse;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(RM_InpEnableEMACross)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RM_EMACross";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RM_InpMagicNumberEMACross;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
}
|
||||
if(EnableRSIScalpingAPPL)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RS_Scalp_AAPL";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RS_APPL_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSIScalpingBTCUSD)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RS_Scalp_BTC";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RS_BTCUSD_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSIScalpingNVDA)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RS_Scalp_NVDA";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RS_NVDA_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSIScalpingTSLA)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RS_Scalp_TSLA";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RS_TSLA_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSIScalpingXAUUSD)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RS_Scalp_XAU";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RS_XAUUSD_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSIReversalEURUSD)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RRA_EURUSD";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RRA_EURUSD_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSIReversalAUDUSD)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "RRA_AUDUSD";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RRA_AUDUSD_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableRSISecretSauceXAUUSD)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "SecretSauce";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)RSS_XAUUSD_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
if(EnableSuperEMA)
|
||||
{
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].name = "SuperEMA";
|
||||
g_unitedPnLRows[g_unitedPnLRowCount].magic = (long)SE_MagicNumber;
|
||||
g_unitedPnLRowCount++;
|
||||
}
|
||||
|
||||
ArrayResize(g_unitedPnLRows, MathMax(g_unitedPnLRowCount, 1));
|
||||
}
|
||||
|
||||
void UnitedPnL_EnsureObjects()
|
||||
{
|
||||
const long ch = UnitedPnL_ChartId();
|
||||
const string bg = UnitedPnL_Obj("BG");
|
||||
if(ObjectFind(ch, bg) < 0)
|
||||
{
|
||||
if(!ObjectCreate(ch, bg, OBJ_RECTANGLE_LABEL, 0, 0, 0))
|
||||
{
|
||||
Print("UnitedPnL: BG ObjectCreate failed, err=", GetLastError());
|
||||
return;
|
||||
}
|
||||
ObjectSetInteger(ch, bg, OBJPROP_BORDER_TYPE, BORDER_FLAT);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_COLOR, C'90,90,90');
|
||||
ObjectSetInteger(ch, bg, OBJPROP_BGCOLOR, C'25,25,30');
|
||||
ObjectSetInteger(ch, bg, OBJPROP_WIDTH, 1);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_BACK, false);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_SELECTABLE, false);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_HIDDEN, false);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_ZORDER, 0);
|
||||
}
|
||||
|
||||
for(int i = 0; i < UNITED_PNL_MAX_LINES; i++)
|
||||
{
|
||||
const string nm = UnitedPnL_LineObjName(i);
|
||||
if(ObjectFind(ch, nm) >= 0)
|
||||
continue;
|
||||
if(!ObjectCreate(ch, nm, OBJ_LABEL, 0, 0, 0))
|
||||
{
|
||||
Print("UnitedPnL: line ", i, " ObjectCreate failed, err=", GetLastError());
|
||||
continue;
|
||||
}
|
||||
ObjectSetString(ch, nm, OBJPROP_FONT, "Arial");
|
||||
ObjectSetInteger(ch, nm, OBJPROP_FONTSIZE, UnitedPanel_FontSize);
|
||||
ObjectSetInteger(ch, nm, OBJPROP_BACK, false);
|
||||
ObjectSetInteger(ch, nm, OBJPROP_SELECTABLE, false);
|
||||
ObjectSetInteger(ch, nm, OBJPROP_HIDDEN, false);
|
||||
ObjectSetInteger(ch, nm, OBJPROP_ZORDER, 2);
|
||||
}
|
||||
}
|
||||
|
||||
void UnitedPnL_ApplyGeometry()
|
||||
{
|
||||
if(!UnitedPanel_Enable)
|
||||
return;
|
||||
const long ch = UnitedPnL_ChartId();
|
||||
const string bg = UnitedPnL_Obj("BG");
|
||||
if(ObjectFind(ch, bg) < 0)
|
||||
return;
|
||||
|
||||
const int lineH = UnitedPanel_FontSize + 5;
|
||||
const int vis = MathMax(g_unitedPnL_visibleLineCount, 6);
|
||||
const int h = UnitedPanel_YMargin * 2 + lineH * vis;
|
||||
|
||||
const ENUM_BASE_CORNER corner = (ENUM_BASE_CORNER)UnitedPanel_Corner;
|
||||
ObjectSetInteger(ch, bg, OBJPROP_CORNER, corner);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_XDISTANCE, UnitedPanel_X);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_YDISTANCE, UnitedPanel_Y);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_XSIZE, UnitedPanel_Width);
|
||||
ObjectSetInteger(ch, bg, OBJPROP_YSIZE, MathMax(h, 80));
|
||||
|
||||
const int baseX = UnitedPanel_X + UnitedPanel_XMargin;
|
||||
const int baseY = UnitedPanel_Y + UnitedPanel_YMargin;
|
||||
for(int i = 0; i < UNITED_PNL_MAX_LINES; i++)
|
||||
{
|
||||
const string nm = UnitedPnL_LineObjName(i);
|
||||
if(ObjectFind(ch, nm) < 0)
|
||||
continue;
|
||||
ObjectSetInteger(ch, nm, OBJPROP_CORNER, corner);
|
||||
ObjectSetInteger(ch, nm, OBJPROP_XDISTANCE, baseX);
|
||||
ObjectSetInteger(ch, nm, OBJPROP_YDISTANCE, baseY + i * lineH);
|
||||
ObjectSetInteger(ch, nm, OBJPROP_FONTSIZE, UnitedPanel_FontSize);
|
||||
}
|
||||
}
|
||||
|
||||
void UnitedPnL_RefreshText()
|
||||
{
|
||||
const long ch = UnitedPnL_ChartId();
|
||||
const string bg = UnitedPnL_Obj("BG");
|
||||
if(ObjectFind(ch, bg) < 0)
|
||||
return;
|
||||
|
||||
UnitedPnL_CollectRows();
|
||||
|
||||
const datetime now = TimeCurrent();
|
||||
const datetime y0 = UnitedPnL_StartOfYear(now);
|
||||
const datetime m0 = UnitedPnL_StartOfMonth(now);
|
||||
const string cur = AccountInfoString(ACCOUNT_CURRENCY);
|
||||
|
||||
double yearPl[];
|
||||
double monthPl[];
|
||||
const bool histOk = UnitedPnL_ScanDealsOnce(yearPl, monthPl, y0, m0, now);
|
||||
const string histNote = histOk ? "" : " [hist fail: Toolbox>History]";
|
||||
|
||||
double sumY = 0.0, sumM = 0.0, sumF = 0.0;
|
||||
|
||||
string lines[];
|
||||
int n = 0;
|
||||
ArrayResize(lines, UNITED_PNL_MAX_LINES);
|
||||
|
||||
lines[n++] = "United EA " + cur + histNote;
|
||||
lines[n++] = UnitedPanel_ShowFloating
|
||||
? "Y/M = closed deals | F = open P/L+swap"
|
||||
: "Y/M = closed deal P/L+swap+comm";
|
||||
lines[n++] = "----------------------------------";
|
||||
|
||||
for(int r = 0; r < g_unitedPnLRowCount; r++)
|
||||
{
|
||||
const long mg = g_unitedPnLRows[r].magic;
|
||||
double yv = 0.0, mv = 0.0;
|
||||
if(histOk && r < ArraySize(yearPl))
|
||||
yv = yearPl[r];
|
||||
if(histOk && r < ArraySize(monthPl))
|
||||
mv = monthPl[r];
|
||||
const double fv = UnitedPanel_ShowFloating ? UnitedPnL_SumFloatingForMagic(mg) : 0.0;
|
||||
sumY += yv;
|
||||
sumM += mv;
|
||||
sumF += fv;
|
||||
}
|
||||
|
||||
string tot = "TOTAL Y:" + DoubleToString(sumY, 2) + " M:" + DoubleToString(sumM, 2);
|
||||
if(UnitedPanel_ShowFloating)
|
||||
tot += " F:" + DoubleToString(sumF, 2);
|
||||
lines[n++] = tot;
|
||||
lines[n++] = "----------------------------------";
|
||||
|
||||
if(g_unitedPnLRowCount == 0)
|
||||
lines[n++] = "(no strategies enabled)";
|
||||
else
|
||||
{
|
||||
for(int r = 0; r < g_unitedPnLRowCount; r++)
|
||||
{
|
||||
if(n >= UNITED_PNL_MAX_LINES - 1)
|
||||
break;
|
||||
const long mg = g_unitedPnLRows[r].magic;
|
||||
double yv = 0.0, mv = 0.0;
|
||||
if(histOk && r < ArraySize(yearPl))
|
||||
yv = yearPl[r];
|
||||
if(histOk && r < ArraySize(monthPl))
|
||||
mv = monthPl[r];
|
||||
const double fv = UnitedPanel_ShowFloating ? UnitedPnL_SumFloatingForMagic(mg) : 0.0;
|
||||
|
||||
lines[n++] = g_unitedPnLRows[r].name + " [" + IntegerToString((int)mg) + "]";
|
||||
string row2 = " Y:" + DoubleToString(yv, 2) + " M:" + DoubleToString(mv, 2);
|
||||
if(UnitedPanel_ShowFloating)
|
||||
row2 += " F:" + DoubleToString(fv, 2);
|
||||
lines[n++] = row2;
|
||||
}
|
||||
}
|
||||
|
||||
g_unitedPnL_visibleLineCount = n;
|
||||
|
||||
color c = clrSilver;
|
||||
if(sumM > 0.0001)
|
||||
c = clrPaleGreen;
|
||||
else if(sumM < -0.0001)
|
||||
c = clrTomato;
|
||||
|
||||
for(int i = 0; i < UNITED_PNL_MAX_LINES; i++)
|
||||
{
|
||||
const string nm = UnitedPnL_LineObjName(i);
|
||||
if(ObjectFind(ch, nm) < 0)
|
||||
continue;
|
||||
if(i < n)
|
||||
{
|
||||
ObjectSetString(ch, nm, OBJPROP_TEXT, lines[i]);
|
||||
ObjectSetInteger(ch, nm, OBJPROP_COLOR, c);
|
||||
}
|
||||
else
|
||||
{
|
||||
ObjectSetString(ch, nm, OBJPROP_TEXT, "");
|
||||
}
|
||||
}
|
||||
|
||||
UnitedPnL_ApplyGeometry();
|
||||
ChartRedraw(ch);
|
||||
}
|
||||
|
||||
void UnitedProfitPanelInit()
|
||||
{
|
||||
if(!UnitedPanel_Enable)
|
||||
return;
|
||||
UnitedPnL_EnsureObjects();
|
||||
UnitedPnL_CollectRows();
|
||||
g_unitedPnL_visibleLineCount = 6;
|
||||
UnitedPnL_ApplyGeometry();
|
||||
UnitedPnL_RefreshText();
|
||||
}
|
||||
|
||||
void UnitedProfitPanelDeinit()
|
||||
{
|
||||
ObjectsDeleteAll(UnitedPnL_ChartId(), "UnitedPnL_");
|
||||
}
|
||||
|
||||
void UnitedProfitPanelRefresh()
|
||||
{
|
||||
if(!UnitedPanel_Enable)
|
||||
return;
|
||||
UnitedPnL_RefreshText();
|
||||
}
|
||||
|
||||
void UnitedProfitPanelOnChartEvent(const int id)
|
||||
{
|
||||
if(!UnitedPanel_Enable)
|
||||
return;
|
||||
if(id == CHARTEVENT_CHART_CHANGE)
|
||||
{
|
||||
UnitedPnL_CollectRows();
|
||||
UnitedPnL_ApplyGeometry();
|
||||
ChartRedraw(UnitedPnL_ChartId());
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -1,6 +0,0 @@
|
||||
\begin{figure}[t]
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{frontline/MQL5/_united_dynamic/report/pnl_by_magic_robot.pdf}
|
||||
\caption{Net closed P\&L by robot magic number from the united\_dynamic live report export. Bars show net realized P\&L (USD) and the label \texttt{n} is the number of closed trades. Because the MT5 report does not expose per-deal magic directly in this extract, XAUUSD trades that come from multiple XAU strategies are shown as one mixed bucket.}
|
||||
\label{fig:united-dynamic-pnl-by-magic}
|
||||
\end{figure}
|
||||
@@ -1,6 +0,0 @@
|
||||
\begin{figure*}[t]
|
||||
\centering
|
||||
\includegraphics[width=\textwidth]{frontline/MQL5/_united_dynamic/report/pnl_timeseries_by_robot.pdf}
|
||||
\caption{Cumulative closed P\&L over time split by robot. Non-XAU robots are mapped directly by symbol-to-magic configuration; XAU trades are assigned by ticket-matched strategy comments when available, and otherwise grouped into an unattributed XAU bucket.}
|
||||
\label{fig:united-dynamic-pnl-timeseries-by-robot}
|
||||
\end{figure*}
|
||||
@@ -1,6 +0,0 @@
|
||||
\begin{figure}[t]
|
||||
\centering
|
||||
\includegraphics[width=\linewidth]{frontline/MQL5/_united_dynamic/report/pnl_timeseries_line.pdf}
|
||||
\caption{Cumulative closed P\&L over time for the united\_dynamic account history in \texttt{ReportHistory-51389369.xlsx}. The curve is formed by sorting closed deals by close timestamp and cumulatively summing realized deal P\&L.}
|
||||
\label{fig:united-dynamic-pnl-timeseries}
|
||||
\end{figure}
|
||||
@@ -1,9 +0,0 @@
|
||||
symbol,magic_number,robot,count,sum
|
||||
MSFT.US,20002,RSI Scalping MSFT,12,-1042.0
|
||||
EURUSD,30001,RSI Reversal Asian EURUSD,20,-264.84999999999997
|
||||
BTCUSD,123459123,RSI Scalping BTCUSD,11,-203.41000000000003
|
||||
NVDA.US,20003,RSI Scalping NVDA,32,-42.54000000000002
|
||||
AAPL.US,20001,RSI Scalping AAPL,5,-2.0
|
||||
AUDUSD,30002,RSI Reversal Asian AUDUSD,14,78.08000000000001
|
||||
XAUUSD,MIXED,XAUUSD Multi-Strategy Bucket,291,1953.66
|
||||
TSLA.US,125421321,RSI Scalping TSLA,16,2352.57
|
||||
|
|
Before Width: | Height: | Size: 137 KiB |
@@ -1,386 +0,0 @@
|
||||
close_time,125421321 RSI Scalping TSLA,XAU Unattributed (multiple robots),129102315 RSI Scalping XAUUSD,30002 RSI Reversal Asian AUDUSD,20003 RSI Scalping NVDA,12350 EMA Slope Distance (XAU),123459123 RSI Scalping BTCUSD,30001 RSI Reversal Asian EURUSD,20002 RSI Scalping MSFT
|
||||
2026-01-05 08:00:00,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0
|
||||
2026-01-05 12:06:01,0.0,0.0,0.0,0.0,0.0,61.98,0.0,0.0,0.0
|
||||
2026-01-05 18:06:21,0.0,0.0,0.0,0.0,0.0,86.07,0.0,0.0,0.0
|
||||
2026-01-06 07:55:38,0.0,0.0,0.0,0.0,0.0,86.07,0.0,-3.0,0.0
|
||||
2026-01-06 08:00:00,0.0,0.0,0.0,4.2,0.0,86.07,0.0,-3.0,0.0
|
||||
2026-01-06 12:00:00,0.0,0.0,-81.78,4.2,0.0,86.07,0.0,-3.0,0.0
|
||||
2026-01-06 15:13:04,0.0,0.0,-78.69,4.2,0.0,86.07,0.0,-3.0,0.0
|
||||
2026-01-06 16:39:10,0.0,0.0,-78.69,4.2,0.0,111.69,0.0,-3.0,0.0
|
||||
2026-01-06 19:42:51,0.0,0.0,-78.69,4.2,0.0,101.72999999999999,0.0,-3.0,0.0
|
||||
2026-01-07 08:00:00,0.0,0.0,-78.69,12.2,0.0,101.72999999999999,0.0,-3.0,0.0
|
||||
2026-01-07 11:00:00,0.0,0.0,-78.69,12.2,0.0,29.189999999999984,0.0,-3.0,0.0
|
||||
2026-01-08 08:21:15,0.0,0.0,-78.69,12.2,0.0,29.339999999999982,0.0,-3.0,0.0
|
||||
2026-01-08 18:00:00,0.0,0.0,-78.69,12.2,0.0,29.339999999999982,0.0,-3.0,-49.1
|
||||
2026-01-09 07:00:00,0.0,0.0,-78.69,12.2,0.0,29.339999999999982,0.0,-3.0,-49.1
|
||||
2026-01-12 03:00:00,0.0,0.0,296.85,12.2,0.0,29.339999999999982,0.0,-3.0,-49.1
|
||||
2026-01-12 05:43:32,0.0,0.0,296.85,12.2,0.0,36.11999999999998,0.0,-3.0,-49.1
|
||||
2026-01-12 06:00:00,0.0,0.0,296.85,12.2,0.0,35.399999999999984,0.0,-3.0,-49.1
|
||||
2026-01-12 06:01:28,0.0,0.0,296.85,12.2,0.0,35.399999999999984,0.0,-3.8,-49.1
|
||||
2026-01-13 00:01:01,0.0,0.0,296.85,12.2,0.0,35.399999999999984,0.0,-10.2,-49.1
|
||||
2026-01-13 03:00:00,0.0,0.0,246.06000000000003,12.2,0.0,35.399999999999984,0.0,-10.2,-49.1
|
||||
2026-01-13 16:28:43,0.0,0.0,267.48,12.2,0.0,56.819999999999986,0.0,-10.2,-49.1
|
||||
2026-01-13 20:00:00,0.0,0.0,267.48,12.2,0.0,-63.00000000000001,0.0,-10.2,-49.1
|
||||
2026-01-14 05:28:14,0.0,0.0,267.48,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-14 07:19:03,0.0,0.0,305.1,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-14 15:00:44,0.0,-11.19,305.1,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-14 17:11:47,49.1,-11.19,305.1,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-15 03:00:00,49.1,-74.88,305.1,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-15 07:28:43,49.1,-69.75,305.1,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-15 17:00:00,49.1,-141.66,305.1,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-16 08:00:00,49.1,-152.35999999999999,305.1,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-19 01:01:01,49.1,-348.98,305.1,12.2,0.0,-72.63000000000001,0.0,-10.2,-49.1
|
||||
2026-01-19 02:08:19,49.1,-348.98,305.1,12.2,0.0,-72.63000000000001,0.0,-0.6999999999999993,-49.1
|
||||
2026-01-19 03:00:46,49.1,-354.74,305.1,12.2,0.0,-72.63000000000001,0.0,-0.6999999999999993,-49.1
|
||||
2026-01-19 04:00:26,49.1,-354.74,305.1,12.2,0.0,-72.63000000000001,0.0,9.4,-49.1
|
||||
2026-01-20 00:01:00,49.1,-354.74,305.1,12.2,0.0,-72.63000000000001,0.0,-5.199999999999999,-49.1
|
||||
2026-01-20 07:24:12,49.1,-282.38,305.1,12.2,0.0,-72.63000000000001,0.0,-5.199999999999999,-49.1
|
||||
2026-01-20 08:00:00,49.1,-282.38,305.1,-4.199999999999999,0.0,-72.63000000000001,0.0,-5.199999999999999,-49.1
|
||||
2026-01-20 09:51:16,49.1,-271.4,305.1,-4.199999999999999,0.0,-72.63000000000001,0.0,-5.199999999999999,-49.1
|
||||
2026-01-20 10:19:24,49.1,-254.29999999999998,305.1,-4.199999999999999,0.0,-72.63000000000001,0.0,-5.199999999999999,-49.1
|
||||
2026-01-20 12:00:07,49.1,-247.93999999999997,305.1,-4.199999999999999,0.0,-72.63000000000001,0.0,-5.199999999999999,-49.1
|
||||
2026-01-20 15:34:19,49.1,-237.22999999999996,305.1,-4.199999999999999,0.0,-72.63000000000001,0.0,-5.199999999999999,-49.1
|
||||
2026-01-21 00:01:00,49.1,-237.22999999999996,305.1,-4.199999999999999,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-21 17:24:43,49.1,-145.00999999999996,305.1,-4.199999999999999,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-22 02:00:00,49.1,-361.5799999999999,305.1,-4.199999999999999,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-22 08:00:00,49.1,-459.2299999999999,305.1,-31.4,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-22 18:00:00,23.700000000000003,-459.2299999999999,305.1,-31.4,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-22 18:30:02,23.700000000000003,-434.1799999999999,305.1,-31.4,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-22 21:27:07,23.700000000000003,-334.9099999999999,305.1,-31.4,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-22 22:00:00,23.700000000000003,-335.6599999999999,305.1,-31.4,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-23 03:00:00,23.700000000000003,-498.8299999999999,305.1,-31.4,0.0,-72.63000000000001,0.0,-81.3,-49.1
|
||||
2026-01-23 04:44:42,23.700000000000003,-498.8299999999999,305.1,-31.4,0.0,-72.63000000000001,0.0,-81.39999999999999,-49.1
|
||||
2026-01-23 05:16:54,23.700000000000003,-506.74999999999994,305.1,-31.4,0.0,-72.63000000000001,0.0,-81.39999999999999,-49.1
|
||||
2026-01-23 08:00:00,23.700000000000003,-506.74999999999994,305.1,-46.0,0.0,-72.63000000000001,0.0,-81.39999999999999,-49.1
|
||||
2026-01-23 11:00:00,23.700000000000003,-388.3399999999999,305.1,-46.0,0.0,-72.63000000000001,0.0,-81.39999999999999,-49.1
|
||||
2026-01-26 04:00:00,23.700000000000003,34.3300000000001,305.1,-46.0,0.0,-72.63000000000001,0.0,-81.39999999999999,-49.1
|
||||
2026-01-26 08:00:00,23.700000000000003,34.3300000000001,305.1,-34.4,0.0,-72.63000000000001,0.0,-81.39999999999999,-49.1
|
||||
2026-01-26 21:00:00,23.700000000000003,65.1700000000001,305.1,-34.4,0.0,-72.63000000000001,0.0,-81.39999999999999,-49.1
|
||||
2026-01-27 00:01:00,23.700000000000003,65.1700000000001,305.1,-34.4,0.0,-72.63000000000001,0.0,-214.09999999999997,-49.1
|
||||
2026-01-27 04:00:00,23.700000000000003,-41.089999999999904,305.1,-34.4,0.0,-72.63000000000001,0.0,-214.09999999999997,-49.1
|
||||
2026-01-27 05:07:00,23.700000000000003,-41.089999999999904,305.1,-34.4,0.0,-72.63000000000001,0.0,-207.59999999999997,-49.1
|
||||
2026-01-27 06:09:45,23.700000000000003,-40.60999999999991,305.1,-34.4,0.0,-72.63000000000001,0.0,-207.59999999999997,-49.1
|
||||
2026-01-27 08:50:00,23.700000000000003,-5.089999999999904,305.1,-34.4,0.0,-72.63000000000001,0.0,-207.59999999999997,-49.1
|
||||
2026-01-27 09:12:16,23.700000000000003,-0.25999999999990386,305.1,-34.4,0.0,-72.63000000000001,0.0,-207.59999999999997,-49.1
|
||||
2026-01-27 11:45:33,23.700000000000003,2.560000000000096,305.1,-34.4,0.0,-72.63000000000001,0.0,-207.59999999999997,-49.1
|
||||
2026-01-27 16:00:00,23.700000000000003,-61.159999999999904,305.1,-34.4,0.0,-72.63000000000001,0.0,-207.59999999999997,-49.1
|
||||
2026-01-27 17:03:41,54.300000000000004,-61.159999999999904,305.1,-34.4,0.0,-72.63000000000001,0.0,-207.59999999999997,-49.1
|
||||
2026-01-27 23:00:30,54.300000000000004,159.3400000000001,305.1,-34.4,0.0,-72.63000000000001,0.0,-207.59999999999997,-49.1
|
||||
2026-01-28 03:31:17,54.300000000000004,159.3400000000001,305.1,-34.4,0.0,-72.63000000000001,0.0,-171.69999999999996,-49.1
|
||||
2026-01-28 07:01:59,54.300000000000004,588.97,305.1,-34.4,0.0,-72.63000000000001,0.0,-171.69999999999996,-49.1
|
||||
2026-01-28 08:00:00,54.300000000000004,588.97,305.1,-27.2,0.0,-72.63000000000001,0.0,-171.69999999999996,-49.1
|
||||
2026-01-28 09:00:38,54.300000000000004,601.69,305.1,-27.2,0.0,-72.63000000000001,0.0,-171.69999999999996,-49.1
|
||||
2026-01-28 10:12:05,54.300000000000004,603.82,305.1,-27.2,0.0,-72.63000000000001,0.0,-171.69999999999996,-49.1
|
||||
2026-01-28 14:12:22,54.300000000000004,604.0,305.1,-27.2,0.0,-72.63000000000001,0.0,-171.69999999999996,-49.1
|
||||
2026-01-28 17:12:17,54.300000000000004,647.86,305.1,-27.2,0.0,-72.63000000000001,0.0,-171.69999999999996,-49.1
|
||||
2026-01-28 18:53:19,54.300000000000004,647.86,305.1,-27.2,0.0,-72.63000000000001,0.0,-171.69999999999996,2.3999999999999986
|
||||
2026-01-28 19:08:19,54.300000000000004,645.46,305.1,-27.2,0.0,-72.63000000000001,0.0,-171.69999999999996,2.3999999999999986
|
||||
2026-01-29 02:00:01,54.300000000000004,-0.8899999999999864,305.1,-27.2,0.0,-72.63000000000001,0.0,-171.69999999999996,2.3999999999999986
|
||||
2026-01-29 07:58:06,54.300000000000004,-0.8899999999999864,305.1,-27.2,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-29 08:00:00,54.300000000000004,-0.8899999999999864,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-29 12:38:43,54.300000000000004,8.890000000000013,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-30 01:01:01,54.300000000000004,-650.63,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-30 04:00:00,54.300000000000004,-1064.69,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-30 06:00:34,54.300000000000004,-1001.1800000000001,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-30 07:00:00,54.300000000000004,-1003.58,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-30 09:00:00,54.300000000000004,-1044.07,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-30 11:00:10,54.300000000000004,-873.4,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-30 20:00:04,54.300000000000004,-397.51,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-01-30 23:00:03,54.300000000000004,-318.01,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-03 02:00:00,54.300000000000004,-244.57,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-03 04:00:10,54.300000000000004,-85.47999999999999,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-03 07:13:20,54.300000000000004,-60.609999999999985,305.1,-57.8,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-03 08:00:00,54.300000000000004,-60.609999999999985,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-03 08:12:16,54.300000000000004,-30.879999999999985,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-03 09:16:31,54.300000000000004,-23.319999999999986,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-03 10:24:18,54.300000000000004,32.72000000000001,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-03 17:27:59,154.4,32.72000000000001,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-159.99999999999997,2.3999999999999986
|
||||
2026-02-04 04:50:05,154.4,32.72000000000001,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-152.49999999999997,2.3999999999999986
|
||||
2026-02-04 07:00:00,154.4,31.830000000000013,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-152.49999999999997,2.3999999999999986
|
||||
2026-02-04 07:00:02,154.4,482.03999999999996,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-152.49999999999997,2.3999999999999986
|
||||
2026-02-04 12:13:15,154.4,487.61999999999995,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-152.49999999999997,2.3999999999999986
|
||||
2026-02-04 18:24:11,154.4,558.9,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-152.49999999999997,2.3999999999999986
|
||||
2026-02-05 00:01:00,154.4,558.9,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-05 01:01:00,154.4,305.93999999999994,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-05 04:00:00,154.4,145.13999999999993,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-05 08:00:12,154.4,155.80999999999992,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-05 17:48:31,154.4,177.07999999999993,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-05 23:01:58,154.4,181.36999999999992,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-06 01:01:01,154.4,131.0399999999999,305.1,-61.599999999999994,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-06 04:01:08,154.4,131.0399999999999,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-06 08:00:00,154.4,-452.8200000000001,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-09 03:51:31,154.4,-249.7200000000001,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-09 03:59:22,154.4,-83.5700000000001,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-09 07:00:00,154.4,-87.02000000000011,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-09 13:00:00,154.4,73.72999999999989,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-09 15:00:02,154.4,69.55999999999989,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-09 17:43:21,-126.6,69.55999999999989,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 05:00:00,-126.6,-29.140000000000114,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 07:00:00,-126.6,-30.010000000000115,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 07:15:30,-126.6,50.63999999999989,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 10:50:55,-126.6,76.61999999999989,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 11:13:05,-126.6,111.65999999999988,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 12:54:34,-126.6,123.17999999999988,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 13:18:10,-126.6,126.59999999999988,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 16:25:00,-126.6,213.71999999999989,305.1,9.400000000000006,0.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 16:45:00,-126.6,213.71999999999989,305.1,9.400000000000006,2.0,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 17:00:00,-126.6,213.71999999999989,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 17:15:40,-126.6,213.8999999999999,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,2.3999999999999986
|
||||
2026-02-10 21:00:01,-126.6,213.8999999999999,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-11 04:02:06,-126.6,237.0299999999999,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-11 07:48:46,-126.6,237.9299999999999,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-11 08:00:00,-126.6,218.2799999999999,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-11 11:49:18,-126.6,235.7999999999999,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-11 12:27:16,-126.6,295.1599999999999,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-11 13:24:06,-126.6,304.6699999999999,305.1,9.400000000000006,2.55,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-11 17:25:57,-126.6,304.6699999999999,305.1,9.400000000000006,3.0,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-11 19:20:00,-126.6,304.6699999999999,305.1,9.400000000000006,3.0,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-12 05:00:00,-126.6,174.6699999999999,305.1,9.400000000000006,3.0,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-12 07:00:00,-126.6,173.1699999999999,305.1,9.400000000000006,3.0,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-12 09:00:00,-126.6,14.919999999999902,305.1,9.400000000000006,3.0,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-12 17:45:00,-126.6,14.919999999999902,305.1,9.400000000000006,17.45,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-12 18:00:01,-126.6,14.919999999999902,305.1,9.400000000000006,19.849999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-12 20:01:58,-126.6,43.119999999999905,305.1,9.400000000000006,19.849999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-12 23:02:07,-126.6,97.1499999999999,305.1,9.400000000000006,19.849999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-13 05:18:27,-126.6,105.3999999999999,305.1,9.400000000000006,19.849999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-13 08:00:00,-126.6,0.9699999999998994,305.1,9.400000000000006,19.849999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-13 15:42:45,-126.6,-294.7100000000001,305.1,9.400000000000006,19.849999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-13 19:00:00,-126.6,-488.5700000000001,305.1,9.400000000000006,19.849999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-13 21:42:00,-126.6,-488.5700000000001,305.1,9.400000000000006,28.349999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-13 21:58:36,-126.6,-446.1500000000001,305.1,9.400000000000006,28.349999999999998,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-13 22:00:00,-126.6,-446.1500000000001,305.1,9.400000000000006,32.55,-72.63000000000001,0.0,-129.39999999999998,-20.5
|
||||
2026-02-16 02:00:00,-126.6,-446.1500000000001,305.1,9.400000000000006,32.55,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-16 05:00:00,-126.6,-579.1000000000001,305.1,9.400000000000006,32.55,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-17 17:00:00,-49.8,-579.1000000000001,305.1,9.400000000000006,32.55,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-17 17:45:00,-49.8,-579.1000000000001,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-19 22:00:00,-49.8,-133.80000000000013,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-20 07:00:00,-49.8,-201.30000000000013,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-23 02:00:00,-49.8,1316.8999999999999,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-24 02:00:00,-49.8,407.79999999999984,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-24 04:00:00,-49.8,860.9999999999998,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-24 10:01:34,-49.8,880.3799999999998,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-24 14:01:01,-49.8,873.7799999999997,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-24 18:00:00,-49.8,759.9899999999998,305.1,9.400000000000006,26.449999999999996,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-24 18:15:00,-49.8,759.9899999999998,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-25 05:55:01,-49.8,762.1799999999998,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-25 08:00:56,-49.8,811.8899999999999,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-25 16:00:00,-49.8,634.3899999999999,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-25 18:07:26,-49.8,624.6399999999999,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-25 23:00:03,-49.8,442.65999999999985,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-26 03:00:00,-49.8,375.05999999999983,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,-16.6,-129.39999999999998,-20.5
|
||||
2026-02-26 06:00:00,-49.8,375.05999999999983,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,106.34,-129.39999999999998,-20.5
|
||||
2026-02-26 13:00:00,-49.8,293.0099999999998,305.1,9.400000000000006,-58.300000000000004,-72.63000000000001,106.34,-129.39999999999998,-20.5
|
||||
2026-02-26 16:45:00,-49.8,293.0099999999998,305.1,9.400000000000006,21.699999999999996,-72.63000000000001,106.34,-129.39999999999998,-20.5
|
||||
2026-02-26 16:46:48,-49.8,293.0099999999998,305.1,9.400000000000006,26.399999999999995,-72.63000000000001,106.34,-129.39999999999998,-20.5
|
||||
2026-02-26 16:46:53,-49.8,293.0099999999998,305.1,9.400000000000006,52.099999999999994,-72.63000000000001,106.34,-129.39999999999998,-20.5
|
||||
2026-02-26 16:46:56,-49.8,293.0099999999998,305.1,9.400000000000006,89.94999999999999,-72.63000000000001,106.34,-129.39999999999998,-20.5
|
||||
2026-02-26 18:56:28,-49.8,293.0099999999998,305.1,9.400000000000006,89.94999999999999,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-26 20:45:00,-49.8,293.0099999999998,305.1,9.400000000000006,40.44999999999999,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-26 22:30:01,-49.8,293.0099999999998,305.1,9.400000000000006,3.6999999999999886,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-27 07:00:01,-49.8,292.3299999999998,305.1,9.400000000000006,3.6999999999999886,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-27 16:45:00,-49.8,292.3299999999998,305.1,9.400000000000006,5.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-27 18:00:00,-49.8,292.3299999999998,305.1,9.400000000000006,13.199999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-27 18:00:33,-49.8,329.3799999999998,305.1,9.400000000000006,13.199999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-27 18:15:00,-49.8,329.3799999999998,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-27 20:15:53,-49.8,337.0899999999998,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-27 21:03:14,187.2,337.0899999999998,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-02-27 23:01:44,187.2,377.5299999999998,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-02 01:03:37,187.2,1653.3299999999997,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-02 02:00:03,187.2,1747.1699999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-02 06:01:54,187.2,1803.8999999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-02 09:01:24,187.2,1889.0999999999997,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-02 09:13:03,187.2,1095.8999999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-02 17:00:00,187.2,1730.3999999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-02 18:00:30,187.2,1378.8899999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-02 23:30:48,187.2,1418.6999999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-03 02:00:21,187.2,1442.7299999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-03 05:17:20,187.2,1477.2599999999995,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-03 11:00:00,187.2,530.9999999999995,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-03 12:00:00,187.2,529.2599999999995,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-03 13:00:18,187.2,593.6999999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-18.25
|
||||
2026-03-03 16:31:02,187.2,593.6999999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-98.75
|
||||
2026-03-03 17:00:05,187.2,897.6599999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-98.75
|
||||
2026-03-03 20:00:21,187.2,935.6399999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-98.75
|
||||
2026-03-03 22:00:04,187.2,996.3299999999997,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-98.75
|
||||
2026-03-04 18:00:00,187.2,828.2399999999997,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-98.75
|
||||
2026-03-04 20:00:10,187.2,844.6499999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,106.34,-129.39999999999998,-98.75
|
||||
2026-03-05 04:00:00,187.2,844.6499999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-05 05:00:00,187.2,668.1899999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-05 09:00:00,187.2,415.9899999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-05 16:00:00,187.2,371.4299999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-05 16:00:11,187.2,456.3299999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-05 19:02:14,187.2,515.6099999999996,305.1,9.400000000000006,11.449999999999989,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-05 20:30:00,187.2,515.6099999999996,305.1,9.400000000000006,-1.0500000000000114,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-06 12:00:00,187.2,417.5299999999996,305.1,9.400000000000006,-1.0500000000000114,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-06 15:00:00,187.2,355.42999999999955,305.1,9.400000000000006,-1.0500000000000114,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-06 17:00:00,187.2,209.44999999999956,305.1,9.400000000000006,-1.0500000000000114,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-06 22:30:00,187.2,209.44999999999956,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-09 01:01:22,187.2,288.10999999999956,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-09 04:06:01,187.2,357.8299999999996,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-09 05:00:00,187.2,-362.5700000000004,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-09 09:00:00,187.2,-525.8900000000003,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-09 12:01:35,187.2,-530.5700000000003,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-09 17:00:00,599.95,-530.5700000000003,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-09 17:00:25,599.95,-500.0600000000003,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-10 01:01:33,599.95,-490.52000000000027,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-10 05:02:32,599.95,-405.5600000000003,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-10 08:00:01,599.95,-407.40000000000026,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-10 09:05:27,599.95,-379.41000000000025,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-10 11:03:06,599.95,-369.30000000000024,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-10 17:00:17,599.95,-311.97000000000025,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-10 19:03:01,599.95,-253.23000000000025,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-11 07:00:00,599.95,-253.71000000000024,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-11 10:00:00,599.95,299.38999999999976,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-11 15:00:01,599.95,158.68999999999977,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-11 16:31:01,510.95000000000005,158.68999999999977,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-98.75
|
||||
2026-03-11 18:00:00,510.95000000000005,158.68999999999977,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-131.25
|
||||
2026-03-12 03:09:47,510.95000000000005,155.53999999999976,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-131.25
|
||||
2026-03-12 06:01:28,510.95000000000005,152.23999999999975,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-131.25
|
||||
2026-03-12 11:00:00,510.95000000000005,32.05999999999975,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-131.25
|
||||
2026-03-12 12:00:00,510.95000000000005,40.11999999999975,305.1,9.400000000000006,-71.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-131.25
|
||||
2026-03-12 17:30:01,510.95000000000005,40.11999999999975,305.1,9.400000000000006,27.19999999999999,-72.63000000000001,259.51,-129.39999999999998,-131.25
|
||||
2026-03-12 18:46:42,510.95000000000005,102.39999999999975,305.1,9.400000000000006,27.19999999999999,-72.63000000000001,259.51,-129.39999999999998,-131.25
|
||||
2026-03-12 19:04:29,510.95000000000005,151.41999999999976,305.1,9.400000000000006,27.19999999999999,-72.63000000000001,259.51,-129.39999999999998,-131.25
|
||||
2026-03-12 21:00:02,510.95000000000005,151.41999999999976,305.1,9.400000000000006,27.19999999999999,-72.63000000000001,259.51,-129.39999999999998,-174.5
|
||||
2026-03-12 21:01:15,510.95000000000005,196.56999999999977,305.1,9.400000000000006,27.19999999999999,-72.63000000000001,259.51,-129.39999999999998,-174.5
|
||||
2026-03-12 23:01:04,510.95000000000005,216.24999999999977,305.1,9.400000000000006,27.19999999999999,-72.63000000000001,259.51,-129.39999999999998,-174.5
|
||||
2026-03-13 08:00:00,510.95000000000005,195.32999999999976,305.1,9.400000000000006,27.19999999999999,-72.63000000000001,259.51,-129.39999999999998,-174.5
|
||||
2026-03-13 18:00:14,510.95000000000005,286.34999999999974,305.1,9.400000000000006,27.19999999999999,-72.63000000000001,259.51,-129.39999999999998,-174.5
|
||||
2026-03-13 19:30:00,510.95000000000005,286.34999999999974,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,259.51,-129.39999999999998,-174.5
|
||||
2026-03-13 23:00:00,510.95000000000005,286.34999999999974,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,28.92999999999998,-129.39999999999998,-174.5
|
||||
2026-03-13 23:00:35,510.95000000000005,330.9299999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,28.92999999999998,-129.39999999999998,-174.5
|
||||
2026-03-16 03:00:15,510.95000000000005,355.52999999999975,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,28.92999999999998,-129.39999999999998,-174.5
|
||||
2026-03-16 05:00:33,510.95000000000005,376.43999999999977,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,28.92999999999998,-129.39999999999998,-174.5
|
||||
2026-03-16 11:00:31,510.95000000000005,392.00999999999976,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,28.92999999999998,-129.39999999999998,-174.5
|
||||
2026-03-16 13:09:14,510.95000000000005,429.08999999999975,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,28.92999999999998,-129.39999999999998,-174.5
|
||||
2026-03-16 14:00:00,510.95000000000005,457.3099999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,28.92999999999998,-129.39999999999998,-174.5
|
||||
2026-03-16 15:00:00,510.95000000000005,457.3099999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-1.2600000000000229,-129.39999999999998,-174.5
|
||||
2026-03-16 17:00:00,501.95000000000005,457.3099999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-1.2600000000000229,-129.39999999999998,-174.5
|
||||
2026-03-17 11:00:01,501.95000000000005,457.3099999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-17 14:00:00,501.95000000000005,401.4499999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-17 14:08:21,501.95000000000005,421.4899999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-17 19:18:11,501.95000000000005,429.28999999999974,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-17 23:04:43,501.95000000000005,424.45999999999975,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 05:00:33,501.95000000000005,418.78999999999974,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 06:00:00,501.95000000000005,401.00999999999976,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 07:24:05,501.95000000000005,394.76999999999975,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 14:14:57,501.95000000000005,443.4299999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 16:31:00,503.70000000000005,443.4299999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 16:42:22,503.70000000000005,580.7099999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 18:00:39,503.70000000000005,597.5699999999997,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 22:04:29,503.70000000000005,618.3899999999998,305.1,9.400000000000006,-16.55000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-18 22:45:00,503.70000000000005,618.3899999999998,305.1,9.400000000000006,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-19 01:01:09,503.70000000000005,647.6999999999997,305.1,9.400000000000006,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-19 05:07:38,503.70000000000005,647.6999999999997,305.1,51.60000000000001,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-19 09:00:35,503.70000000000005,659.9999999999997,305.1,51.60000000000001,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-19 11:00:07,503.70000000000005,761.2199999999997,305.1,51.60000000000001,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-19 13:00:36,503.70000000000005,783.0299999999996,305.1,51.60000000000001,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-19 16:20:36,503.70000000000005,1087.8299999999997,305.1,51.60000000000001,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-19 16:31:00,1279.2,1087.8299999999997,305.1,51.60000000000001,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-19 18:00:12,1279.2,1136.1899999999996,305.1,51.60000000000001,-35.05000000000001,-72.63000000000001,-142.25000000000003,-129.39999999999998,-174.5
|
||||
2026-03-20 04:50:41,1279.2,1136.1899999999996,305.1,51.60000000000001,-35.05000000000001,-72.63000000000001,-142.25000000000003,-109.49999999999997,-174.5
|
||||
2026-03-20 18:00:00,1279.2,1136.1899999999996,305.1,51.60000000000001,-186.55,-72.63000000000001,-142.25000000000003,-109.49999999999997,-174.5
|
||||
2026-03-20 20:45:00,1279.2,1136.1899999999996,305.1,51.60000000000001,-275.05,-72.63000000000001,-142.25000000000003,-109.49999999999997,-174.5
|
||||
2026-03-23 23:00:00,1279.2,1136.1899999999996,305.1,51.60000000000001,-275.05,-72.63000000000001,-225.91000000000003,-109.49999999999997,-174.5
|
||||
2026-03-24 04:00:00,1279.2,1009.8699999999997,305.1,51.60000000000001,-275.05,-72.63000000000001,-225.91000000000003,-109.49999999999997,-174.5
|
||||
2026-03-24 17:30:00,1279.2,1009.8699999999997,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-109.49999999999997,-174.5
|
||||
2026-03-25 02:00:30,1279.2,1028.9499999999996,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-109.49999999999997,-174.5
|
||||
2026-03-25 04:00:04,1279.2,1065.3699999999997,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-109.49999999999997,-174.5
|
||||
2026-03-25 04:54:18,1279.2,1065.3699999999997,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-25 16:31:01,871.7,1065.3699999999997,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-25 23:00:00,871.7,871.1799999999996,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-26 01:01:01,871.7,1292.4799999999996,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-26 05:00:47,871.7,1284.1699999999996,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-26 12:00:55,871.7,1305.8899999999996,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-26 13:00:00,871.7,1353.8899999999996,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-26 15:00:47,871.7,1347.1999999999996,305.1,51.60000000000001,-392.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-26 17:30:00,871.7,1347.1999999999996,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-26 20:00:33,871.7,1457.0299999999995,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-26 23:11:44,871.7,1488.7099999999996,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-27 04:00:00,871.7,1421.1099999999997,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-27 04:00:03,871.7,1417.3899999999996,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-27 09:00:00,871.7,1308.3699999999997,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-27 14:00:12,871.7,1330.2699999999998,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-27 16:31:00,1699.7,1330.2699999999998,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-27 18:00:01,1699.7,1054.2399999999998,305.1,51.60000000000001,-391.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-27 20:30:01,1699.7,1054.2399999999998,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-174.5
|
||||
2026-03-27 21:00:00,1699.7,1054.2399999999998,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 03:00:01,1699.7,828.9099999999997,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 04:00:13,1699.7,70.40999999999974,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 05:00:00,1699.7,-33.84000000000026,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 09:00:03,1699.7,33.29999999999974,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 10:00:00,1699.7,32.679999999999744,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 12:06:36,1699.7,44.169999999999746,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 15:00:29,1699.7,113.01999999999974,305.1,51.60000000000001,-477.05,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 22:30:00,1699.7,113.01999999999974,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-30 23:00:00,1699.7,37.119999999999735,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-102.99999999999997,-117.5
|
||||
2026-03-31 04:50:01,1699.7,37.119999999999735,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-03-31 05:00:17,1699.7,129.66999999999973,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-03-31 07:00:00,1699.7,129.30999999999972,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-03-31 09:00:13,1699.7,122.34999999999972,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-03-31 11:02:00,1699.7,133.98999999999972,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-03-31 15:14:01,1699.7,167.58999999999972,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-03-31 17:09:58,1699.7,253.86999999999972,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-03-31 21:10:02,1699.7,253.86999999999972,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-03-31 22:08:48,1699.7,448.26999999999975,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-04-01 03:00:31,1699.7,475.2399999999998,305.1,51.60000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-04-01 08:00:00,1699.7,475.2399999999998,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-94.59999999999997,-117.5
|
||||
2026-04-02 00:01:00,1699.7,475.2399999999998,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-117.5
|
||||
2026-04-02 08:00:00,1699.7,1736.6399999999999,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-117.5
|
||||
2026-04-02 18:00:01,1699.7,1470.8999999999999,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-117.5
|
||||
2026-04-06 03:01:14,1699.7,1538.61,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-117.5
|
||||
2026-04-06 08:00:00,1699.7,1426.62,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-117.5
|
||||
2026-04-06 12:50:29,1699.7,1448.79,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-117.5
|
||||
2026-04-06 17:00:00,1699.7,1295.09,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-117.5
|
||||
2026-04-06 18:00:00,1699.7,1295.09,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-188.5
|
||||
2026-04-06 18:40:05,1699.7,1295.09,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-188.5
|
||||
2026-04-06 20:00:00,1699.7,1195.1899999999998,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-188.5
|
||||
2026-04-06 20:00:01,2471.7,1195.1899999999998,305.1,99.80000000000001,-642.55,-72.63000000000001,-225.91000000000003,-138.49999999999997,-188.5
|
||||
2026-04-07 01:00:00,2471.7,1195.1899999999998,305.1,99.80000000000001,-642.55,-72.63000000000001,-113.86000000000003,-138.49999999999997,-188.5
|
||||
2026-04-07 08:00:01,2471.7,1094.1499999999999,305.1,99.80000000000001,-642.55,-72.63000000000001,-113.86000000000003,-138.49999999999997,-188.5
|
||||
2026-04-07 14:00:00,2471.7,998.3899999999999,305.1,99.80000000000001,-642.55,-72.63000000000001,-113.86000000000003,-138.49999999999997,-188.5
|
||||
2026-04-07 16:00:00,2471.7,684.1899999999998,305.1,99.80000000000001,-642.55,-72.63000000000001,-113.86000000000003,-138.49999999999997,-188.5
|
||||
2026-04-07 17:30:00,2471.7,684.1899999999998,305.1,99.80000000000001,-264.04999999999995,-72.63000000000001,-113.86000000000003,-138.49999999999997,-188.5
|
||||
2026-04-07 18:00:01,2471.7,684.1899999999998,305.1,99.80000000000001,-264.04999999999995,-72.63000000000001,-113.86000000000003,-138.49999999999997,-356.5
|
||||
2026-04-07 21:00:00,2471.7,555.0999999999998,305.1,99.80000000000001,-264.04999999999995,-72.63000000000001,-113.86000000000003,-138.49999999999997,-356.5
|
||||
2026-04-08 01:01:06,2471.7,678.7299999999998,305.1,99.80000000000001,-264.04999999999995,-72.63000000000001,-113.86000000000003,-138.49999999999997,-356.5
|
||||
2026-04-08 03:00:07,2471.7,712.4799999999998,305.1,99.80000000000001,-264.04999999999995,-72.63000000000001,-113.86000000000003,-138.49999999999997,-356.5
|
||||
2026-04-08 08:00:00,2471.7,712.4799999999998,305.1,-72.39999999999998,-264.04999999999995,-72.63000000000001,-113.86000000000003,-138.49999999999997,-356.5
|
||||
2026-04-08 09:08:23,2471.7,730.9599999999998,305.1,-72.39999999999998,-264.04999999999995,-72.63000000000001,-113.86000000000003,-138.49999999999997,-356.5
|
||||
2026-04-08 10:00:00,2471.7,730.9599999999998,305.1,-72.39999999999998,-264.04999999999995,-72.63000000000001,-96.76000000000002,-138.49999999999997,-356.5
|
||||
2026-04-08 16:31:00,2471.7,730.9599999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-138.49999999999997,-356.5
|
||||
2026-04-08 18:20:00,2471.7,730.9599999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-138.49999999999997,-356.5
|
||||
2026-04-08 20:00:00,2471.7,1312.6599999999999,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-138.49999999999997,-356.5
|
||||
2026-04-08 21:00:01,2471.7,1056.0099999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-138.49999999999997,-356.5
|
||||
2026-04-09 00:01:00,2471.7,1056.0099999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-356.5
|
||||
2026-04-09 13:00:01,2471.7,978.8799999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-356.5
|
||||
2026-04-09 16:31:01,2471.7,978.8799999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-953.0
|
||||
2026-04-09 17:00:38,2471.7,995.0199999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-953.0
|
||||
2026-04-09 19:13:39,2471.7,1057.1799999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-953.0
|
||||
2026-04-09 21:01:21,2471.7,1073.4099999999999,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-953.0
|
||||
2026-04-10 01:01:52,2471.7,1075.2699999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-953.0
|
||||
2026-04-10 05:00:02,2471.7,1155.7699999999998,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-953.0
|
||||
2026-04-10 05:00:30,2471.7,1149.5899999999997,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-953.0
|
||||
2026-04-10 17:00:01,2471.7,1149.9499999999996,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-953.0
|
||||
2026-04-10 18:36:21,2471.7,1149.9499999999996,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-10 21:00:00,2471.7,985.5499999999996,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-13 01:01:02,2471.7,641.7499999999995,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-13 01:01:03,2471.7,1087.5699999999995,305.1,-72.39999999999998,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-13 07:33:34,2471.7,1087.5699999999995,305.1,78.08000000000001,198.95000000000005,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-13 18:00:01,2471.7,1087.5699999999995,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-13 20:00:00,2352.5699999999997,787.4099999999994,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-14 04:00:02,2352.5699999999997,813.0899999999993,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-14 06:00:57,2352.5699999999997,833.8799999999993,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-14 08:02:23,2352.5699999999997,847.8799999999993,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-14 09:00:04,2352.5699999999997,844.2399999999993,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-96.76000000000002,-211.49999999999997,-1042.0
|
||||
2026-04-14 09:00:07,2352.5699999999997,844.2399999999993,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,0.9899999999999807,-211.49999999999997,-1042.0
|
||||
2026-04-14 12:05:23,2352.5699999999997,851.1599999999993,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,0.9899999999999807,-211.49999999999997,-1042.0
|
||||
2026-04-14 18:00:36,2352.5699999999997,939.3599999999993,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,0.9899999999999807,-211.49999999999997,-1042.0
|
||||
2026-04-14 21:21:16,2352.5699999999997,1039.9199999999994,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,0.9899999999999807,-211.49999999999997,-1042.0
|
||||
2026-04-14 23:00:00,2352.5699999999997,1039.9199999999994,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-203.41000000000003,-211.49999999999997,-1042.0
|
||||
2026-04-14 23:04:34,2352.5699999999997,1068.0699999999995,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-203.41000000000003,-211.49999999999997,-1042.0
|
||||
2026-04-15 00:01:00,2352.5699999999997,1068.0699999999995,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-203.41000000000003,-264.84999999999997,-1042.0
|
||||
2026-04-15 05:15:57,2352.5699999999997,1086.4199999999994,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-203.41000000000003,-264.84999999999997,-1042.0
|
||||
2026-04-15 08:30:19,2352.5699999999997,1076.7199999999993,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-203.41000000000003,-264.84999999999997,-1042.0
|
||||
2026-04-15 12:00:00,2352.5699999999997,1796.5999999999995,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-203.41000000000003,-264.84999999999997,-1042.0
|
||||
2026-04-15 14:00:00,2352.5699999999997,1721.9599999999994,305.1,78.08000000000001,-42.539999999999964,-72.63000000000001,-203.41000000000003,-264.84999999999997,-1042.0
|
||||
|
|
Before Width: | Height: | Size: 267 KiB |
@@ -1,102 +0,0 @@
|
||||
close_time,daily_pnl,cum_pnl
|
||||
2026-01-05,85.61999999999999,85.61999999999999
|
||||
2026-01-06,-61.83,23.789999999999992
|
||||
2026-01-07,-64.69000000000001,-40.90000000000002
|
||||
2026-01-08,-48.95,-89.85000000000002
|
||||
2026-01-09,-0.17,-90.02000000000002
|
||||
2026-01-10,0.0,-90.02000000000002
|
||||
2026-01-11,0.0,-90.02000000000002
|
||||
2026-01-12,380.8,290.78
|
||||
2026-01-13,-134.17,156.60999999999999
|
||||
2026-01-14,65.9,222.51
|
||||
2026-01-15,-130.47,92.03999999999999
|
||||
2026-01-16,-10.7,81.33999999999999
|
||||
2026-01-17,0.0,81.33999999999999
|
||||
2026-01-18,0.0,81.33999999999999
|
||||
2026-01-19,-182.78,-101.44000000000001
|
||||
2026-01-20,86.51,-14.930000000000007
|
||||
2026-01-21,16.120000000000005,1.1899999999999977
|
||||
2026-01-22,-243.25,-242.06
|
||||
2026-01-23,-67.38,-309.44
|
||||
2026-01-24,0.0,-309.44
|
||||
2026-01-25,0.0,-309.44
|
||||
2026-01-26,465.11,155.67000000000002
|
||||
2026-01-27,-1.4299999999999784,154.24000000000004
|
||||
2026-01-28,580.72,734.96
|
||||
2026-01-29,-655.47,79.49000000000001
|
||||
2026-01-30,-326.9,-247.40999999999997
|
||||
2026-01-31,0.0,-247.40999999999997
|
||||
2026-02-01,0.0,-247.40999999999997
|
||||
2026-02-02,0.0,-247.40999999999997
|
||||
2026-02-03,447.03,199.62
|
||||
2026-02-04,533.68,733.3
|
||||
2026-02-05,-354.43,378.86999999999995
|
||||
2026-02-06,-563.19,-184.3200000000001
|
||||
2026-02-07,0.0,-184.3200000000001
|
||||
2026-02-08,0.0,-184.3200000000001
|
||||
2026-02-09,241.38,57.05999999999989
|
||||
2026-02-10,123.99000000000001,181.0499999999999
|
||||
2026-02-11,111.97,293.01999999999987
|
||||
2026-02-12,-190.67000000000002,102.34999999999985
|
||||
2026-02-13,-530.6,-428.25000000000017
|
||||
2026-02-14,0.0,-428.25000000000017
|
||||
2026-02-15,0.0,-428.25000000000017
|
||||
2026-02-16,-149.54999999999998,-577.8000000000002
|
||||
2026-02-17,70.7,-507.1000000000002
|
||||
2026-02-18,0.0,-507.1000000000002
|
||||
2026-02-19,445.3,-61.80000000000018
|
||||
2026-02-20,-67.5,-129.30000000000018
|
||||
2026-02-21,0.0,-129.30000000000018
|
||||
2026-02-22,0.0,-129.30000000000018
|
||||
2026-02-23,1518.2,1388.8999999999999
|
||||
2026-02-24,-656.6600000000001,732.2399999999998
|
||||
2026-02-25,-317.33,414.9099999999998
|
||||
2026-02-26,37.540000000000006,452.4499999999998
|
||||
2026-02-27,329.27,781.7199999999998
|
||||
2026-02-28,0.0,781.7199999999998
|
||||
2026-03-01,0.0,781.7199999999998
|
||||
2026-03-02,1041.1699999999998,1822.8899999999996
|
||||
2026-03-03,-502.8700000000001,1320.0199999999995
|
||||
2026-03-04,-151.68,1168.3399999999995
|
||||
2026-03-05,-188.37,979.9699999999995
|
||||
2026-03-06,-376.65999999999997,603.3099999999995
|
||||
2026-03-07,0.0,603.3099999999995
|
||||
2026-03-08,0.0,603.3099999999995
|
||||
2026-03-09,-296.76,306.5499999999995
|
||||
2026-03-10,246.82999999999998,553.3799999999994
|
||||
2026-03-11,290.42,843.7999999999995
|
||||
2026-03-12,113.06,956.8599999999994
|
||||
2026-03-13,-159.65000000000003,797.2099999999994
|
||||
2026-03-14,0.0,797.2099999999994
|
||||
2026-03-15,0.0,797.2099999999994
|
||||
2026-03-16,87.19,884.3999999999994
|
||||
2026-03-17,-173.84,710.5599999999994
|
||||
2026-03-18,177.18,887.7399999999993
|
||||
2026-03-19,1335.5,2223.2399999999993
|
||||
2026-03-20,-220.1,2003.1399999999994
|
||||
2026-03-21,0.0,2003.1399999999994
|
||||
2026-03-22,0.0,2003.1399999999994
|
||||
2026-03-23,-83.66,1919.4799999999993
|
||||
2026-03-24,-243.82,1675.6599999999994
|
||||
2026-03-25,-539.69,1135.9699999999993
|
||||
2026-03-26,618.53,1754.4999999999993
|
||||
2026-03-27,365.03,2119.5299999999993
|
||||
2026-03-28,0.0,2119.5299999999993
|
||||
2026-03-29,0.0,2119.5299999999993
|
||||
2026-03-30,-1182.6200000000001,936.9099999999992
|
||||
2026-03-31,425.55,1362.4599999999991
|
||||
2026-04-01,75.17,1437.6299999999992
|
||||
2026-04-02,951.76,2389.3899999999994
|
||||
2026-04-03,0.0,2389.3899999999994
|
||||
2026-04-04,0.0,2389.3899999999994
|
||||
2026-04-05,0.0,2389.3899999999994
|
||||
2026-04-06,421.78999999999996,2811.1799999999994
|
||||
2026-04-07,-317.53999999999996,2493.6399999999994
|
||||
2026-04-08,798.5600000000001,3292.1999999999994
|
||||
2026-04-09,-652.1,2640.0999999999995
|
||||
2026-04-10,-176.86,2463.2399999999993
|
||||
2026-04-11,0.0,2463.2399999999993
|
||||
2026-04-12,0.0,2463.2399999999993
|
||||
2026-04-13,-408.28000000000003,2054.959999999999
|
||||
2026-04-14,174.01000000000002,2228.9699999999993
|
||||
2026-04-15,600.54,2829.5099999999993
|
||||
|
|
Before Width: | Height: | Size: 139 KiB |
@@ -1,75 +0,0 @@
|
||||
# Pepperstone US - Symbol Setup Guide
|
||||
|
||||
## Finding Correct Symbol Names in MetaTrader 5
|
||||
|
||||
### Step-by-Step Instructions:
|
||||
|
||||
1. **Open Market Watch Window**
|
||||
- Press `Ctrl+M` or go to `View > Market Watch`
|
||||
|
||||
2. **Show All Symbols**
|
||||
- Right-click in the Market Watch window
|
||||
- Select `Show All` or `Symbols`
|
||||
- This shows all available symbols from your broker
|
||||
|
||||
3. **Search for Your Symbols**
|
||||
- Use the search box in the Market Watch window
|
||||
- Search for: "AAPL", "MSFT", "NVDA", "TSLA", "BTCUSD", "XAUUSD"
|
||||
|
||||
4. **Note the Exact Symbol Name**
|
||||
- The symbol name shown in Market Watch is what you need to use
|
||||
- Common formats for Pepperstone US:
|
||||
- Stocks: `AAPL.US`, `MSFT.US`, `NVDA.US`, `TSLA.US`
|
||||
- Or: `NASDAQ:AAPL`, `NASDAQ:MSFT`, etc.
|
||||
- Or: Just `AAPL`, `MSFT`, etc. (if available)
|
||||
|
||||
5. **Add to Market Watch**
|
||||
- Double-click the symbol to add it to your Market Watch
|
||||
- Or right-click and select `Show`
|
||||
|
||||
6. **Update EA Inputs**
|
||||
- Open the EA inputs in MetaTrader 5
|
||||
- Update each symbol parameter with the exact name from Market Watch
|
||||
|
||||
## Common Pepperstone US Symbol Formats
|
||||
|
||||
### US Stocks:
|
||||
- **Apple**: `AAPL.US` or `NASDAQ:AAPL` or `AAPL`
|
||||
- **Microsoft**: `MSFT.US` or `NASDAQ:MSFT` or `MSFT`
|
||||
- **NVIDIA**: `NVDA.US` or `NASDAQ:NVDA` or `NVDA`
|
||||
- **Tesla**: `TSLA.US` or `NASDAQ:TSLA` or `TSLA`
|
||||
|
||||
### Cryptocurrencies:
|
||||
- **Bitcoin**: `BTCUSD` or `BTC/USD` or `BTCUSD.c`
|
||||
|
||||
### Precious Metals:
|
||||
- **Gold**: `XAUUSD` or `GOLD` or `XAU/USD`
|
||||
|
||||
## Important Notes:
|
||||
|
||||
1. **Symbol Names are Case-Sensitive**: Use exact capitalization
|
||||
2. **Add Symbols to Market Watch**: Symbols must be in Market Watch for the EA to access them
|
||||
3. **Check Trading Hours**: US stocks trade during US market hours (9:30 AM - 4:00 PM ET)
|
||||
4. **CFD vs Stock**: Pepperstone offers CFDs on stocks, not actual stocks
|
||||
5. **Spread**: Check the spread for each symbol - some may have wider spreads
|
||||
|
||||
## Troubleshooting:
|
||||
|
||||
### If Symbol Not Found:
|
||||
1. Check if you're connected to Pepperstone US server
|
||||
2. Verify your account type supports the symbol
|
||||
3. Contact Pepperstone support for symbol availability
|
||||
4. Check if symbol requires special account permissions
|
||||
|
||||
### If EA Shows "Symbol Not Available":
|
||||
1. Make sure symbol is added to Market Watch
|
||||
2. Verify symbol name matches exactly (including dots, colons, etc.)
|
||||
3. Check broker connection status
|
||||
4. Try different symbol format variations
|
||||
|
||||
## Testing Symbols:
|
||||
|
||||
You can test if a symbol works by:
|
||||
1. Opening a chart with that symbol
|
||||
2. If chart opens successfully, the symbol name is correct
|
||||
3. Use that exact symbol name in the EA inputs
|
||||
@@ -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
|
||||
@@ -20,6 +20,23 @@ bool WeekDays_Check(datetime aTime)
|
||||
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();
|
||||
@@ -151,8 +168,7 @@ void ProcessRSICrossOverReversal(string symbol)
|
||||
return;
|
||||
}
|
||||
|
||||
if(!((currentHour < RC_tradingHourOneEnd && currentHour > RC_tradingHourOneBegin) ||
|
||||
(currentHour < RC_tradingHourTwoEnd && currentHour > RC_tradingHourTwoBegin)))
|
||||
if(!RC_TradingHoursAllow(currentHour))
|
||||
{
|
||||
Close_Position_MN(RC_MagicNumber);
|
||||
return;
|
||||
@@ -173,7 +189,7 @@ void ProcessRSICrossOverReversal(string symbol)
|
||||
double previousEMA = ema[1];
|
||||
|
||||
double emaSlope = (currentEMA - previousEMA) * 100;
|
||||
double closeCurr = iClose(Symbol(), Period(), 0);
|
||||
const double closeCurr = iClose(rcData.symbol, RC_TimeFrame1, 0);
|
||||
double priceToEmaDistance = (closeCurr - currentEMA) * 10;
|
||||
|
||||
bool isBuyPosition = false;
|
||||
@@ -211,10 +227,10 @@ void ProcessRSICrossOverReversal(string symbol)
|
||||
{
|
||||
Close_Position_MN(RC_MagicNumber);
|
||||
rcData.lastTradeTime = currentTime;
|
||||
return;
|
||||
}
|
||||
|
||||
if(currentRSI < RC_overboughtLevel - RC_entryRSISellSpread && rcData.previousRSIDef >= RC_overboughtLevel &&
|
||||
|
||||
if(!isTrendStrong &&
|
||||
currentRSI < RC_overboughtLevel - RC_entryRSISellSpread && rcData.previousRSIDef >= RC_overboughtLevel &&
|
||||
!isSellPosition && !hasPosition && cooldownPassed)
|
||||
{
|
||||
rcData.trade.SetExpertMagicNumber(RC_MagicNumber);
|
||||
@@ -223,8 +239,9 @@ void ProcessRSICrossOverReversal(string symbol)
|
||||
rcData.lastTradeTime = currentTime;
|
||||
}
|
||||
}
|
||||
|
||||
if(currentRSI > RC_oversoldLevel + RC_entryRSIBuySpread && rcData.previousRSIDef <= RC_oversoldLevel &&
|
||||
|
||||
if(!isTrendStrong &&
|
||||
currentRSI > RC_oversoldLevel + RC_entryRSIBuySpread && rcData.previousRSIDef <= RC_oversoldLevel &&
|
||||
!isBuyPosition && !hasPosition && cooldownPassed)
|
||||
{
|
||||
rcData.trade.SetExpertMagicNumber(RC_MagicNumber);
|
||||
@@ -22,6 +22,104 @@ struct RSIScalpingData {
|
||||
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)));
|
||||
}
|
||||
|
||||
string ErrorDescription(int errorCode)
|
||||
{
|
||||
switch(errorCode)
|
||||
@@ -420,7 +518,9 @@ void ClosePosition(RSIScalpingData& data, int MagicNumber)
|
||||
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)
|
||||
int BarsToWait, double LotSize, int MagicNumber,
|
||||
bool UseReversalEscape, int ReversalATRPeriod, double ReversalAdverseAtrMult,
|
||||
int ReversalSignsRequired, double ReversalRsiVelocity, double ReversalBodyAtrMult)
|
||||
{
|
||||
// Skip if not initialized (symbol not available)
|
||||
if(!data.isInitialized)
|
||||
@@ -429,16 +529,25 @@ void ProcessRSIScalping(RSIScalpingData& data, string symbol, ENUM_TIMEFRAMES Ti
|
||||
data.symbol = symbol; // Update symbol in case it changed
|
||||
if(Bars(data.symbol, TimeFrame) < RSI_Period + 2)
|
||||
return;
|
||||
|
||||
datetime current_bar_time = iTime(data.symbol, TimeFrame, 0);
|
||||
if(current_bar_time == data.last_bar_time)
|
||||
|
||||
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;
|
||||
|
||||
data.last_bar_time = current_bar_time;
|
||||
|
||||
|
||||
if(!UpdateRSI(data))
|
||||
return;
|
||||
|
||||
|
||||
if(in_pos && UseReversalEscape)
|
||||
RS_TryReversalEscape(data, TimeFrame, MagicNumber, ReversalATRPeriod, ReversalAdverseAtrMult,
|
||||
ReversalSignsRequired, ReversalRsiVelocity, ReversalBodyAtrMult);
|
||||
|
||||
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);
|
||||
|
||||
@@ -228,6 +228,9 @@ int SuperEMA_BarsSinceOpen(SuperEMAData &d, const datetime openTime)
|
||||
|
||||
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);
|
||||
@@ -235,6 +238,9 @@ void SuperEMA_CloseTicket(SuperEMAData &d, const ulong ticket, const string reas
|
||||
|
||||
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);
|
||||
@@ -412,9 +418,6 @@ void ProcessSuperEMA(SuperEMAData &d, const double lots)
|
||||
|
||||
SuperEMA_ManageExits(d);
|
||||
|
||||
if(d.oneTradeOnly && SuperEMA_PositionsByMagic(d) > 0)
|
||||
return;
|
||||
|
||||
const int sh = d.emaTrendBars;
|
||||
double h1 = 0.0, h2 = 0.0;
|
||||
if(!SuperEMA_MacdHistAt(d, 1, h1) || !SuperEMA_MacdHistAt(d, 2, h2))
|
||||
@@ -450,6 +453,16 @@ void ProcessSuperEMA(SuperEMAData &d, const double lots)
|
||||
break;
|
||||
}
|
||||
|
||||
if(d.oneTradeOnly && SuperEMA_PositionsByMagic(d) > 0)
|
||||
{
|
||||
if(wantBuy && !United_MayOpenNewEntry(d.symbol, (ulong)d.magic, true))
|
||||
wantBuy = false;
|
||||
if(wantSell && !United_MayOpenNewEntry(d.symbol, (ulong)d.magic, false))
|
||||
wantSell = false;
|
||||
if(!wantBuy && !wantSell)
|
||||
return;
|
||||
}
|
||||
|
||||
MqlTick tick;
|
||||
if(!SymbolInfoTick(d.symbol, tick))
|
||||
return;
|
||||
@@ -458,13 +471,17 @@ void ProcessSuperEMA(SuperEMAData &d, const double lots)
|
||||
|
||||
if(wantBuy && !wantSell)
|
||||
{
|
||||
#ifndef UNITED_MARTINGALE_NO_SELF_CLOSE
|
||||
SuperEMA_ComputeSLTP(d, true, sl, tp);
|
||||
#endif
|
||||
if(d.trade.Buy(lots, 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(lots, d.symbol, tick.bid, sl, tp, "United SuperEMA short"))
|
||||
SuperEMA_Log(d, StringFormat("SELL bid=%.5f sl=%.5f", tick.bid, sl));
|
||||
}
|
||||
@@ -1,15 +1,11 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| UnitedEA.mq5 |
|
||||
//| Cent ".c" symbols; InpDynamicRefDeposit MUST match ACCOUNT_ |
|
||||
//| CURRENCY numbers (USC ~50k for ~$500, or USD ~500 — not mixed). |
|
||||
//| Per-order max lots = broker spec 最大量 SYMBOL_VOLUME_MAX |
|
||||
//| (often 1000 on *.c); EA cannot exceed it — see symbol contract. |
|
||||
//| Copyright 2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.10"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
@@ -17,22 +13,29 @@
|
||||
#include <Indicators\Trend.mqh>
|
||||
#include <Indicators\Volumes.mqh>
|
||||
#include "MagicNumberHelpers.mqh"
|
||||
|
||||
// Lot globals must exist before strategy .mqh (Darvas uses g_DB_LotSize; EMA/RC/RM use g_ES/g_RC/g_RM)
|
||||
double g_ES_LotSize;
|
||||
double g_RC_LotSize;
|
||||
double g_RM_LotSize;
|
||||
double g_DB_LotSize;
|
||||
double g_DynLotScaleLast = 1.0; // last applied scale: lots = baseLot * scale * InpLotSizeScale
|
||||
double g_DynamicRefBaseline = 0.0; // when InpDynamicRefDeposit<=0, frozen ref = equity at first sizing call
|
||||
|
||||
// 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"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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
|
||||
|
||||
bool United_MayOpenNewEntry(const string symbol, const ulong magic, const bool isBuy)
|
||||
{
|
||||
if(PositionExistsByMagic(symbol, magic))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Strategy Enable/Disable Switches |
|
||||
@@ -47,51 +50,30 @@ input bool EnableRSIScalpingBTCUSD = true;
|
||||
input bool EnableRSIScalpingNVDA = true;
|
||||
input bool EnableRSIScalpingTSLA = true;
|
||||
input bool EnableRSIScalpingXAUUSD = true;
|
||||
input bool EnableSuperEMA = true;
|
||||
input bool EnableRSIConsolidation = true;
|
||||
input bool EnableRSIReversalAsianEURUSD = true;
|
||||
input bool EnableRSIReversalAsianAUDUSD = true;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Dynamic lot sizing — 默认「按比例」:lots = base × (equity/ref) × lotScale |
|
||||
//| 可选幂曲线:lots = base × (equity/ref)^exp × lotScale(旧行为) |
|
||||
//| min/max 约束的是「比例系数」不是手数本身;max<=0 表示比例系数上不封顶 |
|
||||
//| |
|
||||
//| USC (deposit currency) vs "lot size": |
|
||||
//| • Equity/ref for the multiplier are BOTH in account currency |
|
||||
//| (USC). Same units → ratio is correct; no ×100 on the ratio. |
|
||||
//| • Strategy base lots (e.g. DB_BaseLotSize) are ORDER VOLUME in |
|
||||
//| lots, not "USC lots". Broker SYMBOL_VOLUME_* / contract define |
|
||||
//| how much margin and P/L appear in USC. |
|
||||
//| • Do not multiply lot inputs by 100 only because balance is USC. |
|
||||
//| If DD too high: raise InpDynamicRefDeposit and/or lower base lots.|
|
||||
//| If balance is USD ~500 but ref is ~50k–300k: mult→floor, lots→0.01.|
|
||||
//| Ref<=0: 挂上时余额/净值为参考,之后手数随净值相对该基准的比例变化。 |
|
||||
//| 单笔上限:品种规格里的「最大量」(SYMBOL_VOLUME_MAX),非 EA 参数。 |
|
||||
//| InpMaxLotsPerOrder:EA 再截一刀,防止动态+scale 顶满 1000 爆仓。 |
|
||||
//+------------------------------------------------------------------+
|
||||
enum ENUM_LOT_SCALE_CURVE
|
||||
{
|
||||
LOT_CURVE_PROPORTIONAL = 0, // 按比例:scale = 净值/参考(线性)
|
||||
LOT_CURVE_POWER = 1 // 幂:scale = (净值/参考)^exp
|
||||
};
|
||||
|
||||
input group "=== Dynamic lot sizing (动态手数) ==="
|
||||
input bool InpDynamicLotEnable = true; // Enable balance/equity-based scaling
|
||||
input ENUM_LOT_SCALE_CURVE InpDynamicLotCurve = LOT_CURVE_PROPORTIONAL; // 默认按比例;幂曲线=旧 (equity/ref)^exp
|
||||
input double InpDynamicRefDeposit = 0.0; // <=0: auto — ref=挂上时净值/余额(与测试器初始一致则手数随盈利涨); >0 手动参考金
|
||||
input bool InpDynamicRefEqualsEquity = false; // true: 比例系数固定为 1(只用基础手×lotScale)
|
||||
input double InpDynamicExponent = 1.22; // 仅 LOT_CURVE_POWER 时:(净值/参考) 的指数
|
||||
input double InpDynamicMinMult = 0.0; // 比例系数下限;<=0 不抬(按比例时净值<参考会缩小手数)
|
||||
input double InpDynamicMaxMult = 20.0; // 比例系数上限;<=0 不封顶(高风险)
|
||||
input bool InpDynamicUseEquity = true; // true=ACCOUNT_EQUITY, false=ACCOUNT_BALANCE
|
||||
input double InpDynamicStockLotCap = 0.0; // Max lots after scale (0=off); raise if InpLotSizeScale is large
|
||||
input double InpLotSizeScale = 1.0; // 全局手数倍率; 曾用100易过大,默认1按需再加
|
||||
input double InpMaxLotsPerOrder = 20.0; // 单笔最大手数(0=仅券商SYMBOL_VOLUME_MAX); 保守可设5~10
|
||||
input group "=== Centralized Lot Size (Granular Per Robot) ==="
|
||||
input double LOT_ES_EMASlopeDistance = 0.05;
|
||||
input double LOT_RC_RSICrossOver = 0.1;
|
||||
input double LOT_RM_RSIMidPointHijack = 0.01;
|
||||
input double LOT_RS_APPL = 100.0;
|
||||
input double LOT_RS_BTCUSD = 0.15;
|
||||
input double LOT_RS_NVDA = 60.0;
|
||||
input double LOT_RS_TSLA = 20.0;
|
||||
input double LOT_RS_XAUUSD = 0.02;
|
||||
input double LOT_RRA_EURUSD = 0.01;
|
||||
input double LOT_RRA_AUDUSD = 0.10;
|
||||
input double LOT_SE_SuperEMA = 0.01;
|
||||
input double LOT_RCO_RSIConsolidation = 0.04;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Strategy 1: DarvasBoxXAUUSD (cent symbol) |
|
||||
//| Strategy 1: DarvasBoxXAUUSD |
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== DarvasBox Strategy ==="
|
||||
input string DB_Symbol = "XAUUSD.c";
|
||||
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.
|
||||
@@ -108,20 +90,19 @@ input double DB_TrendThreshold = 4.94;
|
||||
input int DB_VolumeMA_Period = 110;
|
||||
input double DB_VolumeThresholdMultiplier = 1.5;
|
||||
input int DB_MagicNumber = 135790;
|
||||
input double DB_BaseLotSize = 0.02; // Base lot at InpDynamicRefDeposit (Darvas)
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Strategy 2: EMASlopeDistanceCocktailXAUUSD |
|
||||
//| Cent: gold is usually "XAUUSD.c" (verify in Market Watch). |
|
||||
//| PEPPERSTONE US: Gold symbol is typically "XAUUSD" or "GOLD" |
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== EMA Slope Distance Strategy ==="
|
||||
input string ES_Symbol = "XAUUSD.c";
|
||||
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 = 250.0;
|
||||
input double ES_LotGröße = 0.05;
|
||||
input double ES_LotGröße = 0.03;
|
||||
input int ES_MagicNumber = 12350;
|
||||
input bool ES_UseSpreadAdjustment = true;
|
||||
input ENUM_TIMEFRAMES ES_Timeframe = PERIOD_H1;
|
||||
@@ -132,17 +113,17 @@ input bool ES_CloseUnprofitableTrades = true;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Strategy 3: RSICrossOverReversalXAUUSD |
|
||||
//| Cent: use "XAUUSD.c" if that is what the broker lists. |
|
||||
//| PEPPERSTONE US: Gold symbol is typically "XAUUSD" or "GOLD" |
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== RSI CrossOver Reversal Strategy ==="
|
||||
input string RC_Symbol = "XAUUSD.c";
|
||||
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.02;
|
||||
input double RC_lotSize = 0.01;
|
||||
input int RC_slippage = 3;
|
||||
input int RC_cooldownSeconds = 209;
|
||||
input ENUM_TIMEFRAMES RC_TimeFrame1 = PERIOD_M1;
|
||||
@@ -168,12 +149,12 @@ input bool RC_Saturday = false;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Strategy 4: RSIMidPointHijackXAUUSD |
|
||||
//| Cent: use "XAUUSD.c" if that is what the broker lists. |
|
||||
//| PEPPERSTONE US: Gold symbol is typically "XAUUSD" or "GOLD" |
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== RSI MidPoint Hijack Strategy ==="
|
||||
input string RM_Symbol = "XAUUSD.c";
|
||||
input string RM_Symbol = "XAUUSD";
|
||||
input ENUM_TIMEFRAMES RM_InpTimeframe = PERIOD_H1;
|
||||
input double RM_InpLotSize = 0.03;
|
||||
input double RM_InpLotSize = 0.02;
|
||||
input int RM_InpMagicNumberRSIFollow = 1001;
|
||||
input int RM_InpMagicNumberRSIReverse = 1002;
|
||||
input int RM_InpMagicNumberEMACross = 1003;
|
||||
@@ -217,11 +198,16 @@ input int RM_InpEMADistancePeriod = 26;
|
||||
//| - TSLA: Tesla stock |
|
||||
//| - XAUUSD: Gold/USD |
|
||||
//| |
|
||||
//| USC cent: many symbols end with ".c" — use Market Watch names. |
|
||||
//| Stocks may be "AAPL.US.c" or unchanged; verify before live. |
|
||||
//| 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) - cent ==="
|
||||
input string RS_APPL_Symbol = "AAPL.US.c"; // If missing, try AAPL.US / NASDAQ:AAPL / AAPL
|
||||
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;
|
||||
@@ -230,12 +216,12 @@ 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 = 38;
|
||||
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.c"; // If missing, try BTCUSD or BTC/USD
|
||||
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;
|
||||
@@ -244,12 +230,12 @@ 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.15;
|
||||
input double RS_BTCUSD_LotSize = 0.1;
|
||||
input int RS_BTCUSD_MagicNumber = 123459123;
|
||||
input int RS_BTCUSD_Slippage = 3;
|
||||
|
||||
input group "=== RSI Scalping NVDA - cent ==="
|
||||
input string RS_NVDA_Symbol = "NVDA.US.c"; // If missing, try NVDA.US / NASDAQ:NVDA / NVDA
|
||||
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;
|
||||
@@ -258,12 +244,12 @@ 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 = 75;
|
||||
input double RS_NVDA_LotSize = 50;
|
||||
input int RS_NVDA_MagicNumber = 20003;
|
||||
input int RS_NVDA_Slippage = 3;
|
||||
|
||||
input group "=== RSI Scalping TSLA - cent ==="
|
||||
input string RS_TSLA_Symbol = "TSLA.US.c"; // If missing, try TSLA.US / NASDAQ:TSLA / TSLA
|
||||
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;
|
||||
@@ -272,12 +258,12 @@ 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 = 75;
|
||||
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.c";
|
||||
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;
|
||||
@@ -286,10 +272,18 @@ 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.15;
|
||||
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 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;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Strategy 11-12: RSI Reversal Asian Strategies |
|
||||
//| Each RSI Reversal Asian strategy trades on its own symbol: |
|
||||
@@ -297,13 +291,13 @@ input int RS_XAUUSD_Slippage = 3;
|
||||
//| - AUDUSD: Australian Dollar/USD |
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== RSI Reversal Asian EURUSD ==="
|
||||
input string RRA_EURUSD_Symbol = "EURUSD.c";
|
||||
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.15;
|
||||
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;
|
||||
@@ -316,13 +310,13 @@ input int RRA_EURUSD_MagicNumber = 30001;
|
||||
input int RRA_EURUSD_Slippage = 3;
|
||||
|
||||
input group "=== RSI Reversal Asian AUDUSD ==="
|
||||
input string RRA_AUDUSD_Symbol = "AUDUSD.c";
|
||||
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.3;
|
||||
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;
|
||||
@@ -334,6 +328,63 @@ 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;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Global Variables - DarvasBox |
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -430,6 +481,8 @@ RSIScalpingData rsBTCUSDData;
|
||||
RSIScalpingData rsNVDAData;
|
||||
RSIScalpingData rsTSLAData;
|
||||
RSIScalpingData rsXAUUSDData;
|
||||
SuperEMAData seData;
|
||||
RSIConsolidationData rcoData;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Global Variables - RSI Reversal Asian |
|
||||
@@ -437,107 +490,6 @@ RSIScalpingData rsXAUUSDData;
|
||||
RSIReversalAsianData rraEURUSDData;
|
||||
RSIReversalAsianData rraAUDUSDData;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Dynamic lot helpers |
|
||||
//+------------------------------------------------------------------+
|
||||
double DynClamp(const double v, const double lo, const double hi)
|
||||
{
|
||||
return MathMax(lo, MathMin(hi, v));
|
||||
}
|
||||
|
||||
// Clamp scale factor (proportion or pow result). max<=0 = no upper clamp.
|
||||
double ApplyDynamicScaleClamp(const double scaleRaw)
|
||||
{
|
||||
double s = scaleRaw;
|
||||
if(InpDynamicMinMult > 0.0)
|
||||
s = MathMax(s, InpDynamicMinMult);
|
||||
if(InpDynamicMaxMult > 0.0)
|
||||
s = MathMin(s, InpDynamicMaxMult);
|
||||
return s;
|
||||
}
|
||||
|
||||
// Reference for (equity/ref)^exp: manual deposit, or first-seen balance when input <= 0
|
||||
double GetDynamicRefForRatio()
|
||||
{
|
||||
if(InpDynamicRefDeposit > 0.0)
|
||||
return MathMax(InpDynamicRefDeposit, 1.0);
|
||||
double capNow = InpDynamicUseEquity ? AccountInfoDouble(ACCOUNT_EQUITY) : AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
if(g_DynamicRefBaseline <= 0.0)
|
||||
g_DynamicRefBaseline = MathMax(capNow, 1.0);
|
||||
return MathMax(g_DynamicRefBaseline, 1.0);
|
||||
}
|
||||
|
||||
// Broker hard cap: 最大量 = SYMBOL_VOLUME_MAX (e.g. 1000 on EURUSD.c / XAUUSD.c)
|
||||
double NormalizeVolumeForSymbol(const string symbol, double lots)
|
||||
{
|
||||
double minL = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
|
||||
double maxL = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
|
||||
double step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
|
||||
if(step > 0.0)
|
||||
lots = MathFloor(lots / step + 1e-12) * step;
|
||||
if(lots < minL) lots = minL;
|
||||
if(lots > maxL) lots = maxL;
|
||||
return lots;
|
||||
}
|
||||
|
||||
// Apply EA risk cap before broker min/step/max (InpMaxLotsPerOrder 0 = disabled)
|
||||
double NormalizeVolumeForSymbolWithEACap(const string symbol, double lots)
|
||||
{
|
||||
if(InpMaxLotsPerOrder > 0.0)
|
||||
lots = MathMin(lots, InpMaxLotsPerOrder);
|
||||
return NormalizeVolumeForSymbol(symbol, lots);
|
||||
}
|
||||
|
||||
// Scale factor for lots: baseLot * scale * InpLotSizeScale (then caps)
|
||||
double GetDynamicLotScaleFactor()
|
||||
{
|
||||
if(!InpDynamicLotEnable)
|
||||
return 1.0;
|
||||
if(InpDynamicRefEqualsEquity)
|
||||
return ApplyDynamicScaleClamp(1.0);
|
||||
double cap = InpDynamicUseEquity ? AccountInfoDouble(ACCOUNT_EQUITY) : AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
double refv = GetDynamicRefForRatio();
|
||||
if(cap <= 0.0)
|
||||
cap = refv;
|
||||
double ratio = cap / refv;
|
||||
if(ratio <= 0.0)
|
||||
ratio = 1.0;
|
||||
double scaleRaw = ratio;
|
||||
if(InpDynamicLotCurve == LOT_CURVE_POWER)
|
||||
scaleRaw = MathPow(ratio, InpDynamicExponent);
|
||||
return ApplyDynamicScaleClamp(scaleRaw);
|
||||
}
|
||||
|
||||
// baseLot = size at reference deposit; optionalCap 0 = no extra ceiling (broker min/max still apply)
|
||||
double DynamicLotForSymbol(const string symbol, const double baseLot, const double optionalCap = 0.0)
|
||||
{
|
||||
double scale = GetDynamicLotScaleFactor();
|
||||
g_DynLotScaleLast = scale;
|
||||
double sc = (InpLotSizeScale > 0.0 ? InpLotSizeScale : 1.0);
|
||||
double v = baseLot * scale * sc;
|
||||
if(optionalCap > 0.0 && v > optionalCap)
|
||||
v = optionalCap;
|
||||
return NormalizeVolumeForSymbolWithEACap(symbol, v);
|
||||
}
|
||||
|
||||
void RefreshDynamicStrategyLots()
|
||||
{
|
||||
double sc = (InpLotSizeScale > 0.0 ? InpLotSizeScale : 1.0);
|
||||
if(!InpDynamicLotEnable)
|
||||
{
|
||||
g_ES_LotSize = NormalizeVolumeForSymbolWithEACap(ES_Symbol, ES_LotGröße * sc);
|
||||
g_RC_LotSize = NormalizeVolumeForSymbolWithEACap(RC_Symbol, RC_lotSize * sc);
|
||||
g_RM_LotSize = NormalizeVolumeForSymbolWithEACap(RM_Symbol, RM_InpLotSize * sc);
|
||||
g_DB_LotSize = NormalizeVolumeForSymbolWithEACap(DB_Symbol, DB_BaseLotSize * sc);
|
||||
g_DynLotScaleLast = 1.0;
|
||||
return;
|
||||
}
|
||||
g_ES_LotSize = DynamicLotForSymbol(ES_Symbol, ES_LotGröße);
|
||||
g_RC_LotSize = DynamicLotForSymbol(RC_Symbol, RC_lotSize);
|
||||
g_RM_LotSize = DynamicLotForSymbol(RM_Symbol, RM_InpLotSize);
|
||||
g_DB_LotSize = DynamicLotForSymbol(DB_Symbol, DB_BaseLotSize);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -545,17 +497,10 @@ int OnInit()
|
||||
{
|
||||
int initResult = INIT_SUCCEEDED;
|
||||
|
||||
g_DynamicRefBaseline = 0.0;
|
||||
|
||||
RefreshDynamicStrategyLots();
|
||||
|
||||
string acctCur = AccountInfoString(ACCOUNT_CURRENCY);
|
||||
double eq0 = AccountInfoDouble(ACCOUNT_EQUITY);
|
||||
if(InpDynamicLotEnable && !InpDynamicRefEqualsEquity && InpDynamicRefDeposit > 1000.0 && eq0 > 0.0
|
||||
&& eq0 <= InpDynamicRefDeposit / 25.0)
|
||||
Print("United EA: equity ", DoubleToString(eq0, 2), " ", acctCur, " vs ref ", InpDynamicRefDeposit,
|
||||
" — dynamic mult is tiny; set InpDynamicRefDeposit to your balance in ", acctCur,
|
||||
" (e.g. 500 for USD) or enable InpDynamicRefEqualsEquity. Else lots stay at broker minimum.");
|
||||
// Initialize global lot size variables
|
||||
g_ES_LotSize = LOT_ES_EMASlopeDistance;
|
||||
g_RC_LotSize = LOT_RC_RSICrossOver;
|
||||
g_RM_LotSize = LOT_RM_RSIMidPointHijack;
|
||||
|
||||
// Initialize strategies - log warnings but don't fail entire EA if symbol unavailable
|
||||
if(EnableDarvasBox)
|
||||
@@ -589,11 +534,30 @@ int OnInit()
|
||||
|
||||
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(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, RRA_EURUSD_MaxLotSize,
|
||||
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))
|
||||
@@ -601,24 +565,12 @@ int OnInit()
|
||||
|
||||
if(EnableRSIReversalAsianAUDUSD)
|
||||
if(!InitRSIReversalAsian(rraAUDUSDData, RRA_AUDUSD_Symbol, RRA_AUDUSD_RSIPeriod, RRA_AUDUSD_OverboughtLevel, RRA_AUDUSD_OversoldLevel,
|
||||
RRA_AUDUSD_TakeProfitPips, RRA_AUDUSD_StopLossPips, RRA_AUDUSD_MaxLotSize,
|
||||
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, "'");
|
||||
|
||||
double refEffInit = GetDynamicRefForRatio();
|
||||
double capInit = InpDynamicUseEquity ? eq0 : AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
if(capInit <= 0.0)
|
||||
capInit = refEffInit;
|
||||
double ratioInit = capInit / refEffInit;
|
||||
double powInit = MathPow(ratioInit, InpDynamicExponent);
|
||||
string curveStr = (InpDynamicLotCurve == LOT_CURVE_POWER ? "POWER" : "PROP");
|
||||
Print("United EA v1.10 ", acctCur, " curve=", curveStr, " equity=", DoubleToString(eq0, 2), " refEff=", DoubleToString(refEffInit, 2),
|
||||
" (inpRef=", InpDynamicRefDeposit, " baseline=", DoubleToString(g_DynamicRefBaseline, 2), ") equity/ref=", DoubleToString(ratioInit, 6),
|
||||
" pow^exp=", DoubleToString(powInit, 6), " scaleOut=", DoubleToString(g_DynLotScaleLast, 6),
|
||||
" minS=", InpDynamicMinMult, " maxS=", InpDynamicMaxMult, " lotScale=", InpLotSizeScale, " maxLots=", InpMaxLotsPerOrder,
|
||||
" lots ES=", g_ES_LotSize, " RC=", g_RC_LotSize, " RM=", g_RM_LotSize, " DB=", g_DB_LotSize);
|
||||
Print("United EA initialized. Active strategies: ",
|
||||
(EnableDarvasBox ? "DarvasBox " : ""),
|
||||
(EnableEMASlopeDistance ? "EMASlope " : ""),
|
||||
@@ -629,6 +581,8 @@ int OnInit()
|
||||
(EnableRSIScalpingNVDA ? "RSIScalpingNVDA " : ""),
|
||||
(EnableRSIScalpingTSLA ? "RSIScalpingTSLA " : ""),
|
||||
(EnableRSIScalpingXAUUSD ? "RSIScalpingXAUUSD " : ""),
|
||||
(EnableSuperEMA ? "SuperEMA " : ""),
|
||||
(EnableRSIConsolidation ? "RSIConsolidation " : ""),
|
||||
(EnableRSIReversalAsianEURUSD ? "RSIReversalAsianEURUSD " : ""),
|
||||
(EnableRSIReversalAsianAUDUSD ? "RSIReversalAsianAUDUSD " : ""));
|
||||
|
||||
@@ -666,6 +620,12 @@ void OnDeinit(const int reason)
|
||||
|
||||
if(EnableRSIScalpingXAUUSD)
|
||||
DeinitRSIScalping(rsXAUUSDData);
|
||||
|
||||
if(EnableSuperEMA)
|
||||
DeinitSuperEMA(seData);
|
||||
|
||||
if(EnableRSIConsolidation)
|
||||
DeinitRSIConsolidation(rcoData);
|
||||
|
||||
if(EnableRSIReversalAsianEURUSD)
|
||||
DeinitRSIReversalAsian(rraEURUSDData);
|
||||
@@ -681,8 +641,6 @@ void OnDeinit(const int reason)
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
RefreshDynamicStrategyLots();
|
||||
|
||||
if(EnableDarvasBox)
|
||||
ProcessDarvasBox(DB_Symbol);
|
||||
|
||||
@@ -698,39 +656,49 @@ void OnTick()
|
||||
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,
|
||||
DynamicLotForSymbol(RS_APPL_Symbol, RS_APPL_LotSize, InpDynamicStockLotCap),
|
||||
RS_APPL_MagicNumber);
|
||||
RS_APPL_BarsToWait, LOT_RS_APPL, RS_APPL_MagicNumber,
|
||||
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
|
||||
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult);
|
||||
|
||||
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, DynamicLotForSymbol(RS_BTCUSD_Symbol, RS_BTCUSD_LotSize), RS_BTCUSD_MagicNumber);
|
||||
RS_BTCUSD_BarsToWait, LOT_RS_BTCUSD, RS_BTCUSD_MagicNumber,
|
||||
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
|
||||
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult);
|
||||
|
||||
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,
|
||||
DynamicLotForSymbol(RS_NVDA_Symbol, RS_NVDA_LotSize, InpDynamicStockLotCap),
|
||||
RS_NVDA_MagicNumber);
|
||||
RS_NVDA_BarsToWait, LOT_RS_NVDA, RS_NVDA_MagicNumber,
|
||||
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
|
||||
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult);
|
||||
|
||||
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,
|
||||
DynamicLotForSymbol(RS_TSLA_Symbol, RS_TSLA_LotSize, InpDynamicStockLotCap),
|
||||
RS_TSLA_MagicNumber);
|
||||
RS_TSLA_BarsToWait, LOT_RS_TSLA, RS_TSLA_MagicNumber,
|
||||
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
|
||||
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult);
|
||||
|
||||
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, DynamicLotForSymbol(RS_XAUUSD_Symbol, RS_XAUUSD_LotSize), RS_XAUUSD_MagicNumber);
|
||||
RS_XAUUSD_BarsToWait, LOT_RS_XAUUSD, RS_XAUUSD_MagicNumber,
|
||||
RS_UseReversalEscape, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
|
||||
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult);
|
||||
|
||||
if(EnableRSIReversalAsianEURUSD)
|
||||
ProcessRSIReversalAsian(rraEURUSDData, DynamicLotForSymbol(RRA_EURUSD_Symbol, RRA_EURUSD_MaxLotSize));
|
||||
ProcessRSIReversalAsian(rraEURUSDData, LOT_RRA_EURUSD);
|
||||
|
||||
if(EnableRSIReversalAsianAUDUSD)
|
||||
ProcessRSIReversalAsian(rraAUDUSDData, DynamicLotForSymbol(RRA_AUDUSD_Symbol, RRA_AUDUSD_MaxLotSize));
|
||||
ProcessRSIReversalAsian(rraAUDUSDData, LOT_RRA_AUDUSD);
|
||||
|
||||
if(EnableSuperEMA)
|
||||
ProcessSuperEMA(seData, LOT_SE_SuperEMA);
|
||||
|
||||
if(EnableRSIConsolidation)
|
||||
ProcessRSIConsolidation(rcoData, LOT_RCO_RSIConsolidation);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
@@ -104,7 +104,7 @@ bool IsStockSymbol(string symbol)
|
||||
// String-based checks (.US, NASDAQ:, NYSE:, common tickers) are sufficient
|
||||
|
||||
// Common stock tickers (without .US suffix)
|
||||
string commonStocks[] = {"AAPL", "NVDA", "TSLA", "GOOGL", "AMZN", "META", "AMD", "NFLX"};
|
||||
string commonStocks[] = {"AAPL", "MSFT", "NVDA", "TSLA", "GOOGL", "AMZN", "META", "NFLX"};
|
||||
for(int i = 0; i < ArraySize(commonStocks); i++)
|
||||
{
|
||||
if(StringFind(symbol, commonStocks[i]) == 0) return true;
|
||||
@@ -195,9 +195,9 @@ bool PlaceOrder(ENUM_ORDER_TYPE orderType, double price, double sl, double tp)
|
||||
// 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(g_DB_LotSize, dbData.symbol, 0, sl, tp, "Darvas Box Breakout");
|
||||
result = dbData.trade.Buy(0.01, dbData.symbol, 0, sl, tp, "Darvas Box Breakout");
|
||||
else
|
||||
result = dbData.trade.Sell(g_DB_LotSize, dbData.symbol, 0, sl, tp, "Darvas Box Breakdown");
|
||||
result = dbData.trade.Sell(0.01, dbData.symbol, 0, sl, tp, "Darvas Box Breakdown");
|
||||
|
||||
// Always log errors, success only if logging enabled
|
||||
if(result)
|
||||
@@ -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
|
||||
@@ -20,6 +20,23 @@ bool WeekDays_Check(datetime aTime)
|
||||
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();
|
||||
@@ -151,8 +168,7 @@ void ProcessRSICrossOverReversal(string symbol)
|
||||
return;
|
||||
}
|
||||
|
||||
if(!((currentHour < RC_tradingHourOneEnd && currentHour > RC_tradingHourOneBegin) ||
|
||||
(currentHour < RC_tradingHourTwoEnd && currentHour > RC_tradingHourTwoBegin)))
|
||||
if(!RC_TradingHoursAllow(currentHour))
|
||||
{
|
||||
Close_Position_MN(RC_MagicNumber);
|
||||
return;
|
||||
@@ -173,7 +189,7 @@ void ProcessRSICrossOverReversal(string symbol)
|
||||
double previousEMA = ema[1];
|
||||
|
||||
double emaSlope = (currentEMA - previousEMA) * 100;
|
||||
double closeCurr = iClose(Symbol(), Period(), 0);
|
||||
const double closeCurr = iClose(rcData.symbol, RC_TimeFrame1, 0);
|
||||
double priceToEmaDistance = (closeCurr - currentEMA) * 10;
|
||||
|
||||
bool isBuyPosition = false;
|
||||
@@ -211,10 +227,10 @@ void ProcessRSICrossOverReversal(string symbol)
|
||||
{
|
||||
Close_Position_MN(RC_MagicNumber);
|
||||
rcData.lastTradeTime = currentTime;
|
||||
return;
|
||||
}
|
||||
|
||||
if(currentRSI < RC_overboughtLevel - RC_entryRSISellSpread && rcData.previousRSIDef >= RC_overboughtLevel &&
|
||||
|
||||
if(!isTrendStrong &&
|
||||
currentRSI < RC_overboughtLevel - RC_entryRSISellSpread && rcData.previousRSIDef >= RC_overboughtLevel &&
|
||||
!isSellPosition && !hasPosition && cooldownPassed)
|
||||
{
|
||||
rcData.trade.SetExpertMagicNumber(RC_MagicNumber);
|
||||
@@ -223,8 +239,9 @@ void ProcessRSICrossOverReversal(string symbol)
|
||||
rcData.lastTradeTime = currentTime;
|
||||
}
|
||||
}
|
||||
|
||||
if(currentRSI > RC_oversoldLevel + RC_entryRSIBuySpread && rcData.previousRSIDef <= RC_oversoldLevel &&
|
||||
|
||||
if(!isTrendStrong &&
|
||||
currentRSI > RC_oversoldLevel + RC_entryRSIBuySpread && rcData.previousRSIDef <= RC_oversoldLevel &&
|
||||
!isBuyPosition && !hasPosition && cooldownPassed)
|
||||
{
|
||||
rcData.trade.SetExpertMagicNumber(RC_MagicNumber);
|
||||
@@ -22,6 +22,104 @@ struct RSIScalpingData {
|
||||
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)));
|
||||
}
|
||||
|
||||
string ErrorDescription(int errorCode)
|
||||
{
|
||||
switch(errorCode)
|
||||
@@ -420,7 +518,9 @@ void ClosePosition(RSIScalpingData& data, int MagicNumber)
|
||||
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)
|
||||
int BarsToWait, double LotSize, int MagicNumber,
|
||||
bool UseReversalEscape, int ReversalATRPeriod, double ReversalAdverseAtrMult,
|
||||
int ReversalSignsRequired, double ReversalRsiVelocity, double ReversalBodyAtrMult)
|
||||
{
|
||||
// Skip if not initialized (symbol not available)
|
||||
if(!data.isInitialized)
|
||||
@@ -429,16 +529,25 @@ void ProcessRSIScalping(RSIScalpingData& data, string symbol, ENUM_TIMEFRAMES Ti
|
||||
data.symbol = symbol; // Update symbol in case it changed
|
||||
if(Bars(data.symbol, TimeFrame) < RSI_Period + 2)
|
||||
return;
|
||||
|
||||
datetime current_bar_time = iTime(data.symbol, TimeFrame, 0);
|
||||
if(current_bar_time == data.last_bar_time)
|
||||
|
||||
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;
|
||||
|
||||
data.last_bar_time = current_bar_time;
|
||||
|
||||
|
||||
if(!UpdateRSI(data))
|
||||
return;
|
||||
|
||||
|
||||
if(in_pos && UseReversalEscape)
|
||||
RS_TryReversalEscape(data, TimeFrame, MagicNumber, ReversalATRPeriod, ReversalAdverseAtrMult,
|
||||
ReversalSignsRequired, ReversalRsiVelocity, ReversalBodyAtrMult);
|
||||
|
||||
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);
|
||||
|
||||
@@ -0,0 +1,495 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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);
|
||||
}
|
||||
|
||||
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;
|
||||
return (lo <= emaF + d.slBufferPoints * _Point * 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;
|
||||
return (hi >= emaF - d.slBufferPoints * _Point * 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(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 * _Point;
|
||||
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);
|
||||
|
||||
const int sh = d.emaTrendBars;
|
||||
double h1 = 0.0, h2 = 0.0;
|
||||
if(!SuperEMA_MacdHistAt(d, 1, h1) || !SuperEMA_MacdHistAt(d, 2, h2))
|
||||
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(d.oneTradeOnly && SuperEMA_PositionsByMagic(d) > 0)
|
||||
{
|
||||
if(wantBuy && !United_MayOpenNewEntry(d.symbol, (ulong)d.magic, true))
|
||||
wantBuy = false;
|
||||
if(wantSell && !United_MayOpenNewEntry(d.symbol, (ulong)d.magic, false))
|
||||
wantSell = false;
|
||||
if(!wantBuy && !wantSell)
|
||||
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(lots, 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(lots, 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
|
||||
@@ -0,0 +1,704 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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"
|
||||
// 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"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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
|
||||
|
||||
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 = true;
|
||||
input bool EnableRSIScalpingNVDA = true;
|
||||
input bool EnableRSIScalpingTSLA = true;
|
||||
input bool EnableRSIScalpingXAUUSD = true;
|
||||
input bool EnableSuperEMA = true;
|
||||
input bool EnableRSIConsolidation = true;
|
||||
input bool EnableRSIReversalAsianEURUSD = true;
|
||||
input bool EnableRSIReversalAsianAUDUSD = true;
|
||||
|
||||
input group "=== Centralized Lot Size (Granular Per Robot) ==="
|
||||
input double LOT_ES_EMASlopeDistance = 0.05;
|
||||
input double LOT_RC_RSICrossOver = 0.1;
|
||||
input double LOT_RM_RSIMidPointHijack = 0.01;
|
||||
input double LOT_RS_APPL = 100.0;
|
||||
input double LOT_RS_BTCUSD = 0.15;
|
||||
input double LOT_RS_NVDA = 60.0;
|
||||
input double LOT_RS_TSLA = 20.0;
|
||||
input double LOT_RS_XAUUSD = 0.02;
|
||||
input double LOT_RRA_EURUSD = 0.01;
|
||||
input double LOT_RRA_AUDUSD = 0.10;
|
||||
input double LOT_SE_SuperEMA = 0.01;
|
||||
input double LOT_RCO_RSIConsolidation = 0.04;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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 = 250.0;
|
||||
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;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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 |
|
||||
//| - 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 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 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;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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;
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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;
|
||||
SuperEMAData seData;
|
||||
RSIConsolidationData rcoData;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Global Variables - RSI Reversal Asian |
|
||||
//+------------------------------------------------------------------+
|
||||
RSIReversalAsianData rraEURUSDData;
|
||||
RSIReversalAsianData rraAUDUSDData;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
int initResult = INIT_SUCCEEDED;
|
||||
|
||||
// Initialize global lot size variables
|
||||
g_ES_LotSize = LOT_ES_EMASlopeDistance;
|
||||
g_RC_LotSize = LOT_RC_RSICrossOver;
|
||||
g_RM_LotSize = LOT_RM_RSIMidPointHijack;
|
||||
|
||||
// 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(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, "'");
|
||||
|
||||
Print("United EA initialized. Active strategies: ",
|
||||
(EnableDarvasBox ? "DarvasBox " : ""),
|
||||
(EnableEMASlopeDistance ? "EMASlope " : ""),
|
||||
(EnableRSICrossOverReversal ? "RSICrossOver " : ""),
|
||||
(EnableRSIMidPointHijack ? "RSIMidPoint " : ""),
|
||||
(EnableRSIScalpingAPPL ? "RSIScalpingAPPL " : ""),
|
||||
(EnableRSIScalpingBTCUSD ? "RSIScalpingBTCUSD " : ""),
|
||||
(EnableRSIScalpingNVDA ? "RSIScalpingNVDA " : ""),
|
||||
(EnableRSIScalpingTSLA ? "RSIScalpingTSLA " : ""),
|
||||
(EnableRSIScalpingXAUUSD ? "RSIScalpingXAUUSD " : ""),
|
||||
(EnableSuperEMA ? "SuperEMA " : ""),
|
||||
(EnableRSIConsolidation ? "RSIConsolidation " : ""),
|
||||
(EnableRSIReversalAsianEURUSD ? "RSIReversalAsianEURUSD " : ""),
|
||||
(EnableRSIReversalAsianAUDUSD ? "RSIReversalAsianAUDUSD " : ""));
|
||||
|
||||
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(EnableSuperEMA)
|
||||
DeinitSuperEMA(seData);
|
||||
|
||||
if(EnableRSIConsolidation)
|
||||
DeinitRSIConsolidation(rcoData);
|
||||
|
||||
if(EnableRSIReversalAsianEURUSD)
|
||||
DeinitRSIReversalAsian(rraEURUSDData);
|
||||
|
||||
if(EnableRSIReversalAsianAUDUSD)
|
||||
DeinitRSIReversalAsian(rraAUDUSDData);
|
||||
|
||||
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, LOT_RS_APPL, RS_APPL_MagicNumber,
|
||||
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
|
||||
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult);
|
||||
|
||||
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, LOT_RS_BTCUSD, RS_BTCUSD_MagicNumber,
|
||||
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
|
||||
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult);
|
||||
|
||||
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, LOT_RS_NVDA, RS_NVDA_MagicNumber,
|
||||
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
|
||||
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult);
|
||||
|
||||
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, LOT_RS_TSLA, RS_TSLA_MagicNumber,
|
||||
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
|
||||
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult);
|
||||
|
||||
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, LOT_RS_XAUUSD, RS_XAUUSD_MagicNumber,
|
||||
RS_UseReversalEscape, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
|
||||
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult);
|
||||
|
||||
if(EnableRSIReversalAsianEURUSD)
|
||||
ProcessRSIReversalAsian(rraEURUSDData, LOT_RRA_EURUSD);
|
||||
|
||||
if(EnableRSIReversalAsianAUDUSD)
|
||||
ProcessRSIReversalAsian(rraAUDUSDData, LOT_RRA_AUDUSD);
|
||||
|
||||
if(EnableSuperEMA)
|
||||
ProcessSuperEMA(seData, LOT_SE_SuperEMA);
|
||||
|
||||
if(EnableRSIConsolidation)
|
||||
ProcessRSIConsolidation(rcoData, LOT_RCO_RSIConsolidation);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
@@ -25,6 +25,7 @@ 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;
|
||||
@@ -154,6 +155,7 @@ input int RM_InpEMADistancePeriod = 26;
|
||||
//| 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 |
|
||||
@@ -194,6 +196,20 @@ 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;
|
||||
@@ -349,6 +365,7 @@ RSICrossOverData rcData;
|
||||
RSIMidPointData rmData;
|
||||
RSIScalpingData rsAPPLData;
|
||||
RSIScalpingData rsBTCUSDData;
|
||||
RSIScalpingData rsMSFTData;
|
||||
RSIScalpingData rsNVDAData;
|
||||
RSIScalpingData rsTSLAData;
|
||||
RSIScalpingData rsXAUUSDData;
|
||||
@@ -363,6 +380,7 @@ double g_RC_LotSize = 0.01; // RSI CrossOver Reversal - start with minimum
|
||||
double g_RM_LotSize = 0.01; // RSI MidPoint Hijack - start with minimum
|
||||
double g_RS_APPL_LotSize = 5.0; // Stock - start with stock minimum (5.0)
|
||||
double g_RS_BTCUSD_LotSize = 0.01; // Crypto - start with forex minimum (0.01)
|
||||
double g_RS_MSFT_LotSize = 5.0; // Stock - start with stock minimum (5.0)
|
||||
double g_RS_NVDA_LotSize = 5.0; // Stock - start with stock minimum (5.0)
|
||||
double g_RS_TSLA_LotSize = 5.0; // Stock - start with stock minimum (5.0)
|
||||
double g_RS_XAUUSD_LotSize = 0.01; // Forex - start with forex minimum (0.01)
|
||||
@@ -446,6 +464,15 @@ int OnInit()
|
||||
g_RS_BTCUSD_LotSize = minLot;
|
||||
}
|
||||
|
||||
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);
|
||||
RegisterStrategy("RSIScalpingMSFT", RS_MSFT_MagicNumber, RS_MSFT_LotSize, RS_MSFT_Symbol);
|
||||
// Start with minimum lot size (will be adjusted by performance evaluator)
|
||||
double minLot = GetMinLotSizeForSymbol(RS_MSFT_Symbol);
|
||||
g_RS_MSFT_LotSize = minLot;
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -492,6 +519,9 @@ int OnInit()
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingBTCUSD", RS_BTCUSD_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_BTCUSD_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingMSFT", RS_MSFT_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_MSFT_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingNVDA", RS_NVDA_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_NVDA_LotSize = adjustedLot;
|
||||
|
||||
@@ -509,6 +539,7 @@ int OnInit()
|
||||
(EnableRSIMidPointHijack ? "RSIMidPoint " : ""),
|
||||
(EnableRSIScalpingAPPL ? "RSIScalpingAPPL " : ""),
|
||||
(EnableRSIScalpingBTCUSD ? "RSIScalpingBTCUSD " : ""),
|
||||
(EnableRSIScalpingMSFT ? "RSIScalpingMSFT " : ""),
|
||||
(EnableRSIScalpingNVDA ? "RSIScalpingNVDA " : ""),
|
||||
(EnableRSIScalpingTSLA ? "RSIScalpingTSLA " : ""),
|
||||
(EnableRSIScalpingXAUUSD ? "RSIScalpingXAUUSD " : ""));
|
||||
@@ -542,6 +573,9 @@ void OnDeinit(const int reason)
|
||||
if(EnableRSIScalpingBTCUSD)
|
||||
DeinitRSIScalping(rsBTCUSDData);
|
||||
|
||||
if(EnableRSIScalpingMSFT)
|
||||
DeinitRSIScalping(rsMSFTData);
|
||||
|
||||
if(EnableRSIScalpingNVDA)
|
||||
DeinitRSIScalping(rsNVDAData);
|
||||
|
||||
@@ -581,6 +615,9 @@ void OnTick()
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingBTCUSD", RS_BTCUSD_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_BTCUSD_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingMSFT", RS_MSFT_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_MSFT_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingNVDA", RS_NVDA_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_NVDA_LotSize = adjustedLot;
|
||||
|
||||
@@ -613,6 +650,11 @@ void OnTick()
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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,
|
||||
@@ -104,7 +104,7 @@ bool IsStockSymbol(string symbol)
|
||||
// String-based checks (.US, NASDAQ:, NYSE:, common tickers) are sufficient
|
||||
|
||||
// Common stock tickers (without .US suffix)
|
||||
string commonStocks[] = {"AAPL", "NVDA", "TSLA", "GOOGL", "AMZN", "META", "AMD", "NFLX"};
|
||||
string commonStocks[] = {"AAPL", "MSFT", "NVDA", "TSLA", "GOOGL", "AMZN", "META", "NFLX"};
|
||||
for(int i = 0; i < ArraySize(commonStocks); i++)
|
||||
{
|
||||
if(StringFind(symbol, commonStocks[i]) == 0) return true;
|
||||
@@ -195,9 +195,9 @@ bool PlaceOrder(ENUM_ORDER_TYPE orderType, double price, double sl, double tp)
|
||||
// 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(g_DB_LotSize, dbData.symbol, 0, sl, tp, "Darvas Box Breakout");
|
||||
result = dbData.trade.Buy(0.01, dbData.symbol, 0, sl, tp, "Darvas Box Breakout");
|
||||
else
|
||||
result = dbData.trade.Sell(g_DB_LotSize, dbData.symbol, 0, sl, tp, "Darvas Box Breakdown");
|
||||
result = dbData.trade.Sell(0.01, dbData.symbol, 0, sl, tp, "Darvas Box Breakdown");
|
||||
|
||||
// Always log errors, success only if logging enabled
|
||||
if(result)
|
||||
@@ -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
|
||||
@@ -20,6 +20,23 @@ bool WeekDays_Check(datetime aTime)
|
||||
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();
|
||||
@@ -151,8 +168,7 @@ void ProcessRSICrossOverReversal(string symbol)
|
||||
return;
|
||||
}
|
||||
|
||||
if(!((currentHour < RC_tradingHourOneEnd && currentHour > RC_tradingHourOneBegin) ||
|
||||
(currentHour < RC_tradingHourTwoEnd && currentHour > RC_tradingHourTwoBegin)))
|
||||
if(!RC_TradingHoursAllow(currentHour))
|
||||
{
|
||||
Close_Position_MN(RC_MagicNumber);
|
||||
return;
|
||||
@@ -173,7 +189,7 @@ void ProcessRSICrossOverReversal(string symbol)
|
||||
double previousEMA = ema[1];
|
||||
|
||||
double emaSlope = (currentEMA - previousEMA) * 100;
|
||||
double closeCurr = iClose(Symbol(), Period(), 0);
|
||||
const double closeCurr = iClose(rcData.symbol, RC_TimeFrame1, 0);
|
||||
double priceToEmaDistance = (closeCurr - currentEMA) * 10;
|
||||
|
||||
bool isBuyPosition = false;
|
||||
@@ -211,10 +227,10 @@ void ProcessRSICrossOverReversal(string symbol)
|
||||
{
|
||||
Close_Position_MN(RC_MagicNumber);
|
||||
rcData.lastTradeTime = currentTime;
|
||||
return;
|
||||
}
|
||||
|
||||
if(currentRSI < RC_overboughtLevel - RC_entryRSISellSpread && rcData.previousRSIDef >= RC_overboughtLevel &&
|
||||
|
||||
if(!isTrendStrong &&
|
||||
currentRSI < RC_overboughtLevel - RC_entryRSISellSpread && rcData.previousRSIDef >= RC_overboughtLevel &&
|
||||
!isSellPosition && !hasPosition && cooldownPassed)
|
||||
{
|
||||
rcData.trade.SetExpertMagicNumber(RC_MagicNumber);
|
||||
@@ -223,8 +239,9 @@ void ProcessRSICrossOverReversal(string symbol)
|
||||
rcData.lastTradeTime = currentTime;
|
||||
}
|
||||
}
|
||||
|
||||
if(currentRSI > RC_oversoldLevel + RC_entryRSIBuySpread && rcData.previousRSIDef <= RC_oversoldLevel &&
|
||||
|
||||
if(!isTrendStrong &&
|
||||
currentRSI > RC_oversoldLevel + RC_entryRSIBuySpread && rcData.previousRSIDef <= RC_oversoldLevel &&
|
||||
!isBuyPosition && !hasPosition && cooldownPassed)
|
||||
{
|
||||
rcData.trade.SetExpertMagicNumber(RC_MagicNumber);
|
||||
@@ -0,0 +1,560 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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)));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
double minLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
|
||||
double maxLot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
|
||||
double lotStep = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
|
||||
|
||||
// Round to lot step
|
||||
if(lotStep > 0)
|
||||
lotSize = MathFloor(lotSize / lotStep) * lotStep;
|
||||
|
||||
// Apply min/max constraints
|
||||
if(lotSize < minLot)
|
||||
lotSize = minLot;
|
||||
if(lotSize > maxLot)
|
||||
lotSize = maxLot;
|
||||
|
||||
return 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)
|
||||
{
|
||||
// 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(!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,495 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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);
|
||||
}
|
||||
|
||||
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;
|
||||
return (lo <= emaF + d.slBufferPoints * _Point * 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;
|
||||
return (hi >= emaF - d.slBufferPoints * _Point * 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(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 * _Point;
|
||||
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);
|
||||
|
||||
const int sh = d.emaTrendBars;
|
||||
double h1 = 0.0, h2 = 0.0;
|
||||
if(!SuperEMA_MacdHistAt(d, 1, h1) || !SuperEMA_MacdHistAt(d, 2, h2))
|
||||
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(d.oneTradeOnly && SuperEMA_PositionsByMagic(d) > 0)
|
||||
{
|
||||
if(wantBuy && !United_MayOpenNewEntry(d.symbol, (ulong)d.magic, true))
|
||||
wantBuy = false;
|
||||
if(wantSell && !United_MayOpenNewEntry(d.symbol, (ulong)d.magic, false))
|
||||
wantSell = false;
|
||||
if(!wantBuy && !wantSell)
|
||||
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(lots, 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(lots, 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
|
||||
@@ -5,7 +5,7 @@
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.17"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
@@ -13,25 +13,33 @@
|
||||
#include <Indicators\Trend.mqh>
|
||||
#include <Indicators\Volumes.mqh>
|
||||
#include "MagicNumberHelpers.mqh"
|
||||
|
||||
// Lot globals must exist before strategy .mqh (Darvas uses g_DB_LotSize; EMA/RC/RM use g_ES/g_RC/g_RM)
|
||||
double g_ES_LotSize;
|
||||
double g_RC_LotSize;
|
||||
double g_RM_LotSize;
|
||||
double g_DB_LotSize;
|
||||
double g_DynMultLast = 1.0;
|
||||
double g_equityPeakHighWater = 0.0; // for drawdown lot cap (updated each tick via Refresh)
|
||||
datetime g_ddLotCapAnchorTime = 0; // tester/attach start — grace period before DD cap may apply
|
||||
|
||||
// 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/RSIReversalAsianStrategy.mqh"
|
||||
#include "Strategies/RSISecretSauceStrategy.mqh"
|
||||
#include "Strategies/SuperEMAStrategy.mqh"
|
||||
#include "Strategies/RSIReversalAsianStrategy.mqh"
|
||||
#include "Strategies/RSIConsolidationStrategy.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_LotScaleGrowth = 1.0;
|
||||
double g_LotScaleMargin = 1.0;
|
||||
double g_LotScaleFinal = 1.0;
|
||||
datetime g_LastScaleLogTime = 0;
|
||||
|
||||
bool United_MayOpenNewEntry(const string symbol, const ulong magic, const bool isBuy)
|
||||
{
|
||||
if(PositionExistsByMagic(symbol, magic))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Strategy Enable/Disable Switches |
|
||||
@@ -46,69 +54,143 @@ input bool EnableRSIScalpingBTCUSD = true;
|
||||
input bool EnableRSIScalpingNVDA = true;
|
||||
input bool EnableRSIScalpingTSLA = true;
|
||||
input bool EnableRSIScalpingXAUUSD = true;
|
||||
input bool EnableRSIReversalEURUSD = true; // RSI Reversal Asian session (EURUSD)
|
||||
input bool EnableRSIReversalAUDUSD = true; // RSI Reversal Asian session (AUDUSD)
|
||||
input bool EnableRSISecretSauceXAUUSD = true;
|
||||
input bool EnableSuperEMA = true;
|
||||
input bool EnableRSIConsolidation = true;
|
||||
input bool EnableRSIReversalAsianEURUSD = true;
|
||||
input bool EnableRSIReversalAsianAUDUSD = true;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| SuperEMA — EMA + CCI + MACD (XAUUSD default) |
|
||||
//+------------------------------------------------------------------+
|
||||
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 "=== Centralized Lot Size (Granular Per Robot) ==="
|
||||
input double LOT_ES_EMASlopeDistance = 0.05;
|
||||
input double LOT_RC_RSICrossOver = 0.1;
|
||||
input double LOT_RM_RSIMidPointHijack = 0.01;
|
||||
input double LOT_RS_APPL = 100.0;
|
||||
input double LOT_RS_BTCUSD = 0.15;
|
||||
input double LOT_RS_NVDA = 60.0;
|
||||
input double LOT_RS_TSLA = 20.0;
|
||||
input double LOT_RS_XAUUSD = 0.02;
|
||||
input double LOT_RRA_EURUSD = 0.01;
|
||||
input double LOT_RRA_AUDUSD = 0.10;
|
||||
input double LOT_SE_SuperEMA = 0.01;
|
||||
input double LOT_RCO_RSIConsolidation = 0.04;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Dynamic lot sizing — scale base lots vs reference deposit |
|
||||
//| mult=(equity/ref)^exp; maxMult<=0 上不封顶; minMult<=0 不锁下限 |
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== Dynamic lot sizing (动态手数) ==="
|
||||
input bool InpDynamicLotEnable = true; // Enable balance/equity-based scaling
|
||||
input double InpDynamicRefDeposit = 3000.0; // Reference balance (match Tester initial deposit)
|
||||
input double InpDynamicExponent = 1.15; // 1.0=linear; >1 faster growth; <1 conservative
|
||||
input double InpDynamicMinMult = 0.0; // <=0 不锁下限; >0 例如0.25 为最低倍数
|
||||
input double InpDynamicMaxMult = 0.0; // <=0 动态倍数不封顶; >0 上限封顶
|
||||
input bool InpDynamicUseEquity = true; // true=ACCOUNT_EQUITY, false=ACCOUNT_BALANCE
|
||||
input double InpDynamicStockLotCap = 0.0; // Extra cap for stock CFDs (0 = none)
|
||||
input group "=== Auto Lot Scaling (Equity/Balance + Margin Guard) ==="
|
||||
input bool EnableAutoLotScaling = true;
|
||||
input double ScalingReferenceBalanceUSD = 1000.0;
|
||||
input double ScalingCurveExponent = 0.70; // 1.0=linear, <1 smoother, >1 aggressive
|
||||
input double ScaleMinMultiplier = 0.50;
|
||||
input double ScaleMaxMultiplier = 3.00;
|
||||
input bool EnableMarginGuard = true;
|
||||
input double MarginSafeLevelPercent = 420.0; // >= safe: no reduction
|
||||
input double MarginCriticalLevelPercent = 170.0;
|
||||
input double MarginGuardMinMultiplier = 0.20;
|
||||
input int ScaleLogIntervalSeconds = 300;
|
||||
input bool ShowScaleStatusOnChart = true;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Lot cap: optional account-wide DD from peak, and/or per-strategy |
|
||||
//| (last *closed* calendar month losing for that magic). |
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== Drawdown / loser lot cap ==="
|
||||
input bool InpDdLotCapEnable = true; // master: allow clamping when a mode below triggers
|
||||
input bool InpDdLotCapGlobalEquityEnable = false; // cap *all* robots when equity DD from peak >= X% (after grace)
|
||||
input bool InpDdLotCapPerStratEnable = true; // cap only robots whose last closed month was red (by magic)
|
||||
input bool InpDdLotCapUseEquity = true; // true=ACCOUNT_EQUITY, false=BALANCE (global mode + peak tracking)
|
||||
input double InpDdLotCapFromPeakPercent = 7.0; // global: trigger if (peak-equity)/peak*100 >= this
|
||||
input double InpDdLotCapMaxLots = 0.01; // max volume per order while that mode is triggered
|
||||
input int InpDdLotCapGraceDays = 90; // global only: wait N days from attach before DD cap can apply (0=immediate)
|
||||
input double InpDdLotCapStratLossThreshold = 0.0; // per-strat: month P/L < -this counts as losing (0 = any loss)
|
||||
input int InpDdLotCapUpdateSeconds = 3600; // min 60; refresh last-month P/L when adaptive monthly is off
|
||||
input group "=== Minimum Balance Recommendation ==="
|
||||
input bool PrintMinimumBalanceRecommendation = true;
|
||||
input double MinBalPerLot_ES = 1200.0;
|
||||
input double MinBalPerLot_RC = 900.0;
|
||||
input double MinBalPerLot_RM = 900.0;
|
||||
input double MinBalPerLot_RS_APPL = 8.0;
|
||||
input double MinBalPerLot_RS_BTCUSD = 2500.0;
|
||||
input double MinBalPerLot_RS_NVDA = 8.0;
|
||||
input double MinBalPerLot_RS_TSLA = 8.0;
|
||||
input double MinBalPerLot_RS_XAUUSD = 3000.0;
|
||||
input double MinBalPerLot_RRA_EURUSD = 1200.0;
|
||||
input double MinBalPerLot_RRA_AUDUSD = 1200.0;
|
||||
input double MinBalPerLot_SE = 1500.0;
|
||||
input double MinBalPerLot_RCO = 1800.0;
|
||||
input double MinBalanceSafetyBufferPercent = 25.0;
|
||||
input double MinAbsoluteRecommendedBalance = 300.0;
|
||||
|
||||
double ClampValue(const double v, const double minV, const double maxV)
|
||||
{
|
||||
if(v < minV) return minV;
|
||||
if(v > maxV) return maxV;
|
||||
return v;
|
||||
}
|
||||
|
||||
double GetAutoScaledLot(const double baseLot)
|
||||
{
|
||||
const double scaled = baseLot * g_LotScaleFinal;
|
||||
if(scaled <= 0.0)
|
||||
return 0.0;
|
||||
return scaled;
|
||||
}
|
||||
|
||||
double ComputeRecommendedMinBalance()
|
||||
{
|
||||
double required = 0.0;
|
||||
required += LOT_ES_EMASlopeDistance * MinBalPerLot_ES;
|
||||
required += LOT_RC_RSICrossOver * MinBalPerLot_RC;
|
||||
required += LOT_RM_RSIMidPointHijack * MinBalPerLot_RM;
|
||||
required += LOT_RS_APPL * MinBalPerLot_RS_APPL;
|
||||
required += LOT_RS_BTCUSD * MinBalPerLot_RS_BTCUSD;
|
||||
required += LOT_RS_NVDA * MinBalPerLot_RS_NVDA;
|
||||
required += LOT_RS_TSLA * MinBalPerLot_RS_TSLA;
|
||||
required += LOT_RS_XAUUSD * MinBalPerLot_RS_XAUUSD;
|
||||
required += LOT_RRA_EURUSD * MinBalPerLot_RRA_EURUSD;
|
||||
required += LOT_RRA_AUDUSD * MinBalPerLot_RRA_AUDUSD;
|
||||
required += LOT_SE_SuperEMA * MinBalPerLot_SE;
|
||||
required += LOT_RCO_RSIConsolidation * MinBalPerLot_RCO;
|
||||
required *= (1.0 + MinBalanceSafetyBufferPercent / 100.0);
|
||||
if(required < MinAbsoluteRecommendedBalance)
|
||||
required = MinAbsoluteRecommendedBalance;
|
||||
return required;
|
||||
}
|
||||
|
||||
void UpdateAutoLotScaling()
|
||||
{
|
||||
if(!EnableAutoLotScaling)
|
||||
{
|
||||
g_LotScaleGrowth = 1.0;
|
||||
g_LotScaleMargin = 1.0;
|
||||
g_LotScaleFinal = 1.0;
|
||||
return;
|
||||
}
|
||||
|
||||
double refBalance = ScalingReferenceBalanceUSD;
|
||||
if(refBalance < 1.0)
|
||||
refBalance = 1.0;
|
||||
|
||||
const double balance = AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
const double equity = AccountInfoDouble(ACCOUNT_EQUITY);
|
||||
double base = MathMax(balance, equity);
|
||||
if(base < 1.0)
|
||||
base = 1.0;
|
||||
|
||||
const double growthRatio = base / refBalance;
|
||||
g_LotScaleGrowth = MathPow(growthRatio, ScalingCurveExponent);
|
||||
g_LotScaleGrowth = ClampValue(g_LotScaleGrowth, ScaleMinMultiplier, ScaleMaxMultiplier);
|
||||
|
||||
g_LotScaleMargin = 1.0;
|
||||
if(EnableMarginGuard)
|
||||
{
|
||||
const double ml = AccountInfoDouble(ACCOUNT_MARGIN_LEVEL);
|
||||
if(ml <= 0.0 || ml != ml)
|
||||
{
|
||||
g_LotScaleMargin = 1.0;
|
||||
}
|
||||
else if(ml >= MarginSafeLevelPercent)
|
||||
{
|
||||
g_LotScaleMargin = 1.0;
|
||||
}
|
||||
else if(ml <= MarginCriticalLevelPercent)
|
||||
{
|
||||
g_LotScaleMargin = MarginGuardMinMultiplier;
|
||||
}
|
||||
else
|
||||
{
|
||||
const double span = MarginSafeLevelPercent - MarginCriticalLevelPercent;
|
||||
const double t = (span > 0.0) ? (ml - MarginCriticalLevelPercent) / span : 0.0;
|
||||
g_LotScaleMargin = MarginGuardMinMultiplier + t * (1.0 - MarginGuardMinMultiplier);
|
||||
}
|
||||
g_LotScaleMargin = ClampValue(g_LotScaleMargin, MarginGuardMinMultiplier, 1.0);
|
||||
}
|
||||
|
||||
g_LotScaleFinal = g_LotScaleGrowth * g_LotScaleMargin;
|
||||
g_LotScaleFinal = ClampValue(g_LotScaleFinal, ScaleMinMultiplier, ScaleMaxMultiplier);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Strategy 1: DarvasBoxXAUUSD |
|
||||
@@ -131,7 +213,6 @@ input double DB_TrendThreshold = 4.94;
|
||||
input int DB_VolumeMA_Period = 110;
|
||||
input double DB_VolumeThresholdMultiplier = 1.5;
|
||||
input int DB_MagicNumber = 135790;
|
||||
input double DB_BaseLotSize = 0.01; // Base lot at InpDynamicRefDeposit (Darvas)
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Strategy 2: EMASlopeDistanceCocktailXAUUSD |
|
||||
@@ -318,35 +399,21 @@ input double RS_XAUUSD_LotSize = 0.1;
|
||||
input int RS_XAUUSD_MagicNumber = 129102315;
|
||||
input int RS_XAUUSD_Slippage = 3;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Strategy: RSI Secret Sauce XAUUSD (leave zone → re-entry peak/bottom) |
|
||||
//| Defaults match secret_sauce.set except symbol stays XAUUSD here. |
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== RSI Secret Sauce XAUUSD ==="
|
||||
input string RSS_XAUUSD_Symbol = "XAUUSD"; // not BTCUSD — gold chart / portfolio default
|
||||
input double RSS_XAUUSD_LotSize = 0.1;
|
||||
input int RSS_XAUUSD_MagicNumber = 789012;
|
||||
input int RSS_XAUUSD_Slippage = 10;
|
||||
input ENUM_TIMEFRAMES RSS_XAUUSD_Timeframe = PERIOD_M30;
|
||||
input int RSS_XAUUSD_RSIPeriod = 16;
|
||||
input double RSS_XAUUSD_RSIOverbought = 72.5;
|
||||
input double RSS_XAUUSD_RSIOversold = 32.5;
|
||||
input int RSS_XAUUSD_RSILookback = 60;
|
||||
input int RSS_XAUUSD_PeakBars = 2;
|
||||
input bool RSS_XAUUSD_RequireDivergence = false;
|
||||
input double RSS_XAUUSD_StopLossATR = 2.75;
|
||||
input double RSS_XAUUSD_TakeProfitATR = 5.0;
|
||||
input int RSS_XAUUSD_ATRPeriod = 14;
|
||||
input bool RSS_XAUUSD_UseSwingStopLoss = false;
|
||||
input int RSS_XAUUSD_SwingLookback = 30;
|
||||
input int RSS_XAUUSD_MaxPositions = 1;
|
||||
input int RSS_XAUUSD_MinBarsBetweenTrades = 7;
|
||||
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;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Strategy 11-12: RSI Reversal (Asian session) EURUSD & AUDUSD |
|
||||
//| Same logic as RSIReversalAsianEURUSD / RSIReversalAsianAUDUSD EAs |
|
||||
//| 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 EURUSD (Asian session) ==="
|
||||
input group "=== RSI Reversal Asian EURUSD ==="
|
||||
input string RRA_EURUSD_Symbol = "EURUSD";
|
||||
input int RRA_EURUSD_RSIPeriod = 28;
|
||||
input double RRA_EURUSD_OverboughtLevel = 60;
|
||||
@@ -365,7 +432,7 @@ input ENUM_TIMEFRAMES RRA_EURUSD_TimeFrame = PERIOD_M15;
|
||||
input int RRA_EURUSD_MagicNumber = 30001;
|
||||
input int RRA_EURUSD_Slippage = 3;
|
||||
|
||||
input group "=== RSI Reversal AUDUSD (Asian session) ==="
|
||||
input group "=== RSI Reversal Asian AUDUSD ==="
|
||||
input string RRA_AUDUSD_Symbol = "AUDUSD";
|
||||
input int RRA_AUDUSD_RSIPeriod = 28;
|
||||
input double RRA_AUDUSD_OverboughtLevel = 68;
|
||||
@@ -384,45 +451,62 @@ input ENUM_TIMEFRAMES RRA_AUDUSD_TimeFrame = PERIOD_M15;
|
||||
input int RRA_AUDUSD_MagicNumber = 30002;
|
||||
input int RRA_AUDUSD_Slippage = 3;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chart panel: closed-deal P&L by strategy (magic) + optional open |
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== Chart profit panel (by magic) ==="
|
||||
input bool UnitedPanel_Enable = false; // OBJ_LABEL + background on chart
|
||||
input int UnitedPanel_Seconds = 60; // refresh interval (min 5); history scan once per tick
|
||||
input int UnitedPanel_Corner = 0; // ENUM_BASE_CORNER e.g. 0=left upper
|
||||
input int UnitedPanel_X = 8;
|
||||
input int UnitedPanel_Y = 24;
|
||||
input int UnitedPanel_Width = 360;
|
||||
input int UnitedPanel_FontSize = 9;
|
||||
input int UnitedPanel_XMargin = 6;
|
||||
input int UnitedPanel_YMargin = 6;
|
||||
input bool UnitedPanel_ShowFloating = false; // open P/L+swap per magic
|
||||
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;
|
||||
|
||||
enum ENUM_ADAPTIVE_STREAK_UNIT
|
||||
{
|
||||
ADAPTIVE_STREAK_BY_MONTH = 0, // consecutive closed calendar months
|
||||
ADAPTIVE_STREAK_BY_DAY = 1 // consecutive closed calendar days (server time)
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Pause strategies after consecutive losing periods (month or day)|
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== Adaptive regime (per robot / magic) ==="
|
||||
input bool InpAdaptiveEnable = true; // If false, every other InpAdaptive* input is ignored (no streak / canary / pause). Set true to optimize or use adaptive regime.
|
||||
input ENUM_ADAPTIVE_STREAK_UNIT InpAdaptiveStreakUnit = ADAPTIVE_STREAK_BY_DAY;
|
||||
input int InpAdaptiveRedStreak = 5; // consecutive red months OR red days (see streak unit)
|
||||
input double InpAdaptiveRedThreshold = 0.0; // period P/L < -threshold counts red (0 = any loss)
|
||||
input int InpAdaptiveLookbackMonths = 14; // if unit=MONTH: history depth in months (>= streak+1)
|
||||
input int InpAdaptiveLookbackDays = 36; // if unit=DAY: closed days of history (>= streak+1)
|
||||
input int InpAdaptiveUpdateSeconds = 3600; // min 60; how often to recompute
|
||||
input double InpAdaptiveCanaryLotMult = 0.07; // probation: scale lots (0 = hard pause on streak, no canary)
|
||||
input int InpAdaptiveHardRetryMonths = 3; // if unit=MONTH: 0=no auto retry; else retry after N months
|
||||
input int InpAdaptiveHardRetryDays = 32; // if unit=DAY: 0=no auto retry; else retry after N days
|
||||
input int InpAdaptivePostCanaryCooldownDays = 37; // after successful canary, block re-arming another canary (days)
|
||||
|
||||
#include "UnitedProfitPanel.mqh"
|
||||
#include "AdaptiveMonthlyRegime.mqh"
|
||||
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;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Global Variables - DarvasBox |
|
||||
@@ -520,137 +604,14 @@ RSIScalpingData rsBTCUSDData;
|
||||
RSIScalpingData rsNVDAData;
|
||||
RSIScalpingData rsTSLAData;
|
||||
RSIScalpingData rsXAUUSDData;
|
||||
SuperEMAData seData;
|
||||
RSIConsolidationData rcoData;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Global Variables - RSI Reversal Asian |
|
||||
//+------------------------------------------------------------------+
|
||||
RSIReversalAsianData rraEURUSDData;
|
||||
RSIReversalAsianData rraAUDUSDData;
|
||||
RSISecretSauceData rsSecretSauceXAUUSDData;
|
||||
SuperEMAData seData;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Dynamic lot helpers |
|
||||
//+------------------------------------------------------------------+
|
||||
double DynClamp(const double v, const double lo, const double hi)
|
||||
{
|
||||
return MathMax(lo, MathMin(hi, v));
|
||||
}
|
||||
|
||||
// maxMult<=0: no ceiling. minMult<=0: no floor on raw (equity/ref)^exp.
|
||||
double ApplyDynamicMultClamp(const double mult)
|
||||
{
|
||||
double m = mult;
|
||||
if(InpDynamicMinMult > 0.0)
|
||||
m = MathMax(m, InpDynamicMinMult);
|
||||
if(InpDynamicMaxMult > 0.0)
|
||||
m = MathMin(m, InpDynamicMaxMult);
|
||||
return m;
|
||||
}
|
||||
|
||||
double NormalizeVolumeForSymbol(const string symbol, double lots)
|
||||
{
|
||||
double minL = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
|
||||
double maxL = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
|
||||
double step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
|
||||
if(step > 0.0)
|
||||
lots = MathFloor(lots / step + 1e-12) * step;
|
||||
if(lots < minL) lots = minL;
|
||||
if(lots > maxL) lots = maxL;
|
||||
return lots;
|
||||
}
|
||||
|
||||
void UpdateEquityPeakForDdCap()
|
||||
{
|
||||
if(!InpDdLotCapEnable || !InpDdLotCapGlobalEquityEnable)
|
||||
return;
|
||||
const double cur = InpDdLotCapUseEquity ? AccountInfoDouble(ACCOUNT_EQUITY) : AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
if(cur > g_equityPeakHighWater)
|
||||
g_equityPeakHighWater = cur;
|
||||
}
|
||||
|
||||
// After dynamic sizing: global equity DD and/or per-strategy last-month loser -> clamp to InpDdLotCapMaxLots.
|
||||
double LotsAfterDrawdownCap(const string symbol, const double lotsRaw, const int ddStratId = -1)
|
||||
{
|
||||
double lots = NormalizeVolumeForSymbol(symbol, lotsRaw);
|
||||
if(!InpDdLotCapEnable)
|
||||
return lots;
|
||||
|
||||
bool needCap = false;
|
||||
|
||||
if(InpDdLotCapGlobalEquityEnable)
|
||||
{
|
||||
bool globalCheck = true;
|
||||
if(InpDdLotCapGraceDays > 0 && g_ddLotCapAnchorTime > 0)
|
||||
{
|
||||
const long needSec = (long)InpDdLotCapGraceDays * 86400L;
|
||||
if((long)(TimeCurrent() - g_ddLotCapAnchorTime) < needSec)
|
||||
globalCheck = false;
|
||||
}
|
||||
if(globalCheck && g_equityPeakHighWater > 0.0)
|
||||
{
|
||||
const double cur = InpDdLotCapUseEquity ? AccountInfoDouble(ACCOUNT_EQUITY) : AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
if(cur < g_equityPeakHighWater)
|
||||
{
|
||||
const double ddPct = 100.0 * (g_equityPeakHighWater - cur) / g_equityPeakHighWater;
|
||||
if(ddPct >= InpDdLotCapFromPeakPercent)
|
||||
needCap = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(InpDdLotCapPerStratEnable && ddStratId >= 0 && UnitedAdaptive_StratLastMonthIsLosing(ddStratId))
|
||||
needCap = true;
|
||||
|
||||
if(!needCap)
|
||||
return lots;
|
||||
return NormalizeVolumeForSymbol(symbol, MathMin(lots, InpDdLotCapMaxLots));
|
||||
}
|
||||
|
||||
double GetDynamicMultiplier()
|
||||
{
|
||||
if(!InpDynamicLotEnable)
|
||||
return 1.0;
|
||||
double cap = InpDynamicUseEquity ? AccountInfoDouble(ACCOUNT_EQUITY) : AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
if(cap <= 0.0)
|
||||
cap = InpDynamicRefDeposit;
|
||||
double refv = MathMax(InpDynamicRefDeposit, 1.0);
|
||||
double ratio = cap / refv;
|
||||
if(ratio <= 0.0)
|
||||
ratio = 1.0;
|
||||
double mult = MathPow(ratio, InpDynamicExponent);
|
||||
return ApplyDynamicMultClamp(mult);
|
||||
}
|
||||
|
||||
// baseLot = size at reference deposit; optionalCap 0 = no extra ceiling (broker min/max still apply)
|
||||
double DynamicLotForSymbol(const string symbol, const double baseLot, const double optionalCap = 0.0, const int ddStratId = -1)
|
||||
{
|
||||
double mult = GetDynamicMultiplier();
|
||||
g_DynMultLast = mult;
|
||||
double v = baseLot * mult;
|
||||
if(optionalCap > 0.0 && v > optionalCap)
|
||||
v = optionalCap;
|
||||
return LotsAfterDrawdownCap(symbol, v, ddStratId);
|
||||
}
|
||||
|
||||
void RefreshDynamicStrategyLots()
|
||||
{
|
||||
UpdateEquityPeakForDdCap();
|
||||
|
||||
if(!InpDynamicLotEnable)
|
||||
{
|
||||
g_ES_LotSize = LotsAfterDrawdownCap(ES_Symbol, ES_LotGröße * UnitedAdaptive_GetLotMult(UNITED_AD_ES), UNITED_AD_ES);
|
||||
g_RC_LotSize = LotsAfterDrawdownCap(RC_Symbol, RC_lotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RC), UNITED_AD_RC);
|
||||
g_RM_LotSize = LotsAfterDrawdownCap(RM_Symbol, RM_InpLotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RM), UNITED_AD_RM);
|
||||
g_DB_LotSize = LotsAfterDrawdownCap(DB_Symbol, DB_BaseLotSize * UnitedAdaptive_GetLotMult(UNITED_AD_DARVAS), UNITED_AD_DARVAS);
|
||||
g_DynMultLast = 1.0;
|
||||
return;
|
||||
}
|
||||
g_ES_LotSize = DynamicLotForSymbol(ES_Symbol, ES_LotGröße * UnitedAdaptive_GetLotMult(UNITED_AD_ES), 0.0, UNITED_AD_ES);
|
||||
g_RC_LotSize = DynamicLotForSymbol(RC_Symbol, RC_lotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RC), 0.0, UNITED_AD_RC);
|
||||
g_RM_LotSize = DynamicLotForSymbol(RM_Symbol, RM_InpLotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RM), 0.0, UNITED_AD_RM);
|
||||
g_DB_LotSize = DynamicLotForSymbol(DB_Symbol, DB_BaseLotSize * UnitedAdaptive_GetLotMult(UNITED_AD_DARVAS), 0.0, UNITED_AD_DARVAS);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
@@ -659,16 +620,21 @@ int OnInit()
|
||||
{
|
||||
int initResult = INIT_SUCCEEDED;
|
||||
|
||||
UnitedAdaptive_Init();
|
||||
UpdateAutoLotScaling();
|
||||
|
||||
// Initialize global lot size variables
|
||||
g_ES_LotSize = GetAutoScaledLot(LOT_ES_EMASlopeDistance);
|
||||
g_RC_LotSize = GetAutoScaledLot(LOT_RC_RSICrossOver);
|
||||
g_RM_LotSize = GetAutoScaledLot(LOT_RM_RSIMidPointHijack);
|
||||
|
||||
g_equityPeakHighWater = InpDdLotCapUseEquity ? AccountInfoDouble(ACCOUNT_EQUITY) : AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
if(g_equityPeakHighWater <= 0.0)
|
||||
g_equityPeakHighWater = MathMax(InpDynamicRefDeposit, 1.0);
|
||||
g_ddLotCapAnchorTime = TimeCurrent();
|
||||
|
||||
UnitedAdaptive_UpdateIfDue();
|
||||
|
||||
RefreshDynamicStrategyLots();
|
||||
if(PrintMinimumBalanceRecommendation)
|
||||
{
|
||||
const double minBalance = ComputeRecommendedMinBalance();
|
||||
Print("Lot scaling initialized | scale=", DoubleToString(g_LotScaleFinal, 3),
|
||||
" (growth=", DoubleToString(g_LotScaleGrowth, 3),
|
||||
", margin=", DoubleToString(g_LotScaleMargin, 3), ")",
|
||||
" | recommended minimum balance=", DoubleToString(minBalance, 2));
|
||||
}
|
||||
|
||||
// Initialize strategies - log warnings but don't fail entire EA if symbol unavailable
|
||||
if(EnableDarvasBox)
|
||||
@@ -702,31 +668,6 @@ int OnInit()
|
||||
|
||||
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);
|
||||
|
||||
// Initialize RSI Reversal Asian strategies
|
||||
if(EnableRSIReversalEURUSD)
|
||||
if(!InitRSIReversalAsian(rraEURUSDData, RRA_EURUSD_Symbol, RRA_EURUSD_RSIPeriod, RRA_EURUSD_OverboughtLevel, RRA_EURUSD_OversoldLevel,
|
||||
RRA_EURUSD_TakeProfitPips, RRA_EURUSD_StopLossPips, RRA_EURUSD_MaxLotSize,
|
||||
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: RSIReversalEURUSD strategy failed to initialize for symbol '", RRA_EURUSD_Symbol, "'");
|
||||
|
||||
if(EnableRSIReversalAUDUSD)
|
||||
if(!InitRSIReversalAsian(rraAUDUSDData, RRA_AUDUSD_Symbol, RRA_AUDUSD_RSIPeriod, RRA_AUDUSD_OverboughtLevel, RRA_AUDUSD_OversoldLevel,
|
||||
RRA_AUDUSD_TakeProfitPips, RRA_AUDUSD_StopLossPips, RRA_AUDUSD_MaxLotSize,
|
||||
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: RSIReversalAUDUSD strategy failed to initialize for symbol '", RRA_AUDUSD_Symbol, "'");
|
||||
|
||||
if(EnableRSISecretSauceXAUUSD)
|
||||
if(!InitRSISecretSauce(rsSecretSauceXAUUSDData, RSS_XAUUSD_Symbol, RSS_XAUUSD_Timeframe, RSS_XAUUSD_RSIPeriod,
|
||||
RSS_XAUUSD_RSIOverbought, RSS_XAUUSD_RSIOversold, RSS_XAUUSD_RSILookback, RSS_XAUUSD_PeakBars,
|
||||
RSS_XAUUSD_RequireDivergence, RSS_XAUUSD_StopLossATR, RSS_XAUUSD_TakeProfitATR, RSS_XAUUSD_ATRPeriod,
|
||||
RSS_XAUUSD_UseSwingStopLoss, RSS_XAUUSD_SwingLookback, RSS_XAUUSD_MaxPositions,
|
||||
RSS_XAUUSD_MinBarsBetweenTrades, RSS_XAUUSD_MagicNumber, RSS_XAUUSD_Slippage))
|
||||
Print("Warning: RSISecretSauceXAUUSD failed to initialize for symbol '", RSS_XAUUSD_Symbol, "'");
|
||||
|
||||
if(EnableSuperEMA)
|
||||
if(!InitSuperEMA(seData, SE_Symbol, SE_Timeframe, SE_SlippagePoints, SE_MagicNumber,
|
||||
@@ -737,19 +678,33 @@ int OnInit()
|
||||
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, "'");
|
||||
|
||||
string acctCur = AccountInfoString(ACCOUNT_CURRENCY);
|
||||
double eq0 = AccountInfoDouble(ACCOUNT_EQUITY);
|
||||
double refvInit = MathMax(InpDynamicRefDeposit, 1.0);
|
||||
double capInit = InpDynamicUseEquity ? eq0 : AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
if(capInit <= 0.0)
|
||||
capInit = refvInit;
|
||||
double ratioInit = capInit / refvInit;
|
||||
double rawPowInit = MathPow(ratioInit, InpDynamicExponent);
|
||||
Print("United EA v1.17 ", acctCur, " equity=", DoubleToString(eq0, 2), " equity/ref=", DoubleToString(ratioInit, 6),
|
||||
" raw^exp=", DoubleToString(rawPowInit, 6), " multOut=", DoubleToString(g_DynMultLast, 6),
|
||||
" minM=", InpDynamicMinMult, " maxM=", InpDynamicMaxMult, " ref=", InpDynamicRefDeposit, " exp=", InpDynamicExponent,
|
||||
" lots ES=", g_ES_LotSize, " RC=", g_RC_LotSize, " RM=", g_RM_LotSize, " DB=", g_DB_LotSize);
|
||||
Print("United EA initialized. Active strategies: ",
|
||||
(EnableDarvasBox ? "DarvasBox " : ""),
|
||||
(EnableEMASlopeDistance ? "EMASlope " : ""),
|
||||
@@ -760,29 +715,11 @@ int OnInit()
|
||||
(EnableRSIScalpingNVDA ? "RSIScalpingNVDA " : ""),
|
||||
(EnableRSIScalpingTSLA ? "RSIScalpingTSLA " : ""),
|
||||
(EnableRSIScalpingXAUUSD ? "RSIScalpingXAUUSD " : ""),
|
||||
(EnableRSIReversalEURUSD ? "RSIReversalEURUSD " : ""),
|
||||
(EnableRSIReversalAUDUSD ? "RSIReversalAUDUSD " : ""),
|
||||
(EnableRSISecretSauceXAUUSD ? "RSISecretSauceXAUUSD " : ""),
|
||||
(EnableSuperEMA ? "SuperEMA " : ""));
|
||||
|
||||
EventSetTimer(0);
|
||||
int timerSec = 0;
|
||||
if(UnitedPanel_Enable)
|
||||
timerSec = MathMax(5, UnitedPanel_Seconds);
|
||||
if(InpAdaptiveEnable)
|
||||
{
|
||||
const int adSec = MathMax(60, InpAdaptiveUpdateSeconds);
|
||||
timerSec = (timerSec == 0) ? adSec : MathMin(timerSec, adSec);
|
||||
}
|
||||
if(InpDdLotCapEnable && InpDdLotCapPerStratEnable && !InpAdaptiveEnable)
|
||||
{
|
||||
const int ddSec = MathMax(60, InpDdLotCapUpdateSeconds);
|
||||
timerSec = (timerSec == 0) ? ddSec : MathMin(timerSec, ddSec);
|
||||
}
|
||||
if(timerSec > 0)
|
||||
EventSetTimer(timerSec);
|
||||
UnitedProfitPanelInit();
|
||||
|
||||
(EnableSuperEMA ? "SuperEMA " : ""),
|
||||
(EnableRSIConsolidation ? "RSIConsolidation " : ""),
|
||||
(EnableRSIReversalAsianEURUSD ? "RSIReversalAsianEURUSD " : ""),
|
||||
(EnableRSIReversalAsianAUDUSD ? "RSIReversalAsianAUDUSD " : ""));
|
||||
|
||||
return initResult;
|
||||
}
|
||||
|
||||
@@ -791,9 +728,6 @@ int OnInit()
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
EventSetTimer(0);
|
||||
UnitedProfitPanelDeinit();
|
||||
|
||||
if(EnableDarvasBox)
|
||||
DeinitDarvasBox();
|
||||
|
||||
@@ -820,18 +754,18 @@ void OnDeinit(const int reason)
|
||||
|
||||
if(EnableRSIScalpingXAUUSD)
|
||||
DeinitRSIScalping(rsXAUUSDData);
|
||||
|
||||
if(EnableRSIReversalEURUSD)
|
||||
DeinitRSIReversalAsian(rraEURUSDData);
|
||||
|
||||
if(EnableRSIReversalAUDUSD)
|
||||
DeinitRSIReversalAsian(rraAUDUSDData);
|
||||
|
||||
if(EnableRSISecretSauceXAUUSD)
|
||||
DeinitRSISecretSauce(rsSecretSauceXAUUSDData);
|
||||
|
||||
if(EnableSuperEMA)
|
||||
DeinitSuperEMA(seData);
|
||||
|
||||
if(EnableRSIConsolidation)
|
||||
DeinitRSIConsolidation(rcoData);
|
||||
|
||||
if(EnableRSIReversalAsianEURUSD)
|
||||
DeinitRSIReversalAsian(rraEURUSDData);
|
||||
|
||||
if(EnableRSIReversalAsianAUDUSD)
|
||||
DeinitRSIReversalAsian(rraAUDUSDData);
|
||||
|
||||
Print("United EA deinitialized. Reason: ", reason);
|
||||
}
|
||||
@@ -841,84 +775,94 @@ void OnDeinit(const int reason)
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
UnitedAdaptive_ProcessCanaryTransitions();
|
||||
RefreshDynamicStrategyLots();
|
||||
|
||||
if(EnableDarvasBox && UnitedAdaptive_StrategyActive(UNITED_AD_DARVAS))
|
||||
UpdateAutoLotScaling();
|
||||
g_ES_LotSize = GetAutoScaledLot(LOT_ES_EMASlopeDistance);
|
||||
g_RC_LotSize = GetAutoScaledLot(LOT_RC_RSICrossOver);
|
||||
g_RM_LotSize = GetAutoScaledLot(LOT_RM_RSIMidPointHijack);
|
||||
|
||||
if(ScaleLogIntervalSeconds > 0)
|
||||
{
|
||||
const datetime now = TimeCurrent();
|
||||
if(g_LastScaleLogTime == 0 || (now - g_LastScaleLogTime) >= ScaleLogIntervalSeconds)
|
||||
{
|
||||
g_LastScaleLogTime = now;
|
||||
Print("Lot scale update | final=", DoubleToString(g_LotScaleFinal, 3),
|
||||
" growth=", DoubleToString(g_LotScaleGrowth, 3),
|
||||
" margin=", DoubleToString(g_LotScaleMargin, 3),
|
||||
" ml=", DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN_LEVEL), 1),
|
||||
" eq=", DoubleToString(AccountInfoDouble(ACCOUNT_EQUITY), 2),
|
||||
" bal=", DoubleToString(AccountInfoDouble(ACCOUNT_BALANCE), 2));
|
||||
}
|
||||
}
|
||||
|
||||
if(ShowScaleStatusOnChart)
|
||||
{
|
||||
const double minBalance = ComputeRecommendedMinBalance();
|
||||
Comment("Scale=", DoubleToString(g_LotScaleFinal, 3),
|
||||
" (growth=", DoubleToString(g_LotScaleGrowth, 3),
|
||||
", margin=", DoubleToString(g_LotScaleMargin, 3), ")",
|
||||
" | Rec.Min.Balance=", DoubleToString(minBalance, 2),
|
||||
" | MarginLevel=", DoubleToString(AccountInfoDouble(ACCOUNT_MARGIN_LEVEL), 1), "%");
|
||||
}
|
||||
|
||||
if(EnableDarvasBox)
|
||||
ProcessDarvasBox(DB_Symbol);
|
||||
|
||||
if(EnableEMASlopeDistance && UnitedAdaptive_StrategyActive(UNITED_AD_ES))
|
||||
if(EnableEMASlopeDistance)
|
||||
ProcessEMASlopeDistance(ES_Symbol);
|
||||
|
||||
if(EnableRSICrossOverReversal && UnitedAdaptive_StrategyActive(UNITED_AD_RC))
|
||||
if(EnableRSICrossOverReversal)
|
||||
ProcessRSICrossOverReversal(RC_Symbol);
|
||||
|
||||
if(EnableRSIMidPointHijack && UnitedAdaptive_StrategyActive(UNITED_AD_RM))
|
||||
if(EnableRSIMidPointHijack)
|
||||
ProcessRSIMidPointHijack(RM_Symbol);
|
||||
|
||||
if(EnableRSIScalpingAPPL && UnitedAdaptive_StrategyActive(UNITED_AD_RS_APPL))
|
||||
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,
|
||||
DynamicLotForSymbol(RS_APPL_Symbol, RS_APPL_LotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RS_APPL), InpDynamicStockLotCap, UNITED_AD_RS_APPL),
|
||||
RS_APPL_MagicNumber);
|
||||
RS_APPL_BarsToWait, GetAutoScaledLot(LOT_RS_APPL), RS_APPL_MagicNumber,
|
||||
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
|
||||
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult);
|
||||
|
||||
if(EnableRSIScalpingBTCUSD && UnitedAdaptive_StrategyActive(UNITED_AD_RS_BTC))
|
||||
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, DynamicLotForSymbol(RS_BTCUSD_Symbol, RS_BTCUSD_LotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RS_BTC), 0.0, UNITED_AD_RS_BTC), RS_BTCUSD_MagicNumber);
|
||||
RS_BTCUSD_BarsToWait, GetAutoScaledLot(LOT_RS_BTCUSD), RS_BTCUSD_MagicNumber,
|
||||
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
|
||||
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult);
|
||||
|
||||
if(EnableRSIScalpingNVDA && UnitedAdaptive_StrategyActive(UNITED_AD_RS_NVDA))
|
||||
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,
|
||||
DynamicLotForSymbol(RS_NVDA_Symbol, RS_NVDA_LotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RS_NVDA), InpDynamicStockLotCap, UNITED_AD_RS_NVDA),
|
||||
RS_NVDA_MagicNumber);
|
||||
RS_NVDA_BarsToWait, GetAutoScaledLot(LOT_RS_NVDA), RS_NVDA_MagicNumber,
|
||||
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
|
||||
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult);
|
||||
|
||||
if(EnableRSIScalpingTSLA && UnitedAdaptive_StrategyActive(UNITED_AD_RS_TSLA))
|
||||
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,
|
||||
DynamicLotForSymbol(RS_TSLA_Symbol, RS_TSLA_LotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RS_TSLA), InpDynamicStockLotCap, UNITED_AD_RS_TSLA),
|
||||
RS_TSLA_MagicNumber);
|
||||
RS_TSLA_BarsToWait, GetAutoScaledLot(LOT_RS_TSLA), RS_TSLA_MagicNumber,
|
||||
false, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
|
||||
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult);
|
||||
|
||||
if(EnableRSIScalpingXAUUSD && UnitedAdaptive_StrategyActive(UNITED_AD_RS_XAU))
|
||||
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, DynamicLotForSymbol(RS_XAUUSD_Symbol, RS_XAUUSD_LotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RS_XAU), 0.0, UNITED_AD_RS_XAU), RS_XAUUSD_MagicNumber);
|
||||
RS_XAUUSD_BarsToWait, GetAutoScaledLot(LOT_RS_XAUUSD), RS_XAUUSD_MagicNumber,
|
||||
RS_UseReversalEscape, RS_ReversalATRPeriod, RS_ReversalAdverseAtrMult, RS_ReversalSignsRequired,
|
||||
RS_ReversalRsiVelocity, RS_ReversalBodyAtrMult);
|
||||
|
||||
if(EnableRSIReversalEURUSD && UnitedAdaptive_StrategyActive(UNITED_AD_RRA_EUR))
|
||||
ProcessRSIReversalAsian(rraEURUSDData, DynamicLotForSymbol(RRA_EURUSD_Symbol, RRA_EURUSD_MaxLotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RRA_EUR), 0.0, UNITED_AD_RRA_EUR));
|
||||
if(EnableRSIReversalAsianEURUSD)
|
||||
ProcessRSIReversalAsian(rraEURUSDData, GetAutoScaledLot(LOT_RRA_EURUSD));
|
||||
|
||||
if(EnableRSIReversalAUDUSD && UnitedAdaptive_StrategyActive(UNITED_AD_RRA_AUD))
|
||||
ProcessRSIReversalAsian(rraAUDUSDData, DynamicLotForSymbol(RRA_AUDUSD_Symbol, RRA_AUDUSD_MaxLotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RRA_AUD), 0.0, UNITED_AD_RRA_AUD));
|
||||
if(EnableRSIReversalAsianAUDUSD)
|
||||
ProcessRSIReversalAsian(rraAUDUSDData, GetAutoScaledLot(LOT_RRA_AUDUSD));
|
||||
|
||||
if(EnableRSISecretSauceXAUUSD && UnitedAdaptive_StrategyActive(UNITED_AD_RSS))
|
||||
ProcessRSISecretSauce(rsSecretSauceXAUUSDData, DynamicLotForSymbol(RSS_XAUUSD_Symbol, RSS_XAUUSD_LotSize * UnitedAdaptive_GetLotMult(UNITED_AD_RSS), 0.0, UNITED_AD_RSS));
|
||||
if(EnableSuperEMA)
|
||||
ProcessSuperEMA(seData, GetAutoScaledLot(LOT_SE_SuperEMA));
|
||||
|
||||
if(EnableSuperEMA && UnitedAdaptive_StrategyActive(UNITED_AD_SUPEREMA))
|
||||
ProcessSuperEMA(seData, DynamicLotForSymbol(SE_Symbol, SE_LotSize * UnitedAdaptive_GetLotMult(UNITED_AD_SUPEREMA), 0.0, UNITED_AD_SUPEREMA));
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Timer — refresh profit panel (history scan) |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTimer()
|
||||
{
|
||||
if(InpAdaptiveEnable)
|
||||
UnitedAdaptive_ProcessCanaryTransitions();
|
||||
if(InpAdaptiveEnable || (InpDdLotCapEnable && InpDdLotCapPerStratEnable))
|
||||
UnitedAdaptive_UpdateIfDue();
|
||||
if(UnitedPanel_Enable)
|
||||
UnitedProfitPanelRefresh();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Chart events — panel layout on resize |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
|
||||
{
|
||||
UnitedProfitPanelOnChartEvent(id);
|
||||
if(EnableRSIConsolidation)
|
||||
ProcessRSIConsolidation(rcoData, GetAutoScaledLot(LOT_RCO_RSIConsolidation));
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
@@ -25,6 +25,7 @@ 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;
|
||||
@@ -154,6 +155,7 @@ input int RM_InpEMADistancePeriod = 26;
|
||||
//| 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 |
|
||||
@@ -194,6 +196,20 @@ 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;
|
||||
@@ -349,6 +365,7 @@ RSICrossOverData rcData;
|
||||
RSIMidPointData rmData;
|
||||
RSIScalpingData rsAPPLData;
|
||||
RSIScalpingData rsBTCUSDData;
|
||||
RSIScalpingData rsMSFTData;
|
||||
RSIScalpingData rsNVDAData;
|
||||
RSIScalpingData rsTSLAData;
|
||||
RSIScalpingData rsXAUUSDData;
|
||||
@@ -363,6 +380,7 @@ double g_RC_LotSize = 0.01; // RSI CrossOver Reversal - start with minimum
|
||||
double g_RM_LotSize = 0.01; // RSI MidPoint Hijack - start with minimum
|
||||
double g_RS_APPL_LotSize = 5.0; // Stock - start with stock minimum (5.0)
|
||||
double g_RS_BTCUSD_LotSize = 0.01; // Crypto - start with forex minimum (0.01)
|
||||
double g_RS_MSFT_LotSize = 5.0; // Stock - start with stock minimum (5.0)
|
||||
double g_RS_NVDA_LotSize = 5.0; // Stock - start with stock minimum (5.0)
|
||||
double g_RS_TSLA_LotSize = 5.0; // Stock - start with stock minimum (5.0)
|
||||
double g_RS_XAUUSD_LotSize = 0.01; // Forex - start with forex minimum (0.01)
|
||||
@@ -446,6 +464,15 @@ int OnInit()
|
||||
g_RS_BTCUSD_LotSize = minLot;
|
||||
}
|
||||
|
||||
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);
|
||||
RegisterStrategy("RSIScalpingMSFT", RS_MSFT_MagicNumber, RS_MSFT_LotSize, RS_MSFT_Symbol);
|
||||
// Start with minimum lot size (will be adjusted by performance evaluator)
|
||||
double minLot = GetMinLotSizeForSymbol(RS_MSFT_Symbol);
|
||||
g_RS_MSFT_LotSize = minLot;
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -492,6 +519,9 @@ int OnInit()
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingBTCUSD", RS_BTCUSD_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_BTCUSD_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingMSFT", RS_MSFT_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_MSFT_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingNVDA", RS_NVDA_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_NVDA_LotSize = adjustedLot;
|
||||
|
||||
@@ -509,6 +539,7 @@ int OnInit()
|
||||
(EnableRSIMidPointHijack ? "RSIMidPoint " : ""),
|
||||
(EnableRSIScalpingAPPL ? "RSIScalpingAPPL " : ""),
|
||||
(EnableRSIScalpingBTCUSD ? "RSIScalpingBTCUSD " : ""),
|
||||
(EnableRSIScalpingMSFT ? "RSIScalpingMSFT " : ""),
|
||||
(EnableRSIScalpingNVDA ? "RSIScalpingNVDA " : ""),
|
||||
(EnableRSIScalpingTSLA ? "RSIScalpingTSLA " : ""),
|
||||
(EnableRSIScalpingXAUUSD ? "RSIScalpingXAUUSD " : ""));
|
||||
@@ -542,6 +573,9 @@ void OnDeinit(const int reason)
|
||||
if(EnableRSIScalpingBTCUSD)
|
||||
DeinitRSIScalping(rsBTCUSDData);
|
||||
|
||||
if(EnableRSIScalpingMSFT)
|
||||
DeinitRSIScalping(rsMSFTData);
|
||||
|
||||
if(EnableRSIScalpingNVDA)
|
||||
DeinitRSIScalping(rsNVDAData);
|
||||
|
||||
@@ -581,6 +615,9 @@ void OnTick()
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingBTCUSD", RS_BTCUSD_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_BTCUSD_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingMSFT", RS_MSFT_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_MSFT_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingNVDA", RS_NVDA_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_NVDA_LotSize = adjustedLot;
|
||||
|
||||
@@ -613,6 +650,11 @@ void OnTick()
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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,
|
||||
@@ -1,28 +1,30 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Select position by symbol and magic number |
|
||||
//+------------------------------------------------------------------+
|
||||
bool PositionSelectByMagic(string symbol, ulong magic_number)
|
||||
{
|
||||
// First try to find position by symbol
|
||||
if(!PositionSelect(symbol))
|
||||
return false;
|
||||
|
||||
|
||||
// Check if the selected position has the correct magic number
|
||||
if(PositionGetInteger(POSITION_MAGIC) != magic_number)
|
||||
{
|
||||
// Position exists but wrong magic number, search all positions
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||
{
|
||||
if(PositionGetTicket(i) > 0)
|
||||
{
|
||||
if(PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||
if(PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||
PositionGetInteger(POSITION_MAGIC) == magic_number)
|
||||
{
|
||||
return true;
|
||||
@@ -31,7 +33,7 @@ bool PositionSelectByMagic(string symbol, ulong magic_number)
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -42,7 +44,7 @@ bool PositionSelectByTicketAndMagic(ulong ticket, ulong magic_number)
|
||||
{
|
||||
if(!PositionSelectByTicket(ticket))
|
||||
return false;
|
||||
|
||||
|
||||
return (PositionGetInteger(POSITION_MAGIC) == magic_number);
|
||||
}
|
||||
|
||||
@@ -53,8 +55,8 @@ bool PositionSelectByTicketSymbolAndMagic(ulong ticket, string symbol, ulong mag
|
||||
{
|
||||
if(!PositionSelectByTicket(ticket))
|
||||
return false;
|
||||
|
||||
return (PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||
|
||||
return (PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||
PositionGetInteger(POSITION_MAGIC) == magic_number);
|
||||
}
|
||||
|
||||
@@ -76,7 +78,7 @@ ulong GetPositionTicketByMagic(string symbol, ulong magic_number)
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if(ticket > 0)
|
||||
{
|
||||
if(PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||
if(PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||
PositionGetInteger(POSITION_MAGIC) == magic_number)
|
||||
{
|
||||
return ticket;
|
||||
@@ -94,20 +96,20 @@ 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)
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -118,7 +120,7 @@ double GetPositionProfitByMagic(string symbol, ulong magic_number)
|
||||
{
|
||||
if(!PositionSelectByMagic(symbol, magic_number))
|
||||
return 0.0;
|
||||
|
||||
|
||||
return PositionGetDouble(POSITION_PROFIT);
|
||||
}
|
||||
|
||||
@@ -129,7 +131,7 @@ ENUM_POSITION_TYPE GetPositionTypeByMagic(string symbol, ulong magic_number)
|
||||
{
|
||||
if(!PositionSelectByMagic(symbol, magic_number))
|
||||
return WRONG_VALUE;
|
||||
|
||||
|
||||
return (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
}
|
||||
|
||||
@@ -144,7 +146,7 @@ int CountPositionsByMagic(string symbol, ulong magic_number)
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if(ticket > 0)
|
||||
{
|
||||
if(PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||
if(PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||
PositionGetInteger(POSITION_MAGIC) == magic_number)
|
||||
{
|
||||
count++;
|
||||
@@ -0,0 +1,607 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| PerformanceEvaluator.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"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Performance Metrics Structure |
|
||||
//+------------------------------------------------------------------+
|
||||
struct StrategyPerformance {
|
||||
string strategyName;
|
||||
string symbol; // Store symbol to determine if it's a stock
|
||||
int magicNumber;
|
||||
double initialLotSize;
|
||||
double currentLotSize;
|
||||
double quarterProfit;
|
||||
double quarterTrades;
|
||||
double quarterWins;
|
||||
double quarterLosses;
|
||||
double maxDrawdown;
|
||||
double winRate;
|
||||
datetime quarterStart;
|
||||
datetime quarterEnd;
|
||||
bool isActive;
|
||||
bool inPenaltyMode; // True if strategy is in penalty (worst performer)
|
||||
double lotSizeBeforePenalty; // Store lot size before penalty
|
||||
datetime penaltyStartTime; // When penalty started
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Global Performance Tracking |
|
||||
//+------------------------------------------------------------------+
|
||||
StrategyPerformance strategyPerformances[];
|
||||
int totalStrategies = 0;
|
||||
datetime lastMonthCheck = 0;
|
||||
datetime currentMonthStart = 0;
|
||||
datetime currentMonthEnd = 0;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Performance Adjustment Parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
input group "=== Performance Evaluation Settings ==="
|
||||
input bool PE_EnableAutoAdjustment = true; // Enable automatic lot size adjustment
|
||||
input double PE_LotSizeIncreasePercent = 10.0; // % increase for top-ranked strategies
|
||||
input double PE_LotSizeDecreasePercent = 10.0; // % decrease for bottom-ranked strategies
|
||||
input double PE_MinLotSize = 0.01; // Minimum lot size for forex/crypto
|
||||
input double PE_MinLotSizeStocks = 5.0; // Minimum lot size for stocks (5-10 range)
|
||||
input double PE_MaxLotSize = 100.0; // Maximum lot size after adjustment
|
||||
input int PE_TopPerformersCount = 3; // Number of top strategies to increase lot size
|
||||
input int PE_BottomPerformersCount = 3; // Number of bottom strategies to decrease lot size
|
||||
input bool PE_UseWinRateWeight = true; // Consider win rate in ranking (50% profit, 50% win rate)
|
||||
input bool PE_EnableBlitzPlay = true; // Enable blitz play: worst performer gets minimum lot size penalty
|
||||
input bool PE_EnableLogging = true; // Enable performance logging
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Initialize Performance Tracking |
|
||||
//+------------------------------------------------------------------+
|
||||
void InitPerformanceTracking()
|
||||
{
|
||||
// Calculate current month dates
|
||||
MqlDateTime dt;
|
||||
TimeToStruct(TimeCurrent(), dt);
|
||||
|
||||
// Determine month start (first day of current month)
|
||||
dt.day = 1;
|
||||
dt.hour = 0;
|
||||
dt.min = 0;
|
||||
dt.sec = 0;
|
||||
currentMonthStart = StructToTime(dt);
|
||||
|
||||
// Calculate month end (first day of next month - 1 second)
|
||||
dt.mon += 1;
|
||||
if(dt.mon > 12)
|
||||
{
|
||||
dt.mon = 1;
|
||||
dt.year++;
|
||||
}
|
||||
currentMonthEnd = StructToTime(dt) - 1; // End of last day of month
|
||||
|
||||
lastMonthCheck = TimeCurrent();
|
||||
|
||||
if(PE_EnableLogging)
|
||||
{
|
||||
Print("Performance Evaluator: Initialized");
|
||||
Print("Current Month Start: ", TimeToString(currentMonthStart));
|
||||
Print("Current Month End: ", TimeToString(currentMonthEnd));
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if Symbol is a Stock |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IsStockSymbol(string symbol)
|
||||
{
|
||||
// Check if symbol contains common stock indicators
|
||||
if(StringFind(symbol, ".US") >= 0) return true;
|
||||
if(StringFind(symbol, "NASDAQ:") >= 0) return true;
|
||||
if(StringFind(symbol, "NYSE:") >= 0) return true;
|
||||
|
||||
// Note: Symbol category check removed to avoid enum conversion issues
|
||||
// String-based checks (.US, NASDAQ:, NYSE:, common tickers) are sufficient
|
||||
|
||||
// Common stock tickers (without .US suffix)
|
||||
string commonStocks[] = {"AAPL", "MSFT", "NVDA", "TSLA", "GOOGL", "AMZN", "META", "NFLX"};
|
||||
for(int i = 0; i < ArraySize(commonStocks); i++)
|
||||
{
|
||||
if(StringFind(symbol, commonStocks[i]) == 0) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get Minimum Lot Size for Symbol |
|
||||
//+------------------------------------------------------------------+
|
||||
double GetMinLotSizeForSymbol(string symbol)
|
||||
{
|
||||
if(IsStockSymbol(symbol))
|
||||
return PE_MinLotSizeStocks;
|
||||
else
|
||||
return PE_MinLotSize;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Register Strategy for Performance Tracking |
|
||||
//+------------------------------------------------------------------+
|
||||
void RegisterStrategy(string strategyName, int magicNumber, double initialLotSize, string symbol = "")
|
||||
{
|
||||
// Check if strategy already registered
|
||||
for(int i = 0; i < ArraySize(strategyPerformances); i++)
|
||||
{
|
||||
if(strategyPerformances[i].strategyName == strategyName &&
|
||||
strategyPerformances[i].magicNumber == magicNumber)
|
||||
{
|
||||
if(PE_EnableLogging)
|
||||
Print("Performance Evaluator: Strategy '", strategyName, "' already registered");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Add new strategy
|
||||
int newSize = ArraySize(strategyPerformances) + 1;
|
||||
ArrayResize(strategyPerformances, newSize);
|
||||
|
||||
strategyPerformances[newSize - 1].strategyName = strategyName;
|
||||
strategyPerformances[newSize - 1].symbol = symbol;
|
||||
strategyPerformances[newSize - 1].magicNumber = magicNumber;
|
||||
strategyPerformances[newSize - 1].initialLotSize = initialLotSize;
|
||||
// Start with minimum lot size for safety (symbol-specific minimum)
|
||||
double minLot = GetMinLotSizeForSymbol(symbol);
|
||||
strategyPerformances[newSize - 1].currentLotSize = minLot;
|
||||
strategyPerformances[newSize - 1].quarterProfit = 0.0;
|
||||
strategyPerformances[newSize - 1].quarterTrades = 0;
|
||||
strategyPerformances[newSize - 1].quarterWins = 0;
|
||||
strategyPerformances[newSize - 1].quarterLosses = 0;
|
||||
strategyPerformances[newSize - 1].maxDrawdown = 0.0;
|
||||
strategyPerformances[newSize - 1].winRate = 0.0;
|
||||
strategyPerformances[newSize - 1].quarterStart = currentMonthStart;
|
||||
strategyPerformances[newSize - 1].quarterEnd = currentMonthEnd;
|
||||
strategyPerformances[newSize - 1].isActive = true;
|
||||
strategyPerformances[newSize - 1].inPenaltyMode = false;
|
||||
strategyPerformances[newSize - 1].lotSizeBeforePenalty = initialLotSize;
|
||||
strategyPerformances[newSize - 1].penaltyStartTime = 0;
|
||||
|
||||
totalStrategies = newSize;
|
||||
|
||||
if(PE_EnableLogging)
|
||||
Print("Performance Evaluator: Registered strategy '", strategyName,
|
||||
"' (Magic: ", magicNumber, ", Initial Lot: ", initialLotSize, ")");
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update Strategy Performance Metrics |
|
||||
//+------------------------------------------------------------------+
|
||||
void UpdateStrategyPerformance(string strategyName, int magicNumber)
|
||||
{
|
||||
for(int i = 0; i < ArraySize(strategyPerformances); i++)
|
||||
{
|
||||
if(strategyPerformances[i].strategyName == strategyName &&
|
||||
strategyPerformances[i].magicNumber == magicNumber &&
|
||||
strategyPerformances[i].isActive)
|
||||
{
|
||||
// Calculate performance for current quarter
|
||||
double totalProfit = 0.0;
|
||||
int totalTrades = 0;
|
||||
int wins = 0;
|
||||
int losses = 0;
|
||||
double maxDD = 0.0;
|
||||
double peakBalance = 0.0;
|
||||
|
||||
// Scan all closed deals in current quarter
|
||||
datetime quarterStart = strategyPerformances[i].quarterStart;
|
||||
datetime quarterEnd = strategyPerformances[i].quarterEnd;
|
||||
|
||||
// Select history for the quarter
|
||||
if(HistorySelect(quarterStart, quarterEnd))
|
||||
{
|
||||
int totalDeals = HistoryDealsTotal();
|
||||
for(int j = 0; j < totalDeals; j++)
|
||||
{
|
||||
ulong ticket = HistoryDealGetTicket(j);
|
||||
if(ticket > 0)
|
||||
{
|
||||
long dealMagic = HistoryDealGetInteger(ticket, DEAL_MAGIC);
|
||||
if(dealMagic == magicNumber)
|
||||
{
|
||||
double profit = HistoryDealGetDouble(ticket, DEAL_PROFIT);
|
||||
double swap = HistoryDealGetDouble(ticket, DEAL_SWAP);
|
||||
double commission = HistoryDealGetDouble(ticket, DEAL_COMMISSION);
|
||||
double totalDealProfit = profit + swap + commission;
|
||||
|
||||
totalProfit += totalDealProfit;
|
||||
totalTrades++;
|
||||
|
||||
if(totalDealProfit > 0)
|
||||
wins++;
|
||||
else if(totalDealProfit < 0)
|
||||
losses++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate win rate
|
||||
double winRate = 0.0;
|
||||
if(totalTrades > 0)
|
||||
winRate = (double)wins / (double)totalTrades * 100.0;
|
||||
|
||||
// Update metrics
|
||||
strategyPerformances[i].quarterProfit = totalProfit;
|
||||
strategyPerformances[i].quarterTrades = totalTrades;
|
||||
strategyPerformances[i].quarterWins = wins;
|
||||
strategyPerformances[i].quarterLosses = losses;
|
||||
strategyPerformances[i].winRate = winRate;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Strategy Ranking Structure |
|
||||
//+------------------------------------------------------------------+
|
||||
struct StrategyRank {
|
||||
int index;
|
||||
double score;
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate Strategy Score for Ranking |
|
||||
//+------------------------------------------------------------------+
|
||||
double CalculateStrategyScore(int strategyIndex)
|
||||
{
|
||||
double profit = strategyPerformances[strategyIndex].quarterProfit;
|
||||
double winRate = strategyPerformances[strategyIndex].winRate;
|
||||
double trades = strategyPerformances[strategyIndex].quarterTrades;
|
||||
|
||||
// Normalize profit (scale to 0-100 range, assuming max profit of $1000)
|
||||
double normalizedProfit = MathMin(profit / 10.0, 100.0);
|
||||
if(profit < 0) normalizedProfit = profit / 5.0; // Penalize losses more
|
||||
|
||||
// Calculate score
|
||||
double score = 0.0;
|
||||
if(PE_UseWinRateWeight)
|
||||
{
|
||||
// 50% profit, 50% win rate (if enough trades)
|
||||
if(trades >= 5)
|
||||
score = (normalizedProfit * 0.5) + (winRate * 0.5);
|
||||
else
|
||||
score = normalizedProfit; // Not enough trades, use profit only
|
||||
}
|
||||
else
|
||||
{
|
||||
// Profit only
|
||||
score = normalizedProfit;
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if Month Ended and Evaluate Performance |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckMonthEnd()
|
||||
{
|
||||
datetime now = TimeCurrent();
|
||||
|
||||
// Check if we've entered a new month
|
||||
if(now >= currentMonthEnd)
|
||||
{
|
||||
if(PE_EnableLogging)
|
||||
Print("Performance Evaluator: Month ended. Evaluating and ranking strategies...");
|
||||
|
||||
// Update performance metrics for all strategies
|
||||
for(int i = 0; i < ArraySize(strategyPerformances); i++)
|
||||
{
|
||||
if(strategyPerformances[i].isActive)
|
||||
{
|
||||
UpdateStrategyPerformance(strategyPerformances[i].strategyName,
|
||||
strategyPerformances[i].magicNumber);
|
||||
}
|
||||
}
|
||||
|
||||
// Rank strategies
|
||||
int activeCount = 0;
|
||||
for(int i = 0; i < ArraySize(strategyPerformances); i++)
|
||||
{
|
||||
if(strategyPerformances[i].isActive)
|
||||
activeCount++;
|
||||
}
|
||||
|
||||
if(activeCount > 0)
|
||||
{
|
||||
// Create ranking array
|
||||
StrategyRank ranks[];
|
||||
ArrayResize(ranks, activeCount);
|
||||
int rankIndex = 0;
|
||||
|
||||
for(int i = 0; i < ArraySize(strategyPerformances); i++)
|
||||
{
|
||||
if(strategyPerformances[i].isActive)
|
||||
{
|
||||
ranks[rankIndex].index = i;
|
||||
ranks[rankIndex].score = CalculateStrategyScore(i);
|
||||
rankIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by score (descending - highest score first)
|
||||
for(int i = 0; i < activeCount - 1; i++)
|
||||
{
|
||||
for(int j = i + 1; j < activeCount; j++)
|
||||
{
|
||||
if(ranks[j].score > ranks[i].score)
|
||||
{
|
||||
StrategyRank temp = ranks[i];
|
||||
ranks[i] = ranks[j];
|
||||
ranks[j] = temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Adjust lot sizes based on ranking
|
||||
if(PE_EnableAutoAdjustment)
|
||||
{
|
||||
// Increase top performers (skip if in penalty mode)
|
||||
int topCount = MathMin(PE_TopPerformersCount, activeCount);
|
||||
for(int i = 0; i < topCount; i++)
|
||||
{
|
||||
int strategyIdx = ranks[i].index;
|
||||
|
||||
// Skip if strategy is in penalty mode
|
||||
if(strategyPerformances[strategyIdx].inPenaltyMode)
|
||||
continue;
|
||||
|
||||
double oldLotSize = strategyPerformances[strategyIdx].currentLotSize;
|
||||
double newLotSize = oldLotSize * (1.0 + PE_LotSizeIncreasePercent / 100.0);
|
||||
|
||||
if(newLotSize > PE_MaxLotSize)
|
||||
newLotSize = PE_MaxLotSize;
|
||||
|
||||
strategyPerformances[strategyIdx].currentLotSize = newLotSize;
|
||||
|
||||
if(PE_EnableLogging)
|
||||
Print("Performance Evaluator: Rank #", (i+1), " - Increasing '",
|
||||
strategyPerformances[strategyIdx].strategyName,
|
||||
"' lot size from ", oldLotSize, " to ", newLotSize,
|
||||
" (Score: ", DoubleToString(ranks[i].score, 2),
|
||||
", Profit: $", DoubleToString(strategyPerformances[strategyIdx].quarterProfit, 2),
|
||||
", Win Rate: ", DoubleToString(strategyPerformances[strategyIdx].winRate, 2), "%)");
|
||||
}
|
||||
|
||||
// Decrease bottom performers (skip worst one if blitz play is enabled)
|
||||
int bottomCount = MathMin(PE_BottomPerformersCount, activeCount);
|
||||
int startIdx = activeCount - bottomCount;
|
||||
|
||||
// If blitz play is enabled, skip the worst performer (it will get minimum penalty)
|
||||
if(PE_EnableBlitzPlay && activeCount > 0)
|
||||
startIdx = activeCount - bottomCount + 1;
|
||||
|
||||
for(int i = startIdx; i < activeCount; i++)
|
||||
{
|
||||
int strategyIdx = ranks[i].index;
|
||||
|
||||
// Skip if strategy is in penalty mode
|
||||
if(strategyPerformances[strategyIdx].inPenaltyMode)
|
||||
continue;
|
||||
|
||||
double oldLotSize = strategyPerformances[strategyIdx].currentLotSize;
|
||||
double newLotSize = oldLotSize * (1.0 - PE_LotSizeDecreasePercent / 100.0);
|
||||
|
||||
// Use symbol-specific minimum lot size
|
||||
double minLot = GetMinLotSizeForSymbol(strategyPerformances[strategyIdx].symbol);
|
||||
if(newLotSize < minLot)
|
||||
newLotSize = minLot;
|
||||
|
||||
strategyPerformances[strategyIdx].currentLotSize = newLotSize;
|
||||
|
||||
if(PE_EnableLogging)
|
||||
Print("Performance Evaluator: Rank #", (i+1), " - Decreasing '",
|
||||
strategyPerformances[strategyIdx].strategyName,
|
||||
"' lot size from ", oldLotSize, " to ", newLotSize,
|
||||
" (Score: ", DoubleToString(ranks[i].score, 2),
|
||||
", Profit: $", DoubleToString(strategyPerformances[strategyIdx].quarterProfit, 2),
|
||||
", Win Rate: ", DoubleToString(strategyPerformances[strategyIdx].winRate, 2), "%)");
|
||||
}
|
||||
}
|
||||
|
||||
// Blitz Play: Apply penalty to worst performer
|
||||
if(PE_EnableBlitzPlay && activeCount > 0)
|
||||
{
|
||||
// Find worst performer (last in ranking)
|
||||
int worstIdx = ranks[activeCount - 1].index;
|
||||
|
||||
// Remove penalty from previous worst performer (if any)
|
||||
for(int i = 0; i < ArraySize(strategyPerformances); i++)
|
||||
{
|
||||
if(strategyPerformances[i].isActive && strategyPerformances[i].inPenaltyMode)
|
||||
{
|
||||
// Check if penalty period has passed (one month)
|
||||
if(now - strategyPerformances[i].penaltyStartTime >= 2592000) // ~30 days
|
||||
{
|
||||
// Restore lot size to before penalty
|
||||
strategyPerformances[i].currentLotSize = strategyPerformances[i].lotSizeBeforePenalty;
|
||||
strategyPerformances[i].inPenaltyMode = false;
|
||||
strategyPerformances[i].penaltyStartTime = 0;
|
||||
|
||||
if(PE_EnableLogging)
|
||||
Print("Blitz Play: Penalty removed from '", strategyPerformances[i].strategyName,
|
||||
"'. Lot size restored to ", strategyPerformances[i].currentLotSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply penalty to new worst performer
|
||||
if(!strategyPerformances[worstIdx].inPenaltyMode)
|
||||
{
|
||||
strategyPerformances[worstIdx].lotSizeBeforePenalty = strategyPerformances[worstIdx].currentLotSize;
|
||||
// Use symbol-specific minimum lot size
|
||||
double minLot = GetMinLotSizeForSymbol(strategyPerformances[worstIdx].symbol);
|
||||
strategyPerformances[worstIdx].currentLotSize = minLot;
|
||||
strategyPerformances[worstIdx].inPenaltyMode = true;
|
||||
strategyPerformances[worstIdx].penaltyStartTime = now;
|
||||
|
||||
if(PE_EnableLogging)
|
||||
Print("Blitz Play: WORST PERFORMER - '", strategyPerformances[worstIdx].strategyName,
|
||||
"' penalized! Lot size reduced from ", strategyPerformances[worstIdx].lotSizeBeforePenalty,
|
||||
" to minimum ", minLot, " (Score: ", DoubleToString(ranks[activeCount - 1].score, 2),
|
||||
", Profit: $", DoubleToString(strategyPerformances[worstIdx].quarterProfit, 2), ")");
|
||||
}
|
||||
}
|
||||
|
||||
// Log performance report
|
||||
if(PE_EnableLogging)
|
||||
{
|
||||
Print("=== Monthly Performance Ranking ===");
|
||||
for(int i = 0; i < activeCount; i++)
|
||||
{
|
||||
int strategyIdx = ranks[i].index;
|
||||
Print("Rank #", (i+1), ": ", strategyPerformances[strategyIdx].strategyName,
|
||||
" - Score: ", DoubleToString(ranks[i].score, 2),
|
||||
", Profit: $", DoubleToString(strategyPerformances[strategyIdx].quarterProfit, 2),
|
||||
", Win Rate: ", DoubleToString(strategyPerformances[strategyIdx].winRate, 2), "%",
|
||||
", Trades: ", (int)strategyPerformances[strategyIdx].quarterTrades,
|
||||
", Lot Size: ", DoubleToString(strategyPerformances[strategyIdx].currentLotSize, 2));
|
||||
}
|
||||
Print("===================================");
|
||||
}
|
||||
}
|
||||
|
||||
// Reset month metrics for all strategies
|
||||
for(int i = 0; i < ArraySize(strategyPerformances); i++)
|
||||
{
|
||||
if(strategyPerformances[i].isActive)
|
||||
{
|
||||
strategyPerformances[i].quarterProfit = 0.0;
|
||||
strategyPerformances[i].quarterTrades = 0;
|
||||
strategyPerformances[i].quarterWins = 0;
|
||||
strategyPerformances[i].quarterLosses = 0;
|
||||
strategyPerformances[i].maxDrawdown = 0.0;
|
||||
strategyPerformances[i].winRate = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
// Update month dates
|
||||
MqlDateTime dt;
|
||||
TimeToStruct(now, dt);
|
||||
|
||||
// First day of current month
|
||||
dt.day = 1;
|
||||
dt.hour = 0;
|
||||
dt.min = 0;
|
||||
dt.sec = 0;
|
||||
currentMonthStart = StructToTime(dt);
|
||||
|
||||
// First day of next month - 1 second
|
||||
dt.mon += 1;
|
||||
if(dt.mon > 12)
|
||||
{
|
||||
dt.mon = 1;
|
||||
dt.year++;
|
||||
}
|
||||
currentMonthEnd = StructToTime(dt) - 1;
|
||||
|
||||
// Update month dates for all strategies
|
||||
for(int i = 0; i < ArraySize(strategyPerformances); i++)
|
||||
{
|
||||
strategyPerformances[i].quarterStart = currentMonthStart;
|
||||
strategyPerformances[i].quarterEnd = currentMonthEnd;
|
||||
}
|
||||
|
||||
lastMonthCheck = now;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get Current Lot Size for Strategy |
|
||||
//+------------------------------------------------------------------+
|
||||
double GetStrategyLotSize(string strategyName, int magicNumber)
|
||||
{
|
||||
for(int i = 0; i < ArraySize(strategyPerformances); i++)
|
||||
{
|
||||
if(strategyPerformances[i].strategyName == strategyName &&
|
||||
strategyPerformances[i].magicNumber == magicNumber &&
|
||||
strategyPerformances[i].isActive)
|
||||
{
|
||||
return strategyPerformances[i].currentLotSize;
|
||||
}
|
||||
}
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Process Performance Evaluation (call from OnTick) |
|
||||
//+------------------------------------------------------------------+
|
||||
void ProcessPerformanceEvaluation()
|
||||
{
|
||||
// Check if month ended
|
||||
CheckMonthEnd();
|
||||
|
||||
// Check for penalty expiration (blitz play)
|
||||
if(PE_EnableBlitzPlay)
|
||||
{
|
||||
datetime now = TimeCurrent();
|
||||
for(int i = 0; i < ArraySize(strategyPerformances); i++)
|
||||
{
|
||||
if(strategyPerformances[i].isActive && strategyPerformances[i].inPenaltyMode)
|
||||
{
|
||||
// Check if penalty period has passed (one month = ~30 days)
|
||||
if(now - strategyPerformances[i].penaltyStartTime >= 2592000)
|
||||
{
|
||||
// Restore lot size to before penalty
|
||||
strategyPerformances[i].currentLotSize = strategyPerformances[i].lotSizeBeforePenalty;
|
||||
strategyPerformances[i].inPenaltyMode = false;
|
||||
strategyPerformances[i].penaltyStartTime = 0;
|
||||
|
||||
if(PE_EnableLogging)
|
||||
Print("Blitz Play: Penalty expired for '", strategyPerformances[i].strategyName,
|
||||
"'. Lot size restored to ", strategyPerformances[i].currentLotSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Update performance metrics periodically (every hour)
|
||||
static datetime lastUpdate = 0;
|
||||
if(TimeCurrent() - lastUpdate >= 3600)
|
||||
{
|
||||
for(int i = 0; i < ArraySize(strategyPerformances); i++)
|
||||
{
|
||||
if(strategyPerformances[i].isActive)
|
||||
{
|
||||
UpdateStrategyPerformance(strategyPerformances[i].strategyName,
|
||||
strategyPerformances[i].magicNumber);
|
||||
}
|
||||
}
|
||||
lastUpdate = TimeCurrent();
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get Performance Summary |
|
||||
//+------------------------------------------------------------------+
|
||||
string GetPerformanceSummary()
|
||||
{
|
||||
string summary = "\n=== Performance Summary ===\n";
|
||||
summary += "Current Month: " + TimeToString(currentMonthStart) + " to " + TimeToString(currentMonthEnd) + "\n\n";
|
||||
|
||||
for(int i = 0; i < ArraySize(strategyPerformances); i++)
|
||||
{
|
||||
if(strategyPerformances[i].isActive)
|
||||
{
|
||||
summary += strategyPerformances[i].strategyName + ":\n";
|
||||
summary += " Profit: $" + DoubleToString(strategyPerformances[i].quarterProfit, 2) + "\n";
|
||||
summary += " Trades: " + IntegerToString((int)strategyPerformances[i].quarterTrades) + "\n";
|
||||
summary += " Win Rate: " + DoubleToString(strategyPerformances[i].winRate, 2) + "%\n";
|
||||
summary += " Lot Size: " + DoubleToString(strategyPerformances[i].currentLotSize, 2) + "\n\n";
|
||||
}
|
||||
}
|
||||
|
||||
return summary;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -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,300 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| DarvasBoxStrategy.mqh |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
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);
|
||||
dbData.volumeHandle = iVolumes(symbol, PERIOD_CURRENT, 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)
|
||||
{
|
||||
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()
|
||||
{
|
||||
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];
|
||||
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;
|
||||
|
||||
// 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(0.01, dbData.symbol, 0, sl, tp, "Darvas Box Breakout");
|
||||
else
|
||||
result = dbData.trade.Sell(0.01, 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_CURRENT, 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,496 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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))
|
||||
{
|
||||
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))
|
||||
{
|
||||
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");
|
||||
Print("TRACE: Lot: ", g_ES_LotSize);
|
||||
|
||||
bool success = false;
|
||||
|
||||
if(order_type == ORDER_TYPE_BUY)
|
||||
{
|
||||
success = esData.trade.Buy(g_ES_LotSize, esData.symbol, 0, 0, 0, "EMA Crossover Trade");
|
||||
}
|
||||
else
|
||||
{
|
||||
success = esData.trade.Sell(g_ES_LotSize, 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);
|
||||
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;
|
||||
|
||||
double position_profit = PositionGetDouble(POSITION_PROFIT);
|
||||
double position_open_price = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
double current_price = PositionGetDouble(POSITION_PRICE_CURRENT);
|
||||
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;
|
||||
double trailing_stop_pips = ES_TrailingStop;
|
||||
|
||||
//--- Gleitender Stop (Trailing Stop) - nur wenn Position im Profit ist
|
||||
if(position_profit > 0) // Only apply trailing stop when in profit
|
||||
{
|
||||
if(position_type == POSITION_TYPE_BUY)
|
||||
{
|
||||
double new_stop_loss = current_price - (trailing_stop_pips * point * pips_multiplier);
|
||||
double current_stop_loss = PositionGetDouble(POSITION_SL);
|
||||
|
||||
// Only move stop loss if new stop is higher than current stop
|
||||
if(new_stop_loss > current_stop_loss)
|
||||
{
|
||||
ÄndereStopLoss(new_stop_loss);
|
||||
}
|
||||
}
|
||||
else if(position_type == POSITION_TYPE_SELL)
|
||||
{
|
||||
double new_stop_loss = current_price + (trailing_stop_pips * point * pips_multiplier);
|
||||
double current_stop_loss = PositionGetDouble(POSITION_SL);
|
||||
|
||||
// Only move stop loss if new stop is lower than current stop
|
||||
if(new_stop_loss < current_stop_loss || current_stop_loss == 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
// Skip if not initialized (symbol not available)
|
||||
if(!esData.isInitialized)
|
||||
return;
|
||||
|
||||
esData.symbol = symbol; // Update symbol in case it changed
|
||||
|
||||
//--- Bar-Daten oder Tick-Daten verwenden (Use bar data or tick data)
|
||||
if(ES_UseBarData)
|
||||
{
|
||||
//--- Nur bei neuen Bars ausführen (Only execute on new bars)
|
||||
datetime current_bar_time = iTime(esData.symbol, ES_Timeframe, 0);
|
||||
|
||||
if(current_bar_time == esData.last_bar_time)
|
||||
{
|
||||
return; // Kein neuer Bar, nichts tun
|
||||
}
|
||||
|
||||
esData.last_bar_time = current_bar_time;
|
||||
}
|
||||
|
||||
//--- EMA Werte berechnen (Calculate EMA values)
|
||||
BerechneEMA();
|
||||
|
||||
//--- Debug: Aktuelle Werte ausgeben (Debug: Output current values)
|
||||
if(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];
|
||||
int digits = (int)SymbolInfoInteger(esData.symbol, SYMBOL_DIGITS);
|
||||
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("==================");
|
||||
}
|
||||
|
||||
//--- Überwachung prüfen (Check monitoring)
|
||||
if(esData.überwachung_aktiv)
|
||||
{
|
||||
if(ES_UseBarData)
|
||||
{
|
||||
// Bar-basierte Überwachungszeit
|
||||
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
|
||||
{
|
||||
// Tick-basierte Überwachungszeit
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//--- Trigger-Bedingungen prüfen (Check trigger conditions)
|
||||
PrüfeTrigger();
|
||||
|
||||
//--- Trade Management (Trade management)
|
||||
VerwalteTrades();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,257 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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.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);
|
||||
double priceToEmaDistance = (closeCurr - currentEMA) * 10;
|
||||
|
||||
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;
|
||||
bool isTrendStrong = MathAbs(emaSlope) > RC_emaSlopeThreshold || MathAbs(priceToEmaDistance) > 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)
|
||||
{
|
||||
rcData.trade.SetExpertMagicNumber(RC_MagicNumber);
|
||||
if(rcData.trade.Sell(g_RC_LotSize, 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)
|
||||
{
|
||||
rcData.trade.SetExpertMagicNumber(RC_MagicNumber);
|
||||
if(rcData.trade.Buy(g_RC_LotSize, rcData.symbol, 0.0, 0.0, 0.0, "Buy Order"))
|
||||
{
|
||||
rcData.lastTradeTime = currentTime;
|
||||
}
|
||||
}
|
||||
|
||||
rcData.previousRSIDef = currentRSI;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,471 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RSIMidPointHijackStrategy.mqh |
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
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);
|
||||
rmData.trade.Sell(g_RM_LotSize, 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);
|
||||
rmData.trade.Buy(g_RM_LotSize, 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);
|
||||
rmData.trade.Sell(g_RM_LotSize, 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);
|
||||
rmData.trade.Buy(g_RM_LotSize, 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);
|
||||
rmData.trade.Buy(g_RM_LotSize, 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);
|
||||
rmData.trade.Sell(g_RM_LotSize, 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);
|
||||
rmData.trade.Buy(g_RM_LotSize, 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);
|
||||
rmData.trade.Sell(g_RM_LotSize, 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,493 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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)
|
||||
{
|
||||
// Check if market is open
|
||||
long tradeMode = SymbolInfoInteger(data.symbol, SYMBOL_TRADE_MODE);
|
||||
if(tradeMode != SYMBOL_TRADE_MODE_FULL)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough money
|
||||
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.SetTypeFilling(ORDER_FILLING_IOC);
|
||||
|
||||
// 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;
|
||||
|
||||
// Set trade parameters
|
||||
data.trade.SetDeviationInPoints(data.Slippage);
|
||||
data.trade.SetTypeFilling(ORDER_FILLING_IOC);
|
||||
data.trade.SetExpertMagicNumber(data.MagicNumber);
|
||||
|
||||
// Use dynamic lot size
|
||||
double tradeLotSize = lotSize > 0 ? lotSize : data.MaxLotSize;
|
||||
|
||||
// Place buy order using CTrade
|
||||
if(data.trade.Buy(tradeLotSize, 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;
|
||||
|
||||
// Set trade parameters
|
||||
data.trade.SetDeviationInPoints(data.Slippage);
|
||||
data.trade.SetTypeFilling(ORDER_FILLING_IOC);
|
||||
data.trade.SetExpertMagicNumber(data.MagicNumber);
|
||||
|
||||
// Use dynamic lot size
|
||||
double tradeLotSize = lotSize > 0 ? lotSize : data.MaxLotSize;
|
||||
|
||||
// Place sell order using CTrade
|
||||
if(data.trade.Sell(tradeLotSize, data.symbol, currentBid, sl, tp, "RSI Overbought Crossover Sell"))
|
||||
{
|
||||
data.isPositionOpen = true;
|
||||
data.positionOpenPrice = currentBid;
|
||||
data.positionOpenTime = TimeCurrent();
|
||||
data.lastPositionType = POSITION_TYPE_SELL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 29 KiB |
@@ -0,0 +1,683 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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"
|
||||
#include "PerformanceEvaluator.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 = 250.0;
|
||||
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;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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;
|
||||
};
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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 Dynamic Lot Sizes |
|
||||
//+------------------------------------------------------------------+
|
||||
// All strategies start with minimum lot size for safety (will be adjusted by performance evaluator)
|
||||
double g_DB_LotSize = 0.01; // DarvasBox uses fixed lot size
|
||||
double g_ES_LotSize = 0.01; // EMA Slope Distance - start with minimum
|
||||
double g_RC_LotSize = 0.01; // RSI CrossOver Reversal - start with minimum
|
||||
double g_RM_LotSize = 0.01; // RSI MidPoint Hijack - start with minimum
|
||||
double g_RS_APPL_LotSize = 5.0; // Stock - start with stock minimum (5.0)
|
||||
double g_RS_BTCUSD_LotSize = 0.01; // Crypto - start with forex minimum (0.01)
|
||||
double g_RS_MSFT_LotSize = 5.0; // Stock - start with stock minimum (5.0)
|
||||
double g_RS_NVDA_LotSize = 5.0; // Stock - start with stock minimum (5.0)
|
||||
double g_RS_TSLA_LotSize = 5.0; // Stock - start with stock minimum (5.0)
|
||||
double g_RS_XAUUSD_LotSize = 0.01; // Forex - start with forex minimum (0.01)
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
int initResult = INIT_SUCCEEDED;
|
||||
|
||||
// Initialize Performance Evaluator
|
||||
InitPerformanceTracking();
|
||||
|
||||
// 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, "'");
|
||||
else
|
||||
RegisterStrategy("DarvasBox", DB_MagicNumber, 0.01, DB_Symbol); // Fixed lot size
|
||||
}
|
||||
|
||||
if(EnableEMASlopeDistance)
|
||||
{
|
||||
if(!InitEMASlopeDistance(ES_Symbol))
|
||||
Print("Warning: EMASlopeDistance strategy failed to initialize for symbol '", ES_Symbol, "'");
|
||||
else
|
||||
{
|
||||
RegisterStrategy("EMASlopeDistance", ES_MagicNumber, ES_LotGröße, ES_Symbol);
|
||||
// Start with minimum lot size (will be adjusted by performance evaluator)
|
||||
double minLot = GetMinLotSizeForSymbol(ES_Symbol);
|
||||
g_ES_LotSize = minLot;
|
||||
}
|
||||
}
|
||||
|
||||
if(EnableRSICrossOverReversal)
|
||||
{
|
||||
if(!InitRSICrossOverReversal(RC_Symbol))
|
||||
Print("Warning: RSICrossOverReversal strategy failed to initialize for symbol '", RC_Symbol, "'");
|
||||
else
|
||||
{
|
||||
RegisterStrategy("RSICrossOverReversal", RC_MagicNumber, RC_lotSize, RC_Symbol);
|
||||
// Start with minimum lot size (will be adjusted by performance evaluator)
|
||||
double minLot = GetMinLotSizeForSymbol(RC_Symbol);
|
||||
g_RC_LotSize = minLot;
|
||||
}
|
||||
}
|
||||
|
||||
if(EnableRSIMidPointHijack)
|
||||
{
|
||||
if(!InitRSIMidPointHijack(RM_Symbol))
|
||||
Print("Warning: RSIMidPointHijack strategy failed to initialize for symbol '", RM_Symbol, "'");
|
||||
else
|
||||
{
|
||||
RegisterStrategy("RSIMidPointHijack", RM_InpMagicNumberRSIFollow, RM_InpLotSize, RM_Symbol);
|
||||
RegisterStrategy("RSIMidPointHijack_Reverse", RM_InpMagicNumberRSIReverse, RM_InpLotSize, RM_Symbol);
|
||||
RegisterStrategy("RSIMidPointHijack_EMACross", RM_InpMagicNumberEMACross, RM_InpLotSize, RM_Symbol);
|
||||
// Start with minimum lot size (will be adjusted by performance evaluator)
|
||||
double minLot = GetMinLotSizeForSymbol(RM_Symbol);
|
||||
g_RM_LotSize = minLot;
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
RegisterStrategy("RSIScalpingAPPL", RS_APPL_MagicNumber, RS_APPL_LotSize, RS_APPL_Symbol);
|
||||
// Start with minimum lot size (will be adjusted by performance evaluator)
|
||||
double minLot = GetMinLotSizeForSymbol(RS_APPL_Symbol);
|
||||
g_RS_APPL_LotSize = minLot;
|
||||
}
|
||||
|
||||
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);
|
||||
RegisterStrategy("RSIScalpingBTCUSD", RS_BTCUSD_MagicNumber, RS_BTCUSD_LotSize, RS_BTCUSD_Symbol);
|
||||
// Start with minimum lot size (will be adjusted by performance evaluator)
|
||||
double minLot = GetMinLotSizeForSymbol(RS_BTCUSD_Symbol);
|
||||
g_RS_BTCUSD_LotSize = minLot;
|
||||
}
|
||||
|
||||
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);
|
||||
RegisterStrategy("RSIScalpingMSFT", RS_MSFT_MagicNumber, RS_MSFT_LotSize, RS_MSFT_Symbol);
|
||||
// Start with minimum lot size (will be adjusted by performance evaluator)
|
||||
double minLot = GetMinLotSizeForSymbol(RS_MSFT_Symbol);
|
||||
g_RS_MSFT_LotSize = minLot;
|
||||
}
|
||||
|
||||
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);
|
||||
RegisterStrategy("RSIScalpingNVDA", RS_NVDA_MagicNumber, RS_NVDA_LotSize, RS_NVDA_Symbol);
|
||||
// Start with minimum lot size (will be adjusted by performance evaluator)
|
||||
double minLot = GetMinLotSizeForSymbol(RS_NVDA_Symbol);
|
||||
g_RS_NVDA_LotSize = minLot;
|
||||
}
|
||||
|
||||
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);
|
||||
RegisterStrategy("RSIScalpingTSLA", RS_TSLA_MagicNumber, RS_TSLA_LotSize, RS_TSLA_Symbol);
|
||||
// Start with minimum lot size (will be adjusted by performance evaluator)
|
||||
double minLot = GetMinLotSizeForSymbol(RS_TSLA_Symbol);
|
||||
g_RS_TSLA_LotSize = minLot;
|
||||
}
|
||||
|
||||
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);
|
||||
RegisterStrategy("RSIScalpingXAUUSD", RS_XAUUSD_MagicNumber, RS_XAUUSD_LotSize, RS_XAUUSD_Symbol);
|
||||
// Start with minimum lot size (will be adjusted by performance evaluator)
|
||||
double minLot = GetMinLotSizeForSymbol(RS_XAUUSD_Symbol);
|
||||
g_RS_XAUUSD_LotSize = minLot;
|
||||
}
|
||||
|
||||
// Load adjusted lot sizes from performance evaluator
|
||||
if(PE_EnableAutoAdjustment)
|
||||
{
|
||||
double adjustedLot;
|
||||
adjustedLot = GetStrategyLotSize("EMASlopeDistance", ES_MagicNumber);
|
||||
if(adjustedLot > 0) g_ES_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSICrossOverReversal", RC_MagicNumber);
|
||||
if(adjustedLot > 0) g_RC_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIMidPointHijack", RM_InpMagicNumberRSIFollow);
|
||||
if(adjustedLot > 0) g_RM_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingAPPL", RS_APPL_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_APPL_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingBTCUSD", RS_BTCUSD_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_BTCUSD_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingMSFT", RS_MSFT_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_MSFT_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingNVDA", RS_NVDA_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_NVDA_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingTSLA", RS_TSLA_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_TSLA_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingXAUUSD", RS_XAUUSD_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_XAUUSD_LotSize = adjustedLot;
|
||||
}
|
||||
|
||||
Print("United EA initialized. Active strategies: ",
|
||||
(EnableDarvasBox ? "DarvasBox " : ""),
|
||||
(EnableEMASlopeDistance ? "EMASlope " : ""),
|
||||
(EnableRSICrossOverReversal ? "RSICrossOver " : ""),
|
||||
(EnableRSIMidPointHijack ? "RSIMidPoint " : ""),
|
||||
(EnableRSIScalpingAPPL ? "RSIScalpingAPPL " : ""),
|
||||
(EnableRSIScalpingBTCUSD ? "RSIScalpingBTCUSD " : ""),
|
||||
(EnableRSIScalpingMSFT ? "RSIScalpingMSFT " : ""),
|
||||
(EnableRSIScalpingNVDA ? "RSIScalpingNVDA " : ""),
|
||||
(EnableRSIScalpingTSLA ? "RSIScalpingTSLA " : ""),
|
||||
(EnableRSIScalpingXAUUSD ? "RSIScalpingXAUUSD " : ""));
|
||||
|
||||
if(PE_EnableLogging)
|
||||
Print(GetPerformanceSummary());
|
||||
|
||||
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()
|
||||
{
|
||||
// Process performance evaluation (checks for quarter end and adjusts lot sizes)
|
||||
ProcessPerformanceEvaluation();
|
||||
|
||||
// Update lot sizes from performance evaluator if auto-adjustment is enabled
|
||||
if(PE_EnableAutoAdjustment)
|
||||
{
|
||||
double adjustedLot;
|
||||
adjustedLot = GetStrategyLotSize("EMASlopeDistance", ES_MagicNumber);
|
||||
if(adjustedLot > 0) g_ES_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSICrossOverReversal", RC_MagicNumber);
|
||||
if(adjustedLot > 0) g_RC_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIMidPointHijack", RM_InpMagicNumberRSIFollow);
|
||||
if(adjustedLot > 0) g_RM_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingAPPL", RS_APPL_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_APPL_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingBTCUSD", RS_BTCUSD_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_BTCUSD_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingMSFT", RS_MSFT_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_MSFT_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingNVDA", RS_NVDA_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_NVDA_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingTSLA", RS_TSLA_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_TSLA_LotSize = adjustedLot;
|
||||
|
||||
adjustedLot = GetStrategyLotSize("RSIScalpingXAUUSD", RS_XAUUSD_MagicNumber);
|
||||
if(adjustedLot > 0) g_RS_XAUUSD_LotSize = adjustedLot;
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Include strategy implementations |
|
||||
//+------------------------------------------------------------------+
|
||||
#include "Strategies/DarvasBoxStrategy.mqh"
|
||||
#include "Strategies/EMASlopeDistanceStrategy.mqh"
|
||||
#include "Strategies/RSICrossOverReversalStrategy.mqh"
|
||||
#include "Strategies/RSIMidPointHijackStrategy.mqh"
|
||||
#include "Strategies/RSIScalpingStrategy.mqh"
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,27 @@
|
||||
; saved on 2026.04.22
|
||||
; genetic optimization set for DarvasBoxXAUUSD/main.mq5
|
||||
; load in MT5 Strategy Tester -> Inputs -> Load
|
||||
;
|
||||
; === Core Darvas Box Parameters ===
|
||||
BoxPeriod=165||80||5||280||Y
|
||||
BoxDeviation=25140||8000||500||50000||Y
|
||||
VolumeThreshold=938||200||25||2500||Y
|
||||
StopLoss=1665||600||50||4000||Y
|
||||
TakeProfit=3685||1200||75||8000||Y
|
||||
EnableLogging=false||false||0||true||N
|
||||
BoxColor=255||0||1||16777215||N
|
||||
BoxWidth=1||1||1||3||N
|
||||
;
|
||||
; === Trend Confirmation Parameters ===
|
||||
TrendTimeframe=16386||16385||1||16388||Y
|
||||
MA_Period=125||20||5||260||Y
|
||||
MA_Method=1||0||1||3||Y
|
||||
MA_Price=6||0||1||6||Y
|
||||
TrendThreshold=4.94||1.0||0.2||20.0||Y
|
||||
;
|
||||
; === Volume Analysis Parameters ===
|
||||
VolumeMA_Period=110||20||5||220||Y
|
||||
VolumeThresholdMultiplier=1.5||1.0||0.1||3.5||Y
|
||||
;
|
||||
; === Execution / ID ===
|
||||
MagicNumber=135790||135790||1||1357900||N
|
||||
@@ -3,25 +3,30 @@
|
||||
//| Copyright 2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property link "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"
|
||||
//--- Eingabeparameter (Input Parameters) - Optimized Profitable Parameters
|
||||
input int EMA_Periode = 46; // EMA Periode
|
||||
input double PreisSchwelle = 600.0; // Preisbewegung Schwelle in Pips
|
||||
input double SteigungSchwelle = 80.0; // EMA Steigung Schwelle in Pips
|
||||
input int ÜberwachungTimeout = 800; // Überwachungszeit in Sekunden
|
||||
input double TrailingStop = 260.0; // Gleitender Stop in Pips
|
||||
input double LotGröße = 0.03; // Handelsvolumen
|
||||
input int MagicNumber = 12351; // Magic Number für Trades
|
||||
input int EMA_Periode = 50; // EMA Periode
|
||||
input double PreisSchwelle = 700.0; // Preisbewegung Schwelle in Pips
|
||||
input double SteigungSchwelle = 25.0; // EMA Steigung Schwelle in Pips
|
||||
input int ÜberwachungTimeout = 340; // Überwachungszeit in Sekunden
|
||||
input double TrailingStop = 370.0; // Gleitender Stop in Pips
|
||||
input double LotGröße = 0.07; // Handelsvolumen
|
||||
input int MagicNumber = 135790; // Magic Number für Trades
|
||||
input bool UseSpreadAdjustment = true; // Spread-Anpassung verwenden
|
||||
input ENUM_TIMEFRAMES Timeframe = PERIOD_H1; // Zeitraum für Analyse
|
||||
input bool UseBarData = true; // Bar-Daten statt Tick-Daten verwenden
|
||||
input int MaxTradesPerCrossover = 9; // Maximale Trades pro Crossover-Ereignis
|
||||
input int ProfitCheckBars = 12; // Bars bis zur Profit-Prüfung
|
||||
input int MaxTradesPerCrossover = 10; // Maximale Trades pro Crossover-Ereignis
|
||||
input int ProfitCheckBars = 15; // Bars bis zur Profit-Prüfung
|
||||
input bool CloseUnprofitableTrades = true; // Unprofitable Trades nach X Bars schließen
|
||||
input bool UseWeeklyADXFilter = true; // W1 ADX Trendfilter aktivieren
|
||||
input int WeeklyADXPeriod = 15; // ADX-Periode auf W1
|
||||
input double WeeklyADXMin = 40.0; // Minimaler ADX fuer Trendfreigabe
|
||||
input int WeeklyADXBarShift = 2; // 1=letzte geschlossene W1-Kerze
|
||||
input bool WeeklyADXUseDirection = true; // +DI/-DI Richtung mitpruefen
|
||||
|
||||
//--- Globale Variablen (Global Variables)
|
||||
int ema_handle; // EMA Indicator Handle
|
||||
@@ -36,6 +41,64 @@ int trades_in_current_crossover = 0; // Anzahl Trades im aktuellen Crossover
|
||||
bool crossover_detected = false; // Crossover erkannt
|
||||
datetime trade_open_time = 0; // Zeitpunkt des Trade-Öffnens
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Weekly ADX trend filter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IsWeeklyADXTrendFavorable(ENUM_ORDER_TYPE order_type)
|
||||
{
|
||||
if(!UseWeeklyADXFilter)
|
||||
return true;
|
||||
|
||||
int adxShift = WeeklyADXBarShift;
|
||||
if(adxShift < 0)
|
||||
adxShift = 0;
|
||||
|
||||
int adx_handle = iADX(_Symbol, PERIOD_W1, WeeklyADXPeriod);
|
||||
if(adx_handle == INVALID_HANDLE)
|
||||
{
|
||||
Print("TRACE: Weekly ADX Handle ungültig - Filter blockiert Entry");
|
||||
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)
|
||||
{
|
||||
Print("TRACE: Weekly ADX Daten nicht verfügbar - Filter blockiert Entry");
|
||||
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 >= WeeklyADXMin);
|
||||
bool direction_ok = true;
|
||||
if(WeeklyADXUseDirection)
|
||||
{
|
||||
if(order_type == ORDER_TYPE_BUY)
|
||||
direction_ok = (plus_di > minus_di);
|
||||
else
|
||||
direction_ok = (minus_di > plus_di);
|
||||
}
|
||||
|
||||
Print("TRACE: Weekly ADX Filter | ADX=", DoubleToString(adx_value, 2),
|
||||
" +DI=", DoubleToString(plus_di, 2),
|
||||
" -DI=", DoubleToString(minus_di, 2),
|
||||
" strength_ok=", strength_ok,
|
||||
" direction_ok=", direction_ok);
|
||||
|
||||
return (strength_ok && direction_ok);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -292,6 +355,11 @@ void PrüfeTrigger()
|
||||
|
||||
if(bullish_signal && !PositionExistsByMagic(_Symbol, MagicNumber))
|
||||
{
|
||||
if(!IsWeeklyADXTrendFavorable(ORDER_TYPE_BUY))
|
||||
{
|
||||
Print("TRACE: Weekly ADX blockiert BUY-Entry");
|
||||
return;
|
||||
}
|
||||
Print("TRACE: Versuche KAUF-Trade zu platzieren (Trade #", trades_in_current_crossover + 1, ")");
|
||||
if(PlatziereTrade(ORDER_TYPE_BUY))
|
||||
{
|
||||
@@ -300,6 +368,11 @@ void PrüfeTrigger()
|
||||
}
|
||||
else if(bearish_signal && !PositionExistsByMagic(_Symbol, MagicNumber))
|
||||
{
|
||||
if(!IsWeeklyADXTrendFavorable(ORDER_TYPE_SELL))
|
||||
{
|
||||
Print("TRACE: Weekly ADX blockiert SELL-Entry");
|
||||
return;
|
||||
}
|
||||
Print("TRACE: Versuche VERKAUF-Trade zu platzieren (Trade #", trades_in_current_crossover + 1, ")");
|
||||
if(PlatziereTrade(ORDER_TYPE_SELL))
|
||||
{
|
||||
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
@@ -0,0 +1,362 @@
|
||||
#property strict
|
||||
#property version "1.00"
|
||||
#property description "BTCUSD mean reversion: RSI extreme + EMA distance + low ADX; escape when ADX trends up."
|
||||
|
||||
#include <Trade/Trade.mqh>
|
||||
|
||||
input group "=== Market ==="
|
||||
input string InpSymbol = "BTCUSD";
|
||||
input ENUM_TIMEFRAMES InpTimeframe = PERIOD_M20;
|
||||
input double InpLots = 0.01;
|
||||
input int InpSlippagePoints = 30;
|
||||
input int InpMagic = 930201;
|
||||
input int InpMaxPositions = 5;
|
||||
input bool InpDebugLogs = false;
|
||||
|
||||
input group "=== EMA distance (mean reversion stretch) ==="
|
||||
input int InpEmaPeriod = 250;
|
||||
input double InpMinEmaDistancePts = 3650.0; // |close-EMA| in points; raise/lower for BTC broker digits
|
||||
|
||||
input group "=== RSI ==="
|
||||
input int InpRsiPeriod = 28;
|
||||
input double InpRsiOversold = 40.0;
|
||||
input double InpRsiOverbought = 83.0;
|
||||
input bool InpUseRsiCross = false; // true: require cross into zone on last bar
|
||||
|
||||
input group "=== ADX (trend filter + escape) ==="
|
||||
input int InpAdxPeriod = 27;
|
||||
input double InpAdxMaxForEntry = 17.0; // no new trades if ADX >= this (ranging bias)
|
||||
input double InpAdxEscape = 34.0; // close all if ADX >= this (trend building)
|
||||
|
||||
input group "=== Price action (optional) ==="
|
||||
input bool InpRequireReversalBar = false; // buy: bearish bar at signal; sell: bullish bar
|
||||
|
||||
input group "=== Risk ==="
|
||||
input bool InpUseHardSLTP = false;
|
||||
input double InpSLPoints = 1300;
|
||||
input double InpTPPoints = 13400;
|
||||
|
||||
CTrade trade;
|
||||
datetime g_lastBarTime = 0;
|
||||
|
||||
int g_hRsi = INVALID_HANDLE;
|
||||
int g_hEma = INVALID_HANDLE;
|
||||
int g_hAdx = INVALID_HANDLE;
|
||||
|
||||
void DebugLog(const string msg)
|
||||
{
|
||||
if(InpDebugLogs)
|
||||
Print("[MeanRevEMA_RSI_ADX] ", msg);
|
||||
}
|
||||
|
||||
bool IsNewBar(const string symbol, const ENUM_TIMEFRAMES tf)
|
||||
{
|
||||
datetime t = iTime(symbol, tf, 0);
|
||||
if(t <= 0 || t == g_lastBarTime)
|
||||
return false;
|
||||
g_lastBarTime = t;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CopyOne(const int handle, const int buffer, const int shift, double &out)
|
||||
{
|
||||
if(handle == INVALID_HANDLE)
|
||||
return false;
|
||||
double v[1];
|
||||
if(CopyBuffer(handle, buffer, shift, 1, v) != 1)
|
||||
return false;
|
||||
out = v[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
double GetAdx(const int shift)
|
||||
{
|
||||
double v = 0.0;
|
||||
if(!CopyOne(g_hAdx, 0, shift, v))
|
||||
return 0.0;
|
||||
return v;
|
||||
}
|
||||
|
||||
double GetRsi(const int shift)
|
||||
{
|
||||
double v = 0.0;
|
||||
if(!CopyOne(g_hRsi, 0, shift, v))
|
||||
return 0.0;
|
||||
return v;
|
||||
}
|
||||
|
||||
double GetEma(const int shift)
|
||||
{
|
||||
double v = 0.0;
|
||||
if(!CopyOne(g_hEma, 0, shift, v))
|
||||
return 0.0;
|
||||
return v;
|
||||
}
|
||||
|
||||
int CountPositionsByMagic(const string symbol, const int magic)
|
||||
{
|
||||
int count = 0;
|
||||
for(int i = PositionsTotal() - 1; i >= 0; --i)
|
||||
{
|
||||
ulong t = PositionGetTicket(i);
|
||||
if(t == 0)
|
||||
continue;
|
||||
if(PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||
(int)PositionGetInteger(POSITION_MAGIC) == magic)
|
||||
count++;
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
void CloseAllByMagic(const string symbol, const int magic)
|
||||
{
|
||||
for(int i = PositionsTotal() - 1; i >= 0; --i)
|
||||
{
|
||||
ulong t = PositionGetTicket(i);
|
||||
if(t == 0)
|
||||
continue;
|
||||
if(PositionGetString(POSITION_SYMBOL) == symbol &&
|
||||
(int)PositionGetInteger(POSITION_MAGIC) == magic)
|
||||
trade.PositionClose(t);
|
||||
}
|
||||
}
|
||||
|
||||
void ComputeSLTP(const bool isBuy, const double entry, double &sl, double &tp)
|
||||
{
|
||||
if(!InpUseHardSLTP)
|
||||
{
|
||||
sl = 0.0;
|
||||
tp = 0.0;
|
||||
return;
|
||||
}
|
||||
if(isBuy)
|
||||
{
|
||||
sl = entry - InpSLPoints * _Point;
|
||||
tp = entry + InpTPPoints * _Point;
|
||||
}
|
||||
else
|
||||
{
|
||||
sl = entry + InpSLPoints * _Point;
|
||||
tp = entry - InpTPPoints * _Point;
|
||||
}
|
||||
}
|
||||
|
||||
bool RsiOversoldSignal()
|
||||
{
|
||||
double r1 = 0.0, r2 = 0.0;
|
||||
if(!CopyOne(g_hRsi, 0, 1, r1) || !CopyOne(g_hRsi, 0, 2, r2))
|
||||
return false;
|
||||
if(InpUseRsiCross)
|
||||
return (r2 > InpRsiOversold && r1 <= InpRsiOversold);
|
||||
return (r1 <= InpRsiOversold);
|
||||
}
|
||||
|
||||
bool RsiOverboughtSignal()
|
||||
{
|
||||
double r1 = 0.0, r2 = 0.0;
|
||||
if(!CopyOne(g_hRsi, 0, 1, r1) || !CopyOne(g_hRsi, 0, 2, r2))
|
||||
return false;
|
||||
if(InpUseRsiCross)
|
||||
return (r2 < InpRsiOverbought && r1 >= InpRsiOverbought);
|
||||
return (r1 >= InpRsiOverbought);
|
||||
}
|
||||
|
||||
bool BarBearish(const int shift)
|
||||
{
|
||||
double o = iOpen(InpSymbol, InpTimeframe, shift);
|
||||
double c = iClose(InpSymbol, InpTimeframe, shift);
|
||||
return (c < o);
|
||||
}
|
||||
|
||||
bool BarBullish(const int shift)
|
||||
{
|
||||
double o = iOpen(InpSymbol, InpTimeframe, shift);
|
||||
double c = iClose(InpSymbol, InpTimeframe, shift);
|
||||
return (c > o);
|
||||
}
|
||||
|
||||
bool BuySetup()
|
||||
{
|
||||
if(!RsiOversoldSignal())
|
||||
return false;
|
||||
|
||||
double ema = GetEma(1);
|
||||
double cls = iClose(InpSymbol, InpTimeframe, 1);
|
||||
if(ema <= 0.0 || cls <= 0.0)
|
||||
return false;
|
||||
|
||||
double distPts = (ema - cls) / _Point;
|
||||
if(distPts < InpMinEmaDistancePts)
|
||||
return false;
|
||||
|
||||
if(InpRequireReversalBar && !BarBearish(1))
|
||||
return false;
|
||||
|
||||
double adx = GetAdx(1);
|
||||
if(adx <= 0.0)
|
||||
return false;
|
||||
if(adx >= InpAdxMaxForEntry)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SellSetup()
|
||||
{
|
||||
if(!RsiOverboughtSignal())
|
||||
return false;
|
||||
|
||||
double ema = GetEma(1);
|
||||
double cls = iClose(InpSymbol, InpTimeframe, 1);
|
||||
if(ema <= 0.0 || cls <= 0.0)
|
||||
return false;
|
||||
|
||||
double distPts = (cls - ema) / _Point;
|
||||
if(distPts < InpMinEmaDistancePts)
|
||||
return false;
|
||||
|
||||
if(InpRequireReversalBar && !BarBullish(1))
|
||||
return false;
|
||||
|
||||
double adx = GetAdx(1);
|
||||
if(adx <= 0.0)
|
||||
return false;
|
||||
if(adx >= InpAdxMaxForEntry)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int OnInit()
|
||||
{
|
||||
if(StringLen(InpSymbol) == 0)
|
||||
{
|
||||
Print("[MeanRevEMA_RSI_ADX] OnInit: InpSymbol is empty.");
|
||||
return INIT_PARAMETERS_INCORRECT;
|
||||
}
|
||||
if(InpRsiPeriod < 2 || InpEmaPeriod < 1 || InpAdxPeriod < 1)
|
||||
{
|
||||
Print("[MeanRevEMA_RSI_ADX] OnInit: invalid periods rsi=", InpRsiPeriod,
|
||||
" ema=", InpEmaPeriod, " adx=", InpAdxPeriod);
|
||||
return INIT_PARAMETERS_INCORRECT;
|
||||
}
|
||||
if(!SymbolSelect(InpSymbol, true))
|
||||
{
|
||||
Print("[MeanRevEMA_RSI_ADX] OnInit: SymbolSelect failed (symbol missing on this agent?): ", InpSymbol,
|
||||
" err=", GetLastError(),
|
||||
" — use Local agents only for broker-specific names, or set InpSymbol to a symbol the agent has.");
|
||||
return INIT_PARAMETERS_INCORRECT;
|
||||
}
|
||||
|
||||
g_hRsi = iRSI(InpSymbol, InpTimeframe, InpRsiPeriod, PRICE_CLOSE);
|
||||
if(g_hRsi == INVALID_HANDLE)
|
||||
{
|
||||
Print("[MeanRevEMA_RSI_ADX] OnInit: iRSI failed sym=", InpSymbol, " tf=", (int)InpTimeframe,
|
||||
" period=", InpRsiPeriod, " err=", GetLastError());
|
||||
return INIT_FAILED;
|
||||
}
|
||||
g_hEma = iMA(InpSymbol, InpTimeframe, InpEmaPeriod, 0, MODE_EMA, PRICE_CLOSE);
|
||||
if(g_hEma == INVALID_HANDLE)
|
||||
{
|
||||
Print("[MeanRevEMA_RSI_ADX] OnInit: iMA failed sym=", InpSymbol, " tf=", (int)InpTimeframe,
|
||||
" period=", InpEmaPeriod, " err=", GetLastError());
|
||||
IndicatorRelease(g_hRsi);
|
||||
g_hRsi = INVALID_HANDLE;
|
||||
return INIT_FAILED;
|
||||
}
|
||||
g_hAdx = iADX(InpSymbol, InpTimeframe, InpAdxPeriod);
|
||||
if(g_hAdx == INVALID_HANDLE)
|
||||
{
|
||||
Print("[MeanRevEMA_RSI_ADX] OnInit: iADX failed sym=", InpSymbol, " tf=", (int)InpTimeframe,
|
||||
" period=", InpAdxPeriod, " err=", GetLastError());
|
||||
IndicatorRelease(g_hRsi);
|
||||
IndicatorRelease(g_hEma);
|
||||
g_hRsi = g_hEma = INVALID_HANDLE;
|
||||
return INIT_FAILED;
|
||||
}
|
||||
|
||||
trade.SetExpertMagicNumber(InpMagic);
|
||||
trade.SetDeviationInPoints(InpSlippagePoints);
|
||||
return INIT_SUCCEEDED;
|
||||
}
|
||||
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
if(g_hRsi != INVALID_HANDLE) IndicatorRelease(g_hRsi);
|
||||
if(g_hEma != INVALID_HANDLE) IndicatorRelease(g_hEma);
|
||||
if(g_hAdx != INVALID_HANDLE) IndicatorRelease(g_hAdx);
|
||||
g_hRsi = g_hEma = g_hAdx = INVALID_HANDLE;
|
||||
}
|
||||
|
||||
void OnTick()
|
||||
{
|
||||
if(_Symbol != InpSymbol)
|
||||
{
|
||||
static datetime lastMismatchLog = 0;
|
||||
datetime nowBar = iTime(_Symbol, PERIOD_M1, 0);
|
||||
if(nowBar != lastMismatchLog)
|
||||
{
|
||||
lastMismatchLog = nowBar;
|
||||
DebugLog(StringFormat("Skipped: chart symbol=%s but InpSymbol=%s.", _Symbol, InpSymbol));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const int posCount = CountPositionsByMagic(InpSymbol, InpMagic);
|
||||
const double adxLive = GetAdx(0);
|
||||
|
||||
if(posCount > 0 && adxLive > 0.0 && adxLive >= InpAdxEscape)
|
||||
{
|
||||
DebugLog(StringFormat("ADX escape: adx0=%.2f >= %.2f -> closing %d position(s).", adxLive, InpAdxEscape, posCount));
|
||||
CloseAllByMagic(InpSymbol, InpMagic);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!IsNewBar(InpSymbol, InpTimeframe))
|
||||
return;
|
||||
|
||||
const double rsi1 = GetRsi(1);
|
||||
const double adx1 = GetAdx(1);
|
||||
const double ema1 = GetEma(1);
|
||||
const double c1 = iClose(InpSymbol, InpTimeframe, 1);
|
||||
DebugLog(StringFormat("Bar=%s rsi1=%.2f adx1=%.2f ema1=%.5f close1=%.5f positions=%d",
|
||||
TimeToString(iTime(InpSymbol, InpTimeframe, 1), TIME_DATE | TIME_MINUTES),
|
||||
rsi1, adx1, ema1, c1, posCount));
|
||||
|
||||
if(posCount >= InpMaxPositions)
|
||||
{
|
||||
DebugLog(StringFormat("Skipped: max positions (%d).", InpMaxPositions));
|
||||
return;
|
||||
}
|
||||
|
||||
MqlTick tick;
|
||||
if(!SymbolInfoTick(InpSymbol, tick))
|
||||
{
|
||||
DebugLog("Skipped: SymbolInfoTick failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
double sl = 0.0, tp = 0.0;
|
||||
|
||||
if(BuySetup())
|
||||
{
|
||||
ComputeSLTP(true, tick.ask, sl, tp);
|
||||
if(trade.Buy(InpLots, InpSymbol, tick.ask, sl, tp, "MeanRev_RSI_OS_EMA"))
|
||||
DebugLog(StringFormat("BUY lots=%.2f ask=%.2f sl=%.2f tp=%.2f", InpLots, tick.ask, sl, tp));
|
||||
else
|
||||
DebugLog(StringFormat("BUY failed retcode=%d", trade.ResultRetcode()));
|
||||
return;
|
||||
}
|
||||
|
||||
if(SellSetup())
|
||||
{
|
||||
ComputeSLTP(false, tick.bid, sl, tp);
|
||||
if(trade.Sell(InpLots, InpSymbol, tick.bid, sl, tp, "MeanRev_RSI_OB_EMA"))
|
||||
DebugLog(StringFormat("SELL lots=%.2f bid=%.2f sl=%.2f tp=%.2f", InpLots, tick.bid, sl, tp));
|
||||
else
|
||||
DebugLog(StringFormat("SELL failed retcode=%d", trade.ResultRetcode()));
|
||||
return;
|
||||
}
|
||||
|
||||
DebugLog("No entry: RSI/EMA distance/ADX/bar filters not aligned.");
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
; Synced with daughter.set (ranges + current defaults). Strategy Tester → Inputs → Load.
|
||||
; Format: value||start||step||stop||Y|N
|
||||
;
|
||||
; === Market ===
|
||||
InpSymbol=BTCUSD
|
||||
InpTimeframe=20||15||0||16385||Y
|
||||
InpLots=0.01||0.01||0.001000||0.050000||N
|
||||
InpSlippagePoints=30||30||1||300||N
|
||||
InpMagic=930201||930201||1||930201||N
|
||||
InpMaxPositions=5||1||1||8||Y
|
||||
InpDebugLogs=false||false||0||true||N
|
||||
; === EMA distance (mean reversion stretch) ===
|
||||
InpEmaPeriod=250||50||10||400||Y
|
||||
InpMinEmaDistancePts=3650||200.0||50.0||5000.0||Y
|
||||
; === RSI ===
|
||||
InpRsiPeriod=28||7||1||28||Y
|
||||
InpRsiOversold=40||18.0||1.0||42.0||Y
|
||||
InpRsiOverbought=83||58.0||1.0||88.0||Y
|
||||
InpUseRsiCross=false||false||0||true||Y
|
||||
; === ADX (trend filter + escape) ===
|
||||
InpAdxPeriod=27||7||1||28||Y
|
||||
InpAdxMaxForEntry=17||15.0||1.0||40.0||Y
|
||||
InpAdxEscape=34||22.0||1.0||55.0||Y
|
||||
; === Price action (optional) ===
|
||||
InpRequireReversalBar=false||false||0||true||Y
|
||||
; === Risk ===
|
||||
InpUseHardSLTP=false||false||0||true||Y
|
||||
InpSLPoints=1300||800.0||100.0||8000.0||Y
|
||||
InpTPPoints=13400||1000.0||200.0||15000.0||Y
|
||||
@@ -0,0 +1,30 @@
|
||||
; saved on 2026.04.23 22:29:36
|
||||
; this file contains input parameters for testing/optimizing MeanReversion expert advisor
|
||||
; to use it in the strategy tester, click Load in the context menu of the Inputs tab
|
||||
;
|
||||
; === Market ===
|
||||
InpSymbol=BTCUSD
|
||||
InpTimeframe=20||15||0||16385||Y
|
||||
InpLots=0.01||0.01||0.001000||0.050000||N
|
||||
InpSlippagePoints=30||30||1||300||N
|
||||
InpMagic=930201||930201||1||930201||N
|
||||
InpMaxPositions=5||1||1||8||Y
|
||||
InpDebugLogs=false||false||0||true||N
|
||||
; === EMA distance (mean reversion stretch) ===
|
||||
InpEmaPeriod=250||50||10||400||Y
|
||||
InpMinEmaDistancePts=3650||200.0||50.0||5000.0||Y
|
||||
; === RSI ===
|
||||
InpRsiPeriod=28||7||1||28||Y
|
||||
InpRsiOversold=40||18.0||1.0||42.0||Y
|
||||
InpRsiOverbought=83||58.0||1.0||88.0||Y
|
||||
InpUseRsiCross=false||false||0||true||Y
|
||||
; === ADX (trend filter + escape) ===
|
||||
InpAdxPeriod=27||7||1||28||Y
|
||||
InpAdxMaxForEntry=17||15.0||1.0||40.0||Y
|
||||
InpAdxEscape=34||22.0||1.0||55.0||Y
|
||||
; === Price action (optional) ===
|
||||
InpRequireReversalBar=false||false||0||true||Y
|
||||
; === Risk ===
|
||||
InpUseHardSLTP=false||false||0||true||Y
|
||||
InpSLPoints=1300||800.0||100.0||8000.0||Y
|
||||
InpTPPoints=13400||1000.0||200.0||15000.0||Y
|
||||
@@ -0,0 +1,347 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RSIConsolidation.mq5 |
|
||||
//| Mean-reversion RSI for ranging markets; trend filters block runs |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025"
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
|
||||
//--- Symbol (empty = chart symbol)
|
||||
input group "=== Symbol & session ==="
|
||||
input string InpSymbol = "";
|
||||
|
||||
input group "=== Timeframe & bar logic ==="
|
||||
input ENUM_TIMEFRAMES SignalTF = PERIOD_M15;
|
||||
input bool EntryOnNewBarOnly = true;
|
||||
|
||||
//--- Core: no trend / consolidation regime
|
||||
input group "=== Regime: consolidation (anti-trend) ==="
|
||||
input int ADX_Period = 23;
|
||||
input double ADX_Max = 29.0;
|
||||
input bool UseATRRatioFilter = true;
|
||||
input int ATR_Period = 8;
|
||||
input int ATR_SMA_Period = 35;
|
||||
input double ATR_Ratio_Max = 1.36;
|
||||
input bool UseFlatEMAFilter = true;
|
||||
input int EMA_Fast = 13;
|
||||
input int EMA_Slow = 17;
|
||||
input double EMA_Separation_MaxPct = 0.26;
|
||||
|
||||
//--- RSI entries (fade extremes toward mean)
|
||||
input group "=== RSI entries ==="
|
||||
input int RSI_Period = 8;
|
||||
input ENUM_APPLIED_PRICE RSI_Price = PRICE_OPEN;
|
||||
input double RSI_Oversold = 22.0;
|
||||
input double RSI_Overbought = 63.0;
|
||||
|
||||
//--- Exits: mean target + hard ATR bracket
|
||||
input group "=== Exits ==="
|
||||
input bool UseRSI_MeanExit = true;
|
||||
input double RSI_Exit_Long = 48.0;
|
||||
input double RSI_Exit_Short = 52.0;
|
||||
input double SL_ATR_Mult = 2.15;
|
||||
input double TP_ATR_Mult = 2.40;
|
||||
input int MaxBarsInTrade = 54;
|
||||
|
||||
input group "=== Risk & execution ==="
|
||||
input double Lots = 0.10;
|
||||
input ulong MagicNumber = 20250420;
|
||||
input int Slippage = 10;
|
||||
input int MaxSpreadPoints = 28;
|
||||
|
||||
CTrade trade;
|
||||
string g_sym;
|
||||
|
||||
int h_rsi = INVALID_HANDLE;
|
||||
int h_adx = INVALID_HANDLE;
|
||||
int h_atr = INVALID_HANDLE;
|
||||
int h_ema_fast = INVALID_HANDLE;
|
||||
int h_ema_slow = INVALID_HANDLE;
|
||||
|
||||
datetime g_last_bar = 0;
|
||||
|
||||
bool PositionExistsByMagicSym(string sym, ulong magic)
|
||||
{
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||
{
|
||||
ulong t = PositionGetTicket(i);
|
||||
if(t == 0) continue;
|
||||
if(PositionGetString(POSITION_SYMBOL) == sym && PositionGetInteger(POSITION_MAGIC) == (long)magic)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ulong GetPositionTicketByMagicSym(string sym, ulong magic)
|
||||
{
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--)
|
||||
{
|
||||
ulong t = PositionGetTicket(i);
|
||||
if(t == 0) continue;
|
||||
if(PositionGetString(POSITION_SYMBOL) == sym && PositionGetInteger(POSITION_MAGIC) == (long)magic)
|
||||
return t;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool SelectPositionTicketSymMagic(ulong ticket, string sym, ulong magic)
|
||||
{
|
||||
if(!PositionSelectByTicket(ticket)) return false;
|
||||
return PositionGetString(POSITION_SYMBOL) == sym && PositionGetInteger(POSITION_MAGIC) == (long)magic;
|
||||
}
|
||||
|
||||
double NormalizeVolume(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 CurrentSpreadPoints(string sym)
|
||||
{
|
||||
long spread = 0;
|
||||
if(!SymbolInfoInteger(sym, SYMBOL_SPREAD, spread))
|
||||
return 999999;
|
||||
return (int)spread;
|
||||
}
|
||||
|
||||
double MinStopsDistancePrice(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 Copy1(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 RSI_Buffers(double &cur, double &prev, double &twoAgo)
|
||||
{
|
||||
double b[];
|
||||
ArraySetAsSeries(b, true);
|
||||
if(CopyBuffer(h_rsi, 0, 0, 3, b) < 3) return false;
|
||||
cur = b[0];
|
||||
prev = b[1];
|
||||
twoAgo = b[2];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Regime_IsConsolidation()
|
||||
{
|
||||
double adx = 0;
|
||||
if(!Copy1(h_adx, adx))
|
||||
return false;
|
||||
if(adx >= ADX_Max)
|
||||
return false;
|
||||
|
||||
if(UseATRRatioFilter)
|
||||
{
|
||||
double atrArr[], atrSma[];
|
||||
ArraySetAsSeries(atrArr, true);
|
||||
if(CopyBuffer(h_atr, 0, 0, ATR_SMA_Period + 1, atrArr) < ATR_SMA_Period + 1)
|
||||
return false;
|
||||
double sum = 0;
|
||||
for(int i = 1; i <= ATR_SMA_Period; i++)
|
||||
sum += atrArr[i];
|
||||
double smaAtr = sum / (double)ATR_SMA_Period;
|
||||
if(smaAtr <= 0.0)
|
||||
return false;
|
||||
double ratio = atrArr[0] / smaAtr;
|
||||
if(ratio > ATR_Ratio_Max)
|
||||
return false;
|
||||
}
|
||||
|
||||
if(UseFlatEMAFilter)
|
||||
{
|
||||
double ef[], es[];
|
||||
ArraySetAsSeries(ef, true);
|
||||
ArraySetAsSeries(es, true);
|
||||
if(CopyBuffer(h_ema_fast, 0, 0, 1, ef) < 1) return false;
|
||||
if(CopyBuffer(h_ema_slow, 0, 0, 1, es) < 1) return false;
|
||||
double c = SymbolInfoDouble(g_sym, SYMBOL_BID);
|
||||
if(c <= 0) return false;
|
||||
double sep = MathAbs(ef[0] - es[0]) / c * 100.0;
|
||||
if(sep > EMA_Separation_MaxPct)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Entry_BuyCross(double twoAgo, double prev)
|
||||
{
|
||||
return (twoAgo <= RSI_Oversold && prev > RSI_Oversold);
|
||||
}
|
||||
|
||||
bool Entry_SellCross(double twoAgo, double prev)
|
||||
{
|
||||
return (twoAgo >= RSI_Overbought && prev < RSI_Overbought);
|
||||
}
|
||||
|
||||
void TryCloseByRSI(ENUM_POSITION_TYPE typ, double rsi)
|
||||
{
|
||||
ulong tk = GetPositionTicketByMagicSym(g_sym, MagicNumber);
|
||||
if(tk == 0 || !SelectPositionTicketSymMagic(tk, g_sym, MagicNumber))
|
||||
return;
|
||||
if(!UseRSI_MeanExit)
|
||||
return;
|
||||
if(typ == POSITION_TYPE_BUY && rsi >= RSI_Exit_Long)
|
||||
trade.PositionClose(tk);
|
||||
else if(typ == POSITION_TYPE_SELL && rsi <= RSI_Exit_Short)
|
||||
trade.PositionClose(tk);
|
||||
}
|
||||
|
||||
void ManageOpenPosition(double rsi)
|
||||
{
|
||||
ulong tk = GetPositionTicketByMagicSym(g_sym, MagicNumber);
|
||||
if(tk == 0 || !SelectPositionTicketSymMagic(tk, g_sym, MagicNumber))
|
||||
return;
|
||||
ENUM_POSITION_TYPE typ = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
datetime openT = (datetime)PositionGetInteger(POSITION_TIME);
|
||||
int barsAgo = iBarShift(g_sym, SignalTF, openT, false);
|
||||
if(barsAgo >= 0 && barsAgo >= MaxBarsInTrade)
|
||||
{
|
||||
trade.PositionClose(tk);
|
||||
return;
|
||||
}
|
||||
TryCloseByRSI(typ, rsi);
|
||||
}
|
||||
|
||||
int OnInit()
|
||||
{
|
||||
g_sym = InpSymbol;
|
||||
StringTrimLeft(g_sym);
|
||||
StringTrimRight(g_sym);
|
||||
if(StringLen(g_sym) == 0)
|
||||
g_sym = _Symbol;
|
||||
|
||||
if(!SymbolSelect(g_sym, true))
|
||||
{
|
||||
Print("RSIConsolidation: SymbolSelect failed: ", g_sym);
|
||||
return INIT_FAILED;
|
||||
}
|
||||
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
trade.SetDeviationInPoints(Slippage);
|
||||
trade.SetTypeFilling(ORDER_FILLING_RETURN);
|
||||
|
||||
h_rsi = iRSI(g_sym, SignalTF, RSI_Period, RSI_Price);
|
||||
h_adx = iADX(g_sym, SignalTF, ADX_Period);
|
||||
h_atr = iATR(g_sym, SignalTF, ATR_Period);
|
||||
h_ema_fast = iMA(g_sym, SignalTF, EMA_Fast, 0, MODE_EMA, PRICE_CLOSE);
|
||||
h_ema_slow = iMA(g_sym, SignalTF, EMA_Slow, 0, MODE_EMA, PRICE_CLOSE);
|
||||
|
||||
if(h_rsi == INVALID_HANDLE || h_adx == INVALID_HANDLE || h_atr == INVALID_HANDLE
|
||||
|| h_ema_fast == INVALID_HANDLE || h_ema_slow == INVALID_HANDLE)
|
||||
{
|
||||
Print("RSIConsolidation: indicator init failed");
|
||||
return INIT_FAILED;
|
||||
}
|
||||
|
||||
Print("RSIConsolidation: symbol=", g_sym, " TF=", EnumToString(SignalTF));
|
||||
return INIT_SUCCEEDED;
|
||||
}
|
||||
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
if(h_rsi != INVALID_HANDLE) IndicatorRelease(h_rsi);
|
||||
if(h_adx != INVALID_HANDLE) IndicatorRelease(h_adx);
|
||||
if(h_atr != INVALID_HANDLE) IndicatorRelease(h_atr);
|
||||
if(h_ema_fast != INVALID_HANDLE) IndicatorRelease(h_ema_fast);
|
||||
if(h_ema_slow != INVALID_HANDLE) IndicatorRelease(h_ema_slow);
|
||||
}
|
||||
|
||||
bool EnoughHistory()
|
||||
{
|
||||
int need = MathMax(RSI_Period + 3, MathMax(ADX_Period + 2, ATR_SMA_Period + 3));
|
||||
if(Bars(g_sym, SignalTF) < need)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void OnTick()
|
||||
{
|
||||
if(!EnoughHistory())
|
||||
return;
|
||||
|
||||
if(MaxSpreadPoints > 0 && CurrentSpreadPoints(g_sym) > MaxSpreadPoints)
|
||||
return;
|
||||
|
||||
double rsi, rsiPrev, rsi2;
|
||||
if(!RSI_Buffers(rsi, rsiPrev, rsi2))
|
||||
return;
|
||||
|
||||
datetime barTime = iTime(g_sym, SignalTF, 0);
|
||||
bool isNew = (barTime != g_last_bar);
|
||||
|
||||
if(PositionExistsByMagicSym(g_sym, MagicNumber))
|
||||
{
|
||||
ManageOpenPosition(rsi);
|
||||
if(isNew)
|
||||
g_last_bar = barTime;
|
||||
return;
|
||||
}
|
||||
|
||||
if(EntryOnNewBarOnly && !isNew)
|
||||
return;
|
||||
|
||||
g_last_bar = barTime;
|
||||
|
||||
if(!Regime_IsConsolidation())
|
||||
return;
|
||||
|
||||
double atrArr[];
|
||||
ArraySetAsSeries(atrArr, true);
|
||||
if(CopyBuffer(h_atr, 0, 0, 1, atrArr) < 1)
|
||||
return;
|
||||
double atr = atrArr[0];
|
||||
int dig = (int)SymbolInfoInteger(g_sym, SYMBOL_DIGITS);
|
||||
|
||||
double slDist = atr * SL_ATR_Mult;
|
||||
double tpDist = atr * TP_ATR_Mult;
|
||||
double minD = MinStopsDistancePrice(g_sym);
|
||||
if(slDist < minD)
|
||||
slDist = minD;
|
||||
if(tpDist < minD)
|
||||
tpDist = minD;
|
||||
|
||||
double vol = NormalizeVolume(g_sym, Lots);
|
||||
|
||||
if(Entry_BuyCross(rsi2, rsiPrev))
|
||||
{
|
||||
double ask = SymbolInfoDouble(g_sym, SYMBOL_ASK);
|
||||
double sl = ask - slDist;
|
||||
double tp = ask + tpDist;
|
||||
sl = NormalizeDouble(sl, dig);
|
||||
tp = NormalizeDouble(tp, dig);
|
||||
trade.Buy(vol, g_sym, ask, sl, tp, "RSIConsolidation BUY");
|
||||
}
|
||||
else if(Entry_SellCross(rsi2, rsiPrev))
|
||||
{
|
||||
double bid = SymbolInfoDouble(g_sym, SYMBOL_BID);
|
||||
double sl = bid + slDist;
|
||||
double tp = bid - tpDist;
|
||||
sl = NormalizeDouble(sl, dig);
|
||||
tp = NormalizeDouble(tp, dig);
|
||||
trade.Sell(vol, g_sym, bid, sl, tp, "RSIConsolidation SELL");
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
@@ -0,0 +1,37 @@
|
||||
; RSIConsolidation.mq5 — optimization preset (Strategy Tester → Inputs → Load)
|
||||
; Format: Name=Current||Start||Step||Stop||Y|N (Y = include in optimization)
|
||||
;
|
||||
; === Symbol & session ===
|
||||
InpSymbol=
|
||||
; === Timeframe & bar logic ===
|
||||
; SignalTF: optimize per run (ENUM is non-sequential); M15=15, H1=16385, H4=16388
|
||||
SignalTF=15||15||0||15||N
|
||||
EntryOnNewBarOnly=true||false||0||true||N
|
||||
; === Regime: consolidation (anti-trend) ===
|
||||
ADX_Period=14||7||1||28||Y
|
||||
ADX_Max=22.0||16.0||1.0||32.0||Y
|
||||
UseATRRatioFilter=true||false||0||true||N
|
||||
ATR_Period=14||7||1||21||Y
|
||||
ATR_SMA_Period=50||20||5||100||Y
|
||||
ATR_Ratio_Max=1.18||1.0||0.02||1.35||Y
|
||||
UseFlatEMAFilter=true||false||0||true||N
|
||||
EMA_Fast=8||5||1||13||Y
|
||||
EMA_Slow=21||13||2||34||Y
|
||||
EMA_Separation_MaxPct=0.22||0.08||0.02||0.45||Y
|
||||
; === RSI entries ===
|
||||
RSI_Period=14||7||1||21||Y
|
||||
RSI_Price=1||1||1||7||Y
|
||||
RSI_Oversold=32.0||22.0||1.0||42.0||Y
|
||||
RSI_Overbought=68.0||58.0||1.0||78.0||Y
|
||||
; === Exits ===
|
||||
UseRSI_MeanExit=true||false||0||true||N
|
||||
RSI_Exit_Long=52.0||48.0||1.0||62.0||Y
|
||||
RSI_Exit_Short=48.0||38.0||1.0||52.0||Y
|
||||
SL_ATR_Mult=1.35||0.9||0.05||2.2||Y
|
||||
TP_ATR_Mult=1.85||1.0||0.05||3.0||Y
|
||||
MaxBarsInTrade=36||12||2||80||Y
|
||||
; === Risk & execution ===
|
||||
Lots=0.1||0.1||0.01||1.0||N
|
||||
MagicNumber=20250420||20250420||1||20250420||N
|
||||
Slippage=10||10||1||100||N
|
||||
MaxSpreadPoints=0||0||1||30||Y
|
||||
@@ -9,7 +9,7 @@ input int overboughtLevel = 93; // Overbought level (RSI > 70 for sell)
|
||||
input int oversoldLevel = 22; // Oversold level (RSI < 30 for buy)
|
||||
input double entryRSIBuySpread = 0;
|
||||
input double entryRSISellSpread = 0;
|
||||
input double lotSize = 0.01; // Trade lot size
|
||||
input double lotSize = 0.1; // Trade lot size
|
||||
input int slippage = 3; // Slippage for orders
|
||||
input int cooldownSeconds = 209; // Cooldown period in seconds
|
||||
input ENUM_TIMEFRAMES TimeFrame1 = PERIOD_M1; // RSI Timeframe
|
||||
@@ -14,7 +14,7 @@
|
||||
// Input Parameters
|
||||
input group "General Settings"
|
||||
input ENUM_TIMEFRAMES InpTimeframe = PERIOD_H1; // Trading Timeframe
|
||||
input double InpLotSize = 0.02; // Lot Size
|
||||
input double InpLotSize = 0.1; // Lot Size
|
||||
input int InpMagicNumberRSIFollow = 1001; // Magic Number RSI Follow
|
||||
input int InpMagicNumberRSIReverse = 1002;// Magic Number RSI Reverse
|
||||
input int InpMagicNumberEMACross = 1003; // Magic Number EMA Cross
|
||||
@@ -23,9 +23,9 @@ input group "Strategy Switches"
|
||||
input bool InpEnableRSIFollow = true; // Enable RSI Follow Strategy
|
||||
input bool InpEnableRSIReverse = true; // Enable RSI Reverse Strategy
|
||||
input bool InpEnableEMACross = true; // Enable EMA Cross Strategy
|
||||
input bool InpEnableStrategyLock = false; // Enable Strategy Lock
|
||||
input double InpLockProfitThreshold = 0.0; // Lock Profit Threshold (pips)
|
||||
input bool InpCloseOppositeTrades = false; // Close Opposite Trades When Profiting
|
||||
input bool InpEnableStrategyLock = true; // Enable Strategy Lock
|
||||
input double InpLockProfitThreshold = 6.0; // Lock Profit Threshold (pips)
|
||||
input bool InpCloseOppositeTrades = true; // Close Opposite Trades When Profiting
|
||||
|
||||
input group "RSI Follow Strategy"
|
||||
input int InpRSIPeriod = 32; // RSI Period
|
||||
|
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 241 KiB After Width: | Height: | Size: 241 KiB |