Esta estrategia emula un gráfico clásico de ladrillos Renko y opera ante cambios en la dirección del ladrillo. Fue convertida del script de MetaTrader RenkoLiveChart_v600.
Lógica
La estrategia construye ladrillos Renko usando velas temporales terminadas. Cuando el precio se mueve al menos el tamaño de caja seleccionado desde el precio del último ladrillo, se forma un nuevo ladrillo. Se abre una posición larga en un ladrillo ascendente y una posición corta en un ladrillo descendente.
Parámetros
Candle Type – marco temporal de las velas de entrada utilizadas para la construcción de ladrillos.
Brick Size – paso de precio que define la altura de un ladrillo Renko.
Brick Offset – desplazamiento inicial en ladrillos aplicado al primer ladrillo.
Show Wicks – mostrar mechas en el gráfico al dibujar las velas.
Notas
Las operaciones se ejecutan solo en velas completadas.
La protección de posición se inicia automáticamente al arrancar la estrategia.
Esta implementación se centra en el comportamiento central de Renko e ignora las funciones avanzadas del script original, como el manejo de archivos externos.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Renko live chart emulation strategy.
/// </summary>
public class RenkoLiveChartStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _brickSize;
private decimal _renkoPrice;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public decimal BrickSize { get => _brickSize.Value; set => _brickSize.Value = value; }
public RenkoLiveChartStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Working candle timeframe", "General");
_brickSize = Param(nameof(BrickSize), 500m)
.SetGreaterThanZero()
.SetDisplay("Brick Size", "Renko brick size", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_renkoPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
SubscribeCandles(CandleType).Bind(ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
var size = BrickSize;
if (_renkoPrice == 0m)
{
_renkoPrice = close;
return;
}
var diff = close - _renkoPrice;
if (Math.Abs(diff) < size)
return;
var direction = Math.Sign(diff);
_renkoPrice += direction * size;
if (direction > 0 && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (direction < 0 && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
}
}
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.Strategies import Strategy
class renko_live_chart_strategy(Strategy):
def __init__(self):
super(renko_live_chart_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Working candle timeframe", "General")
self._brick_size = self.Param("BrickSize", 500.0) \
.SetDisplay("Brick Size", "Renko brick size", "General")
self._renko_price = 0.0
@property
def candle_type(self):
return self._candle_type.Value
@property
def brick_size(self):
return self._brick_size.Value
def OnReseted(self):
super(renko_live_chart_strategy, self).OnReseted()
self._renko_price = 0.0
def OnStarted2(self, time):
super(renko_live_chart_strategy, self).OnStarted2(time)
self.SubscribeCandles(self.candle_type).Bind(self.process_candle).Start()
def process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
size = float(self.brick_size)
if self._renko_price == 0.0:
self._renko_price = close
return
diff = close - self._renko_price
if abs(diff) < size:
return
direction = 1 if diff > 0 else -1
self._renko_price += direction * size
if direction > 0 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif direction < 0 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return renko_live_chart_strategy()