在 GitHub 上查看

Up3x1 Krohabor Shift 策略

概览

up3x1 Krohabor D 策略移植自 MetaTrader 4 专家顾问 up3x1_Krohabor_D.mq4。策略核心思想是对三条前移的简单移动平均线 (SMA) 进行比较,以便在所选周期上识别趋势延续突破。本 C# 版本基于 StockSharp 的高层 API,通过 K 线订阅与指标绑定完成信号计算,同时针对 .NET 环境重新实现了风控与仓位管理。

交易逻辑

  • 计算三条基于收盘价的简单移动平均线:
    • 快速 SMA(默认 24 根 K 线)
    • 中速 SMA(默认 60 根 K 线)
    • 慢速 SMA(默认 120 根 K 线)
  • 所有均线都会向前平移可配置的已完成 K 线数量(默认 6)。策略分别比较当前与上一根 K 线的移位值。
  • 多头进场条件
    • 当前与上一根慢速 SMA 均位于当前与上一根快/中速 SMA 之下,显示出多头排列。
    • 中速 SMA 相对快速 SMA 下行(上一根中速高于快速,当前中速低于快速)。
  • 空头进场条件:与多头条件完全相反。
  • 策略同一时间只允许一笔仓位;若当前没有持仓则等待新的入场信号,否则执行离场管理。

离场规则与保护

  • 通过监控 K 线高低点来模拟保护性订单:
    • 止损距离以最小价格步长(默认 110 点)表示,建仓后立即生效。
    • 止盈同样使用价格步长表示(默认 5 点)。
  • 当未实现盈亏超过阈值时(默认 10 点)启用移动止损,并始终沿盈利方向收紧止损价位。
  • 若快速 SMA 再次穿越中速与慢速 SMA,则按照原始 EA 的逻辑立即平仓。
  • 连续亏损后会自动减小下次下单手数,并受到最小手数限制,以模拟 MT4 版本的资金管理。

参数

名称 说明
FastPeriod 快速 SMA 的周期。
MediumPeriod 中速 SMA 的周期。
SlowPeriod 慢速 SMA 的周期。
MaShift 向前平移的已完成 K 线数量。
Volume 新开仓的基础手数。
MinVolume 连续亏损后允许的最小手数。
LossReductionFactor 连续亏损时缩减手数所使用的除数。
StopLossPoints 止损距离(价格步长)。
TakeProfitPoints 止盈距离(价格步长)。
TrailingPoints 移动止损距离与触发阈值(价格步长)。
CandleType 用于分析的 K 线类型或周期。

备注

  • 通过 SubscribeCandlesBind 获取指标结果,无需手动读取指标值。
  • 止损、止盈与移动止损均在策略内部模拟,可在实盘中替换为真实委托实现。
  • 代码中的注释全部采用英文,以符合项目规范。
  • 项目未附带自动化测试,请在 StockSharp 回测环境中验证不同参数组合。
using System;







using StockSharp.Algo.Indicators;



using StockSharp.Algo.Strategies;



using StockSharp.BusinessEntities;



using StockSharp.Messages;







namespace StockSharp.Samples.Strategies;







public class Up3x1KrohaborShiftStrategy : Strategy



{



	private readonly StrategyParam<int> _channelPeriod;



	private readonly StrategyParam<int> _emaPeriod;



	private readonly StrategyParam<DataType> _candleType;







	private decimal _prevClose; private decimal _prevMid; private bool _hasPrev;



	private int _cooldown;







	public int ChannelPeriod { get => _channelPeriod.Value; set => _channelPeriod.Value = value; }



	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }



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







	public Up3x1KrohaborShiftStrategy()



	{



		_channelPeriod = Param(nameof(ChannelPeriod), 20).SetDisplay("Channel Period", "Channel lookback", "Indicators");



		_emaPeriod = Param(nameof(EmaPeriod), 14).SetDisplay("EMA Period", "EMA filter", "Indicators");



		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");



	}







	/// <inheritdoc />



	protected override void OnReseted()



	{



		base.OnReseted();



		_prevClose = default;



		_prevMid = default;



		_hasPrev = default;



		_cooldown = default;



	}







	/// <inheritdoc />



	/// <inheritdoc />

	protected override void OnStarted2(DateTime time)



	{



		base.OnStarted2(time);



		_hasPrev = false;



		var highest = new Highest { Length = ChannelPeriod };



		var lowest = new Lowest { Length = ChannelPeriod };



		var subscription = SubscribeCandles(CandleType);



		subscription.Bind(highest, lowest, ProcessCandle).Start();



	}







	private void ProcessCandle(ICandleMessage candle, decimal highest, decimal lowest)



	{



		if (candle.State != CandleStates.Finished) return;



		if (!IsFormedAndOnlineAndAllowTrading()) return;



		var close = candle.ClosePrice;



		var mid = (highest + lowest) / 2;



		if (!_hasPrev) { _prevClose = close; _prevMid = mid; _hasPrev = true; return; }



		if (_cooldown > 0)



		{



			_cooldown--;



			_prevClose = close; _prevMid = mid;



			return;



		}







		if (_prevClose <= _prevMid && close > mid && Position <= 0)



		{



			var volume = Volume + Math.Abs(Position);



			BuyMarket(volume);



			_cooldown = 6;



		}



		else if (_prevClose >= _prevMid && close < mid && Position >= 0)



		{



			var volume = Volume + Math.Abs(Position);



			SellMarket(volume);



			_cooldown = 6;



		}



		_prevClose = close; _prevMid = mid;



	}



}