Estrategia de Cruce de Fase con Zona
Esta estrategia de ejemplo entra en largo cuando una SMA suavizada con desplazamiento positivo cruza por encima de una EMA con desplazamiento negativo. La posición se cierra cuando ocurre el cruce opuesto.
Detalles
- Criterios de entrada: SMA + desplazamiento cruza por encima de EMA - desplazamiento.
- Largo/Corto: solo largo.
- Criterios de salida: cruce opuesto.
- Stops: ninguno.
- Valores predeterminados:
Length= 20.Offset= 0.5.
- Filtros: ninguno.
- Complejidad: baja.
- Marco temporal: configurable.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class PhaseCrossWithZoneStrategy : Strategy
{
private readonly StrategyParam<int> _length;
private readonly StrategyParam<decimal> _offset;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevLead;
private decimal _prevLag;
private bool _prevInit;
public int Length
{
get => _length.Value;
set => _length.Value = value;
}
public decimal Offset
{
get => _offset.Value;
set => _offset.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public PhaseCrossWithZoneStrategy()
{
_length = Param(nameof(Length), 20)
.SetGreaterThanZero()
.SetDisplay("Length", "Smoothing length", "General")
.SetOptimize(5, 50, 1);
_offset = Param(nameof(Offset), 0.5m)
.SetDisplay("Offset", "Phase offset", "General")
.SetOptimize(0m, 1m, 0.1m);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
protected override void OnReseted()
{
base.OnReseted();
_prevLead = 0;
_prevLag = 0;
_prevInit = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sma = new SimpleMovingAverage { Length = Length };
var ema = new ExponentialMovingAverage { Length = Length * 2 };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, ema, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal smaValue, decimal emaValue)
{
if (candle.State != CandleStates.Finished)
return;
var lead = smaValue + Offset;
var lag = emaValue - Offset;
if (_prevInit)
{
var crossedUp = _prevLead <= _prevLag && lead > lag;
var crossedDown = _prevLead >= _prevLag && lead < lag;
if (crossedUp && Position <= 0)
BuyMarket();
else if (crossedDown && Position >= 0)
SellMarket();
}
_prevLead = lead;
_prevLag = lag;
_prevInit = true;
}
}
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 SimpleMovingAverage, ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class phase_cross_with_zone_strategy(Strategy):
def __init__(self):
super(phase_cross_with_zone_strategy, self).__init__()
self._length = self.Param("Length", 20).SetGreaterThanZero().SetDisplay("Length", "Smoothing length", "General")
self._offset = self.Param("Offset", 0.5).SetDisplay("Offset", "Phase offset", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Type of candles", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(phase_cross_with_zone_strategy, self).OnReseted()
self._prev_lead = 0
self._prev_lag = 0
self._prev_init = False
def OnStarted2(self, time):
super(phase_cross_with_zone_strategy, self).OnStarted2(time)
self._prev_lead = 0
self._prev_lag = 0
self._prev_init = False
sma = SimpleMovingAverage()
sma.Length = self._length.Value
ema = ExponentialMovingAverage()
ema.Length = self._length.Value * 2
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(sma, ema, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, sma)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def OnProcess(self, candle, sma_val, ema_val):
if candle.State != CandleStates.Finished:
return
lead = sma_val + self._offset.Value
lag = ema_val - self._offset.Value
if self._prev_init:
crossed_up = self._prev_lead <= self._prev_lag and lead > lag
crossed_down = self._prev_lead >= self._prev_lag and lead < lag
if crossed_up and self.Position <= 0:
self.BuyMarket()
elif crossed_down and self.Position >= 0:
self.SellMarket()
self._prev_lead = lead
self._prev_lag = lag
self._prev_init = True
def CreateClone(self):
return phase_cross_with_zone_strategy()