Saltar a contenido

Codificar estrategias multi-temporales

A menudo, las estrategias automatizadas necesitan considerar información de diferentes marcos temporales antes de tomar una decisión de trading. Afortunadamente, cTrader proporciona muchas herramientas que permiten a los algoritmos acceder fácilmente a datos de múltiples marcos temporales. En este video y su artículo correspondiente, explicaremos cómo puede usar estas herramientas para crear un cBot efectivo.

Declarar parámetros del cBot

Comenzaremos declarando los parámetros necesarios para una media móvil. Necesitaremos el período, el marco temporal y el tipo de media móvil.

1
2
3
4
5
6
7
8
[Parameter("MA 1 Period", DefaultValue = 14, Group = "Moving Averages")]
        public int MA1Period { get; set; }

[Parameter("MA 1 Timeframe", DefaultValue = "Hour", Group = "Moving Averages")]
public TimeFrame MA1Timeframe { get; set; }

[Parameter("MA 1 Type", Group = "Moving Averages")]
public MovingAverageType MA1Type { get; set; }

Luego, podemos definir la media móvil.

1
private MovingAverage _ma1;

Podemos inicializar la media móvil en el método OnStart(). Usaremos el método MarketData.GetBars() para obtener las barras de la primera media móvil y pasarlas al constructor del indicador. El método GetBars() es útil para obtener datos de barras para cualquier marco temporal y cualquier símbolo que necesite.

1
_ma1 = Indicators.MovingAverage(MarketData.GetBars(MA1Timeframe).ClosePrices, MA1Period, MA1Type);

Repetiremos el proceso para las otras dos medias móviles. Puede simplemente copiar y pegar el código a continuación para continuar.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Parameter("MA 1 Period", DefaultValue = 14, Group = "Moving Averages")]
public int MA1Period { get; set; }

[Parameter("MA 1 Timeframe", DefaultValue = "Hour", Group = "Moving Averages")]
public TimeFrame MA1Timeframe { get; set; }

[Parameter("MA 1 Type", Group = "Moving Averages")]
public MovingAverageType MA1Type { get; set; }

[Parameter("MA 2 Period", DefaultValue = 14, Group = "Moving Averages")]
public int MA2Period { get; set; }

[Parameter("MA 2 Timeframe", DefaultValue = "Hour2", Group = "Moving Averages")]
public TimeFrame MA2Timeframe { get; set; }

[Parameter("MA 2 Type", Group = "Moving Averages")]
public MovingAverageType MA2Type { get; set; }

[Parameter("MA 3 Period", DefaultValue = 14, Group = "Moving Averages")]
public int MA3Period { get; set; }

[Parameter("MA 3 Timeframe", DefaultValue = "Hour4", Group = "Moving Averages")]
public TimeFrame MA3Timeframe { get; set; }

[Parameter("MA 3 Type", Group = "Moving Averages")]
public MovingAverageType MA3Type { get; set; }

private MovingAverage _ma1;
private MovingAverage _ma2;
private MovingAverage _ma3;

protected override void OnStart()
{
    _ma1 = Indicators.MovingAverage(MarketData.GetBars(MA1Timeframe).ClosePrices, MA1Period, MA1Type);
    _ma2 = Indicators.MovingAverage(MarketData.GetBars(MA2Timeframe).ClosePrices, MA2Period, MA2Type);
    _ma3 = Indicators.MovingAverage(MarketData.GetBars(MA3Timeframe).ClosePrices, MA3Period, MA3Type);
}

Implementar la lógica de trading

En este punto, podemos implementar la lógica de trading. Nuestra estrategia mantendrá una posición de compra cuando todas las medias móviles estén subiendo y una posición de venta cuando las medias móviles estén bajando. Aquí está el código para toda la lógica de compra.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
if (_ma1.Result.IsRising() && _ma2.Result.IsRising() && _ma3.Result.IsRising())
{
    if (Positions.Count(p => p.SymbolName == SymbolName && p.TradeType == TradeType.Buy) == 0)
        ExecuteMarketOrder(TradeType.Buy, SymbolName, 100000);
}
else
{
    foreach (var position in Positions.Where(p => p.SymbolName == SymbolName && p.TradeType == TradeType.Buy))
    {
        position.Close();
    }
}

Y aquí está el código para la lógica de venta.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
if (_ma1.Result.IsFalling() && _ma2.Result.IsFalling() && _ma3.Result.IsFalling())
{
    if (Positions.Count(p => p.SymbolName == SymbolName && p.TradeType == TradeType.Sell) == 0)
        ExecuteMarketOrder(TradeType.Sell, SymbolName, 100000);
}
else
{
    foreach (var position in Positions.Where(p => p.SymbolName == SymbolName && p.TradeType == TradeType.Sell))
    {
        position.Close();
    }
}

Hacer backtesting de la estrategia multitemporal

Por último, deberíamos hacer backtesting de nuestro nuevo cBot. Podemos ver que el cBot abre posiciones cuando las medias móviles están sincronizadas en la misma dirección y se mantiene fuera del mercado cuando cada indicador apunta a una dirección diferente.