Librerías: MultiTester - página 3

 
Edgar:

Si te refieres a cómo ver los resultados de la optimización, me refería a leer los resultados de la caché mediante programación.

No me refería a eso. Pero la lectura de la caché es posible. Sólo tienes que escribirlo.

[Eliminado]  

¡¡¡Genial!!!

Atornillado Cycles a él también y era exactamente lo que me faltaba )))))

#include <fxsaber\MultiTester\MultiTester.mqh> // Múltiples ejecuciones/optimizaciones en Tester.

enum CyclNum
{
   n01   = 1,     // 1
   n02,           // 2
   n03,           // 3
   n04,           // 4
   n05,           // 5
   n06,           // 6
   n07,           // 7
   n08,           // 8
   n09,           // 9
   n10,           // 0
};
sinput bool Period_M1 = false;         // Conectar M1
sinput bool Period_M5 = false;         // Conectar M5
sinput bool Period_M15 = false;        // Conectar M15
sinput bool OnlyCustomSymbols = false; // Sólo caracteres personalizados
sinput CyclNum number_cycles  = n06;   // Número de ciclos

// Esta función se encarga de generar la lista de tareas.
void SetTesterSettings()
{
   for(int n = 0; n < number_cycles; n++)
   {
      // Buscar todos los símbolos de la Observación del Mercado.
      for (int i = SymbolsTotal(true) - 1; i >= 0; i--)
      {

¡¡¡Gracias!!!

 
Сергей Таболин:

Le añadí Cycles y era exactamente lo que necesitaba ))))

Necesito funciones de pulsar botones en el Probador. Entonces la automatización sería de otro nivel.

 

He añadido algunas funciones para los controles que necesito (Depo, Currency, Leverage, OptimisationType, BarsType, Criteria). Pero todavía no lo he probado. Puedo publicarlo después.

Quería implementar la gestión de agentes. Por ejemplo, puede hacer clic en la lista de agentes, pulse INICIO, y seleccione cada agente con VK_DOWN. Pero no se como llamar al menu contextual para la fila seleccionada. Y habría que pulsar 'd'/'e' para desactivar/activar.

¿Alguien me puede dar una pista?

Es aún más difícil habilitar/deshabilitar la nube (deshabilitar antes del tick o la optimización cruzada). Si llegas al menú contextual, no puedes activar/desactivar explícitamente, sólo puedes darle la vuelta. No se puede averiguar el estado actual mediante programación. Puedes leer en el log del terminal "2019.07.31 19:27:35.664 Tester Cloud servers using switch off". Parece que tampoco se puede leer el log programáticamente, hay que mirar en el fichero log.

Todavía existe la posibilidad de que existan comandos WinAPI no documentados. ¿Quizás algún programador de C++ sepa como encontrarlos?

[Eliminado]  

Ante el problema del apagón. Ahora no sé cuánta optimización se ha hecho ((((

Cuando tenga tiempo, intentaré añadir una comprobación de % de optimización total y caracteres trabajados. Espero que al autor no le importe. ))) ¿O querrá hacerlo él mismo?

 
Сергей Таболин:

Enfrentado al problema del corte de luz. Ahora no sé cuánto se ha optimizado (((

MultiTester refleja sus pasos en los logs. Si el terminal ha guardado los logs, verás todo allí.

Además, las cachés de optimización se guardan al 100%. Así que puedes ver lo que se ha ejecutado.

 
Edgar:

He añadido algunas funciones para los controles que necesito (Depo, Currency, Leverage, OptimisationType, BarsType, Criteria). Pero todavía no lo he probado. Puedo publicarlo después.

Antes de resolver problemas privados, sería bueno describir escenarios de uso de sus soluciones.

 
fxsaber:

Antes de resolver problemas privados, conviene prescribir escenarios para utilizar sus soluciones.

He descrito mi escenario en la página anterior.

Clicker no es un sustituto para todo, es una de varias herramientas necesarias para automatizar la optimización. Le permite hacer todo dentro de un terminal sin necesidad de lanzar un terminal adicional. Yo añadiría marcos para analizar resultados (tu nueva librería para leer la caché de optimización sirve para lo mismo), funciones para gestionar variables de entrada, SQLITE para almacenar estados y estadísticas. Y puedes escribir scripts de optimización inteligentes. No se puede lograr la universalidad, cada Asesor Experto tiene su propio script. Y tienes que crearlo manualmente y sólo entonces aplicarlo repetidamente.

Ya se han añadido marcos. Yo tenía experiencia con SQLITE.

Acabo de ampliar su lib para mis necesidades. Estoy seguro de que usted mismo lo estaba planeando, pero no esperé. Esta es la única tecnología de las anteriores para la que no tenía una solución preparada. Por cierto, he comprobado mis complementos, funcionan. Los problemas de gestión de agentes siguen siendo relevantes. Spy++ puede ayudar en la captura de mensajes para un ingeniero de sistemas con experiencia, pero tuve poca ayuda, necesito saber qué filtrar. Espero que la gente se ponga las pilas. El tema lleva apareciendo desde 2008.

 
Edgar:

Así es como me gustaría mejorarlo. Mi escenario típico de optimización:

Ejecutar N ejecuciones genéticas para OHLC. Tomar el mejor resultado de cada una de ellas según un criterio personalizado.

Realizar una optimización lenta en cada grupo de parámetros (cada grupo tiene 2-3 parámetros interdependientes).

Repita iterativamente las optimizaciones lentas para cada grupo hasta alcanzar el óptimo (los parámetros dejan de flotar).

Cambiar a ticks reales, realizar las mismas optimizaciones lentas.

Cambiar a otro símbolo, repetir todo.

No tengo esa tarea delante de mí. Por supuesto, sería bueno que la automatización lo permitiera.

Yo mismo me estoy esforzando por desarrollar un criterio para la solidez del ST mediante indicadores de autooptimización. Falta mucho para que la investigación sea más objetiva.

El esquema del autooptimizador está completamente pensado, no hay obstáculos técnicos para su aplicación.

Bibla definitivamente necesita ser complementado con funcionalidad. Así que por favor sugiera sus realizaciones.

 
enum eOptType   { eOptOff, eOptSlow, eOptGen, eOptAllSym };
enum eBars      { eBarsEvery, eBarsReal, eBarsOHLC, eBarsOpen, eBarsMath };
enum eCriteria  { eCritBal, eCritPF, eCritEPO, eCritDD, eCritRF, eCritSR, eCritCust };



class MTTESTER {
public:

        static bool 
        SetOptType(eOptType opt) {
                const bool rc = MTTESTER::IsReady();
                if (rc) {
                        static const int ControlID[] = { 0xE81E, 0x804E, 0x28EC, 0x28FB };
                        GET_HANDLE
                        user32::SendMessageW(Handle, WM_KEYDOWN, VK_HOME, 0);
                        for (int i = 0; i < opt; i++)
                                user32::SendMessageW(Handle, WM_KEYDOWN, VK_DOWN, 0);
                }
                return rc;
        }



        static bool 
        SetBars(eBars type) {
                const bool rc = MTTESTER::IsReady();
                if (rc) {
                        static const int ControlID[] = { 0xE81E, 0x804E, 0x28EC, 0x2913 };
                        GET_HANDLE
                        user32::SendMessageW(Handle, WM_KEYDOWN, VK_HOME, 0);
                        for (int i = 0; i < type; i++)
                                user32::SendMessageW(Handle, WM_KEYDOWN, VK_DOWN, 0);
                }
                return rc;
        }



        static bool 
        SetCriteria(eCriteria type) {
                const bool Res = MTTESTER::IsReady();
                if (Res) {
                        static const int ControlID[] = { 0xE81E, 0x804E, 0x28EC, 0x290B };
                        GET_HANDLE
                        user32::SendMessageW(Handle, WM_KEYDOWN, VK_HOME, 0);
                        for (int i = 0; i < type; i++)
                                user32::SendMessageW(Handle, WM_KEYDOWN, VK_DOWN, 0);
                }
                return Res;
        }



        static bool 
        SetCurrency(const string name) {
                const bool Res = MTTESTER::IsReady();
                if (Res) {
                        static const int ControlID[] = { 0xE81E, 0x804E, 0x28EC, 0x293F, 0x03E9 };
                        GET_HANDLE
                        user32::SendMessageW(Handle, WM_LBUTTONDOWN, 0, 0);
                        user32::SendMessageW(Handle, WM_KEYDOWN, VK_DELETE, 0);
                        char Chars[];
                        const int Size = ::StringToCharArray(name, Chars);
                        for (int i = 0; i < Size; i++)
                                user32::SendMessageW(Handle, WM_CHAR, Chars[i], 0);
                }
                return Res;
        }



        static bool 
        SetDepo(const long depo) {
                const bool Res = MTTESTER::IsReady();
                if (Res) {
                        static const int ControlID[] = { 0xE81E, 0x804E, 0x28EC, 0x28F9, 0x03E9 };
                        GET_HANDLE
                        user32::SendMessageW(Handle, WM_LBUTTONDOWN, 0, 0);
                        user32::SendMessageW(Handle, WM_KEYDOWN, VK_DELETE, 0);
                        string s = IntegerToString(depo);
                        char Chars[];
                        const int Size = ::StringToCharArray(s, Chars);
                        for (int i = 0; i < Size; i++)
                                user32::SendMessageW(Handle, WM_CHAR, Chars[i], 0);
                }
                return Res;
        }



        static bool 
        SetLeverage(const long leverage) {
                const bool Res = MTTESTER::IsReady();
                if (Res) {
                        static const int ControlID[] = { 0xE81E, 0x804E, 0x28EC, 0x28E9, 0x03E9 };
                        GET_HANDLE
                        user32::SendMessageW(Handle, WM_LBUTTONDOWN, 0, 0);
                        user32::SendMessageW(Handle, WM_KEYDOWN, VK_DELETE, 0);
                        string s = "1:" + IntegerToString(leverage);
                        char Chars[];
                        const int Size = ::StringToCharArray(s, Chars);
                        for (int i = 0; i < Size; i++)
                                user32::SendMessageW(Handle, WM_CHAR, Chars[i], 0);
                }
                return Res;
        }