Ha MaZi 戦略
Heikin Ashiローソク足、EMAフィルター、ZigZagピボット確認を組み合わせます。EMAの上でZigZagの新たな安値に強気のHeikin Ashiローソク足が形成されたときにロング取引を開きます。EMAの下でZigZagの新たな高値に弱気のローソク足が現れたときにショートポジションを開きます。ポジションは固定ストップロスまたはテイクプロフィットによってクローズされます。
詳細
- エントリー条件: Heikin Ashiの方向とEMAフィルターによるZigZagピボット。
- ロング/ショート: 両方向。
- エグジット条件: ストップロスまたはテイクプロフィット。
- ストップ: 固定ストップと目標。
- デフォルト値:
MaPeriod= 40ZigzagLength= 13StopLoss= 70TakeProfit= 200CandleType= TimeSpan.FromMinutes(1)
- フィルター:
- カテゴリ: トレンド
- 方向: 両方
- インジケーター: Heikin Ashi, EMA, ZigZag
- ストップ: はい
- 複雑さ: 中級
- 時間軸: イントラデイ
- 季節性: いいえ
- ニューラルネットワーク: いいえ
- ダイバージェンス: いいえ
- リスクレベル: 中
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>
/// Heikin Ashi with moving average and ZigZag-style pivot confirmation.
/// </summary>
public class HaMaZiStrategy : Strategy
{
private readonly StrategyParam<int> _maPeriod;
private readonly StrategyParam<int> _zigzagLength;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _stopLossPct;
private readonly StrategyParam<decimal> _takeProfitPct;
private Highest _highest;
private Lowest _lowest;
private decimal _haOpenPrev;
private decimal _haClosePrev;
private decimal _lastZigzag;
private decimal _lastZigzagHigh;
private decimal _lastZigzagLow;
public int MaPeriod { get => _maPeriod.Value; set => _maPeriod.Value = value; }
public int ZigzagLength { get => _zigzagLength.Value; set => _zigzagLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public decimal StopLossPct { get => _stopLossPct.Value; set => _stopLossPct.Value = value; }
public decimal TakeProfitPct { get => _takeProfitPct.Value; set => _takeProfitPct.Value = value; }
public HaMaZiStrategy()
{
_maPeriod = Param(nameof(MaPeriod), 40)
.SetDisplay("MA Period", "EMA period", "General");
_zigzagLength = Param(nameof(ZigzagLength), 13)
.SetDisplay("ZigZag Length", "Lookback for pivot search", "ZigZag");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_stopLossPct = Param(nameof(StopLossPct), 2m)
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk");
_takeProfitPct = Param(nameof(TakeProfitPct), 3m)
.SetDisplay("Take Profit %", "Take profit percentage", "Risk");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_highest = default;
_lowest = default;
_haOpenPrev = 0; _haClosePrev = 0;
_lastZigzag = 0; _lastZigzagHigh = 0; _lastZigzagLow = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema = new ExponentialMovingAverage { Length = MaPeriod };
_highest = new Highest { Length = ZigzagLength };
_lowest = new Lowest { Length = ZigzagLength };
Indicators.Add(_highest);
Indicators.Add(_lowest);
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema, (candle, emaVal) =>
{
if (candle.State != CandleStates.Finished)
return;
var highResult = _highest.Process(candle);
var lowResult = _lowest.Process(candle);
if (!highResult.IsFormed || !lowResult.IsFormed)
return;
var highest = highResult.ToDecimal();
var lowest = lowResult.ToDecimal();
var haClose = (candle.OpenPrice + candle.HighPrice + candle.LowPrice + candle.ClosePrice) / 4m;
var haOpen = (_haOpenPrev == 0 && _haClosePrev == 0)
? (candle.OpenPrice + candle.ClosePrice) / 2m
: (_haOpenPrev + _haClosePrev) / 2m;
var haBull = haClose > haOpen;
var haBear = haClose < haOpen;
if (candle.HighPrice >= highest && _lastZigzag != candle.HighPrice)
{
_lastZigzag = candle.HighPrice;
_lastZigzagHigh = candle.HighPrice;
_lastZigzagLow = 0;
}
else if (candle.LowPrice <= lowest && _lastZigzag != candle.LowPrice)
{
_lastZigzag = candle.LowPrice;
_lastZigzagLow = candle.LowPrice;
_lastZigzagHigh = 0;
}
if (_lastZigzag == _lastZigzagLow && _lastZigzagLow > 0 && haBull && candle.ClosePrice > emaVal && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (_lastZigzag == _lastZigzagHigh && _lastZigzagHigh > 0 && haBear && candle.ClosePrice < emaVal && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_haOpenPrev = haOpen;
_haClosePrev = haClose;
})
.Start();
StartProtection(
takeProfit: new Unit(TakeProfitPct, UnitTypes.Percent),
stopLoss: new Unit(StopLossPct, UnitTypes.Percent),
useMarketOrders: true);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
clr.AddReference("StockSharp.BusinessEntities")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import ExponentialMovingAverage, Highest, Lowest, CandleIndicatorValue
from StockSharp.Algo.Strategies import Strategy
class ha_ma_zi_strategy(Strategy):
def __init__(self):
super(ha_ma_zi_strategy, self).__init__()
self._ma_period = self.Param("MaPeriod", 40) \
.SetDisplay("MA Period", "EMA period", "General")
self._zigzag_length = self.Param("ZigzagLength", 13) \
.SetDisplay("ZigZag Length", "Lookback for pivot search", "ZigZag")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._stop_loss_pct = self.Param("StopLossPct", 2.0) \
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk")
self._take_profit_pct = self.Param("TakeProfitPct", 3.0) \
.SetDisplay("Take Profit %", "Take profit percentage", "Risk")
self._highest = None
self._lowest = None
self._ha_open_prev = 0.0
self._ha_close_prev = 0.0
self._last_zigzag = 0.0
self._last_zigzag_high = 0.0
self._last_zigzag_low = 0.0
@property
def ma_period(self):
return self._ma_period.Value
@property
def zigzag_length(self):
return self._zigzag_length.Value
@property
def candle_type(self):
return self._candle_type.Value
@property
def stop_loss_pct(self):
return self._stop_loss_pct.Value
@property
def take_profit_pct(self):
return self._take_profit_pct.Value
def OnReseted(self):
super(ha_ma_zi_strategy, self).OnReseted()
self._highest = None
self._lowest = None
self._ha_open_prev = 0.0
self._ha_close_prev = 0.0
self._last_zigzag = 0.0
self._last_zigzag_high = 0.0
self._last_zigzag_low = 0.0
def OnStarted2(self, time):
super(ha_ma_zi_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self.ma_period
self._highest = Highest()
self._highest.Length = self.zigzag_length
self._lowest = Lowest()
self._lowest.Length = self.zigzag_length
self.Indicators.Add(self._highest)
self.Indicators.Add(self._lowest)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, self.on_candle).Start()
self.StartProtection(
takeProfit=Unit(self.take_profit_pct, UnitTypes.Percent),
stopLoss=Unit(self.stop_loss_pct, UnitTypes.Percent),
useMarketOrders=True)
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def on_candle(self, candle, ema_val):
if candle.State != CandleStates.Finished:
return
cv_h = CandleIndicatorValue(self._highest, candle)
high_result = self._highest.Process(cv_h)
cv_l = CandleIndicatorValue(self._lowest, candle)
low_result = self._lowest.Process(cv_l)
if not high_result.IsFormed or not low_result.IsFormed:
return
highest = float(high_result)
lowest = float(low_result)
ema_val = float(ema_val)
o = float(candle.OpenPrice)
h = float(candle.HighPrice)
l = float(candle.LowPrice)
c = float(candle.ClosePrice)
ha_close = (o + h + l + c) / 4.0
if self._ha_open_prev == 0 and self._ha_close_prev == 0:
ha_open = (o + c) / 2.0
else:
ha_open = (self._ha_open_prev + self._ha_close_prev) / 2.0
ha_bull = ha_close > ha_open
ha_bear = ha_close < ha_open
if h >= highest and self._last_zigzag != h:
self._last_zigzag = h
self._last_zigzag_high = h
self._last_zigzag_low = 0.0
elif l <= lowest and self._last_zigzag != l:
self._last_zigzag = l
self._last_zigzag_low = l
self._last_zigzag_high = 0.0
if (self._last_zigzag == self._last_zigzag_low and self._last_zigzag_low > 0 and
ha_bull and c > ema_val and self.Position <= 0):
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif (self._last_zigzag == self._last_zigzag_high and self._last_zigzag_high > 0 and
ha_bear and c < ema_val and self.Position >= 0):
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._ha_open_prev = ha_open
self._ha_close_prev = ha_close
def CreateClone(self):
return ha_ma_zi_strategy()