我不知道 MetaTrader Tester 如何为每个核心选择输入。在线研究的主要想法是,从一个通道到另一个通道使用预训练模型。但是,如果测试员一次运行 Optimithation 1...4 到 Agent 1,它们都使用随机(非预训练)模型。
我还添加了一些指标和参数,共有 27 个 BarDescr....动量、波段和一目均衡 Kinko Hyo =)
int OnInit()
{
设置符号并刷新
if(! Symb.Name(_Symbol))
返回 INIT_FAILED;
Symb.Refresh();
//---
如果(!Create(Symb.Name(), TimeFrame, RSIPeriod, RSIPrice))
return INIT_FAILED;
//---
如果(!CCI.Create(Symb.Name(), TimeFrame, CCIPeriod, CCIPrice))
返回 INIT_FAILED;
//---
if(!Create(Symb.Name(), TimeFrame, ATRPeriod))
return INIT_FAILED;
//---
if(!Create(Symb.Name(), TimeFrame, FastPeriod, SlowPeriod, SignalPeriod, MACDPrice))
返回 INIT_FAILED;
//---
if (! Momentum.Create(Symb.Name(), TimeFrame, MomentumMaPeriod, MomentumApplied))
返回 INIT_FAILED;
初始化 Ichimoku Kinko Hyo 指标
如果 (! Ichimoku.Create(Symb.Name(), TimeFrame, Ichimokutenkan_senPeriod, Ichimokukijun_senPeriod, Ichimokusenkou_span_bPeriod))
返回 INIT_FAILED;
//---
if (! Bands.Create(Symb.Name(), TimeFrame, BandsMaPeriod, BandsMaShift, BandsDeviation, BandsApplied))
返回 INIT_FAILED;
//---
if(!BufferResize(HistoryBars) || !CCI.BufferResize(HistoryBars) ||| !
!ATR.BufferResize(HistoryBars)BufferResize(HistoryBars) || !MACD.BufferResize(HistoryBars)MACD.BufferResize(HistoryBars))
{
PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
返回 INIT_FAILED;
}
//---
void OnTick()
{
//---
if(! IsNewBar())
返回;
//---
int bars = CopyRates(Symb.Name(), TimeFrame, iTime(Symb.Name(), TimeFrame, 1), HistoryBars, Rates);
if(! ArraySetAsSeries(Rates, true))
返回;
//---
RSI.Refresh();
CCI.Refresh();
ATR.Refresh()刷新();
MACD.刷新(); Symb.Refresh()
Symb.Refresh();
Momentum.Refresh();
Bands.Refresh();
Symb.RefreshRates();
刷新当前条形图的 Ichimoku 值
Ichimoku.Refresh();
--- 历史数据
float atr = 0;
for (int b = 0; b < (int)HistoryBars; b++)
{
float open = (float)Rates[b].open;
float close = (float)Rates[b].close;
float rsi = (float)RSI.Main(b);
float cci = (float)CCI.Main(b);
atr = (float)ATR.Main(b);
float macd = (float)MACD.Main(b);
float sign = (float)MACD.Signal(b);
float mome = (float)Momentum.Main(b);
float bandzup = (float)Bands.Upper(b);
float bandzb = (float)Bands.Base(b);
float bandzlo = (float)Bands.Lower(b);
float tenkan = (float)Ichimoku.TenkanSen(0); 使用计算值
float kijun = (float)Ichimoku.KijunSen(1); 使用计算值
float senkasa = (float)Ichimoku.SenkouSpanA(2); 使用计算值
float senkb = (float)Ichimoku.SenkouSpanB(3); 使用计算值
检查是否存在 EMPTY_VALUE 和除以零的情况
如果 (rsi == EMPTY_VALUE || cci == EMPTY_VALUE || atr == EMPTY_VALUE || macd == EMPTY_VALUE |||)
sign == EMPTY_VALUE || mome == EMPTY_VALUE || bandzup == EMPTY_VALUE || bandzb == EMPTY_VALUE ||| bandzb == EMPTY_VALUE |||| bandzlo == EMPTY_VALUE |||...
bandzlo == EMPTY_VALUE || tenkan == EMPTY_VALUE || kijun == EMPTY_VALUE || senkasa == EMPTY_VALUE || senkasa == EMPTY_VALUE ||...
senkb == EMPTY_VALUE || kijun == 0.0 || senkb == 0.0)
{
继续
}
确保不在循环中调整缓冲区大小
int shift = b * BarDescr;
sState.state[shift] = (float)(Rates[b].close - open);
sState.state[shift + 1] = ((float)(Rates[b].close - open) + (tenkan - kijun)) / 2.0f;
sState.state[shift + 2] = (float)(Rates[b].high - open);
sState.state[shift + 3] = (float)(Rates[b].low - open);
sState.state[shift + 4] = (float)(Rates[b].high - close);
sState.state[shift + 5] = (float)(Rates[b].low - close);
sState.state[shift + 6] = (tenkan - kijun);
sState.state[shift + 7] = (float)(Rates[b].tick_volume / 1000.0f);
sState.state[shift + 8] = ((float)(Rates[b].high) - (float)(Rates[b].low));
sState.state[shift + 9] = (bandzup - bandzlo);
sState.state[shift + 10] = rsi;
sState.state[shift + 11] = cci;
sState.state[shift + 12] = atr;
sState.state[shift + 13] = macd;
sState.state[shift + 14] = sign;
sState.state[shift + 15] = mome;
sState.state[shift + 16] = (float)(Rates[b].open - tenkan);
sState.state[shift + 17] = (float)(Rates[b].open - kijun);
sState.state[shift + 18] = (float)(Rates[b].open - bandzb);
sState.state[shift + 19] = (float)(Rates[b].open - senkasa);
sState.state[shift + 20] = (float)(Rates[b].open - senkb);
sState.state[shift + 21] = (float)(Rates[b].close - tenkan);
sState.state[shift + 22] = (float)(Rates[b].close - kijun);
sState.state[shift + 23] = (float)(Rates[b].close - bandzb);
sState.state[shift + 24] = (float)(Rates[b].close - senkasa);
sState.state[shift + 25] = (float)(Rates[b].close - senkb);
sState.state[shift + 26] = senkasa - senkb;
//---
RSI.Refresh();
CCI.Refresh();
ATR.Refresh();
MACD.Refresh();
Symb.Refresh();
Momentum.Refresh();
Bands.Refresh();
Symb.RefreshRates();
// 刷新当前条形图的 Ichimoku 值
Ichimoku.Refresh();
//---
Print("State 0: ", sState.state[shift]);
Print("State 1: ", sState.state[shift + 1]);
Print("State 2: ", sState.state[shift + 2]);
打印("状态 3:",sState.state[shift + 3]);
打印("状态 4:",sState.state[shift + 4]);
打印("状态 5:",sState.state[shift + 5]);
打印("状态 6:",sState.state[shift + 6]);
打印("状态 7:",sState.state[shift + 7]);
打印("状态 8:",sState.state[shift + 8]);
打印("状态 9:",sState.state[shift + 9]);
打印("状态 10:",sState.state[shift + 10]);
打印("状态 11:",sState.state[shift + 11]);
打印("状态 12:",sState.state[shift + 12]);
打印("状态 13:",sState.state[shift + 13]);
打印("状态 14:",sState.state[shift + 14]);
打印("状态 15:",sState.state[shift + 15]);
打印("状态 16:",sState.state[shift + 16]);
打印("状态 17:",sState.state[shift + 17]);
打印("状态 18:",sState.state[shift + 18]);
打印("状态 19:",sState.state[shift + 19]);
打印("状态 20:",sState.state[shift + 20]);
打印("状态 21:",sState.state[shift + 21]);
打印("状态 22:",sState.state[shift + 22]);
打印("状态 23:",sState.state[shift + 23]);
打印("状态 24:",sState.state[shift + 24]);
打印("状态 25:",sState.state[shift + 25]);
打印("状态 26:",sState.state[shift + 26]);
Print("Tenkan Sen: ", tenkan);
Print("Kijun Sen: ", kijun);
Print("Senkou Span A: ", senkasa);
Print("Senkou Span B: ", senkb);
}
bState.AssignArray(sState.state);
我还添加了一些指标和参数,共计 27 BarDescr....Momentum, Bands & Ichimoku Kinko Hyo =)
int OnInit()
{
设置符号并刷新
if(! Symb.Name(_Symbol))
返回 INIT_FAILED;
Symb.Refresh();
//---
如果(!Create(Symb.Name(), TimeFrame, RSIPeriod, RSIPrice))
返回 INIT_FAILED;
//---
如果(!CCI.Create(Symb.Name(), TimeFrame, CCIPeriod, CCIPrice))
返回 INIT_FAILED;
//---
if(! ATR.Create(Symb.Name(, TimeFrame, ATRPeriod))Create(Symb.Name(), TimeFrame, ATRPeriod))
返回 INIT_FAILED;
//---
如果(!Create(Symb.Name(), TimeFrame, FastPeriod, SlowPeriod, SignalPeriod, MACDPrice))
返回 INIT_FAILED;
//---
如果 (! Momentum.Create(Symb.Name(), TimeFrame, MomentumMaPeriod, MomentumApplied))
返回 INIT_FAILED;
初始化 Ichimoku Kinko Hyo 指标
如果 (! Ichimoku.Create(Symb.Name(), TimeFrame, Ichimokutenkan_senPeriod, Ichimokukijun_senPeriod, Ichimokusenkou_span_bPeriod))
返回 INIT_FAILED;
//---
如果 (! Bands.Create(Symb.Name(), TimeFrame, BandsMaPeriod, BandsMaShift, BandsDeviation, BandsApplied))
返回 INIT_FAILED;
//---
if(! RSI.BufferResize(HistoryBars)BufferResize(HistoryBars) || !CCI.BufferResize(HistoryBars) || !
!ATR.BufferResize(HistoryBars)BufferResize(HistoryBars) || !MACD.BufferResize(HistoryBars)BufferResize(HistoryBars))
{
PrintFormat("%s -> %d", __FUNCTION__, __LINE__);
返回 INIT_FAILED;
}
//---
void OnTick()
{
//---
if(! IsNewBar())
返回;
//---
int bars = CopyRates(Symb.Name(), TimeFrame, iTime(Symb.Name(), TimeFrame, 1), HistoryBars, Rates);
if(! ArraySetAsSeries(Rates, true))
返回;
//---
RSI.刷新();
CCI.Refresh();
ATR.刷新();
MACD.刷新();
Symb.Refresh();
Momentum.刷新();
Bands.Refresh();
Symb.RefreshRates();
刷新当前条形图的 Ichimoku 值
Ichimoku.Refresh();
--- 历史数据
float atr = 0;
for (int b = 0; b < (int)HistoryBars; b++)
{
float open = (float)Rates[b].open;
float close = (float)Rates[b].close;
float rsi = (float)RSI.Main(b);
float cci = (float)CCI.Main(b);
atr = (float)ATR.Main(b);
float macd = (float)MACD.Main(b);
float sign = (float)MACD.Signal(b);
float mome = (float)Momentum.Main(b);
float bandzup = (float)Bands.Upper(b);
float bandzb = (float)Bands.Base(b);
float bandzlo = (float)Bands.Lower(b);
float tenkan = (float)Ichimoku.TenkanSen(0); 使用计算值
float kijun = (float)Ichimoku.KijunSen(1); 使用计算值
float senkasa = (float)Ichimoku.SenkouSpanA(2); 使用计算值
float senkb = (float)Ichimoku.SenkouSpanB(3); 使用计算值
检查是否存在 EMPTY_VALUE 和除以零的情况
if (rsi == EMPTY_VALUE || cci == EMPTY_VALUE || atr == EMPTY_VALUE || macd == EMPTY_VALUE |||)
sign == EMPTY_VALUE || mome == EMPTY_VALUE || bandzup == EMPTY_VALUE || bandzb == EMPTY_VALUE || bandzb == EMPTY_VALUE ||...
bandzlo == EMPTY_VALUE || tenkan == EMPTY_VALUE || kijun == EMPTY_VALUE || senkasa == EMPTY_VALUE || senkasa == EMPTY_VALUE |||...
senkb == EMPTY_VALUE || kijun == 0.0 || senkb == 0.0)
{
继续;
}
确保不在循环中调整缓冲区大小
int shift = b * BarDescr;
sState.state[shift] = (float)(Rates[b].close - open);
sState.state[shift + 1] = ((float)(Rates[b].close - open) + (tenkan - kijun)) / 2.0f;
sState.state[shift + 2] = (float)(Rates[b].high - open);
sState.state[shift + 3] = (float)(Rates[b].low - open);
sState.state[shift + 4] = (float)(Rates[b].high - close);
sState.state[shift + 5] = (float)(Rates[b].low - close);
sState.state[shift + 6] = (tenkan - kijun);
sState.state[shift + 7] = (float)(Rates[b].tick_volume / 1000.0f);
sState.state[shift + 8] = ((float)(Rates[b].high) - (float)(Rates[b].low));
sState.state[shift + 9] = (bandzup - bandzlo);
sState.state[shift + 10] = rsi;
sState.state[shift + 11] = cci;
sState.state[shift + 12] = atr;
sState.state[shift + 13] = macd;
sState.state[shift + 14] = sign;
sState.state[shift + 15] = mome;
sState.state[shift + 16] = (float)(Rates[b].open - tenkan);
sState.state[shift + 17] = (float)(Rates[b].open - kijun);
sState.state[shift + 18] = (float)(Rates[b].open - bandzb);
sState.state[shift + 19] = (float)(Rates[b].open - senkasa);
sState.state[shift + 20] = (float)(Rates[b].open - senkb);
sState.state[shift + 21] = (float)(Rates[b].close - tenkan);
sState.state[shift + 22] = (float)(Rates[b].close - kijun);
sState.state[shift + 23] = (float)(Rates[b].close - bandzb);
sState.state[shift + 24] = (float)(Rates[b].close - senkasa);
sState.state[shift + 25] = (float)(Rates[b].close - senkb);
sState.state[shift + 26] = senkasa - senkb;
//---
RSI.Refresh();
CCI.Refresh();
ATR.Refresh();
MACD.Refresh();
Symb.Refresh();
Momentum.Refresh();
Bands.Refresh();
Symb.RefreshRates();
// 刷新当前条形图的一目均衡数值
Ichimoku.Refresh();
//---
Print("State 0: ", sState.state[shift]);
Print("State 1: ", sState.state[shift + 1]);
打印("状态 2:",sState.state[shift + 2]);
打印("状态 3:",sState.state[shift + 3]);
打印("状态 4:",sState.state[shift + 4]);
打印("状态 5:",sState.state[shift + 5]);
打印("状态 6:",sState.state[shift + 6]);
打印("状态 7:",sState.state[shift + 7]);
打印("状态 8:",sState.state[shift + 8]);
打印("状态 9:",sState.state[shift + 9]);
打印("状态 10:",sState.state[shift + 10]);
打印("状态 11:",sState.state[shift + 11]);
打印("状态 12:",sState.state[shift + 12]);
打印("状态 13:",sState.state[shift + 13]);
打印("状态 14:",sState.state[shift + 14]);
打印("状态 15:",sState.state[shift + 15]);
打印("状态 16:",sState.state[shift + 16]);
打印("状态 17:",sState.state[shift + 17]);
打印("状态 18:",sState.state[shift + 18]);
打印("状态 19:",sState.state[shift + 19]);
打印("状态 20:",sState.state[shift + 20]);
打印("状态 21:",sState.state[shift + 21]);
打印("状态 22:",sState.state[shift + 22]);
打印("状态 23:",sState.state[shift + 23]);
打印("状态 24:",sState.state[shift + 24]);
打印("状态 25:",sState.state[shift + 25]);
打印("状态 26:",sState.state[shift + 26]);
Print("Tenkan Sen: ", tenkan);
Print("Kijun Sen: ", kijun);
Print("Senkou Span A: ", senkasa);
Print("Senkou Span B: ", senkb);
}
bState.AssignArray(sState.state);
JimReaper - 在得到图片中的结果之前,您研究了多少次您的版本?花了多长时间?
您的计算机配置(处理器、显卡、内存)如何?
谢谢
新文章 神经网络变得简单(第 66 部分):离线学习中的探索问题已发布:
使用准备好的训练数据集中的数据对模型进行离线训练,这种方法虽然有一定的优势,但其不利的一面是,环境信息被大大压缩到训练数据集的大小。这反过来又限制了探索的可能性。在本文中,我们将探讨一种方法,这种方法可以用尽可能多样化的数据来填充训练数据集。
ExORL 方法可分为 3 个主要阶段。第一阶段是收集未标记的探索性数据。这个阶段可以使用各种无监督学习算法。该方法的作者并没有限制适用算法的范围。此外,在与环境互动的过程中,在每个回合(episode)中,我们会根据之前互动的历史记录使用一种策略 π。每一回合都以状态St、行动At和后续状态St+1 的序列保存在数据集中。训练数据的收集一直持续到训练数据集全部填满为止。该训练数据集的规模受到技术规格或可用资源的限制。
在收集了状态和行动数据集之后,下一阶段就是利用给定的奖励函数对数据进行重新标记。这一阶段意味着对数据集中每个元组的奖励进行评估。
实际经验表明,通过不同方法收集的回放缓冲区可以并行使用。我使用了之前讨论过的 EA Research.mq5 和 EA ResearchExORL.mq5 收集的轨迹。第一,指出了学习完毕的 Actor 策略的优缺点。其次,我们可以尽可能多地探索环境,评估未被考虑的机会。
在反复训练模型的过程中,我设法提高了模型的性能。
虽然测试期间的交易次数总体减少了 3 倍(56 对 176),但利润却增加了近 3 倍。最大盈利交易额增加了一倍多。平均盈利交易增加了 5 倍。此外,我们还发现,在整个测试期间,余额都在增加。因此,模型的利润系数从 1.3 提高到 2.96。
作者:Dmitriy Gizlyk