Стратегия Forex Profit
Перевод советника MetaTrader «Forex Profit». Стратегия ожидает совпадения трёх экспоненциальных средних и подтверждения от Parabolic SAR, после чего входит в рынок по цене закрытия сформированной свечи. Управление рисками включает несимметричные уровни стоп-лосса и тейк-профита, трейлинг-стоп и дополнительную фиксацию прибыли по развороту EMA.
Детали
- Условия входа:
- Лонг:
EMA10вышеEMA25иEMA50, значениеEMA10на предыдущей свече не вышеEMA50, Parabolic SAR ниже прошлого закрытия. - Шорт:
EMA10нижеEMA25иEMA50, значениеEMA10на предыдущей свече не нижеEMA50, Parabolic SAR выше прошлого закрытия. - Сигналы проверяются только один раз для каждой завершённой свечи.
- Лонг:
- Условия выхода:
- Закрыть лонг, когда
EMA10опускается ниже своего прошлого значения и текущая прибыль превышаетProfitThreshold. - Закрыть шорт, когда
EMA10поднимается выше прошлого значения и текущая прибыль превышаетProfitThreshold. - Стоп-лосс и тейк-профит задаются при открытии сделки (разные дистанции для лонга и шорта).
- Трейлинг-стоп активируется после движения цены на
TrailingStopPointsот входа и сдвигается шагамиTrailingStepPoints.
- Закрыть лонг, когда
- Стопы: Да — фиксированный стоп-лосс, фиксированный тейк-профит и трейлинг.
- Значения по умолчанию:
FastEmaLength= 10MediumEmaLength= 25SlowEmaLength= 50TakeProfitBuyPoints= 55TakeProfitSellPoints= 65StopLossBuyPoints= 60StopLossSellPoints= 85TrailingStopPoints= 74TrailingStepPoints= 5ProfitThreshold= 10SarAcceleration= 0.02SarMaxAcceleration= 0.2Volume= 1CandleType= таймфрейм 1 час
- Дополнительные замечания:
- Расстояния стопов и целей задаются в шагах цены инструмента и автоматически переводятся с учётом тика.
- Закрытия по прибыли рассчитываются от общего результата позиции (с учётом объёма) в валюте счёта через преобразование тиковой стоимости.
- Трейлинг поддерживает стоп вслед за ценой без перескоков меньше указанного шага.
- Фильтры:
- Категория: Trend following
- Направление: Лонг и Шорт
- Индикаторы: EMA, Parabolic SAR
- Стопы: Да (фиксированные + трейлинг)
- Сложность: Средняя
- Таймфрейм: Настраиваемый (по умолчанию 1 час)
- Сезонность: Нет
- Нейросети: Нет
- Дивергенция: Нет
- Риск: Средний
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>
/// Trend-following strategy translated from the "Forex Profit" MQL expert.
/// Combines EMA alignment with Parabolic SAR confirmation and dynamic exits.
/// </summary>
public class ForexProfitStrategy : Strategy
{
private readonly StrategyParam<int> _fastEmaLength;
private readonly StrategyParam<int> _mediumEmaLength;
private readonly StrategyParam<int> _slowEmaLength;
private readonly StrategyParam<decimal> _takeProfitBuyPoints;
private readonly StrategyParam<decimal> _takeProfitSellPoints;
private readonly StrategyParam<decimal> _stopLossBuyPoints;
private readonly StrategyParam<decimal> _stopLossSellPoints;
private readonly StrategyParam<decimal> _trailingStopPoints;
private readonly StrategyParam<decimal> _trailingStepPoints;
private readonly StrategyParam<decimal> _profitThreshold;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _sarAcceleration;
private readonly StrategyParam<decimal> _sarMaxAcceleration;
private ExponentialMovingAverage _emaFast;
private ExponentialMovingAverage _emaMedium;
private ExponentialMovingAverage _emaSlow;
private ParabolicSar _sar;
private decimal? _ema10Prev;
private decimal? _ema10PrevPrev;
private decimal? _entryPrice;
private decimal? _stopPrice;
private decimal? _takeProfitPrice;
/// <summary>
/// Fast EMA length.
/// </summary>
public int FastEmaLength
{
get => _fastEmaLength.Value;
set => _fastEmaLength.Value = value;
}
/// <summary>
/// Medium EMA length.
/// </summary>
public int MediumEmaLength
{
get => _mediumEmaLength.Value;
set => _mediumEmaLength.Value = value;
}
/// <summary>
/// Slow EMA length.
/// </summary>
public int SlowEmaLength
{
get => _slowEmaLength.Value;
set => _slowEmaLength.Value = value;
}
/// <summary>
/// Take profit distance for long positions in price steps.
/// </summary>
public decimal TakeProfitBuyPoints
{
get => _takeProfitBuyPoints.Value;
set => _takeProfitBuyPoints.Value = value;
}
/// <summary>
/// Take profit distance for short positions in price steps.
/// </summary>
public decimal TakeProfitSellPoints
{
get => _takeProfitSellPoints.Value;
set => _takeProfitSellPoints.Value = value;
}
/// <summary>
/// Stop loss distance for long positions in price steps.
/// </summary>
public decimal StopLossBuyPoints
{
get => _stopLossBuyPoints.Value;
set => _stopLossBuyPoints.Value = value;
}
/// <summary>
/// Stop loss distance for short positions in price steps.
/// </summary>
public decimal StopLossSellPoints
{
get => _stopLossSellPoints.Value;
set => _stopLossSellPoints.Value = value;
}
/// <summary>
/// Trailing stop distance in price steps.
/// </summary>
public decimal TrailingStopPoints
{
get => _trailingStopPoints.Value;
set => _trailingStopPoints.Value = value;
}
/// <summary>
/// Minimum step for trailing stop updates in price steps.
/// </summary>
public decimal TrailingStepPoints
{
get => _trailingStepPoints.Value;
set => _trailingStepPoints.Value = value;
}
/// <summary>
/// Minimal profit in account currency required to exit on EMA reversal.
/// </summary>
public decimal ProfitThreshold
{
get => _profitThreshold.Value;
set => _profitThreshold.Value = value;
}
/// <summary>
/// Candle type for calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initial Parabolic SAR acceleration.
/// </summary>
public decimal SarAcceleration
{
get => _sarAcceleration.Value;
set => _sarAcceleration.Value = value;
}
/// <summary>
/// Maximum Parabolic SAR acceleration.
/// </summary>
public decimal SarMaxAcceleration
{
get => _sarMaxAcceleration.Value;
set => _sarMaxAcceleration.Value = value;
}
/// <summary>
/// Initializes <see cref="ForexProfitStrategy"/>.
/// </summary>
public ForexProfitStrategy()
{
_fastEmaLength = Param(nameof(FastEmaLength), 10)
.SetGreaterThanZero()
.SetDisplay("Fast EMA Length", "Length of the fast EMA", "Averages")
;
_mediumEmaLength = Param(nameof(MediumEmaLength), 25)
.SetGreaterThanZero()
.SetDisplay("Medium EMA Length", "Length of the medium EMA", "Averages")
;
_slowEmaLength = Param(nameof(SlowEmaLength), 50)
.SetGreaterThanZero()
.SetDisplay("Slow EMA Length", "Length of the slow EMA", "Averages")
;
_takeProfitBuyPoints = Param(nameof(TakeProfitBuyPoints), 55m)
.SetGreaterThanZero()
.SetDisplay("Take Profit Long", "Take profit distance for buys (points)", "Risk")
;
_takeProfitSellPoints = Param(nameof(TakeProfitSellPoints), 65m)
.SetGreaterThanZero()
.SetDisplay("Take Profit Short", "Take profit distance for sells (points)", "Risk")
;
_stopLossBuyPoints = Param(nameof(StopLossBuyPoints), 60m)
.SetGreaterThanZero()
.SetDisplay("Stop Loss Long", "Stop loss distance for buys (points)", "Risk")
;
_stopLossSellPoints = Param(nameof(StopLossSellPoints), 85m)
.SetGreaterThanZero()
.SetDisplay("Stop Loss Short", "Stop loss distance for sells (points)", "Risk")
;
_trailingStopPoints = Param(nameof(TrailingStopPoints), 74m)
.SetNotNegative()
.SetDisplay("Trailing Stop", "Trailing stop distance (points)", "Risk")
;
_trailingStepPoints = Param(nameof(TrailingStepPoints), 5m)
.SetNotNegative()
.SetDisplay("Trailing Step", "Minimal trailing step (points)", "Risk")
;
_profitThreshold = Param(nameof(ProfitThreshold), 10m)
.SetNotNegative()
.SetDisplay("Profit Threshold", "Profit required for EMA exit", "Risk")
;
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for calculations", "General");
_sarAcceleration = Param(nameof(SarAcceleration), 0.02m)
.SetGreaterThanZero()
.SetDisplay("SAR Start", "Initial SAR acceleration", "Indicators")
;
_sarMaxAcceleration = Param(nameof(SarMaxAcceleration), 0.2m)
.SetGreaterThanZero()
.SetDisplay("SAR Max", "Maximum SAR acceleration", "Indicators")
;
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_ema10Prev = null;
_ema10PrevPrev = null;
_entryPrice = null;
_stopPrice = null;
_takeProfitPrice = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_emaFast = new EMA { Length = FastEmaLength };
_emaMedium = new EMA { Length = MediumEmaLength };
_emaSlow = new EMA { Length = SlowEmaLength };
_sar = new ParabolicSar
{
Acceleration = SarAcceleration,
AccelerationMax = SarMaxAcceleration
};
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _emaFast);
DrawIndicator(area, _emaMedium);
DrawIndicator(area, _emaSlow);
DrawIndicator(area, _sar);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var ema10Prev = _ema10Prev;
var ema10PrevPrev = _ema10PrevPrev;
var median = (candle.HighPrice + candle.LowPrice) / 2m;
var isFinal = candle.State == CandleStates.Finished;
var ema10Value = _emaFast.Process(new DecimalIndicatorValue(_emaFast, median, candle.OpenTime) { IsFinal = isFinal }).ToDecimal();
var ema25Value = _emaMedium.Process(new DecimalIndicatorValue(_emaMedium, median, candle.OpenTime) { IsFinal = isFinal }).ToDecimal();
var ema50Value = _emaSlow.Process(new DecimalIndicatorValue(_emaSlow, median, candle.OpenTime) { IsFinal = isFinal }).ToDecimal();
var sarResult = _sar.Process(candle);
if (!_emaSlow.IsFormed || !_sar.IsFormed)
{
_ema10PrevPrev = ema10Prev;
_ema10Prev = ema10Value;
return;
}
var sarValue = sarResult.ToDecimal();
var step = Security?.PriceStep ?? 1m;
if (step <= 0m)
step = 1m;
var stepPrice = step;
var longSignal = ema10Value > ema25Value &&
ema10Value > ema50Value &&
ema10PrevPrev.HasValue &&
ema10PrevPrev.Value <= ema50Value &&
sarValue < candle.ClosePrice;
var shortSignal = ema10Value < ema25Value &&
ema10Value < ema50Value &&
ema10PrevPrev.HasValue &&
ema10PrevPrev.Value >= ema50Value &&
sarValue > candle.ClosePrice;
if (Position == 0m && IsFormedAndOnlineAndAllowTrading())
{
if (longSignal)
{
TryEnterLong(candle, step);
}
else if (shortSignal)
{
TryEnterShort(candle, step);
}
}
else if (Position > 0m)
{
ManageLongPosition(candle, ema10Value, ema10Prev, step, stepPrice);
}
else if (Position < 0m)
{
ManageShortPosition(candle, ema10Value, ema10Prev, step, stepPrice);
}
_ema10PrevPrev = ema10Prev;
_ema10Prev = ema10Value;
}
private void TryEnterLong(ICandleMessage candle, decimal step)
{
if (Volume <= 0m)
return;
BuyMarket(Volume);
var entry = candle.ClosePrice;
_entryPrice = entry;
_stopPrice = entry - step * StopLossBuyPoints;
_takeProfitPrice = entry + step * TakeProfitBuyPoints;
}
private void TryEnterShort(ICandleMessage candle, decimal step)
{
if (Volume <= 0m)
return;
SellMarket(Volume);
var entry = candle.ClosePrice;
_entryPrice = entry;
_stopPrice = entry + step * StopLossSellPoints;
_takeProfitPrice = entry - step * TakeProfitSellPoints;
}
private void ManageLongPosition(ICandleMessage candle, decimal ema10Value, decimal? ema10Prev, decimal step, decimal stepPrice)
{
if (_entryPrice == null)
return;
var profit = ComputeProfit(candle.ClosePrice, step, stepPrice);
if (ema10Prev.HasValue && ema10Value < ema10Prev.Value && profit > ProfitThreshold)
{
SellMarket(Math.Abs(Position));
ResetPositionTargets();
return;
}
if (_takeProfitPrice.HasValue && candle.HighPrice >= _takeProfitPrice.Value)
{
SellMarket(Math.Abs(Position));
ResetPositionTargets();
return;
}
if (_stopPrice.HasValue && candle.LowPrice <= _stopPrice.Value)
{
SellMarket(Math.Abs(Position));
ResetPositionTargets();
return;
}
UpdateLongTrailing(candle, step);
}
private void ManageShortPosition(ICandleMessage candle, decimal ema10Value, decimal? ema10Prev, decimal step, decimal stepPrice)
{
if (_entryPrice == null)
return;
var profit = ComputeProfit(candle.ClosePrice, step, stepPrice);
if (ema10Prev.HasValue && ema10Value > ema10Prev.Value && profit > ProfitThreshold)
{
BuyMarket(Math.Abs(Position));
ResetPositionTargets();
return;
}
if (_takeProfitPrice.HasValue && candle.LowPrice <= _takeProfitPrice.Value)
{
BuyMarket(Math.Abs(Position));
ResetPositionTargets();
return;
}
if (_stopPrice.HasValue && candle.HighPrice >= _stopPrice.Value)
{
BuyMarket(Math.Abs(Position));
ResetPositionTargets();
return;
}
UpdateShortTrailing(candle, step);
}
private void UpdateLongTrailing(ICandleMessage candle, decimal step)
{
if (TrailingStopPoints <= 0m || _entryPrice == null)
return;
var trailingDistance = step * TrailingStopPoints;
var trailingStep = step * TrailingStepPoints;
var movement = candle.ClosePrice - _entryPrice.Value;
if (movement > trailingDistance)
{
var newStop = candle.ClosePrice - trailingDistance;
if (!_stopPrice.HasValue || newStop - _stopPrice.Value >= trailingStep)
_stopPrice = newStop;
}
}
private void UpdateShortTrailing(ICandleMessage candle, decimal step)
{
if (TrailingStopPoints <= 0m || _entryPrice == null)
return;
var trailingDistance = step * TrailingStopPoints;
var trailingStep = step * TrailingStepPoints;
var movement = _entryPrice.Value - candle.ClosePrice;
if (movement > trailingDistance)
{
var newStop = candle.ClosePrice + trailingDistance;
if (!_stopPrice.HasValue || _stopPrice.Value - newStop >= trailingStep)
_stopPrice = newStop;
}
}
private decimal ComputeProfit(decimal currentPrice, decimal step, decimal stepPrice)
{
if (_entryPrice == null || Position == 0m)
return 0m;
var ticks = (currentPrice - _entryPrice.Value) / step;
return ticks * stepPrice * Position;
}
private void ResetPositionTargets()
{
_entryPrice = null;
_stopPrice = null;
_takeProfitPrice = null;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.BusinessEntities")
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, Unit, UnitTypes
from StockSharp.Algo.Indicators import ExponentialMovingAverage, ParabolicSar, CandleIndicatorValue
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class forex_profit_strategy(Strategy):
def __init__(self):
super(forex_profit_strategy, self).__init__()
self._fast_ema_length = self.Param("FastEmaLength", 10)
self._medium_ema_length = self.Param("MediumEmaLength", 25)
self._slow_ema_length = self.Param("SlowEmaLength", 50)
self._take_profit_buy_points = self.Param("TakeProfitBuyPoints", 55.0)
self._take_profit_sell_points = self.Param("TakeProfitSellPoints", 65.0)
self._stop_loss_buy_points = self.Param("StopLossBuyPoints", 60.0)
self._stop_loss_sell_points = self.Param("StopLossSellPoints", 85.0)
self._trailing_stop_points = self.Param("TrailingStopPoints", 74.0)
self._trailing_step_points = self.Param("TrailingStepPoints", 5.0)
self._profit_threshold = self.Param("ProfitThreshold", 10.0)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._sar_acceleration = self.Param("SarAcceleration", 0.02)
self._sar_max_acceleration = self.Param("SarMaxAcceleration", 0.2)
self._ema_fast = None
self._ema_medium = None
self._ema_slow = None
self._sar = None
self._ema10_prev = None
self._ema10_prev_prev = None
self._entry_price = None
self._stop_price = None
self._take_profit_price = None
@property
def FastEmaLength(self):
return self._fast_ema_length.Value
@FastEmaLength.setter
def FastEmaLength(self, value):
self._fast_ema_length.Value = value
@property
def MediumEmaLength(self):
return self._medium_ema_length.Value
@MediumEmaLength.setter
def MediumEmaLength(self, value):
self._medium_ema_length.Value = value
@property
def SlowEmaLength(self):
return self._slow_ema_length.Value
@SlowEmaLength.setter
def SlowEmaLength(self, value):
self._slow_ema_length.Value = value
@property
def TakeProfitBuyPoints(self):
return self._take_profit_buy_points.Value
@TakeProfitBuyPoints.setter
def TakeProfitBuyPoints(self, value):
self._take_profit_buy_points.Value = value
@property
def TakeProfitSellPoints(self):
return self._take_profit_sell_points.Value
@TakeProfitSellPoints.setter
def TakeProfitSellPoints(self, value):
self._take_profit_sell_points.Value = value
@property
def StopLossBuyPoints(self):
return self._stop_loss_buy_points.Value
@StopLossBuyPoints.setter
def StopLossBuyPoints(self, value):
self._stop_loss_buy_points.Value = value
@property
def StopLossSellPoints(self):
return self._stop_loss_sell_points.Value
@StopLossSellPoints.setter
def StopLossSellPoints(self, value):
self._stop_loss_sell_points.Value = value
@property
def TrailingStopPoints(self):
return self._trailing_stop_points.Value
@TrailingStopPoints.setter
def TrailingStopPoints(self, value):
self._trailing_stop_points.Value = value
@property
def TrailingStepPoints(self):
return self._trailing_step_points.Value
@TrailingStepPoints.setter
def TrailingStepPoints(self, value):
self._trailing_step_points.Value = value
@property
def ProfitThreshold(self):
return self._profit_threshold.Value
@ProfitThreshold.setter
def ProfitThreshold(self, value):
self._profit_threshold.Value = value
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def SarAcceleration(self):
return self._sar_acceleration.Value
@SarAcceleration.setter
def SarAcceleration(self, value):
self._sar_acceleration.Value = value
@property
def SarMaxAcceleration(self):
return self._sar_max_acceleration.Value
@SarMaxAcceleration.setter
def SarMaxAcceleration(self, value):
self._sar_max_acceleration.Value = value
def OnStarted2(self, time):
super(forex_profit_strategy, self).OnStarted2(time)
self._ema10_prev = None
self._ema10_prev_prev = None
self._entry_price = None
self._stop_price = None
self._take_profit_price = None
self._ema_fast = ExponentialMovingAverage()
self._ema_fast.Length = self.FastEmaLength
self._ema_medium = ExponentialMovingAverage()
self._ema_medium.Length = self.MediumEmaLength
self._ema_slow = ExponentialMovingAverage()
self._ema_slow.Length = self.SlowEmaLength
self._sar = ParabolicSar()
self._sar.Acceleration = self.SarAcceleration
self._sar.AccelerationMax = self.SarMaxAcceleration
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self.ProcessCandle).Start()
self.StartProtection(
Unit(2000.0, UnitTypes.Absolute),
Unit(1000.0, UnitTypes.Absolute))
def ProcessCandle(self, candle):
if candle.State != CandleStates.Finished:
return
median = (float(candle.HighPrice) + float(candle.LowPrice)) / 2.0
close = float(candle.ClosePrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
ema10_result = process_float(self._ema_fast, Decimal(median), candle.CloseTime, True)
ema25_result = process_float(self._ema_medium, Decimal(median), candle.CloseTime, True)
ema50_result = process_float(self._ema_slow, Decimal(median), candle.CloseTime, True)
sar_result = self._sar.Process(CandleIndicatorValue(self._sar, candle))
ema10_value = float(ema10_result)
ema25_value = float(ema25_result)
ema50_value = float(ema50_result)
sar_value = float(sar_result)
ema10_prev = self._ema10_prev
ema10_prev_prev = self._ema10_prev_prev
if not self._ema_slow.IsFormed or not self._sar.IsFormed:
self._ema10_prev_prev = ema10_prev
self._ema10_prev = ema10_value
return
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if step <= 0.0:
step = 1.0
long_signal = (ema10_value > ema25_value and
ema10_value > ema50_value and
ema10_prev_prev is not None and
ema10_prev_prev <= ema50_value and
sar_value < close)
short_signal = (ema10_value < ema25_value and
ema10_value < ema50_value and
ema10_prev_prev is not None and
ema10_prev_prev >= ema50_value and
sar_value > close)
if self.Position == 0:
if long_signal:
self.BuyMarket()
self._entry_price = close
self._stop_price = close - step * float(self.StopLossBuyPoints)
self._take_profit_price = close + step * float(self.TakeProfitBuyPoints)
elif short_signal:
self.SellMarket()
self._entry_price = close
self._stop_price = close + step * float(self.StopLossSellPoints)
self._take_profit_price = close - step * float(self.TakeProfitSellPoints)
elif self.Position > 0:
self._manage_long(candle, ema10_value, ema10_prev, step)
elif self.Position < 0:
self._manage_short(candle, ema10_value, ema10_prev, step)
self._ema10_prev_prev = ema10_prev
self._ema10_prev = ema10_value
def _manage_long(self, candle, ema10_value, ema10_prev, step):
if self._entry_price is None:
return
close = float(candle.ClosePrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
profit = self._compute_profit(close, step)
if ema10_prev is not None and ema10_value < ema10_prev and profit > float(self.ProfitThreshold):
self.SellMarket()
self._reset_position_targets()
return
if self._take_profit_price is not None and high >= self._take_profit_price:
self.SellMarket()
self._reset_position_targets()
return
if self._stop_price is not None and low <= self._stop_price:
self.SellMarket()
self._reset_position_targets()
return
self._update_long_trailing(candle, step)
def _manage_short(self, candle, ema10_value, ema10_prev, step):
if self._entry_price is None:
return
close = float(candle.ClosePrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
profit = self._compute_profit(close, step)
if ema10_prev is not None and ema10_value > ema10_prev and profit > float(self.ProfitThreshold):
self.BuyMarket()
self._reset_position_targets()
return
if self._take_profit_price is not None and low <= self._take_profit_price:
self.BuyMarket()
self._reset_position_targets()
return
if self._stop_price is not None and high >= self._stop_price:
self.BuyMarket()
self._reset_position_targets()
return
self._update_short_trailing(candle, step)
def _update_long_trailing(self, candle, step):
trail_pts = float(self.TrailingStopPoints)
if trail_pts <= 0.0 or self._entry_price is None:
return
close = float(candle.ClosePrice)
trailing_distance = step * trail_pts
trailing_step = step * float(self.TrailingStepPoints)
movement = close - self._entry_price
if movement > trailing_distance:
new_stop = close - trailing_distance
if self._stop_price is None or new_stop - self._stop_price >= trailing_step:
self._stop_price = new_stop
def _update_short_trailing(self, candle, step):
trail_pts = float(self.TrailingStopPoints)
if trail_pts <= 0.0 or self._entry_price is None:
return
close = float(candle.ClosePrice)
trailing_distance = step * trail_pts
trailing_step = step * float(self.TrailingStepPoints)
movement = self._entry_price - close
if movement > trailing_distance:
new_stop = close + trailing_distance
if self._stop_price is None or self._stop_price - new_stop >= trailing_step:
self._stop_price = new_stop
def _compute_profit(self, current_price, step):
if self._entry_price is None or self.Position == 0:
return 0.0
ticks = (current_price - self._entry_price) / step
return ticks * step * self.Position
def _reset_position_targets(self):
self._entry_price = None
self._stop_price = None
self._take_profit_price = None
def OnReseted(self):
super(forex_profit_strategy, self).OnReseted()
self._ema_fast = None
self._ema_medium = None
self._ema_slow = None
self._sar = None
self._ema10_prev = None
self._ema10_prev_prev = None
self._entry_price = None
self._stop_price = None
self._take_profit_price = None
def CreateClone(self):
return forex_profit_strategy()