Turtle Trader Strategie
Turtle Trader folgt dem klassischen Turtle-Ausbruchssystem mit Donchian-Kanälen und ATR-basiertem Moneymanagement. Es kauft, wenn der Kurs neue Hochs durchbricht, und verkauft, wenn er unter neue Tiefs fällt. Pyramiding fügt Gewinnerpositionen hinzu, wenn sich der Kurs in die gewünschte Richtung bewegt.
Details
- Einstiegskriterien: Ausbruch über Hochs/Tiefs von
S1oderS2 - Long/Short: Beide
- Ausstiegskriterien: gegenläufiger Ausbruch oder ATR-Stop
- Stops: ATR-basiert
- Standardwerte:
RiskPercent= 1AtrPeriod= 20StopMultiplier= 1.5PyramidProfit= 0.5S1Long= 20S2Long= 55S1LongExit= 10S2LongExit= 20S1Short= 15S2Short= 55S1ShortExit= 7S2ShortExit= 20
- Filter:
- Kategorie: Trendfolge
- Richtung: Beide
- Indikatoren: ATR, Highest, Lowest
- Stops: ATR
- Komplexität: Mittel
- Zeitrahmen: Täglich
- Saisonalität: Nein
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Mittel
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;
/// <summary>
/// Turtle Trader strategy using RSI momentum with EMA trend filter.
/// </summary>
public class TurtleTraderStrategy : Strategy
{
private readonly StrategyParam<int> _entryLength;
private readonly StrategyParam<int> _exitLength;
private readonly StrategyParam<decimal> _stopPct;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevRsi;
private decimal _prevFast;
private decimal _prevSlow;
private int _cooldown;
public int EntryLength { get => _entryLength.Value; set => _entryLength.Value = value; }
public int ExitLength { get => _exitLength.Value; set => _exitLength.Value = value; }
public decimal StopPct { get => _stopPct.Value; set => _stopPct.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public TurtleTraderStrategy()
{
_entryLength = Param(nameof(EntryLength), 20)
.SetGreaterThanZero()
.SetDisplay("Entry Length", "Donchian breakout length", "General");
_exitLength = Param(nameof(ExitLength), 10)
.SetGreaterThanZero()
.SetDisplay("Exit Length", "Donchian exit length", "General");
_stopPct = Param(nameof(StopPct), 2m)
.SetGreaterThanZero()
.SetDisplay("Stop %", "Stop loss percent", "Risk");
_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();
_prevRsi = 0;
_prevFast = 0;
_prevSlow = 0;
_cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = 14 };
var emaFast = new ExponentialMovingAverage { Length = 8 };
var emaSlow = new ExponentialMovingAverage { Length = 21 };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, emaFast, emaSlow, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, emaFast);
DrawIndicator(area, emaSlow);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsiVal, decimal emaFast, decimal emaSlow)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevRsi == 0 || _prevFast == 0 || _prevSlow == 0)
{
_prevRsi = rsiVal;
_prevFast = emaFast;
_prevSlow = emaSlow;
return;
}
if (_cooldown > 0)
{
_cooldown--;
_prevRsi = rsiVal;
_prevFast = emaFast;
_prevSlow = emaSlow;
return;
}
var hist = emaFast - emaSlow;
var histUp = hist > 0m;
var histDown = hist < 0m;
var rsiCrossUp = _prevRsi <= 50m && rsiVal > 50m;
var rsiCrossDown = _prevRsi >= 50m && rsiVal < 50m;
// Exit
if (Position > 0 && rsiCrossDown)
{
SellMarket();
_cooldown = 80;
}
else if (Position < 0 && rsiCrossUp)
{
BuyMarket();
_cooldown = 80;
}
// Entry
if (Position == 0)
{
if (rsiCrossUp && histUp)
{
BuyMarket();
_cooldown = 80;
}
else if (rsiCrossDown && histDown)
{
SellMarket();
_cooldown = 80;
}
}
_prevRsi = rsiVal;
_prevFast = emaFast;
_prevSlow = emaSlow;
}
}
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 ExponentialMovingAverage, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class turtle_trader_strategy(Strategy):
def __init__(self):
super(turtle_trader_strategy, self).__init__()
self._entry_length = self.Param("EntryLength", 20) \
.SetDisplay("Entry Length", "Donchian breakout length", "General")
self._exit_length = self.Param("ExitLength", 10) \
.SetDisplay("Exit Length", "Donchian exit length", "General")
self._stop_pct = self.Param("StopPct", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Stop %", "Stop loss percent", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._prev_rsi = 0.0
self._prev_fast = 0.0
self._prev_slow = 0.0
self._cooldown = 0
@property
def entry_length(self):
return self._entry_length.Value
@property
def exit_length(self):
return self._exit_length.Value
@property
def stop_pct(self):
return self._stop_pct.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(turtle_trader_strategy, self).OnReseted()
self._prev_rsi = 0.0
self._prev_fast = 0.0
self._prev_slow = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(turtle_trader_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = 14
ema_fast = ExponentialMovingAverage()
ema_fast.Length = 8
ema_slow = ExponentialMovingAverage()
ema_slow.Length = 21
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(rsi, ema_fast, ema_slow, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema_fast)
self.DrawIndicator(area, ema_slow)
self.DrawOwnTrades(area)
def on_process(self, candle, rsi_val, ema_fast, ema_slow):
if candle.State != CandleStates.Finished:
return
rsi_val = float(rsi_val)
ema_fast = float(ema_fast)
ema_slow = float(ema_slow)
if self._prev_rsi == 0 or self._prev_fast == 0 or self._prev_slow == 0:
self._prev_rsi = rsi_val
self._prev_fast = ema_fast
self._prev_slow = ema_slow
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_rsi = rsi_val
self._prev_fast = ema_fast
self._prev_slow = ema_slow
return
hist = ema_fast - ema_slow
hist_up = hist > 0
hist_down = hist < 0
rsi_cross_up = self._prev_rsi <= 50 and rsi_val > 50
rsi_cross_down = self._prev_rsi >= 50 and rsi_val < 50
if self.Position > 0 and rsi_cross_down:
self.SellMarket()
self._cooldown = 80
elif self.Position < 0 and rsi_cross_up:
self.BuyMarket()
self._cooldown = 80
if self.Position == 0:
if rsi_cross_up and hist_up:
self.BuyMarket()
self._cooldown = 80
elif rsi_cross_down and hist_down:
self.SellMarket()
self._cooldown = 80
self._prev_rsi = rsi_val
self._prev_fast = ema_fast
self._prev_slow = ema_slow
def CreateClone(self):
return turtle_trader_strategy()