Estrategia Forex de Martillo y Hombre Colgado
Esta estrategia opera los patrones clásicos de reversión de velas japonesas: el martillo alcista y el hombre colgado bajista. Entra largo después de un martillo y corto después de un hombre colgado, manteniendo la posición durante un número fijo de barras.
La posición se cierra una vez que expira el período de retención o se activan los stops de protección.
Detalles
- Criterios de entrada: Martillo para largo, hombre colgado para corto.
- Largo/Corto: Ambos.
- Criterios de salida: Período de retención o stop-loss/take-profit.
- Stops: Sí.
- Valores predeterminados:
CandleType= TimeSpan.FromMinutes(5)BodyLengthMultiplier= 5ShadowRatio= 1HoldPeriods= 26
- Filtros:
- Categoría: Patrón
- Dirección: Ambos
- Indicadores: Candlestick
- Stops: Sí
- Complejidad: Básico
- Marco temporal: Intradía
- Estacionalidad: No
- Redes neuronales: No
- Divergencia: No
- Nivel de riesgo: Medio
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Forex Hammer and Hanging Man strategy.
/// A candle qualifies when its range exceeds BodyLengthMultiplier times its body and its lower shadow is longer than ShadowRatio
/// times its upper shadow. A bullish one is a hammer and goes long, a bearish one is a hanging man and goes short, reversing an
/// opposite position. A position is closed after HoldPeriods candles.
/// </summary>
public class ForexHammerAndHangingManStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _bodyLengthMultiplier;
private readonly StrategyParam<decimal> _shadowRatio;
private readonly StrategyParam<int> _holdPeriods;
private int _barsInPosition;
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// How many bodies the candle range must exceed.
/// </summary>
public decimal BodyLengthMultiplier
{
get => _bodyLengthMultiplier.Value;
set => _bodyLengthMultiplier.Value = value;
}
/// <summary>
/// How many upper shadows the lower shadow must exceed.
/// </summary>
public decimal ShadowRatio
{
get => _shadowRatio.Value;
set => _shadowRatio.Value = value;
}
/// <summary>
/// Candles a position is held.
/// </summary>
public int HoldPeriods
{
get => _holdPeriods.Value;
set => _holdPeriods.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public ForexHammerAndHangingManStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_bodyLengthMultiplier = Param(nameof(BodyLengthMultiplier), 5m)
.SetNotNegative()
.SetDisplay("Body Multiplier", "How many bodies the candle range must exceed", "Pattern");
_shadowRatio = Param(nameof(ShadowRatio), 1m)
.SetNotNegative()
.SetDisplay("Shadow Ratio", "How many upper shadows the lower shadow must exceed", "Pattern");
_holdPeriods = Param(nameof(HoldPeriods), 26)
.SetGreaterThanZero()
.SetDisplay("Hold Periods", "Candles a position is held", "Trading");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_barsInPosition = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_barsInPosition = 0;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
var range = candle.HighPrice - candle.LowPrice;
var lowerShadow = Math.Min(candle.OpenPrice, candle.ClosePrice) - candle.LowPrice;
var upperShadow = candle.HighPrice - Math.Max(candle.OpenPrice, candle.ClosePrice);
var shape = range > 0 && range > BodyLengthMultiplier * body && lowerShadow > ShadowRatio * upperShadow;
var hammer = shape && candle.ClosePrice > candle.OpenPrice;
var hangingMan = shape && candle.ClosePrice < candle.OpenPrice;
if (hammer && Position <= 0)
{
BuyMarket(Volume + Math.Abs(Position));
_barsInPosition = 0;
return;
}
if (hangingMan && Position >= 0)
{
SellMarket(Volume + Math.Abs(Position));
_barsInPosition = 0;
return;
}
if (Position == 0)
return;
_barsInPosition++;
if (_barsInPosition < HoldPeriods)
return;
if (Position > 0)
SellMarket(Position);
else
BuyMarket(-Position);
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Strategies import Strategy
class forex_hammer_and_hanging_man_strategy(Strategy):
"""
Forex Hammer and Hanging Man strategy.
A candle qualifies when its range exceeds BodyLengthMultiplier times its body and its lower shadow is longer than ShadowRatio
times its upper shadow. A bullish one is a hammer and goes long, a bearish one is a hanging man and goes short, reversing an
opposite position. A position is closed after HoldPeriods candles.
"""
def __init__(self):
super(forex_hammer_and_hanging_man_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._body_length_multiplier = self.Param("BodyLengthMultiplier", 5.0).SetNotNegative().SetDisplay("Body Multiplier", "How many bodies the candle range must exceed", "Pattern")
self._shadow_ratio = self.Param("ShadowRatio", 1.0).SetNotNegative().SetDisplay("Shadow Ratio", "How many upper shadows the lower shadow must exceed", "Pattern")
self._hold_periods = self.Param("HoldPeriods", 26).SetGreaterThanZero().SetDisplay("Hold Periods", "Candles a position is held", "Trading")
self._bars_in_position = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(forex_hammer_and_hanging_man_strategy, self).OnReseted()
self._bars_in_position = 0
def OnStarted2(self, time):
super(forex_hammer_and_hanging_man_strategy, self).OnStarted2(time)
self._bars_in_position = 0
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.DrawOwnTrades(area)
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
open_price = float(candle.OpenPrice)
close = float(candle.ClosePrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
body = abs(close - open_price)
rng = high - low
lower_shadow = min(open_price, close) - low
upper_shadow = high - max(open_price, close)
shape = rng > 0 and rng > float(self._body_length_multiplier.Value) * body and lower_shadow > float(self._shadow_ratio.Value) * upper_shadow
hammer = shape and close > open_price
hanging_man = shape and close < open_price
if hammer and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
self._bars_in_position = 0
return
if hanging_man and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
self._bars_in_position = 0
return
if self.Position == 0:
return
self._bars_in_position += 1
if self._bars_in_position < self._hold_periods.Value:
return
if self.Position > 0:
self.SellMarket(self.Position)
else:
self.BuyMarket(-self.Position)
def CreateClone(self):
return forex_hammer_and_hanging_man_strategy()