Ver no GitHub

Estratégia de grade semanal RangeEA

Visão geral

RangeEA Weekly Grid Strategy é um sistema de grade de ordem limite convertido do consultor especialista MetaTrader original. O algoritmo identifica a corrente faixa de negociação semanal e a preenche com um número configurável de ordens com limite pendentes. Cada pedido usa stop-loss dinâmico e compensações de take-profit escalonadas em relação à distância entre o preço limite e o preço de mercado atual, respeitando também distâncias mínimas expressas em pontos. Os lucros podem ser bloqueados fechando todo o livro assim que o patrimônio do portfólio crescer porcentagem predefinida.

A implementação aproveita o API de alto nível de API: velas conduzem a lógica de decisão, pedidos pendentes são gerenciados com o métodos auxiliares de estratégia e controles de risco são expostos como parâmetros prontos para otimização.

Lógica de negociação

  1. Assine dois streams de velas:
    • Um período de tempo definido pelo usuário (1 hora por padrão) que orienta a manutenção da rede.
    • Velas semanais que são usadas para estimar a faixa de negociação atual.
  2. Para cada vela semanal concluída, atualize a máxima mais alta e a mínima mais baixa das últimas duas semanas. A diferença deles torna-se a faixa de negociação ativa.
  3. Em cada vela de negociação finalizada:
    • Respeite a janela de negociação configurada (StartTradeHour a EndTradeHour).
    • Opcionalmente, redefina a grade no início de cada dia de negociação.
    • Se não existirem ordens com limite pendentes, distribua as novas ordens uniformemente entre o intervalo mínimo e o intervalo máximo.
    • Depois que duas ordens já tiverem sido executadas, substitua o penúltimo preenchimento por uma nova ordem com o mesmo preço quando a grade diminui para NumberOfOrders - 2 itens.
    • Monitore continuamente o patrimônio da conta e liquide tudo quando o percentual de lucro configurado for atingido.
  4. Quando a janela de negociação fechar e CloseAllAtEndTrade estiver ativado, cancele todas as ordens pendentes e saia das posições existentes.

Parâmetros

Nome Descrição Padrão
CandleType Prazo de negociação usado para acionar a manutenção da rede. Velas de 1 hora
WeeklyCandleType Período usado para derivar os limites do intervalo. velas de 1 semana
StartTradeHour Hora do dia em que novos pedidos podem ser feitos. 0
EndTradeHour Hora do dia em que a negociação é interrompida. 24
CloseAllAtEndTrade Feche todas as ordens e posições fora da janela de negociação. verdade
MaxOpenOrders Número máximo de ordens e posições simultâneas. 5
NumberOfOrders Número de ordens limitadas na grade. 10
OrderVolume Volume utilizado para cada pedido. 0,01
ResetOrdersDaily Reconstrua a grade no início de cada dia de negociação. verdade
StopLossPoints Distância mínima de stop-loss em pontos. 60
TakeProfitPoints Distância mínima de take-profit em pontos. 60
StopLossMultiplier Multiplicador aplicado à distância dinâmica de stop-loss. 3
TakeProfitMultiplier Multiplicador aplicado à distância dinâmica do take-profit. 1
TargetPercentage Porcentagem de ganho patrimonial que desencadeia a liquidação. 8

Gestão de risco

  • A estratégia respeita o limite MaxOpenOrders para manter o número de ordens e posições ativas sob controle.
  • Os níveis de stop-loss e take-profit estão sempre a pelo menos o número configurado de pontos de distância da entrada e podem opcionalmente ser estendido pelos parâmetros do multiplicador.
  • A opção de redefinição diária evita que pedidos obsoletos sejam transferidos para uma nova sessão.
  • Uma meta de patrimônio no nível do portfólio permite que a estratégia obtenha lucros ao nivelar a carteira.

Notas

  • Certifique-se de que o título selecionado forneça velas semanais; caso contrário, a estratégia não poderá calcular o intervalo.
  • Ao usar instrumentos com etapas de preços não padronizadas, ajuste as configurações baseadas em pontos para corresponder ao tamanho do tick subjacente.
  • Otimizar NumberOfOrders, OrderVolume e os multiplicadores stop/take ajuda a adaptar a grade a diferentes níveis de volatilidade.
using System;
using System.Collections.Generic;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Range based grid strategy that detects the trading range from recent price action
/// and places buy/sell limit orders at grid levels within the range.
/// Buys at lower grid levels, sells at upper grid levels.
/// </summary>
public class RangeWeeklyGridStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rangePeriod;
	private readonly StrategyParam<int> _gridLevels;

	private decimal _rangeHigh;
	private decimal _rangeLow;
	private bool _rangeSet;
	private decimal _entryPrice;
	private DateTimeOffset _lastTradeTime;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int RangePeriod
	{
		get => _rangePeriod.Value;
		set => _rangePeriod.Value = value;
	}

	public int GridLevels
	{
		get => _gridLevels.Value;
		set => _gridLevels.Value = value;
	}

	public RangeWeeklyGridStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Primary candle type", "General");

		_rangePeriod = Param(nameof(RangePeriod), 100)
			.SetDisplay("Range Period", "Number of candles to determine range", "Logic");

		_gridLevels = Param(nameof(GridLevels), 5)
			.SetDisplay("Grid Levels", "Number of grid levels within the range", "Logic");
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_rangeHigh = 0;
		_rangeLow = 0;
		_rangeSet = false;
		_entryPrice = 0;
		_lastTradeTime = default;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var highest = new Highest { Length = RangePeriod };
		var lowest = new Lowest { Length = RangePeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(highest, lowest, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal highestValue, decimal lowestValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (highestValue <= 0 || lowestValue <= 0 || highestValue <= lowestValue)
			return;

		_rangeHigh = highestValue;
		_rangeLow = lowestValue;
		_rangeSet = true;

		if (!_rangeSet)
			return;

		var range = _rangeHigh - _rangeLow;
		if (range <= 0)
			return;

		// Cooldown: at least 1 day between trades
		if (_lastTradeTime != default && candle.CloseTime - _lastTradeTime < TimeSpan.FromDays(1))
			return;

		var gridStep = range / (GridLevels + 1);
		var close = candle.ClosePrice;
		var mid = (_rangeHigh + _rangeLow) / 2;

		// Buy when price is in lower portion of range
		if (close <= _rangeLow + gridStep && Position <= 0)
		{
			BuyMarket();
			_entryPrice = close;
			_lastTradeTime = candle.CloseTime;
		}
		// Sell when price is in upper portion of range
		else if (close >= _rangeHigh - gridStep && Position >= 0)
		{
			SellMarket();
			_entryPrice = close;
			_lastTradeTime = candle.CloseTime;
		}
		// Take profit at mid-range
		else if (Position > 0 && close >= mid)
		{
			SellMarket();
			_lastTradeTime = candle.CloseTime;
		}
		else if (Position < 0 && close <= mid)
		{
			BuyMarket();
			_lastTradeTime = candle.CloseTime;
		}
	}
}