Sophia 1_1 ist eine Grid-basierte Martingale-Handelsstrategie.
Die Strategie eröffnet eine Position nach vier aufeinanderfolgenden Kerzen in dieselbe Richtung:
Vier steigende Kerzen lösen einen Short-Einstieg aus.
Vier fallende Kerzen lösen einen Long-Einstieg aus.
Sobald der Markt betreten wurde, fügt der Algorithmus jedes Mal Positionen hinzu, wenn sich der Kurs um eine feste Anzahl von Kursschritten (Pip Step) gegen die aktuelle Position bewegt.
Das Volumen jedes zusätzlichen Trades wird mit Lot Exponent multipliziert, wodurch ein klassisches Martingale-Grid entsteht.
Das Risikomanagement erfolgt durch Take Profit, Stop Loss und einen optionalen Trailing-Stop.
Der Trailing-Mechanismus startet, sobald der Gewinn Trail Start erreicht, und verfolgt das Stop-Level um Trail Stop Kursschritte.
Parameter
Volume – Basisvolumen für den ersten Trade.
Pip Step – Distanz in Kursschritten vor dem Hinzufügen einer neuen Position.
Lot Exponent – Multiplikator für das Volumen jedes zusätzlichen Trades.
Max Trades – maximale Anzahl von Positionen im Grid.
Take Profit – Gewinnziel in Kursschritten vom durchschnittlichen Einstiegspreis.
Stop Loss – Verlustschwelle in Kursschritten vom durchschnittlichen Einstiegspreis.
Use Trailing – Trailing-Stop aktivieren oder deaktivieren.
Trail Start – erforderlicher Gewinn, bevor der Trailing-Stop aktiv wird.
Trail Stop – Distanz des Trailing-Stops in Kursschritten.
Candle Type – Zeitrahmen der Kerzen für Berechnungen.
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()