Aumente la eficiencia de sus sistemas lineales de trading

laplacianlab | 7 mayo, 2014

Introducción

En el artículo de hoy se muestra a los programadores intermedios en MQL5 cómo pueden sacar mayor rendimiento a sus sistemas lineales de trading (lote fijo) mediante una simple implementación de la conocida técnica de potenciación. En este caso, se usa el término general de potenciación para referirse a aquellos modelos de gestión monetaria en los que el tamaño o el número de posiciones colocadas en el mercado depende del riesgo asumido. Se llama así, porque el crecimiento de la curva de patrimonio resultante es geométrico o exponencial, con forma de parábola. En este contexto, se usa también el término "lineal", que está a medio camino entre el concepto matemático y el de la programación. En particular, vamos a implementar una variante práctica de MQL5, se trata del método de fracción fija para determinar el tamaño de una posición, desarrollado por Ralph Vince.

Figura 1. Parábola matemática


Figura 1. Parábola matemática

Hagamos ahora un breve resumen de los modelos de gestión monetaria y veamos cómo podemos implementar una variante del método de fracción fija para determinar el tamaño de una posición, desarrollado por Ralph Vince. ¿Está listo? ¡No pierda la oportunidad de sacar más rendimiento a sus estrategias de trading!


1. ¿Qué son los modelos de gestión monetaria?

En pocas palabras, los modelos de gestión monetaria son los marcos conceptuales, en función de los cuales toma sus decisiones en cuanto a determinar el tamaño de su posición, usar sus Stop Loss y calcular su margen y costes de trading. ¡Existen muchos modelos de gestión monetaria! Si lo desea, puede encontrar más información sobre estas clásicas técnicas buscando en Google términos como lote fijo, fracción fija, ratio fijo, porcentaje de Kelly o modelo del precio efectivo. Como ya mencioné, este artículo abarca solo el modelo de fracción fija.


1.2. Fracción fija

La idea detrás de este modelo de gestión monetaria es que el tamaño de operaciones depende del riesgo estimado correspondiente a las mismas. El riesgo es igual a la misma fracción del saldo neto en cada operación de trading. 

La ecuación para determinar el número de contratos en el método de fracción fija para determinar el tamaño de una posición es la siguiente:



N = f * Equity / Trade Risk

N es el número de contratos, f es la fracción fija (un número entre 0 y 1), Equity es el valor actual del patrimonio de la cuenta, y Trade Risk es el riesgo de la operación de trading por contrato para el cual se está calculando el número de contratos. Consulte el artículo Fixed Fractional Position Sizing (Determinar el tamaño de una posición mediante el método de fracción fija) de Michael R. Bryant para aprender más sobre este modelo.

Una característica interesante del modelo de fracción fija es que al ser el tamaño de las operaciones proporcional al saldo neto de la cuenta, es teóricamente imposible que pierda todo su capital. El riesgo de ruina es cero. Por otra parte, a medida que bajen los porcentajes del capital arriesgado, una racha de operaciones con ganancias o pérdidas no tiene un impacto drástico en la curva de beneficios.


2. Añadir la fracción fija a su sistema de trading


2.1. Escoja su sistema de trading lineal

Está claro que para poner a prueba la potencia exponencial de bajo riesgo, ¡necesita primero un sistema de trading lineal! Este sistema servirá como base de la potencia, por así decirlo. Por sistema lineal, me refiero a un sistema de trading que ha demostrado ser rentable durante un cierto intervalo de tiempo y cuya curva de patrimonio parece una línea recta. Por ejemplo, HawaiianTsunamiSurfer es un sistema de trading lineal disponible en la Biblioteca de códigos fuente. Su curva de patrimonio parece una línea recta entre enero 2012 y marzo 2012.

Figura 2. Curva de patrimonio de HawaiianTsunamiSurfer desde enero 2012 hasta marzo 2012

Figura 2. Curva de patrimonio de HawaiianTsunamiSurfer desde enero 2012 hasta marzo 2012

El objetivo de este artículo no es el desarrollo de un sistema de trading desde cero, sino proporcionarle las herramientas necesarias para que pueda sacar el máximo rendimiento a sus sistemas. Así que a partir de ahora, voy a suponer que ya ha desarrollado un sistema de trading como este, basado en la programación orientada a objetos. En este caso, debe añadir el elemento OO, que voy a explicar a continuación.

2.2. CEvolution, la clase principal de MQL5 para mejorar su sistema

Así que una vez más, usamos el enfoque orientado a objetos para implementar el código de nuestro Asesor Experto. Le recomiendo que lea primero los artículos Otra clase POO de MQL5 e Implementar un trader de noticias automático para obtener las bases técnicas de este enfoque OO. Si ya lo ha hecho, recuerde que los códigos analizados en estos artículos incorporan un elemento muy importante, llamado CEvolution. Este elemento nos permite hacer el seguimiento de alguna información temporal importante, como el estado del robot en un momento determinado, el historial de las operaciones llevadas a cabo, etc.

Esta vez, vamos a implementar el código de la lógica necesaria para gestionar nuestro dinero en CEvolution. Puesto que la fracción fija arriesgada sigue siendo proporcional al patrimonio, que a su vez no es constante, sino variable, se debe incluir el código de esta lógica en CEvolution. O simplemente, puesto que la pendiente del patrimonio evoluciona con el tiempo, hay que reflejarlo en CEvolution. Este es el concepto abstracto de nuestro enfoque orientado a objetos. Le dejo como ejercicio la integración de la siguiente clase OO en su sistema de trading orientado a objetos.

La clase CEvolution.mqh:

//+------------------------------------------------------------------+
//|                                                   CEvolution.mqh |
//|                               Copyright © 2013, Jordi Bassagañas |
//+------------------------------------------------------------------+
#include <Mine\Enums.mqh>
//+------------------------------------------------------------------+
//| CEvolution Class                                                 |
//+------------------------------------------------------------------+
class CEvolution
  {
protected:
   ENUM_STATUS_EA                   m_status;            // The current EA's status
   ENUM_EXP_EQUITY_CURVE_LEVEL      m_expEquityLevel;    // The current exponential equity level
   double                           m_originalEquity;    // The original equity value
   double                           m_lotSize;           // The current lot size

public:
   //--- Constructor and destructor methods
                                    CEvolution(ENUM_STATUS_EA status,ENUM_EXP_EQUITY_CURVE_LEVEL exp_equity_level);
                                    ~CEvolution(void);
   //--- Getter methods
   ENUM_STATUS_EA                   GetStatus(void);
   ENUM_EXP_EQUITY_CURVE_LEVEL      GetExpEquityLevel(void);
   double                           GetOriginalEquity(void);
   double                           GetLotSize(void);
   //--- Setter methods
   void                             SetStatus(ENUM_STATUS_EA status);
   void                             SetExpEquityLevel(ENUM_EXP_EQUITY_CURVE_LEVEL exp_equity_level);
   void                             SetOriginalEquity(double equity);
   void                             SetLotSize(double size);
   //--- CEvolution specific methods
   double                           CalcEquityGrowth(double currentEquity);
   void                             RefreshExpEquityLevel(double currentEquity);
   void                             RefreshLotSize();
  };
//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CEvolution::CEvolution(ENUM_STATUS_EA status,ENUM_EXP_EQUITY_CURVE_LEVEL exp_equity_level)
  {
   m_status=status;
   m_expEquityLevel=exp_equity_level;
   RefreshLotSize();
   m_originalEquity=AccountInfoDouble(ACCOUNT_EQUITY);
  }
//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CEvolution::~CEvolution(void)
  {
  }
//+------------------------------------------------------------------+
//| GetStatus                                                        |
//+------------------------------------------------------------------+
ENUM_STATUS_EA CEvolution::GetStatus(void)
  {
   return m_status;
  }
//+------------------------------------------------------------------+
//| GetExpEquityLevel                                                |
//+------------------------------------------------------------------+
ENUM_EXP_EQUITY_CURVE_LEVEL CEvolution::GetExpEquityLevel(void)
  {
   return m_expEquityLevel;
  }
//+------------------------------------------------------------------+
//| GetEquity                                                        |
//+------------------------------------------------------------------+
double CEvolution::GetOriginalEquity(void)
  {
   return m_originalEquity;
  }
//+------------------------------------------------------------------+
//| GetLotSize                                                       |
//+------------------------------------------------------------------+
double CEvolution::GetLotSize(void)
  {
   return m_lotSize;
  }
//+------------------------------------------------------------------+
//| SetStatus                                                        |
//+------------------------------------------------------------------+
void CEvolution::SetStatus(ENUM_STATUS_EA status)
  {
   m_status=status;
  }
//+------------------------------------------------------------------+
//| SetExpEquityLevel                                                |
//+------------------------------------------------------------------+
void CEvolution::SetExpEquityLevel(ENUM_EXP_EQUITY_CURVE_LEVEL exp_equity_level)
  {
   m_expEquityLevel=exp_equity_level;
  }
//+------------------------------------------------------------------+
//| SetEquity                                                        |
//+------------------------------------------------------------------+
void CEvolution::SetOriginalEquity(double equity)
  {
   m_originalEquity=equity;
  }
//+------------------------------------------------------------------+
//| SetLotSize                                                       |
//+------------------------------------------------------------------+
void CEvolution::SetLotSize(double lot_size)
  {
   m_lotSize=lot_size;
  }
//+------------------------------------------------------------------+
//| CalcEquityGrowth                                                 |
//+------------------------------------------------------------------+
double CEvolution::CalcEquityGrowth(double currentEquity)
  {
   return NormalizeDouble(currentEquity * 100 / m_originalEquity - 100,2);
  }
//+------------------------------------------------------------------+
//| RefreshExpEquityLevel                                            |
//+------------------------------------------------------------------+
void CEvolution::RefreshExpEquityLevel(double currentEquity)
  {
   double growth = CalcEquityGrowth(currentEquity);
   //--- is the current equity less than 10% of the original amount?
   if(growth <= 10)
   {
      SetExpEquityLevel(LEVEL_ONE);
   }
   //--- is the current equity more than 10% of the original amount and less than 20%?
   else if(growth > 10 && growth <= 20)
   {
      SetExpEquityLevel(LEVEL_TWO);
   }
   //--- is the current equity more than 20% of the original amount and less than 30%?
   else if(growth > 20 && growth <= 30)
   {
      SetExpEquityLevel(LEVEL_THREE);
   }
   //--- is the current equity more than 30% of the original amount and less than 40%?
   else if(growth > 30 && growth <= 40)
   {
      SetExpEquityLevel(LEVEL_FOUR);
   }
   //--- is the current equity more than 40% of the original amount and less than 50%?
   else if(growth > 40 && growth <= 50)
   {
      SetExpEquityLevel(LEVEL_FIVE);
   }
   //--- is the current equity more than 50% of the original amount and less than 60%?
   else if(growth > 50 && growth <= 60)
   {
      SetExpEquityLevel(LEVEL_SEVEN);
   }
   //--- is the current equity more than 60% of the original amount and less than 70%?   
   else if(growth > 60 && growth <= 70)
   {
      SetExpEquityLevel(LEVEL_EIGHT);
   }
   //--- is the current equity more than 70% of the original amount and less than 80%?   
   else if(growth > 70 && growth <= 80)
   {
      SetExpEquityLevel(LEVEL_NINE);
   }
   //--- is the current equity more than 90% of the original amount?
   else if(growth > 90)
   {
      SetExpEquityLevel(LEVEL_TEN);
   }
  }
//+------------------------------------------------------------------+
//| RefreshLotSize                                                   |
//+------------------------------------------------------------------+
void CEvolution::RefreshLotSize()
  {
   switch(m_expEquityLevel)
   {
      case LEVEL_ONE:
         SetLotSize(0.01);
         break;
         
      case LEVEL_TWO:
         SetLotSize(0.02);
         break;
         
      case LEVEL_THREE:
         SetLotSize(0.03);
         break;
         
      case LEVEL_FOUR:
         SetLotSize(0.04);
         break;
         
      case LEVEL_FIVE:
         SetLotSize(0.05);
         break;
         
      case LEVEL_SIX:
         SetLotSize(0.06);
         break;
         
      case LEVEL_SEVEN:
         SetLotSize(0.07);
         break;

      case LEVEL_EIGHT:
         SetLotSize(0.08);
         break;
         
      case LEVEL_NINE:
         SetLotSize(0.09);
         break;
         
      case LEVEL_TEN:
         SetLotSize(0.1);
         break;
   }
  }
//+------------------------------------------------------------------+

¡Comentemos ahora algunas partes importantes de esta clase! 

Cuando se genera el Asesor Experto, se almacena el valor inicial de la curva del patrimonio en m_originalEquity:

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CEvolution::CEvolution(ENUM_STATUS_EA status,ENUM_EXP_EQUITY_CURVE_LEVEL exp_equity_level)
  {
   m_status=status;
   m_expEquityLevel=exp_equity_level;
   RefreshLotSize();
   m_originalEquity=AccountInfoDouble(ACCOUNT_EQUITY);
  }

El método CEvolution::CalcEquityGrowth sirve para calcular el crecimiento de la curva de patrimonio, siempre en relación a su valor inicial:

//+------------------------------------------------------------------+
//| CalcEquityGrowth                                                 |
//+------------------------------------------------------------------+
double CEvolution::CalcEquityGrowth(double currentEquity)
  {
   return NormalizeDouble(currentEquity * 100 / m_originalEquity - 100,2);
  }

Por último, CEvolution::RefreshExpEquityLevel sirve para actualizar el nivel del patrimonio en cada tick (observe cómo depende absolutamente del crecimiento del patrimonio) y CEvolution::RefreshLotSize sirve para actualizar el tamaño del lote en cada tick. Se supone que usted actualiza esta información en el método OnTick de su Asesor Experto del siguiente modo:

GetEvolution().RefreshExpEquityLevel(AccountInfoDouble(ACCOUNT_EQUITY));
GetEvolution().RefreshLotSize();

Por cierto, esta solución requiere el uso de la siguiente enumeración personalizada de MQL5:

//+------------------------------------------------------------------+
//| Exponential equity curve level enumeration                       |
//+------------------------------------------------------------------+
enum ENUM_EXP_EQUITY_CURVE_LEVEL
  {
   LEVEL_ONE,
   LEVEL_TWO,
   LEVEL_THREE,
   LEVEL_FOUR,
   LEVEL_FIVE,
   LEVEL_SIX,
   LEVEL_SEVEN,
   LEVEL_EIGHT,
   LEVEL_NINE,
   LEVEL_TEN
  };
Decimos que esta implementación es una variante de la fracción fija porque en realidad introduce algunas peculiaridades. Por ejemplo, la curva de patrimonio crecerá exponencialmente hasta alcanzar el "nivel diez", a partir del cual el sistema será lineal. Sin embargo, CEvolution conserva la idea básica del incremento constante del tamaño de las posiciones proporcionalmente a la curva de patrimonio.

2.3. Tomar sus decisiones acerca de la fracción fija

Teniendo en cuenta el trabajo realizado antes, ya puede tomar sus decisiones acerca de la gestión monetaria en función del estado actual de su robot.

En alguna parte del método OnTick de su Asesor Experto:

switch(GetEvolution().GetStatus())
     {
      case BUY:

         tp = ask + m_takeProfit * _Point;
         sl = bid - m_stopLoss * _Point;

         GetTrade().PositionOpen(GetBrain().GetSymbol(),ORDER_TYPE_BUY,m_evolution.GetLotSize(),ask,sl,tp);
         
         break;

      case SELL:

         sl = ask + m_takeProfit * _Point;
         tp = bid - m_stopLoss * _Point;

         GetTrade().PositionOpen(GetBrain().GetSymbol(),ORDER_TYPE_SELL,m_evolution.GetLotSize(),bid,sl,tp);
         
         break;

      case DO_NOTHING:

         // Nothing...

         break;
     }

He cambiado el nombre de mi nuevo sistema potenciado a ExponentialHawaiian.


3. Backtesting de su sistema potenciado

Después de añadir a su sistema la lógica OO descrita anteriormente, ¡no se olvide de probar su sistema! Ahora estoy haciendo el backtesting de ExponentialHawaiian, la variante "fracción fija" de HawaiianTsunamiSurfer:

Figura 3. Curva de patrimonio de ExponentialHawaiian desde enero 2012 hasta marzo 2012

Figura 3. Curva de patrimonio de ExponentialHawaiian desde enero 2012 hasta marzo 2012

Mientras el sistema subyacente sigue siendo lineal la curva de la figura anterior seguirá siendo exponencial. Si esta condición deja de cumplirse, el sistema se vuelve inestable, con un riesgo de ruina.


Conclusión

En este artículo hemos visto la forma de sacar mayor rendimiento a nuestros sistemas lineales de trading, aquellos que implementan un modelo de gestión monetaria con fracción fija, mediante el uso de la técnica de potenciación.

Al principio, hemos presentado algunos modelos clásicos de gestión monetaria (lote fijo, fracción fija, ratio fijo, porcentaje de Kelly y el modelo del precio efectivo) y hemos decidido centrarnos en la fracción fija, un modelo simple en el cual se mantiene el tamaño de las operaciones proporcional al saldo neto de la cuenta. Y por último, hemos utilizado un sistema de trading que muestra resultados lineales para un intervalo de tiempo determinado, y hemos mostrado los resultados de las pruebas con el probador de estrategias de MetaTrader.

Una vez más, hemos recurrido al enfoque orientado a objetos para implementar el código de nuestro Asesor Experto. Es muy recomendable leer primero los artículos Otra clase POO de MQL5 e Implementar un trader de noticias automático para obtener las bases técnicas de este enfoque OO.