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
156 changes: 156 additions & 0 deletions API/2303_ADX_DMI/CS/AdxDmiStrategy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
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>
/// Directional Movement Index crossover strategy.
/// </summary>
public class AdxDmiStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleTypeParam;
private readonly StrategyParam<int> _dmiPeriod;
private readonly StrategyParam<bool> _allowLong;
private readonly StrategyParam<bool> _allowShort;
private readonly StrategyParam<bool> _closeLong;
private readonly StrategyParam<bool> _closeShort;

private DirectionalIndex _dmi = null!;
private decimal? _prevPlus;
private decimal? _prevMinus;

public AdxDmiStrategy()
{
_candleTypeParam = Param(nameof(CandleType), TimeSpan.FromHours(8).TimeFrame())
.SetDisplay("Candle Type", "Time frame for strategy calculation", "General");

_dmiPeriod = Param(nameof(DmiPeriod), 14)
.SetDisplay("DMI Period", "Directional Movement Index period", "Indicators")
.SetGreaterThanZero();

_allowLong = Param(nameof(AllowLong), true)
.SetDisplay("Allow Long", "Enable long entries", "Trading");

_allowShort = Param(nameof(AllowShort), true)
.SetDisplay("Allow Short", "Enable short entries", "Trading");

_closeLong = Param(nameof(CloseLong), true)
.SetDisplay("Close Long", "Close long positions on opposite signal", "Trading");

_closeShort = Param(nameof(CloseShort), true)
.SetDisplay("Close Short", "Close short positions on opposite signal", "Trading");
}

public DataType CandleType
{
get => _candleTypeParam.Value;
set => _candleTypeParam.Value = value;
}

public int DmiPeriod
{
get => _dmiPeriod.Value;
set => _dmiPeriod.Value = value;
}

public bool AllowLong
{
get => _allowLong.Value;
set => _allowLong.Value = value;
}

public bool AllowShort
{
get => _allowShort.Value;
set => _allowShort.Value = value;
}

public bool CloseLong
{
get => _closeLong.Value;
set => _closeLong.Value = value;
}

public bool CloseShort
{
get => _closeShort.Value;
set => _closeShort.Value = value;
}

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

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

_dmi = new DirectionalIndex
{
Length = DmiPeriod
};

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

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

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

var dmi = (DirectionalIndexValue)dmiValue;

if (dmi.Plus is not decimal currentPlus ||
dmi.Minus is not decimal currentMinus)
return;

if (_prevPlus is null || _prevMinus is null)
{
_prevPlus = currentPlus;
_prevMinus = currentMinus;
return;
}

var buySignal = _prevMinus > _prevPlus && currentMinus <= currentPlus;
var sellSignal = _prevPlus > _prevMinus && currentPlus <= currentMinus;

if (buySignal)
{
if (CloseShort && Position < 0)
BuyMarket(Math.Abs(Position));

if (AllowLong && Position <= 0)
BuyMarket(Volume);
}

if (sellSignal)
{
if (CloseLong && Position > 0)
SellMarket(Position);

if (AllowShort && Position >= 0)
SellMarket(Volume);
}

_prevPlus = currentPlus;
_prevMinus = currentMinus;
}
}
26 changes: 26 additions & 0 deletions API/2303_ADX_DMI/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# ADX DMI Strategy
[Русский](README_ru.md) | [中文](README_cn.md)

Uses the Directional Movement Index (DMI) to trade crossovers between the +DI and -DI lines. When -DI moves above +DI and then drops below it, the strategy opens a long position. When +DI rises above -DI and then falls back below, it opens a short position. Opposite signals can optionally close existing positions.

## Details

- **Entry Criteria**:
- **Long**: -DI was above +DI on the previous bar and crosses below it on the latest bar.
- **Short**: +DI was above -DI on the previous bar and crosses below it on the latest bar.
- **Exit Criteria**:
- Reverse crossover if corresponding close option is enabled.
- **Indicators**:
- Directional Index (period 14 by default)
- **Stops**: none by default.
- **Default Values**:
- `DmiPeriod` = 14
- `AllowLong` = true
- `AllowShort` = true
- `CloseLong` = true
- `CloseShort` = true
- **Filters**:
- Works on any timeframe
- Indicators: DMI
- Stops: optional via external risk management
- Complexity: basic
26 changes: 26 additions & 0 deletions API/2303_ADX_DMI/README_cn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# ADX DMI 策略
[English](README.md) | [Русский](README_ru.md)

使用方向移动指数(DMI)交易 +DI 与 -DI 线的交叉。当上一根K线的 -DI 高于 +DI 而当前K线跌破 +DI 时,策略开多仓。上一根K线的 +DI 高于 -DI 而当前K线跌破 -DI 时,策略开空仓。反向信号可选择性关闭已有仓位。

## 详情

- **入场条件**:
- **多头**:上一根 -DI > +DI,当前 -DI 下穿 +DI。
- **空头**:上一根 +DI > -DI,当前 +DI 下穿 -DI。
- **出场条件**:
- 反向交叉(若启用相应的平仓选项)。
- **指标**:
- Directional Index(默认周期 14)
- **止损**:默认无。
- **默认值**:
- `DmiPeriod` = 14
- `AllowLong` = true
- `AllowShort` = true
- `CloseLong` = true
- `CloseShort` = true
- **过滤条件**:
- 适用于任何时间周期
- 指标:DMI
- 止损:可通过外部风控模块设置
- 复杂度:基础
26 changes: 26 additions & 0 deletions API/2303_ADX_DMI/README_ru.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Стратегия ADX DMI
[English](README.md) | [中文](README_cn.md)

Использует Directional Movement Index (DMI) для торговли пересечениями линий +DI и -DI. Когда -DI находился выше +DI на предыдущей свече и опускается ниже на текущей, стратегия открывает длинную позицию. Когда +DI был выше -DI и опускается ниже, открывается короткая позиция. Обратные сигналы по желанию закрывают открытые позиции.

## Детали

- **Условия входа**:
- **Лонг**: -DI был выше +DI на предыдущей свече и пересекает её сверху вниз на текущей.
- **Шорт**: +DI был выше -DI на предыдущей свече и пересекает её сверху вниз на текущей.
- **Условия выхода**:
- Обратное пересечение при включённой соответствующей опции закрытия.
- **Индикаторы**:
- Directional Index (период по умолчанию 14)
- **Стопы**: отсутствуют по умолчанию.
- **Значения по умолчанию**:
- `DmiPeriod` = 14
- `AllowLong` = true
- `AllowShort` = true
- `CloseLong` = true
- `CloseShort` = true
- **Фильтры**:
- Работает на любых таймфреймах
- Индикаторы: DMI
- Стопы: опционально через внешнее управление рисками
- Сложность: базовая