Start
/
Strategie-Beispiele
Auf GitHub ansehen
Take Profit Breakout Strategy
This strategy replicates the MetaTrader "take-profit" expert by looking for four consecutive candles with strictly monotonic highs and opens. When the current candle completes with rising highs and opens the algorithm treats the sequence as bullish momentum and submits a market buy. A mirrored condition with falling highs and opens produces a market sell. Orders are managed with an account-level profit target, a trailing stop that can partially close exposure, and an optional fixed stop-loss defined in price steps.
The default configuration trades on one-minute candles. The strategy can be tuned for different instruments by adjusting the candle type, shift indexes that control which candles are compared, trailing distance, stop-loss distance, profit target, and position sizing mode. It supports either a fixed lot size or a dynamic volume computed from the portfolio equity and user-defined risk percentage. When the trailing stop advances the algorithm can optionally close half of the remaining position to lock in profits while keeping a runner active.
Reaching the configured profit target measured on portfolio equity immediately liquidates the current position and cancels any working orders. This mirrors the original MQL expert that closed all trades when account equity exceeded balance plus the desired gain. The risk-management branch validates the configured risk percentage and ensures the requested volume respects the security volume step.
Details
Entry Logic :
Long : the four monitored candles show strictly increasing highs and strictly increasing opens.
Short : the four monitored candles show strictly decreasing highs and strictly decreasing opens.
Position Management :
Optional stop-loss placed at the entry price minus/plus the configured number of price steps.
Trailing stop follows the close price once it moves more than the trailing distance from the entry.
Partial exit (50% of the remaining volume) is executed every time the trailing stop moves, subject to the security volume step and the minimum tradable lot.
Account Target : closes all exposure and cancels active orders when portfolio equity ≥ initial equity + ProfitTarget.
Risk Management :
Fixed lot mode uses the configured Lots parameter (or Volume from the strategy base if specified).
Risk-percent mode sizes the order as equity * RiskPercent / max(stopDistance, price) and normalizes the result by the volume step.
Default Parameters :
Shift1 = 0, Shift2 = 1, Shift3 = 2, Shift4 = 3.
TrailingStopPoints = 1, StopLossPoints = 0, ProfitTarget = 1 (account currency units).
Lots = 1, RiskPercent = 1, MaxOrders = 1.
CandleType = 1-minute time frame.
Best Markets : trending futures, FX majors, and liquid crypto pairs where short-term momentum persists across multiple candles.
Strengths : fast momentum detection, configurable equity target, partial scaling-out, and simple risk controls.
Weaknesses : sensitive to noisy ranges, depends on correct step sizes, and assumes netting mode (single aggregated position).
Parameters
Name
Description
Shift1 – Shift4
Indexes of the candles compared for the breakout sequence.
TrailingStopPoints
Trailing distance in price steps.
StopLossPoints
Initial stop distance in price steps; zero disables the stop-loss.
ProfitTarget
Profit target applied to portfolio equity before closing all trades.
Lots
Fixed trading volume when risk management is disabled.
RiskManagement
Enables risk-based sizing using RiskPercent.
RiskPercent
Percentage of portfolio equity risked on each trade when risk management is active.
PartialClose
If enabled, closes half of the position whenever the trailing stop moves.
MaxOrders
Maximum number of base units allowed simultaneously (net position limit).
CandleType
Time frame used for signal generation.
Usage Tips
Align the Shift parameters with the instrument's volatility. Larger shifts analyze longer momentum sequences.
Set TrailingStopPoints relative to the security price step; too small values may generate rapid partial exits.
Use risk-percent sizing with an explicit StopLossPoints so the position size reflects the actual monetary risk per trade.
Monitor the equity curve: once the global target is hit the strategy stops trading until restarted, mimicking the original EA.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Take Profit Breakout: Consecutive candle breakout with EMA filter and ATR stops.
/// </summary>
public class TakeProfitBreakoutStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastEmaLength;
private readonly StrategyParam<int> _slowEmaLength;
private readonly StrategyParam<int> _atrLength;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
public TakeProfitBreakoutStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_fastEmaLength = Param(nameof(FastEmaLength), 10)
.SetDisplay("Fast EMA Length", "Fast EMA period.", "Indicators");
_slowEmaLength = Param(nameof(SlowEmaLength), 30)
.SetDisplay("Slow EMA Length", "Slow EMA period.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period.", "Indicators");
}
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int FastEmaLength { get => _fastEmaLength.Value; set => _fastEmaLength.Value = value; }
public int SlowEmaLength { get => _slowEmaLength.Value; set => _slowEmaLength.Value = value; }
public int AtrLength { get => _atrLength.Value; set => _atrLength.Value = value; }
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0; _prevSlow = 0; _entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = 0; _prevSlow = 0; _entryPrice = 0;
var fastEma = new ExponentialMovingAverage { Length = FastEmaLength };
var slowEma = new ExponentialMovingAverage { Length = SlowEmaLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fastEma, slowEma, atr, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fastEma); DrawIndicator(area, slowEma); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished) return;
if (_prevFast == 0 || _prevSlow == 0 || atrVal <= 0) { _prevFast = fastVal; _prevSlow = slowVal; return; }
var close = candle.ClosePrice;
if (Position > 0)
{
if ((fastVal < slowVal && _prevFast >= _prevSlow) || close <= _entryPrice - atrVal * 2m) { SellMarket(); _entryPrice = 0; }
}
else if (Position < 0)
{
if ((fastVal > slowVal && _prevFast <= _prevSlow) || close >= _entryPrice + atrVal * 2m) { BuyMarket(); _entryPrice = 0; }
}
if (Position == 0)
{
if (fastVal > slowVal && _prevFast <= _prevSlow) { _entryPrice = close; BuyMarket(); }
else if (fastVal < slowVal && _prevFast >= _prevSlow) { _entryPrice = close; SellMarket(); }
}
_prevFast = fastVal; _prevSlow = slowVal;
}
}
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.Strategies import Strategy
from StockSharp.Algo.Indicators import ExponentialMovingAverage, AverageTrueRange
class take_profit_breakout_strategy(Strategy):
def __init__(self):
super(take_profit_breakout_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._fast_ema_length = self.Param("FastEmaLength", 10) \
.SetDisplay("Fast EMA Length", "Fast EMA period.", "Indicators")
self._slow_ema_length = self.Param("SlowEmaLength", 30) \
.SetDisplay("Slow EMA Length", "Slow EMA period.", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period.", "Indicators")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastEmaLength(self):
return self._fast_ema_length.Value
@property
def SlowEmaLength(self):
return self._slow_ema_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
def OnStarted2(self, time):
super(take_profit_breakout_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._fast_ema = ExponentialMovingAverage()
self._fast_ema.Length = self.FastEmaLength
self._slow_ema = ExponentialMovingAverage()
self._slow_ema.Length = self.SlowEmaLength
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._fast_ema, self._slow_ema, self._atr, self.ProcessCandle).Start()
def ProcessCandle(self, candle, fast_val, slow_val, atr_val):
if candle.State != CandleStates.Finished:
return
fv = float(fast_val)
sv = float(slow_val)
av = float(atr_val)
if self._prev_fast == 0 or self._prev_slow == 0 or av <= 0:
self._prev_fast = fv
self._prev_slow = sv
return
close = float(candle.ClosePrice)
if self.Position > 0:
if (fv < sv and self._prev_fast >= self._prev_slow) or close <= self._entry_price - av * 2.0:
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0:
if (fv > sv and self._prev_fast <= self._prev_slow) or close >= self._entry_price + av * 2.0:
self.BuyMarket()
self._entry_price = 0.0
if self.Position == 0:
if fv > sv and self._prev_fast <= self._prev_slow:
self._entry_price = close
self.BuyMarket()
elif fv < sv and self._prev_fast >= self._prev_slow:
self._entry_price = close
self.SellMarket()
self._prev_fast = fv
self._prev_slow = sv
def OnReseted(self):
super(take_profit_breakout_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
def CreateClone(self):
return take_profit_breakout_strategy()