在 GitHub 上查看
Alerting System 策略是 MetaTrader 4 顾问 AlertingSystem.mq4 在 StockSharp 平台上的精确移植版。原始脚本会绘制两条水平线,当价格触碰线条时播放提示音。StockSharp 实现通过订阅 Level1(最优买/卖)行情,并在价格越过预设水平时向日志写入提示,从而复现相同的监控流程。
核心思路
- 订阅 Level1 数据流,保证策略像 MQL4 中的
OnTick 一样在每个报价到来时获得买价和卖价。
- 读取用户设置的
UpperPrice 与 LowerPrice 参数。数值为 0 表示关闭对应的预警,相当于在 MetaTrader 中删除该水平线。
- 将每个最新买价与上方水平比较,同时将最新卖价与下方水平比较。
- 当行情首次越过某个启用的水平时输出一条日志提示,并等待价格回到安全区后再次“上膛”,避免重复刷屏但仍保留原始脚本的提醒含义。
参数
| 名称 |
默认值 |
说明 |
UpperPrice |
0 |
上方水平预警价。设置为 0 时禁用。 |
LowerPrice |
0 |
下方水平预警价。设置为 0 时禁用。 |
参数可以在 Designer 界面中配置,也可以在运行时修改。新的报价到达后即会采用最新数值。
运行特性
- 数据订阅:
GetWorkingSecurities 请求 Level1 流,因此即便没有蜡烛或成交明细,策略仍能获得最新报价。
- 初始化日志:
OnStarted 会记录当前配置的上下水平,方便操作者核对。
- 预警判定:
CheckUpperAlert 与 CheckLowerAlert 使用内部布尔标志,确保价格突破某条水平线时只输出一次提示,直到行情回到原有区间。
- 无交易指令:此移植版不下单,仅用于提醒,完全符合原始顾问只播放声音的定位。
- 复位:
OnReseted 会清空内部标志,下一次启动从干净状态重新计数。
推荐使用流程
- 在 StockSharp Designer 中选择目标标的并附加
AlertingSystemStrategy。
- 设定上方和/或下方预警价,若不需要某一侧则保持数值为
0。
- 启动策略。日志窗口会显示哪些预警已启用。
- 关注日志输出:当买价突破上方水平或卖价跌破下方水平时,将出现描述性的提醒信息。
转换说明
- MetaTrader 允许用鼠标拖动水平线。StockSharp 版本改为显式参数,便于重复执行并适应算法化环境。
- 原脚本在符合条件的每个 tick 都会调用
PlaySound。为了避免日志泛滥,此实现加入“防抖”逻辑,等待价格回到水平线之外后再重新触发。
- 策略没有使用任何指标,仅依赖原始报价,因此适用于任何能够提供 Level1 数据的品种和周期。
分类
- 类别:工具 / 预警
- 交易方向:无
- 执行方式:事件驱动监控
- 数据需求:Level1 买卖价
- 复杂度:基础
- 推荐周期:任意(基于报价)
- 风险管理:不适用(不持仓)
以上内容展示了在 StockSharp 中如何还原 MetaTrader 的预警顾问,并提供了实际部署时的操作要点。
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Alerting System strategy: Bollinger Band breakout.
/// Buys when price crosses above upper band, sells when below lower band.
/// </summary>
public class AlertingSystemStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _bbPeriod;
private readonly StrategyParam<decimal> _bbWidth;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int BbPeriod { get => _bbPeriod.Value; set => _bbPeriod.Value = value; }
public decimal BbWidth { get => _bbWidth.Value; set => _bbWidth.Value = value; }
public AlertingSystemStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_bbPeriod = Param(nameof(BbPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");
_bbWidth = Param(nameof(BbWidth), 2m)
.SetDisplay("BB Width", "Bollinger Bands width multiplier", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var bb = new BollingerBands
{
Length = BbPeriod,
Width = BbWidth
};
var subscription = SubscribeCandles(CandleType);
subscription.BindEx(bb, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue bbValue)
{
if (candle.State != CandleStates.Finished) return;
if (!bbValue.IsFinal) return;
var typed = (BollingerBandsValue)bbValue;
if (typed.UpBand is not decimal upper || typed.LowBand is not decimal lower) return;
var close = candle.ClosePrice;
// Mean reversion: buy at lower band, sell at upper band
if (close < lower && Position <= 0)
BuyMarket();
else if (close > upper && Position >= 0)
SellMarket();
}
}
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.Indicators import BollingerBands
from StockSharp.Algo.Strategies import Strategy
class alerting_system_strategy(Strategy):
def __init__(self):
super(alerting_system_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._bb_period = self.Param("BbPeriod", 20) \
.SetGreaterThanZero() \
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators")
self._bb_width = self.Param("BbWidth", 2.0) \
.SetDisplay("BB Width", "Bollinger Bands width multiplier", "Indicators")
@property
def candle_type(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(alerting_system_strategy, self).OnStarted2(time)
self._bb = BollingerBands()
self._bb.Length = self._bb_period.Value
self._bb.Width = self._bb_width.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(self._bb, self._process_candle).Start()
def _process_candle(self, candle, bb_value):
if candle.State != CandleStates.Finished:
return
if not bb_value.IsFinal:
return
upper = bb_value.UpBand
lower = bb_value.LowBand
if upper is None or lower is None:
return
close = float(candle.ClosePrice)
upper_val = float(upper)
lower_val = float(lower)
if close < lower_val and self.Position <= 0:
self.BuyMarket()
elif close > upper_val and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return alerting_system_strategy()