Стратегия Smart Money Yuri Garcia
Стратегия Smart Money ищет реакции цены внутри зон высокого объема и четырехчасовых уровней поддержки/сопротивления. Входы подтверждаются кумулятивной дельтой и возвратами свечей.
Тесты показывают среднегодовую доходность около 42%. Лучше всего работает на BTC и основных индексах.
Система использует ATR для расчета стоп-лосса и тейк-профита с настраиваемым соотношением риск/прибыль. Сделки могут быть только в одну сторону или в обе, и открываются лишь при выполнении условий зоны, возврата и подтверждения дельтой.
Детали
- Условия входа:
- Покупка: Цена в зоне, бычий возврат свечи и растущая кумулятивная дельта.
- Продажа: Цена в зоне, медвежий возврат и падающая дельта.
- Длинные/короткие: Настраивается (оба, только лонг или только шорт).
- Условия выхода:
- Стоп-лосс или тейк-профит по ATR.
- Стопы: Да, основаны на ATR.
- Фильтры:
- Зоны HTF, подтверждение кумулятивной дельтой и возврат свечи.
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>
/// Smart money strategy using HTF zones, cumulative delta and wick pullback.
/// </summary>
public class YuriGarciaSmartMoneyStrategy : Strategy
{
private readonly StrategyParam<int> _zoneLookback;
private readonly StrategyParam<decimal> _zoneBuffer;
private readonly StrategyParam<decimal> _stopPercent;
private readonly StrategyParam<decimal> _riskReward;
private readonly StrategyParam<DataType> _candleType;
private decimal _entryPrice;
private decimal _prevHigh;
private decimal _prevLow;
private bool _prevBull;
private bool _prevBear;
private bool _isReady;
public int ZoneLookback { get => _zoneLookback.Value; set => _zoneLookback.Value = value; }
public decimal ZoneBuffer { get => _zoneBuffer.Value; set => _zoneBuffer.Value = value; }
public decimal StopPercent { get => _stopPercent.Value; set => _stopPercent.Value = value; }
public decimal RiskReward { get => _riskReward.Value; set => _riskReward.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public YuriGarciaSmartMoneyStrategy()
{
_zoneLookback = Param(nameof(ZoneLookback), 20)
.SetGreaterThanZero()
.SetDisplay("Zone Lookback", "Lookback for high/low zone", "General");
_zoneBuffer = Param(nameof(ZoneBuffer), 0.002m)
.SetDisplay("Zone Buffer", "Buffer percent", "General");
_stopPercent = Param(nameof(StopPercent), 3m)
.SetGreaterThanZero()
.SetDisplay("Stop %", "Stop loss percentage", "Risk");
_riskReward = Param(nameof(RiskReward), 2m)
.SetGreaterThanZero()
.SetDisplay("RRR", "Risk reward ratio", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0;
_prevHigh = 0;
_prevLow = 0;
_prevBull = false;
_prevBear = false;
_isReady = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var highest = new Highest { Length = ZoneLookback };
var lowest = new Lowest { Length = ZoneLookback };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(highest, lowest, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, highest);
DrawIndicator(area, lowest);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal highZone, decimal lowZone)
{
if (candle.State != CandleStates.Finished)
return;
if (!_isReady)
{
_prevHigh = highZone;
_prevLow = lowZone;
_isReady = true;
return;
}
var top = _prevHigh * (1 + ZoneBuffer);
var bottom = _prevLow * (1 - ZoneBuffer);
var isBull = candle.ClosePrice > candle.OpenPrice;
var isBear = candle.ClosePrice < candle.OpenPrice;
var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
var pullLong = isBull && _prevBear && candle.LowPrice <= candle.OpenPrice - body / 2m;
var pullShort = isBear && _prevBull && candle.HighPrice >= candle.ClosePrice + body / 2m;
_prevBull = isBull;
_prevBear = isBear;
var nearSupport = candle.ClosePrice <= bottom * 1.02m;
var nearResistance = candle.ClosePrice >= top * 0.98m;
if (nearSupport && pullLong && Position <= 0)
{
BuyMarket();
_entryPrice = candle.ClosePrice;
}
else if (nearResistance && pullShort && Position >= 0)
{
SellMarket();
_entryPrice = candle.ClosePrice;
}
if (Position > 0 && _entryPrice > 0)
{
var stop = _entryPrice * (1 - StopPercent / 100m);
var target = _entryPrice * (1 + StopPercent * RiskReward / 100m);
if (candle.ClosePrice <= stop || candle.ClosePrice >= target)
SellMarket();
}
else if (Position < 0 && _entryPrice > 0)
{
var stop = _entryPrice * (1 + StopPercent / 100m);
var target = _entryPrice * (1 - StopPercent * RiskReward / 100m);
if (candle.ClosePrice >= stop || candle.ClosePrice <= target)
BuyMarket();
}
_prevHigh = highZone;
_prevLow = lowZone;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class yuri_garcia_smart_money_strategy(Strategy):
def __init__(self):
super(yuri_garcia_smart_money_strategy, self).__init__()
self._zone_lookback = self.Param("ZoneLookback", 20) \
.SetDisplay("Zone Lookback", "Lookback for high/low zone", "General")
self._zone_buffer = self.Param("ZoneBuffer", 0.002) \
.SetDisplay("Zone Buffer", "Buffer percent", "General")
self._stop_percent = self.Param("StopPercent", 3.0) \
.SetDisplay("Stop %", "Stop loss percentage", "Risk")
self._risk_reward = self.Param("RiskReward", 2.0) \
.SetDisplay("RRR", "Risk reward ratio", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._entry_price = 0.0
self._prev_high = 0.0
self._prev_low = 0.0
self._prev_bull = False
self._prev_bear = False
self._is_ready = False
@property
def zone_lookback(self):
return self._zone_lookback.Value
@property
def zone_buffer(self):
return self._zone_buffer.Value
@property
def stop_percent(self):
return self._stop_percent.Value
@property
def risk_reward(self):
return self._risk_reward.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(yuri_garcia_smart_money_strategy, self).OnReseted()
self._entry_price = 0.0
self._prev_high = 0.0
self._prev_low = 0.0
self._prev_bull = False
self._prev_bear = False
self._is_ready = False
def OnStarted2(self, time):
super(yuri_garcia_smart_money_strategy, self).OnStarted2(time)
highest = Highest()
highest.Length = self.zone_lookback
lowest = Lowest()
lowest.Length = self.zone_lookback
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(highest, lowest, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, highest)
self.DrawIndicator(area, lowest)
self.DrawOwnTrades(area)
def on_process(self, candle, high_zone, low_zone):
if candle.State != CandleStates.Finished:
return
if not self._is_ready:
self._prev_high = high_zone
self._prev_low = low_zone
self._is_ready = True
return
top = self._prev_high * (1 + self.zone_buffer)
bottom = self._prev_low * (1 - self.zone_buffer)
is_bull = candle.ClosePrice > candle.OpenPrice
is_bear = candle.ClosePrice < candle.OpenPrice
body = abs(candle.ClosePrice - candle.OpenPrice)
pull_long = is_bull and self._prev_bear and candle.LowPrice <= candle.OpenPrice - body / 2
pull_short = is_bear and self._prev_bull and candle.HighPrice >= candle.ClosePrice + body / 2
self._prev_bull = is_bull
self._prev_bear = is_bear
near_support = candle.ClosePrice <= bottom * 1.02
near_resistance = candle.ClosePrice >= top * 0.98
if near_support and pull_long and self.Position <= 0:
self.BuyMarket()
self._entry_price = candle.ClosePrice
elif near_resistance and pull_short and self.Position >= 0:
self.SellMarket()
self._entry_price = candle.ClosePrice
if self.Position > 0 and self._entry_price > 0:
stop = self._entry_price * (1 - self.stop_percent / 100)
target = self._entry_price * (1 + self.stop_percent * self.risk_reward / 100)
if candle.ClosePrice <= stop or candle.ClosePrice >= target:
self.SellMarket()
elif self.Position < 0 and self._entry_price > 0:
stop = self._entry_price * (1 + self.stop_percent / 100)
target = self._entry_price * (1 - self.stop_percent * self.risk_reward / 100)
if candle.ClosePrice >= stop or candle.ClosePrice <= target:
self.BuyMarket()
self._prev_high = high_zone
self._prev_low = low_zone
def CreateClone(self):
return yuri_garcia_smart_money_strategy()