Discusión sobre el artículo "Redes neuronales: así de sencillo (Parte 52): Exploración con optimismo y corrección de la distribución" - página 2

 
Dmitriy Gizlyk #:

Me di cuenta de un error tipográfico en el código del Asesor Experto Study.mq5

Los archivos en el artículo se han actualizado.

 
Dmitry, ¿por qué esta red abre todas las operaciones con exactamente 1 lote, cuando se entrena en todas las pruebas, y no intenta cambiar el lote? No intenta poner lotes fraccionados y tampoco quiere poner más de 1 lote. Los parámetros de entrenamiento son los mismos que los suyos.
 
Viktor Kudriavtsev #:
Dmitry, ¿por qué esta red abre todas las operaciones con exactamente 1 lote, cuando se entrena en todas las pruebas, y no intenta cambiar el lote? No intenta establecer lotes fraccionados y tampoco quiere establecer más de 1 lote. Los parámetros de entrenamiento son los mismos que los suyos.

En la última capa Actor utilizamos sigmoide como función de activación, que limita los valores en el rango [0,1]. Para TP y SL, usamos un multiplicador para ajustar los valores. El tamaño del lote no se ajusta. Por lo tanto, 1 lote es el valor máximo posible.

//--- capa 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;
     }
 
Dmitriy Gizlyk #:

En la última capa Actor, utilizamos sigmoide como función de activación, que limita los valores al intervalo [0,1]. Para TP y SL utilizamos un multiplicador para ajustar los valores. El tamaño del lote no se ajusta. Por lo tanto, 1 lote es el valor máximo posible.

Entendido, Gracias.

 
DISFRUTA <3

//+------------------------------------------------------------------+
//| Función tick experto |
//+------------------------------------------------------------------+
void OnTick()
{
//---
if(!IsNewBar())
vuelve;
//---
int bars = CopyRates(Symb.Name(), TimeFrame, iTime(Symb.Name(), TimeFrame, 1), HistoryBars, Rates);
if(!ArraySetAsSeries(Tipos, true))
vuelve;
//---
RSI.Refresh();
CCI.Refresh();
ATR.Actualizar();
MACD.Actualizar();
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.Señal(b);
if(rsi == EMPTY_VALUE || cci == EMPTY_VALUE || atr == EMPTY_VALUE || macd == EMPTY_VALUE || sign == EMPTY_VALUE)
continuar;
//---
int desplazamiento = 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 valor_compra = 0, valor_venta = 0, beneficio_compra = 0, beneficio_venta = 0;
double posición_descuento = 0;
double multiplicador = 1.0 / (60.0 * 60.0 * 10.0);
int total = TotalPosiciones();
datetime actual = TimeCurrent();
for(int i = 0; i < total; i++)
{
if(PositionGetSymbol(i) != Symb.Name())
continúa;
double beneficio = PositionGetDouble(POSITION_PROFIT);
switch((int)PositionGetInteger(POSITION_TYPE))
{
case POSITION_TYPE_BUY:
valor_compra += PositionGetDouble(VOLUMEN_POSICION);
comprar_ganancia += ganancia;
pausa;
case POSITION_TYPE_SELL:
valor_venta += PositionGetDouble(VOLUMEN_POSICION);
vender_ganancia += ganancia;
interrupción;
}
position_discount += beneficio - (actual - PositionGetInteger(POSITION_TIME)) * multiplicador * MathAbs(beneficio);
}
sEstado.cuenta[2] = (float)valor_compra;
sState.account[3] = (float)sell_value;
sState.account[4] = (float)buy_profit;
sState.account[5] = (float)sell_profit;
sState.account[6] = (float)posición_descuento;
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(sEstado.cuenta[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)Tarifas[0].hora / (double)(D'2024.01.01.01' - D'2023.01.01');
bAccount.Add((float)MathSin(x != 0 ? 2.0 * M_PI * x : 0));
x = (double)Tasas[0].tiempo / (double)PeriodoSegundos(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())
devuelve;
//---
if (!Actor.feedForward(GetPointer(bState), 1, false, GetPointer(bAccount)))
vuelve;
//---
SaldoAnterior = sEstado.cuenta[0];
PrevEquity = sState.account[1];
//---
vector<float> temp;
Actor.getResults(temp);
float delta = MathAbs(ActorResultado - temp).Sum();
ActorResultado = temp;
//---
double min_lot = Symb.LotsMin();
double paso_lote = Symb.LotesPaso();
double stops = MathMax(Symb.StopsLevel(), 1) * Symb.Point();
if (temp[0] >= temp[3])
{
temp[0] -= temp[3];
temp[3] = 0;
}
si no
{
temp[3] -= temp[0];
temp[0] = 0;
}
//--- comprar control
if (temp[0] < min_lot || (temp[1] * MaxTP * Symb.Point()) <= stops || (temp[2] * MaxSL * Symb.Point()) <= paradas)
{
if (valor_compra > 0)
CloseByDirection(POSITION_TYPE_BUY);
}
si no
{
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 (valor_compra > 0)
TrailPosition(POSITION_TYPE_BUY, buy_sl, buy_tp);
if (buy_value != buy_lot)
{
si (valor_compra > lote_compra)
ClosePartial(POSITION_TYPE_BUY, buy_value - buy_lot);
si no
Trade.Buy(buy_lot - buy_value, Symb.Name(), Symb.Ask(), buy_sl, buy_tp);
}
}
//--- vender control
if (temp[3] < min_lot || (temp[4] * MaxTP * Symb.Point()) <= stops || (temp[5] * MaxSL * Symb.Point()) <= paradas)
{
si (valor_venta > 0)
CloseByDirection(POSITION_TYPE_SELL);
}
si no
{
double vender_lote = min_lote + MathRound((double)(temp[3] - min_lote) / paso_lote) * paso_lote;
double vender_tp = NormalizeDouble(Symb.Oferta() - temp[4] * MaxTP * Symb.Punto(), Symb.Dígitos());
double sell_sl = NormalizeDouble(Symb.Bid() + temp[5] * MaxSL * Symb.Point(), Symb.Digits());
if (valor_venta > 0)
TrailPosition(POSITION_TYPE_SELL, sell_sl, sell_tp);
if (sell_value != sell_lot)
{
si (valor_venta > lote_venta)
ClosePartial(POSITION_TYPE_SELL, sell_value - sell_lot);
si no
Comercio.Vender(vender_lote - vender_valor, Symb.Nombre(), Symb.Oferta(), vender_sl, vender_tp);
}
}
// Calcular recompensas iniciales
float iRecompensas = bCuenta[0];
vector<float> log_prob;
Actor.GetLogProbs(log_prob);
// Normalizar ATR al rango [0, 1]
float minATR = -100.0; // Ajuste estos valores basándose en sus datos
float maxATR = 100.0;
float norm_atr = (atr - minATR) / (maxATR - minATR);
// Definir pesos para la normalización
float minPeso = 0.0;
float maxPeso = 1.0;
// Normalizar las recompensas iniciales y el ATR normalizado en función de los pesos.
float norm_iRecompensas = (iRecompensas - minPeso) / (maxPeso - minPeso);
float norm_norm_atr = (norm_atr - minPeso) / (maxPeso - minPeso);
// Calcula la penalización por no operar
doble penalización = (valor_compra + valor_venta) == 0 ? (norm_norm_atr + atr / (PrevBalance + LogProbMultiplier)) : 0.0;
// Actualizar recompensas y probabilidades logarítmicas
for (ulong i = 0; i < temp.Size(); i++)
{
sState.action[i] = temp[i];
sState.log_prob[i] = log_prob[i];
}
// Calcular incremento basado en log_prob_sum
float iRewards_increment = MathLog((float)PrevBalance);
// Ajustar recompensas en base a norm_iRewards inicial
if (norm_iRewards != 0)
{
norm_iRewards += norm_norm_atr + iRewards_increment;
}
// Aplicar normalización de puntuación Z a norm_iRewards
float meanRewards = -10.0; // Calcular la media de las recompensas a lo largo del tiempo
float stdRewards = 10.0; // Calcular la desviación estándar de las recompensas a lo largo del tiempo
float normalized_iRewards = (norm_iRewards - meanRewards) / stdRewards;
// Aplicar la transformación de potencia para mejorar la distribución de los datos (por ejemplo, transformación de Box-Cox)
float power = 0.5; // Ajuste el parámetro de potencia según sea necesario
float recompensa_transformada = (pow(1 + recompensa_i normalizada, potencia) - 1) / potencia;
// Aplicar transformación exponencial para mejorar la distribución de los datos
float ZRecompensa = (recompensa_transformada - (LogProbMultiplier)) / (5 - (LogProbMultiplier));
float Mreward = MathLog10(ZReward + 1);
float recompensa = (Mreward - (-1.0f)) / (0.4f - (-1.0f));
Aplica la transformación de raíz cuadrada
Calcula los valores mapeados de vuelta al rango [1, 100]
float SRQTreward = sqrt(recompensa);
Imprime las recompensas y otra información
Print("Valor de compra: ", valor_compra);
Imprimir("Valor de venta: ", valor_de_venta);
Print("Temperatura: ", temp);
Print("Tamaño temperatura: ", temp. Tamaño());
Imprimir("iRecompensas: ", iRecompensas);
Print("ATR normalizado: ", norm_norm_atr);
Print("iRewards normalizado: ", normalized_iRewards);
Print("Recompensa transformada: ", recompensa_transformada);
Print("Recompensa de trayectoria: ", ZRecompensa);
Print("MATHLOG: ", Mreward);
Print("Recompensa escalada: ", recompensa);
Print("Recompensa SRQT: ", recompensa SRQT);
Añade el estado y las recompensas normalizadas a la trayectoria
if (! Base.Add(sEstado, recompensa))
{
ExpertRemove(); Maneja el caso en que la adición a Base falla
}
}
//+------------------------------------------------------------------+



//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
bool CreateDescriptions(CArrayObj *actor, CArrayObj *critic)
{
//---
CLayerDescription *descr;
//---
if(!actor)
{
actor = new CArrayObj();
if(!actor)
return false;
}
if(!critic)
{
critic = new CArrayObj();
if(!critic)
return false;
}
//--- Actor
actor.Clear();
//--- Capa de entrada
if(!(descr = new CLayerDescription()))
return false;
descr.type = defNeuronBaseOCL;
int prev_count = descr.count = (HistoryBars * BarDescr);
descr.window = 0;
descr.activation = None;
descr.optimización = ADAM;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 1
if(!(descr = new CLayerDescription())))
return 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.optimización = ADAM;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 2
if(!(descr = new CLayerDescription())))
return 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.optimización = ADAM;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 3
if(!(descr = new CLayerDescription())))
return 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.optimización = ADAM;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 4
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronBaseOCL;
descr.count = 1024;
descr.activation = LReLU;
descr.optimisation = ADAM;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 5
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronBaseOCL;
prev_count = descr.count = 512;
descr.activation = LReLU;
descr.optimisation = ADAM;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 6
if(!(descr = new CLayerDescription())))
return 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.optimización = ADAM;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 7
if(!(descr = new CLayerDescription())))
return 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.optimización = ADAM;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 8
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronConvOCL;
prev_count = descr.count = prev_count - 1;
descr.window = 2;
descr.paso = 1;
descr.window_out = 8;
descr.activation = LReLU;
descr.optimización = ADAM;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 9
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronConvOCL;
prev_count = descr.count = prev_count;
descr.window = 8;
descr.paso = 8;
descr.window_out = 8;
descr.activation = LReLU;
descr.optimización = ADAM;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 10
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronBatchNormOCL;
descr.count = prev_count;
descr.batch = 1000;
descr.activation = None;
descr.optimización = ADAM;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 11
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronBaseOCL;
descr.count = 1024;
descr.activation = LReLU;
descr.optimisation = ADAM;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 12
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronBaseOCL;
prev_count = descr.count = 512;
descr.activation = LReLU;
descr.optimisation = ADAM;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 13
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronConcatenate;
descr.count = LatentCount;
descr.window = recuento_previo;
descr.paso = AccountDescr;
descr.optimizar = ADAM;
descr.activation = SIGMOID;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 14
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronBaseOCL;
descr.count = 1024;
descr.activation = LReLU;
descr.optimisation = ADAM;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 15
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronBaseOCL;
prev_count = descr.count = 1024;
descr.activation = LReLU;
descr.optimisation = ADAM;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 16
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronBaseOCL;
descr.count = prev_count;
descr.activation = LReLU;
descr.optimisation = ADAM;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- capa 17
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronSoftActorCritic;
descr.count = NActions;
descr.window_out = 32;
descr.optimise = ADAM;
descr.activation = SIGMOID;
if(!actor.Add(descr))
{
borrar descr;
return false;
}
//--- Crítico
critic.Clear();
//--- Capa de entrada
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronBaseOCL;
prev_count = descr.count = LatentCount;
descr.window = 0;
descr.activation = None;
descr.optimización = ADAM;
if(!critic.Add(descr))
{
borrar descr;
return false;
}
//--- capa 1
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronConcatenate;
descr.count = 1024;
descr.window = prev_count;
descr.step = 6;
descr.optimizar = ADAM;
descr.activación = LReLU;
if(!critic.Add(descr))
{
borrar descr;
return false;
}
//--- capa 2
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronBaseOCL;
descr.count = 1024;
descr.activation = LReLU;
descr.optimisation = ADAM;
if(!critic.Add(descr))
{
borrar descr;
return false;
}
//--- capa 3
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronBaseOCL;
descr.count = 1024;
descr.activation = LReLU;
descr.optimisation = ADAM;
if(!critic.Add(descr))
{
borrar descr;
return false;
}
//--- capa 4
if(!(descr = new CLayerDescription())))
return false;
descr.type = defNeuronBaseOCL;
descr.count = 1024;
descr.activation = LReLU;
descr.optimisation = ADAM;
if(!critic. Add(descr))
{
borrar descr;
return false;
}
--- capa 5
if(!( descr = new CLayerDescription())))
return false;
descr.type = defNeuronBaseOCL;
descr.count = 1;
descr.optimise = ADAM;
descr.activation = None;
if(!critic. Add(descr))
{
borrar descr;
return false;
}
//---
devuelve true;
}
 
Gracias
Archivos adjuntos:
Dmtry.PNG  34 kb