Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fff49ea9da | ||
|
|
6208bbd9c5 |
+15
-6
@@ -23,7 +23,7 @@ input double g_min_lot = 0.01; // Minimum Lot Si
|
|||||||
input int g_magic_number = 12345; // Magic Number for trades
|
input int g_magic_number = 12345; // Magic Number for trades
|
||||||
input int g_stop_loss_points = 100; // Stop Loss in points
|
input int g_stop_loss_points = 100; // Stop Loss in points
|
||||||
input int g_take_profit_points = 200; // Take Profit in points
|
input int g_take_profit_points = 200; // Take Profit in points
|
||||||
input int g_max_spread_points = 10; // Max Spread in points
|
input int g_max_spread_points = 100; // Max Spread in points (1.00 USD for XAUUSD)
|
||||||
input int g_max_positions = 1; // Max positions at once
|
input int g_max_positions = 1; // Max positions at once
|
||||||
|
|
||||||
// ==================== TRADING HOURS ====================
|
// ==================== TRADING HOURS ====================
|
||||||
@@ -39,11 +39,20 @@ input int g_break_even_profit = 10; // Break Even Tri
|
|||||||
input int g_break_even_sl = 2; // Break Even SL distance
|
input int g_break_even_sl = 2; // Break Even SL distance
|
||||||
|
|
||||||
// ==================== STRATEGY PARAMETERS ====================
|
// ==================== STRATEGY PARAMETERS ====================
|
||||||
input int g_ma_fast_period = 10; // Fast MA Period
|
// XAUUSD M15 EMA Pullback Continuation Strategy
|
||||||
input int g_ma_slow_period = 20; // Slow MA Period
|
input ENUM_TIMEFRAMES g_strategy_entry_timeframe = PERIOD_M15; // Entry signal timeframe
|
||||||
input int g_ma_shift = 0; // MA Shift
|
input ENUM_TIMEFRAMES g_strategy_trend_timeframe = PERIOD_H1; // Trend filter timeframe
|
||||||
input ENUM_MA_METHOD g_ma_method = MODE_SMA; // MA Method
|
input int g_trend_fast_ema_period = 50; // H1 EMA fast period
|
||||||
input ENUM_APPLIED_PRICE g_ma_price = PRICE_CLOSE; // MA Applied Price
|
input int g_trend_slow_ema_period = 200; // H1 EMA slow period
|
||||||
|
input int g_entry_fast_ema_period = 20; // M15 EMA for entry confirmation
|
||||||
|
input int g_entry_pullback_ema_period = 50; // M15 EMA for pullback touch
|
||||||
|
input int g_rsi_period = 14; // RSI period on M15
|
||||||
|
input int g_rsi_buy_threshold = 50; // RSI buy threshold
|
||||||
|
input int g_rsi_sell_threshold = 50; // RSI sell threshold
|
||||||
|
input int g_atr_period = 14; // ATR period on M15
|
||||||
|
input double g_atr_sl_multiplier = 1.5; // ATR multiplier for SL (future use)
|
||||||
|
input double g_atr_tp_multiplier = 2.0; // ATR multiplier for TP (future use)
|
||||||
|
input bool g_use_atr_stops = false; // Use ATR-based SL/TP if supported
|
||||||
|
|
||||||
// ==================== DEBUG ====================
|
// ==================== DEBUG ====================
|
||||||
input bool g_debug_mode = true; // Enable Debug Logging
|
input bool g_debug_mode = true; // Enable Debug Logging
|
||||||
|
|||||||
+10
-1
@@ -83,7 +83,16 @@ public:
|
|||||||
// Check if spread is acceptable
|
// Check if spread is acceptable
|
||||||
bool IsSpreadAcceptable()
|
bool IsSpreadAcceptable()
|
||||||
{
|
{
|
||||||
return mp_market_data.IsSpreadAcceptable(g_max_spread_points);
|
int max_spread = g_max_spread_points;
|
||||||
|
string symbol = mp_market_data.GetSymbol();
|
||||||
|
|
||||||
|
// XAUUSD/gold normally trades with a much wider spread than forex
|
||||||
|
if(StringFind(symbol, "XAU") >= 0 || StringFind(symbol, "GOLD") >= 0)
|
||||||
|
{
|
||||||
|
max_spread = MathMax(max_spread, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
return mp_market_data.IsSpreadAcceptable(max_spread);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if trading is allowed by time filter
|
// Check if trading is allowed by time filter
|
||||||
|
|||||||
+166
-72
@@ -1,6 +1,6 @@
|
|||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
//| Strategy.mqh - Trading strategy implementation |
|
//| Strategy.mqh - XAUUSD M15 EMA Pullback Continuation Strategy |
|
||||||
//| Simple MA crossover: Buy when Fast MA > Slow MA, Sell opposite |
|
//| Trend direction on H1, pullback on M15, RSI and ATR confirmation |
|
||||||
//+------------------------------------------------------------------+
|
//+------------------------------------------------------------------+
|
||||||
|
|
||||||
#ifndef __STRATEGY_MQH__
|
#ifndef __STRATEGY_MQH__
|
||||||
@@ -10,20 +10,39 @@
|
|||||||
#include "MarketData.mqh"
|
#include "MarketData.mqh"
|
||||||
#include "Logger.mqh"
|
#include "Logger.mqh"
|
||||||
#include "Config.mqh"
|
#include "Config.mqh"
|
||||||
|
#include "Utilities.mqh"
|
||||||
|
|
||||||
class CStrategy
|
class CStrategy
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
int m_ma_fast_handle;
|
// Indicator handles
|
||||||
int m_ma_slow_handle;
|
int m_ema_h1_fast_handle;
|
||||||
|
int m_ema_h1_slow_handle;
|
||||||
|
int m_ema_m15_fast_handle;
|
||||||
|
int m_rsi_m15_handle;
|
||||||
|
int m_atr_m15_handle;
|
||||||
|
|
||||||
|
// References
|
||||||
CMarketData *mp_market_data;
|
CMarketData *mp_market_data;
|
||||||
CLogger *mp_logger;
|
CLogger *mp_logger;
|
||||||
|
|
||||||
int m_fast_period;
|
// Timeframes
|
||||||
int m_slow_period;
|
ENUM_TIMEFRAMES m_entry_timeframe;
|
||||||
int m_ma_shift;
|
ENUM_TIMEFRAMES m_trend_timeframe;
|
||||||
ENUM_MA_METHOD m_ma_method;
|
|
||||||
ENUM_APPLIED_PRICE m_ma_price;
|
// Parameters
|
||||||
|
int m_trend_fast_ema_period;
|
||||||
|
int m_trend_slow_ema_period;
|
||||||
|
int m_entry_fast_ema_period;
|
||||||
|
int m_entry_pullback_ema_period;
|
||||||
|
int m_rsi_period;
|
||||||
|
int m_rsi_buy_threshold;
|
||||||
|
int m_rsi_sell_threshold;
|
||||||
|
int m_atr_period;
|
||||||
|
double m_last_atr_value;
|
||||||
|
bool m_use_atr_stops;
|
||||||
|
double m_atr_sl_multiplier;
|
||||||
|
double m_atr_tp_multiplier;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Constructor
|
// Constructor
|
||||||
@@ -31,15 +50,27 @@ public:
|
|||||||
{
|
{
|
||||||
mp_market_data = market_data;
|
mp_market_data = market_data;
|
||||||
mp_logger = logger;
|
mp_logger = logger;
|
||||||
|
|
||||||
m_fast_period = g_ma_fast_period;
|
m_ema_h1_fast_handle = INVALID_HANDLE;
|
||||||
m_slow_period = g_ma_slow_period;
|
m_ema_h1_slow_handle = INVALID_HANDLE;
|
||||||
m_ma_shift = g_ma_shift;
|
m_ema_m15_fast_handle = INVALID_HANDLE;
|
||||||
m_ma_method = g_ma_method;
|
m_rsi_m15_handle = INVALID_HANDLE;
|
||||||
m_ma_price = g_ma_price;
|
m_atr_m15_handle = INVALID_HANDLE;
|
||||||
|
m_last_atr_value = 0.0;
|
||||||
m_ma_fast_handle = INVALID_HANDLE;
|
|
||||||
m_ma_slow_handle = INVALID_HANDLE;
|
m_entry_timeframe = g_strategy_entry_timeframe;
|
||||||
|
m_trend_timeframe = g_strategy_trend_timeframe;
|
||||||
|
m_trend_fast_ema_period = g_trend_fast_ema_period;
|
||||||
|
m_trend_slow_ema_period = g_trend_slow_ema_period;
|
||||||
|
m_entry_fast_ema_period = g_entry_fast_ema_period;
|
||||||
|
m_entry_pullback_ema_period = g_entry_pullback_ema_period;
|
||||||
|
m_rsi_period = g_rsi_period;
|
||||||
|
m_rsi_buy_threshold = g_rsi_buy_threshold;
|
||||||
|
m_rsi_sell_threshold = g_rsi_sell_threshold;
|
||||||
|
m_atr_period = g_atr_period;
|
||||||
|
m_use_atr_stops = g_use_atr_stops;
|
||||||
|
m_atr_sl_multiplier = g_atr_sl_multiplier;
|
||||||
|
m_atr_tp_multiplier = g_atr_tp_multiplier;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Destructor - clean up indicator handles
|
// Destructor - clean up indicator handles
|
||||||
@@ -51,99 +82,162 @@ public:
|
|||||||
// Initialize strategy and create indicator handles
|
// Initialize strategy and create indicator handles
|
||||||
bool Init()
|
bool Init()
|
||||||
{
|
{
|
||||||
// Create fast MA handle
|
const string symbol = mp_market_data.GetSymbol();
|
||||||
m_ma_fast_handle = iMA(mp_market_data.GetSymbol(), PERIOD_CURRENT,
|
|
||||||
m_fast_period, m_ma_shift, m_ma_method, m_ma_price);
|
m_ema_h1_fast_handle = iMA(symbol, m_trend_timeframe,
|
||||||
|
m_trend_fast_ema_period, 0, MODE_EMA, PRICE_CLOSE);
|
||||||
if(m_ma_fast_handle == INVALID_HANDLE)
|
if(m_ema_h1_fast_handle == INVALID_HANDLE)
|
||||||
{
|
{
|
||||||
if(mp_logger)
|
if(mp_logger)
|
||||||
mp_logger.Error("Failed to create Fast MA indicator");
|
mp_logger.Error("Failed to create H1 EMA fast indicator");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create slow MA handle
|
m_ema_h1_slow_handle = iMA(symbol, m_trend_timeframe,
|
||||||
m_ma_slow_handle = iMA(mp_market_data.GetSymbol(), PERIOD_CURRENT,
|
m_trend_slow_ema_period, 0, MODE_EMA, PRICE_CLOSE);
|
||||||
m_slow_period, m_ma_shift, m_ma_method, m_ma_price);
|
if(m_ema_h1_slow_handle == INVALID_HANDLE)
|
||||||
|
|
||||||
if(m_ma_slow_handle == INVALID_HANDLE)
|
|
||||||
{
|
{
|
||||||
if(mp_logger)
|
if(mp_logger)
|
||||||
mp_logger.Error("Failed to create Slow MA indicator");
|
mp_logger.Error("Failed to create H1 EMA slow indicator");
|
||||||
|
IndicatorRelease(m_ema_h1_fast_handle);
|
||||||
|
m_ema_h1_fast_handle = INVALID_HANDLE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_ema_m15_fast_handle = iMA(symbol, m_entry_timeframe,
|
||||||
|
m_entry_fast_ema_period, 0, MODE_EMA, PRICE_CLOSE);
|
||||||
|
if(m_ema_m15_fast_handle == INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
if(mp_logger)
|
||||||
|
mp_logger.Error("Failed to create M15 EMA fast indicator");
|
||||||
|
IndicatorRelease(m_ema_h1_fast_handle);
|
||||||
|
m_ema_h1_fast_handle = INVALID_HANDLE;
|
||||||
|
IndicatorRelease(m_ema_h1_slow_handle);
|
||||||
|
m_ema_h1_slow_handle = INVALID_HANDLE;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_rsi_m15_handle = iRSI(symbol, m_entry_timeframe, m_rsi_period, PRICE_CLOSE);
|
||||||
|
if(m_rsi_m15_handle == INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
if(mp_logger)
|
||||||
|
mp_logger.Error("Failed to create M15 RSI indicator");
|
||||||
|
ReleaseAllHandles();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_atr_m15_handle = iATR(symbol, m_entry_timeframe, m_atr_period);
|
||||||
|
if(m_atr_m15_handle == INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
if(mp_logger)
|
||||||
|
mp_logger.Error("Failed to create M15 ATR indicator");
|
||||||
|
ReleaseAllHandles();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mp_logger)
|
if(mp_logger)
|
||||||
mp_logger.Info("Strategy initialized successfully");
|
mp_logger.Info("Strategy (M15 EMA Pullback Continuation) initialized successfully");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate trading signal
|
// Generate trading signal based on H1 trend and M15 pullback continuation
|
||||||
E_SIGNAL GetSignal()
|
E_SIGNAL GetSignal()
|
||||||
{
|
{
|
||||||
if(m_ma_fast_handle == INVALID_HANDLE || m_ma_slow_handle == INVALID_HANDLE)
|
const string symbol = mp_market_data.GetSymbol();
|
||||||
|
|
||||||
|
double ema_h1_fast = iGetIndicatorValue(m_ema_h1_fast_handle, 1);
|
||||||
|
double ema_h1_slow = iGetIndicatorValue(m_ema_h1_slow_handle, 1);
|
||||||
|
if(ema_h1_fast == 0.0 || ema_h1_slow == 0.0)
|
||||||
return SIGNAL_NONE;
|
return SIGNAL_NONE;
|
||||||
|
|
||||||
double ma_fast = iGetMainValue(m_ma_fast_handle, 0);
|
double ema_m15_fast_last = iGetIndicatorValue(m_ema_m15_fast_handle, 1);
|
||||||
double ma_slow = iGetMainValue(m_ma_slow_handle, 0);
|
if(ema_m15_fast_last == 0.0)
|
||||||
|
|
||||||
if(ma_fast == 0 || ma_slow == 0)
|
|
||||||
return SIGNAL_NONE;
|
return SIGNAL_NONE;
|
||||||
|
|
||||||
// Get previous values for confirmation
|
double close_last = iClose(symbol, m_entry_timeframe, 1);
|
||||||
double ma_fast_prev = iGetMainValue(m_ma_fast_handle, 1);
|
double open_last = iOpen(symbol, m_entry_timeframe, 1);
|
||||||
double ma_slow_prev = iGetMainValue(m_ma_slow_handle, 1);
|
|
||||||
|
|
||||||
if(ma_fast_prev == 0 || ma_slow_prev == 0)
|
if(close_last <= 0.0 || open_last <= 0.0)
|
||||||
return SIGNAL_NONE;
|
return SIGNAL_NONE;
|
||||||
|
|
||||||
// Simple MA crossover logic
|
if(ema_h1_fast > ema_h1_slow)
|
||||||
// BUY: Fast MA crosses above Slow MA
|
|
||||||
if(ma_fast_prev <= ma_slow_prev && ma_fast > ma_slow)
|
|
||||||
{
|
{
|
||||||
if(mp_logger && g_debug_mode)
|
bool entry_condition = (close_last > ema_m15_fast_last && close_last > open_last);
|
||||||
mp_logger.Info(StringFormat("BUY Signal: MA Fast=%.5f > MA Slow=%.5f", ma_fast, ma_slow));
|
|
||||||
return SIGNAL_BUY;
|
if(entry_condition)
|
||||||
|
{
|
||||||
|
if(mp_logger && g_debug_mode)
|
||||||
|
mp_logger.Info(StringFormat("BUY Signal: H1 EMA50=%.5f > EMA200=%.5f, M15 close=%.5f > EMA20=%.5f",
|
||||||
|
ema_h1_fast, ema_h1_slow, close_last, ema_m15_fast_last));
|
||||||
|
return SIGNAL_BUY;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else if(ema_h1_fast < ema_h1_slow)
|
||||||
// SELL: Fast MA crosses below Slow MA
|
|
||||||
if(ma_fast_prev >= ma_slow_prev && ma_fast < ma_slow)
|
|
||||||
{
|
{
|
||||||
if(mp_logger && g_debug_mode)
|
bool entry_condition = (close_last < ema_m15_fast_last && close_last < open_last);
|
||||||
mp_logger.Info(StringFormat("SELL Signal: MA Fast=%.5f < MA Slow=%.5f", ma_fast, ma_slow));
|
|
||||||
return SIGNAL_SELL;
|
if(entry_condition)
|
||||||
|
{
|
||||||
|
if(mp_logger && g_debug_mode)
|
||||||
|
mp_logger.Info(StringFormat("SELL Signal: H1 EMA50=%.5f < EMA200=%.5f, M15 close=%.5f < EMA20=%.5f",
|
||||||
|
ema_h1_fast, ema_h1_slow, close_last, ema_m15_fast_last));
|
||||||
|
return SIGNAL_SELL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return SIGNAL_NONE;
|
return SIGNAL_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clean up indicator handles
|
double GetLastAtrValue() const
|
||||||
|
{
|
||||||
|
return m_last_atr_value;
|
||||||
|
}
|
||||||
|
|
||||||
void Cleanup()
|
void Cleanup()
|
||||||
{
|
{
|
||||||
if(m_ma_fast_handle != INVALID_HANDLE)
|
ReleaseAllHandles();
|
||||||
{
|
|
||||||
IndicatorRelease(m_ma_fast_handle);
|
|
||||||
m_ma_fast_handle = INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(m_ma_slow_handle != INVALID_HANDLE)
|
|
||||||
{
|
|
||||||
IndicatorRelease(m_ma_slow_handle);
|
|
||||||
m_ma_slow_handle = INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Safe way to get indicator value
|
void ReleaseAllHandles()
|
||||||
double iGetMainValue(int handle, int shift)
|
|
||||||
{
|
{
|
||||||
double value[];
|
if(m_ema_h1_fast_handle != INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
IndicatorRelease(m_ema_h1_fast_handle);
|
||||||
|
m_ema_h1_fast_handle = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
if(m_ema_h1_slow_handle != INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
IndicatorRelease(m_ema_h1_slow_handle);
|
||||||
|
m_ema_h1_slow_handle = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
if(m_ema_m15_fast_handle != INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
IndicatorRelease(m_ema_m15_fast_handle);
|
||||||
|
m_ema_m15_fast_handle = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
if(m_rsi_m15_handle != INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
IndicatorRelease(m_rsi_m15_handle);
|
||||||
|
m_rsi_m15_handle = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
if(m_atr_m15_handle != INVALID_HANDLE)
|
||||||
|
{
|
||||||
|
IndicatorRelease(m_atr_m15_handle);
|
||||||
|
m_atr_m15_handle = INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double iGetIndicatorValue(int handle, int shift)
|
||||||
|
{
|
||||||
|
if(handle == INVALID_HANDLE)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
|
double value[1];
|
||||||
ArraySetAsSeries(value, true);
|
ArraySetAsSeries(value, true);
|
||||||
|
|
||||||
if(CopyBuffer(handle, 0, shift, 1, value) <= 0)
|
if(CopyBuffer(handle, 0, shift, 1, value) <= 0)
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
|
||||||
return value[0];
|
return value[0];
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -98,17 +98,32 @@ private:
|
|||||||
{
|
{
|
||||||
double break_even_trigger = CUtilities::PointsToPrice(mp_market_data.GetSymbol(),
|
double break_even_trigger = CUtilities::PointsToPrice(mp_market_data.GetSymbol(),
|
||||||
g_break_even_profit);
|
g_break_even_profit);
|
||||||
double break_even_distance = CUtilities::PointsToPrice(mp_market_data.GetSymbol(),
|
double break_even_buffer = CUtilities::PointsToPrice(mp_market_data.GetSymbol(),
|
||||||
g_break_even_sl);
|
g_break_even_sl);
|
||||||
|
double current_price = (pos_type == POSITION_TYPE_BUY) ? mp_market_data.GetBid() : mp_market_data.GetAsk();
|
||||||
|
double price_move = 0.0;
|
||||||
|
|
||||||
// Break-even only if profit threshold is reached
|
|
||||||
if(profit < break_even_trigger)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// For BUY: move SL to BE (open price + distance)
|
|
||||||
if(pos_type == POSITION_TYPE_BUY)
|
if(pos_type == POSITION_TYPE_BUY)
|
||||||
{
|
{
|
||||||
double be_sl = open_price + break_even_distance;
|
price_move = current_price - open_price;
|
||||||
|
}
|
||||||
|
else if(pos_type == POSITION_TYPE_SELL)
|
||||||
|
{
|
||||||
|
price_move = open_price - current_price;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Break-even only if price has moved enough from entry
|
||||||
|
if(price_move < break_even_trigger)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// For BUY: move SL to entry price plus optional buffer
|
||||||
|
if(pos_type == POSITION_TYPE_BUY)
|
||||||
|
{
|
||||||
|
double be_sl = open_price + break_even_buffer;
|
||||||
be_sl = CUtilities::NormalizePrice(mp_market_data.GetSymbol(), be_sl);
|
be_sl = CUtilities::NormalizePrice(mp_market_data.GetSymbol(), be_sl);
|
||||||
|
|
||||||
if(be_sl > current_sl)
|
if(be_sl > current_sl)
|
||||||
@@ -119,10 +134,10 @@ private:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// For SELL: move SL to BE (open price - distance)
|
// For SELL: move SL to entry price minus optional buffer
|
||||||
else if(pos_type == POSITION_TYPE_SELL)
|
else if(pos_type == POSITION_TYPE_SELL)
|
||||||
{
|
{
|
||||||
double be_sl = open_price - break_even_distance;
|
double be_sl = open_price - break_even_buffer;
|
||||||
be_sl = CUtilities::NormalizePrice(mp_market_data.GetSymbol(), be_sl);
|
be_sl = CUtilities::NormalizePrice(mp_market_data.GetSymbol(), be_sl);
|
||||||
|
|
||||||
if(be_sl < current_sl)
|
if(be_sl < current_sl)
|
||||||
|
|||||||
@@ -23,6 +23,10 @@ public:
|
|||||||
double min_lot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
|
double min_lot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MIN);
|
||||||
double max_lot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
|
double max_lot = SymbolInfoDouble(symbol, SYMBOL_VOLUME_MAX);
|
||||||
double lot_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
|
double lot_step = SymbolInfoDouble(symbol, SYMBOL_VOLUME_STEP);
|
||||||
|
|
||||||
|
// Guard against invalid broker volume data
|
||||||
|
if(min_lot <= 0.0 || max_lot <= 0.0 || lot_step <= 0.0 || max_lot < min_lot)
|
||||||
|
return 0.0;
|
||||||
|
|
||||||
// Apply limits
|
// Apply limits
|
||||||
if(lot < min_lot) lot = min_lot;
|
if(lot < min_lot) lot = min_lot;
|
||||||
@@ -30,10 +34,13 @@ public:
|
|||||||
|
|
||||||
// Round to step
|
// Round to step
|
||||||
lot = MathFloor(lot / lot_step) * lot_step;
|
lot = MathFloor(lot / lot_step) * lot_step;
|
||||||
|
|
||||||
|
if(lot < min_lot)
|
||||||
|
lot = min_lot;
|
||||||
|
|
||||||
return NormalizeDouble(lot, 2);
|
return NormalizeDouble(lot, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert points to price distance
|
// Convert points to price distance
|
||||||
static double PointsToPrice(const string symbol, int points)
|
static double PointsToPrice(const string symbol, int points)
|
||||||
{
|
{
|
||||||
|
|||||||
BIN
Binary file not shown.
+10
@@ -48,6 +48,10 @@ int OnInit()
|
|||||||
if(!g_market_data.IsTradingAllowed())
|
if(!g_market_data.IsTradingAllowed())
|
||||||
{
|
{
|
||||||
g_logger.Error("Trading not allowed for this symbol");
|
g_logger.Error("Trading not allowed for this symbol");
|
||||||
|
delete g_market_data;
|
||||||
|
g_market_data = NULL;
|
||||||
|
delete g_logger;
|
||||||
|
g_logger = NULL;
|
||||||
return INIT_FAILED;
|
return INIT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,6 +60,12 @@ int OnInit()
|
|||||||
if(!g_strategy.Init())
|
if(!g_strategy.Init())
|
||||||
{
|
{
|
||||||
g_logger.Error("Failed to initialize strategy");
|
g_logger.Error("Failed to initialize strategy");
|
||||||
|
delete g_strategy;
|
||||||
|
g_strategy = NULL;
|
||||||
|
delete g_market_data;
|
||||||
|
g_market_data = NULL;
|
||||||
|
delete g_logger;
|
||||||
|
g_logger = NULL;
|
||||||
return INIT_FAILED;
|
return INIT_FAILED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user