Estrategia de Máximos y Mínimos
Estrategia que opera en los puntos medios de velas en relación con el rango de máximos y mínimos.
Compra cuando el punto medio de la vela actual está por debajo del promedio de los valores máximo y mínimo y la distancia normalizada está por debajo de LowThreshold. Cierra la posición larga cuando el punto medio sube por encima del promedio y la distancia normalizada está por encima de HighThreshold.
Detalles
- Criterios de entrada: Punto medio por debajo del promedio y distancia normalizada por debajo de LowThreshold.
- Largo/Corto: Solo largo.
- Criterios de salida: Punto medio por encima del promedio y distancia normalizada por encima de HighThreshold.
- Stops: No.
- Valores predeterminados:
Range= 100LowThreshold= 15mHighThreshold= 85mCandleType= TimeSpan.FromMinutes(240)
- Filtros:
- Categoría: Rango
- Dirección: Largo
- Indicadores: Highest, Lowest
- Stops: No
- Complejidad: Básico
- Marco temporal: Intradía (240m)
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
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>
/// Highs Lows strategy.
/// Tracks the highest high and lowest low of the last Range candles. The candle midpoint is compared with the average of
/// these extremes, and their distance is normalized by half the range (0 at the average, 100 at an extreme). A long opens when the midpoint is
/// below the average and the normalized distance is below LowThreshold, and closes when the midpoint is above the average
/// and the normalized distance is above HighThreshold.
/// </summary>
public class HighsLowsStrategy : Strategy
{
private readonly StrategyParam<int> _range;
private readonly StrategyParam<decimal> _lowThreshold;
private readonly StrategyParam<decimal> _highThreshold;
private readonly StrategyParam<DataType> _candleType;
private Highest _highest;
private Lowest _lowest;
/// <summary>
/// Number of candles for the highest and lowest values.
/// </summary>
public int Range
{
get => _range.Value;
set => _range.Value = value;
}
/// <summary>
/// Normalized distance below which a long opens.
/// </summary>
public decimal LowThreshold
{
get => _lowThreshold.Value;
set => _lowThreshold.Value = value;
}
/// <summary>
/// Normalized distance above which the long closes.
/// </summary>
public decimal HighThreshold
{
get => _highThreshold.Value;
set => _highThreshold.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public HighsLowsStrategy()
{
_range = Param(nameof(Range), 100)
.SetGreaterThanZero()
.SetDisplay("Range", "Number of candles for highest and lowest values", "Indicators");
_lowThreshold = Param(nameof(LowThreshold), 15m)
.SetDisplay("Low Threshold", "Normalized distance below which a long opens", "Signals");
_highThreshold = Param(nameof(HighThreshold), 85m)
.SetDisplay("High Threshold", "Normalized distance above which the long closes", "Signals");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(240).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_highest = null;
_lowest = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_highest = new Highest { Length = Range };
_lowest = new Lowest { Length = Range };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _highest);
DrawIndicator(area, _lowest);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var highest = _highest.Process(candle.HighPrice, candle.OpenTime, true).ToDecimal();
var lowest = _lowest.Process(candle.LowPrice, candle.OpenTime, true).ToDecimal();
if (!_highest.IsFormed || !_lowest.IsFormed)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var width = highest - lowest;
if (width <= 0)
return;
var midpoint = (candle.HighPrice + candle.LowPrice) / 2;
var average = (highest + lowest) / 2;
// Distance from the average as a percentage of the half range: 0 at the average, 100 at an extreme.
var distance = Math.Abs(midpoint - average) / (width / 2) * 100m;
if (Position <= 0 && midpoint < average && distance < LowThreshold)
BuyMarket(Volume + Math.Abs(Position));
else if (Position > 0 && midpoint > average && distance > HighThreshold)
SellMarket(Position);
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class highs_lows_strategy(Strategy):
"""
Highs Lows strategy.
Tracks the highest high and lowest low of the last Range candles. The candle midpoint is compared with the average of
these extremes, and their distance is normalized by half the range (0 at the average, 100 at an extreme). A long opens when the midpoint is
below the average and the normalized distance is below LowThreshold, and closes when the midpoint is above the average
and the normalized distance is above HighThreshold.
"""
def __init__(self):
super(highs_lows_strategy, self).__init__()
self._range = self.Param("Range", 100).SetGreaterThanZero().SetDisplay("Range", "Number of candles for highest and lowest values", "Indicators")
self._low_threshold = self.Param("LowThreshold", 15.0).SetDisplay("Low Threshold", "Normalized distance below which a long opens", "Signals")
self._high_threshold = self.Param("HighThreshold", 85.0).SetDisplay("High Threshold", "Normalized distance above which the long closes", "Signals")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(240))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._highest = None
self._lowest = None
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(highs_lows_strategy, self).OnReseted()
self._highest = None
self._lowest = None
def OnStarted2(self, time):
super(highs_lows_strategy, self).OnStarted2(time)
self._highest = Highest()
self._highest.Length = self._range.Value
self._lowest = Lowest()
self._lowest.Length = self._range.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, self._highest)
self.DrawIndicator(area, self._lowest)
self.DrawOwnTrades(area)
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
highest = process_float(self._highest, candle.HighPrice, candle.OpenTime, True).GetValue[Decimal](None)
lowest = process_float(self._lowest, candle.LowPrice, candle.OpenTime, True).GetValue[Decimal](None)
if not self._highest.IsFormed or not self._lowest.IsFormed:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
width = highest - lowest
if width <= 0:
return
midpoint = (candle.HighPrice + candle.LowPrice) / Decimal(2)
average = (highest + lowest) / Decimal(2)
# Distance from the average as a percentage of the half range: 0 at the average, 100 at an extreme.
distance = abs(midpoint - average) / (width / Decimal(2)) * Decimal(100)
if self.Position <= 0 and midpoint < average and distance < Decimal(self._low_threshold.Value):
self.BuyMarket(self.Volume + abs(self.Position))
elif self.Position > 0 and midpoint > average and distance > Decimal(self._high_threshold.Value):
self.SellMarket(self.Position)
def CreateClone(self):
return highs_lows_strategy()