English Русский 中文 Deutsch 日本語 Português
preview
Teoría de categorías en MQL5 (Parte 15): Funtores con grafos

Teoría de categorías en MQL5 (Parte 15): Funtores con grafos

MetaTrader 5Probador | 18 enero 2024, 09:53
247 0
Stephen Njuki
Stephen Njuki

Introducción

En el artículo anterior analizamos cómo conceptos ya considerados, como los órdenes lineales, pueden considerarse categorías y por qué sus "morfismos" son de hecho funtores cuando se aplican a otras categorías. Hoy veremos ejemplos del artículo anterior, en particular cómo los grafos pueden tener usos similares a los órdenes lineales discutidos en el artículo anterior. Para utilizar los grafos, transformaremos los datos del calendario MQL5 en un grafo y, por tanto, en una categoría. Este será el punto clave del presente artículo. Por consiguiente, el propósito de este artículo, como en el anterior, será demostrar el potencial de los funtores para predecir la volatilidad entre dos categorías. No obstante, en este caso, nuestra categoría de dominio será un gráfico, mientras que el codominio mostrará los valores de volatilidad del S&P 500 (no del VIX) en un conjunto preordenado de series temporales.


Convertimos los datos de entrada del Calendario MQL5 en forma de grafo

Ya hemos hablado del calendario económico de MQL5 al analizar la teoría de categorías en el contexto de los esquemas de bases de datos, así que nonos repetiremos. Para representarlo como un grafo, una secuencia de aristas y nodos, primero deberemos preseleccionar un subconjunto de noticias que incluiremos en nuestra categoría. Como podemos ver en la web del calendario económico, tenemos mucho donde elegir, sin embargo, si decidimos seleccionar, digamos, solo cuatro tipos de datos según su supuesta relación, como se muestra a continuación:


Nuestra hipótesis entonces sería que las ventas minoristas son una función del PMI, que a su vez es un derivado del Índice de Precios al Consumidor (IPC), que depende de la subasta de rendimientos a 10 años (10-year yield auction), cuyos resultados también se basan en las cifras de las ventas minoristas. Se trata, pues, de un ciclo simple, cuya fiabilidad no supone el tema del artículo, sino que pretende ilustrar la posible composición del grafo a partir de los datos del calendario económico.

Los gráficos permiten simplificar sistemas complejos interconectados mediante la creación de dos tablas simples, una que representa pares de vértices y otra que sirve como índice de los vértices. Podemos considerar un grafo como una categoría porque los vértices se pueden considerar como objetos (dominios), lo cual significa que las aristas sirven como morfismos. La diferencia con el orden lineal discutido en el artículo anterior (como sugiere el nombre) reside en la linealidad. Los grafos tienden a formar relaciones más complejas donde un objeto/dominio puede asociarse con más de un objeto.

Entonces, en lugar de combinar objetos individuales en esta categoría con objetos de la categoría de volatilidad del S&P, como hicimos en el artículo anterior sobre órdenes lineales, conectaremos filas de pares de vértices con la categoría del S&P. Esto significa que esta no puede ser isomórfica, porque varias filas están vinculadas a un solo objeto (punto de datos) en el S&P, dado que el S&P se basa en el tiempo. Esto también significa que nuestros objetos de dominio constarán de cuatro elementos (los últimos valores de cada uno de los cuatro elementos del ciclo).


Teoría de categorías y funtores: una breve descripción

Como ya hemos mencionado, la teoría de categorías tiene muchas aplicaciones, pero la mayor parte del material disponible públicamente se centra en la topología algebraica más que en el comercio de acciones. La mayoría de los tráders familiarizados con MQL5 tienden a utilizar redes neuronales para mejorar la eficiencia de sus sistemas, quizás debido a su mayor conocimiento en comparación con las categorías. Sin embargo, esto no debería impedir el estudio de las categorías. La mayoría de los tráders buscan algún tipo de ventaja en el comercio, pero si un sistema o método es demasiado común, las posibilidades de encontrar esa ventaja se reducirán.

Como mencionamos en nuestro último artículo, los funtores, en esencia, son morfismos entre categorías. Estos "morfismos" no solo conectan objetos en dos categorías, sino que también conectan homomorfismos entre categorías.

En el artículo anterior, probamos dos escenarios: uno en el que usamos una relación de objeto entre dos categorías y otro en el que observamos una relación de morfismo entre las mismas categorías. El funtor es el logaritmo de ambos, pero para nuestros objetivos, exploramos las diferencias entre ellos observando uno a cada vez, y generamos informes del simulador de estrategias para cada uno que resaltaron la importancia relativa en la predicción de la volatilidad del NASDAQ. Dada la brevedad de la ventana de prueba (del 1 de enero al 15de marzo de 2020) no se pudieron sacar conclusiones sobre qué escenario era mejor, pero la diferencia en los resultados indicaba una alta sensibilidad a las diferencias.


Creando la categoría de volatilidad del S&P 500

La recopilación y el procesamiento de los datos de volatilidad del SP500 será simple y resultará similar a la medición de la volatilidad del NASDAQ en el artículo anterior. VIX supone un indicador independiente. Por lo tanto, el valor de volatilidad actual se volverá a calcular en cada nueva barra según el siguiente listado:

      double _float_value=0.0;
      //where R is an instance of MqlRates...
      _float_value=(R.high-R.low)/Point();


Como ya hemos mencionado, S&P formará nuestro codominio con objetos que capturan las lecturas de la volatilidad como un conjunto de objetos, y los morfismos entre ellos, que capturan el cambio relativo entre lecturas de volatilidad. Esta categoría se puede inicializar de la forma siguiente:

//+------------------------------------------------------------------+
//|   Get SP500-100 data from symbol (NDX100 for this broker).       | 
//|   Load it into SP500 category.                                   |
//+------------------------------------------------------------------+
void SetSP500(MqlRates &R)
   {
      _hmorph_sp500.Let();
      
      double _float_value=0.0;
      
      _float_value=(R.high-R.low)/Point();
      
      _element_value.Let();_element_value.Cardinality(1);_element_value.Set(0,DoubleToString(_float_value));
      _domain_sp500.Cardinality(1);_domain_sp500.Set(0,_element_value);
      
      //_category_sp500.Domains(_category_sp500.Domains()+1);
      _category_sp500.SetDomain(_category_sp500.Domains(),_domain_sp500);  
   }


Como vimos en el artículo anterior, si podemos asignar un dominio de retraso a este codominio, podemos obtener cierta capacidad para predecir la volatilidad del índice S&P 500. Como en el artículo anterior, probaremos los funtores de objeto y morfismo por separado en ajustes idénticos para el control de señales y capital, para evaluar la sensibilidad.


Funtores desde el calendario económico hasta el S&P 500

Construiremos la categoría de datos del calendario económico utilizando la siguiente lista:

//+------------------------------------------------------------------+
//|   Get Ocean data from file defined in input.                     | 
//|   Load it into Ocean category.                                   |
//+------------------------------------------------------------------+
void SetEconomic(MqlRates &R)
   {
      datetime _time=R.time;
      
      int _elements=1;
      
      _e_retail.Let();
      SampleEvents(_time,_e_retail,IntToCountry(__country),__currency,TYPE_RETAIL_SALES);//printf(__FUNCSIG__+"...retail. ");
      
      _e_cpi.Let();
      string _cpi_time="";_e_retail.Get(0,_cpi_time);
      SampleEvents(StringToTime(_cpi_time),_e_cpi,IntToCountry(__country),__currency,TYPE_CPI);//printf(__FUNCSIG__+"...cpi. ");
      
      _e_auction.Let();
      string _auction_time="";_e_cpi.Get(0,_auction_time);
      SampleEvents(StringToTime(_auction_time),_e_auction,IntToCountry(__country),__currency,TYPE_AUCTION_10YR);//printf(__FUNCSIG__+"...auction. ");
      
      _e_pmi.Let();
      string _pmi_time="";_e_auction.Get(0,_pmi_time);
      SampleEvents(StringToTime(_pmi_time),_e_pmi,IntToCountry(__country),__currency,TYPE_PMI);//printf(__FUNCSIG__+"...pmi. ");
      
       _domain_economic.Cardinality(__ECON);
       _domain_economic.Set(0,_e_retail);
       _domain_economic.Set(1,_e_cpi);
       _domain_economic.Set(2,_e_auction);
       _domain_economic.Set(3,_e_pmi);
      
       _category_economic.SetDomain(_category_economic.Domains(),_domain_economic);
   }


Cada objeto en este dominio tendrá dos vértices que representarán valores de calendario emparejados, de los cuales al menos uno estará en el rango de tiempo del valor de volatilidad en el codominio. Dado que estos datos económicos se publican aproximadamente a intervalos mensuales, los probaremos en un gráfico mensual. Al igual que en el artículo anterior, nuestro mapeo de funtores tendrá coeficientes para cada punto de datos del objeto. Como diferencia, aquí nos enfrentaremos a la posibilidad de hacer coincidir varios objetos con la misma volatilidad en el codominio. De manera ideal, necesitaríamos obtener el coeficiente (para mapeo lineal) de cada objeto por separado y usar este en el pronóstico. Esto significa que deberían ofrecer proyecciones inconsistentes además de las proyecciones proporcionadas por la coincidencia de los morfismos. Es por eso que, para los objetivos de este artículo, podríamos ponderar cada funtor que asigna los datos del calendario a la categoría S&P y tomar la suma de los productos escalares de todos para asignar el valor de la volatilidad.

La aplicación práctica de los funtores, como en el artículo anterior, seguirá dos opciones: mapearemos los objetos en la primera iteración y luego mapearemos los morfismos en la siguiente. El mapeo de objetos de la función Output() se vería así:

//+------------------------------------------------------------------+
//| Get Forecast value, forecast for next change in price bar range. |
//+------------------------------------------------------------------+
double GetObjectsForecast(MqlRates &R)
   {
      double _output=0.0;
      
      //econ init
      SetEconomic(R);
      
      //sp500 init
      SetSP500(R);
      
      matrix _domain;
      vector _codomain,_inputs;
      
      _domain.Init(__ECON+1,__ECON);
      
      for(int r=0;r<__ECON+1;r++)
      {
         CDomain<string> _d;_d.Let();
         _category_economic.GetDomain(_category_economic.Domains()-r-1,_d);
         
         for(int c=0;c<__ECON;c++)
         {
            CElement<string> _e; _d.Get(c,_e);
            
            string _s; _e.Get(1,_s);
            
            _domain[r][c]=StringToDouble(_s);
         }
      }
      
      _codomain.Init(__ECON);
      
      for(int r=0;r<__ECON;r++)
      {
         CDomain<string> _d;_d.Let();
         _category_sp500.GetDomain(_category_sp500.Domains()-r-1,_d);
         
         CElement<string> _e; _d.Get(0,_e);
         
         string _s; _e.Get(0,_s);
            
         _codomain[r]=StringToDouble(_s);
      }
      
      _inputs.Init(__ECON);_inputs.Fill(__constant_morph);
      
      M(_domain,_codomain,_inputs,_output,1);
      
      return(_output);
   }


Nuestro mapeo de morfismos también se gestionará de manera diferente, haciendo coincidir los morfismos entre vértices definidos por el delta de cambio, con el morfismo entre los puntos de datos de volatilidad de S&P, que también estará definido por el valor de cambio. El procesamiento se implementará de la siguiente manera:

//+--------------------------------------------------------------------+
//|   Get Forecast value, forecast for next change in price bar range. |
//+--------------------------------------------------------------------+
double GetMorphsForecast(MqlRates &R)
   {
      ...
      
      for(int r=0;r<__ECON+1;r++)
      {
         ...
         
         for(int c=0;c<__ECON;c++)
         {
            CElement<string> _e_new; _d_new.Get(c,_e_new);
            
            string _s_new; _e_new.Get(1,_s_new);
            
            CElement<string> _e_old; _d_old.Get(c,_e_old);
            
            string _s_old; _e_old.Get(1,_s_old);
            
            _domain[r][c]=StringToDouble(_s_new)-StringToDouble(_s_old);
         }
      }
      
      _codomain.Init(__ECON);
      
      for(int r=0;r<__ECON;r++)
      {
         ...
         
         CElement<string> _e_new; _d_new.Get(0,_e_new);
         
         string _s_new; _e_new.Get(0,_s_new);
         
         CElement<string> _e_old; _d_old.Get(0,_e_old);
         
         string _s_old; _e_old.Get(0,_s_old);
         
         _codomain[r]=StringToDouble(_s_new)-StringToDouble(_s_old);
      }
      
      _inputs.Init(__ECON);_inputs.Fill(__constant_morph);
      
      M(_domain,_codomain,_inputs,_output,1);
      
      return(_output);
   }


La representación esquemática de estas dos partes del funtor también será ligeramente distinta de lo que vimos en el artículo anterior, ya que nuestra relación ya no será isomórfica. Podemos ilustrar el mapeo de objetos de la manera que sigue:


El mapeo del morfismo se vería así:


Por desgracia, el simulador de estrategias MQL5 no permite realizar pruebas con acceso a los eventos del calendario económico. El desafío de lograr aumentos significativos del rendimiento mediante el desarrollo de sistemas comerciales más fiables sigue sin resolverse. Lo mejor que podemos hacer es mostrar el cambio previsto en la volatilidad según nuestro pronóstico, y si nos desplazamos por la historia podremos hacernos una idea de lo precisos que son nuestros pronósticos.

No obstante, si ejecutamos nuestro script según los datos de precio proporcionados por el bróker, podremos construir nuestras dos categorías en función del gráfico de datos del calendario y la volatilidad del SP500 más su funtor de enlace. Podemos obtener las siguientes previsiones de volatilidad. El mapeo de funtores objeto-objeto da como resultado las siguientes entradas:

2023.07.30 13:45:47.035 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: 0.00000000, on: 2020.01.01 00:00, with actual being: 54260.00000000
2023.07.30 13:45:47.134 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: 0.00000000, on: 2020.02.01 00:00, with actual being: 95438.00000000
2023.07.30 13:45:47.265 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: 0.00000000, on: 2020.03.01 00:00, with actual being: 53588.00000000
2023.07.30 13:45:47.392 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: 0.00000000, on: 2020.04.01 00:00, with actual being: 30352.00000000
2023.07.30 13:45:47.512 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: 0.00000000, on: 2020.05.01 00:00, with actual being: 29694.00000000
2023.07.30 13:45:47.644 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: -716790.11376869, on: 2020.06.01 00:00, with actual being: 21905.00000000
2023.07.30 13:45:47.740 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: -12424.22112077, on: 2020.07.01 00:00, with actual being: 26509.00000000
2023.07.30 13:45:47.852 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: 53612.17123096, on: 2020.08.01 00:00, with actual being: 37890.00000000




...

2023.07.30 13:45:50.294 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: -27774.72154618, on: 2022.09.01 00:00, with actual being: 42426.00000000
2023.07.30 13:45:50.377 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: 46751.59791572, on: 2022.10.01 00:00, with actual being: 39338.00000000
2023.07.30 13:45:50.487 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: -19820.29385469, on: 2022.11.01 00:00, with actual being: 37305.00000000
2023.07.30 13:45:50.593 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: -5370.60103622, on: 2022.12.01 00:00, with actual being: 30192.00000000
2023.07.30 13:45:50.700 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: -4662833.98425755, on: 2023.01.01 00:00, with actual being: 25359.00000000
2023.07.30 13:45:50.795 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: 33455.47933459, on: 2023.02.01 00:00, with actual being: 30681.00000000
2023.07.30 13:45:50.905 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: -40357.22273603, on: 2023.03.01 00:00, with actual being: 12502.00000000
2023.07.30 13:45:51.001 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: -37676.03496283, on: 2023.04.01 00:00, with actual being: 18835.00000000
2023.07.30 13:45:51.094 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: -54634.02723538, on: 2023.05.01 00:00, with actual being: 28877.00000000
2023.07.30 13:45:51.178 ct_15_w (SPX500,MN1)    void OnStart() Objects forecast is: -35897.40757724, on: 2023.06.01 00:00, with actual being: 23306.00000000
2023.07.30 13:45:51.178 ct_15_w (SPX500,MN1)    void OnStart() corr is: 0.36053106 with morph constant as: 50000.00000000


El mapeo de morfismos produce los siguientes resultados:

2023.07.30 13:47:38.737 ct_15_w (SPX500,MN1)    void OnStart() Morphs forecast is: 0.00000000, on: 2020.01.01 00:00, with actual being: 54260.00000000
2023.07.30 13:47:38.797 ct_15_w (SPX500,MN1)    void OnStart() Morphs forecast is: 0.00000000, on: 2020.02.01 00:00, with actual being: 95438.00000000
2023.07.30 13:47:38.852 ct_15_w (SPX500,MN1)    void OnStart() Morphs forecast is: 0.00000000, on: 2020.03.01 00:00, with actual being: 53588.00000000
2023.07.30 13:47:38.906 ct_15_w (SPX500,MN1)    void OnStart() Morphs forecast is: 0.00000000, on: 2020.04.01 00:00, with actual being: 30352.00000000
2023.07.30 13:47:39.010 ct_15_w (SPX500,MN1)    void OnStart() Morphs forecast is: 0.00000000, on: 2020.05.01 00:00, with actual being: 29694.00000000
2023.07.30 13:47:39.087 ct_15_w (SPX500,MN1)    void OnStart() Morphs forecast is: -2482719.31391738, on: 2020.06.01 00:00, with actual being: 21905.00000000




...

2023.07.30 13:47:41.541 ct_15_w (SPX500,MN1)    void OnStart() Morphs forecast is: -86724.54189079, on: 2022.11.01 00:00, with actual being: 37305.00000000
2023.07.30 13:47:41.661 ct_15_w (SPX500,MN1)    void OnStart() Morphs forecast is: -126817.99564744, on: 2022.12.01 00:00, with actual being: 30192.00000000
2023.07.30 13:47:41.793 ct_15_w (SPX500,MN1)    void OnStart() Morphs forecast is: -198737.93199622, on: 2023.01.01 00:00, with actual being: 25359.00000000
2023.07.30 13:47:41.917 ct_15_w (SPX500,MN1)    void OnStart() Morphs forecast is: -280104.88246660, on: 2023.02.01 00:00, with actual being: 30681.00000000
2023.07.30 13:47:42.037 ct_15_w (SPX500,MN1)    void OnStart() Morphs forecast is: 24129.34336223, on: 2023.03.01 00:00, with actual being: 12502.00000000
2023.07.30 13:47:42.157 ct_15_w (SPX500,MN1)    void OnStart() Morphs forecast is: 4293.73674465, on: 2023.04.01 00:00, with actual being: 18835.00000000
2023.07.30 13:47:42.280 ct_15_w (SPX500,MN1)    void OnStart() Morphs forecast is: 763492.31964126, on: 2023.05.01 00:00, with actual being: 28877.00000000
2023.07.30 13:47:42.401 ct_15_w (SPX500,MN1)    void OnStart() Morphs forecast is: -30298.30836734, on: 2023.06.01 00:00, with actual being: 23306.00000000
2023.07.30 13:47:42.401 ct_15_w (SPX500,MN1)    void OnStart() corr is: 0.03400012 with morph constant as: 50000.00000000


Vamos a destacar algunos puntos respecto a las entradas. En primer lugar, los cinco primeros meses pronostican un valor igual a cero. Creo que esto se debe a la falta de datos de precio para realizar los cálculos completos, como ocurre a veces con muchos indicadores. En segundo lugar, los valores negativos forman parte de los pronósticos, pero simplemente buscaremos un valor estrictamente positivo para indicar cuál será nuestra volatilidad en la siguiente barra. Esto puede deberse al hecho de que no hemos podido determinar valores de volatilidad bajos, ya que utilizamos las herramientas de regresión de la biblioteca MQL5, que usan matrices de identidad al trabajar con múltiples coeficientes (en nuestro caso, cuatro). Podemos solucionar este problema normalizando los valores negativos con una función como la que se muestra a continuación.

//+------------------------------------------------------------------+
//| Normalizes negative projections to positive number.              |
//+------------------------------------------------------------------+
double NormalizeForecast(double NegativeValue,double CurrentActual,double PreviousActual,double PreviousForecast)
   {
      return(CurrentActual+(((CurrentActual-NegativeValue)/CurrentActual)*fabs(PreviousActual-PreviousForecast)));
   }


Si ahora ejecutamos nuestro script y verificamos la correlación entre nuestras predicciones y los valores reales, seguramente obtendremos resultados distintos, especialmente porque la constante de la ecuación es una magnitud muy sensible que determina en gran medida qué resultado y qué predicciones terminaremos obteniendo. Lo configuraremos en cero para las entradas siguientes. Primero ejecutaremos el funtor objeto-objeto:

2023.07.30 14:43:42.224 ct_15_w_n (SPX500,MN1)  void OnStart() Objects forecast is: 15650.00000000, on: 2020.01.01 00:00, with actual being: 54260.00000000

...

2023.07.30 14:43:45.895 ct_15_w_n (SPX500,MN1)  void OnStart() Objects forecast is: 15718.63125861, on: 2023.03.01 00:00, with actual being: 12502.00000000
2023.07.30 14:43:45.957 ct_15_w_n (SPX500,MN1)  void OnStart() Objects forecast is: 12187.53007421, on: 2023.04.01 00:00, with actual being: 18835.00000000
2023.07.30 14:43:46.026 ct_15_w_n (SPX500,MN1)  void OnStart() Objects forecast is: 19185.80075759, on: 2023.05.01 00:00, with actual being: 28877.00000000
2023.07.30 14:43:46.129 ct_15_w_n (SPX500,MN1)  void OnStart() Objects forecast is: 11544.54076238, on: 2023.06.01 00:00, with actual being: 23306.00000000
2023.07.30 14:43:46.129 ct_15_w_n (SPX500,MN1)  void OnStart() correlation is: 0.46195608 with morph constant as: 0.00000000


Luego ejecutaremos nuestro script creando proyecciones basadas en el funtor morfismo-morfismo, nuevamente con la misma constante de ecuación establecida en cero.

2023.07.30 14:45:54.257 ct_15_w_n (SPX500,MN1)  void OnStart() Morphs forecast is: 54260.00000000, on: 2020.02.01 00:00, with actual being: 95438.00000000

...

2023.07.30 14:45:57.449 ct_15_w_n (SPX500,MN1)  void OnStart() Morphs forecast is: 257937.92970615, on: 2023.05.01 00:00, with actual being: 28877.00000000
2023.07.30 14:45:57.527 ct_15_w_n (SPX500,MN1)  void OnStart() Morphs forecast is: 679078.55629755, on: 2023.06.01 00:00, with actual being: 23306.00000000
2023.07.30 14:45:57.527 ct_15_w_n (SPX500,MN1)  void OnStart() correlation is: -0.03589660 with morph constant as: 0.00000000


Obtendremos una correlación ligeramente superior a 0,46 en comparación con la magnitud 0,3 que hemos obtenido sin normalización. Esto puede indicar alguna ventaja por parte de la normalización, pero en nuestro caso la constante de entrada se ha cambiado desde 50 000 y, como hemos mencionado, las predicciones y, por lo tanto, la correlación son muy sensibles a ello. Como solo tenemos una señal de entrada, ejecutaremos el simulador de estrategias para optimizar su valor y obtener resultados más significativos.


Implicaciones para los tráders

En mi opinión, el valor subestimado de la teoría de categorías para el análisis financiero reside en el aprendizaje por transferencia (transfer learning). ¿Cuáles son sus ventajas? Como resultado de nuestras pruebas anteriores, hemos obtenido los coeficientes entre el mapeo de funtores de objetos y el mapeo de morfismos. El proceso de obtención de estos coeficientes requerirá necesariamente grandes recursos computacionales, especialmente si la optimización se realiza, como es de esperar, durante largos periodos históricos en el simulador de estrategias MQL5.

Y, sin embargo, como los coeficientes de funtores forman parte de la hipótesis establecida que planteamos antes en el ciclo anterior, podemos argumentar que estos coeficientes, que funcionan de manera especial con los valores en dólares estadounidenses del calendario económico, pueden ser igualmente efectivos con, digamos, los valores del calendario económico de EUR según la volatilidad de EURO-STOXX o los valores de GBP según la volatilidad de FTSE. Obtenemos un conjunto de posibles combinaciones. Aquí es donde nuestros funtores se convierten en herramientas de valor incalculable para tomar los coeficientes, obtenidos de una optimización larga e intensiva (desde el punto de vista computacional), y aplicarlos a cualquiera de esas combinaciones que (según nuestra hipótesis) pueden producir un resultado superior al medio.

Para ilustrar lo anterior usando la entrada que se muestra a continuación:


Realizaremos algunas pruebas con divisas alternativas y sus correspondientes índices bursátiles. Si comenzamos con los valores del calendario económico de EUR obtenidos de Alemania, en la categoría de funtor emparejada con la categoría de volatilidad del DAX30, entonces con la configuración anterior obtendremos el siguiente informe del simulador:

2023.07.30 15:12:25.655	ct_15_w_n (GER30,MN1)	void OnStart() Objects forecast is: 75550.00000000, on: 2020.01.01 00:00, with actual being: 210640.00000000
2023.07.30 15:12:25.727	ct_15_w_n (GER30,MN1)	void OnStart() Objects forecast is: 210640.00000000, on: 2020.02.01 00:00, with actual being: 431320.00000000

...

2023.07.30 15:12:28.445	ct_15_w_n (GER30,MN1)	void OnStart() Objects forecast is: 144734.23693128, on: 2022.09.01 00:00, with actual being: 154697.00000000
2023.07.30 15:12:28.539	ct_15_w_n (GER30,MN1)	void OnStart() Objects forecast is: 171908.69769099, on: 2022.10.01 00:00, with actual being: 156643.00000000
2023.07.30 15:12:28.648	ct_15_w_n (GER30,MN1)	void OnStart() Objects forecast is: 298789.42486333, on: 2022.11.01 00:00, with actual being: 99044.00000000
2023.07.30 15:12:28.753	ct_15_w_n (GER30,MN1)	void OnStart() Objects forecast is: 178962.89317906, on: 2022.12.01 00:00, with actual being: 137604.00000000
2023.07.30 15:12:28.901	ct_15_w_n (GER30,MN1)	void OnStart() Objects forecast is: 440957.33259197, on: 2023.01.01 00:00, with actual being: 55544.00000000
2023.07.30 15:12:29.032	ct_15_w_n (GER30,MN1)	void OnStart() Objects forecast is: 143198.91357580, on: 2023.02.01 00:00, with actual being: 124659.00000000
2023.07.30 15:12:29.151	ct_15_w_n (GER30,MN1)	void OnStart() Objects forecast is: 24327.24201304, on: 2023.03.01 00:00, with actual being: 48737.00000000
2023.07.30 15:12:29.267	ct_15_w_n (GER30,MN1)	void OnStart() Objects forecast is: 167059.32862279, on: 2023.04.01 00:00, with actual being: 69888.00000000
2023.07.30 15:12:29.357	ct_15_w_n (GER30,MN1)	void OnStart() Objects forecast is: 67301.73632062, on: 2023.05.01 00:00, with actual being: 74073.00000000
2023.07.30 15:12:29.470	ct_15_w_n (GER30,MN1)	void OnStart() Objects forecast is: 87406.10063493, on: 2023.06.01 00:00, with actual being: 104992.00000000
2023.07.30 15:12:29.470	ct_15_w_n (GER30,MN1)	void OnStart() correlation is: 0.02260757 with morph constant as: 0.00000000


Para GBP y FTSE-100 obtendremos lo siguiente:

2023.07.30 15:12:45.341	ct_15_w_n (UK100,MN1)	void OnStart() Objects forecast is: 45860.00000000, on: 2020.01.01 00:00, with actual being: 109780.00000000
2023.07.30 15:12:45.381	ct_15_w_n (UK100,MN1)	void OnStart() Objects forecast is: 109780.00000000, on: 2020.02.01 00:00, with actual being: 210420.00000000
2023.07.30 15:12:45.420	ct_15_w_n (UK100,MN1)	void OnStart() Objects forecast is: 210420.00000000, on: 2020.03.01 00:00, with actual being: 87250.00000000
2023.07.30 15:12:45.466	ct_15_w_n (UK100,MN1)	void OnStart() Objects forecast is: 87250.00000000, on: 2020.04.01 00:00, with actual being: 58380.00000000
2023.07.30 15:12:45.508	ct_15_w_n (UK100,MN1)	void OnStart() Objects forecast is: 1581489.63705309, on: 2020.05.01 00:00, with actual being: 58370.00000000

...

2023.07.30 15:12:46.685	ct_15_w_n (UK100,MN1)	void OnStart() Objects forecast is: 153576.16806574, on: 2023.01.01 00:00, with actual being: 30453.00000000
2023.07.30 15:12:46.710	ct_15_w_n (UK100,MN1)	void OnStart() Objects forecast is: 222058.94934174, on: 2023.02.01 00:00, with actual being: 77051.00000000
2023.07.30 15:12:46.739	ct_15_w_n (UK100,MN1)	void OnStart() Objects forecast is: 50993.02046828, on: 2023.03.01 00:00, with actual being: 30780.00000000
2023.07.30 15:12:46.784	ct_15_w_n (UK100,MN1)	void OnStart() Objects forecast is: 66795.26430874, on: 2023.04.01 00:00, with actual being: 45453.00000000
2023.07.30 15:12:46.832	ct_15_w_n (UK100,MN1)	void OnStart() Objects forecast is: 75492.86146563, on: 2023.05.01 00:00, with actual being: 28845.00000000
2023.07.30 15:12:46.876	ct_15_w_n (UK100,MN1)	void OnStart() Objects forecast is: 92298.50964858, on: 2023.06.01 00:00, with actual being: 49472.00000000
2023.07.30 15:12:46.876	ct_15_w_n (UK100,MN1)	void OnStart() correlation is: 0.14415363 with morph constant as: 0.00000000


Gracias a nuestras entradas iniciales queda claro que, si bien podemos realizar predicciones, no podemos verificarlas de manera fiable debido al uso limitado de los datos del calendario en el simulador de estrategias. Obviamente, nuestra hipótesis no ha sido confirmada y resultaba poco probable que la correlación de 0,46 obtenida para el dólar estadounidense y el SP500 fuera concluyente. 

De hecho, el valor de correlación es una "solución" temporal porque sirve solo como un indicador muy temprano de lo fiables que pueden ser las predicciones dependiendo de la elección de los datos de entrada, que en nuestro caso suponen principalmente el coeficiente de dependencia lineal entre la categoría de un dominio y su codominio. Las opciones más fiables y a más largo plazo implican exportar manualmente los datos del calendario económico, ya sea como un archivo CSV para que lo lea el asesor, o en una base de datos para un mejor almacenamiento. Con cualquiera de las opciones, se pueden realizar pruebas adecuadas durante largos periodos de tiempo ideales.

Además de pronosticar la volatilidad como medio para determinar el stop loss ideal, es posible que también debamos adoptar un enfoque sistemático para dimensionar las posiciones. Para lograr esto usando nuestra metodología, podemos suponer que tenemos una categoría no relacionada de datos de series temporales que representan la historia comercial de un valor en particular, donde cada objeto en la categoría representa un resultado comercial particular, mientras que las flechas (morfismos) entre objetos representan los cambios en esos resultados registrados a lo largo del tiempo.

Para utilizar esta categoría a la hora de determinar o predecir el tamaño de una posición ideal para un sistema comercial, la mapearíamos usando un funtor con otra categoría de serie temporal de los tamaños de posición ideales basados ​​en los resultados comerciales reales y posiblemente la volatilidad asociada. Entonces, por ejemplo, si una operación ha tenido pérdidas, entonces un objeto en esa categoría registraría un tamaño de posición pequeño en ese momento, mientras que de otro modo registraría un tamaño de posición mayor. La volatilidad puede suponer un factor adicional de cuánto más pequeña o grande es una posición según la volatilidad registrada durante la operación. Por lo tanto, la escala puede ser tal que, cuando las operaciones resultan perdedoras, el tamaño ideal de la posición se reduce aún más en proporción a la tasa de volatilidad. Del mismo modo, si la operación resulta tener beneficios, entonces el tamaño ideal de la posición también aumentará en proporción a la volatilidad. El funtor de representación, como se esperaba, tendrá tal retraso que, digamos, el resultado de una operación ahora esté relacionado con el tamaño de la posición para el próximo periodo.

El funtor relacionará no solo los resultados comerciales con el tamaño ideal esperado de la posición, sino también los morfismos entre los resultados comerciales y los morfismos entre el tamaño ideal de la posición. Como vimos en el artículo anterior y también más arriba, uno puede ser verificado por el otro, pero la cuestión más profunda podría ser cómo la función de mapeo asocia un dominio con un codominio.

Hasta ahora hemos usado coeficientes muy simples basados ​​en la regresión de los resultados pasados. Como podemos ver en la fuente adjunta al final de este artículo y del anterior, hemos asumido la adición de una constante simple más un coeficiente al valor del dominio para producir el valor del codominio en lo que puede interpretarse como una relación lineal simple. Pero más allá de la relación lineal, los valores de un dominio se pueden mapear con un codominio usando una relación cuadrática, donde, si nuestro exponente más alto es dos, tendremos un factor adicional que se multiplicará por el cuadrado del valor del dominio para obtener el análogo asociado del codominio. Y, por supuesto, cuantos más exponentes se usen, más coeficientes se necesitarán para determinar el mapa de funtores.

Una alternativa a este enfoque simple y posiblemente propenso a errores sería utiliza una red neuronal para determinar el mapeo de homomorfismo entre dos dominios. Esto deberá hacerse tanto para los objetos como para los morfismos, y seguramente producirá resultados más precisos al entrenarse principalmente con grandes cantidades de datos. Pero dejando de lado la cuestión de la precisión, este es un enfoque intuitivamente correcto, ya que las redes neuronales pueden recibir múltiples entradas y producir una único resultado de salida, lo cual resulta aplicable en este caso.


Conclusión

Los puntos principales abarcados en el artículo han sido: el mapeo de datos del calendario económico como un gráfico, la representación de ese gráfico como una categoría y, como en nuestro artículo anterior, el uso de un índice de funtor que se retrasa respecto a la volatilidad del índice S&P 500 para hacer pronósticos de volatilidad del índice S&P 500. Al igual que en las partes anteriores de la serie, hemos utilizado estos pronósticos para mover los trailing stops de las posiciones abiertas. Además de establecer un stop loss para las posiciones abiertas, podríamos usar la relación del funtor para establecer el tamaño de la posición de las nuevas órdenes o incluso determinar una señal de entrada para cualquier valor comerciado. En esta serie de artículos no abarcaremos estos dos últimos ejemplos, ya que estamos hablando de crear un asesor utilizando el wizard IDE. El usuario podrá entonces realizar los cambios necesarios según su propia estrategia. También hemos analizado la definición de transformación (morphing), y ahora las relaciones de funtores. Asimismo, hemos usado valores incrementales aproximados que podrían tener una relación lineal o cuadrática de dominio a codominio, pero también se pueden usar redes neuronales artificiales para determinar este mapeo. Quizá exploremos este tema en futuros artículos.


Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/13033

Archivos adjuntos |
ct_14_1s.mqh (73.52 KB)
ct_15_w.mq5 (17.23 KB)
ct_15_w_n.mq5 (18.41 KB)
Redes neuronales: así de sencillo (Parte 52): Exploración con optimismo y corrección de la distribución Redes neuronales: así de sencillo (Parte 52): Exploración con optimismo y corrección de la distribución
A medida que el modelo se entrena con el búfer de reproducción de experiencias, la política actual del Actor se aleja cada vez más de los ejemplos almacenados, lo cual reduce la eficacia del entrenamiento del modelo en general. En este artículo, analizaremos un algoritmo para mejorar la eficiencia del uso de las muestras en los algoritmos de aprendizaje por refuerzo.
Transacciones comerciales. Estructuras de solicitud y respuesta, descripción y registro. Transacciones comerciales. Estructuras de solicitud y respuesta, descripción y registro.
En el presente artículo veremos cómo trabajar con las estructuras de las solicitudes comerciales: la creación de una solicitud, su verificación preliminar antes de enviarla al servidor, la respuesta del servidor a una solicitud comercial y la estructura de las transacciones comerciales. Asimismo, crearemos funciones simples y cómodas para enviar órdenes comerciales al servidor y, basándonos en todo lo discutido, y también crearemos un asesor-informante sobre las transacciones comerciales.
Mejore sus gráficos comerciales con una GUI interactiva basada en MQL5 (Parte III): Interfaz comercial simple y móvil Mejore sus gráficos comerciales con una GUI interactiva basada en MQL5 (Parte III): Interfaz comercial simple y móvil
En esta serie de artículos analizamos la integración de interfaces gráficas interactivas en paneles comerciales móviles en MQL5. En la tercera parte, utilizaremos los desarrollos de las partes anteriores para convertir paneles comerciales estáticos en dinámicos.
La técnica comercial RSI Deep Three Move La técnica comercial RSI Deep Three Move
El presente artículo muestra la técnica comercial RSI Deep Three Move en MetaTrader 5. El artículo se basa en una nueva serie de estudios que demuestran varias técnicas comerciales basadas en el RSI, así como un indicador técnico para medir la fuerza y el impulso de los valores, incluidas las acciones, las divisas y las materias primas.