Nevalyashka Stopup 策略
该策略在每次交易结束后反向开仓,类似会翻身的玩具。若交易亏损,下一笔交易的止损和止盈距离按马丁系数放大;若交易盈利,距离恢复为初始值并可选择停止交易。
初始方向为做空。每次平仓后都会以设定的手数在相反方向重新入场。
细节
- 入场条件:
- 第一笔交易以市价卖出。
- 之后总是在上一笔平仓的反方向入场。
- 多空方向:双向。
- 离场条件:
- 价格到达入场价的止盈或止损距离时平仓。
- 止损:是,固定点数。亏损后距离按系数增加。
- 默认参数:
StopLossPoints= 150TakeProfitPoints= 50OrderVolume= 0.1MartingaleCoeff= 1.5StopAfterProfit= false
- 过滤器:
- 类别:反转 / 马丁
- 方向:双向
- 指标:无
- 止损:有
- 复杂度:简单
- 周期:任意
- 季节性:无
- 神经网络:无
- 背离:无
- 风险水平:高
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()