Стратегия Super Take
Стратегия попеременно открывает длинные и короткие позиции и после каждого убыточного трейда увеличивает уровень тейк‑профита по принципу мартингейла. Стоп‑лосс фиксированный, а тейк‑профит после прибыльного трейда возвращается к базовому значению. Постоянно меняя направление и корректируя цель после убытков, система стремится компенсировать предыдущие просадки.
Новая позиция открывается только при отсутствии текущей. Первый трейд по умолчанию — покупка. Каждый последующий вход осуществляется в противоположную сторону от последней закрытой позиции.
Детали
- Критерии входа:
- Длинная позиция: нет активной позиции и последняя закрытая позиция была короткой либо отсутствует.
- Короткая позиция: нет активной позиции и последняя закрытая позиция была длинной.
- Длинные/короткие: обе стороны.
- Критерии выхода:
- Позиция закрывается при достижении динамического тейк‑профита или фиксированного стоп‑лосса.
- Стопы: фиксированный стоп‑лосс, тейк‑профит увеличивается по мартингейлу после убыточных сделок.
- Значения по умолчанию:
TakeProfit= 10StopLoss= 15MartinFactor= 1.8
- Фильтры:
- Категория: разворот
- Направление: обе стороны
- Индикаторы: нет
- Стопы: да
- Сложность: простая
- Таймфрейм: любой
- Сезонность: нет
- Нейросети: нет
- Дивергенция: нет
- Уровень риска: высокий
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Alternating buy/sell strategy with martingale take profit.
/// Opens trades in opposite direction after each close,
/// enlarges take profit after losses.
/// </summary>
public class SuperTakeStrategy : Strategy
{
private readonly StrategyParam<decimal> _takeProfit;
private readonly StrategyParam<decimal> _stopLoss;
private readonly StrategyParam<decimal> _martinFactor;
private readonly StrategyParam<DataType> _candleType;
private decimal _entryPrice;
private decimal _currentTakeProfit;
private decimal _lastTakeProfitDistance;
private bool _isLong;
private bool _lastTradeWasLoss;
private bool? _lastClosedWasBuy;
public decimal TakeProfit { get => _takeProfit.Value; set => _takeProfit.Value = value; }
public decimal StopLoss { get => _stopLoss.Value; set => _stopLoss.Value = value; }
public decimal MartinFactor { get => _martinFactor.Value; set => _martinFactor.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public SuperTakeStrategy()
{
_takeProfit = Param(nameof(TakeProfit), 3000m)
.SetGreaterThanZero()
.SetDisplay("Take Profit", "Base take profit distance", "Risk");
_stopLoss = Param(nameof(StopLoss), 5000m)
.SetGreaterThanZero()
.SetDisplay("Stop Loss", "Stop loss distance", "Risk");
_martinFactor = Param(nameof(MartinFactor), 1.5m)
.SetGreaterThanZero()
.SetDisplay("Martingale Factor", "Multiplier after losing trade", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0;
_currentTakeProfit = 0;
_lastTakeProfitDistance = 0;
_isLong = false;
_lastTradeWasLoss = false;
_lastClosedWasBuy = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_lastTakeProfitDistance = TakeProfit;
SubscribeCandles(CandleType)
.Bind(ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (Position != 0)
{
if (_isLong)
{
var profit = candle.ClosePrice - _entryPrice;
if (profit >= _currentTakeProfit)
{
SellMarket();
_lastTradeWasLoss = false;
_lastTakeProfitDistance = _currentTakeProfit;
_lastClosedWasBuy = true;
_entryPrice = 0;
}
else if (profit <= -StopLoss)
{
SellMarket();
_lastTradeWasLoss = true;
_lastTakeProfitDistance = _currentTakeProfit;
_lastClosedWasBuy = true;
_entryPrice = 0;
}
}
else
{
var profit = _entryPrice - candle.ClosePrice;
if (profit >= _currentTakeProfit)
{
BuyMarket();
_lastTradeWasLoss = false;
_lastTakeProfitDistance = _currentTakeProfit;
_lastClosedWasBuy = false;
_entryPrice = 0;
}
else if (profit <= -StopLoss)
{
BuyMarket();
_lastTradeWasLoss = true;
_lastTakeProfitDistance = _currentTakeProfit;
_lastClosedWasBuy = false;
_entryPrice = 0;
}
}
return;
}
var openBuy = _lastClosedWasBuy is not true;
_currentTakeProfit = _lastTradeWasLoss
? _lastTakeProfitDistance * MartinFactor
: TakeProfit;
if (openBuy)
{
BuyMarket();
_entryPrice = candle.ClosePrice;
_isLong = true;
}
else
{
SellMarket();
_entryPrice = candle.ClosePrice;
_isLong = false;
}
}
}
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
class super_take_strategy(Strategy):
def __init__(self):
super(super_take_strategy, self).__init__()
self._take_profit = self.Param("TakeProfit", 3000.0) \
.SetDisplay("Take Profit", "Base take profit distance", "Risk")
self._stop_loss = self.Param("StopLoss", 5000.0) \
.SetDisplay("Stop Loss", "Stop loss distance", "Risk")
self._martin_factor = self.Param("MartinFactor", 1.5) \
.SetDisplay("Martingale Factor", "Multiplier after losing trade", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._entry_price = 0.0
self._current_take_profit = 0.0
self._last_take_profit_distance = 0.0
self._is_long = False
self._last_trade_was_loss = False
self._last_closed_was_buy = None
@property
def TakeProfit(self):
return self._take_profit.Value
@TakeProfit.setter
def TakeProfit(self, value):
self._take_profit.Value = value
@property
def StopLoss(self):
return self._stop_loss.Value
@StopLoss.setter
def StopLoss(self, value):
self._stop_loss.Value = value
@property
def MartinFactor(self):
return self._martin_factor.Value
@MartinFactor.setter
def MartinFactor(self, value):
self._martin_factor.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(super_take_strategy, self).OnStarted2(time)
self._last_take_profit_distance = float(self.TakeProfit)
self.SubscribeCandles(self.CandleType) \
.Bind(self.ProcessCandle) \
.Start()
def ProcessCandle(self, candle):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
tp = float(self.TakeProfit)
sl = float(self.StopLoss)
mf = float(self.MartinFactor)
if self.Position != 0:
if self._is_long:
profit = close - self._entry_price
if profit >= self._current_take_profit:
self.SellMarket()
self._last_trade_was_loss = False
self._last_take_profit_distance = self._current_take_profit
self._last_closed_was_buy = True
self._entry_price = 0.0
elif profit <= -sl:
self.SellMarket()
self._last_trade_was_loss = True
self._last_take_profit_distance = self._current_take_profit
self._last_closed_was_buy = True
self._entry_price = 0.0
else:
profit = self._entry_price - close
if profit >= self._current_take_profit:
self.BuyMarket()
self._last_trade_was_loss = False
self._last_take_profit_distance = self._current_take_profit
self._last_closed_was_buy = False
self._entry_price = 0.0
elif profit <= -sl:
self.BuyMarket()
self._last_trade_was_loss = True
self._last_take_profit_distance = self._current_take_profit
self._last_closed_was_buy = False
self._entry_price = 0.0
return
open_buy = self._last_closed_was_buy is not True
if self._last_trade_was_loss:
self._current_take_profit = self._last_take_profit_distance * mf
else:
self._current_take_profit = tp
if open_buy:
self.BuyMarket()
self._entry_price = close
self._is_long = True
else:
self.SellMarket()
self._entry_price = close
self._is_long = False
def OnReseted(self):
super(super_take_strategy, self).OnReseted()
self._entry_price = 0.0
self._current_take_profit = 0.0
self._last_take_profit_distance = 0.0
self._is_long = False
self._last_trade_was_loss = False
self._last_closed_was_buy = None
def CreateClone(self):
return super_take_strategy()