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
123 changes: 123 additions & 0 deletions API/2324_RAVI_Histogram/CS/RaviHistogramStrategy.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// RAVI Histogram trend strategy based on fast and slow EMA difference.
/// </summary>
public class RaviHistogramStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<decimal> _upLevel;
private readonly StrategyParam<decimal> _downLevel;
private readonly StrategyParam<bool> _buyOpen;
private readonly StrategyParam<bool> _sellOpen;
private readonly StrategyParam<bool> _buyClose;
private readonly StrategyParam<bool> _sellClose;
private readonly StrategyParam<DataType> _candleType;

private decimal _prevRavi;
private bool _isFirst = true;

public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
public decimal UpLevel { get => _upLevel.Value; set => _upLevel.Value = value; }
public decimal DownLevel { get => _downLevel.Value; set => _downLevel.Value = value; }
public bool BuyOpen { get => _buyOpen.Value; set => _buyOpen.Value = value; }
public bool SellOpen { get => _sellOpen.Value; set => _sellOpen.Value = value; }
public bool BuyClose { get => _buyClose.Value; set => _buyClose.Value = value; }
public bool SellClose { get => _sellClose.Value; set => _sellClose.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

public RaviHistogramStrategy()
{
_fastLength = Param(nameof(FastLength), 7)
.SetGreaterThanZero()
.SetDisplay("Fast Length", "Fast EMA length", "General");

_slowLength = Param(nameof(SlowLength), 65)
.SetGreaterThanZero()
.SetDisplay("Slow Length", "Slow EMA length", "General");

_upLevel = Param(nameof(UpLevel), 0.1m)
.SetDisplay("Upper Level", "Upper threshold for trend", "General");

_downLevel = Param(nameof(DownLevel), -0.1m)
.SetDisplay("Lower Level", "Lower threshold for trend", "General");

_buyOpen = Param(nameof(BuyOpen), true)
.SetDisplay("Open Long", "Allow opening long positions", "Trading");

_sellOpen = Param(nameof(SellOpen), true)
.SetDisplay("Open Short", "Allow opening short positions", "Trading");

_buyClose = Param(nameof(BuyClose), true)
.SetDisplay("Close Long", "Allow closing long positions", "Trading");

_sellClose = Param(nameof(SellClose), true)
.SetDisplay("Close Short", "Allow closing short positions", "Trading");

_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}

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

protected override void OnStarted(DateTimeOffset time)
{
base.OnStarted(time);

var fast = new EMA { Length = FastLength };
var slow = new EMA { Length = SlowLength };

// Subscribe to candle data and bind indicators.
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
}

private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished || slow == 0)
return;

// Calculate RAVI value from EMA difference.
var ravi = 100m * (fast - slow) / slow;

if (_isFirst)
{
_prevRavi = ravi;
_isFirst = false;
return;
}

// Handle signals when RAVI crosses thresholds.
if (ravi > UpLevel)
{
if (SellClose && Position < 0)
BuyMarket();

if (BuyOpen && _prevRavi <= UpLevel && Position <= 0)
BuyMarket();
}
else if (ravi < DownLevel)
{
if (BuyClose && Position > 0)
SellMarket();

if (SellOpen && _prevRavi >= DownLevel && Position >= 0)
SellMarket();
}

_prevRavi = ravi;
}
}
22 changes: 22 additions & 0 deletions API/2324_RAVI_Histogram/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# RAVI Histogram Strategy
[Русский](README_ru.md) | [中文](README_cn.md)

This strategy converts the MetaTrader RAVI Histogram expert to StockSharp. It measures trend strength as the percentage difference between a fast and a slow EMA. The result is compared with upper and lower levels to decide when to trade.

When the RAVI value rises above the upper level the market is considered bullish. Short positions are closed and, if enabled, a long position is opened. When the value falls below the lower level the strategy closes longs and may open a short. By default it operates on four‑hour candles.

## Details

- **Entry Criteria**:
- **Long**: RAVI crosses upward through `UpLevel`.
- **Short**: RAVI crosses downward through `DownLevel`.
- **Long/Short**: Both.
- **Exit Criteria**:
- Opposite RAVI signal closes existing positions.
- **Stops**: None.
- **Filters**: None.
- **Timeframe**: 4‑hour candles by default.
- **Parameters**:
- `FastLength` and `SlowLength` – EMA periods for RAVI calculation.
- `UpLevel` and `DownLevel` – thresholds defining trending zones.
- `BuyOpen`, `SellOpen`, `BuyClose`, `SellClose` – enable or disable operations in each direction.
22 changes: 22 additions & 0 deletions API/2324_RAVI_Histogram/README_cn.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# RAVI Histogram 策略
[English](README.md) | [Русский](README_ru.md)

该策略将 MetaTrader 的 RAVI Histogram 专家移植到 StockSharp。RAVI 指标通过比较快 EMA 与慢 EMA 的百分比差异来衡量趋势强度,并与上下阈值比较以决定交易。

当 RAVI 高于上限时,被视为多头趋势:若允许,将平掉空头并开多。当 RAVI 低于下限时,策略关闭多头并可开空。默认使用四小时 K 线。

## 细节

- **入场条件**:
- **多头**:RAVI 向上突破 `UpLevel`。
- **空头**:RAVI 向下跌破 `DownLevel`。
- **方向**:可做多也可做空。
- **出场条件**:
- RAVI 产生相反信号时平仓。
- **止损**:无。
- **过滤器**:无。
- **时间框架**:默认 4 小时。
- **参数**:
- `FastLength` 与 `SlowLength` — 用于计算 RAVI 的 EMA 周期。
- `UpLevel` 与 `DownLevel` — 定义趋势区域的阈值。
- `BuyOpen`、`SellOpen`、`BuyClose`、`SellClose` — 各方向操作的开关。
22 changes: 22 additions & 0 deletions API/2324_RAVI_Histogram/README_ru.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Стратегия RAVI Histogram
[English](README.md) | [中文](README_cn.md)

Эта стратегия представляет собой перенос эксперта MetaTrader RAVI Histogram в StockSharp. Индикатор RAVI измеряет силу тренда как процентное различие между быстрой и медленной EMA. Полученное значение сравнивается с верхним и нижним уровнями для принятия торговых решений.

Когда RAVI поднимается выше верхнего уровня, рынок считается растущим: короткие позиции закрываются и, при разрешении, открывается длинная. Когда значение опускается ниже нижнего уровня, стратегия закрывает длинные позиции и может открыть короткую. По умолчанию используется четырёхчасовой таймфрейм.

## Подробности

- **Условия входа**:
- **Long**: RAVI пересекает `UpLevel` снизу вверх.
- **Short**: RAVI пересекает `DownLevel` сверху вниз.
- **Направления**: длинные и короткие.
- **Условия выхода**:
- Противоположный сигнал RAVI закрывает текущие позиции.
- **Стопы**: отсутствуют.
- **Фильтры**: отсутствуют.
- **Таймфрейм**: по умолчанию 4-часовые свечи.
- **Параметры**:
- `FastLength` и `SlowLength` – периоды EMA для расчёта RAVI.
- `UpLevel` и `DownLevel` – пороги, определяющие зоны тренда.
- `BuyOpen`, `SellOpen`, `BuyClose`, `SellClose` – разрешение операций в каждую сторону.