La estrategia usa el indicador Modified Moving Average (AMMA) para capturar cambios de tendencia a corto plazo. Analiza la dirección de la pendiente de AMMA en las velas recientes y abre una posición en la dirección de la tendencia emergente mientras cierra la opuesta.
Cómo funciona
Se calcula una ModifiedMovingAverage con un período configurable en el marco temporal seleccionado.
En cada vela terminada, la estrategia compara los últimos tres valores de AMMA.
Si los valores del indicador forman una secuencia ascendente y el valor más reciente es mayor que el anterior, se abre una posición larga. Se cierra cualquier posición corta.
Si los valores del indicador forman una secuencia descendente y el valor más reciente es menor que el anterior, se abre una posición corta. Se cierra cualquier posición larga.
Parámetros
CandleType – marco temporal de las velas utilizadas para los cálculos.
MaPeriod – período de la media móvil modificada.
AllowLongEntry – habilitar la apertura de posiciones largas.
AllowShortEntry – habilitar la apertura de posiciones cortas.
AllowLongExit – habilitar el cierre de posiciones largas.
AllowShortExit – habilitar el cierre de posiciones cortas.
Notas
La estrategia opera únicamente en velas completadas y se apoya en los métodos incorporados BuyMarket y SellMarket para la ejecución de órdenes. Las funciones de gestión de riesgo pueden añadirse externamente usando las propiedades estándar de Strategy.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// AMMA Trend strategy using Modified Moving Average direction changes.
/// Buys when MMA turns up, sells when MMA turns down.
/// </summary>
public class AmmaTrendStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _maPeriod;
private decimal? _mma0;
private decimal? _mma1;
private decimal? _mma2;
private decimal? _mma3;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int MaPeriod { get => _maPeriod.Value; set => _maPeriod.Value = value; }
public AmmaTrendStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use for analysis", "General");
_maPeriod = Param(nameof(MaPeriod), 25)
.SetGreaterThanZero()
.SetDisplay("AMMA Period", "Period of the modified moving average", "Indicator");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_mma0 = _mma1 = _mma2 = _mma3 = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var mma = new SmoothedMovingAverage { Length = MaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(mma, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, mma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal mmaValue)
{
if (candle.State != CandleStates.Finished)
return;
_mma3 = _mma2;
_mma2 = _mma1;
_mma1 = _mma0;
_mma0 = mmaValue;
if (_mma1 is null || _mma2 is null || _mma3 is null)
return;
// Upward movement detected: MMA turned from falling to rising
if (_mma2 < _mma3 && _mma1 > _mma2 && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
// Downward movement detected: MMA turned from rising to falling
else if (_mma2 > _mma3 && _mma1 < _mma2 && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import SmoothedMovingAverage
from StockSharp.Algo.Strategies import Strategy
class amma_trend_strategy(Strategy):
def __init__(self):
super(amma_trend_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles to use for analysis", "General")
self._ma_period = self.Param("MaPeriod", 25) \
.SetDisplay("AMMA Period", "Period of the modified moving average", "Indicator")
self._mma0 = None
self._mma1 = None
self._mma2 = None
self._mma3 = None
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def MaPeriod(self):
return self._ma_period.Value
@MaPeriod.setter
def MaPeriod(self, value):
self._ma_period.Value = value
def OnStarted2(self, time):
super(amma_trend_strategy, self).OnStarted2(time)
self._mma0 = None
self._mma1 = None
self._mma2 = None
self._mma3 = None
mma = SmoothedMovingAverage()
mma.Length = self.MaPeriod
self.SubscribeCandles(self.CandleType) \
.Bind(mma, self.ProcessCandle) \
.Start()
def ProcessCandle(self, candle, mma_val):
if candle.State != CandleStates.Finished:
return
mma_f = float(mma_val)
self._mma3 = self._mma2
self._mma2 = self._mma1
self._mma1 = self._mma0
self._mma0 = mma_f
if self._mma1 is None or self._mma2 is None or self._mma3 is None:
return
if self._mma2 < self._mma3 and self._mma1 > self._mma2 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._mma2 > self._mma3 and self._mma1 < self._mma2 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def OnReseted(self):
super(amma_trend_strategy, self).OnReseted()
self._mma0 = None
self._mma1 = None
self._mma2 = None
self._mma3 = None
def CreateClone(self):
return amma_trend_strategy()