Forex Fraus 4 For M1s 策略
转换自 MQL4 策略 #13643。原始 EA 在 Williams %R 指标触及极值并反转时进场。此 C# 版本基于 StockSharp 的高级 API。
策略使用 1 分钟 K 线,并关注两个关键水平:
- 当 Williams %R 从低于 -99.9 上穿该值时触发做多信号。
- 当 Williams %R 从高于 -0.1 下穿该值时触发做空信号。
仓位可通过固定止损、止盈或跟踪止损退出。时间过滤器允许限制交易在特定时段内进行。
细节
- 入场条件
- 多头:
WilliamsR从下方上穿BuyThreshold(-99.9)。 - 空头:
WilliamsR从上方下穿SellThreshold(-0.1)。
- 多头:
- 多空方向:双向
- 出场条件
- 价格达到止损 (
StopLoss) 或止盈 (TakeProfit) - 启用时的跟踪止损 (
TrailingStop)
- 价格达到止损 (
- 止损类型:以价格步长计算
- 默认参数
WprPeriod= 360BuyThreshold= -99.9SellThreshold= -0.1StopLoss= 0TakeProfit= 0UseProfitTrailing= trueTrailingStop= 30TrailingStep= 1UseTimeFilter= falseStartHour= 7StopHour= 17Volume= 0.01CandleType= TimeSpan.FromMinutes(1).TimeFrame()
- 筛选标签
- 分类:趋势反转
- 方向:双向
- 指标:Williams %R
- 止损:有
- 复杂度:基础
- 时间框架:日内 (M1)
- 季节性:无
- 神经网络:无
- 背离:无
- 风险等级:中等
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Williams %R extreme cross strategy.
/// Buys when WPR crosses above oversold level, sells when crossing below overbought level.
/// </summary>
public class ForexFraus4ForM1sStrategy : Strategy
{
private readonly StrategyParam<int> _wprPeriod;
private readonly StrategyParam<decimal> _buyThreshold;
private readonly StrategyParam<decimal> _sellThreshold;
private readonly StrategyParam<DataType> _candleType;
private bool _wasOversold;
private bool _wasOverbought;
public int WprPeriod { get => _wprPeriod.Value; set => _wprPeriod.Value = value; }
public decimal BuyThreshold { get => _buyThreshold.Value; set => _buyThreshold.Value = value; }
public decimal SellThreshold { get => _sellThreshold.Value; set => _sellThreshold.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ForexFraus4ForM1sStrategy()
{
_wprPeriod = Param(nameof(WprPeriod), 100)
.SetGreaterThanZero()
.SetDisplay("Williams %R Period", "Period for Williams %R", "Indicators");
_buyThreshold = Param(nameof(BuyThreshold), -90m)
.SetDisplay("Buy Threshold", "Level crossing up triggers buy", "Trading");
_sellThreshold = Param(nameof(SellThreshold), -10m)
.SetDisplay("Sell Threshold", "Level crossing down triggers sell", "Trading");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_wasOversold = default;
_wasOverbought = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_wasOversold = false;
_wasOverbought = false;
var wpr = new WilliamsR { Length = WprPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(wpr, ProcessCandle)
.Start();
StartProtection(
takeProfit: new Unit(2, UnitTypes.Percent),
stopLoss: new Unit(1, UnitTypes.Percent)
);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, wpr);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue wprValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!wprValue.IsFormed)
return;
var wpr = wprValue.ToDecimal();
// Track oversold/overbought states
if (wpr < BuyThreshold)
_wasOversold = true;
if (wpr > SellThreshold)
_wasOverbought = true;
// Buy signal: was oversold and now crossed above threshold
if (_wasOversold && wpr > BuyThreshold && Position <= 0)
{
_wasOversold = false;
if (Position < 0) BuyMarket();
BuyMarket();
}
// Sell signal: was overbought and now crossed below threshold
else if (_wasOverbought && wpr < SellThreshold && Position >= 0)
{
_wasOverbought = false;
if (Position > 0) SellMarket();
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import WilliamsR
from StockSharp.Algo.Strategies import Strategy
class forex_fraus4_for_m1s_strategy(Strategy):
def __init__(self):
super(forex_fraus4_for_m1s_strategy, self).__init__()
self._wpr_period = self.Param("WprPeriod", 100) \
.SetDisplay("Williams %R Period", "Period for Williams %R", "Indicators")
self._buy_threshold = self.Param("BuyThreshold", -90.0) \
.SetDisplay("Buy Threshold", "Level crossing up triggers buy", "Trading")
self._sell_threshold = self.Param("SellThreshold", -10.0) \
.SetDisplay("Sell Threshold", "Level crossing down triggers sell", "Trading")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._was_oversold = False
self._was_overbought = False
@property
def WprPeriod(self):
return self._wpr_period.Value
@WprPeriod.setter
def WprPeriod(self, value):
self._wpr_period.Value = value
@property
def BuyThreshold(self):
return self._buy_threshold.Value
@BuyThreshold.setter
def BuyThreshold(self, value):
self._buy_threshold.Value = value
@property
def SellThreshold(self):
return self._sell_threshold.Value
@SellThreshold.setter
def SellThreshold(self, value):
self._sell_threshold.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(forex_fraus4_for_m1s_strategy, self).OnStarted2(time)
self._was_oversold = False
self._was_overbought = False
wpr = WilliamsR()
wpr.Length = self.WprPeriod
self.SubscribeCandles(self.CandleType) \
.BindEx(wpr, self.ProcessCandle) \
.Start()
self.StartProtection(
takeProfit=Unit(2.0, UnitTypes.Percent),
stopLoss=Unit(1.0, UnitTypes.Percent)
)
def ProcessCandle(self, candle, wpr_value):
if candle.State != CandleStates.Finished:
return
if not wpr_value.IsFormed:
return
wpr = float(wpr_value)
buy_th = float(self.BuyThreshold)
sell_th = float(self.SellThreshold)
if wpr < buy_th:
self._was_oversold = True
if wpr > sell_th:
self._was_overbought = True
if self._was_oversold and wpr > buy_th and self.Position <= 0:
self._was_oversold = False
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._was_overbought and wpr < sell_th and self.Position >= 0:
self._was_overbought = False
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def OnReseted(self):
super(forex_fraus4_for_m1s_strategy, self).OnReseted()
self._was_oversold = False
self._was_overbought = False
def CreateClone(self):
return forex_fraus4_for_m1s_strategy()