在 GitHub 上查看
OHLC Check 策略
概述
OHLC Check 策略复刻了经典的 MetaTrader 智能交易系统:它观察历史蜡烛的开盘价、最高价、最低价和收盘价,并根据蜡烛实体的方向来下单。策略允许用户选择信号引用的历史偏移量,还可以反转信号方向,从而在没有技术指标的情况下完成基于价格行为的交易。
运行逻辑
- 策略订阅所选周期的蜡烛,只有在蜡烛收盘后才会处理数据。
- 每根收盘蜡烛都会存储其开盘价与收盘价,供
SignalShift 参数访问较早的历史数据。
- 如果收盘价高于开盘价,生成做多信号;如果收盘价低于开盘价,生成做空信号;若两者相等则跳过交易。
ReverseSignals 参数可以反转方向,完全模拟原始 EA 的反向交易模式。
- 当当前没有持仓时,只要最新买卖价之间的差值不超过
SpreadLimitPips 所设的阈值,策略就会按信号方向发送市价单。买卖差值通过订阅深度数据实时跟踪。
- 如果已经持仓,出现反向信号时策略仅关闭原有仓位,而不是直接反手,这与 MQL 实现保持一致。
- 在启动阶段会按照点值距离创建止盈和止损保护,数值会按照交易品种的价格步长自动换算。
参数
| 参数 |
默认值 |
说明 |
CandleType |
5 分钟周期 |
用于判断信号的蜡烛类型。 |
StopLossPips |
50 |
止损距离(点);为 0 时关闭止损。 |
TakeProfitPips |
100 |
止盈距离(点);为 0 时关闭止盈。 |
ReverseSignals |
false |
是否反转多空信号。 |
SpreadLimitPips |
1 |
开仓时允许的最大点差。 |
SignalShift |
1 |
用于计算信号的历史偏移量(1 表示上一根已收盘蜡烛)。 |
OrderVolume |
1 |
每次市价单的下单数量。 |
使用提示
- 策略会根据交易品种的价格精度自动将点值转换成价格步长;当报价保留 3 或 5 位小数时,会自动乘以 10 以匹配常规点值。
- 为了正确检查点差,需要在数据源中启用委托簿/盘口订阅。如果没有可用的买价或卖价,策略会跳过开仓。
- 止盈止损在
OnStarted 阶段只初始化一次,若需要修改距离请在修改参数后重新启动策略。
- 该策略只关注蜡烛实体,不会使用最高价与最低价,与原始 MQL 代码完全一致。
部署步骤
- 将策略应用到同时提供蜡烛数据和盘口数据的交易品种上。
- 根据交易风格设置周期、点值距离和下单量等参数。
- 启动策略,策略会等待下一根收盘蜡烛后开始执行。
- 观察日志中的点差拒绝或成交记录,并根据需要微调参数。
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>
/// OHLC check strategy. Trades based on candle structure (bullish/bearish body).
/// </summary>
public class OhlcCheckStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _confirmBars;
private int _bullCount;
private int _bearCount;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int ConfirmBars
{
get => _confirmBars.Value;
set => _confirmBars.Value = value;
}
public OhlcCheckStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_confirmBars = Param(nameof(ConfirmBars), 3)
.SetGreaterThanZero()
.SetDisplay("Confirm Bars", "Consecutive candles to confirm direction", "Trading");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_bullCount = 0;
_bearCount = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_bullCount = 0;
_bearCount = 0;
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;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (candle.ClosePrice > candle.OpenPrice)
{
_bullCount++;
_bearCount = 0;
}
else if (candle.ClosePrice < candle.OpenPrice)
{
_bearCount++;
_bullCount = 0;
}
// Consecutive bullish candles → buy
if (_bullCount >= ConfirmBars && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
_bullCount = 0;
}
// Consecutive bearish candles → sell
else if (_bearCount >= ConfirmBars && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
_bearCount = 0;
}
}
}
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 ohlc_check_strategy(Strategy):
def __init__(self):
super(ohlc_check_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._confirm_bars = self.Param("ConfirmBars", 3) \
.SetDisplay("Confirm Bars", "Consecutive candles to confirm direction", "Trading")
self._bull_count = 0
self._bear_count = 0
@property
def CandleType(self):
return self._candle_type.Value
@property
def ConfirmBars(self):
return self._confirm_bars.Value
def OnReseted(self):
super(ohlc_check_strategy, self).OnReseted()
self._bull_count = 0
self._bear_count = 0
def OnStarted2(self, time):
super(ohlc_check_strategy, self).OnStarted2(time)
self._bull_count = 0
self._bear_count = 0
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _on_process(self, candle):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
open_price = float(candle.OpenPrice)
if close > open_price:
self._bull_count += 1
self._bear_count = 0
elif close < open_price:
self._bear_count += 1
self._bull_count = 0
cb = int(self.ConfirmBars)
# Consecutive bullish candles
if self._bull_count >= cb and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._bull_count = 0
# Consecutive bearish candles
elif self._bear_count >= cb and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._bear_count = 0
def CreateClone(self):
return ohlc_check_strategy()