502 lines
No EOL
40 KiB
MQL5
502 lines
No EOL
40 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| WaveDetector2.mq5 |
|
|
//| Copyright 2024, MetaQuotes Software Corp. |
|
|
//| https://www.mql5.com |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2024, MetaQuotes Software Corp."
|
|
#property link "https://www.mql5.com"
|
|
#property version "1.01"
|
|
#property strict
|
|
#include <ChartObjects\ChartObject.mqh>
|
|
|
|
// 调试标志 - 设置为true启用调试日志
|
|
#define DEBUG_MODE true
|
|
|
|
// 调试日志函数
|
|
void DebugLog(string message) {
|
|
if(DEBUG_MODE) {
|
|
Print("[DEBUG] " + message);
|
|
}
|
|
}
|
|
|
|
// 浪型结构体(存储浪型信息)
|
|
struct WaveInfo
|
|
{
|
|
string wave_type; // 浪型(上升浪/下降浪)
|
|
int start_index; // 起始K线索引
|
|
double start_price; // 起始价格
|
|
int end_index; // 结束K线索引
|
|
double end_price; // 结束价格
|
|
double amplitude; // 幅度(%)
|
|
};
|
|
|
|
// 极值点结构体(存储高/低点信息)
|
|
struct ExtremePoint
|
|
{
|
|
string type; // 类型(high/low)
|
|
int index; // K线索引
|
|
double price; // 价格
|
|
};
|
|
|
|
// 全局参数(可在MT5界面调整)
|
|
input int Window_Size = 6; // 滑动窗口大小
|
|
input double Trend_Threshold = 0.015; // 趋势反转阈值(1.5%)
|
|
input int ATR_Period = 14; // ATR计算周期
|
|
input int MACD_Fast_Period = 12; // MACD快速周期
|
|
input int MACD_Slow_Period = 26; // MACD慢速周期
|
|
input int MACD_Signal_Period = 9; // MACD信号周期
|
|
input int Divergence_Lookback = 10; // MACD背离回溯窗口
|
|
input bool Show_Debug_Info = true; // 是否在图表上显示调试信息
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 计算ATR(平均真实波幅)- 自适应幅度阈值用 |
|
|
//+------------------------------------------------------------------+
|
|
double CalculateATR(const int rates_total, const MqlRates &rates[])
|
|
{
|
|
DebugLog("CalculateATR: rates_total = " + IntegerToString(rates_total));
|
|
|
|
if(rates_total < ATR_Period + 1) {
|
|
DebugLog("CalculateATR: 数据不足,返回0");
|
|
return 0.0;
|
|
}
|
|
|
|
double tr_sum = 0.0;
|
|
// 计算前ATR_Period根K线的真实波幅总和
|
|
for(int i = rates_total - ATR_Period; i < rates_total; i++)
|
|
{
|
|
double tr = MathMax(rates[i].high - rates[i].low,
|
|
MathMax(MathAbs(rates[i].high - rates[i-1].close),
|
|
MathAbs(rates[i].low - rates[i-1].close)));
|
|
tr_sum += tr;
|
|
}
|
|
double atr_value = tr_sum / ATR_Period;
|
|
DebugLog("CalculateATR: 返回值 = " + DoubleToString(atr_value, 5));
|
|
return atr_value;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 计算MACD指标 - 背离验证用 |
|
|
//+------------------------------------------------------------------+
|
|
bool CalculateMACD(const int rates_total, const MqlRates &rates[],
|
|
double &macd_line[], double &signal_line[], double &histogram[])
|
|
{
|
|
DebugLog("CalculateMACD: rates_total = " + IntegerToString(rates_total));
|
|
|
|
if(rates_total < MACD_Slow_Period + 1) {
|
|
DebugLog("CalculateMACD: 数据不足,返回false");
|
|
return false;
|
|
}
|
|
|
|
// 初始化数组
|
|
ArrayResize(macd_line, rates_total);
|
|
ArrayResize(signal_line, rates_total);
|
|
ArrayResize(histogram, rates_total);
|
|
|
|
// 计算EMA
|
|
double ema_fast = 0.0, ema_slow = 0.0;
|
|
double alpha_fast = 2.0 / (MACD_Fast_Period + 1);
|
|
double alpha_slow = 2.0 / (MACD_Slow_Period + 1);
|
|
|
|
// 初始化EMA的第一个值
|
|
ema_fast = rates[0].close;
|
|
ema_slow = rates[0].close;
|
|
|
|
for(int i = 1; i < rates_total; i++)
|
|
{
|
|
// 指数移动平均(EMA)计算
|
|
ema_fast = (rates[i].close - ema_fast) * alpha_fast + ema_fast;
|
|
ema_slow = (rates[i].close - ema_slow) * alpha_slow + ema_slow;
|
|
macd_line[i] = ema_fast - ema_slow;
|
|
|
|
// 信号线(EMA of MACD线)
|
|
if(i == 1) signal_line[i] = macd_line[i];
|
|
else signal_line[i] = (macd_line[i] - signal_line[i-1]) * (2.0/(MACD_Signal_Period + 1)) + signal_line[i-1];
|
|
|
|
histogram[i] = macd_line[i] - signal_line[i];
|
|
}
|
|
|
|
DebugLog("CalculateMACD: 成功计算,最后一个histogram值 = " + DoubleToString(histogram[rates_total-1], 5));
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 检测候选极值点(滑动窗口+ATR自适应阈值) |
|
|
//+------------------------------------------------------------------+
|
|
bool DetectExtremes(const int rates_total, const MqlRates &rates[],
|
|
const double atr, ExtremePoint &extremes[], int &ext_count)
|
|
{
|
|
DebugLog("DetectExtremes: rates_total = " + IntegerToString(rates_total) + ", atr = " + DoubleToString(atr, 5));
|
|
|
|
if(rates_total < Window_Size * 2 + ATR_Period) {
|
|
DebugLog("DetectExtremes: 数据不足,返回false");
|
|
return false;
|
|
}
|
|
|
|
ext_count = 0;
|
|
ArrayResize(extremes, 1000); // 预分配数组大小,避免溢出
|
|
|
|
double dynamic_amp = atr / rates[rates_total - 1].close; // 自适应相对幅度
|
|
DebugLog("DetectExtremes: dynamic_amp = " + DoubleToString(dynamic_amp * 100, 2) + "%");
|
|
|
|
// 滑动窗口扫描K线
|
|
for(int i = Window_Size + ATR_Period; i < rates_total - Window_Size; i++)
|
|
{
|
|
// 找窗口内最高/最低价
|
|
double window_max = rates[i].high;
|
|
double window_min = rates[i].low;
|
|
for(int j = i - Window_Size; j <= i + Window_Size; j++)
|
|
{
|
|
if(rates[j].high > window_max) window_max = rates[j].high;
|
|
if(rates[j].low < window_min) window_min = rates[j].low;
|
|
}
|
|
|
|
// 优化后的极值点检测逻辑
|
|
bool is_high = (rates[i].high == window_max);
|
|
bool is_low = (rates[i].low == window_min);
|
|
|
|
// 计算价格变化
|
|
if(is_high && i > 0) {
|
|
double price_change_high = (rates[i].high / rates[i-1].close - 1);
|
|
// 检测高点:窗口内最高 + 突破自适应幅度阈值
|
|
if(price_change_high >= MathMax(dynamic_amp * 0.5, Trend_Threshold * 0.5)) {
|
|
extremes[ext_count].type = "high";
|
|
extremes[ext_count].index = i;
|
|
extremes[ext_count].price = rates[i].high;
|
|
ext_count++;
|
|
DebugLog("DetectExtremes: 检测到高点 #" + IntegerToString(ext_count) +
|
|
" 索引=" + IntegerToString(i) +
|
|
" 价格=" + DoubleToString(rates[i].high, 5) +
|
|
" 涨幅=" + DoubleToString(price_change_high * 100, 2) + "%");
|
|
}
|
|
}
|
|
else if(is_low && i > 0) {
|
|
double price_change_low = (rates[i-1].close / rates[i].low - 1);
|
|
// 检测低点:窗口内最低 + 突破自适应幅度阈值
|
|
if(price_change_low >= MathMax(dynamic_amp * 0.5, Trend_Threshold * 0.5)) {
|
|
extremes[ext_count].type = "low";
|
|
extremes[ext_count].index = i;
|
|
extremes[ext_count].price = rates[i].low;
|
|
ext_count++;
|
|
DebugLog("DetectExtremes: 检测到低点 #" + IntegerToString(ext_count) +
|
|
" 索引=" + IntegerToString(i) +
|
|
" 价格=" + DoubleToString(rates[i].low, 5) +
|
|
" 跌幅=" + DoubleToString(price_change_low * 100, 2) + "%");
|
|
}
|
|
}
|
|
}
|
|
|
|
DebugLog("DetectExtremes: 共检测到 " + IntegerToString(ext_count) + " 个候选极值点");
|
|
return ext_count > 0;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| MACD背离验证 - 确认极值点有效性 |
|
|
//+------------------------------------------------------------------+
|
|
bool VerifyMACD_Divergence(const int rates_total, const MqlRates &rates[],
|
|
const double &histogram[], const string ext_type, const int ext_idx)
|
|
{
|
|
DebugLog("VerifyMACD_Divergence: ext_type = " + ext_type + ", ext_idx = " + IntegerToString(ext_idx));
|
|
|
|
// 为了测试,暂时总是返回true,以便看到所有检测到的浪型
|
|
return true;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 筛选有效极值点(趋势突变+MACD背离) |
|
|
//+------------------------------------------------------------------+
|
|
bool FilterValidExtremes(const int rates_total, const MqlRates &rates[],
|
|
const ExtremePoint &extremes[], const int ext_count,
|
|
const double &histogram[], ExtremePoint &valid_extremes[], int &valid_count)
|
|
{
|
|
DebugLog("FilterValidExtremes: 开始筛选有效极值点,候选点数量 = " + IntegerToString(ext_count));
|
|
|
|
valid_count = 0;
|
|
ArrayResize(valid_extremes, ext_count);
|
|
|
|
for(int i = 0; i < ext_count; i++)
|
|
{
|
|
// MACD背离验证
|
|
bool macd_valid = VerifyMACD_Divergence(rates_total, rates, histogram, extremes[i].type, extremes[i].index);
|
|
|
|
// 趋势突变验证(相邻极值点反向且价格变化达标)
|
|
bool trend_valid = true;
|
|
if(valid_count > 0)
|
|
{
|
|
ExtremePoint prev_ext = valid_extremes[valid_count - 1];
|
|
|
|
// 检查是否连续同类型极值点
|
|
if(extremes[i].type == prev_ext.type) {
|
|
DebugLog("FilterValidExtremes: 跳过连续同类型极值点 #" + IntegerToString(i));
|
|
trend_valid = false;
|
|
}
|
|
else {
|
|
// 检查价格变化是否达标
|
|
double price_change = MathAbs((extremes[i].price - prev_ext.price) / prev_ext.price);
|
|
// 确保计算的是正确的百分比变化
|
|
if(price_change < Trend_Threshold) {
|
|
DebugLog("FilterValidExtremes: 跳过价格变化不足的极值点 #" + IntegerToString(i) +
|
|
" 变化率=" + DoubleToString(price_change * 100, 2) + "%");
|
|
trend_valid = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 只有通过验证的点才被保留
|
|
if(macd_valid && trend_valid) {
|
|
valid_extremes[valid_count] = extremes[i];
|
|
DebugLog("FilterValidExtremes: 保留有效极值点 #" + IntegerToString(valid_count + 1) +
|
|
" 类型=" + extremes[i].type +
|
|
" 索引=" + IntegerToString(extremes[i].index) +
|
|
" 价格=" + DoubleToString(extremes[i].price, 5));
|
|
valid_count++;
|
|
}
|
|
}
|
|
|
|
DebugLog("FilterValidExtremes: 筛选后有效极值点数量 = " + IntegerToString(valid_count));
|
|
return valid_count > 1; // 至少2个有效极值点才构成浪
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 串联有效极值点,生成浪型数据 |
|
|
//+------------------------------------------------------------------+
|
|
bool GenerateWaves(const ExtremePoint &valid_extremes[], const int valid_count,
|
|
WaveInfo &waves[], int &wave_count)
|
|
{
|
|
DebugLog("GenerateWaves: 开始生成浪型数据,有效极值点数量 = " + IntegerToString(valid_count));
|
|
|
|
wave_count = 0;
|
|
ArrayResize(waves, valid_count - 1);
|
|
|
|
for(int i = 1; i < valid_count; i++)
|
|
{
|
|
ExtremePoint start = valid_extremes[i-1];
|
|
ExtremePoint end = valid_extremes[i];
|
|
|
|
// 判定浪型方向
|
|
if(start.type == "low" && end.type == "high")
|
|
waves[wave_count].wave_type = "上升浪";
|
|
else if(start.type == "high" && end.type == "low")
|
|
waves[wave_count].wave_type = "下降浪";
|
|
else {
|
|
DebugLog("GenerateWaves: 跳过无效的浪型连接 #" + IntegerToString(i));
|
|
continue;
|
|
}
|
|
|
|
// 填充浪型信息
|
|
waves[wave_count].start_index = start.index;
|
|
waves[wave_count].start_price = start.price;
|
|
waves[wave_count].end_index = end.index;
|
|
waves[wave_count].end_price = end.price;
|
|
waves[wave_count].amplitude = (end.price / start.price - 1) * 100;
|
|
|
|
DebugLog("GenerateWaves: 生成浪型 #" + IntegerToString(wave_count + 1) +
|
|
" 类型=" + waves[wave_count].wave_type +
|
|
" 幅度=" + DoubleToString(waves[wave_count].amplitude, 2) + "%");
|
|
|
|
wave_count++;
|
|
}
|
|
|
|
DebugLog("GenerateWaves: 共生成 " + IntegerToString(wave_count) + " 个浪型");
|
|
return wave_count > 0;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 主函数 - 浪型检测入口 |
|
|
//+------------------------------------------------------------------+
|
|
bool DetectWaves(const int rates_total, const MqlRates &rates[],
|
|
WaveInfo &waves[], int &wave_count)
|
|
{
|
|
DebugLog("====== DetectWaves 开始执行 ======");
|
|
|
|
// 验证输入参数
|
|
if(rates_total <= 0) {
|
|
DebugLog("DetectWaves: 无效的rates_total值");
|
|
return false;
|
|
}
|
|
|
|
// 1. 计算辅助指标(ATR + MACD)
|
|
double atr = CalculateATR(rates_total, rates);
|
|
if(atr <= 0) {
|
|
DebugLog("DetectWaves: ATR计算失败或为零");
|
|
return false;
|
|
}
|
|
|
|
double macd_line[], signal_line[], histogram[];
|
|
if(!CalculateMACD(rates_total, rates, macd_line, signal_line, histogram)) {
|
|
DebugLog("DetectWaves: MACD计算失败");
|
|
return false;
|
|
}
|
|
|
|
// 2. 检测候选极值点
|
|
ExtremePoint extremes[];
|
|
int ext_count = 0;
|
|
if(!DetectExtremes(rates_total, rates, atr, extremes, ext_count)) {
|
|
DebugLog("DetectWaves: 未检测到候选极值点");
|
|
return false;
|
|
}
|
|
|
|
// 3. 筛选有效极值点
|
|
ExtremePoint valid_extremes[];
|
|
int valid_count = 0;
|
|
if(!FilterValidExtremes(rates_total, rates, extremes, ext_count, histogram, valid_extremes, valid_count)) {
|
|
DebugLog("DetectWaves: 有效极值点不足,无法构成浪型");
|
|
return false;
|
|
}
|
|
|
|
// 4. 生成浪型数据
|
|
bool result = GenerateWaves(valid_extremes, valid_count, waves, wave_count);
|
|
|
|
if(result) {
|
|
DebugLog("====== DetectWaves 执行成功,共检测到 " + IntegerToString(wave_count) + " 个浪型 ======");
|
|
} else {
|
|
DebugLog("====== DetectWaves 执行失败 ======");
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 测试函数 - 在MT5图表中显示结果 |
|
|
//+------------------------------------------------------------------+
|
|
void OnDeinit(const int reason)
|
|
{
|
|
// 清除图表上的所有对象
|
|
ObjectsDeleteAll(ChartID());
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| 实时更新 - 每根K线闭合后检测浪型 |
|
|
//+------------------------------------------------------------------+
|
|
void OnTick()
|
|
{
|
|
// 为了减少CPU使用率,添加时间过滤(每5秒只执行一次)
|
|
static datetime last_execution = 0;
|
|
if(TimeCurrent() - last_execution < 5) return;
|
|
last_execution = TimeCurrent();
|
|
|
|
DebugLog("OnTick: 开始执行浪型检测");
|
|
|
|
MqlRates rates[];
|
|
int rates_total = CopyRates(_Symbol, _Period, 0, Bars(_Symbol, _Period), rates);
|
|
|
|
DebugLog("OnTick: rates_total = " + IntegerToString(rates_total));
|
|
|
|
if(rates_total < 100) {
|
|
DebugLog("OnTick: 数据不足,需要至少100根K线");
|
|
return; // 确保数据足够
|
|
}
|
|
|
|
// 显示调试信息到图表
|
|
if(Show_Debug_Info) {
|
|
string debug_text = StringFormat("检测时间: %s\nK线数量: %d\n当前品种: %s\n当前周期: %s",
|
|
TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES),
|
|
rates_total, _Symbol, EnumToString(_Period));
|
|
|
|
// 创建或更新调试信息文本对象
|
|
string debug_obj_name = "debug_info";
|
|
if(ObjectFind(ChartID(), debug_obj_name) < 0) {
|
|
ObjectCreate(ChartID(), debug_obj_name, OBJ_LABEL, 0, 0, 0);
|
|
ObjectSetInteger(ChartID(), debug_obj_name, OBJPROP_CORNER, 0);
|
|
ObjectSetInteger(ChartID(), debug_obj_name, OBJPROP_XDISTANCE, 10);
|
|
ObjectSetInteger(ChartID(), debug_obj_name, OBJPROP_YDISTANCE, 10);
|
|
ObjectSetInteger(ChartID(), debug_obj_name, OBJPROP_COLOR, clrBlue);
|
|
ObjectSetInteger(ChartID(), debug_obj_name, OBJPROP_BGCOLOR, 16776960);
|
|
ObjectSetInteger(ChartID(), debug_obj_name, OBJPROP_BORDER_TYPE, 0);
|
|
ObjectSetInteger(ChartID(), debug_obj_name, OBJPROP_XSIZE, 200);
|
|
ObjectSetInteger(ChartID(), debug_obj_name, OBJPROP_YSIZE, 80);
|
|
}
|
|
ObjectSetString(ChartID(), debug_obj_name, OBJPROP_TEXT, debug_text);
|
|
}
|
|
|
|
WaveInfo waves[];
|
|
int wave_count = 0;
|
|
if(DetectWaves(rates_total, rates, waves, wave_count))
|
|
{
|
|
DebugLog("OnTick: 检测成功,准备在图表上绘制浪型");
|
|
|
|
// 清除旧的浪型标记
|
|
ObjectsDeleteAll(ChartID());
|
|
|
|
// 重新添加调试信息
|
|
if(Show_Debug_Info) {
|
|
string debug_text = StringFormat("检测时间: %s\nK线数量: %d\n当前品种: %s\n当前周期: %d\n检测到浪型数: %d",
|
|
TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES),
|
|
rates_total, _Symbol, _Period, wave_count);
|
|
|
|
string debug_obj_name = "debug_info";
|
|
if(ObjectFind(ChartID(), debug_obj_name) < 0) {
|
|
ObjectCreate(ChartID(), debug_obj_name, OBJ_LABEL, 0, 0, 0);
|
|
ObjectSetInteger(ChartID(), debug_obj_name, OBJPROP_CORNER, 0);
|
|
ObjectSetInteger(ChartID(), debug_obj_name, OBJPROP_XDISTANCE, 10);
|
|
ObjectSetInteger(ChartID(), debug_obj_name, OBJPROP_YDISTANCE, 10);
|
|
ObjectSetInteger(ChartID(), debug_obj_name, OBJPROP_COLOR, clrBlue);
|
|
ObjectSetInteger(ChartID(), debug_obj_name, OBJPROP_BGCOLOR, 16776960);
|
|
ObjectSetInteger(ChartID(), debug_obj_name, OBJPROP_BORDER_TYPE, 0);
|
|
ObjectSetInteger(ChartID(), debug_obj_name, OBJPROP_XSIZE, 200);
|
|
ObjectSetInteger(ChartID(), debug_obj_name, OBJPROP_YSIZE, 100);
|
|
}
|
|
ObjectSetString(ChartID(), debug_obj_name, OBJPROP_TEXT, debug_text);
|
|
}
|
|
|
|
// 在图表上绘制浪型(矩形+文字)
|
|
for(int i = 0; i < wave_count; i++)
|
|
{
|
|
// 绘制浪型背景矩形
|
|
string rect_name = "wave_rect_" + IntegerToString(i);
|
|
|
|
// 确保对象创建成功
|
|
if(!ObjectCreate(ChartID(), rect_name, OBJ_RECTANGLE_LABEL, 0,
|
|
waves[i].start_index, waves[i].start_price,
|
|
waves[i].end_index, waves[i].end_price)) {
|
|
DebugLog("OnTick: 创建矩形对象失败 #" + IntegerToString(i) + ", 错误码: " + IntegerToString(GetLastError()));
|
|
continue;
|
|
}
|
|
|
|
// 设置矩形属性
|
|
ObjectSetInteger(ChartID(), rect_name, OBJPROP_COLOR,
|
|
(waves[i].wave_type == "上升浪") ? clrGreen : clrRed);
|
|
ObjectSetInteger(ChartID(), rect_name, OBJPROP_BORDER_COLOR,
|
|
(waves[i].wave_type == "上升浪") ? clrGreen : clrRed);
|
|
ObjectSetInteger(ChartID(), rect_name, OBJPROP_STYLE, 0);
|
|
ObjectSetInteger(ChartID(), rect_name, OBJPROP_WIDTH, 1);
|
|
ObjectSetInteger(ChartID(), rect_name, OBJPROP_BACK, true);
|
|
|
|
// 绘制浪型信息文字
|
|
string text_name = "wave_text_" + IntegerToString(i);
|
|
string text = StringFormat("浪%d: %s (%.2f%%)", i+1, waves[i].wave_type, waves[i].amplitude);
|
|
|
|
// 确保文字对象创建成功
|
|
if(!ObjectCreate(ChartID(), text_name, OBJ_TEXT, 0,
|
|
(waves[i].start_index + waves[i].end_index)/2,
|
|
(waves[i].start_price + waves[i].end_price)/2)) {
|
|
DebugLog("OnTick: 创建文字对象失败 #" + IntegerToString(i) + ", 错误码: " + IntegerToString(GetLastError()));
|
|
continue;
|
|
}
|
|
|
|
// 设置文字属性
|
|
ObjectSetString(ChartID(), text_name, OBJPROP_TEXT, text);
|
|
ObjectSetInteger(ChartID(), text_name, OBJPROP_COLOR, clrBlue);
|
|
ObjectSetInteger(ChartID(), text_name, OBJPROP_FONTSIZE, 16);
|
|
|
|
|
|
DebugLog("OnTick: 成功绘制浪型 #" + IntegerToString(i+1) + ": " + waves[i].wave_type);
|
|
}
|
|
}
|
|
else {
|
|
DebugLog("OnTick: 未检测到有效浪型");
|
|
|
|
// 仍然显示调试信息
|
|
if(Show_Debug_Info) {
|
|
string debug_text = StringFormat("检测时间: %s\nK线数量: %d\n当前品种: %s\n当前周期: %d\n未检测到浪型",
|
|
TimeToString(TimeCurrent(), TIME_DATE|TIME_MINUTES),
|
|
rates_total, _Symbol, _Period);
|
|
|
|
string debug_obj_name = "debug_info";
|
|
if(ObjectFind(ChartID(), debug_obj_name) < 0) {
|
|
ObjectCreate(ChartID(), debug_obj_name, OBJ_LABEL, 0, 0, 0);
|
|
}
|
|
ObjectSetString(ChartID(), debug_obj_name, OBJPROP_TEXT, debug_text);
|
|
}
|
|
}
|
|
}
|
|
//+------------------------------------------------------------------+ |