3Commas HA & MA
该策略结合 Heikin Ashi 蜡烛和两条指数均线。当前一根 HA 为阴线、当前为阳线且快线高于慢线时做多;相反条件下做空。价格突破慢线或达到摆动止损时平仓。
细节
- 入场条件:Heikin Ashi 反转并由均线确认。
- 多空方向:双向。
- 出场条件:价格突破慢线或触发止损。
- 止损:摆动高点/低点。
- 默认值:
MaFast= 9MaSlow= 18CandleType= TimeSpan.FromMinutes(1)
- 过滤器:
- 类别: 趋势
- 方向: 双向
- 指标: Heikin Ashi, EMA
- 止损: 是
- 复杂度: 中等
- 时间框架: 日内
- 季节性: 无
- 神经网络: 无
- 背离: 无
- 风险水平: 中等
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Heikin Ashi with moving averages.
/// </summary>
public class ThreeCommasHaMaStrategy : Strategy
{
private readonly StrategyParam<int> _maFast;
private readonly StrategyParam<int> _maSlow;
private readonly StrategyParam<DataType> _candleType;
private decimal _haOpenPrev;
private decimal _haClosePrev;
private decimal _stopPrice;
public int MaFast
{
get => _maFast.Value;
set => _maFast.Value = value;
}
public int MaSlow
{
get => _maSlow.Value;
set => _maSlow.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public ThreeCommasHaMaStrategy()
{
_maFast = Param(nameof(MaFast), 9)
.SetDisplay("MA Fast", "Fast moving average period", "MA");
_maSlow = Param(nameof(MaSlow), 18)
.SetDisplay("MA Slow", "Slow moving average period", "MA");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_haOpenPrev = 0m;
_haClosePrev = 0m;
_stopPrice = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ma1 = new ExponentialMovingAverage { Length = MaFast };
var ma2 = new ExponentialMovingAverage { Length = MaSlow };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ma1, ma2, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ma1);
DrawIndicator(area, ma2);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal ma1, decimal ma2)
{
if (candle.State != CandleStates.Finished)
return;
var haClose = (candle.OpenPrice + candle.HighPrice + candle.LowPrice + candle.ClosePrice) / 4m;
var haOpen = (_haOpenPrev == 0m && _haClosePrev == 0m) ? (candle.OpenPrice + candle.ClosePrice) / 2m : (_haOpenPrev + _haClosePrev) / 2m;
var haBull = haClose > haOpen;
var haBearPrev = _haClosePrev < _haOpenPrev;
var haBullPrev = _haClosePrev > _haOpenPrev;
if (haBearPrev && ma1 > ma2 && haBull && candle.ClosePrice > ma1 && Position <= 0)
{
_stopPrice = candle.LowPrice;
BuyMarket();
}
else if (haBullPrev && ma1 < ma2 && !haBull && candle.ClosePrice < ma1 && Position >= 0)
{
_stopPrice = candle.HighPrice;
SellMarket();
}
if (Position > 0 && candle.ClosePrice < ma2)
SellMarket();
else if (Position < 0 && candle.ClosePrice > ma2)
BuyMarket();
_haOpenPrev = haOpen;
_haClosePrev = haClose;
}
}
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
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class three_commas_ha_ma_strategy(Strategy):
def __init__(self):
super(three_commas_ha_ma_strategy, self).__init__()
self._ma_fast = self.Param("MaFast", 9) \
.SetDisplay("MA Fast", "Fast moving average period", "MA")
self._ma_slow = self.Param("MaSlow", 18) \
.SetDisplay("MA Slow", "Slow moving average period", "MA")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._ha_open_prev = 0.0
self._ha_close_prev = 0.0
self._stop_price = 0.0
@property
def ma_fast(self):
return self._ma_fast.Value
@property
def ma_slow(self):
return self._ma_slow.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(three_commas_ha_ma_strategy, self).OnReseted()
self._ha_open_prev = 0.0
self._ha_close_prev = 0.0
self._stop_price = 0.0
def OnStarted2(self, time):
super(three_commas_ha_ma_strategy, self).OnStarted2(time)
ma1 = ExponentialMovingAverage()
ma1.Length = self.ma_fast
ma2 = ExponentialMovingAverage()
ma2.Length = self.ma_slow
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ma1, ma2, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ma1)
self.DrawIndicator(area, ma2)
self.DrawOwnTrades(area)
def on_process(self, candle, ma1, ma2):
if candle.State != CandleStates.Finished:
return
ha_close = (candle.OpenPrice + candle.HighPrice + candle.LowPrice + candle.ClosePrice) / 4
ha_open = ((candle.OpenPrice + candle.ClosePrice) / 2 if (self._ha_open_prev == 0 and self._ha_close_prev == 0) else (self._ha_open_prev + self._ha_close_prev) / 2)
ha_bull = ha_close > ha_open
ha_bear_prev = self._ha_close_prev < self._ha_open_prev
ha_bull_prev = self._ha_close_prev > self._ha_open_prev
if ha_bear_prev and ma1 > ma2 and ha_bull and candle.ClosePrice > ma1 and self.Position <= 0:
self._stop_price = candle.LowPrice
self.BuyMarket()
elif ha_bull_prev and ma1 < ma2 and not ha_bull and candle.ClosePrice < ma1 and self.Position >= 0:
self._stop_price = candle.HighPrice
self.SellMarket()
if self.Position > 0 and candle.ClosePrice < ma2:
self.SellMarket()
elif self.Position < 0 and candle.ClosePrice > ma2:
self.BuyMarket()
self._ha_open_prev = ha_open
self._ha_close_prev = ha_close
def CreateClone(self):
return three_commas_ha_ma_strategy()