Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
129 changes: 129 additions & 0 deletions API/2355_JSatl_Candle/CS/JSatlCandleStrategy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
using System;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy based on Jurik Moving Average slope changes.
/// Opens long when JMA turns upward and short when it turns downward.
/// Includes optional stop loss and take profit protection.
/// </summary>
public class JSatlCandleStrategy : Strategy
{
private readonly StrategyParam<int> _jmaLength;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<bool> _enableStopLoss;
private readonly StrategyParam<decimal> _takeProfitPercent;

private decimal? _prevJma;
private int _prevDirection;

/// <summary>
/// JMA period length.
/// </summary>
public int JmaLength
{
get => _jmaLength.Value;
set => _jmaLength.Value = value;
}

/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}

/// <summary>
/// Stop loss percent.
/// </summary>
public decimal StopLossPercent
{
get => _stopLossPercent.Value;
set => _stopLossPercent.Value = value;
}

/// <summary>
/// Enable stop loss.
/// </summary>
public bool EnableStopLoss
{
get => _enableStopLoss.Value;
set => _enableStopLoss.Value = value;
}

/// <summary>
/// Take profit percent.
/// </summary>
public decimal TakeProfitPercent
{
get => _takeProfitPercent.Value;
set => _takeProfitPercent.Value = value;
}

public JSatlCandleStrategy()
{
_jmaLength = Param(nameof(JmaLength), 5)
.SetGreaterThanZero()
.SetDisplay("JMA Length", "Period for Jurik Moving Average", "Parameters")
.SetCanOptimize(true)
.SetOptimize(2, 20, 1);

_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for candles", "Parameters");

_stopLossPercent = Param(nameof(StopLossPercent), 1m)
.SetGreaterThanZero()
.SetDisplay("Stop Loss %", "Stop loss percent", "Risk Management")
.SetCanOptimize(true)
.SetOptimize(0.5m, 3m, 0.5m);

_enableStopLoss = Param(nameof(EnableStopLoss), true)
.SetDisplay("Enable Stop Loss", "Use stop loss", "Risk Management");

_takeProfitPercent = Param(nameof(TakeProfitPercent), 2m)
.SetGreaterThanZero()
.SetDisplay("Take Profit %", "Take profit percent", "Risk Management")
.SetCanOptimize(true)
.SetOptimize(1m, 5m, 1m);
}

/// <inheritdoc />
protected override void OnStarted(DateTimeOffset time)
{
base.OnStarted(time);

var jma = new JurikMovingAverage { Length = JmaLength };

SubscribeCandles(CandleType)
.Bind(jma, ProcessCandle)
.Start();

StartProtection(
takeProfit: new Unit(TakeProfitPercent * 100m, UnitTypes.Percent),
stopLoss: EnableStopLoss ? new Unit(StopLossPercent * 100m, UnitTypes.Percent) : null);
}

private void ProcessCandle(ICandleMessage candle, decimal jmaValue)
{
if (candle.State != CandleStates.Finished)
return;

var direction = _prevJma is decimal prev ? Math.Sign(jmaValue - prev) : 0;

if (_prevDirection <= 0 && direction > 0 && Position <= 0)
BuyMarket();
else if (_prevDirection >= 0 && direction < 0 && Position >= 0)
SellMarket();

_prevDirection = direction;
_prevJma = jmaValue;
}
}
6 changes: 6 additions & 0 deletions API/2355_JSatl_Candle/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# JSatl Candle Strategy

This strategy uses the Jurik Moving Average (JMA) to build a smoothed trend.
A long position is opened when the JMA turns upward after being flat or downward.
A short position is opened when the JMA turns downward after being flat or upward.
Optional stop loss and take profit are applied as percentages from the entry price.
6 changes: 6 additions & 0 deletions API/2355_JSatl_Candle/README_cn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# JSatl Candle 策略

该策略使用 Jurik 移动平均线 (JMA) 构建平滑趋势。
当 JMA 在横盘或下行后向上转折时开多仓。
当 JMA 在横盘或上行后向下转折时开空仓。
可选的止损和止盈按入场价格的百分比计算。
6 changes: 6 additions & 0 deletions API/2355_JSatl_Candle/README_ru.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# Стратегия JSatl Candle

Стратегия использует сглаживающую среднюю Jurik (JMA) для построения тренда.
Длинная позиция открывается, когда JMA разворачивается вверх после бокового или нисходящего движения.
Короткая позиция открывается, когда JMA разворачивается вниз после бокового или восходящего движения.
Опционально применяются стоп‑лосс и тейк‑профит в процентах от цены входа.