Esta estratégia traduz o consultor especialista MQL "Marneni Money Tree" para o StockSharp.
Baseia-se em uma média móvel simples (SMA) de 40 períodos e dois valores deslocados para detectar a direção da tendência.
Quando a SMA deslocada por quatro barras está entre a SMA atual e o valor de trinta barras atrás,
uma ordem de mercado é enviada na direção detectada;
oito ordens limitadas adicionais são colocadas em distâncias crescentes, definidas por Order2Pips até Order9Pips.
Configurações compradas colocam limites de compra abaixo do preço atual. Configurações vendidas colocam limites de venda acima do preço.
As posições são fechadas e as ordens restantes canceladas quando a relação da SMA se inverte.
Parâmetros
Order2Pips–Order9Pips — distância em pips para as ordens limitadas de 2 a 9.
CandleType — período utilizado para os cálculos.
O volume base de negociação é fixado em 2 e pode ser ajustado alterando a propriedade Volume antes de iniciar a estratégia.
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>
/// SMA momentum strategy with shifted MA comparison.
/// Buys when current SMA is above shifted SMA, sells when below.
/// </summary>
public class MarneniMoneyTreeStrategy : Strategy
{
private readonly StrategyParam<int> _smaPeriod;
private readonly StrategyParam<int> _atrPeriod;
private readonly StrategyParam<DataType> _candleType;
private readonly decimal[] _smaBuffer = new decimal[31];
private int _bufferIndex;
private int _valuesCount;
public int SmaPeriod { get => _smaPeriod.Value; set => _smaPeriod.Value = value; }
public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MarneniMoneyTreeStrategy()
{
_smaPeriod = Param(nameof(SmaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("SMA Period", "SMA length", "Indicators");
_atrPeriod = Param(nameof(AtrPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("ATR Period", "ATR for stops", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
Array.Clear(_smaBuffer, 0, _smaBuffer.Length);
_bufferIndex = 0;
_valuesCount = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sma = new SimpleMovingAverage { Length = SmaPeriod };
var atr = new StandardDeviation { Length = AtrPeriod };
SubscribeCandles(CandleType).Bind(sma, atr, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal smaValue, decimal atrValue)
{
if (candle.State != CandleStates.Finished) return;
_smaBuffer[_bufferIndex] = smaValue;
_bufferIndex = (_bufferIndex + 1) % _smaBuffer.Length;
if (_valuesCount < _smaBuffer.Length) _valuesCount++;
if (_valuesCount < _smaBuffer.Length) return;
if (atrValue <= 0) return;
var idxCurrent = (_bufferIndex - 1 + _smaBuffer.Length) % _smaBuffer.Length;
var idxShift4 = (_bufferIndex - 5 + _smaBuffer.Length) % _smaBuffer.Length;
var idxShift30 = _bufferIndex % _smaBuffer.Length;
var ma = _smaBuffer[idxShift4];
var ma1 = _smaBuffer[idxCurrent];
var ma2 = _smaBuffer[idxShift30];
if (Position == 0)
{
if (ma > ma1 && ma < ma2)
SellMarket();
else if (ma < ma1 && ma > ma2)
BuyMarket();
}
else if (Position > 0 && ma > ma1)
SellMarket();
else if (Position < 0 && ma < ma1)
BuyMarket();
}
}
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 SimpleMovingAverage, StandardDeviation
from StockSharp.Algo.Strategies import Strategy
class marneni_money_tree_strategy(Strategy):
def __init__(self):
super(marneni_money_tree_strategy, self).__init__()
self._sma_period = self.Param("SmaPeriod", 20) \
.SetDisplay("SMA Period", "SMA length", "Indicators")
self._atr_period = self.Param("AtrPeriod", 14) \
.SetDisplay("ATR Period", "ATR for stops", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._sma_buffer = [0.0] * 31
self._buffer_index = 0
self._values_count = 0
@property
def sma_period(self):
return self._sma_period.Value
@property
def atr_period(self):
return self._atr_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(marneni_money_tree_strategy, self).OnReseted()
self._sma_buffer = [0.0] * 31
self._buffer_index = 0
self._values_count = 0
def OnStarted2(self, time):
super(marneni_money_tree_strategy, self).OnStarted2(time)
sma = SimpleMovingAverage()
sma.Length = self.sma_period
atr = StandardDeviation()
atr.Length = self.atr_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma, atr, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, sma_value, atr_value):
if candle.State != CandleStates.Finished:
return
buf_len = len(self._sma_buffer)
self._sma_buffer[self._buffer_index] = sma_value
self._buffer_index = (self._buffer_index + 1) % buf_len
if self._values_count < buf_len:
self._values_count += 1
if self._values_count < buf_len:
return
if atr_value <= 0:
return
idx_current = (self._buffer_index - 1 + buf_len) % buf_len
idx_shift4 = (self._buffer_index - 5 + buf_len) % buf_len
idx_shift30 = self._buffer_index % buf_len
ma = self._sma_buffer[idx_shift4]
ma1 = self._sma_buffer[idx_current]
ma2 = self._sma_buffer[idx_shift30]
if self.Position == 0:
if ma > ma1 and ma < ma2:
self.SellMarket()
elif ma < ma1 and ma > ma2:
self.BuyMarket()
elif self.Position > 0 and ma > ma1:
self.SellMarket()
elif self.Position < 0 and ma < ma1:
self.BuyMarket()
def CreateClone(self):
return marneni_money_tree_strategy()