Polish Layer Expert Advisor System Efficient
概述
该策略完整移植自 MQL4 指标交易系统 “Polish Layer Expert Advisor System Efficient”。原版建议运行在 5 或 15 分钟周期的图表上,因此这里同样只在单一时间框上运作,并且同一时间仅持有一张仓位。趋势方向由价格的快慢均线以及两条经 SMA 平滑处理的 RSI 均线共同决定;当趋势条件满足后,还需要同时通过随机指标、DeMarker 与 Williams %R 的极值反转信号确认,才会执行进出场。
交易逻辑
- 趋势过滤。 收盘价的 9 周期简单均线必须位于 45 周期线性加权均线之上才能做多,反之才能做空。与此同时,RSI 值的 9 周期 SMA 也必须高于(做多)或低于(做空)45 周期 SMA。只要任一过滤条件不同步,新的交易就会被禁止。
- 随机指标触发。 在满足多头趋势的前提下,%K 需要从下方突破超卖阈值(默认 19)并向上穿越 %D 才能触发买入。空头信号则要求 %K 从上方跌破超买阈值(默认 81)并且跌破 %D。所有平滑参数都继承自原始脚本。
- 动量确认。 多头入场还需满足 DeMarker 从下方突破 0.35,且 Williams %R 从下方突破 −81;空头则要求 DeMarker 向下突破 0.63,Williams %R 向下突破 −19。所有阈值判断均基于上一根完整 K 线与当前 K 线之间的变化。
- 仓位管理。 仅使用市价单开仓,策略在持仓期间不会加仓或反手。若设置了固定的止损/止盈,则会按照品种的最小报价步长把 “点” 转换为实际价格距离;若无法获得步长,则保护功能会被关闭。
风险管理
- 止损 / 止盈。 参数以点数表示,并通过
Security.PriceStep转换为价格差(默认约定 1 点 = 1 个最小报价步长),在入场后立即生效。将其设为0可关闭对应的保护。 - 单一仓位。 与原版 EA 一样,不会在已有仓位时开立新单。
参数
| 参数 | 默认值 | 说明 |
|---|---|---|
Volume |
0.1 |
下单手数。请根据账户合约规模自行调整。 |
CandleType |
TimeSpan.FromMinutes(15).TimeFrame() |
用于计算指标的 K 线类型。建议使用 5 或 15 分钟周期以贴近原版。 |
RsiPeriod |
14 |
RSI 基础计算周期。 |
ShortPricePeriod |
9 |
趋势过滤中使用的价格快线 SMA 周期。 |
LongPricePeriod |
45 |
趋势过滤中使用的价格慢线 LWMA 周期。 |
ShortRsiPeriod |
9 |
应用于 RSI 数值的快速 SMA 周期。 |
LongRsiPeriod |
45 |
应用于 RSI 数值的慢速 SMA 周期。 |
StochasticKPeriod |
5 |
随机指标 %K 基础周期。 |
StochasticDPeriod |
3 |
%D 平滑周期。 |
StochasticSlowing |
3 |
%K 额外放缓系数。 |
DemarkerPeriod |
14 |
DeMarker 指标的平滑周期。 |
WilliamsPeriod |
14 |
Williams %R 的回溯周期。 |
StochasticOversoldLevel |
19 |
%K 必须向上突破的超卖阈值。 |
StochasticOverboughtLevel |
81 |
%K 必须向下跌破的超买阈值。 |
DemarkerBuyLevel |
0.35 |
多头信号所需的 DeMarker 向上突破水平。 |
DemarkerSellLevel |
0.63 |
空头信号所需的 DeMarker 向下突破水平。 |
WilliamsBuyLevel |
-81 |
Williams %R 向上突破的确认水平(做多)。 |
WilliamsSellLevel |
-19 |
Williams %R 向下突破的确认水平(做空)。 |
StopLossPips |
7777 |
固定止损点数。默认的超大数值相当于关闭止损。 |
TakeProfitPips |
17 |
固定止盈点数。设为 0 可禁用止盈。 |
注意事项
- 请确保
Security.PriceStep、Security.MinVolume与Security.VolumeStep已正确配置,否则点数到价格的转换会失真。 - 所有信号都依赖相邻两根完整 K 线之间的交叉状况,回测时务必保证数据时间对齐与原策略一致。
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Polish Layer Expert Advisor System Efficient strategy converted from MQL4.
/// Combines price and RSI moving averages with Stochastic, DeMarker, and Williams %R confirmations.
/// </summary>
public class PolishLayerExpertAdvisorSystemEfficientStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _shortPricePeriod;
private readonly StrategyParam<int> _longPricePeriod;
private readonly StrategyParam<int> _shortRsiPeriod;
private readonly StrategyParam<int> _longRsiPeriod;
private readonly StrategyParam<int> _stochasticKPeriod;
private readonly StrategyParam<int> _stochasticDPeriod;
private readonly StrategyParam<int> _stochasticSlowing;
private readonly StrategyParam<int> _demarkerPeriod;
private readonly StrategyParam<int> _williamsPeriod;
private readonly StrategyParam<decimal> _stochasticOversoldLevel;
private readonly StrategyParam<decimal> _stochasticOverboughtLevel;
private readonly StrategyParam<decimal> _demarkerBuyLevel;
private readonly StrategyParam<decimal> _demarkerSellLevel;
private readonly StrategyParam<decimal> _williamsBuyLevel;
private readonly StrategyParam<decimal> _williamsSellLevel;
private readonly StrategyParam<decimal> _stopLossPips;
private readonly StrategyParam<decimal> _takeProfitPips;
private SimpleMovingAverage _shortPriceMa = null!;
private WeightedMovingAverage _longPriceMa = null!;
private RelativeStrengthIndex _rsi = null!;
private SimpleMovingAverage _shortRsiAverage = null!;
private SimpleMovingAverage _longRsiAverage = null!;
private StochasticOscillator _stochastic = null!;
private DeMarker _deMarker = null!;
private WilliamsR _williams = null!;
private decimal? _previousStochasticMain;
private decimal? _previousStochasticSignal;
private decimal? _previousDeMarker;
private decimal? _previousWilliams;
private decimal? _longStopPrice;
private decimal? _longTakePrice;
private decimal? _shortStopPrice;
private decimal? _shortTakePrice;
private decimal _priceStep;
/// <summary>
/// Candle type to process.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// RSI calculation period.
/// </summary>
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
/// <summary>
/// Period for the fast price moving average.
/// </summary>
public int ShortPricePeriod
{
get => _shortPricePeriod.Value;
set => _shortPricePeriod.Value = value;
}
/// <summary>
/// Period for the slow price moving average (LWMA).
/// </summary>
public int LongPricePeriod
{
get => _longPricePeriod.Value;
set => _longPricePeriod.Value = value;
}
/// <summary>
/// Length of the short RSI smoothing average.
/// </summary>
public int ShortRsiPeriod
{
get => _shortRsiPeriod.Value;
set => _shortRsiPeriod.Value = value;
}
/// <summary>
/// Length of the long RSI smoothing average.
/// </summary>
public int LongRsiPeriod
{
get => _longRsiPeriod.Value;
set => _longRsiPeriod.Value = value;
}
/// <summary>
/// Stochastic %K period.
/// </summary>
public int StochasticKPeriod
{
get => _stochasticKPeriod.Value;
set => _stochasticKPeriod.Value = value;
}
/// <summary>
/// Stochastic %D period.
/// </summary>
public int StochasticDPeriod
{
get => _stochasticDPeriod.Value;
set => _stochasticDPeriod.Value = value;
}
/// <summary>
/// Stochastic slowing factor.
/// </summary>
public int StochasticSlowing
{
get => _stochasticSlowing.Value;
set => _stochasticSlowing.Value = value;
}
/// <summary>
/// DeMarker period.
/// </summary>
public int DemarkerPeriod
{
get => _demarkerPeriod.Value;
set => _demarkerPeriod.Value = value;
}
/// <summary>
/// Williams %R period.
/// </summary>
public int WilliamsPeriod
{
get => _williamsPeriod.Value;
set => _williamsPeriod.Value = value;
}
/// <summary>
/// Stochastic oversold level.
/// </summary>
public decimal StochasticOversoldLevel
{
get => _stochasticOversoldLevel.Value;
set => _stochasticOversoldLevel.Value = value;
}
/// <summary>
/// Stochastic overbought level.
/// </summary>
public decimal StochasticOverboughtLevel
{
get => _stochasticOverboughtLevel.Value;
set => _stochasticOverboughtLevel.Value = value;
}
/// <summary>
/// DeMarker level for long setups.
/// </summary>
public decimal DemarkerBuyLevel
{
get => _demarkerBuyLevel.Value;
set => _demarkerBuyLevel.Value = value;
}
/// <summary>
/// DeMarker level for short setups.
/// </summary>
public decimal DemarkerSellLevel
{
get => _demarkerSellLevel.Value;
set => _demarkerSellLevel.Value = value;
}
/// <summary>
/// Williams %R threshold that confirms longs.
/// </summary>
public decimal WilliamsBuyLevel
{
get => _williamsBuyLevel.Value;
set => _williamsBuyLevel.Value = value;
}
/// <summary>
/// Williams %R threshold that confirms shorts.
/// </summary>
public decimal WilliamsSellLevel
{
get => _williamsSellLevel.Value;
set => _williamsSellLevel.Value = value;
}
/// <summary>
/// Stop-loss distance expressed in pips.
/// </summary>
public decimal StopLossPips
{
get => _stopLossPips.Value;
set => _stopLossPips.Value = value;
}
/// <summary>
/// Take-profit distance expressed in pips.
/// </summary>
public decimal TakeProfitPips
{
get => _takeProfitPips.Value;
set => _takeProfitPips.Value = value;
}
/// <summary>
/// Initializes strategy parameters.
/// </summary>
public PolishLayerExpertAdvisorSystemEfficientStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Primary timeframe for calculations", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "Base RSI length", "RSI")
;
_shortPricePeriod = Param(nameof(ShortPricePeriod), 9)
.SetGreaterThanZero()
.SetDisplay("Fast Price MA", "Length of the fast price moving average", "Trend")
;
_longPricePeriod = Param(nameof(LongPricePeriod), 45)
.SetGreaterThanZero()
.SetDisplay("Slow Price MA", "Length of the slow price moving average", "Trend")
;
_shortRsiPeriod = Param(nameof(ShortRsiPeriod), 9)
.SetGreaterThanZero()
.SetDisplay("Fast RSI MA", "Length of the fast RSI moving average", "RSI")
;
_longRsiPeriod = Param(nameof(LongRsiPeriod), 45)
.SetGreaterThanZero()
.SetDisplay("Slow RSI MA", "Length of the slow RSI moving average", "RSI")
;
_stochasticKPeriod = Param(nameof(StochasticKPeriod), 5)
.SetGreaterThanZero()
.SetDisplay("%K Period", "Stochastic %K period", "Stochastic")
;
_stochasticDPeriod = Param(nameof(StochasticDPeriod), 3)
.SetGreaterThanZero()
.SetDisplay("%D Period", "Stochastic %D period", "Stochastic");
_stochasticSlowing = Param(nameof(StochasticSlowing), 3)
.SetGreaterThanZero()
.SetDisplay("Slowing", "Stochastic slowing factor", "Stochastic");
_demarkerPeriod = Param(nameof(DemarkerPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("DeMarker Period", "DeMarker averaging period", "DeMarker");
_williamsPeriod = Param(nameof(WilliamsPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Williams %R Period", "Williams %R lookback", "Williams %R");
_stochasticOversoldLevel = Param(nameof(StochasticOversoldLevel), 19m)
.SetDisplay("%K Oversold", "Oversold level for %K", "Thresholds");
_stochasticOverboughtLevel = Param(nameof(StochasticOverboughtLevel), 81m)
.SetDisplay("%K Overbought", "Overbought level for %K", "Thresholds");
_demarkerBuyLevel = Param(nameof(DemarkerBuyLevel), 0.35m)
.SetDisplay("DeMarker Buy Level", "Minimum DeMarker value for longs", "Thresholds");
_demarkerSellLevel = Param(nameof(DemarkerSellLevel), 0.63m)
.SetDisplay("DeMarker Sell Level", "Maximum DeMarker value for shorts", "Thresholds");
_williamsBuyLevel = Param(nameof(WilliamsBuyLevel), -81m)
.SetDisplay("Williams Buy Level", "Williams %R level for longs", "Thresholds");
_williamsSellLevel = Param(nameof(WilliamsSellLevel), -19m)
.SetDisplay("Williams Sell Level", "Williams %R level for shorts", "Thresholds");
_stopLossPips = Param(nameof(StopLossPips), 7777m)
.SetNotNegative()
.SetDisplay("Stop Loss", "Stop-loss distance in pips", "Risk");
_takeProfitPips = Param(nameof(TakeProfitPips), 17m)
.SetNotNegative()
.SetDisplay("Take Profit", "Take-profit distance in pips", "Risk");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_previousStochasticMain = null;
_previousStochasticSignal = null;
_previousDeMarker = null;
_previousWilliams = null;
ResetProtectionLevels();
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
StartProtection(
takeProfit: new Unit(2, UnitTypes.Percent),
stopLoss: new Unit(1, UnitTypes.Percent));
_priceStep = Security?.PriceStep ?? 0m;
_shortPriceMa = new SimpleMovingAverage { Length = ShortPricePeriod };
_longPriceMa = new WeightedMovingAverage { Length = LongPricePeriod };
_rsi = new RelativeStrengthIndex { Length = RsiPeriod };
_shortRsiAverage = new SimpleMovingAverage { Length = ShortRsiPeriod };
_longRsiAverage = new SimpleMovingAverage { Length = LongRsiPeriod };
_stochastic = new StochasticOscillator();
_stochastic.K.Length = StochasticKPeriod;
_stochastic.D.Length = StochasticDPeriod;
_deMarker = new DeMarker { Length = DemarkerPeriod };
_williams = new WilliamsR { Length = WilliamsPeriod };
Indicators.Add(_stochastic);
Indicators.Add(_deMarker);
Indicators.Add(_williams);
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_shortPriceMa, _longPriceMa, _rsi, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _shortPriceMa);
DrawIndicator(area, _longPriceMa);
DrawIndicator(area, _rsi);
DrawIndicator(area, _stochastic);
DrawIndicator(area, _deMarker);
DrawIndicator(area, _williams);
DrawOwnTrades(area);
}
}
private void ProcessCandle(
ICandleMessage candle,
decimal fastPrice,
decimal slowPrice,
decimal rsi)
{
if (candle.State != CandleStates.Finished)
return;
var fastRsi = _shortRsiAverage.Process(rsi, candle.OpenTime, true).ToDecimal();
var slowRsi = _longRsiAverage.Process(rsi, candle.OpenTime, true).ToDecimal();
var stochasticResult = _stochastic.Process(candle);
var demarkerResult = _deMarker.Process(candle);
var williamsResult = _williams.Process(candle);
if (!_stochastic.IsFormed || !_deMarker.IsFormed || !_williams.IsFormed)
return;
if (!_shortRsiAverage.IsFormed || !_longRsiAverage.IsFormed)
return;
var stochastic = (StochasticOscillatorValue)stochasticResult;
if (stochastic.K is not decimal currentStochasticMain || stochastic.D is not decimal currentStochasticSignal)
return;
var demarker = demarkerResult.ToDecimal();
var williams = williamsResult.ToDecimal();
if (_previousStochasticMain is null || _previousStochasticSignal is null || _previousDeMarker is null || _previousWilliams is null)
{
UpdatePreviousValues(currentStochasticMain, currentStochasticSignal, demarker, williams);
return;
}
if (Position != 0)
{
UpdatePreviousValues(currentStochasticMain, currentStochasticSignal, demarker, williams);
return;
}
var longTrend = fastPrice > slowPrice && fastRsi > slowRsi;
var shortTrend = fastPrice < slowPrice && fastRsi < slowRsi;
// Simplified: just require trend + stochastic cross (relax demarker/williams requirements)
var stochasticCrossUp = _previousStochasticMain < StochasticOversoldLevel && currentStochasticMain >= StochasticOversoldLevel;
var stochasticCrossDown = _previousStochasticMain > StochasticOverboughtLevel && currentStochasticMain <= StochasticOverboughtLevel;
var longSignal = longTrend && stochasticCrossUp;
var shortSignal = shortTrend && stochasticCrossDown;
if (longSignal)
{
BuyMarket();
}
else if (shortSignal)
{
SellMarket();
}
UpdatePreviousValues(currentStochasticMain, currentStochasticSignal, demarker, williams);
}
private void TryEnterPosition(Sides side, decimal entryPrice)
{
var volume = Volume;
if (volume <= 0m)
return;
if (side == Sides.Buy)
{
BuyMarket(volume);
SetProtectionLevels(entryPrice, true);
}
else
{
SellMarket(volume);
SetProtectionLevels(entryPrice, false);
}
}
private bool ManageOpenPosition(ICandleMessage candle)
{
if (Position > 0)
{
if (_longStopPrice is decimal stop && candle.LowPrice <= stop)
{
SellMarket(Position);
ResetProtectionLevels();
return true;
}
if (_longTakePrice is decimal take && candle.HighPrice >= take)
{
SellMarket(Position);
ResetProtectionLevels();
return true;
}
}
else if (Position < 0)
{
var shortVolume = Math.Abs(Position);
if (_shortStopPrice is decimal stop && candle.HighPrice >= stop)
{
BuyMarket(shortVolume);
ResetProtectionLevels();
return true;
}
if (_shortTakePrice is decimal take && candle.LowPrice <= take)
{
BuyMarket(shortVolume);
ResetProtectionLevels();
return true;
}
}
return false;
}
private void SetProtectionLevels(decimal entryPrice, bool isLong)
{
if (_priceStep <= 0m)
{
ResetProtectionLevels();
return;
}
var stopOffset = StopLossPips > 0m ? StopLossPips * _priceStep : 0m;
var takeOffset = TakeProfitPips > 0m ? TakeProfitPips * _priceStep : 0m;
if (isLong)
{
_longStopPrice = stopOffset > 0m ? entryPrice - stopOffset : null;
_longTakePrice = takeOffset > 0m ? entryPrice + takeOffset : null;
_shortStopPrice = null;
_shortTakePrice = null;
}
else
{
_shortStopPrice = stopOffset > 0m ? entryPrice + stopOffset : null;
_shortTakePrice = takeOffset > 0m ? entryPrice - takeOffset : null;
_longStopPrice = null;
_longTakePrice = null;
}
}
private void ResetProtectionLevels()
{
_longStopPrice = null;
_longTakePrice = null;
_shortStopPrice = null;
_shortTakePrice = null;
}
private void UpdatePreviousValues(decimal stochasticMain, decimal stochasticSignal, decimal demarker, decimal williams)
{
_previousStochasticMain = stochasticMain;
_previousStochasticSignal = stochasticSignal;
_previousDeMarker = demarker;
_previousWilliams = williams;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates, UnitTypes
from StockSharp.Algo.Strategies import Strategy
from StockSharp.Algo.Indicators import (
SimpleMovingAverage,
WeightedMovingAverage,
RelativeStrengthIndex,
StochasticOscillator,
DeMarker,
WilliamsR,
CandleIndicatorValue,
)
from indicator_extensions import *
class polish_layer_expert_advisor_system_efficient_strategy(Strategy):
def __init__(self):
super(polish_layer_expert_advisor_system_efficient_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Primary timeframe for calculations", "General")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "Base RSI length", "RSI")
self._short_price_period = self.Param("ShortPricePeriod", 9) \
.SetDisplay("Fast Price MA", "Length of the fast price moving average", "Trend")
self._long_price_period = self.Param("LongPricePeriod", 45) \
.SetDisplay("Slow Price MA", "Length of the slow price moving average", "Trend")
self._short_rsi_period = self.Param("ShortRsiPeriod", 9) \
.SetDisplay("Fast RSI MA", "Length of the fast RSI moving average", "RSI")
self._long_rsi_period = self.Param("LongRsiPeriod", 45) \
.SetDisplay("Slow RSI MA", "Length of the slow RSI moving average", "RSI")
self._stochastic_k_period = self.Param("StochasticKPeriod", 5) \
.SetDisplay("%K Period", "Stochastic %K period", "Stochastic")
self._stochastic_d_period = self.Param("StochasticDPeriod", 3) \
.SetDisplay("%D Period", "Stochastic %D period", "Stochastic")
self._stochastic_slowing = self.Param("StochasticSlowing", 3) \
.SetDisplay("Slowing", "Stochastic slowing factor", "Stochastic")
self._demarker_period = self.Param("DemarkerPeriod", 14) \
.SetDisplay("DeMarker Period", "DeMarker averaging period", "DeMarker")
self._williams_period = self.Param("WilliamsPeriod", 14) \
.SetDisplay("Williams %R Period", "Williams %R lookback", "Williams %R")
self._stochastic_oversold_level = self.Param("StochasticOversoldLevel", 19.0) \
.SetDisplay("%K Oversold", "Oversold level for %K", "Thresholds")
self._stochastic_overbought_level = self.Param("StochasticOverboughtLevel", 81.0) \
.SetDisplay("%K Overbought", "Overbought level for %K", "Thresholds")
self._demarker_buy_level = self.Param("DemarkerBuyLevel", 0.35) \
.SetDisplay("DeMarker Buy Level", "Minimum DeMarker value for longs", "Thresholds")
self._demarker_sell_level = self.Param("DemarkerSellLevel", 0.63) \
.SetDisplay("DeMarker Sell Level", "Maximum DeMarker value for shorts", "Thresholds")
self._williams_buy_level = self.Param("WilliamsBuyLevel", -81.0) \
.SetDisplay("Williams Buy Level", "Williams %R level for longs", "Thresholds")
self._williams_sell_level = self.Param("WilliamsSellLevel", -19.0) \
.SetDisplay("Williams Sell Level", "Williams %R level for shorts", "Thresholds")
self._stop_loss_pips = self.Param("StopLossPips", 7777.0) \
.SetDisplay("Stop Loss", "Stop-loss distance in pips", "Risk")
self._take_profit_pips = self.Param("TakeProfitPips", 17.0) \
.SetDisplay("Take Profit", "Take-profit distance in pips", "Risk")
self._previous_stochastic_main = None
self._previous_stochastic_signal = None
self._previous_demarker = None
self._previous_williams = None
self._short_price_ma = None
self._long_price_ma = None
self._rsi = None
self._short_rsi_average = None
self._long_rsi_average = None
self._stochastic = None
self._de_marker = None
self._williams = None
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@property
def ShortPricePeriod(self):
return self._short_price_period.Value
@property
def LongPricePeriod(self):
return self._long_price_period.Value
@property
def ShortRsiPeriod(self):
return self._short_rsi_period.Value
@property
def LongRsiPeriod(self):
return self._long_rsi_period.Value
@property
def StochasticKPeriod(self):
return self._stochastic_k_period.Value
@property
def StochasticDPeriod(self):
return self._stochastic_d_period.Value
@property
def DemarkerPeriod(self):
return self._demarker_period.Value
@property
def WilliamsPeriod(self):
return self._williams_period.Value
@property
def StochasticOversoldLevel(self):
return self._stochastic_oversold_level.Value
@property
def StochasticOverboughtLevel(self):
return self._stochastic_overbought_level.Value
def OnStarted2(self, time):
super(polish_layer_expert_advisor_system_efficient_strategy, self).OnStarted2(time)
from StockSharp.Messages import Unit
self.StartProtection(Unit(2, UnitTypes.Percent), Unit(1, UnitTypes.Percent))
self._short_price_ma = SimpleMovingAverage()
self._short_price_ma.Length = self.ShortPricePeriod
self._long_price_ma = WeightedMovingAverage()
self._long_price_ma.Length = self.LongPricePeriod
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.RsiPeriod
self._short_rsi_average = SimpleMovingAverage()
self._short_rsi_average.Length = self.ShortRsiPeriod
self._long_rsi_average = SimpleMovingAverage()
self._long_rsi_average.Length = self.LongRsiPeriod
self._stochastic = StochasticOscillator()
self._stochastic.K.Length = self.StochasticKPeriod
self._stochastic.D.Length = self.StochasticDPeriod
self._de_marker = DeMarker()
self._de_marker.Length = self.DemarkerPeriod
self._williams = WilliamsR()
self._williams.Length = self.WilliamsPeriod
self.Indicators.Add(self._stochastic)
self.Indicators.Add(self._de_marker)
self.Indicators.Add(self._williams)
subscription = self.SubscribeCandles(self.CandleType)
subscription \
.Bind(self._short_price_ma, self._long_price_ma, self._rsi, self.ProcessCandle) \
.Start()
def ProcessCandle(self, candle, fast_price, slow_price, rsi):
if candle.State != CandleStates.Finished:
return
fast_price = float(fast_price)
slow_price = float(slow_price)
rsi_val = float(rsi)
fast_rsi_result = process_float(self._short_rsi_average, rsi, candle.OpenTime, True)
slow_rsi_result = process_float(self._long_rsi_average, rsi, candle.OpenTime, True)
stoch_input = CandleIndicatorValue(self._stochastic, candle)
stoch_input.IsFinal = True
stochastic_result = self._stochastic.Process(stoch_input)
dm_input = CandleIndicatorValue(self._de_marker, candle)
dm_input.IsFinal = True
demarker_result = self._de_marker.Process(dm_input)
wr_input = CandleIndicatorValue(self._williams, candle)
wr_input.IsFinal = True
williams_result = self._williams.Process(wr_input)
if not self._stochastic.IsFormed or not self._de_marker.IsFormed or not self._williams.IsFormed:
return
if not self._short_rsi_average.IsFormed or not self._long_rsi_average.IsFormed:
return
fast_rsi = float(fast_rsi_result)
slow_rsi = float(slow_rsi_result)
stoch_val = stochastic_result
current_stochastic_main = stoch_val.K
current_stochastic_signal = stoch_val.D
if current_stochastic_main is None or current_stochastic_signal is None:
return
current_stochastic_main = float(current_stochastic_main)
current_stochastic_signal = float(current_stochastic_signal)
demarker = float(demarker_result)
williams = float(williams_result)
if (self._previous_stochastic_main is None or
self._previous_stochastic_signal is None or
self._previous_demarker is None or
self._previous_williams is None):
self._update_previous(current_stochastic_main, current_stochastic_signal, demarker, williams)
return
if self.Position != 0:
self._update_previous(current_stochastic_main, current_stochastic_signal, demarker, williams)
return
long_trend = fast_price > slow_price and fast_rsi > slow_rsi
short_trend = fast_price < slow_price and fast_rsi < slow_rsi
stoch_cross_up = (self._previous_stochastic_main < float(self.StochasticOversoldLevel)
and current_stochastic_main >= float(self.StochasticOversoldLevel))
stoch_cross_down = (self._previous_stochastic_main > float(self.StochasticOverboughtLevel)
and current_stochastic_main <= float(self.StochasticOverboughtLevel))
long_signal = long_trend and stoch_cross_up
short_signal = short_trend and stoch_cross_down
if long_signal:
self.BuyMarket()
elif short_signal:
self.SellMarket()
self._update_previous(current_stochastic_main, current_stochastic_signal, demarker, williams)
def _update_previous(self, stoch_main, stoch_signal, demarker, williams):
self._previous_stochastic_main = stoch_main
self._previous_stochastic_signal = stoch_signal
self._previous_demarker = demarker
self._previous_williams = williams
def OnReseted(self):
super(polish_layer_expert_advisor_system_efficient_strategy, self).OnReseted()
self._previous_stochastic_main = None
self._previous_stochastic_signal = None
self._previous_demarker = None
self._previous_williams = None
def CreateClone(self):
return polish_layer_expert_advisor_system_efficient_strategy()