記事「ニューラルネットワークが簡単に(第66回):オフライン学習における探索問題」についてのディスカッション

 

新しい記事「ニューラルネットワークが簡単に(第66回):オフライン学習における探索問題」はパブリッシュされました:

モデルは、用意された訓練データセットのデータを使用してオフラインで訓練されます。一定の利点がある反面、環境に関する情報が訓練データセットのサイズに大きく圧縮されてしまうというマイナス面もあります。それが逆に、探求の可能性を狭めています。この記事では、可能な限り多様なデータで訓練データセットを埋めることができる方法について考えます。

ExORL法は大きく3つの段階に分けられます。最初の段階は、ラベルのない探索的データの収集です。この段階では、さまざまな教師なし学習アルゴリズムを使用することができます。この方法の著者は、適用できるアルゴリズムの範囲を限定していません。さらに、環境との相互作用の過程では、各エピソードにおいて、過去の相互作用の履歴に応じた方策πを用います。各エピソードは、状態St、行動At、それに続く状態St+1のシーケンスとしてデータセットに保存されます。訓練データの収集は、訓練データセットが完全に埋まるまで続けられます。この訓練データセットのサイズは、技術仕様や利用可能なリソースによって制限されます。

状態と行動のデータセットを収集した後、次の段階は、与えられた報酬関数を使用してデータを関連付けることです。この段階は、データセットの各タプルに対する報酬の評価を意味します。

実際の経験から、異なる方法で収集された1つの再生バッファで並行して使用できる可能性があります。先に説明したEAResearch.mq5とEAResearchExORL.mq5で収集した軌道の両方を使用しました。最初のEAは、学習したActor方策の長所と短所を示しています。もうひとつでは、可能な限り環境を探索し、未知のチャンスを評価することができます。

モデルの反復訓練の過程で、そのパフォーマンスを向上させることに成功しました。

テスト結果

テスト結果

テスト期間中の取引回数は3倍(56回対176回)に減少しましたが、利益は約3倍に増加しました。最大勝ち取引額は2倍以上になり、平均利益率は5倍になりましました。さらに、全テスト期間を通じて残高が増加していることが確認されましました。その結果、このモデルのプロフィットファクターは1.3から2.96に上昇しました。 

作者: Dmitriy Gizlyk

 
ドミトリー、こんにちは。5人のエージェントを使い、100のパスを集めたと書かれています。収集は20回行いましたか?そうでなければ、5つのエージェントで5つのパスしか収集されません。また、同じパラメータでExpert Advisorを実行した場合、再計算は行わず、キャッシュから結果を引き出します。それとも、この5つのエージェントを次の収集ごとに移動させたのでしょうか?この点について説明してください。
 
Viktor Kudriavtsev #:
ドミトリー、こんにちは。5人のエージェントを使い、100のパスを集めたと書かれています。回収を20回実行しましたか?そうでなければ、5つのエージェントで5つのパスしか収集されません。また、同じパラメータでExpert Advisorを実行した場合、再計算は行わず、キャッシュから結果を引き出します。それとも、この5つのエージェントを次の収集ごとに移動させたのでしょうか?この点について説明してください。

20回実行しましたが、キャッシュをクリアしてから実行しました。モデルファイルはエージェント番号にバインドされているため、エージェントをシフトすることはできません。したがって、毎回エージェントをシフトさせると、新しいランダムなモデルが作成され、期待する効果が得られません。

 
Dmitriy Gizlyk #:

20回実行しましたが、開始前にキャッシュをクリアしました。モデルファイルはエージェント番号とリンクしているので、エージェントをずらすことはできない。そのため、エージェントをずらすと、毎回新しいランダムなモデルが作成され、期待する効果が得られません。

ドミトリーさん、こんにちは。同じ効果が得られますか?

input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1;

input double MinProfit = 10;
input int Agent = 1;
input int Optimisation = 1;

then set agent to 5 and Optimisation to 20
Total of 100...


 
JimReaper #:
こんにちは、ドミトリー。同じ効果がありますか?

input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1;

input double MinProfit = 10;
input int Agent = 1;
input int Optimisation = 1;

then set agent to 5 and Optimisation to 20
Total of 100...



何コア使用しましたか?

 
Dmitriy Gizlyk #:

こんにちは、
何コアを使用しましたか?

私は4コアしか使っていません。


ファイル:
Dimi_1.png  2 kb
Dimi_2.png  5 kb
 
JimReaper #:


MetaTrader Testerが各コアの入力をどのように選択するかは知らない。オンラインスタディでの主なアイデアは、あるパスから別のパスへ、事前に訓練されたモデルを使用することです。しかし、テスターがOptimithation 1...4からAgent 1を1つのパスで実行すると、それらはすべてランダムな(事前に訓練されていない)モデルを使用します。

 
Dmitriy Gizlyk #:

MetaTrader Testerが各コアの入力をどのように選択するのかわかりません。オンラインスタディでの主なアイデアは、あるパスから別のパスへと事前に訓練されたモデルを使用することです。しかし、テスターがOptimithation 1...4からAgent 1を1つのパスで実行すると、それらはすべてランダムな(事前に訓練されていない)モデルを使用します。

わかりました!ありがとうございました!

また、いくつかのインジケータとパラメータを追加しました。モメンタム、バンド、一目均衡表 =)

int OnInit()

{

シンボルの設定とリフレッシュ

if(! Symb.Name(_Symbol))

return INIT_FAILED;

Symb.Refresh();

//---

if(! RSI.Create(Symb.Name(), TimeFrame, RSIPeriod, RSIPrice))

return INIT_FAILED;

//---

if(! CCI.Create(Symb.Name(), TimeFrame, CCIPeriod, CCIPrice))

return INIT_FAILED;

//---

if(! ATR.Create(Symb.Name(), TimeFrame, ATRPeriod))

return INIT_FAILED;

//---

if(! MACD.Create(Symb.Name(),TimeFrame,FastPeriod,SlowPeriod,SignalPeriod,MACDPrice)))。

return INIT_FAILED;

//---

if (! Momentum.Create(Symb.Name(), TimeFrame, MomentumMaPeriod, MomentumApplied)))

return INIT_FAILED;

一目均衡表のインジケータを初期化します。

if (! Ichimoku.Create(Symb.Name(), TimeFrame, Ichimokutenkanan_senPeriod, Ichimokukijun_senPeriod, Ichimokusenkou_span_bPeriod))))

return INIT_FAILED;

//---

if (! Bands.Create(Symb.Name(), TimeFrame, BandsMaPeriod, BandsMaShift, BandsDeviation, BandsApplied)))

return INIT_FAILED;

//---

if(! RSI.BufferResize(HistoryBars) || !CCI.BufferResize(HistoryBars) || !

!ATR.BufferResize(HistoryBars) || !MACD.BufferResize(HistoryBars))

{

PrintFormat("%s -> %d", __FUNCTION__, __LINE__);

return 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.Refresh();

Symb.Refresh();

モメンタム.リフレッシュ();

Bands.Refresh();

Symb.RefreshRates();

現在のバーのイチモク値をリフレッシュする

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.メイン(b);

float macd = (float)MACD.Main(b);

float sign = (float)MACD.シグナル(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 || bandzlo == EMPTY_VALUE

bandzlo == EMPTY_VALUE || tenkan == EMPTY_VALUE || kijun == EMPTY_VALUE || senkasa == EMPTY_VALUE || senkasa == EMPTY_VALUE || senkasa == EMPTY_VALUE || senkb == EMPTY_VALUE || senkb == 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();

モメンタム.リフレッシュ()

Bands.Refresh();

Symb.RefreshRates();

// 現在のバーの一目均衡表の値をリフレッシュする。

Ichimoku.Refresh();

//---

Print("State 0: ", sState.state[shift]);

Print("State 1: ", sState.state[shift + 1]);

Print("State 2: ", sState.state[shift + 2]);

Print("State 3: ", sState.state[shift + 3]);

Print("State 4: ", sState.state[shift + 4]);

Print("State 5: ", sState.state[shift + 5]);

Print("State 6: ", sState.state[shift + 6]);

Print("State 7: ", sState.state[shift + 7]);

Print("State 8: ", sState.state[shift + 8]);

Print("State 9: ", sState.state[shift + 9]);

Print("State 10: ", sState.state[shift + 10]);

Print("State 11: ", sState.state[shift + 11]);

Print("State 12: ", sState.state[shift + 12]);

Print("State 13: ", sState.state[shift + 13]);

Print("State 14: ", sState.state[shift + 14]);

Print("State 15: ", sState.state[shift + 15]);

Print("State 16: ", sState.state[shift + 16]);

Print("State 17: ", sState.state[shift + 17]);

Print("State 18: ", sState.state[shift + 18]);

Print("State 19: ", sState.state[shift + 19]);

Print("State 20: ", sState.state[shift + 20]);

Print("State 21: ", sState.state[shift + 21]);

Print("State 22: ", sState.state[shift + 22]);

Print("State 23: ", sState.state[shift + 23]);

Print("State 24: ", sState.state[shift + 24]);

Print("State 25: ", sState.state[shift + 25]);

Print("State 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 #:
理解した!ありがとうございます!

また、いくつかのインジケータとパラメータを追加しました。モメンタム、バンド、一目均衡表 =)

int OnInit()

{

シンボルの設定とリフレッシュ

if(! Symb.Name(_Symbol))

return INIT_FAILED;

Symb.Refresh();

//---

if(! RSI.Create(Symb.Name(), TimeFrame, RSIPeriod, RSIPrice))

return INIT_FAILED;

//---

if(! CCI.Create(Symb.Name(), TimeFrame, CCIPeriod, CCIPrice))

return INIT_FAILED;

//---

if(! ATR.Create(Symb.Name(), TimeFrame, ATRPeriod))

return INIT_FAILED;

//---

if(! MACD.Create(Symb.Name(), TimeFrame, FastPeriod, SlowPeriod, SignalPeriod, MACDPrice))

return INIT_FAILED;

//---

if (! Momentum.Create(Symb.Name(), TimeFrame, MomentumMaPeriod, MomentumApplied))

return INIT_FAILED;

一目均衡表の初期化

If (! Ichimoku.Create(Symb.Name(), TimeFrame, Ichimokutenkan_senPeriod, Ichimokukijun_senPeriod, Ichimokusenkou_span_bPeriod)).

return INIT_FAILED;

//---

if (! Bands.Create(Symb.Name(), TimeFrame, BandsMaPeriod, BandsMaShift, BandsDeviation, BandsApplied))

return INIT_FAILED;

//---

if(! RSI.BufferResize(HistoryBars) || !CCI.BufferResize(ヒストリーバーズ) ||)

!ATR.BufferResize(HistoryBars) || !MACD.BufferResize(HistoryBars)BufferResize(HistoryBars))

{

PrintFormat("%s -> %d", __FUNCTION__, __LINE__);

return 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.Refresh()Refresh();

Symb.Refresh();

モメンタム.リフレッシュ();

Bands.Refresh();

Symb.RefreshRates();

現在のバーのイチモク値を更新する

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 cci = (float)CCI.Main(b)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 || を参照。

バンドズロ==EMPTY_VALUE||天覧==EMPTY_VALUE||紀順==EMPTY_VALUE||千笠==EMPTY_VALUE||千笠==EMPTY_VALUE||千笠==EMPTY_VALUE||千笠==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();

モメンタム.リフレッシュ();

Bands.Refresh();

Symb.RefreshRates();

// 現在のバーのイチモク値をリフレッシュする

Ichimoku.Refresh();

//---

Print("State 0: ", sState.state[shift]);

Print("State 1: ", sState.state[shift + 1]);

Print("State 2: ", sState.state[shift + 2]);

Print("State 3: ", sState.state[shift + 3]);

Print("State 4: ", sState.state[shift + 4]);

Print("State 5: ", sState.state[shift + 5]);

Print("State 6: ", sState.state[shift + 6]);

Print("State 7: ", sState.state[shift + 7]);

Print("State 8: ", sState.state[shift + 8]);

Print("State 9: ", sState.state[shift + 9]);

Print("State 10: ", sState.state[shift + 10]);

Print("State 11: ", sState.state[shift + 11]);

Print("State 12: ", sState.state[shift + 12]);

Print("State 13: ", sState.state[shift + 13]);

Print("State 14: ", sState.state[shift + 14]);

Print("State 15: ", sState.state[shift + 15]);

Print("State 16: ", sState.state[shift + 16]);

Print("State 17: ", sState.state[shift + 17]);

Print("State 18: ", sState.state[shift + 18]);

Print("State 19: ", sState.state[shift + 19]);

Print("State 20: ", sState.state[shift + 20]);

Print("State 21: ", sState.state[shift + 21]);

Print("State 22: ", sState.state[shift + 22]);

Print("State 23: ", sState.state[shift + 23]);

Print("State 24: ", sState.state[shift + 24]);

Print("State 25: ", sState.state[shift + 25]);

Print("State 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 - 写真のような結果が出るまで、何サイクル研究しましたか? データ収集 - トレーニング)。また、どのくらい時間がかかりましたか?


コンピュータの構成(プロセッサ、ビデオカード、RAM)を教えてください。


ありがとうございます。

 
親愛なる皆さん、5人のエージェントから資金を集めるのに約8時間かかります。8コアのプロセッサを使っています。これは遅すぎるのでしょうか、それとも普通なのでしょうか?教えてください。
 
JimReaper #:
こんにちは、ドミトリー。僕はこれを使ってやったんだけど、同じ効果があるかな?

input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1;

input double MinProfit = 10;
input int Agent = 1;
input int Optimisation = 1;

then set agent to 5 and Optimisation to 20
Total of 100...


こんにちは、ジム

コードの中でエージェントが参照されているのはわかりますが、オプティマイゼーションが 見当たりません。この新しいパラメータを使用するために、さらにコードを追加したのですか?
ありがとう
Paul