Ver no GitHub

Estratégia Stochastic Automatizada

Esta estratégia opera usando o Oscilador Stochastic no período de velas selecionado. Ela aguarda %K e %D entrarem em zonas extremas e então age nos cruzamentos para abrir posições. Take profit e stop loss fixos protegem cada operação, enquanto um trailing stop assegura os lucros.

Lógica

  1. Entrada
    • Comprado:
      • Tanto %K quanto %D estavam abaixo de OverSold há duas velas.
      • %D estava acima de %K há duas velas e abaixo de %K há uma vela.
      • %D está subindo.
    • Vendido:
      • Tanto %K quanto %D estavam acima de OverBought há duas velas.
      • %D estava abaixo de %K há duas velas e acima de %K há uma vela.
      • %D está caindo.
  2. Saída
    • A posição é fechada quando o Stochastic sai da zona extrema ou %D vira na direção oposta.
    • Um trailing stop sai se o preço recuar em TrailingStop.
    • TakeProfit e StopLoss globais são aplicados a cada operação.

Parâmetros

Nome Descrição
CandleType Período para os cálculos do Stochastic.
KPeriod Período de retrospecto para a linha %K.
DPeriod Período de suavização para a linha %D.
Slowing Suavização adicional para %K.
OverBought Limiar superior indicando mercado sobrecomprado.
OverSold Limiar inferior indicando mercado sobrevendido.
TakeProfit Distância da entrada para o alvo de lucro (unidades de preço).
StopLoss Distância da entrada para o stop de proteção (unidades de preço).
TrailingStop Distância de rastreamento quando a operação se move no lucro (unidades de preço).

Indicadores

  • StochasticOscillator

Notas

  • Os comentários no código estão em inglês.
  • A versão em Python é intencionalmente omitida.
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>
/// Stochastic oscillator based strategy.
/// Buys on K/D crossover in oversold, sells on crossover in overbought.
/// </summary>
public class StochasticAutomatedStrategy : Strategy
{
	private readonly StrategyParam<int> _kPeriod;
	private readonly StrategyParam<int> _dPeriod;
	private readonly StrategyParam<decimal> _overBought;
	private readonly StrategyParam<decimal> _overSold;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _prevK;
	private decimal? _prevD;

	public int KPeriod { get => _kPeriod.Value; set => _kPeriod.Value = value; }
	public int DPeriod { get => _dPeriod.Value; set => _dPeriod.Value = value; }
	public decimal OverBought { get => _overBought.Value; set => _overBought.Value = value; }
	public decimal OverSold { get => _overSold.Value; set => _overSold.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public StochasticAutomatedStrategy()
	{
		_kPeriod = Param(nameof(KPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("%K Period", "Stochastic %K period", "Stochastic");

		_dPeriod = Param(nameof(DPeriod), 3)
			.SetGreaterThanZero()
			.SetDisplay("%D Period", "Stochastic %D period", "Stochastic");

		_overBought = Param(nameof(OverBought), 80m)
			.SetDisplay("Overbought", "Overbought threshold", "Stochastic");

		_overSold = Param(nameof(OverSold), 20m)
			.SetDisplay("Oversold", "Oversold threshold", "Stochastic");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Time frame", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevK = _prevD = null;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var stochastic = new StochasticOscillator();
		stochastic.K.Length = KPeriod;
		stochastic.D.Length = DPeriod;

		var subscription = SubscribeCandles(CandleType);
		subscription.BindEx(stochastic, ProcessCandle).Start();

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

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue stochValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var stoch = (IStochasticOscillatorValue)stochValue;
		if (stoch.K is not decimal k || stoch.D is not decimal d)
			return;

		if (_prevK is decimal pk && _prevD is decimal pd)
		{
			// Buy: K crosses above D in oversold zone
			if (pk <= pd && k > d && pd < OverSold && Position <= 0)
				BuyMarket();

			// Sell: K crosses below D in overbought zone
			if (pk >= pd && k < d && pd > OverBought && Position >= 0)
				SellMarket();
		}

		_prevK = k;
		_prevD = d;
	}
}