The sixth part of the article about the universal Expert Advisor describes the use of the trailing stop feature. The article will guide you through how to create a custom trailing stop module using unified rules, as well as how to add it to the trading engine so that it would automatically manage positions.
CExpertSignal* CSignalAdapter::CreateSignal(MqlSignalParams& params)
{
DeleteSignal();
switch(params.signal_type)
{
case SIGNAL_AO:
m_signal = new CSignalAO();
break;
case SIGNAL_AC:
m_signal = new CSignalAC();
break;
case SIGNAL_ADAPTIVE_MA:
m_signal = new CSignalAMA();
break;
case SIGNAL_CCI:
m_signal = new CSignalCCI();
break;
case SIGNAL_DeMARKER:
m_signal = new CSignalDeM();
break;
case SIGNAL_DOUBLE_EMA:
m_signal = new CSignalDEMA();
break;
case SIGNAL_ENVELOPES:
m_signal = new CSignalEnvelopes();
break;
case SIGNAL_FRAMA:
m_signal = new CSignalFrAMA();
break;
case SIGNAL_MA:
m_signal = new CSignalMA();
break;
case SIGNAL_MACD:
m_signal = new CSignalMACD();
break;
case SIGNAL_PARABOLIC_SAR:
m_signal = new CSignalSAR();
break;
case SIGNAL_RSI:
m_signal = new CSignalRSI();
break;
case SIGNAL_RVI:
m_signal = new CSignalRVI();
break;
case SIGNAL_STOCHASTIC:
m_signal = new CSignalStoch();
break;
case SIGNAL_TRIPLE_EA:
m_signal = new CSignalTriX();
break;
case SIGNAL_TRIPLE_EMA:
m_signal = new CSignalTEMA();
break;
case SIGNAL_WILLIAMS_PER_RANGE:
m_signal = new CSignalWPR();
break;
}
if(CheckPointer(m_signal)!= POINTER_INVALID)
m_params = params;
return m_signal;
}
bool CSignalAdapter::Init()
{
if(m_params.symbol == "") /* CreateSignal method should be called first in order to update m_params */
return false;
m_info.Name(m_params.symbol);
if(!m_signal.Init(GetPointer(m_info), m_params.period, m_params.point))
return false;
if(!m_signal.InitIndicators(GetPointer(m_indicators)))
return false;
m_signal.EveryTick(m_params.every_tick);
m_signal.Magic(m_params.magic);
m_open.Create(m_params.symbol, m_params.period);
m_high.Create(m_params.symbol, m_params.period);
m_low.Create(m_params.symbol, m_params.period);
m_close.Create(m_params.symbol, m_params.period);
m_times.Create(m_params.symbol, m_params.period);
m_spread.Create(m_params.symbol, m_params.period);
m_tik_vol.Create(m_params.symbol, m_params.period);
m_real_vol.Create(m_params.symbol, m_params.period);
m_signal.SetPriceSeries(GetPointer(m_open), GetPointer(m_high), GetPointer(m_low), GetPointer(m_close));
//m_signal.SetOtherSeries(GetPointer(m_spread), GetPointer(m_times), GetPointer(m_tik_vol), GetPointer(m_real_vol));
int mask = 1;
mask = mask << m_params.usage_pattern;
m_signal.PatternsUsage(mask);
return true;
}
当然,还需要调用新创建的 Init 方法:
CAdapterMACD::CAdapterMACD(void)
{
m_params.symbol = Symbol();
m_params.period = Period();
m_params.every_tick = false;
m_params.signal_type = SIGNAL_MACD;
m_params.magic = 1234;
m_params.point = 1.0;
m_params.usage_pattern = 2;
CSignalMACD* macd = m_signal.CreateSignal(m_params);
macd.PeriodFast(15);
macd.PeriodSlow(32);
macd.PeriodSignal(6);
m_signal.Init(); /* This call is going to create the CSignalMACD object with the custom parameters */
}
感谢瓦西里的贡献。我学到了很多。我下载了所有代码,但在 Panel.mqh 文件中出现了编译错误:
At' - object pointer expected Panel.mqh 210 39
At' - 预期对象指针 Panel.mqh 228 37
能否请您检查一下?
嗨,艾米。我刚刚读完Vasiliy Sokolov 的文章。如果您仍有兴趣找到解决方案。请在此发布错误日志。我记得我遇到过这个错误,并意识到 StrategiesList 文件的声明中有一个".\Panel\Panel.mqh"。 Panel.mqh 并不存在。请尝试访问https://www.mql5.com/zh/articles/2411 并从那里下载 Panel 文件。我相信那里有 Panel.mqh 文件。
Vasiliy 的这个系列作为一个框架真的很不错。我也学到了很多东西,但当一个库出现问题时,如果作者不提供支持,如果你不是一个优秀的程序员,你可能就会被困住。这正是Alain Verleyen 在你们的其他讨论中提出的观点。但是,那些花时间在这里分享他们的知识和技能的人真是了不起。我永远心存感激。
这个引擎非常棒,谢谢你。这是我决定改用的第一个 OOP MQL5 引擎。
但不幸的是,Manager.OnTick() 运行速度非常慢。跟踪显示几乎 100%。在一分钟的时间范围内和使用 OHLC M1 时,测试速度非常慢。3 年来 - 约 50 秒。同时,Expert Advisor 本身不做任何测试,我已经注释掉了加载它的所有内容。也就是说,它只是搜索条形图。
我真的很想优化 Manager.OnTick() 中的代码。
这个引擎非常棒,谢谢你。这是我决定改用的第一个 OOP MQL5 引擎。
但不幸的是,Manager.OnTick() 运行速度非常慢。跟踪显示几乎 100%。在一分钟的时间范围内和使用 OHLC M1 时,测试速度非常慢。3 年来 - 约 50 秒。同时,Expert Advisor 本身不做任何测试,我已经注释掉了加载它的所有内容。也就是说,它只是搜索条形图。
我真的很想优化 Manager.OnTick() 中的代码。
这是启动其他一切的函数--当然,它将是 100% 的。看看里面都花了哪些时间,然后对其进行优化。您可以发布截图。
这个引擎非常棒,谢谢你。这是我决定改用的第一个 OOP MQL5 引擎。
但不幸的是,Manager.OnTick() 运行速度非常慢。跟踪显示几乎 100%。在一分钟的时间范围内和使用 OHLC M1 时,测试速度非常慢。3 年来 - 约 50 秒。同时,Expert Advisor 本身不做任何测试,我已经注释掉了加载它的所有内容。也就是说,它只是搜索条形图。
我真的想优化 Manager.OnTick() 中的代码。
这里没有什么令人惊讶的。这个速度与策略测试器的空闲运行速度相当。OnTick 决定一个新的刻度线的出现和一个新的条形图的打开。这些操作不需要大量资源。
你好,瓦西里。
感谢您的所有文章。
就复杂性和软件架构而言,Universal Expert Advisor 确实令人印象深刻。
对于这个特殊版本,我想在这段代码中提出一个问题:
实际上,MacD 参数(15、32 和 6)在这里不起作用,因为 CreateSignal() 方法会在更新参数之前初始化 MacD 信号。
在这种情况下,我建议将 CSignalAdapter::CreateSignal() 方法分为两部分,第一部分是创建信号并按原样返回,第二部分是在设置所有 "信号相关 "参数(本例中为 PeriodFast、PeriodSlow 和 PeriodSignal)后初始化信号:
CExpertSignal* CSignalAdapter::CreateSignal(MqlSignalParams& params) { DeleteSignal(); switch(params.signal_type) { case SIGNAL_AO: m_signal = new CSignalAO(); break; case SIGNAL_AC: m_signal = new CSignalAC(); break; case SIGNAL_ADAPTIVE_MA: m_signal = new CSignalAMA(); break; case SIGNAL_CCI: m_signal = new CSignalCCI(); break; case SIGNAL_DeMARKER: m_signal = new CSignalDeM(); break; case SIGNAL_DOUBLE_EMA: m_signal = new CSignalDEMA(); break; case SIGNAL_ENVELOPES: m_signal = new CSignalEnvelopes(); break; case SIGNAL_FRAMA: m_signal = new CSignalFrAMA(); break; case SIGNAL_MA: m_signal = new CSignalMA(); break; case SIGNAL_MACD: m_signal = new CSignalMACD(); break; case SIGNAL_PARABOLIC_SAR: m_signal = new CSignalSAR(); break; case SIGNAL_RSI: m_signal = new CSignalRSI(); break; case SIGNAL_RVI: m_signal = new CSignalRVI(); break; case SIGNAL_STOCHASTIC: m_signal = new CSignalStoch(); break; case SIGNAL_TRIPLE_EA: m_signal = new CSignalTriX(); break; case SIGNAL_TRIPLE_EMA: m_signal = new CSignalTEMA(); break; case SIGNAL_WILLIAMS_PER_RANGE: m_signal = new CSignalWPR(); break; } if(CheckPointer(m_signal)!= POINTER_INVALID) m_params = params; return m_signal; } bool CSignalAdapter::Init() { if(m_params.symbol == "") /* CreateSignal method should be called first in order to update m_params */ return false; m_info.Name(m_params.symbol); if(!m_signal.Init(GetPointer(m_info), m_params.period, m_params.point)) return false; if(!m_signal.InitIndicators(GetPointer(m_indicators))) return false; m_signal.EveryTick(m_params.every_tick); m_signal.Magic(m_params.magic); m_open.Create(m_params.symbol, m_params.period); m_high.Create(m_params.symbol, m_params.period); m_low.Create(m_params.symbol, m_params.period); m_close.Create(m_params.symbol, m_params.period); m_times.Create(m_params.symbol, m_params.period); m_spread.Create(m_params.symbol, m_params.period); m_tik_vol.Create(m_params.symbol, m_params.period); m_real_vol.Create(m_params.symbol, m_params.period); m_signal.SetPriceSeries(GetPointer(m_open), GetPointer(m_high), GetPointer(m_low), GetPointer(m_close)); //m_signal.SetOtherSeries(GetPointer(m_spread), GetPointer(m_times), GetPointer(m_tik_vol), GetPointer(m_real_vol)); int mask = 1; mask = mask << m_params.usage_pattern; m_signal.PatternsUsage(mask); return true; }当然,还需要调用新创建的 Init 方法:
感谢您的出色工作,更感谢您的分享,瓦西里!
干杯
罗德里戈-哈勒
我再一次面对这样一个事实,那就是在实际做了一些事情之后,我发现实际上之前已经做了同样的事情(正如人们所说的那样,在我们之前已经发明了一切)。
有一点我想指出--在信号工作中,我从一开始就认为信号的加权平均值是买入和卖出的信号,这不符合典型形式的决策逻辑(决策树,这里已经提到过),我也是这么做的--信号的原生器中除了信号的实际列表外,还包含了 AND、ANDNOT、XOR 的信号槽。这些插槽的所有处理逻辑都是明确的,并且都在原生类中。也就是说,要构建一个策略,您只需将主信号添加到 Expert Advisor 中,并将信号添加到相应的逻辑槽中,原理与最初的相同,即每个逻辑槽最多可添加 64 个额外的过滤器。我认为这种解决方案最简单,也最容易实现。如果您对这个想法感兴趣,但有不明白的地方,请与我联系,我会告诉您更多。
如何在脚本中使用CSignalMACD 类?
我试过在原处获取信号结果,但总是得到 0: