Diese Strategie wechselt die Positionsrichtung nach jedem Trade und imitiert das „Nevalyashka"-Spielzeug, das die Seiten wechselt. Sie verwendet einen Martingale-Ansatz: Wenn ein Trade mit Verlust geschlossen wird, werden die Stop-Loss- und Take-Profit-Abstände für den nächsten Trade mit einem Koeffizienten multipliziert. Nach einem profitablen Trade werden die Abstände auf ihre Basiswerte zurückgesetzt, und die Strategie kann optional den Handel einstellen.
Die anfängliche Richtung ist Short. Jedes Mal, wenn eine Position geschlossen wird, wird die neue Position in die entgegengesetzte Richtung mit dem vorkonfigurierten Volumen geöffnet.
Details
Einstiegskriterien:
Der erste Trade verkauft zum Marktpreis.
Nachfolgende Trades gehen immer in die entgegengesetzte Richtung des letzten geschlossenen Trades.
Long/Short: Beide.
Ausstiegskriterien:
Die Position wird geschlossen, wenn der Kurs den Take-Profit- oder Stop-Loss-Abstand vom Einstieg erreicht.
Stops: Ja, feste Stop-Loss- und Take-Profit-Abstände in Punkten. Abstände wachsen nach Verlusten um den Martingale-Koeffizienten.
Standardwerte:
StopLossPoints = 150
TakeProfitPoints = 50
OrderVolume = 0.1
MartingaleCoeff = 1.5
StopAfterProfit = false
Filter:
Kategorie: Umkehr / Martingale
Richtung: Beide
Indikatoren: Keine
Stops: Ja
Komplexität: Einfach
Zeitrahmen: Beliebig
Saisonalität: Nein
Neuronale Netze: Nein
Divergenz: Nein
Risikolevel: Hoch
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 martingale strategy.
/// Opens opposite direction after each trade and increases
/// stop loss and take profit distances after losses.
/// </summary>
public class NevalyashkaStopupStrategy : Strategy
{
private readonly StrategyParam<decimal> _stopLoss;
private readonly StrategyParam<decimal> _takeProfit;
private readonly StrategyParam<decimal> _martingaleCoeff;
private readonly StrategyParam<DataType> _candleType;
private decimal _entryPrice;
private decimal _currentStopLoss;
private decimal _currentTakeProfit;
private bool _nextIsBuy;
public decimal StopLoss { get => _stopLoss.Value; set => _stopLoss.Value = value; }
public decimal TakeProfit { get => _takeProfit.Value; set => _takeProfit.Value = value; }
public decimal MartingaleCoeff { get => _martingaleCoeff.Value; set => _martingaleCoeff.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public NevalyashkaStopupStrategy()
{
_stopLoss = Param(nameof(StopLoss), 500m)
.SetGreaterThanZero()
.SetDisplay("Stop Loss", "Stop loss in price units", "General");
_takeProfit = Param(nameof(TakeProfit), 200m)
.SetGreaterThanZero()
.SetDisplay("Take Profit", "Take profit in price units", "General");
_martingaleCoeff = Param(nameof(MartingaleCoeff), 1.5m)
.SetGreaterThanZero()
.SetDisplay("Martingale Coeff", "Multiplier applied after loss", "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()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0;
_currentStopLoss = 0;
_currentTakeProfit = 0;
_nextIsBuy = true;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_currentStopLoss = StopLoss;
_currentTakeProfit = TakeProfit;
_nextIsBuy = true;
_entryPrice = 0;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var closePrice = candle.ClosePrice;
// Open first position
if (Position == 0)
{
if (_nextIsBuy)
BuyMarket();
else
SellMarket();
_entryPrice = closePrice;
return;
}
// Check SL/TP for long
if (Position > 0)
{
if (candle.LowPrice <= _entryPrice - _currentStopLoss)
{
SellMarket();
OnTradeClosed(false);
}
else if (candle.HighPrice >= _entryPrice + _currentTakeProfit)
{
SellMarket();
OnTradeClosed(true);
}
}
// Check SL/TP for short
else if (Position < 0)
{
if (candle.HighPrice >= _entryPrice + _currentStopLoss)
{
BuyMarket();
OnTradeClosed(false);
}
else if (candle.LowPrice <= _entryPrice - _currentTakeProfit)
{
BuyMarket();
OnTradeClosed(true);
}
}
}
private void OnTradeClosed(bool wasProfit)
{
if (wasProfit)
{
_currentStopLoss = StopLoss;
_currentTakeProfit = TakeProfit;
}
else
{
_currentStopLoss *= MartingaleCoeff;
_currentTakeProfit *= MartingaleCoeff;
}
_nextIsBuy = !_nextIsBuy;
}
}
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 nevalyashka_stopup_strategy(Strategy):
def __init__(self):
super(nevalyashka_stopup_strategy, self).__init__()
self._stop_loss = self.Param("StopLoss", 500.0).SetGreaterThanZero().SetDisplay("Stop Loss", "Stop loss in price units", "General")
self._take_profit = self.Param("TakeProfit", 200.0).SetGreaterThanZero().SetDisplay("Take Profit", "Take profit in price units", "General")
self._martingale_coeff = self.Param("MartingaleCoeff", 1.5).SetGreaterThanZero().SetDisplay("Martingale Coeff", "Multiplier applied after loss", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).SetDisplay("Candle Type", "Type of candles", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(nevalyashka_stopup_strategy, self).OnReseted()
self._entry_price = 0
self._current_sl = 0
self._current_tp = 0
self._next_is_buy = True
def OnStarted2(self, time):
super(nevalyashka_stopup_strategy, self).OnStarted2(time)
self._current_sl = self._stop_loss.Value
self._current_tp = self._take_profit.Value
self._next_is_buy = True
self._entry_price = 0
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawOwnTrades(area)
def OnProcess(self, candle):
if candle.State != CandleStates.Finished:
return
close = candle.ClosePrice
if self.Position == 0:
if self._next_is_buy:
self.BuyMarket()
else:
self.SellMarket()
self._entry_price = close
return
if self.Position > 0:
if candle.LowPrice <= self._entry_price - self._current_sl:
self.SellMarket()
self._on_trade_closed(False)
elif candle.HighPrice >= self._entry_price + self._current_tp:
self.SellMarket()
self._on_trade_closed(True)
elif self.Position < 0:
if candle.HighPrice >= self._entry_price + self._current_sl:
self.BuyMarket()
self._on_trade_closed(False)
elif candle.LowPrice <= self._entry_price - self._current_tp:
self.BuyMarket()
self._on_trade_closed(True)
def _on_trade_closed(self, was_profit):
if was_profit:
self._current_sl = self._stop_loss.Value
self._current_tp = self._take_profit.Value
else:
self._current_sl *= self._martingale_coeff.Value
self._current_tp *= self._martingale_coeff.Value
self._next_is_buy = not self._next_is_buy
def CreateClone(self):
return nevalyashka_stopup_strategy()