文章 "神经网络变得轻松(第五十二部分):研究乐观情绪和分布校正" - 页 2 12 新评论 Dmitriy Gizlyk 2023.08.08 06:00 #11 Dmitriy Gizlyk #:我注意到 Study.mq5 专家顾问的代码中有一个错别字 文章中的文件已更新。 Viktor Kudriavtsev 2023.08.14 06:15 #12 德米特里,为什么该网络在对所有测试进行训练时, 所有交易的开仓手数均为 1 手,而不尝试更改手数?它不会尝试设置零碎手数,也不想设置超过 1 手。欧元兑美元工具,训练参数与您的相同。 Dmitriy Gizlyk 2023.08.14 14:41 #13 Viktor Kudriavtsev #: 德米特里,为什么该网络在对所有测试进行训练时, 所有交易的开仓手数均为 1 手,而不尝试更改手数?它不会尝试设置零碎手数,也不想设置超过 1 手。欧元兑美元工具的训练参数与您的相同。 在最后一个 Actor 层,我们使用 sigmoid 作为激活函数,将值限制在 [0,1] 范围内。对于 TP 和 SL,我们使用乘数来调整值。批量大小不作调整。因此,1 手是可能的最大值。 //--- 第 9 层 if(!(descr = new CLayerDescription())) return false; descr.type = defNeuronSoftActorCritic; descr.count = NActions; descr.window_out = 32; descr.optimization = ADAM; descr.activation = SIGMOID; if(!actor.Add(descr)) { delete descr; return false; } Viktor Kudriavtsev 2023.08.14 16:43 #14 Dmitriy Gizlyk #:在最后一个 Actor 层,我们使用 sigmoid 作为激活函数,将数值限制在 [0,1] 的范围内。对于 TP 和 SL,我们使用乘数来调整数值。批量大小不作调整。因此,1 手是可能的最大值。 明白了,谢谢。 JimReaper 2023.08.15 20:34 #15 ENJOY <3 //+------------------------------------------------------------------+ //| 专家勾选功能 //+------------------------------------------------------------------+ void OnTick() { //--- 如果(!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(); Symb.RefreshRates(); //--- float atr = 0; for(int b = 0; b < (int)HistoryBars; b++) { float open = (float)Rates[b].open; 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); if(rsi == EMPTY_VALUE || cci == EMPTY_VALUE || atr == EMPTY_VALUE || macd == EMPTY_VALUE || sign == EMPTY_VALUE) 继续; //--- int shift = b * BarDescr; sState.state[shift] = (float)(Rates[b].close - open); sState.state[shift + 1] = (float)(Rates[b].high - open); sState.state[shift + 2] = (float)(Rates[b].low - open); sState.state[shift + 3] = (float)(Rates[b].tick_volume / 1000.0f); sState.state[shift + 4] = rsi; sState.state[shift + 5] = cci; sState.state[shift + 6] = atr; sState.state[shift + 7] = macd; sState.state[shift + 8] = sign; } bState.AssignArray(sState.state); //--- sState.account[0] = (float)AccountInfoDouble(ACCOUNT_BALANCE); sState.account[1] = (float)AccountInfoDouble(ACCOUNT_EQUITY); //--- double buy_value = 0, sell_value = 0, buy_profit = 0, sell_profit = 0; double position_discount = 0; double multiplyer = 1.0 / (60.0 * 60.0 * 10.0); int total = PositionsTotal(); datetime current = TimeCurrent(); for(int i = 0; i < total; i++) { if(PositionGetSymbol(i) != Symb.Name()) 继续; double profit = PositionGetDouble(POSITION_PROFIT); switch((int)PositionGetInteger(POSITION_TYPE)) { case POSITION_TYPE_BUY: buy_value += PositionGetDouble(POSITION_VOLUME); buy_profit += profit; 断开; 情况 POSITION_TYPE_SELL: sell_value += PositionGetDouble(POSITION_VOLUME); sell_profit += profit; 断开; } position_discount += profit - (current - PositionGetInteger(POSITION_TIME))* multiplyer * MathAbs(profit); } sState.account[2] = (float)buy_value; sState.account[3] = (float)sell_value; sState.account[4] = (float)buy_profit; sState.account[5] = (float)sell_profit; sState.account[6] = (float)position_discount; sState.account[7] = (float)Rates[0].time; //--- bAccount.Clear(); bAccount.Add((float)((sState.account[0] - PrevBalance) / PrevBalance)); bAccount.Add((float)(sState.account[1] / PrevBalance)); bAccount.Add((float)((sState.account[1] - PrevEquity) / PrevEquity)); bAccount.Add(sState.account[2]); bAccount.Add(sState.account[3]); bAccount.Add((float)(sState.account[4] / PrevBalance)); bAccount.Add((float)(sState.account[5] / PrevBalance)); bAccount.Add((float)(sState.account[6] / PrevBalance)); double x = (double)Rates[0].time / (double)(D'2024.01.01.01' - D'2023.01.01'); bAccount.Add((float)MathSin(x != 0 ? 2.0 * M_PI * x : 0)); x = (double)Rates[0].time / (double)PeriodSeconds(PERIOD_MN1); bAccount.Add((float)MathCos(x != 0 ? 2.0 * M_PI * x : 0)); x = (double)Rates[0].time / (double)PeriodSeconds(PERIOD_W1); bAccount.Add((float)MathSin(x != 0 ? 2.0 * M_PI * x : 0)); x = (double)Rates[0].time / (double)PeriodSeconds(PERIOD_D1); bAccount.Add((float)MathSin(x != 0 ? 2.0 * M_PI * x : 0)); //--- if (bAccount.GetIndex() >= 0 && !bAccount.BufferWrite()) 返回; //--- if (!Actor.feedForward(GetPointer(bState), 1, false, GetPointer(bAccount))) 返回; //--- PrevBalance = sState.account[0]; PrevEquity = sState.account[1]; //--- vector<float> temp; Actor.getResults(temp); float delta = MathAbs(ActorResult - temp).Sum(); ActorResult = temp; //--- double min_lot = Symb.LotsMin(); double step_lot = Symb.LotsStep(); double stops = MathMax(Symb.StopsLevel(), 1) * Symb.Point(); if (temp[0] >= temp[3]) { temp[0] -= temp[3]; temp[3] = 0; } 否则 { temp[3] -= temp[0]; temp[0] = 0; } //--- 购买控制权 如果 (temp[0] < min_lot || (temp[1] * MaxTP * Symb.Point())<= stops || (temp[2] * MaxSL * Symb.Point())<= 停止) { if (buy_value > 0) CloseByDirection(POSITION_TYPE_BUY); } 否则 { buy_lot = min_lot + MathRound((double)(temp[0] - min_lot) / step_lot) * step_lot; buy_tp = NormalizeDouble(Symb.Ask() + temp[1] * MaxTP * Symb.Point(), Symb.Digits()); double buy_sl = NormalizeDouble(Symb.Ask() - temp[2] * MaxSL * Symb.Point(), Symb.Digits()); if (buy_value > 0) TrailPosition(POSITION_TYPE_BUY, buy_sl, buy_tp); 如果 (buy_value != buy_lot) { 如果 (buy_value > buy_lot) ClosePartial(POSITION_TYPE_BUY, buy_value - buy_lot); 否则 Trade.Buy(buy_lot - buy_value,Symb.Name(),Symb.Ask(),buy_sl,buy_tp); } } //--- 出售控制权 如果 (temp[3] < min_lot || (temp[4] * MaxTP * Symb.Point())<= stops || (temp[5] * MaxSL * Symb.Point())<= 停止) { 如果 (sell_value > 0) CloseByDirection(POSITION_TYPE_SELL); } 否则 { double sell_lot = min_lot + MathRound((double)(temp[3] - min_lot) / step_lot) * step_lot; double sell_tp = NormalizeDouble(Symb.Bid() - temp[4] * MaxTP * Symb.Point(), Symb.Digits()); double sell_sl = NormalizeDouble(Symb.Bid() + temp[5] * MaxSL * Symb.Point(), Symb.Digits()); 如果(sell_value > 0) TrailPosition(POSITION_TYPE_SELL, sell_sl, sell_tp); 如果 (sell_value != sell_lot) { 如果 (sell_value > sell_lot) ClosePartial(POSITION_TYPE_SELL, sell_value - sell_lot); 否则 Trade.Sell(sell_lot - sell_value,Symb.Name(),Symb.Bid(),sell_sl,sell_tp); } } // 计算初始奖励 float iRewards = bAccount[0]; vector<float> log_prob; Actor.GetLogProbs(log_prob); // 将 ATR 归一化到 [0, 1] 范围内 float minATR = -100.0; // 根据数据调整这些值 float maxATR = 100.0; float norm_atr = (atr - minATR) / (maxATR - minATR); // 为标准化定义权重 float minWeight = 0.0; float maxWeight = 1.0; // 根据权重归一化初始奖励和归一化 ATR float norm_iRewards = (iRewards - minWeight) / (maxWeight - minWeight); float norm_norm_atr = (norm_atr - minWeight) / (maxWeight - minWeight); // 计算无交易惩罚 double penalty = (buy_value + sell_value) == 0 ?(norm_norm_atr + atr / (PrevBalance + LogProbMultiplier)): 0.0; // 更新奖励和对数概率 for (ulong i = 0; i < temp.Size(); i++) { sState.action[i] = temp[i]; sState.log_prob[i] = log_prob[i]; } // 根据 log_prob_sum 计算增量 float iRewards_increment = MathLog((float)PrevBalance); // 根据初始常模调整奖励 if (norm_iRewards != 0) { norm_iRewards += norm_norm_atr + iRewards_increment; } // 对 norm_iRewards 进行 Z 分数归一化处理 float meanRewards = -10.0; // 计算一段时间内奖励的平均值 float stdRewards = 10.0; // 计算一段时间内奖励的标准差float normalized_iRewards = (norm_iRewards - meanRewards) / stdRewards; // 应用幂变换来增强数据分布(例如,盒式-考克斯变换) float power = 0.5; // 根据需要调整幂参数 float transformed_reward = (pow(1 + normalised_iRewards, power) - 1) / power; // 应用指数变换以增强数据分布 float ZReward = (transformed_reward - (LogProbMultiplier)) / (5 - (LogProbMultiplier)); float Mreward = MathLog10(ZReward + 1); float reward = (Mreward - (-1.0f)) / (0.4f - (-1.0f)); 应用平方根变换 将映射值计算回 [1, 100] 范围内 float SRQTreward = sqrt(reward); 打印奖励和其他信息 Print("Buy Value: ", buy_value); Print("Sell Value: ", sell_value); Print("Temperature: ", temp); Print("Temperature Size: ", temp.Size()); Print("iRewards: ", iRewards); Print("Normalised ATR: ", norm_norm_atr); Print("Normalized iRewards: ", normalized_iRewards); Print("Transformed Reward: ", transformed_reward); Print("轨迹奖励:", ZReward); Print("MATHLOG: ", Mreward); Print("Scaled Reward: ", reward); Print("SRQT Reward: ", SRQTreward); 将状态和归一化奖励添加到轨迹中 如果 (! Base.Add(sState, reward)) { ExpertRemove(); 处理向 Base 添加失败的情况 } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //|| //+------------------------------------------------------------------+ bool CreateDescriptions(CArrayObj *actor, CArrayObj *critic) { //--- CLayerDescription *descr; //--- if(!actor) { actor = new CArrayObj(); if(!actor) 返回 false; } if(!critic) { critic = new CArrayObj(); if(!critic) 返回 false; } //--- Actor actor.Clear(); //--- 输入层 if(!(descr = new CLayerDescription())) 返回 false; descr.type = defNeuronBaseOCL; int prev_count = descr.count = (HistoryBars * BarDescr); descr.window = 0; descr.activation = None; descr.optimisation = ADAM; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 1 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronConvOCL; prev_count = descr.count = prev_count - 1; descr.window = 7; descr.step = 3; descr.window_out = 8; descr.activation = LReLU; descr.optimisation = ADAM; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 2 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronConvOCL; prev_count = descr.count = prev_count - 1; descr.window = 5; descr.step = 2; descr.window_out = 8; descr.activation = LReLU; descr.optimisation = ADAM; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 3 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronConvOCL; prev_count = descr.count = prev_count - 1; descr.window = 3; descr.step = 1; descr.window_out = 8; descr.activation = LReLU; descr.optimisation = ADAM; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 4 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronBaseOCL; descr.count = 1024; descr.activation = LReLU; descr.optimisation = ADAM; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 5 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronBaseOCL; prev_count = descr.count = 512; descr.activation = LReLU; descr.optimisation = ADAM; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 6 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronConvOCL; prev_count = descr.count = prev_count - 1; descr.window = 6; descr.step = 2; descr.window_out = 8; descr.activation = LReLU; descr.optimisation = ADAM; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 7 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronConvOCL; prev_count = descr.count = prev_count - 1; descr.window = 4; descr.step = 2; descr.window_out = 8; descr.activation = LReLU; descr.optimisation = ADAM; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 8 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronConvOCL; prev_count = descr.count = prev_count - 1; descr.window = 2; descr.step = 1; descr.window_out = 8; descr.activation = LReLU; descr.optimisation = ADAM; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 9 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronConvOCL; prev_count = descr.count = prev_count; descr.window = 8; descr.step = 8; descr.window_out = 8; descr.activation = LReLU; descr.optimisation = ADAM; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 10 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronBatchNormOCL; descr.count = prev_count; descr.batch = 1000; descr.activation = None; descr.optimisation = ADAM; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 11 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronBaseOCL; descr.count = 1024; descr.activation = LReLU; descr.optimisation = ADAM; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 12 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronBaseOCL; prev_count = descr.count = 512; descr.activation = LReLU; descr.optimisation = ADAM; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 13 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronConcatenate; descr.count = LatentCount; descr.window = prev_count; descr.step = AccountDescr; descr.optimise = ADAM; descr.activation = SIGMOID; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 14 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronBaseOCL; descr.count = 1024; descr.activation = LReLU; descr.optimisation = ADAM; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 15 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronBaseOCL; prev_count = descr.count = 1024; descr.activation = LReLU; descr.optimisation = ADAM; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 16 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronBaseOCL; descr.count = prev_count; descr.activation = LReLU; descr.optimisation = ADAM; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 第 17 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronSoftActorCritic; descr.count = NActions; descr.window_out = 32; descr.optimise = ADAM; descr.activation = SIGMOID; if(!actor.Add(descr)) { 删除 descr; return false; } //--- 评论家 critic.Clear(); //--- 输入层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronBaseOCL; prev_count = descr.count = LatentCount; descr.window = 0; descr.activation = None; descr.optimisation = ADAM; if(!critic.Add(descr)) { 删除 descr; return false; } //--- 第 1 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronConcatenate; descr.count = 1024; descr.window = prev_count; descr.step = 6; descr.optimise = ADAM; descr.activation = LReLU; if(!critic.Add(descr)) { 删除 descr; return false; } //--- 第 2 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronBaseOCL; descr.count = 1024; descr.activation = LReLU; descr.optimisation = ADAM; if(!critic.Add(descr)) { 删除 descr; return false; } //--- 第 3 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronBaseOCL; descr.count = 1024; descr.activation = LReLU; descr.optimisation = ADAM; if(!critic.Add(descr)) { 删除 descr; return false; } //--- 第 4 层 if(!(descr = new CLayerDescription()))) 返回 false; descr.type = defNeuronBaseOCL; descr.count = 1024; descr.activation = LReLU; descr.optimisation = ADAM; if(!critic.Add(descr)) { 删除 descr; return false; } --- 第 5 层 if(!( descr = new CLayerDescription()))) return false; descr.type = defNeuronBaseOCL; descr.count = 1; descr.optimise = ADAM; descr.activation = None; if(!critic.Add(descr)) { 删除 descr; return false; } //--- 返回 true; } Discussing the article: "Neural 文章 "神经网络变得轻松(第四十九部分):软性扮演者-评价者" 文章 "神经网络变得轻松(第五十部分):软性扮演者-评价者(模型优化)" JimReaper 2023.08.17 03:05 #16 谢谢 附加的文件: Dmtry.PNG 34 kb 12 新评论 您错过了交易机会: 免费交易应用程序 8,000+信号可供复制 探索金融市场的经济新闻 注册 登录 拉丁字符(不带空格) 密码将被发送至该邮箱 发生错误 使用 Google 登录 您同意网站政策和使用条款 如果您没有帐号,请注册 可以使用cookies登录MQL5.com网站。 请在您的浏览器中启用必要的设置,否则您将无法登录。 忘记您的登录名/密码? 使用 Google 登录
我注意到 Study.mq5 专家顾问的代码中有一个错别字
文章中的文件已更新。
德米特里,为什么该网络在对所有测试进行训练时, 所有交易的开仓手数均为 1 手,而不尝试更改手数?它不会尝试设置零碎手数,也不想设置超过 1 手。欧元兑美元工具的训练参数与您的相同。
在最后一个 Actor 层,我们使用 sigmoid 作为激活函数,将值限制在 [0,1] 范围内。对于 TP 和 SL,我们使用乘数来调整值。批量大小不作调整。因此,1 手是可能的最大值。
在最后一个 Actor 层,我们使用 sigmoid 作为激活函数,将数值限制在 [0,1] 的范围内。对于 TP 和 SL,我们使用乘数来调整数值。批量大小不作调整。因此,1 手是可能的最大值。
明白了,谢谢。