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
149 changes: 149 additions & 0 deletions API/2310_SMI_Correct/CS/SmiCorrectStrategy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
namespace StockSharp.Samples.Strategies;

using System;
using System.Collections.Generic;

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

/// <summary>
/// Strategy based on Stochastic Momentum Index crossings.
/// Buys when the SMI falls below its signal line and sells when it rises above.
/// </summary>
public class SmiCorrectStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _smiLength;
private readonly StrategyParam<int> _signalLength;

private StochasticOscillator _stochastic;
private SimpleMovingAverage _signal;
private decimal? _prevSmi;
private decimal? _prevSignal;

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

/// <summary>
/// Period for SMI calculation.
/// </summary>
public int SmiLength
{
get => _smiLength.Value;
set => _smiLength.Value = value;
}

/// <summary>
/// Smoothing period for the signal line.
/// </summary>
public int SignalLength
{
get => _signalLength.Value;
set => _signalLength.Value = value;
}

/// <summary>
/// Initializes a new instance of the <see cref="SmiCorrectStrategy"/> class.
/// </summary>
public SmiCorrectStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");

_smiLength = Param(nameof(SmiLength), 13)
.SetGreaterThanZero()
.SetDisplay("SMI Length", "Period for SMI calculation", "SMI");

_signalLength = Param(nameof(SignalLength), 5)
.SetGreaterThanZero()
.SetDisplay("Signal Length", "Smoothing period", "SMI");
}

/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}

/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevSmi = null;
_prevSignal = null;
}

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

_stochastic = new StochasticOscillator
{
K = { Length = SmiLength },
D = { Length = 1 }
};

_signal = new SimpleMovingAverage { Length = SignalLength };

var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(_stochastic, ProcessCandle)
.Start();

var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _stochastic);
DrawIndicator(area, _signal);
DrawOwnTrades(area);
}
}

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

var stoch = (StochasticOscillatorValue)stochValue;
if (stoch.K is not decimal k)
return;

var signalValue = _signal.Process(new DecimalIndicatorValue(_signal, k, candle.ServerTime));
if (!signalValue.IsFormed)
{
_prevSmi = k;
_prevSignal = signalValue.ToDecimal();
return;
}

var signal = signalValue.ToDecimal();
if (_prevSmi is null || _prevSignal is null)
{
_prevSmi = k;
_prevSignal = signal;
return;
}

var crossUp = _prevSmi < _prevSignal && k >= signal;
var crossDown = _prevSmi > _prevSignal && k <= signal;

if (crossDown && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (crossUp && Position >= 0)
SellMarket(Volume + Math.Abs(Position));

_prevSmi = k;
_prevSignal = signal;
}
}
17 changes: 17 additions & 0 deletions API/2310_SMI_Correct/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# SMI Correct Strategy

## Overview
SMI Correct Strategy implements a trading system based on the Stochastic Momentum Index (SMI) indicator. The strategy watches the SMI line and its moving average signal line. A long position is opened when the SMI crosses below the signal line. A short position is opened when the SMI crosses above the signal line.

## Parameters
- **Candle Type** – time frame of candles used for calculations.
- **SMI Length** – number of periods for the Stochastic calculation.
- **Signal Length** – smoothing period for the signal line.

## How it works
1. The strategy subscribes to candles of the specified type.
2. For each finished candle, it updates the Stochastic oscillator and the signal moving average.
3. When the SMI crosses below the signal line, any short position is closed and a long position is opened.
4. When the SMI crosses above the signal line, any long position is closed and a short position is opened.

The sample also draws candles and indicator lines on a chart for visualization.
17 changes: 17 additions & 0 deletions API/2310_SMI_Correct/README_cn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# SMI Correct 策略

## 概述
SMI Correct 策略基于 Stochastic Momentum Index (SMI) 指标进行交易。策略跟踪 SMI 线及其移动平均信号线。当 SMI 线下穿信号线时开多仓;当 SMI 线上穿信号线时开空仓。

## 参数
- **Candle Type** – 使用的K线周期。
- **SMI Length** – 计算 SMI 的周期数。
- **Signal Length** – 信号线的平滑周期。

## 工作原理
1. 策略订阅指定类型的K线。
2. 每根收盘K线更新 SMI 和信号线的数值。
3. 当 SMI 下穿信号线时,平掉空头并开多头。
4. 当 SMI 上穿信号线时,平掉多头并开空头。

示例还在图表上绘制K线和指标以供可视化。
17 changes: 17 additions & 0 deletions API/2310_SMI_Correct/README_ru.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Стратегия SMI Correct

## Обзор
Стратегия SMI Correct реализует торговую систему на основе индикатора Stochastic Momentum Index (SMI). Стратегия отслеживает линию SMI и её сигнальную скользящую среднюю. Длинная позиция открывается при пересечении SMI ниже сигнальной линии. Короткая позиция открывается при пересечении SMI выше сигнальной линии.

## Параметры
- **Candle Type** – таймфрейм используемых свечей.
- **SMI Length** – количество периодов для расчёта SMI.
- **Signal Length** – период сглаживания сигнальной линии.

## Как это работает
1. Стратегия подписывается на свечи выбранного таймфрейма.
2. Для каждой завершённой свечи обновляются значения стохастика и сигнальной средней.
3. При пересечении SMI вниз под сигнальную линию закрывается короткая позиция и открывается длинная.
4. При пересечении SMI вверх над сигнальной линией закрывается длинная позиция и открывается короткая.

Пример также отображает свечи и индикаторы на графике.