LANZ戦略 5.0
LANZ戦略5.0は200期間EMAの方向に取引し、同じ色の3本連続ローソク足を必要とします。1日の取引回数、ニューヨーク時間帯、エントリー間の最小距離で取引を制限します。
詳細
- エントリー条件:
- ロングエントリー: EMA上方に価格があり、3本の強気ローソク足。
- ショートエントリー: EMA下方に価格があり、3本の弱気ローソク足(オプション)。
- ロング/ショート: デフォルトはロング。
- エグジット条件:
- 固定ストップロスまたはテイクプロフィット。
- 設定時刻に手動決済。
- ストップ:
- ストップロス = 40 pips。
- テイクプロフィット = 120 pips。
- デフォルト値:
EmaPeriod= 200MaxTrades= 99MinDistancePips= 25StopLossPips= 40TakeProfitPips= 120StartHour= 19EndHour= 15
- フィルター:
- カテゴリ: トレンド
- 方向: ロング
- インジケーター: EMA
- ストップ: はい
- 複雑さ: 中程度
- 時間軸: 任意
- 季節性: いいえ
- ニューラルネットワーク: いいえ
- ダイバージェンス: いいえ
- リスクレベル: 中
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>
/// LANZ Strategy 5.0.
/// Three consecutive bullish candles closing above the EmaPeriod EMA go long; with EnableSell, three bearish candles below it go short,
/// reversing an opposite position. Entries are allowed only between StartHour and EndHour (UTC, the window may cross midnight), at most
/// MaxTrades per day and at least MinDistancePips price steps away from the previous entry. A fixed stop and target in price steps protect
/// each position, and any open position is closed once the window ends.
/// </summary>
public class Lanz50Strategy : Strategy
{
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<int> _maxTrades;
private readonly StrategyParam<decimal> _minDistancePips;
private readonly StrategyParam<decimal> _stopLossPips;
private readonly StrategyParam<decimal> _takeProfitPips;
private readonly StrategyParam<int> _startHour;
private readonly StrategyParam<int> _endHour;
private readonly StrategyParam<bool> _enableBuy;
private readonly StrategyParam<bool> _enableSell;
private readonly StrategyParam<DataType> _candleType;
private decimal? _lastEntryPrice;
private int _dailyTrades;
private DateTime _currentDay;
private int _bullishCount;
private int _bearishCount;
/// <summary>
/// EMA trend filter period.
/// </summary>
public int EmaPeriod
{
get => _emaPeriod.Value;
set => _emaPeriod.Value = value;
}
/// <summary>
/// Maximum entries per day.
/// </summary>
public int MaxTrades
{
get => _maxTrades.Value;
set => _maxTrades.Value = value;
}
/// <summary>
/// Minimum distance from the previous entry in price steps.
/// </summary>
public decimal MinDistancePips
{
get => _minDistancePips.Value;
set => _minDistancePips.Value = value;
}
/// <summary>
/// Stop loss in price steps.
/// </summary>
public decimal StopLossPips
{
get => _stopLossPips.Value;
set => _stopLossPips.Value = value;
}
/// <summary>
/// Take profit in price steps.
/// </summary>
public decimal TakeProfitPips
{
get => _takeProfitPips.Value;
set => _takeProfitPips.Value = value;
}
/// <summary>
/// Hour (UTC) the trading window opens.
/// </summary>
public int StartHour
{
get => _startHour.Value;
set => _startHour.Value = value;
}
/// <summary>
/// Hour (UTC) the trading window closes and positions are closed.
/// </summary>
public int EndHour
{
get => _endHour.Value;
set => _endHour.Value = value;
}
/// <summary>
/// Allow long entries.
/// </summary>
public bool EnableBuy
{
get => _enableBuy.Value;
set => _enableBuy.Value = value;
}
/// <summary>
/// Allow short entries.
/// </summary>
public bool EnableSell
{
get => _enableSell.Value;
set => _enableSell.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initialize <see cref="Lanz50Strategy"/>.
/// </summary>
public Lanz50Strategy()
{
_emaPeriod = Param(nameof(EmaPeriod), 200)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA trend filter period", "Indicators");
_maxTrades = Param(nameof(MaxTrades), 99)
.SetGreaterThanZero()
.SetDisplay("Max Trades", "Maximum entries per day", "Risk");
_minDistancePips = Param(nameof(MinDistancePips), 25m)
.SetNotNegative()
.SetDisplay("Min Distance", "Minimum distance from the previous entry in price steps", "Risk");
_stopLossPips = Param(nameof(StopLossPips), 40m)
.SetNotNegative()
.SetDisplay("Stop Loss", "Stop loss in price steps", "Risk");
_takeProfitPips = Param(nameof(TakeProfitPips), 120m)
.SetNotNegative()
.SetDisplay("Take Profit", "Take profit in price steps", "Risk");
_startHour = Param(nameof(StartHour), 19)
.SetRange(0, 23)
.SetDisplay("Start Hour", "Hour (UTC) the trading window opens", "Time");
_endHour = Param(nameof(EndHour), 15)
.SetRange(0, 23)
.SetDisplay("End Hour", "Hour (UTC) the trading window closes and positions are closed", "Time");
_enableBuy = Param(nameof(EnableBuy), true)
.SetDisplay("Enable Buy", "Allow long entries", "Mode");
_enableSell = Param(nameof(EnableSell), false)
.SetDisplay("Enable Sell", "Allow short entries", "Mode");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
ResetState();
}
private void ResetState()
{
_lastEntryPrice = null;
_dailyTrades = 0;
_currentDay = default;
_bullishCount = 0;
_bearishCount = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
ResetState();
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema, ProcessCandle)
.Start();
var step = Security?.PriceStep ?? 1m;
StartProtection(
TakeProfitPips > 0m ? new Unit(TakeProfitPips * step, UnitTypes.Absolute) : new Unit(),
StopLossPips > 0m ? new Unit(StopLossPips * step, UnitTypes.Absolute) : new Unit(),
useMarketOrders: true);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal emaValue)
{
if (candle.State != CandleStates.Finished)
return;
_bullishCount = candle.ClosePrice > candle.OpenPrice ? _bullishCount + 1 : 0;
_bearishCount = candle.ClosePrice < candle.OpenPrice ? _bearishCount + 1 : 0;
var time = candle.OpenTime;
if (time.Date != _currentDay)
{
_currentDay = time.Date;
_dailyTrades = 0;
}
if (!IsFormedAndOnlineAndAllowTrading())
return;
var hour = time.Hour;
var inWindow = StartHour <= EndHour
? hour >= StartHour && hour < EndHour
: hour >= StartHour || hour < EndHour;
if (!inWindow)
{
if (Position > 0)
SellMarket(Position);
else if (Position < 0)
BuyMarket(-Position);
return;
}
if (_dailyTrades >= MaxTrades)
return;
var close = candle.ClosePrice;
var step = Security.PriceStep ?? 1m;
if (_lastEntryPrice is decimal lastEntry && Math.Abs(close - lastEntry) < MinDistancePips * step)
return;
if (EnableBuy && _bullishCount >= 3 && close > emaValue && Position <= 0)
{
BuyMarket(Volume + Math.Abs(Position));
_dailyTrades++;
_lastEntryPrice = close;
}
else if (EnableSell && _bearishCount >= 3 && close < emaValue && Position >= 0)
{
SellMarket(Volume + Math.Abs(Position));
_dailyTrades++;
_lastEntryPrice = close;
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class lanz_50_strategy(Strategy):
"""
LANZ Strategy 5.0.
Three consecutive bullish candles closing above the EmaPeriod EMA go long; with EnableSell, three bearish candles below it go short,
reversing an opposite position. Entries are allowed only between StartHour and EndHour (UTC, the window may cross midnight), at most
MaxTrades per day and at least MinDistancePips price steps away from the previous entry. A fixed stop and target in price steps protect
each position, and any open position is closed once the window ends.
"""
def __init__(self):
super(lanz_50_strategy, self).__init__()
self._ema_period = self.Param("EmaPeriod", 200).SetGreaterThanZero().SetDisplay("EMA Period", "EMA trend filter period", "Indicators")
self._max_trades = self.Param("MaxTrades", 99).SetGreaterThanZero().SetDisplay("Max Trades", "Maximum entries per day", "Risk")
self._min_distance_pips = self.Param("MinDistancePips", 25.0).SetNotNegative().SetDisplay("Min Distance", "Minimum distance from the previous entry in price steps", "Risk")
self._stop_loss_pips = self.Param("StopLossPips", 40.0).SetNotNegative().SetDisplay("Stop Loss", "Stop loss in price steps", "Risk")
self._take_profit_pips = self.Param("TakeProfitPips", 120.0).SetNotNegative().SetDisplay("Take Profit", "Take profit in price steps", "Risk")
self._start_hour = self.Param("StartHour", 19).SetRange(0, 23).SetDisplay("Start Hour", "Hour (UTC) the trading window opens", "Time")
self._end_hour = self.Param("EndHour", 15).SetRange(0, 23).SetDisplay("End Hour", "Hour (UTC) the trading window closes and positions are closed", "Time")
self._enable_buy = self.Param("EnableBuy", True).SetDisplay("Enable Buy", "Allow long entries", "Mode")
self._enable_sell = self.Param("EnableSell", False).SetDisplay("Enable Sell", "Allow short entries", "Mode")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._reset_state()
@property
def candle_type(self):
return self._candle_type.Value
def _reset_state(self):
self._last_entry_price = None
self._daily_trades = 0
self._current_day = None
self._bullish_count = 0
self._bearish_count = 0
def OnReseted(self):
super(lanz_50_strategy, self).OnReseted()
self._reset_state()
def OnStarted2(self, time):
super(lanz_50_strategy, self).OnStarted2(time)
self._reset_state()
ema = ExponentialMovingAverage()
ema.Length = self._ema_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, self._process_candle).Start()
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
tp = float(self._take_profit_pips.Value)
sl = float(self._stop_loss_pips.Value)
self.StartProtection(
Unit(Decimal(tp * step), UnitTypes.Absolute) if tp > 0 else Unit(),
Unit(Decimal(sl * step), UnitTypes.Absolute) if sl > 0 else Unit(),
useMarketOrders=True)
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def _process_candle(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
open_p = float(candle.OpenPrice)
close = float(candle.ClosePrice)
ema = float(ema_value)
self._bullish_count = self._bullish_count + 1 if close > open_p else 0
self._bearish_count = self._bearish_count + 1 if close < open_p else 0
time = candle.OpenTime
if self._current_day is None or time.Date != self._current_day:
self._current_day = time.Date
self._daily_trades = 0
if not self.IsFormedAndOnlineAndAllowTrading():
return
hour = time.Hour
start = self._start_hour.Value
end = self._end_hour.Value
if start <= end:
in_window = start <= hour < end
else:
in_window = hour >= start or hour < end
if not in_window:
if self.Position > 0:
self.SellMarket(self.Position)
elif self.Position < 0:
self.BuyMarket(-self.Position)
return
if self._daily_trades >= self._max_trades.Value:
return
step = float(self.Security.PriceStep) if self.Security.PriceStep is not None else 1.0
if self._last_entry_price is not None and abs(close - self._last_entry_price) < float(self._min_distance_pips.Value) * step:
return
if self._enable_buy.Value and self._bullish_count >= 3 and close > ema and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
self._daily_trades += 1
self._last_entry_price = close
elif self._enable_sell.Value and self._bearish_count >= 3 and close < ema and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
self._daily_trades += 1
self._last_entry_price = close
def CreateClone(self):
return lanz_50_strategy()