Update BTC
This commit is contained in:
@@ -0,0 +1,426 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ScoringTrade.mq5 |
|
||||
//| Generated by ChatGPT |
|
||||
//| |
|
||||
//+------------------------------------------------------------------+
|
||||
#property strict
|
||||
#include <Trade\Trade.mqh>
|
||||
|
||||
// Input parameters
|
||||
input int MagicNumber = 42; // Unique identifier for this EA's trades
|
||||
input int scoreThreshold = 15000; // Minimum score required to enter a trade (increased for BTC's larger price movements)
|
||||
input int slopeThreshold = 3500; // Minimum EMA slope value to consider trend significant (increased for BTC's steeper trends)
|
||||
input double maxScore = 25000; // Maximum allowed score before clamping (prevents excessive trade signals)
|
||||
input int cooldownMinutes = 18; // Minimum time between crossover signals (prevents over-trading)
|
||||
input int tradeCooldownMinutes = 44; // Minimum time between consecutive trades (trade debounce period)
|
||||
input ENUM_TIMEFRAMES emaTimeFrame = PERIOD_H1; // Timeframe for EMA calculation (1-hour candles)
|
||||
input double delayClampAbsolute = 5000; // Score threshold for applying decay (prevents score from growing too large)
|
||||
input int emaPeriod = 139; // Number of periods for EMA calculation (longer period for smoother trend)
|
||||
input double crossOverStep = 2500; // Score adjustment when price crosses EMA (increased for BTC's larger moves)
|
||||
input double slopeThresholdStep = 2000; // Score adjustment for significant slope changes (increased for BTC)
|
||||
input double emaDistanceStep = 500; // Score adjustment for price distance from EMA (increased for BTC)
|
||||
input double emaDecayStep = 0; // Score decay rate when no significant signals (0 means no decay)
|
||||
input double decayMultiplier = 0.08; // Multiplier applied to score when above delayClampAbsolute
|
||||
input double distanceThreshold = 7100; // Minimum price-EMA distance to trigger score adjustment (increased for BTC)
|
||||
input double atrMultiplier = 3.9; // Multiplier for dynamic stop loss calculation based on ATR
|
||||
input double TrailingStop = 10; // Distance in points for trailing stop loss
|
||||
input bool ApplyTrailingStop = true; // Enable/disable trailing stop functionality
|
||||
input int maxCrossoverTrades = 14; // Maximum number of trades allowed per crossover signal
|
||||
input double max_drawdown = 0.1; // Maximum allowed drawdown as percentage of account balance
|
||||
input bool resetCrossoverTradeOnDistance = false; // Reset trade count when price moves beyond distance threshold
|
||||
input int resetCrossoverNumber = 0; // Number of trades to reset to when resetCrossoverTradeOnDistance is true
|
||||
input double minimumLotSize = 0.01; // Minimum trade size allowed
|
||||
input int maxTimeInPosition = 1; // Maximum time in hours to hold a position
|
||||
input int tradeLengthThreshold = 31; // Time in minutes before considering a reverse trade
|
||||
input int reverseTP = 707; // Take profit level for reverse trades (increased for BTC)
|
||||
input int reverseLotSizeMultiplier = 4; // Multiplier for lot size in reverse trades
|
||||
input int secondaryPositionHoldTime = 75; // Maximum time in minutes to hold a secondary position
|
||||
// Global variables
|
||||
int emaHandle; // EMA handle
|
||||
double prevScore = 0; // Previous score
|
||||
double currentScore = 0; // Current score
|
||||
double emaPrevValue = 0; // Previous EMA value
|
||||
double emaCurrentValue = 0; // Current EMA value
|
||||
double emaSlope = 0; // EMA slope value
|
||||
CTrade trade; // Trading object
|
||||
|
||||
datetime lastCrossoverTime = 0; // Time of last crossover
|
||||
datetime lastTradeTime = 0; // Time of last trade
|
||||
int crossoverTradeCount = 0; // Count of trades after each crossover
|
||||
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit() {
|
||||
// Create EMA handle (e.g., 14-period EMA on the closing price)
|
||||
emaHandle = iMA(Symbol(), emaTimeFrame, emaPeriod, 0, MODE_EMA, PRICE_CLOSE);
|
||||
|
||||
if (emaHandle == INVALID_HANDLE) {
|
||||
Print("Failed to create EMA handle");
|
||||
return INIT_FAILED;
|
||||
}
|
||||
|
||||
return INIT_SUCCEEDED;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason) {
|
||||
// Release the EMA handle
|
||||
if (emaHandle != INVALID_HANDLE) {
|
||||
ExpertRemove();
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick() {
|
||||
// Buffer to hold the EMA values
|
||||
double emaBuffer[];
|
||||
|
||||
// Get dynamic lot size based on current balance and max drawdown
|
||||
double lotSize = CalculateLotSize();
|
||||
|
||||
if(lotSize < minimumLotSize) {
|
||||
lotSize = minimumLotSize;
|
||||
}
|
||||
|
||||
// Get the current Ask and Bid prices
|
||||
double Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
|
||||
double Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
|
||||
|
||||
// Copy the last 2 EMA values (current and previous)
|
||||
int copied = CopyBuffer(emaHandle, 0, 0, 2, emaBuffer);
|
||||
if (copied < 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the current and previous EMA values
|
||||
emaPrevValue = emaBuffer[1]; // Previous EMA value (index 1)
|
||||
emaCurrentValue = emaBuffer[0]; // Current EMA value (index 0)
|
||||
|
||||
// Calculate the EMA slope (change in EMA values)
|
||||
emaSlope = - (emaCurrentValue - emaPrevValue) * 100;
|
||||
Print("EMA Slope: ", emaSlope);
|
||||
|
||||
// Check for price action crossover with EMA
|
||||
double closePrev = iClose(Symbol(), Period(), 1); // Close of previous bar
|
||||
double closeCurr = iClose(Symbol(), Period(), 0); // Close of current bar
|
||||
|
||||
// Check if enough time has passed for the cooldown (cooldownMinutes)
|
||||
if (TimeCurrent() - lastCrossoverTime >= cooldownMinutes * 60) {
|
||||
if (closePrev < emaPrevValue && closeCurr > emaCurrentValue) { // Bullish crossover
|
||||
currentScore += crossOverStep;
|
||||
crossoverTradeCount = 0; // Reset trade count after new crossover
|
||||
lastCrossoverTime = TimeCurrent(); // Update the last crossover time
|
||||
}
|
||||
else if (closePrev > emaPrevValue && closeCurr < emaCurrentValue) { // Bearish crossover
|
||||
currentScore -= crossOverStep;
|
||||
crossoverTradeCount = 0; // Reset trade count after new crossover
|
||||
lastCrossoverTime = TimeCurrent(); // Update the last crossover time
|
||||
}
|
||||
}
|
||||
|
||||
// Check EMA slope
|
||||
if (emaSlope > slopeThreshold) { // Positive slope
|
||||
currentScore += slopeThresholdStep;
|
||||
}
|
||||
else if (emaSlope < -slopeThreshold) { // Negative slope
|
||||
currentScore -= slopeThresholdStep;
|
||||
}
|
||||
else {
|
||||
if (MathAbs(currentScore) > delayClampAbsolute) {
|
||||
currentScore *= decayMultiplier;
|
||||
}
|
||||
}
|
||||
|
||||
if(ApplyTrailingStop) {
|
||||
ApplyTrailingStop();
|
||||
}
|
||||
|
||||
// Calculate distance to EMA and adjust score
|
||||
double priceToEmaDistance = closeCurr - emaCurrentValue; // Distance between the current price and the EMA
|
||||
Print("Price to EMA Distance: ", priceToEmaDistance);
|
||||
|
||||
if (MathAbs(priceToEmaDistance) > distanceThreshold) {
|
||||
if (priceToEmaDistance > 0) { // Bullish (price above EMA)
|
||||
currentScore += emaDistanceStep;
|
||||
}
|
||||
else if (priceToEmaDistance < 0) { // Bearish (price below EMA)
|
||||
currentScore -= emaDistanceStep;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (currentScore > 0) {
|
||||
currentScore -= emaDecayStep;
|
||||
}
|
||||
else {
|
||||
currentScore += emaDecayStep;
|
||||
}
|
||||
}
|
||||
|
||||
// Close all positions if score crosses zero
|
||||
if ((prevScore > 0 && currentScore <= 0) || (prevScore < 0 && currentScore >= 0)) {
|
||||
Close_Position_MN(MagicNumber);
|
||||
}
|
||||
|
||||
// Update the previous score
|
||||
prevScore = currentScore;
|
||||
|
||||
if (crossoverTradeCount > maxCrossoverTrades) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Debounce check: Ensure enough time has passed since the last trade
|
||||
if (TimeCurrent() - lastTradeTime >= tradeCooldownMinutes * 60) {
|
||||
// Calculate ATR (Average True Range) for stop loss calculation
|
||||
double atrArray[];
|
||||
int atrPeriod = 14; // ATR period (can be adjusted)
|
||||
int copied = CopyBuffer(iATR(Symbol(), Period(), atrPeriod), 0, 0, 1, atrArray);
|
||||
if (copied < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the current price (using Bid price)
|
||||
double currentPrice = Bid;
|
||||
// Get ATR value
|
||||
double atrValue = atrArray[0]; // Latest ATR value
|
||||
|
||||
// Get the minimum stop level and freeze level for the symbol
|
||||
int stopLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL);
|
||||
int freezeLevel = SymbolInfoInteger(Symbol(), SYMBOL_TRADE_FREEZE_LEVEL);
|
||||
|
||||
// Calculate the minimum stop loss in price units (converted from pips)
|
||||
double minStopLoss = stopLevel * SymbolInfoDouble(Symbol(), SYMBOL_POINT);
|
||||
double minFreezeLevel = freezeLevel * SymbolInfoDouble(Symbol(), SYMBOL_POINT);
|
||||
|
||||
// Dynamic Stop Loss and Take Profit calculation based on ATR
|
||||
double dynamicSL = atrValue * atrMultiplier;
|
||||
double dynamicTP = atrValue * atrMultiplier;
|
||||
|
||||
// Adjust SL and TP if they are smaller than the minimum stop level
|
||||
dynamicSL = MathMax(dynamicSL, minStopLoss);
|
||||
dynamicTP = MathMax(dynamicTP, dynamicSL); // Ensure TP is at least the same as SL
|
||||
|
||||
// Trade logic based on the score
|
||||
if (currentScore > scoreThreshold) { // Buy signal
|
||||
if (PositionSelect(Symbol()) == false || !PositionGetInteger(POSITION_MAGIC) == MagicNumber && crossoverTradeCount < maxCrossoverTrades) {
|
||||
// Open buy position with dynamic SL and TP
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
if (trade.Buy(lotSize, Symbol(), currentPrice, Bid - dynamicSL, 0)) {
|
||||
crossoverTradeCount++; // Increment trade count
|
||||
lastTradeTime = TimeCurrent(); // Update the last trade time
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (currentScore < -scoreThreshold) { // Sell signal
|
||||
if (PositionSelect(Symbol()) == false || !PositionGetInteger(POSITION_MAGIC) == MagicNumber && crossoverTradeCount < maxCrossoverTrades) {
|
||||
// Open sell position with dynamic SL and TP
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
if (trade.Sell(lotSize, Symbol(), currentPrice, Ask + dynamicSL, 0)) {
|
||||
crossoverTradeCount++; // Increment trade count
|
||||
lastTradeTime = TimeCurrent(); // Update the last trade time
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check existing positions for profit and place reverse trade if needed
|
||||
CheckPositions();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check existing positions for profit and place reverse trade if needed |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckPositions() {
|
||||
// Check if there are any open positions
|
||||
if (PositionsTotal() > 0) {
|
||||
// Check if there are exactly 2 open positions
|
||||
if (PositionsTotal() == 2) {
|
||||
for (int i = 0; i < PositionsTotal(); i++) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (PositionSelectByTicket(ticket)) {
|
||||
datetime openTime = PositionGetInteger(POSITION_TIME);
|
||||
int tradeLength = TimeCurrent() - openTime; // Trade duration in seconds
|
||||
|
||||
// Check if the trade has been open for more than the secondaryPositionHoldTime
|
||||
if (tradeLength > secondaryPositionHoldTime * 60) { // Convert threshold to seconds
|
||||
// Close all positions
|
||||
CloseAllPositions();
|
||||
return; // Exit the function after closing all positions
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (PositionsTotal() < 2) {
|
||||
for (int i = 0; i < PositionsTotal(); i++) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (PositionSelectByTicket(ticket)) {
|
||||
double profit = PositionGetDouble(POSITION_PROFIT);
|
||||
datetime openTime = PositionGetInteger(POSITION_TIME);
|
||||
int tradeLength = TimeCurrent() - openTime; // Trade duration in seconds
|
||||
|
||||
// Check if the trade has been open for more than the tradeLengthThreshold
|
||||
if (tradeLength > tradeLengthThreshold * 60) { // Convert threshold to seconds
|
||||
double lotSize = PositionGetDouble(POSITION_VOLUME);
|
||||
double newLotSize = lotSize * reverseLotSizeMultiplier; // 10 times the original lot size
|
||||
|
||||
crossoverTradeCount = maxCrossoverTrades + 1;
|
||||
|
||||
// Place a reverse trade
|
||||
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
if (trade.Sell(newLotSize, Symbol(), SymbolInfoDouble(Symbol(), SYMBOL_BID))) {
|
||||
} else {
|
||||
Print("Failed to execute reversal sell order");
|
||||
}
|
||||
} else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
if (trade.Buy(newLotSize, Symbol(), SymbolInfoDouble(Symbol(), SYMBOL_ASK))) {
|
||||
} else {
|
||||
Print("Failed to execute reversal buy order");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Close the trade if profit meets the take profit level
|
||||
if (profit >= reverseTP) {
|
||||
Close_Position_MN(MagicNumber);
|
||||
CloseAllPositions();
|
||||
}
|
||||
|
||||
// Check if there is only one position and its volume is lotSize * reverseLotSizeMultiplier
|
||||
if (PositionsTotal() == 1 && PositionGetDouble(POSITION_VOLUME) == minimumLotSize * reverseLotSizeMultiplier) {
|
||||
trade.PositionClose(ticket);
|
||||
}
|
||||
|
||||
// Get the current Ask and Bid prices
|
||||
double Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
|
||||
double Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID);
|
||||
|
||||
// Check if the double down trade is exited by stop loss
|
||||
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY && PositionGetDouble(POSITION_SL) > 0 && Bid <= PositionGetDouble(POSITION_SL)) {
|
||||
// Close the original trade
|
||||
CloseOriginalTrade();
|
||||
} else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL && PositionGetDouble(POSITION_SL) > 0 && Ask >= PositionGetDouble(POSITION_SL)) {
|
||||
// Close the original trade
|
||||
CloseOriginalTrade();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Function to close the original trade
|
||||
void CloseOriginalTrade() {
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (PositionSelectByTicket(ticket)) {
|
||||
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
|
||||
trade.PositionClose(ticket);
|
||||
} else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
|
||||
trade.PositionClose(ticket);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Function to close all positions |
|
||||
//+------------------------------------------------------------------+
|
||||
void CloseAllPositions() {
|
||||
// Loop through all positions and close them
|
||||
for (int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
if (PositionSelectByTicket(ticket)) {
|
||||
if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) {
|
||||
trade.PositionClose(ticket);
|
||||
}
|
||||
else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) {
|
||||
trade.PositionClose(ticket);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ApplyTrailingStop()
|
||||
{
|
||||
for(int i=PositionsTotal()-1; i>=0; i--)
|
||||
{
|
||||
string symbol = PositionGetSymbol(i);
|
||||
ulong PositionTicket = PositionGetTicket(i);
|
||||
long trade_type = PositionGetInteger(POSITION_TYPE);
|
||||
|
||||
if(!PositionGetInteger(POSITION_MAGIC) == MagicNumber) {
|
||||
return;
|
||||
}
|
||||
|
||||
double POINT = SymbolInfoDouble( symbol, SYMBOL_POINT );
|
||||
int DIGIT = (int) SymbolInfoInteger( symbol, SYMBOL_DIGITS );
|
||||
|
||||
if(trade_type == 0)
|
||||
{
|
||||
double Bid = NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_BID),DIGIT);
|
||||
|
||||
if(Bid-PositionGetDouble(POSITION_PRICE_OPEN) > NormalizeDouble(POINT * TrailingStop,DIGIT))
|
||||
{
|
||||
if(PositionGetDouble(POSITION_SL) < NormalizeDouble(Bid - POINT * TrailingStop,DIGIT))
|
||||
{
|
||||
trade.PositionModify(PositionTicket,NormalizeDouble(Bid - POINT * TrailingStop,DIGIT),PositionGetDouble(POSITION_TP));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(trade_type == 1)
|
||||
{
|
||||
double Ask = NormalizeDouble(SymbolInfoDouble(symbol,SYMBOL_ASK),DIGIT);
|
||||
|
||||
if((PositionGetDouble(POSITION_PRICE_OPEN) - Ask) > NormalizeDouble( POINT * TrailingStop,DIGIT))
|
||||
{
|
||||
if((PositionGetDouble(POSITION_SL) > NormalizeDouble(Ask + POINT * TrailingStop,DIGIT)) || (PositionGetDouble(POSITION_SL)==0))
|
||||
{
|
||||
trade.PositionModify(PositionTicket,NormalizeDouble(Ask + POINT * TrailingStop,DIGIT),PositionGetDouble(POSITION_TP));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Close_Position_MN(ulong magicNumber)
|
||||
{
|
||||
int total = PositionsTotal();
|
||||
for(int i = total - 1; i >= 0; i--)
|
||||
{
|
||||
ulong ticket = PositionGetTicket(i);
|
||||
|
||||
// Use PositionSelect by symbol instead of ticket
|
||||
string symbol = PositionGetSymbol(i);
|
||||
if(PositionSelect(symbol))
|
||||
{
|
||||
if (PositionGetInteger(POSITION_MAGIC) == magicNumber && PositionGetInteger(POSITION_TICKET) == ticket)
|
||||
{
|
||||
if(symbol == _Symbol) // Verify the symbol
|
||||
{
|
||||
trade.PositionClose(ticket);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate the dynamic lot size based on max drawdown |
|
||||
//+------------------------------------------------------------------+
|
||||
double CalculateLotSize()
|
||||
{
|
||||
double balance = AccountInfoDouble(ACCOUNT_BALANCE); // Get account balance
|
||||
double allowedDrawdown = balance * max_drawdown; // Calculate allowed drawdown in account currency
|
||||
double baseDrawdownPerLot = 150; // Assumed drawdown per 0.01 lots as per backtest
|
||||
|
||||
// Calculate lot size based on maximum drawdown
|
||||
double lotSize = (allowedDrawdown / baseDrawdownPerLot) * 0.01;
|
||||
return NormalizeDouble(lotSize, 2); // Normalize lot size to 2 decimal places
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 276 KiB |
@@ -7,6 +7,9 @@
|
||||
- [2. EMA Crossover Skirmish](#2-ema-crossover-skirmish)
|
||||
- [3. RSI Divergence Extrema AUDUSD](#3-rsi-divergence-extrema-audusd)
|
||||
- [4. RSI Divergence Extrema EURUSD](#4-rsi-divergence-extrema-eurusd)
|
||||
- [5. RSI Reversal Asian AUDUSD](#5-rsi-reversal-asian-audusd)
|
||||
- [6. RSI Reversal Asian EURUSD](#6-rsi-reversal-asian-eurusd)
|
||||
- [7. EMA Crossover BTC](#7-ema-crossover-btc)
|
||||
- [Technical Details](#technical-details)
|
||||
- [Requirements](#requirements)
|
||||
- [Installation](#installation)
|
||||
@@ -288,6 +291,221 @@ A strategy that combines RSI divergence with extreme price points detection for
|
||||
**Balance Sheet (2021-2025):**
|
||||

|
||||
|
||||
### 5. RSI Reversal Asian AUDUSD
|
||||
|
||||
A strategy specifically designed for the Asian session on AUDUSD, using RSI reversals with optimized parameters for this market condition.
|
||||
|
||||
**Key Features:**
|
||||
- RSI reversal patterns detection
|
||||
- Asian session optimization
|
||||
- Dynamic exit based on RSI thresholds
|
||||
- Advanced position management
|
||||
- Session-based trading rules
|
||||
|
||||
**Strategy Settings:**
|
||||
- Symbol: AUDUSD
|
||||
- Period: M15 (2021.01.01 - 2025.04.03)
|
||||
- RSI Period: 14
|
||||
- RSI Overbought: 67
|
||||
- RSI Oversold: 17
|
||||
- Take Profit: 253 pips
|
||||
- Stop Loss: 429 pips
|
||||
- Max Lot Size: 0.1
|
||||
- Max Spread: 1000
|
||||
- Max Duration: 81
|
||||
- RSI Exit Level: 49
|
||||
- Use Stop Loss: false
|
||||
- Use Take Profit: true
|
||||
- Use RSI Exit: true
|
||||
|
||||
**Performance Metrics (2021-2025):**
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Total Net Profit | $1,521.11 |
|
||||
| Gross Profit | $6,147.84 |
|
||||
| Gross Loss | -$4,626.73 |
|
||||
| Profit Factor | 1.33 |
|
||||
| Recovery Factor | 4.30 |
|
||||
| Expected Payoff | $2.32 |
|
||||
| Sharpe Ratio | 2.14 |
|
||||
| AHPR | 1.0022 (0.22%) |
|
||||
| GHPR | 1.0019 (0.19%) |
|
||||
|
||||
**Trade Statistics (2021-2025):**
|
||||
| Statistic | Value |
|
||||
|-----------|-------|
|
||||
| History Quality | 100% |
|
||||
| Total Bars | 105,824 |
|
||||
| Total Ticks | 6,215,660 |
|
||||
| Total Trades | 657 |
|
||||
| Total Deals | 1,314 |
|
||||
| Profit Trades | 491 (74.73%) |
|
||||
| Loss Trades | 166 (25.27%) |
|
||||
| Short Trades Won | 75.52% |
|
||||
| Long Trades Won | 61.11% |
|
||||
| Largest Profit Trade | $24.20 |
|
||||
| Largest Loss Trade | -$106.60 |
|
||||
| Average Profit Trade | $12.52 |
|
||||
| Average Loss Trade | -$27.87 |
|
||||
| Max Consecutive Wins | 17 ($266.30) |
|
||||
| Max Consecutive Losses | 4 (-$124.19) |
|
||||
|
||||
**Drawdown Analysis (2021-2025):**
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Balance Drawdown Absolute | $158.27 |
|
||||
| Equity Drawdown Absolute | $189.77 |
|
||||
| Balance Drawdown Maximal | $302.68 (16.43%) |
|
||||
| Equity Drawdown Maximal | $353.92 (20.63%) |
|
||||
| Balance Drawdown Relative | 26.38% ($158.27) |
|
||||
| Equity Drawdown Relative | 31.97% ($192.77) |
|
||||
|
||||
**Balance Sheet (2021-2025):**
|
||||

|
||||
|
||||
### 6. RSI Reversal Asian EURUSD
|
||||
|
||||
A strategy specifically designed for the Asian session on EURUSD, using RSI reversals with optimized parameters for this market condition.
|
||||
|
||||
**Key Features:**
|
||||
- RSI reversal patterns detection
|
||||
- Asian session optimization
|
||||
- Dynamic exit based on RSI thresholds
|
||||
- Advanced position management
|
||||
- Session-based trading rules
|
||||
|
||||
**Strategy Settings:**
|
||||
- Symbol: EURUSD
|
||||
- Period: M15 (2021.01.01 - 2025.04.03)
|
||||
- RSI Period: 14
|
||||
- RSI Overbought: 77
|
||||
- RSI Oversold: 10
|
||||
- Take Profit: 116 pips
|
||||
- Stop Loss: 247 pips
|
||||
- Max Lot Size: 0.1
|
||||
- Max Spread: 1000
|
||||
- Max Duration: 67
|
||||
- RSI Exit Level: 40
|
||||
- Use Stop Loss: true
|
||||
- Use Take Profit: false
|
||||
- Use RSI Exit: true
|
||||
|
||||
**Performance Metrics (2021-2025):**
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Total Net Profit | $955.26 |
|
||||
| Gross Profit | $1,961.62 |
|
||||
| Gross Loss | -$1,006.36 |
|
||||
| Profit Factor | 1.95 |
|
||||
| Recovery Factor | 6.70 |
|
||||
| Expected Payoff | $12.09 |
|
||||
| Sharpe Ratio | 6.99 |
|
||||
| AHPR | 1.0132 (1.32%) |
|
||||
| GHPR | 1.0121 (1.21%) |
|
||||
|
||||
**Trade Statistics (2021-2025):**
|
||||
| Statistic | Value |
|
||||
|-----------|-------|
|
||||
| History Quality | 100% |
|
||||
| Total Bars | 105,824 |
|
||||
| Total Ticks | 6,218,391 |
|
||||
| Total Trades | 79 |
|
||||
| Total Deals | 158 |
|
||||
| Profit Trades | 40 (50.63%) |
|
||||
| Loss Trades | 39 (49.37%) |
|
||||
| Short Trades Won | 50.00% |
|
||||
| Long Trades Won | 100.00% |
|
||||
| Largest Profit Trade | $129.78 |
|
||||
| Largest Loss Trade | -$30.90 |
|
||||
| Average Profit Trade | $49.04 |
|
||||
| Average Loss Trade | -$25.80 |
|
||||
| Max Consecutive Wins | 5 ($223.98) |
|
||||
| Max Consecutive Losses | 3 (-$79.60) |
|
||||
|
||||
**Drawdown Analysis (2021-2025):**
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Balance Drawdown Absolute | $0.00 |
|
||||
| Equity Drawdown Absolute | $2.51 |
|
||||
| Balance Drawdown Maximal | $113.91 (7.03%) |
|
||||
| Equity Drawdown Maximal | $142.61 (8.74%) |
|
||||
| Balance Drawdown Relative | 13.81% ($98.24) |
|
||||
| Equity Drawdown Relative | 16.97% ($122.14) |
|
||||
|
||||
**Balance Sheet (2021-2025):**
|
||||

|
||||
|
||||
### 7. EMA Crossover BTC
|
||||
|
||||
A strategy specifically designed for Bitcoin (BTCUSD) using EMA crossovers with advanced scoring and position management.
|
||||
|
||||
**Key Features:**
|
||||
- EMA crossover detection
|
||||
- Advanced scoring system
|
||||
- Trailing stop management
|
||||
- Position scaling and reversal capabilities
|
||||
- Dynamic distance thresholds
|
||||
- Decay multiplier for trend strength
|
||||
|
||||
**Strategy Settings:**
|
||||
- Symbol: BTCUSD
|
||||
- Period: H1 (2021.01.01 - 2025.04.03)
|
||||
- Magic Number: 42
|
||||
- Score Threshold: 15000
|
||||
- Slope Threshold: 3500
|
||||
- Max Score: 25000
|
||||
- Cooldown Minutes: 18
|
||||
- Trade Cooldown Minutes: 44
|
||||
- EMA Time Frame: 16385
|
||||
- Delay Clamp Absolute: 5000
|
||||
- EMA Period: 139
|
||||
- Cross Over Step: 2500
|
||||
- Slope Threshold Step: 2000
|
||||
- EMA Distance Step: 500
|
||||
- EMA Decay Step: 0
|
||||
- Decay Multiplier: 0.08
|
||||
- Distance Threshold: 7100
|
||||
- ATR Multiplier: 3.9
|
||||
- Trailing Stop: 10
|
||||
- Apply Trailing Stop: true
|
||||
- Max Crossover Trades: 14
|
||||
- Max Drawdown: 10%
|
||||
- Minimum Lot Size: 0.01
|
||||
- Max Time in Position: 1 hour
|
||||
- Trade Length Threshold: 31
|
||||
- Reverse TP: 707
|
||||
- Reverse Lot Size Multiplier: 4
|
||||
- Secondary Position Hold Time: 75
|
||||
|
||||
**Performance Metrics (2021-2025):**
|
||||
| Metric | Value |
|
||||
|--------|-------|
|
||||
| Total Net Profit | $632.96 |
|
||||
| Gross Profit | $849.93 |
|
||||
| Gross Loss | -$216.97 |
|
||||
| Profit Factor | 3.92 |
|
||||
| Recovery Factor | 7.47 |
|
||||
| Expected Payoff | $0.58 |
|
||||
| Sharpe Ratio | 7.57 |
|
||||
| AHPR | 1.0007 (0.07%) |
|
||||
| GHPR | 1.0007 (0.07%) |
|
||||
|
||||
**Trade Statistics (2021-2025):**
|
||||
| Statistic | Value |
|
||||
|-----------|-------|
|
||||
| History Quality | 98% |
|
||||
| Total Bars | 35,791 |
|
||||
| Total Ticks | 8,380,510 |
|
||||
| Balance Drawdown Absolute | $0.00 |
|
||||
| Equity Drawdown Absolute | $2.72 |
|
||||
| Balance Drawdown Maximal | $41.94 (3.52%) |
|
||||
| Equity Drawdown Maximal | $84.72 (7.13%) |
|
||||
| Balance Drawdown Relative | 3.52% ($41.94) |
|
||||
| Equity Drawdown Relative | 7.13% ($84.72) |
|
||||
|
||||
**Balance Sheet (2021-2025):**
|
||||

|
||||
|
||||
## Technical Details
|
||||
Each EA is implemented in MQL5 and includes:
|
||||
- Custom strategy implementation
|
||||
|
||||
@@ -0,0 +1,457 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| SimpleRSIReversalAUDUSD.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
// Include trade class
|
||||
#include <Trade\Trade.mqh>
|
||||
|
||||
// Input parameters
|
||||
input int RSIPeriod = 14; // RSI period
|
||||
input double OverboughtLevel = 67; // Overbought level
|
||||
input double OversoldLevel = 17; // Oversold level
|
||||
input int TakeProfitPips = 253; // Take profit in pips
|
||||
input int StopLossPips = 429; // Stop loss in pips
|
||||
input double MaxLotSize = 0.1; // Maximum lot size
|
||||
input int MaxSpread = 1000; // Maximum allowed spread in pips
|
||||
input int MaxDuration = 81; // Maximum trade duration in hours
|
||||
input bool UseStopLoss = false; // Use stop loss
|
||||
input bool UseTakeProfit = true; // Use take profit
|
||||
input bool UseRSIExit = true; // Use RSI for exit
|
||||
input double RSIExitLevel = 49; // RSI level to exit (50 = neutral)
|
||||
input bool CloseOutsideSession = false; // Close trades outside Asian session
|
||||
input color PanelBackground = clrBlack; // Panel background color
|
||||
input color PanelText = clrWhite; // Panel text color
|
||||
input int PanelX = 10; // Panel X position
|
||||
input int PanelY = 20; // Panel Y position
|
||||
|
||||
// Global variables
|
||||
CTrade trade;
|
||||
int rsiHandle;
|
||||
bool isPositionOpen = false;
|
||||
double positionOpenPrice = 0;
|
||||
datetime positionOpenTime = 0;
|
||||
ENUM_POSITION_TYPE lastPositionType = POSITION_TYPE_BUY;
|
||||
bool sessionCloseAttempted = false; // Track if we've attempted to close positions for current session
|
||||
|
||||
// Panel objects
|
||||
string panelName = "RSIPanel";
|
||||
int panelWidth = 200;
|
||||
int panelHeight = 200;
|
||||
int labelHeight = 20;
|
||||
int labelSpacing = 5;
|
||||
|
||||
// Session times (UTC)
|
||||
const int AsianSessionStart = 0; // 00:00 UTC
|
||||
const int AsianSessionEnd = 8; // 08:00 UTC
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create panel |
|
||||
//+------------------------------------------------------------------+
|
||||
void CreatePanel()
|
||||
{
|
||||
// Create panel background
|
||||
ObjectCreate(0, panelName, OBJ_RECTANGLE_LABEL, 0, 0, 0);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_XDISTANCE, PanelX);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_YDISTANCE, PanelY);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_XSIZE, panelWidth);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_YSIZE, panelHeight);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, PanelBackground);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_BORDER_TYPE, BORDER_FLAT);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_COLOR, PanelText);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_STYLE, STYLE_SOLID);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_WIDTH, 1);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_BACK, false);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_SELECTABLE, false);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_SELECTED, false);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_HIDDEN, true);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_ZORDER, 0);
|
||||
|
||||
// Create title label
|
||||
ObjectCreate(0, panelName + "Title", OBJ_LABEL, 0, 0, 0);
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_XDISTANCE, PanelX + 5);
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_YDISTANCE, PanelY + 5);
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_CORNER, CORNER_LEFT_UPPER);
|
||||
ObjectSetString(0, panelName + "Title", OBJPROP_TEXT, "RSI Reversal");
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_COLOR, PanelText);
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_FONTSIZE, 10);
|
||||
|
||||
// Create score labels
|
||||
CreateScoreLabel("RSI", "RSI: ", 0);
|
||||
CreateScoreLabel("Position", "Position: ", 1);
|
||||
CreateScoreLabel("Spread", "Spread: ", 2);
|
||||
CreateScoreLabel("Session", "Session: ", 3);
|
||||
CreateScoreLabel("SL", "Stop Loss: ", 4);
|
||||
CreateScoreLabel("TP", "Take Profit: ", 5);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create score label |
|
||||
//+------------------------------------------------------------------+
|
||||
void CreateScoreLabel(string name, string text, int index)
|
||||
{
|
||||
ObjectCreate(0, panelName + name, OBJ_LABEL, 0, 0, 0);
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_XDISTANCE, PanelX + 5);
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_YDISTANCE, PanelY + 30 + index * (labelHeight + labelSpacing));
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
|
||||
ObjectSetString(0, panelName + name, OBJPROP_TEXT, text);
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_COLOR, PanelText);
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_FONTSIZE, 8);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update panel values |
|
||||
//+------------------------------------------------------------------+
|
||||
void UpdatePanel(double rsi, string position, int spread, string session, double sl, double tp)
|
||||
{
|
||||
ObjectSetString(0, panelName + "RSI", OBJPROP_TEXT, "RSI: " + DoubleToString(rsi, 2));
|
||||
ObjectSetString(0, panelName + "Position", OBJPROP_TEXT, "Position: " + position);
|
||||
ObjectSetString(0, panelName + "Spread", OBJPROP_TEXT, "Spread: " + IntegerToString(spread) + " pips");
|
||||
ObjectSetString(0, panelName + "Session", OBJPROP_TEXT, "Session: " + session);
|
||||
ObjectSetString(0, panelName + "SL", OBJPROP_TEXT, "Stop Loss: " + IntegerToString(StopLossPips) + " pips");
|
||||
ObjectSetString(0, panelName + "TP", OBJPROP_TEXT, "Take Profit: " + IntegerToString(TakeProfitPips) + " pips");
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get current session name |
|
||||
//+------------------------------------------------------------------+
|
||||
string GetCurrentSession()
|
||||
{
|
||||
datetime currentTime = TimeCurrent();
|
||||
MqlDateTime timeStruct;
|
||||
TimeToStruct(currentTime, timeStruct);
|
||||
|
||||
if(timeStruct.hour >= AsianSessionStart && timeStruct.hour < AsianSessionEnd)
|
||||
return "Asian";
|
||||
else if(timeStruct.hour >= 8 && timeStruct.hour < 16)
|
||||
return "London";
|
||||
else if(timeStruct.hour >= 13 && timeStruct.hour < 21)
|
||||
return "New York";
|
||||
else
|
||||
return "Other";
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if trading is allowed |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IsTradingAllowed()
|
||||
{
|
||||
// Check if market is open
|
||||
if(!SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE) == SYMBOL_TRADE_MODE_FULL)
|
||||
{
|
||||
Print("Trading is not allowed for ", _Symbol);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough money
|
||||
if(AccountInfoDouble(ACCOUNT_MARGIN_FREE) <= 0)
|
||||
{
|
||||
Print("Not enough free margin");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
// Initialize RSI indicator
|
||||
rsiHandle = iRSI(_Symbol, PERIOD_M15, RSIPeriod, PRICE_CLOSE);
|
||||
|
||||
if(rsiHandle == INVALID_HANDLE)
|
||||
{
|
||||
Print("Failed to create RSI indicator handle");
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
|
||||
// Create panel
|
||||
CreatePanel();
|
||||
|
||||
Print("Expert Advisor initialized successfully");
|
||||
Print("Trading symbol: ", _Symbol);
|
||||
Print("Account balance: ", AccountInfoDouble(ACCOUNT_BALANCE));
|
||||
Print("Account leverage: ", AccountInfoInteger(ACCOUNT_LEVERAGE));
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
// Release indicator handles
|
||||
IndicatorRelease(rsiHandle);
|
||||
|
||||
// Remove panel objects
|
||||
ObjectsDeleteAll(0, panelName);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Close all trades for the current symbol |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CloseAllTrades(string reason = "")
|
||||
{
|
||||
bool allClosed = true;
|
||||
int totalPositions = PositionsTotal();
|
||||
|
||||
if(totalPositions == 0)
|
||||
return true;
|
||||
|
||||
Print("Attempting to close all positions", (reason != "" ? " - " + reason : ""));
|
||||
|
||||
for(int i = totalPositions - 1; i >= 0; i--)
|
||||
{
|
||||
if(PositionGetSymbol(i) == _Symbol)
|
||||
{
|
||||
// Try to close position with retry logic
|
||||
int retryCount = 0;
|
||||
bool positionClosed = false;
|
||||
|
||||
while(retryCount < 3 && !positionClosed)
|
||||
{
|
||||
if(trade.PositionClose(_Symbol))
|
||||
{
|
||||
Print("Position closed successfully");
|
||||
isPositionOpen = false;
|
||||
positionClosed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int error = GetLastError();
|
||||
Print("Failed to close position. Error: ", error, " Retry: ", retryCount + 1);
|
||||
|
||||
// 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)
|
||||
{
|
||||
Print("Failed to close position after all retries");
|
||||
allClosed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allClosed;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
// Check if trading is allowed
|
||||
if(!IsTradingAllowed())
|
||||
{
|
||||
Print("Trading is not allowed at the moment");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we're in Asian session
|
||||
if(!IsAsianSession())
|
||||
{
|
||||
Print("Not in Asian session");
|
||||
|
||||
// Close all positions if outside Asian session and CloseOutsideSession is true
|
||||
if(CloseOutsideSession && !sessionCloseAttempted)
|
||||
{
|
||||
CloseAllTrades("Outside Asian session");
|
||||
sessionCloseAttempted = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset the session close attempt flag when we enter Asian session
|
||||
sessionCloseAttempted = false;
|
||||
}
|
||||
|
||||
// Get current spread
|
||||
double spread = SymbolInfoDouble(_Symbol, SYMBOL_ASK) - SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
int spreadInPips = (int)(spread / _Point);
|
||||
|
||||
// Check if spread is too high
|
||||
if(spreadInPips > MaxSpread)
|
||||
{
|
||||
Print("Spread too high: ", spreadInPips, " pips");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get RSI value
|
||||
double rsi[];
|
||||
ArraySetAsSeries(rsi, true);
|
||||
|
||||
if(CopyBuffer(rsiHandle, 0, 0, 1, rsi) != 1)
|
||||
return;
|
||||
|
||||
// Get current prices
|
||||
double currentBid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
double currentAsk = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
|
||||
// Get position status
|
||||
string positionStatus = "None";
|
||||
for(int i = 0; i < PositionsTotal(); i++)
|
||||
{
|
||||
if(PositionGetSymbol(i) == _Symbol)
|
||||
{
|
||||
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
positionStatus = (posType == POSITION_TYPE_BUY) ? "Long" : "Short";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate stop loss and take profit levels
|
||||
double sl = 0;
|
||||
double tp = 0;
|
||||
|
||||
// Update panel
|
||||
UpdatePanel(rsi[0], positionStatus, spreadInPips, GetCurrentSession(), sl, tp);
|
||||
|
||||
// Check for open position
|
||||
bool hasOpenPosition = false;
|
||||
for(int i = 0; i < PositionsTotal(); i++)
|
||||
{
|
||||
if(PositionGetSymbol(i) == _Symbol)
|
||||
{
|
||||
hasOpenPosition = true;
|
||||
|
||||
// Get position details
|
||||
double positionProfit = PositionGetDouble(POSITION_PROFIT);
|
||||
double positionVolume = PositionGetDouble(POSITION_VOLUME);
|
||||
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
|
||||
// Check for RSI exit if enabled
|
||||
if(UseRSIExit)
|
||||
{
|
||||
bool shouldExit = false;
|
||||
|
||||
// For long positions, exit when RSI reaches or exceeds exit level
|
||||
if(posType == POSITION_TYPE_BUY && rsi[0] >= RSIExitLevel)
|
||||
{
|
||||
Print("Closing long position due to RSI exit. RSI: ", rsi[0], " Exit Level: ", RSIExitLevel);
|
||||
shouldExit = true;
|
||||
}
|
||||
// For short positions, exit when RSI reaches or falls below exit level
|
||||
else if(posType == POSITION_TYPE_SELL && rsi[0] <= RSIExitLevel)
|
||||
{
|
||||
Print("Closing short position due to RSI exit. RSI: ", rsi[0], " Exit Level: ", RSIExitLevel);
|
||||
shouldExit = true;
|
||||
}
|
||||
|
||||
if(shouldExit)
|
||||
{
|
||||
CloseAllTrades("RSI Exit");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for timeout
|
||||
if(TimeCurrent() - positionOpenTime > MaxDuration * 3600)
|
||||
{
|
||||
Print("Closing position due to timeout");
|
||||
CloseAllTrades("Timeout");
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no position is open, look for entry signals
|
||||
if(!hasOpenPosition)
|
||||
{
|
||||
// Place buy order if RSI is oversold
|
||||
if(rsi[0] <= OversoldLevel)
|
||||
{
|
||||
double sl = UseStopLoss ? currentBid - StopLossPips * _Point : 0;
|
||||
double tp = UseTakeProfit ? currentBid + TakeProfitPips * _Point : 0;
|
||||
|
||||
if(UseStopLoss && sl >= currentBid)
|
||||
return;
|
||||
if(UseTakeProfit && tp <= currentBid)
|
||||
return;
|
||||
|
||||
// Set trade parameters
|
||||
trade.SetDeviationInPoints(3);
|
||||
trade.SetTypeFilling(ORDER_FILLING_IOC);
|
||||
trade.SetExpertMagicNumber(123456);
|
||||
|
||||
// Place buy order using CTrade
|
||||
if(!trade.Buy(MaxLotSize, _Symbol, currentAsk, sl, tp, "RSI Buy"))
|
||||
{
|
||||
Print("Buy order failed. Error code: ", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Buy order placed. RSI: ", rsi[0]);
|
||||
isPositionOpen = true;
|
||||
positionOpenPrice = currentAsk;
|
||||
positionOpenTime = TimeCurrent();
|
||||
lastPositionType = POSITION_TYPE_BUY;
|
||||
}
|
||||
}
|
||||
// Place sell order if RSI is overbought
|
||||
else if(rsi[0] >= OverboughtLevel)
|
||||
{
|
||||
double sl = UseStopLoss ? currentAsk + StopLossPips * _Point : 0;
|
||||
double tp = UseTakeProfit ? currentAsk - TakeProfitPips * _Point : 0;
|
||||
|
||||
if(UseStopLoss && sl <= currentAsk)
|
||||
return;
|
||||
if(UseTakeProfit && tp >= currentAsk)
|
||||
return;
|
||||
|
||||
// Set trade parameters
|
||||
trade.SetDeviationInPoints(3);
|
||||
trade.SetTypeFilling(ORDER_FILLING_IOC);
|
||||
trade.SetExpertMagicNumber(123456);
|
||||
|
||||
// Place sell order using CTrade
|
||||
if(!trade.Sell(MaxLotSize, _Symbol, currentBid, sl, tp, "RSI Sell"))
|
||||
{
|
||||
Print("Sell order failed. Error code: ", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Sell order placed. RSI: ", rsi[0]);
|
||||
isPositionOpen = true;
|
||||
positionOpenPrice = currentBid;
|
||||
positionOpenTime = TimeCurrent();
|
||||
lastPositionType = POSITION_TYPE_SELL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 305 KiB |
@@ -0,0 +1,457 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| SimpleRSIReversalAUDUSD.mq5 |
|
||||
//| Copyright 2024, MetaQuotes Ltd. |
|
||||
//| https://www.mql5.com |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Copyright 2024, MetaQuotes Ltd."
|
||||
#property link "https://www.mql5.com"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
// Include trade class
|
||||
#include <Trade\Trade.mqh>
|
||||
|
||||
// Input parameters
|
||||
input int RSIPeriod = 14; // RSI period
|
||||
input double OverboughtLevel = 77; // Overbought level
|
||||
input double OversoldLevel = 10; // Oversold level
|
||||
input int TakeProfitPips = 116; // Take profit in pips
|
||||
input int StopLossPips = 247; // Stop loss in pips
|
||||
input double MaxLotSize = 0.1; // Maximum lot size
|
||||
input int MaxSpread = 1000; // Maximum allowed spread in pips
|
||||
input int MaxDuration = 67; // Maximum trade duration in hours
|
||||
input bool UseStopLoss = true; // Use stop loss
|
||||
input bool UseTakeProfit = false; // Use take profit
|
||||
input bool UseRSIExit = true; // Use RSI for exit
|
||||
input double RSIExitLevel = 40; // RSI level to exit (50 = neutral)
|
||||
input bool CloseOutsideSession = false; // Close trades outside Asian session
|
||||
input color PanelBackground = clrBlack; // Panel background color
|
||||
input color PanelText = clrWhite; // Panel text color
|
||||
input int PanelX = 10; // Panel X position
|
||||
input int PanelY = 20; // Panel Y position
|
||||
|
||||
// Global variables
|
||||
CTrade trade;
|
||||
int rsiHandle;
|
||||
bool isPositionOpen = false;
|
||||
double positionOpenPrice = 0;
|
||||
datetime positionOpenTime = 0;
|
||||
ENUM_POSITION_TYPE lastPositionType = POSITION_TYPE_BUY;
|
||||
bool sessionCloseAttempted = false; // Track if we've attempted to close positions for current session
|
||||
|
||||
// Panel objects
|
||||
string panelName = "RSIPanel";
|
||||
int panelWidth = 200;
|
||||
int panelHeight = 200;
|
||||
int labelHeight = 20;
|
||||
int labelSpacing = 5;
|
||||
|
||||
// Session times (UTC)
|
||||
const int AsianSessionStart = 0; // 00:00 UTC
|
||||
const int AsianSessionEnd = 8; // 08:00 UTC
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create panel |
|
||||
//+------------------------------------------------------------------+
|
||||
void CreatePanel()
|
||||
{
|
||||
// Create panel background
|
||||
ObjectCreate(0, panelName, OBJ_RECTANGLE_LABEL, 0, 0, 0);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_XDISTANCE, PanelX);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_YDISTANCE, PanelY);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_XSIZE, panelWidth);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_YSIZE, panelHeight);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_BGCOLOR, PanelBackground);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_BORDER_TYPE, BORDER_FLAT);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_COLOR, PanelText);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_STYLE, STYLE_SOLID);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_WIDTH, 1);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_BACK, false);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_SELECTABLE, false);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_SELECTED, false);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_HIDDEN, true);
|
||||
ObjectSetInteger(0, panelName, OBJPROP_ZORDER, 0);
|
||||
|
||||
// Create title label
|
||||
ObjectCreate(0, panelName + "Title", OBJ_LABEL, 0, 0, 0);
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_XDISTANCE, PanelX + 5);
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_YDISTANCE, PanelY + 5);
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_CORNER, CORNER_LEFT_UPPER);
|
||||
ObjectSetString(0, panelName + "Title", OBJPROP_TEXT, "RSI Reversal");
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_COLOR, PanelText);
|
||||
ObjectSetInteger(0, panelName + "Title", OBJPROP_FONTSIZE, 10);
|
||||
|
||||
// Create score labels
|
||||
CreateScoreLabel("RSI", "RSI: ", 0);
|
||||
CreateScoreLabel("Position", "Position: ", 1);
|
||||
CreateScoreLabel("Spread", "Spread: ", 2);
|
||||
CreateScoreLabel("Session", "Session: ", 3);
|
||||
CreateScoreLabel("SL", "Stop Loss: ", 4);
|
||||
CreateScoreLabel("TP", "Take Profit: ", 5);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create score label |
|
||||
//+------------------------------------------------------------------+
|
||||
void CreateScoreLabel(string name, string text, int index)
|
||||
{
|
||||
ObjectCreate(0, panelName + name, OBJ_LABEL, 0, 0, 0);
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_XDISTANCE, PanelX + 5);
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_YDISTANCE, PanelY + 30 + index * (labelHeight + labelSpacing));
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_CORNER, CORNER_LEFT_UPPER);
|
||||
ObjectSetString(0, panelName + name, OBJPROP_TEXT, text);
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_COLOR, PanelText);
|
||||
ObjectSetInteger(0, panelName + name, OBJPROP_FONTSIZE, 8);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Update panel values |
|
||||
//+------------------------------------------------------------------+
|
||||
void UpdatePanel(double rsi, string position, int spread, string session, double sl, double tp)
|
||||
{
|
||||
ObjectSetString(0, panelName + "RSI", OBJPROP_TEXT, "RSI: " + DoubleToString(rsi, 2));
|
||||
ObjectSetString(0, panelName + "Position", OBJPROP_TEXT, "Position: " + position);
|
||||
ObjectSetString(0, panelName + "Spread", OBJPROP_TEXT, "Spread: " + IntegerToString(spread) + " pips");
|
||||
ObjectSetString(0, panelName + "Session", OBJPROP_TEXT, "Session: " + session);
|
||||
ObjectSetString(0, panelName + "SL", OBJPROP_TEXT, "Stop Loss: " + IntegerToString(StopLossPips) + " pips");
|
||||
ObjectSetString(0, panelName + "TP", OBJPROP_TEXT, "Take Profit: " + IntegerToString(TakeProfitPips) + " pips");
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get current session name |
|
||||
//+------------------------------------------------------------------+
|
||||
string GetCurrentSession()
|
||||
{
|
||||
datetime currentTime = TimeCurrent();
|
||||
MqlDateTime timeStruct;
|
||||
TimeToStruct(currentTime, timeStruct);
|
||||
|
||||
if(timeStruct.hour >= AsianSessionStart && timeStruct.hour < AsianSessionEnd)
|
||||
return "Asian";
|
||||
else if(timeStruct.hour >= 8 && timeStruct.hour < 16)
|
||||
return "London";
|
||||
else if(timeStruct.hour >= 13 && timeStruct.hour < 21)
|
||||
return "New York";
|
||||
else
|
||||
return "Other";
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if trading is allowed |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IsTradingAllowed()
|
||||
{
|
||||
// Check if market is open
|
||||
if(!SymbolInfoInteger(_Symbol, SYMBOL_TRADE_MODE) == SYMBOL_TRADE_MODE_FULL)
|
||||
{
|
||||
Print("Trading is not allowed for ", _Symbol);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if we have enough money
|
||||
if(AccountInfoDouble(ACCOUNT_MARGIN_FREE) <= 0)
|
||||
{
|
||||
Print("Not enough free margin");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
// Initialize RSI indicator
|
||||
rsiHandle = iRSI(_Symbol, PERIOD_M15, RSIPeriod, PRICE_CLOSE);
|
||||
|
||||
if(rsiHandle == INVALID_HANDLE)
|
||||
{
|
||||
Print("Failed to create RSI indicator handle");
|
||||
return(INIT_FAILED);
|
||||
}
|
||||
|
||||
// Create panel
|
||||
CreatePanel();
|
||||
|
||||
Print("Expert Advisor initialized successfully");
|
||||
Print("Trading symbol: ", _Symbol);
|
||||
Print("Account balance: ", AccountInfoDouble(ACCOUNT_BALANCE));
|
||||
Print("Account leverage: ", AccountInfoInteger(ACCOUNT_LEVERAGE));
|
||||
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
// Release indicator handles
|
||||
IndicatorRelease(rsiHandle);
|
||||
|
||||
// Remove panel objects
|
||||
ObjectsDeleteAll(0, panelName);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Close all trades for the current symbol |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CloseAllTrades(string reason = "")
|
||||
{
|
||||
bool allClosed = true;
|
||||
int totalPositions = PositionsTotal();
|
||||
|
||||
if(totalPositions == 0)
|
||||
return true;
|
||||
|
||||
Print("Attempting to close all positions", (reason != "" ? " - " + reason : ""));
|
||||
|
||||
for(int i = totalPositions - 1; i >= 0; i--)
|
||||
{
|
||||
if(PositionGetSymbol(i) == _Symbol)
|
||||
{
|
||||
// Try to close position with retry logic
|
||||
int retryCount = 0;
|
||||
bool positionClosed = false;
|
||||
|
||||
while(retryCount < 3 && !positionClosed)
|
||||
{
|
||||
if(trade.PositionClose(_Symbol))
|
||||
{
|
||||
Print("Position closed successfully");
|
||||
isPositionOpen = false;
|
||||
positionClosed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
int error = GetLastError();
|
||||
Print("Failed to close position. Error: ", error, " Retry: ", retryCount + 1);
|
||||
|
||||
// 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)
|
||||
{
|
||||
Print("Failed to close position after all retries");
|
||||
allClosed = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allClosed;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick()
|
||||
{
|
||||
// Check if trading is allowed
|
||||
if(!IsTradingAllowed())
|
||||
{
|
||||
Print("Trading is not allowed at the moment");
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we're in Asian session
|
||||
if(!IsAsianSession())
|
||||
{
|
||||
Print("Not in Asian session");
|
||||
|
||||
// Close all positions if outside Asian session and CloseOutsideSession is true
|
||||
if(CloseOutsideSession && !sessionCloseAttempted)
|
||||
{
|
||||
CloseAllTrades("Outside Asian session");
|
||||
sessionCloseAttempted = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Reset the session close attempt flag when we enter Asian session
|
||||
sessionCloseAttempted = false;
|
||||
}
|
||||
|
||||
// Get current spread
|
||||
double spread = SymbolInfoDouble(_Symbol, SYMBOL_ASK) - SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
int spreadInPips = (int)(spread / _Point);
|
||||
|
||||
// Check if spread is too high
|
||||
if(spreadInPips > MaxSpread)
|
||||
{
|
||||
Print("Spread too high: ", spreadInPips, " pips");
|
||||
return;
|
||||
}
|
||||
|
||||
// Get RSI value
|
||||
double rsi[];
|
||||
ArraySetAsSeries(rsi, true);
|
||||
|
||||
if(CopyBuffer(rsiHandle, 0, 0, 1, rsi) != 1)
|
||||
return;
|
||||
|
||||
// Get current prices
|
||||
double currentBid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
double currentAsk = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
|
||||
// Get position status
|
||||
string positionStatus = "None";
|
||||
for(int i = 0; i < PositionsTotal(); i++)
|
||||
{
|
||||
if(PositionGetSymbol(i) == _Symbol)
|
||||
{
|
||||
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
positionStatus = (posType == POSITION_TYPE_BUY) ? "Long" : "Short";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate stop loss and take profit levels
|
||||
double sl = 0;
|
||||
double tp = 0;
|
||||
|
||||
// Update panel
|
||||
UpdatePanel(rsi[0], positionStatus, spreadInPips, GetCurrentSession(), sl, tp);
|
||||
|
||||
// Check for open position
|
||||
bool hasOpenPosition = false;
|
||||
for(int i = 0; i < PositionsTotal(); i++)
|
||||
{
|
||||
if(PositionGetSymbol(i) == _Symbol)
|
||||
{
|
||||
hasOpenPosition = true;
|
||||
|
||||
// Get position details
|
||||
double positionProfit = PositionGetDouble(POSITION_PROFIT);
|
||||
double positionVolume = PositionGetDouble(POSITION_VOLUME);
|
||||
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
|
||||
// Check for RSI exit if enabled
|
||||
if(UseRSIExit)
|
||||
{
|
||||
bool shouldExit = false;
|
||||
|
||||
// For long positions, exit when RSI reaches or exceeds exit level
|
||||
if(posType == POSITION_TYPE_BUY && rsi[0] >= RSIExitLevel)
|
||||
{
|
||||
Print("Closing long position due to RSI exit. RSI: ", rsi[0], " Exit Level: ", RSIExitLevel);
|
||||
shouldExit = true;
|
||||
}
|
||||
// For short positions, exit when RSI reaches or falls below exit level
|
||||
else if(posType == POSITION_TYPE_SELL && rsi[0] <= RSIExitLevel)
|
||||
{
|
||||
Print("Closing short position due to RSI exit. RSI: ", rsi[0], " Exit Level: ", RSIExitLevel);
|
||||
shouldExit = true;
|
||||
}
|
||||
|
||||
if(shouldExit)
|
||||
{
|
||||
CloseAllTrades("RSI Exit");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check for timeout
|
||||
if(TimeCurrent() - positionOpenTime > MaxDuration * 3600)
|
||||
{
|
||||
Print("Closing position due to timeout");
|
||||
CloseAllTrades("Timeout");
|
||||
return;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no position is open, look for entry signals
|
||||
if(!hasOpenPosition)
|
||||
{
|
||||
// Place buy order if RSI is oversold
|
||||
if(rsi[0] <= OversoldLevel)
|
||||
{
|
||||
double sl = UseStopLoss ? currentBid - StopLossPips * _Point : 0;
|
||||
double tp = UseTakeProfit ? currentBid + TakeProfitPips * _Point : 0;
|
||||
|
||||
if(UseStopLoss && sl >= currentBid)
|
||||
return;
|
||||
if(UseTakeProfit && tp <= currentBid)
|
||||
return;
|
||||
|
||||
// Set trade parameters
|
||||
trade.SetDeviationInPoints(3);
|
||||
trade.SetTypeFilling(ORDER_FILLING_IOC);
|
||||
trade.SetExpertMagicNumber(123456);
|
||||
|
||||
// Place buy order using CTrade
|
||||
if(!trade.Buy(MaxLotSize, _Symbol, currentAsk, sl, tp, "RSI Buy"))
|
||||
{
|
||||
Print("Buy order failed. Error code: ", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Buy order placed. RSI: ", rsi[0]);
|
||||
isPositionOpen = true;
|
||||
positionOpenPrice = currentAsk;
|
||||
positionOpenTime = TimeCurrent();
|
||||
lastPositionType = POSITION_TYPE_BUY;
|
||||
}
|
||||
}
|
||||
// Place sell order if RSI is overbought
|
||||
else if(rsi[0] >= OverboughtLevel)
|
||||
{
|
||||
double sl = UseStopLoss ? currentAsk + StopLossPips * _Point : 0;
|
||||
double tp = UseTakeProfit ? currentAsk - TakeProfitPips * _Point : 0;
|
||||
|
||||
if(UseStopLoss && sl <= currentAsk)
|
||||
return;
|
||||
if(UseTakeProfit && tp >= currentAsk)
|
||||
return;
|
||||
|
||||
// Set trade parameters
|
||||
trade.SetDeviationInPoints(3);
|
||||
trade.SetTypeFilling(ORDER_FILLING_IOC);
|
||||
trade.SetExpertMagicNumber(123456);
|
||||
|
||||
// Place sell order using CTrade
|
||||
if(!trade.Sell(MaxLotSize, _Symbol, currentBid, sl, tp, "RSI Sell"))
|
||||
{
|
||||
Print("Sell order failed. Error code: ", GetLastError());
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Sell order placed. RSI: ", rsi[0]);
|
||||
isPositionOpen = true;
|
||||
positionOpenPrice = currentBid;
|
||||
positionOpenTime = TimeCurrent();
|
||||
lastPositionType = POSITION_TYPE_SELL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 295 KiB |
Reference in New Issue
Block a user