Sophia 1_1 es una estrategia de trading de cuadrícula basada en el principio de martingala.
La estrategia abre una posición después de cuatro velas consecutivas moviéndose en la misma dirección:
Cuatro velas ascendentes activan una entrada corta.
Cuatro velas descendentes activan una entrada larga.
Una vez en el mercado, el algoritmo añade posiciones cada vez que el precio se mueve contra la posición actual en un número fijo de pasos de precio (Pip Step).
El volumen de cada operación adicional se multiplica por Lot Exponent, formando una cuadrícula de martingala clásica.
La gestión del riesgo se maneja a través de Take Profit, Stop Loss y un trailing stop opcional.
El mecanismo de trailing se activa cuando el beneficio alcanza Trail Start y sigue el nivel de stop en Trail Stop pasos de precio.
Parámetros
Volume – volumen base para la primera operación.
Pip Step – distancia en pasos de precio antes de añadir una nueva posición.
Lot Exponent – multiplicador para el volumen de cada operación adicional.
Max Trades – número máximo de posiciones en la cuadrícula.
Take Profit – objetivo de beneficio en pasos de precio desde el precio de entrada promedio.
Stop Loss – umbral de pérdida en pasos de precio desde el precio de entrada promedio.
Use Trailing – habilitar o deshabilitar el trailing stop.
Trail Start – beneficio requerido antes de que el trailing stop se active.
Trail Stop – distancia del trailing stop en pasos de precio.
Candle Type – marco temporal de las velas usadas para los cálculos.
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>
/// Grid mean-reversion strategy. Enters on 3-bar momentum, exits at SMA or ATR stop.
/// </summary>
public class Sophia11Strategy : Strategy
{
private readonly StrategyParam<int> _smaPeriod;
private readonly StrategyParam<int> _atrPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prev1, _prev2, _prev3;
public int SmaPeriod { get => _smaPeriod.Value; set => _smaPeriod.Value = value; }
public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public Sophia11Strategy()
{
_smaPeriod = Param(nameof(SmaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("SMA Period", "SMA for exit target", "Indicators");
_atrPeriod = Param(nameof(AtrPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("ATR Period", "ATR for stops", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle type", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prev1 = _prev2 = _prev3 = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sma = new SimpleMovingAverage { Length = SmaPeriod };
var atr = new StandardDeviation { Length = AtrPeriod };
SubscribeCandles(CandleType).Bind(sma, atr, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal sma, decimal atr)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
if (_prev3 > 0)
{
// 3-bar declining => counter-trend buy
if (_prev1 < _prev2 && _prev2 < _prev3 && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
// 3-bar rising => counter-trend sell
else if (_prev1 > _prev2 && _prev2 > _prev3 && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
// Exit long at SMA or ATR stop
else if (Position > 0 && (close >= sma || (atr > 0 && close < sma - atr * 3)))
{
SellMarket();
}
// Exit short at SMA or ATR stop
else if (Position < 0 && (close <= sma || (atr > 0 && close > sma + atr * 3)))
{
BuyMarket();
}
}
_prev3 = _prev2;
_prev2 = _prev1;
_prev1 = close;
}
}
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, StandardDeviation
from StockSharp.Algo.Strategies import Strategy
class sophia11_strategy(Strategy):
def __init__(self):
super(sophia11_strategy, self).__init__()
self._sma_period = self.Param("SmaPeriod", 20) \
.SetDisplay("SMA Period", "SMA for exit target", "Indicators")
self._atr_period = self.Param("AtrPeriod", 14) \
.SetDisplay("ATR Period", "ATR for stops", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle type", "General")
self._prev1 = 0.0
self._prev2 = 0.0
self._prev3 = 0.0
@property
def sma_period(self):
return self._sma_period.Value
@property
def atr_period(self):
return self._atr_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(sophia11_strategy, self).OnReseted()
self._prev1 = 0.0
self._prev2 = 0.0
self._prev3 = 0.0
def OnStarted2(self, time):
super(sophia11_strategy, self).OnStarted2(time)
sma = SimpleMovingAverage()
sma.Length = self.sma_period
atr = StandardDeviation()
atr.Length = self.atr_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma, atr, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, sma, atr):
if candle.State != CandleStates.Finished:
return
close = candle.ClosePrice
if self._prev3 > 0:
# 3-bar declining => counter-trend buy
if self._prev1 < self._prev2 and self._prev2 < self._prev3 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# 3-bar rising => counter-trend sell
elif self._prev1 > self._prev2 and self._prev2 > self._prev3 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
# Exit long at SMA or ATR stop
elif self.Position > 0 and (close >= sma or (atr > 0 and close < sma - atr * 3)):
self.SellMarket()
# Exit short at SMA or ATR stop
elif self.Position < 0 and (close <= sma or (atr > 0 and close > sma + atr * 3)):
self.BuyMarket()
self._prev3 = self._prev2
self._prev2 = self._prev1
self._prev1 = close
def CreateClone(self):
return sophia11_strategy()