Главная
/
Примеры стратегий
Открыть на GitHub
Стратегия закрытия по проценту от капитала
Стратегия контроля риска отслеживает капитал счёта и закрывает открытую позицию, когда капитал превышает текущий баланс, умноженный на заданный коэффициент. Это позволяет зафиксировать прибыль при достижении целевого роста счёта.
Проверка условия выполняется периодически по свечам. Стратегия не создаёт новые входы, а управляет уже имеющейся позицией. После закрытия базовый баланс обновляется, что даёт возможность повторять процесс для следующих сделок.
Детали
Критерии входа : нет (управляет существующей позицией).
Длинные/короткие : обе стороны.
Критерии выхода : капитал > баланс * EquityPercentFromBalance.
Стопы : нет.
Значения по умолчанию :
EquityPercentFromBalance = 1.2m
CandleType = TimeSpan.FromMinutes(1)
Фильтры :
Категория: Управление рисками
Направление: Оба
Индикаторы: Нет
Стопы: Нет
Сложность: Базовая
Таймфрейм: Внутридневной (1m)
Сезонность: Нет
Нейросети: Нет
Дивергенция: Нет
Уровень риска: Низкий
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>
/// Closes position when equity exceeds balance by a given multiplier.
/// </summary>
public class CloseByEquityPercentStrategy : Strategy
{
private readonly StrategyParam<decimal> _equityPercent;
private readonly StrategyParam<DataType> _candleType;
private decimal _currentBalance;
/// <summary>
/// Equity to balance multiplier.
/// </summary>
public decimal EquityPercentFromBalance
{
get => _equityPercent.Value;
set => _equityPercent.Value = value;
}
/// <summary>
/// Candle type for periodic checks.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of <see cref="CloseByEquityPercentStrategy"/>.
/// </summary>
public CloseByEquityPercentStrategy()
{
_equityPercent = Param(nameof(EquityPercentFromBalance), 1.2m)
.SetDisplay("Equity/Bal Multiplier", "Threshold multiplier for equity relative to balance", "Risk Management")
.SetOptimize(1.1m, 2m, 0.1m);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles for periodic checks", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_currentBalance = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_currentBalance = Portfolio?.CurrentValue ?? 0m;
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 equity = Portfolio?.CurrentValue ?? 0m;
if (equity > _currentBalance * EquityPercentFromBalance)
{
if (Position > 0)
SellMarket(Position);
else if (Position < 0)
BuyMarket(-Position);
_currentBalance = equity;
return;
}
// Simple entry when flat
if (Position == 0)
{
_currentBalance = equity;
if (candle.ClosePrice > candle.OpenPrice)
BuyMarket();
else if (candle.ClosePrice < candle.OpenPrice)
SellMarket();
}
}
}
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 close_by_equity_percent_strategy(Strategy):
def __init__(self):
super(close_by_equity_percent_strategy, self).__init__()
self._equity_percent = self.Param("EquityPercentFromBalance", 1.2) \
.SetDisplay("Equity/Bal Multiplier", "Threshold multiplier for equity relative to balance", "Risk Management")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Type of candles for periodic checks", "General")
self._current_balance = 0.0
@property
def EquityPercentFromBalance(self):
return self._equity_percent.Value
@EquityPercentFromBalance.setter
def EquityPercentFromBalance(self, value):
self._equity_percent.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(close_by_equity_percent_strategy, self).OnStarted2(time)
portfolio = self.Portfolio
if portfolio is not None:
self._current_balance = float(portfolio.CurrentValue)
else:
self._current_balance = 0.0
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self.ProcessCandle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def ProcessCandle(self, candle):
if candle.State != CandleStates.Finished:
return
portfolio = self.Portfolio
equity = float(portfolio.CurrentValue) if portfolio is not None else 0.0
if equity > self._current_balance * float(self.EquityPercentFromBalance):
pos = self.Position
if pos > 0:
self.SellMarket(pos)
elif pos < 0:
self.BuyMarket(-pos)
self._current_balance = equity
return
if self.Position == 0:
self._current_balance = equity
if candle.ClosePrice > candle.OpenPrice:
self.BuyMarket()
elif candle.ClosePrice < candle.OpenPrice:
self.SellMarket()
def OnReseted(self):
super(close_by_equity_percent_strategy, self).OnReseted()
self._current_balance = 0.0
def CreateClone(self):
return close_by_equity_percent_strategy()