在 GitHub 上查看

Alexav SpeedUp M1 策略

概述

Alexav SpeedUp M1 策略 是 MetaTrader 4 智能交易系统 "Alexav_SpeedUp_M1" 的直接移植版本。策略针对已经收盘的日内 K 线主体进行评估,只要实体长度超过可配置的阈值便立即市价入场。建仓之后,它会按照 MetaTrader 的习惯为持仓附加止损、止盈以及追踪止损单。

移植完全基于 StockSharp 的高级 API:通过 SubscribeCandles 订阅蜡烛数据,通过 level1 行情获取用于追踪的买一/卖一价格,并使用 BuyStopSellStopBuyLimitSellLimit 等便捷方法来挂出保护性订单,无需编写任何自定义指标计算。

信号生成

  1. 策略检查所选时间框架内每一根已收盘的蜡烛。
  2. 当蜡烛收盘价高于开盘价,并且差值超过 Body Threshold(实体阈值)时,策略以市价开多或反向开多。
  3. 当蜡烛收盘价低于开盘价,并且差值超过同一阈值时,策略以市价开空或反向开空。
  4. 如果存在反向持仓,策略会自动在市价单中追加对应的手数以平掉旧仓,从而忠实还原原始 EA 的行为。

订单管理

  • 初始止损:只要仓位增加,即在多单入场价下方(空单入场价上方)按照配置的点数挂出保护性止损单。
  • 止盈:根据 Take Profit (points) 参数,在入场方向的目标价位挂出同等手数的限价单。
  • 追踪止损:借助 level1 的买一/卖一价格监控浮动盈亏,当未实现利润超过追踪距离时,保护性止损会沿着价格移动,保持设定的间距且绝不回撤。
  • 当仓位回到零时,所有保护性订单都会被取消。

移植保持了原策略的简洁性——不会额外引入过滤条件、指标或风险控制,逻辑与 MQL 实现保持一致。

参数

名称 说明
Lot Size 每笔市价单的基础手数(以标准手计)。在反向开仓时,系统会自动增加手数以对冲原有仓位。
Take Profit (points) 入场价到止盈价之间的距离,单位为 MetaTrader 的点(会根据品种的最小跳动单位转换)。
Initial Stop (points) 入场价到初始止损价之间的距离,单位同上。
Trailing Stop (points) 当行情朝有利方向运行时,追踪止损保持的固定距离。设为 0 可以关闭追踪功能。
Body Threshold 蜡烛收盘价与开盘价的最小差值,只有超过该阈值才会触发交易。
Candle Type 用于生成信号的蜡烛序列(时间框架),默认与原 EA 的一分钟图相同。

使用说明

  • 请确保交易品种提供有效的 PriceStep。如果缺失,策略会退化为直接把点数视为价格差值。
  • 追踪止损需要 level1 行情支持(买一/卖一价)。若只有蜡烛数据,则追踪功能不会启动。
  • 策略面向日内交易,通过内部逻辑保证每根蜡烛最多触发一次交易,与原始 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>
/// Alexav SpeedUp M1 Body strategy.
/// Trades based on large candle body breakouts.
/// Buys after a large bullish candle, sells after a large bearish candle.
/// Uses ATR to define "large" body threshold.
/// </summary>
public class AlexavSpeedUpM1BodyBreakStrategy : Strategy
{
	private readonly StrategyParam<int> _atrPeriod;
	private readonly StrategyParam<decimal> _bodyMultiplier;
	private readonly StrategyParam<DataType> _candleType;

	public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
	public decimal BodyMultiplier { get => _bodyMultiplier.Value; set => _bodyMultiplier.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public AlexavSpeedUpM1BodyBreakStrategy()
	{
		_atrPeriod = Param(nameof(AtrPeriod), 14)
			.SetDisplay("ATR Period", "ATR period for body threshold", "Indicators");

		_bodyMultiplier = Param(nameof(BodyMultiplier), 1.0m)
			.SetDisplay("Body Multiplier", "Body must exceed ATR * multiplier", "Indicators");

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

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var atr = new AverageTrueRange { Length = AtrPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(atr, ProcessCandle)
			.Start();
	}

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

		var body = candle.ClosePrice - candle.OpenPrice;
		var absBody = Math.Abs(body);
		var threshold = atrValue * BodyMultiplier;

		if (absBody < threshold)
			return;

		// Large bullish candle - buy
		if (body > 0 && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Large bearish candle - sell
		else if (body < 0 && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
	}
}