128 lines
4.7 KiB
MQL5
128 lines
4.7 KiB
MQL5
// BollAveragesStrategy.mqh
| |||
// Strategy using the 2_Averages_with_BollingerBands indicator.
| |||
| |||
#property copyright "2025, Windsurf Engineering"
| |||
#property link "https://www.windsurf.ai"
| |||
| |||
#include "..\IStrategy.mqh"
| |||
// For CFeaturesKB
| |||
#include "..\KnowledgeBase.mqh"
| |||
| |||
// --- Buffer indices for the '2_Averages_with_BollingerBands' custom indicator
| |||
#define MA1_BUFFER 0
| |||
#define MA2_BUFFER 1
| |||
#define BB_UPPER_BUFFER 4
| |||
#define BB_MIDDLE_BUFFER 5
| |||
#define BB_LOWER_BUFFER 6
| |||
| |||
class CBollAveragesStrategy : public IStrategy
| |||
{
| |||
private:
| |||
int m_indicator_handle;
| |||
string m_symbol;
| |||
ENUM_TIMEFRAMES m_timeframe;
| |||
| |||
// --- Data arrays
| |||
double m_ma1_buffer[];
| |||
double m_ma2_buffer[];
| |||
| |||
public:
| |||
CBollAveragesStrategy(string symbol, ENUM_TIMEFRAMES timeframe);
| |||
~CBollAveragesStrategy();
| |||
| |||
// --- IStrategy interface methods
| |||
virtual void Refresh() override;
| |||
virtual TradeOrder CheckSignal() override;
| |||
virtual string Name() override { return "BollAveragesStrategy"; }
| |||
virtual void ExportFeatures(CFeaturesKB* kb, const datetime ts) override
| |||
{
| |||
if(CheckPointer(kb)==POINTER_INVALID) return;
| |||
if(m_indicator_handle==INVALID_HANDLE) return;
| |||
// Read latest buffers
| |||
double ma1[1], ma2[1], bb_up[1], bb_mid[1], bb_lo[1];
| |||
if(CopyBuffer(m_indicator_handle, MA1_BUFFER, 0, 1, ma1)==1)
| |||
(*kb).WriteKV(ts, m_symbol, Name(), "ma1", ma1[0]);
| |||
if(CopyBuffer(m_indicator_handle, MA2_BUFFER, 0, 1, ma2)==1)
| |||
(*kb).WriteKV(ts, m_symbol, Name(), "ma2", ma2[0]);
| |||
if(CopyBuffer(m_indicator_handle, BB_UPPER_BUFFER, 0, 1, bb_up)==1)
| |||
(*kb).WriteKV(ts, m_symbol, Name(), "bb_upper", bb_up[0]);
| |||
if(CopyBuffer(m_indicator_handle, BB_MIDDLE_BUFFER, 0, 1, bb_mid)==1)
| |||
(*kb).WriteKV(ts, m_symbol, Name(), "bb_middle", bb_mid[0]);
| |||
if(CopyBuffer(m_indicator_handle, BB_LOWER_BUFFER, 0, 1, bb_lo)==1)
| |||
(*kb).WriteKV(ts, m_symbol, Name(), "bb_lower", bb_lo[0]);
| |||
}
| |||
};
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Constructor |
| |||
//+------------------------------------------------------------------+
| |||
CBollAveragesStrategy::CBollAveragesStrategy(string symbol, ENUM_TIMEFRAMES timeframe)
| |||
{
| |||
m_symbol = symbol;
| |||
m_timeframe = timeframe;
| |||
| |||
// --- Get indicator handle
| |||
m_indicator_handle = iCustom(m_symbol, m_timeframe, "Downloads\\2_Averages_with_BollingerBands");
| |||
| |||
// --- Set buffers as series
| |||
ArraySetAsSeries(m_ma1_buffer, true);
| |||
ArraySetAsSeries(m_ma2_buffer, true);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Destructor |
| |||
//+------------------------------------------------------------------+
| |||
CBollAveragesStrategy::~CBollAveragesStrategy()
| |||
{
| |||
IndicatorRelease(m_indicator_handle);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| Refresh - Copies the latest indicator data into local buffers |
| |||
//+------------------------------------------------------------------+
| |||
void CBollAveragesStrategy::Refresh()
| |||
{
| |||
if(m_indicator_handle == INVALID_HANDLE)
| |||
{
| |||
Print("CBollAveragesStrategy: Invalid indicator handle.");
| |||
return;
| |||
}
| |||
| |||
// Copy the last 3 bars of data for crossover detection
| |||
CopyBuffer(m_indicator_handle, MA1_BUFFER, 0, 3, m_ma1_buffer);
| |||
CopyBuffer(m_indicator_handle, MA2_BUFFER, 0, 3, m_ma2_buffer);
| |||
}
| |||
| |||
//+------------------------------------------------------------------+
| |||
//| CheckSignal - Checks for a moving average crossover |
| |||
//+------------------------------------------------------------------+
| |||
TradeOrder CBollAveragesStrategy::CheckSignal()
| |||
{
| |||
TradeOrder order;
| |||
order.strategy_name = Name();
| |||
| |||
// Check for bullish crossover (MA1 crosses above MA2)
| |||
// Bar 1 is the most recently closed bar
| |||
if (m_ma1_buffer[1] > m_ma2_buffer[1] && m_ma1_buffer[2] <= m_ma2_buffer[2])
| |||
{
| |||
order.action = ACTION_BUY;
| |||
order.order_type = ORDER_TYPE_BUY;
| |||
double price = SymbolInfoDouble(m_symbol, SYMBOL_ASK);
| |||
order.stop_loss = price - 150 * _Point; // Example SL
| |||
order.take_profit = price + 300 * _Point; // Example TP
| |||
return order;
| |||
}
| |||
| |||
// Check for bearish crossover (MA1 crosses below MA2)
| |||
if (m_ma1_buffer[1] < m_ma2_buffer[1] && m_ma1_buffer[2] >= m_ma2_buffer[2])
| |||
{
| |||
order.action = ACTION_SELL;
| |||
order.order_type = ORDER_TYPE_SELL;
| |||
double price = SymbolInfoDouble(m_symbol, SYMBOL_BID);
| |||
order.stop_loss = price + 150 * _Point; // Example SL
| |||
order.take_profit = price - 300 * _Point; // Example TP
| |||
return order;
| |||
}
| |||
| |||
return order; // Returns order with ACTION_NONE
| |||
}
|