Update
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
; saved on 2026.02.07
|
||||
; Genetic Algorithm Optimization Parameters for RSIScalpingNVDA
|
||||
; Recommended ranges for profitable parameter discovery
|
||||
;
|
||||
; Format: Parameter=Start||Step||Min||Max||Optimize(Y/N)
|
||||
;
|
||||
; NOTE: Current values show RSI_Overbought=19 and RSI_Oversold=50 which are unusual.
|
||||
; This config uses STANDARD RSI ranges (60-85 overbought, 15-40 oversold).
|
||||
; If your current values are intentional, use the alternative ranges in OPTIMIZATION_GUIDE.md
|
||||
;
|
||||
; === PHASE 1: CORE RSI PARAMETERS (Primary Optimization) ===
|
||||
RSI_Period=14||1||7||21||Y
|
||||
RSI_Overbought=70.0||2.0||60.0||85.0||Y
|
||||
RSI_Oversold=30.0||2.0||15.0||40.0||Y
|
||||
RSI_Target_Buy=75.0||2.0||65.0||90.0||Y
|
||||
RSI_Target_Sell=25.0||2.0||10.0||35.0||Y
|
||||
|
||||
; === PHASE 2: RISK MANAGEMENT (Secondary Optimization) ===
|
||||
BarsToWait=2||1||1||8||Y
|
||||
TimeFrame=16387||0||16385||16390||Y
|
||||
|
||||
; === PHASE 3: POSITION SIZING (Optimize with caution) ===
|
||||
LotSize=50.0||5.0||10.0||100.0||Y
|
||||
|
||||
; === Trailing stop (main.mq5 1.01+) ===
|
||||
UseTrailingStop=true||false||0||true||N
|
||||
TrailingStopDistancePoints=375.0||25.0||100.0||800.0||Y
|
||||
TrailingActivationPoints=75.0||5.0||0.0||300.0||Y
|
||||
|
||||
; === Session filter new entries UTC (main.mq5 1.02+) ===
|
||||
UseSessionFilterUTC=false||false||0||true||Y
|
||||
TradeStartHourUTC=9||1||6||14||Y
|
||||
TradeEndHourUTC=22||1||18||24||N
|
||||
|
||||
; === FIXED PARAMETERS (Do Not Optimize) ===
|
||||
RSI_Applied_Price=1||0||1||1||N
|
||||
MagicNumber=12345||0||12345||12345||N
|
||||
Slippage=3||0||3||3||N
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
; saved on 2026.02.07
|
||||
; Alternative Genetic Algorithm Optimization - Respects Current Unusual RSI Values
|
||||
; Use this if RSI_Overbought=19 and RSI_Oversold=50 are intentional
|
||||
;
|
||||
; Format: Parameter=Start||Step||Min||Max||Optimize(Y/N)
|
||||
;
|
||||
; === PHASE 1: CORE RSI PARAMETERS ===
|
||||
RSI_Period=14||1||7||21||Y
|
||||
RSI_Overbought=19.0||1.0||15.0||30.0||Y
|
||||
RSI_Oversold=50.0||2.0||40.0||60.0||Y
|
||||
RSI_Target_Buy=71.0||2.0||65.0||80.0||Y
|
||||
RSI_Target_Sell=70.0||2.0||60.0||75.0||Y
|
||||
|
||||
; === PHASE 2: RISK MANAGEMENT ===
|
||||
BarsToWait=1||1||1||8||Y
|
||||
TimeFrame=16387||0||16385||16390||Y
|
||||
|
||||
; === PHASE 3: POSITION SIZING ===
|
||||
LotSize=50.0||5.0||10.0||100.0||Y
|
||||
|
||||
; === Trailing stop (main.mq5 1.01+) ===
|
||||
UseTrailingStop=true||false||0||true||N
|
||||
TrailingStopDistancePoints=375.0||25.0||100.0||800.0||Y
|
||||
TrailingActivationPoints=75.0||5.0||0.0||300.0||Y
|
||||
|
||||
; === Session filter new entries UTC (main.mq5 1.02+) ===
|
||||
UseSessionFilterUTC=false||false||0||true||Y
|
||||
TradeStartHourUTC=9||1||6||14||Y
|
||||
TradeEndHourUTC=22||1||18||24||N
|
||||
|
||||
; === FIXED PARAMETERS ===
|
||||
RSI_Applied_Price=1||0||1||1||N
|
||||
MagicNumber=12345||0||12345||12345||N
|
||||
Slippage=3||0||3||3||N
|
||||
@@ -0,0 +1,134 @@
|
||||
# Genetic Algorithm Optimization Guide for RSIScalpingNVDA
|
||||
|
||||
## Recommended Optimization Strategy
|
||||
|
||||
### Phase 1: Core RSI Parameters (Primary Focus)
|
||||
These parameters directly control entry/exit signals and should be optimized first.
|
||||
|
||||
#### **RSI_Period** (Y - Optimize)
|
||||
- **Current**: 14
|
||||
- **Recommended Range**: 7-21
|
||||
- **Step**: 1
|
||||
- **Rationale**: Standard RSI periods. Shorter = more sensitive, longer = smoother signals
|
||||
|
||||
#### **RSI_Overbought** (Y - Optimize)
|
||||
- **Current**: 19.0 (unusually low - verify if this is correct)
|
||||
- **Standard Range**: 60.0-85.0
|
||||
- **Step**: 2.0
|
||||
- **Alternative Range** (if current is intentional): 15.0-30.0
|
||||
- **Rationale**: Level where RSI indicates overbought condition for sell entries
|
||||
|
||||
#### **RSI_Oversold** (Y - Optimize)
|
||||
- **Current**: 50.0 (unusually high - verify if this is correct)
|
||||
- **Standard Range**: 15.0-40.0
|
||||
- **Step**: 2.0
|
||||
- **Alternative Range** (if current is intentional): 40.0-60.0
|
||||
- **Rationale**: Level where RSI indicates oversold condition for buy entries
|
||||
|
||||
#### **RSI_Target_Buy** (Y - Optimize)
|
||||
- **Current**: 71.0
|
||||
- **Recommended Range**: 65.0-90.0
|
||||
- **Step**: 2.0
|
||||
- **Rationale**: Exit target for long positions. Must be > RSI_Oversold
|
||||
|
||||
#### **RSI_Target_Sell** (Y - Optimize)
|
||||
- **Current**: 70.0
|
||||
- **Recommended Range**: 10.0-35.0
|
||||
- **Step**: 2.0
|
||||
- **Rationale**: Exit target for short positions. Must be < RSI_Overbought
|
||||
|
||||
### Phase 2: Risk Management Parameters
|
||||
|
||||
#### **BarsToWait** (Y - Optimize)
|
||||
- **Current**: 1
|
||||
- **Recommended Range**: 1-8
|
||||
- **Step**: 1
|
||||
- **Rationale**: Bars to wait before closing when RSI goes against position. Higher = more patience
|
||||
|
||||
#### **TimeFrame** (Y - Optimize)
|
||||
- **Current**: 16387 (M5)
|
||||
- **Recommended**: Test M1, M5, M15, H1
|
||||
- **Values**:
|
||||
- M1 = 16385
|
||||
- M5 = 16387
|
||||
- M15 = 16388
|
||||
- H1 = 16390
|
||||
- **Rationale**: Different timeframes can significantly affect scalping performance
|
||||
|
||||
### Phase 3: Position Sizing (Optimize with Caution)
|
||||
|
||||
#### **LotSize** (Y - Optimize with Fixed Risk)
|
||||
- **Current**: 50.0
|
||||
- **Recommended Range**: 10.0-100.0
|
||||
- **Step**: 5.0
|
||||
- **Note**: Consider using fixed risk % instead of fixed lot size
|
||||
- **Rationale**: Position sizing affects profitability but also risk
|
||||
|
||||
### Fixed Parameters (Do NOT Optimize)
|
||||
|
||||
#### **RSI_Applied_Price** (N)
|
||||
- **Value**: 1 (PRICE_CLOSE)
|
||||
- **Rationale**: Standard choice, changing may not improve results significantly
|
||||
|
||||
#### **MagicNumber** (N)
|
||||
- **Value**: 12345
|
||||
- **Rationale**: Identifier only, no impact on performance
|
||||
|
||||
#### **Slippage** (N)
|
||||
- **Value**: 3
|
||||
- **Rationale**: Broker-specific, should match your actual slippage
|
||||
|
||||
## Genetic Algorithm Settings
|
||||
|
||||
### Recommended GA Settings:
|
||||
- **Optimization Criterion**: Balance (or Custom: Profit Factor * Total Net Profit)
|
||||
- **Population Size**: 50-100
|
||||
- **Mutation Probability**: 0.1-0.2
|
||||
- **Crossover Probability**: 0.7-0.9
|
||||
- **Optimization Passes**: 3-5
|
||||
- **Forward Testing**: Always use out-of-sample data
|
||||
|
||||
### Optimization Phases:
|
||||
|
||||
1. **Broad Search** (First Pass):
|
||||
- Optimize: RSI_Period, RSI_Overbought, RSI_Oversold, RSI_Target_Buy, RSI_Target_Sell
|
||||
- Fix: BarsToWait=1, TimeFrame=M5, LotSize=50
|
||||
|
||||
2. **Refinement** (Second Pass):
|
||||
- Use best results from Phase 1
|
||||
- Optimize: BarsToWait, TimeFrame
|
||||
- Narrow ranges around Phase 1 winners
|
||||
|
||||
3. **Fine-Tuning** (Third Pass):
|
||||
- Optimize: LotSize (if needed)
|
||||
- Very narrow ranges around Phase 2 winners
|
||||
|
||||
## Important Notes
|
||||
|
||||
⚠️ **Current Parameter Anomaly**:
|
||||
- RSI_Overbought=19 and RSI_Oversold=50 are unusual
|
||||
- Standard RSI ranges: Overbought 70-80, Oversold 20-30
|
||||
- **Verify** if these are intentional or if there's a scaling issue
|
||||
|
||||
✅ **Validation Checklist**:
|
||||
- Ensure RSI_Target_Buy > RSI_Oversold
|
||||
- Ensure RSI_Target_Sell < RSI_Overbought
|
||||
- Test on sufficient historical data (at least 6-12 months)
|
||||
- Use forward testing on unseen data
|
||||
- Check for overfitting (too many parameters optimized)
|
||||
|
||||
## Example .set File Structure
|
||||
|
||||
```
|
||||
RSI_Period=14||1||7||21||Y
|
||||
RSI_Overbought=70.0||2.0||60.0||85.0||Y
|
||||
RSI_Oversold=30.0||2.0||15.0||40.0||Y
|
||||
RSI_Target_Buy=75.0||2.0||65.0||90.0||Y
|
||||
RSI_Target_Sell=25.0||2.0||10.0||35.0||Y
|
||||
BarsToWait=2||1||1||8||Y
|
||||
TimeFrame=16387||0||16385||16390||Y
|
||||
LotSize=50.0||5.0||10.0||100.0||Y
|
||||
RSI_Applied_Price=1||0||1||1||N
|
||||
MagicNumber=12345||0||12345||12345||N
|
||||
Slippage=3||0||3||3||N
|
||||
```
|
||||
@@ -0,0 +1,445 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| RSIScalping.mq5 |
|
||||
//| Copyright 2025, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2025, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.02"
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include "../_united/MagicNumberHelpers.mqh"
|
||||
|
||||
//--- Input parameters
|
||||
input ENUM_TIMEFRAMES TimeFrame = PERIOD_M15; // Timeframe for Analysis
|
||||
input int RSI_Period = 8; // RSI Period
|
||||
input ENUM_APPLIED_PRICE RSI_Applied_Price = PRICE_CLOSE; // RSI Applied Price
|
||||
input double RSI_Overbought = 36; // RSI Overbought Level
|
||||
input double RSI_Oversold = 38; // RSI Oversold Level
|
||||
input double RSI_Target_Buy = 90; // RSI Target for Buy Exit
|
||||
input double RSI_Target_Sell = 70; // RSI Target for Sell Exit
|
||||
input int BarsToWait = 5; // Bars to wait when RSI goes against position
|
||||
input double LotSize = 50; // Lot Size
|
||||
input int MagicNumber = 12345; // Magic Number
|
||||
input int Slippage = 3; // Slippage in points
|
||||
|
||||
input group "=== Trailing stop ==="
|
||||
input bool UseTrailingStop = true; // move SL behind bid/ask while in profit
|
||||
input double TrailingStopDistancePoints = 375.0; // SL distance from bid/ask (points)
|
||||
input double TrailingActivationPoints = 75.0; // min profit before trailing (0 = same as distance)
|
||||
|
||||
input group "=== Session filter new entries (UTC) ==="
|
||||
// Stocks/CFDs often shift behaviour around major cash opens; some NVDA 1h charts show a sharp volume + direction change near 09:00 UTC. Filter affects OPEN only (exits/trailing unchanged).
|
||||
input bool UseSessionFilterUTC = false; // if true, block new entries outside [TradeStartHourUTC, TradeEndHourUTC)
|
||||
input int TradeStartHourUTC = 9; // allow new trades when TimeGMT hour >= this (0..23)
|
||||
input int TradeEndHourUTC = 22; // allow new trades when TimeGMT hour < this (exclusive). If Start>End, window wraps midnight (e.g. 22..6)
|
||||
|
||||
//--- Global variables
|
||||
CTrade trade;
|
||||
int rsi_handle;
|
||||
double rsi_buffer[];
|
||||
double rsi_prev, rsi_current, rsi_two_bars_ago;
|
||||
bool position_open = false;
|
||||
int position_ticket = 0;
|
||||
ENUM_POSITION_TYPE current_position_type = POSITION_TYPE_BUY;
|
||||
datetime last_bar_time = 0;
|
||||
bool rsi_against_position = false;
|
||||
int bars_against_count = 0;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
// Initialize RSI indicator
|
||||
rsi_handle = iRSI(_Symbol, TimeFrame, RSI_Period, RSI_Applied_Price);
|
||||
if(rsi_handle == INVALID_HANDLE)
|
||||
{
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
|
||||
// Initialize trade object
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
trade.SetDeviationInPoints(Slippage);
|
||||
trade.SetTypeFilling(ORDER_FILLING_FOK);
|
||||
|
||||
// Allocate arrays
|
||||
ArraySetAsSeries(rsi_buffer, true);
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
if(rsi_handle != INVALID_HANDLE)
|
||||
IndicatorRelease(rsi_handle);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
if(Bars(_Symbol, TimeFrame) < RSI_Period + 2)
|
||||
return;
|
||||
|
||||
const datetime current_bar_time = iTime(_Symbol, TimeFrame, 0);
|
||||
const bool new_bar = (current_bar_time != last_bar_time);
|
||||
const bool in_pos = position_open || PositionExistsByMagic(_Symbol, (ulong)MagicNumber);
|
||||
|
||||
if(!in_pos && !new_bar)
|
||||
return;
|
||||
|
||||
if(!UpdateRSI())
|
||||
return;
|
||||
|
||||
if(in_pos && UseTrailingStop)
|
||||
ApplyTrailingStop();
|
||||
|
||||
if(!new_bar)
|
||||
return;
|
||||
|
||||
last_bar_time = current_bar_time;
|
||||
|
||||
ResyncPositionFromMarket();
|
||||
CheckExistingPosition();
|
||||
|
||||
if(!position_open && !PositionExistsByMagic(_Symbol, (ulong)MagicNumber))
|
||||
CheckEntrySignals();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| New entries allowed in [TradeStartHourUTC, TradeEndHourUTC) GMT |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IsWithinNewEntryWindowUTC()
|
||||
{
|
||||
if(!UseSessionFilterUTC)
|
||||
return true;
|
||||
|
||||
int s = TradeStartHourUTC;
|
||||
int e = TradeEndHourUTC;
|
||||
if(s < 0) s = 0;
|
||||
if(s > 23) s = 23;
|
||||
if(e < 0) e = 0;
|
||||
if(e > 24) e = 24;
|
||||
|
||||
MqlDateTime dt;
|
||||
TimeToStruct(TimeGMT(), dt);
|
||||
const int h = dt.hour;
|
||||
|
||||
if(s == e)
|
||||
return true;
|
||||
|
||||
if(s < e)
|
||||
return (h >= s && h < e);
|
||||
|
||||
return (h >= s || h < e);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update RSI values |
|
||||
//+------------------------------------------------------------------+
|
||||
bool UpdateRSI()
|
||||
{
|
||||
if(CopyBuffer(rsi_handle, 0, 0, 3, rsi_buffer) < 3)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
rsi_current = rsi_buffer[0]; // Current bar
|
||||
rsi_prev = rsi_buffer[1]; // Previous bar
|
||||
rsi_two_bars_ago = rsi_buffer[2]; // Two bars ago
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Trail SL behind favorable price (every tick when enabled) |
|
||||
//+------------------------------------------------------------------+
|
||||
void ApplyTrailingStop()
|
||||
{
|
||||
if(TrailingStopDistancePoints <= 0.0)
|
||||
return;
|
||||
if(!PositionSelectByMagic(_Symbol, (ulong)MagicNumber))
|
||||
return;
|
||||
|
||||
const double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
|
||||
if(point <= 0.0)
|
||||
return;
|
||||
|
||||
const int digits = (int)SymbolInfoInteger(_Symbol, SYMBOL_DIGITS);
|
||||
const double trail_dist = TrailingStopDistancePoints * point;
|
||||
const double activation_pts = (TrailingActivationPoints > 0.0)
|
||||
? TrailingActivationPoints
|
||||
: TrailingStopDistancePoints;
|
||||
const double activation = activation_pts * point;
|
||||
const long stops_level = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL);
|
||||
const double min_dist = (double)stops_level * point;
|
||||
|
||||
const ENUM_POSITION_TYPE ptype = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
const double entry = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
const double cur_sl = PositionGetDouble(POSITION_SL);
|
||||
const double cur_tp = PositionGetDouble(POSITION_TP);
|
||||
|
||||
if(ptype == POSITION_TYPE_BUY)
|
||||
{
|
||||
const double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
if(bid - entry <= activation)
|
||||
return;
|
||||
|
||||
double new_sl = NormalizeDouble(bid - trail_dist, digits);
|
||||
if(min_dist > 0.0 && bid - new_sl < min_dist)
|
||||
new_sl = NormalizeDouble(bid - min_dist, digits);
|
||||
|
||||
if(new_sl >= bid || new_sl <= 0.0)
|
||||
return;
|
||||
if(cur_sl > 0.0 && new_sl <= cur_sl)
|
||||
return;
|
||||
|
||||
ModifyPositionByMagic(trade, _Symbol, (ulong)MagicNumber, new_sl, cur_tp);
|
||||
}
|
||||
else if(ptype == POSITION_TYPE_SELL)
|
||||
{
|
||||
const double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
if(entry - ask <= activation)
|
||||
return;
|
||||
|
||||
double new_sl = NormalizeDouble(ask + trail_dist, digits);
|
||||
if(min_dist > 0.0 && new_sl - ask < min_dist)
|
||||
new_sl = NormalizeDouble(ask + min_dist, digits);
|
||||
|
||||
if(new_sl <= ask || new_sl <= 0.0)
|
||||
return;
|
||||
if(cur_sl > 0.0 && new_sl >= cur_sl)
|
||||
return;
|
||||
|
||||
ModifyPositionByMagic(trade, _Symbol, (ulong)MagicNumber, new_sl, cur_tp);
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Sync ticket/state if a position exists after restart |
|
||||
//+------------------------------------------------------------------+
|
||||
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);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check existing position for exit conditions |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckExistingPosition()
|
||||
{
|
||||
if(!position_open)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if position still exists with correct magic number AND symbol for THIS EA
|
||||
if(!PositionSelectByTicketSymbolAndMagic(position_ticket, _Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
// Exit conditions based on RSI target
|
||||
if(current_position_type == POSITION_TYPE_BUY)
|
||||
{
|
||||
// Check if RSI is against the position (below oversold)
|
||||
if(rsi_current < RSI_Oversold)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bars_against_count++;
|
||||
}
|
||||
|
||||
// Close position if RSI has been against for Y bars
|
||||
if(bars_against_count >= BarsToWait)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// RSI is no longer against the position, reset counter
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
|
||||
// Exit long position when RSI reaches buy target
|
||||
if(rsi_current >= RSI_Target_Buy)
|
||||
{
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(current_position_type == POSITION_TYPE_SELL)
|
||||
{
|
||||
// Check if RSI is against the position (above overbought)
|
||||
if(rsi_current > RSI_Overbought)
|
||||
{
|
||||
if(!rsi_against_position)
|
||||
{
|
||||
rsi_against_position = true;
|
||||
bars_against_count = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
bars_against_count++;
|
||||
}
|
||||
|
||||
// Close position if RSI has been against for Y bars
|
||||
if(bars_against_count >= BarsToWait)
|
||||
{
|
||||
ClosePosition();
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// RSI is no longer against the position, reset counter
|
||||
if(rsi_against_position)
|
||||
{
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
|
||||
// Exit short position when RSI reaches sell target
|
||||
if(rsi_current <= RSI_Target_Sell)
|
||||
{
|
||||
ClosePosition();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check for entry signals |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckEntrySignals()
|
||||
{
|
||||
if(!IsWithinNewEntryWindowUTC())
|
||||
return;
|
||||
|
||||
// Buy signal: RSI crosses from oversold to above oversold (checking the actual crossover)
|
||||
if(rsi_two_bars_ago <= RSI_Oversold && rsi_prev > RSI_Oversold)
|
||||
{
|
||||
OpenBuyPosition();
|
||||
}
|
||||
|
||||
// Sell signal: RSI crosses from overbought to below overbought (checking the actual crossover)
|
||||
if(rsi_two_bars_ago >= RSI_Overbought && rsi_prev < RSI_Overbought)
|
||||
{
|
||||
OpenSellPosition();
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Open buy position |
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenBuyPosition()
|
||||
{
|
||||
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
|
||||
if(PositionExistsByMagic(_Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
return; // Position already exists for this EA
|
||||
}
|
||||
|
||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
|
||||
if(trade.Buy(LotSize, _Symbol, ask, 0, 0, "RSI Scalping Buy"))
|
||||
{
|
||||
ulong new_ticket = trade.ResultOrder();
|
||||
if(new_ticket > 0)
|
||||
{
|
||||
// Verify position was opened for THIS EA (magic number) on THIS symbol
|
||||
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_ticket = new_ticket;
|
||||
position_open = true;
|
||||
current_position_type = POSITION_TYPE_BUY;
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Error: Position opened but doesn't match EA magic number or symbol");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Open sell position |
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenSellPosition()
|
||||
{
|
||||
// Verify no position exists for THIS EA (magic number) on THIS symbol before opening
|
||||
if(PositionExistsByMagic(_Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
return; // Position already exists for this EA
|
||||
}
|
||||
|
||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
|
||||
if(trade.Sell(LotSize, _Symbol, bid, 0, 0, "RSI Scalping Sell"))
|
||||
{
|
||||
ulong new_ticket = trade.ResultOrder();
|
||||
if(new_ticket > 0)
|
||||
{
|
||||
// Verify position was opened for THIS EA (magic number) on THIS symbol
|
||||
if(PositionSelectByTicketSymbolAndMagic(new_ticket, _Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_ticket = new_ticket;
|
||||
position_open = true;
|
||||
current_position_type = POSITION_TYPE_SELL;
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Error: Position opened but doesn't match EA magic number or symbol");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Close current position |
|
||||
//+------------------------------------------------------------------+
|
||||
void ClosePosition()
|
||||
{
|
||||
// Close position using helper that verifies symbol AND magic number for THIS EA
|
||||
if(ClosePositionByMagic(trade, _Symbol, (ulong)MagicNumber))
|
||||
{
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Position doesn't exist or wrong magic number - reset tracking
|
||||
position_open = false;
|
||||
position_ticket = 0;
|
||||
rsi_against_position = false;
|
||||
bars_against_count = 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user