文章目录
MT4指标与MT5指标的区别
- MT4指标可以通过输入参数直接返回指标值,而MT5需要生成指标句柄,然后通过句柄获取指标值。
- MT5指标使用向对MT4指标来说不不便利,但性能更高。
- MT4的指标与MT5在对方的平台上都无法使用。
设计通用MT4与MT5指标的意义
- 用户自定义指标,可以同时运行在MT4与MT5上,可开发跨平台技术指标。
- 用户开发其中一个平台开发的EA程序,指标部分的调用也可同时运行在另一个平台上。
- 深度理解和学习MT4与MT5的差别和联系,加深对开发的理解。
通用技术指标的实现思想
- 以MQL4指标函数作为模板,并在指标函数名字后面增加MQL4的后缀,因MQL4的指标访问更便利并兼顾MQL5指标的性能。
- 由于MT5指标函数在使用前,需要在OnInit函数中进行初始化获取句柄,所以我们需要创建一个保存指标句柄的结构体。
- 每类MT5指标句柄都保存在指标句柄结构体数组中,同类指标单参数不同,则句柄不同。
指标句柄和参数的结构体模板
- 结构设置两个变量:m_handle用来保存指标句柄的值,m_inputs用来保存指标的参数,模板设计可兼容所有指标。
- 重载==运算符用于判断参数是否相对,重载=运算符用于指标参数复制。
- GetHandle()函数可读取指标的句柄值。
//+------------------------------------------------------------------+
//| 指标句柄结构体模板 |
//+------------------------------------------------------------------+
template <typename T>
struct STRUCT_IND_HANDLE
{
private:
int m_handle; // 指标句柄
T m_inputs; // 指标参数
public:
STRUCT_IND_HANDLE() : m_handle(INVALID_HANDLE) { }
bool operator==(const T &inputs) const { return (m_inputs == inputs); }
void operator=(const T &inputs) {m_inputs=inputs; }
int GetHandle() { return((m_handle!=INVALID_HANDLE) ? m_handle : (m_handle=m_inputs.GetHandle())); }
};
//+------------------------------------------------------------------+
//| 获取指标句柄 |
//+------------------------------------------------------------------+
template<typename T>
int GetHandle(STRUCT_IND_HANDLE<T> &arr_handle[], const T &inputs, bool is_created=false)
{
const int size = ArraySize(arr_handle);
//
for (int i=0; i<size; i++)
{
if (arr_handle[i]==inputs) return (arr_handle[i].GetHandle());
}
// 创建指标句柄只可以在OnInit函数数,否者出现Stack overflow
if (is_created)
{
ArrayResize(arr_handle, size+1);
arr_handle[size] = inputs;
return (arr_handle[size].GetHandle());
}
else
return (INVALID_HANDLE);
}
创建多个指标参数结构体
- MACD 指标参数结构体
- RSI 指标参数结构体
- AC 指标参数结构体
- MA 指标参数结构体
- Stochastic 指标参数结构体
//+------------------------------------------------------------------+
//| MACD 指标参数结构体 |
//+------------------------------------------------------------------+
struct STRUCT_MACD_PARAMS
{
private:
string m_symbol;
ENUM_TIMEFRAMES m_tf;
int m_fast_ema_period;
int m_slow_ema_period;
int m_signal_period;
ENUM_APPLIED_PRICE m_applied_price;
public:
STRUCT_MACD_PARAMS() { }
//+------------------------------------------------------------------+
//| A constructor with an initialization list |
//+------------------------------------------------------------------+
STRUCT_MACD_PARAMS(const string &symbol,
const ENUM_TIMEFRAMES &tf,
const int &fast_ema_period,
const int &slow_ema_period,
const int &signal_period,
const ENUM_APPLIED_PRICE &applied_price) : m_symbol((symbol==NULL||symbol=="") ? Symbol() : symbol),
m_tf(tf),
m_fast_ema_period(fast_ema_period),
m_slow_ema_period(slow_ema_period),
m_signal_period(signal_period),
m_applied_price(applied_price) { }
//
int GetHandle(void) const { return (iMACD(m_symbol, m_tf, m_fast_ema_period, m_slow_ema_period, m_signal_period, m_applied_price)); }
//+------------------------------------------------------------------+
//| Operation Overloading "==" |
//+------------------------------------------------------------------+
bool operator==(const STRUCT_MACD_PARAMS &inputs) const
{
return (m_symbol==inputs.m_symbol
&& m_tf==inputs.m_tf
&& m_fast_ema_period==inputs.m_fast_ema_period
&& m_slow_ema_period == inputs.m_slow_ema_period
&& m_signal_period == inputs.m_signal_period
&& m_applied_price==inputs.m_applied_price);
}
};
//+------------------------------------------------------------------+
//| RSI 指标参数结构体 |
//+------------------------------------------------------------------+
struct STRUCT_RSI_PARAMS
{
private:
string m_symbol;
ENUM_TIMEFRAMES m_tf;
int m_ma_period;
ENUM_APPLIED_PRICE m_applied_price;
public:
STRUCT_RSI_PARAMS() { }
//+------------------------------------------------------------------+
//| A constructor with an initialization list |
//+------------------------------------------------------------------+
STRUCT_RSI_PARAMS(const string &symbol,
const ENUM_TIMEFRAMES &tf,
const int &ma_period,
const ENUM_APPLIED_PRICE &applied_price) : m_symbol((symbol==NULL||symbol=="") ? Symbol() : symbol),
m_tf(tf),
m_ma_period(ma_period),
m_applied_price(applied_price) { }
//
int GetHandle(void) const { return (iRSI(m_symbol, m_tf, m_ma_period, m_applied_price)); }
//+------------------------------------------------------------------+
//| Operation Overloading "==" |
//+------------------------------------------------------------------+
bool operator==(const STRUCT_RSI_PARAMS &inputs) const
{
return (m_symbol==inputs.m_symbol
&& m_tf==inputs.m_tf
&& m_ma_period==inputs.m_ma_period
&& m_applied_price==inputs.m_applied_price);
}
};
//+------------------------------------------------------------------+
//| AC指标结构体参数 |
//+------------------------------------------------------------------+
struct STRUCT_AC_PARAMS
{
private:
string m_symbol;
ENUM_TIMEFRAMES m_tf;
public:
STRUCT_AC_PARAMS() { }
//+------------------------------------------------------------------+
//| A constructor with an initialization list |
//+------------------------------------------------------------------+
STRUCT_AC_PARAMS(const string &symbol,
const ENUM_TIMEFRAMES &tf) : m_symbol((symbol==NULL||symbol=="") ? Symbol() : symbol),
m_tf(tf) { }
//
int GetHandle(void) const { return iAC(m_symbol, m_tf); }
//+------------------------------------------------------------------+
//| Operation Overloading "==" |
//+------------------------------------------------------------------+
bool operator==(const STRUCT_AC_PARAMS &inputs) const
{
return (m_symbol==inputs.m_symbol
&& m_tf==inputs.m_tf);
}
};
//+------------------------------------------------------------------+
//| MA指标结构体参数 |
//+------------------------------------------------------------------+
struct STRUCT_MA_PARAMS
{
private:
string m_symbol; // symbol name
ENUM_TIMEFRAMES m_tf; // timeframe
int m_ma_period; // averaging period
int m_ma_shift; // horizontal shift
ENUM_MA_METHOD m_ma_method; // smoothing type
ENUM_APPLIED_PRICE m_applied_price; // type of price
public:
STRUCT_MA_PARAMS() { }
//+------------------------------------------------------------------+
//| A constructor with an initialization list |
//+------------------------------------------------------------------+
STRUCT_MA_PARAMS(const string &symbol,
const ENUM_TIMEFRAMES &tf,
const int &ma_period,
const int &ma_shift,
const ENUM_MA_METHOD &ma_method,
const ENUM_APPLIED_PRICE &applied_price
) : m_symbol((symbol==NULL||symbol=="") ? Symbol() : symbol),
m_tf(tf),
m_ma_period(ma_period),
m_ma_shift(ma_shift),
m_ma_method(ma_method),
m_applied_price(applied_price) { }
//
int GetHandle(void) const { return iMA(m_symbol, m_tf, m_ma_period, m_ma_shift, m_ma_method, m_applied_price); }
//+------------------------------------------------------------------+
//| Operation Overloading "==" |
//+------------------------------------------------------------------+
bool operator==(const STRUCT_MA_PARAMS &inputs) const
{
return (m_symbol==inputs.m_symbol
&& m_tf==inputs.m_tf
&& m_ma_period==inputs.m_ma_period
&& m_ma_shift==inputs.m_ma_shift
&& m_ma_method==inputs.m_ma_method
&& m_applied_price==inputs.m_applied_price);
}
};
//+------------------------------------------------------------------+
//| Struct Stochastic |
//+------------------------------------------------------------------+
struct STRUCT_STOCH_PARAMS
{
private:
string m_symbol; // 交易品种名称
ENUM_TIMEFRAMES m_tf; // K线时间框架
int m_Kperiod; // K线周期 (用于计算的柱数)
int m_Dperiod; // D线周期 (开始平滑周期)
int m_slowing; // 最终平滑
ENUM_MA_METHOD m_ma_method; // 平滑类型
ENUM_STO_PRICE m_price_field; // 随机计算法
public:
STRUCT_STOCH_PARAMS() { }
//+------------------------------------------------------------------+
//| A constructor with an initialization list |
//+------------------------------------------------------------------+
STRUCT_STOCH_PARAMS(const string &symbol,
const ENUM_TIMEFRAMES &tf,
const int &Kperiod,
const int &Dperiod,
const int &slowing,
const ENUM_MA_METHOD &ma_method,
const ENUM_STO_PRICE &price_field
) : m_symbol((symbol==NULL||symbol=="") ? Symbol() : symbol),
m_tf(tf),
m_Kperiod(Kperiod),
m_Dperiod(Dperiod),
m_slowing(slowing),
m_ma_method(ma_method),
m_price_field(price_field) { }
//
int GetHandle(void) const { return ::iStochastic(m_symbol, m_tf, m_Kperiod, m_Dperiod, m_slowing, m_ma_method, m_price_field); }
//+------------------------------------------------------------------+
//| Operation Overloading "==" |
//+------------------------------------------------------------------+
bool operator==(const STRUCT_STOCH_PARAMS &inputs) const
{
return (m_symbol==inputs.m_symbol
&& m_tf==inputs.m_tf
&& m_Kperiod==inputs.m_Kperiod
&& m_Dperiod==inputs.m_Dperiod
&& m_slowing==inputs.m_slowing
&& m_ma_method==inputs.m_ma_method
&& m_price_field==inputs.m_price_field);
}
};
创建通用的MT4与MT5指标方法
- 以iMA指标为例:创建三个函数如下:
- CreateHandleMA 用来创建指标句柄,并保存在句柄数组中,相同参数的指标只创建一次。
- iMACaching 包装MT5的iMA指标,参数中不需要传入句柄。
- iMAMQL4 以MQL4的指标为原型,可同时运行在MT4上和MT5上,实现通用指标。
创建通用的MT4与MT5指标的代码实现,以MA为例,其他指标类似
// 通用MT4与MT5的 iMA指标
//bool CreateHandleMA(string symbol, ENUM_TIMEFRAMES tf, int ma_period, int ma_shift, ENUM_MA_METHOD ma_method, ENUM_APPLIED_PRICE applied_price);
//double iMACaching(string symbol, ENUM_TIMEFRAMES tf, int ma_period, int ma_shift, ENUM_MA_METHOD ma_method, ENUM_APPLIED_PRICE applied_price, int shift)
//double iMAMQL4(string symbol, int tf, int ma_period, int ma_shift, int method, int price, int shift);
// MA 指标句柄数组,在MT5中保存所有MA指标函数的句柄,参数不同句柄不同
STRUCT_IND_HANDLE<STRUCT_MA_PARAMS> g_HANDLES_MA[];
//+------------------------------------------------------------------+
//| 创建MA指标句柄 |
//+------------------------------------------------------------------+
bool CreateHandleMA(string symbol, ENUM_TIMEFRAMES tf, int ma_period, int ma_shift, ENUM_MA_METHOD ma_method, ENUM_APPLIED_PRICE applied_price)
{
//---
const STRUCT_MA_PARAMS Inputs(symbol,tf,ma_period,ma_shift,ma_method,applied_price);
int handle = GetHandle(g_HANDLES_MA, Inputs, true);
//
if (handle == INVALID_HANDLE)
{
Print(__FUNCTION__,": Invalid Handle error=",GetLastError());
return (false);
}
else
return (true);
}
//+------------------------------------------------------------------+
//| iMA function in MQL4 notation |
//+------------------------------------------------------------------+
double iMACaching(string symbol, ENUM_TIMEFRAMES tf, int ma_period, int ma_shift, ENUM_MA_METHOD ma_method, ENUM_APPLIED_PRICE applied_price, int shift)
{
double result=NaN;
//
const STRUCT_MA_PARAMS Inputs(symbol, tf, ma_period, ma_shift, ma_method, applied_price);
int handle = GetHandle(g_HANDLES_MA, Inputs, false);
//---
if (handle == INVALID_HANDLE)
{
Print(__FUNCTION__,": Invalid handle error=",GetLastError());
return (result);
}
double val[1];
int copied = CopyBuffer(handle, 0, shift, 1, val);
if (copied > 0)
result = val[0];
else
Print(__FUNCTION__, ": CopyBuffer error=", GetLastError());
return (result);
}
// iMA 计算移动平均线指标并返回其值
// 通用 MA 指标,在MT4与MT5下皆可运行
double iMAMQL4(string symbol, int tf, int ma_period, int ma_shift, int method, int price, int shift) export
{
#ifdef __MQL5__
ENUM_TIMEFRAMES timeframe = TFMigrate(tf);
ENUM_MA_METHOD ma_method = MethodMigrate(method);
ENUM_APPLIED_PRICE applied_price = PriceMigrate(price);
return iMACaching(symbol, timeframe, ma_period, ma_shift, ma_method, applied_price, shift);
#else
return iMA(symbol, tf, ma_period, ma_shift, method, price, shift);
#endif
}