4218 RSI MA 戦略
概要
この戦略は、MQL/9925 にある元の MetaTrader Expert Advisor の C# ポートです。従来の RSI と加重価格 (High + Low + 2 * Close) / 4 に基づいて構築された指数移動平均の傾きを組み合わせることにより、RSI_MA のモメンタム オシレーターを再作成します。シグナルは完成したキャンドルに対してのみ生成され、動作はソース実装と同一に保たれます。
このスクリプトは日次 EURUSD ローソク足 (D1 タイムフレーム) 用に設計されており、一度に 1 つのポジションをオープンします。それにもかかわらず、ローソク足タイプがそれに応じて設定されている限り、意味のある価格ステップを持つあらゆる商品を使用できます。
戦略ロジック
- 指標の計算
- 設定可能な長さの相対強度指数は、終値に基づいて計算されます。
- 同じ長さの指数移動平均が加重価格に基づいて計算されます。
- インジケーター値は
RSI * (EMA(current) - EMA(previous)) / pipSizeに等しく、[1, 99]の範囲にクリップされます。
- ロングエントリー
- 売られ過ぎの極値 (デフォルト 5) を下回る以前のインジケーターの値。
- 売られすぎアクティベーションしきい値 (デフォルトは 20) を超える最新のインジケーター値。
- オープン ポジションまたは既存のショート ポジションがない (新しいロングを開く前にショートがクローズされている)。
- 短いエントリー
- 買われすぎの極値 (デフォルト 95) を超える以前のインジケーターの値。
- 買われすぎアクティベーションしきい値 (デフォルトは 80) を下回る最新のインジケーター値。
- オープン ポジションまたは既存のロング ポジションがない (新しいショートを開く前にロングがクローズされている)。
- インジケーターベースの出口
- ロングポジションは、インジケーターが買われすぎの極値を超えてアクティブ化レベル (デフォルトでは 95 → 80) を下回るとクローズされます。
- ショートポジションは、インジケーターが売られすぎの極値以下からアクティブレベル(デフォルトでは 5 → 20)以上に上昇するとクローズされます。
- 保護出口
- オプションのストップロス、テイクプロフィット、トレーリングストップの距離はpipsで表されます。距離は、セキュリティ
PriceStep(フォールバック 0.0001) を使用して自動的に価格に変換されます。 - トレーリング ストップの引き締めは、元の EA の動作に従います。設定された距離を超えて価格が有利な方向に変動した場合にのみ有効になります。
- オプションのストップロス、テイクプロフィット、トレーリングストップの距離はpipsで表されます。距離は、セキュリティ
パラメーター
| パラメータ | 説明 |
|---|---|
RsiPeriod |
RSI と EMA の長さ。 |
OversoldActivationLevel |
極端に売られすぎた後の長期セットアップを確認するしきい値。 |
OversoldExtremeLevel |
長く許される前に到達しなければならない極限。 |
OverboughtActivationLevel |
買われすぎの後のショートセットアップを確認するしきい値。 |
OverboughtExtremeLevel |
ショートパンツが許可される前に到達する必要がある極限。 |
StopLossPips |
保護ストップロスの距離。 UseStopLoss 経由で有効/無効にします。 |
TakeProfitPips |
利益目標までの距離。 UseTakeProfit 経由で有効/無効にします。 |
TrailingStopPips |
トレーリングストップまでの距離。 UseTrailingStop 経由で有効/無効にします。 |
UseStopLoss |
ストップロス管理を有効にします。 |
UseTakeProfit |
テイクプロフィット経営を活性化します。 |
UseTrailingStop |
トレーリングストップの更新をアクティブにします。 |
UseMoneyManagement |
RiskPercent に基づいてポジションのサイジングを有効にします。 |
RiskPercent |
資金管理がアクティブな場合の取引ごとのポートフォリオのリスクの割合。 |
TradeVolume |
資金管理が無効な場合に使用される固定量。 |
CandleType |
ストラテジーによって処理されるローソク足のデータ型 (デフォルトは日次)。 |
使用上の注意
- この戦略を EURUSD の日足ローソク足にアタッチして、元の EA の動作を再現します。他の金融商品/時間枠は、
CandleTypeとしきい値を調整した後にサポートされます。 - 常にオープンなポジションは 1 つだけです。新しい取引を開始すると、最初に反対方向が自動的にクローズされます。
- ポートフォリオ情報が利用できない場合、または計算されたボリュームがプラスでなくなると、資金管理は固定の
TradeVolumeに戻ります。 - セキュリティ
PriceStepがピップ (ほとんどの FX ペアでは 0.0001) を反映していることを確認します。それ以外の場合は、それに応じてパラメータを調整します。
リスク管理
- ストップロスとテイクプロフィットのレベルは、ローソクの高値/安値の範囲を使用して、完了したローソクごとに評価されます。
- トレーリングストップは、取引が設定された距離を超えて利益を上げており、不利な方向に動いていない場合にのみ更新されます。
- リスク制御が無効になっている場合でもインジケーターベースの exit は機能し、MQL バージョンと同様の正常な機能低下が保証されます。
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;
using StockSharp.Algo.Candles;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// RSI and EMA based strategy converted from the original MQL implementation.
/// Combines a custom RSI*EMA momentum oscillator with basic risk management.
/// </summary>
public class RsiMaStrategy : Strategy
{
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _oversoldActivationLevel;
private readonly StrategyParam<decimal> _oversoldExtremeLevel;
private readonly StrategyParam<decimal> _overboughtActivationLevel;
private readonly StrategyParam<decimal> _overboughtExtremeLevel;
private readonly StrategyParam<decimal> _stopLossPips;
private readonly StrategyParam<decimal> _takeProfitPips;
private readonly StrategyParam<decimal> _trailingStopPips;
private readonly StrategyParam<bool> _useStopLoss;
private readonly StrategyParam<bool> _useTakeProfit;
private readonly StrategyParam<bool> _useTrailingStop;
private readonly StrategyParam<bool> _useMoneyManagement;
private readonly StrategyParam<decimal> _riskPercent;
private readonly StrategyParam<decimal> _tradeVolume;
private readonly StrategyParam<DataType> _candleType;
private RelativeStrengthIndex _rsi;
private ExponentialMovingAverage _ema;
private decimal? _previousIndicatorValue;
private decimal? _stopLossPrice;
private decimal? _takeProfitPrice;
private decimal _entryPrice;
public RsiMaStrategy()
{
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetDisplay("RSI Period", string.Empty, "Oscillator")
;
_oversoldActivationLevel = Param(nameof(OversoldActivationLevel), 40m)
.SetDisplay("Oversold Activation", string.Empty, "Oscillator")
;
_oversoldExtremeLevel = Param(nameof(OversoldExtremeLevel), 30m)
.SetDisplay("Oversold Extreme", string.Empty, "Oscillator");
_overboughtActivationLevel = Param(nameof(OverboughtActivationLevel), 60m)
.SetDisplay("Overbought Activation", string.Empty, "Oscillator")
;
_overboughtExtremeLevel = Param(nameof(OverboughtExtremeLevel), 70m)
.SetDisplay("Overbought Extreme", string.Empty, "Oscillator");
_stopLossPips = Param(nameof(StopLossPips), 399m)
.SetDisplay("Stop Loss (pips)", string.Empty, "Risk");
_takeProfitPips = Param(nameof(TakeProfitPips), 999m)
.SetDisplay("Take Profit (pips)", string.Empty, "Risk");
_trailingStopPips = Param(nameof(TrailingStopPips), 299m)
.SetDisplay("Trailing Stop (pips)", string.Empty, "Risk");
_useStopLoss = Param(nameof(UseStopLoss), true)
.SetDisplay("Use Stop Loss", string.Empty, "Risk");
_useTakeProfit = Param(nameof(UseTakeProfit), true)
.SetDisplay("Use Take Profit", string.Empty, "Risk");
_useTrailingStop = Param(nameof(UseTrailingStop), true)
.SetDisplay("Use Trailing Stop", string.Empty, "Risk");
_useMoneyManagement = Param(nameof(UseMoneyManagement), false)
.SetDisplay("Use Risk Percent Position Sizing", string.Empty, "Position");
_riskPercent = Param(nameof(RiskPercent), 10m)
.SetDisplay("Risk Percent", string.Empty, "Position");
_tradeVolume = Param(nameof(TradeVolume), 0.1m)
.SetDisplay("Fixed Volume", string.Empty, "Position");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(2).TimeFrame())
.SetDisplay("Candle TimeFrame", string.Empty, "General");
}
/// <summary>
/// RSI calculation period.
/// </summary>
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
/// <summary>
/// Activation threshold after an oversold extreme.
/// </summary>
public decimal OversoldActivationLevel
{
get => _oversoldActivationLevel.Value;
set => _oversoldActivationLevel.Value = value;
}
/// <summary>
/// Oversold extreme required before a long setup becomes valid.
/// </summary>
public decimal OversoldExtremeLevel
{
get => _oversoldExtremeLevel.Value;
set => _oversoldExtremeLevel.Value = value;
}
/// <summary>
/// Activation threshold after an overbought extreme.
/// </summary>
public decimal OverboughtActivationLevel
{
get => _overboughtActivationLevel.Value;
set => _overboughtActivationLevel.Value = value;
}
/// <summary>
/// Overbought extreme required before a short setup becomes valid.
/// </summary>
public decimal OverboughtExtremeLevel
{
get => _overboughtExtremeLevel.Value;
set => _overboughtExtremeLevel.Value = value;
}
/// <summary>
/// Stop-loss distance measured in pips.
/// </summary>
public decimal StopLossPips
{
get => _stopLossPips.Value;
set => _stopLossPips.Value = value;
}
/// <summary>
/// Take-profit distance measured in pips.
/// </summary>
public decimal TakeProfitPips
{
get => _takeProfitPips.Value;
set => _takeProfitPips.Value = value;
}
/// <summary>
/// Trailing-stop distance measured in pips.
/// </summary>
public decimal TrailingStopPips
{
get => _trailingStopPips.Value;
set => _trailingStopPips.Value = value;
}
/// <summary>
/// Enable or disable stop-loss management.
/// </summary>
public bool UseStopLoss
{
get => _useStopLoss.Value;
set => _useStopLoss.Value = value;
}
/// <summary>
/// Enable or disable take-profit management.
/// </summary>
public bool UseTakeProfit
{
get => _useTakeProfit.Value;
set => _useTakeProfit.Value = value;
}
/// <summary>
/// Enable or disable trailing stop adjustments.
/// </summary>
public bool UseTrailingStop
{
get => _useTrailingStop.Value;
set => _useTrailingStop.Value = value;
}
/// <summary>
/// Enable or disable percent based position sizing.
/// </summary>
public bool UseMoneyManagement
{
get => _useMoneyManagement.Value;
set => _useMoneyManagement.Value = value;
}
/// <summary>
/// Portfolio risk percentage when money management is enabled.
/// </summary>
public decimal RiskPercent
{
get => _riskPercent.Value;
set => _riskPercent.Value = value;
}
/// <summary>
/// Fixed volume used when money management is disabled.
/// </summary>
public decimal TradeVolume
{
get => _tradeVolume.Value;
set => _tradeVolume.Value = value;
}
/// <summary>
/// Candle type used for signal generation.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, CandleType);
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_rsi = null;
_ema = null;
_previousIndicatorValue = null;
_stopLossPrice = null;
_takeProfitPrice = null;
_entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_rsi = new RelativeStrengthIndex
{
Length = RsiPeriod
};
_ema = new ExponentialMovingAverage
{
Length = RsiPeriod
};
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_rsi, ProcessCandle)
.Start();
StartProtection(null, null);
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!_rsi.IsFormed)
return;
var indicatorValue = rsiValue;
if (_previousIndicatorValue is decimal previousValue)
{
ManageOpenPosition(candle, previousValue, indicatorValue);
EvaluateEntries(candle, previousValue, indicatorValue);
}
_previousIndicatorValue = indicatorValue;
}
private void ManageOpenPosition(ICandleMessage candle, decimal previousValue, decimal currentValue)
{
if (Position > 0)
{
var exitSignal = previousValue > OverboughtExtremeLevel && currentValue < OverboughtActivationLevel;
if (exitSignal)
{
SellMarket();
ResetRiskLevels();
return;
}
UpdateTrailingStopForLong(candle);
if (ShouldCloseLong(candle))
{
SellMarket();
ResetRiskLevels();
}
}
else if (Position < 0)
{
var exitSignal = previousValue < OversoldExtremeLevel && currentValue > OversoldActivationLevel;
if (exitSignal)
{
BuyMarket();
ResetRiskLevels();
return;
}
UpdateTrailingStopForShort(candle);
if (ShouldCloseShort(candle))
{
BuyMarket();
ResetRiskLevels();
}
}
}
private void EvaluateEntries(ICandleMessage candle, decimal previousValue, decimal currentValue)
{
var price = candle.ClosePrice;
if (price <= 0m)
return;
if (previousValue < OversoldExtremeLevel && currentValue > OversoldActivationLevel && Position <= 0)
{
_entryPrice = price;
InitializeRiskLevelsForLong(price);
BuyMarket();
}
else if (previousValue > OverboughtExtremeLevel && currentValue < OverboughtActivationLevel && Position >= 0)
{
_entryPrice = price;
InitializeRiskLevelsForShort(price);
SellMarket();
}
}
private void InitializeRiskLevelsForLong(decimal price)
{
var pipDistance = GetPipSize();
if (UseStopLoss && StopLossPips > 0m)
_stopLossPrice = price - pipDistance * StopLossPips;
else
_stopLossPrice = null;
if (UseTakeProfit && TakeProfitPips > 0m)
_takeProfitPrice = price + pipDistance * TakeProfitPips;
else
_takeProfitPrice = null;
}
private void InitializeRiskLevelsForShort(decimal price)
{
var pipDistance = GetPipSize();
if (UseStopLoss && StopLossPips > 0m)
_stopLossPrice = price + pipDistance * StopLossPips;
else
_stopLossPrice = null;
if (UseTakeProfit && TakeProfitPips > 0m)
_takeProfitPrice = price - pipDistance * TakeProfitPips;
else
_takeProfitPrice = null;
}
private void UpdateTrailingStopForLong(ICandleMessage candle)
{
if (!UseTrailingStop || TrailingStopPips <= 0m)
return;
var pipDistance = GetPipSize() * TrailingStopPips;
if (pipDistance <= 0m)
return;
var profit = candle.ClosePrice - _entryPrice;
if (profit <= pipDistance)
return;
var newStop = candle.ClosePrice - pipDistance;
if (_stopLossPrice is null || newStop > _stopLossPrice)
_stopLossPrice = newStop;
}
private void UpdateTrailingStopForShort(ICandleMessage candle)
{
if (!UseTrailingStop || TrailingStopPips <= 0m)
return;
var pipDistance = GetPipSize() * TrailingStopPips;
if (pipDistance <= 0m)
return;
var profit = _entryPrice - candle.ClosePrice;
if (profit <= pipDistance)
return;
var newStop = candle.ClosePrice + pipDistance;
if (_stopLossPrice is null || newStop < _stopLossPrice)
_stopLossPrice = newStop;
}
private bool ShouldCloseLong(ICandleMessage candle)
{
var stopHit = UseStopLoss && _stopLossPrice is decimal stop && candle.LowPrice <= stop;
var takeProfitHit = UseTakeProfit && _takeProfitPrice is decimal takeProfit && candle.HighPrice >= takeProfit;
return stopHit || takeProfitHit;
}
private bool ShouldCloseShort(ICandleMessage candle)
{
var stopHit = UseStopLoss && _stopLossPrice is decimal stop && candle.HighPrice >= stop;
var takeProfitHit = UseTakeProfit && _takeProfitPrice is decimal takeProfit && candle.LowPrice <= takeProfit;
return stopHit || takeProfitHit;
}
private void ResetRiskLevels()
{
_stopLossPrice = null;
_takeProfitPrice = null;
_entryPrice = 0m;
}
private decimal GetPipSize()
{
var priceStep = Security?.PriceStep;
if (priceStep is null || priceStep == 0m)
return 0.0001m;
return priceStep.Value;
}
private decimal GetOrderVolume(decimal price)
{
var volume = TradeVolume;
if (!UseMoneyManagement || Portfolio is null || price <= 0m)
return volume;
var portfolioValue = Portfolio.CurrentValue ?? 0m;
if (portfolioValue <= 0m)
return volume;
var riskAmount = portfolioValue * RiskPercent / 100m;
if (riskAmount <= 0m)
return volume;
var estimatedVolume = riskAmount / price;
var volumeStep = Security?.VolumeStep ?? 0m;
if (volumeStep > 0m)
{
estimatedVolume = Math.Floor(estimatedVolume / volumeStep) * volumeStep;
}
if (estimatedVolume <= 0m)
estimatedVolume = volume;
return estimatedVolume;
}
}
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
from StockSharp.Algo.Indicators import RelativeStrengthIndex
class rsi_ma_strategy(Strategy):
def __init__(self):
super(rsi_ma_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(2))) \
.SetDisplay("Candle TimeFrame", "", "General")
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "", "Oscillator")
self._oversold_activation = self.Param("OversoldActivationLevel", 40.0) \
.SetDisplay("Oversold Activation", "", "Oscillator")
self._oversold_extreme = self.Param("OversoldExtremeLevel", 30.0) \
.SetDisplay("Oversold Extreme", "", "Oscillator")
self._overbought_activation = self.Param("OverboughtActivationLevel", 60.0) \
.SetDisplay("Overbought Activation", "", "Oscillator")
self._overbought_extreme = self.Param("OverboughtExtremeLevel", 70.0) \
.SetDisplay("Overbought Extreme", "", "Oscillator")
self._stop_loss_pips = self.Param("StopLossPips", 399.0) \
.SetDisplay("Stop Loss (pips)", "", "Risk")
self._take_profit_pips = self.Param("TakeProfitPips", 999.0) \
.SetDisplay("Take Profit (pips)", "", "Risk")
self._trailing_stop_pips = self.Param("TrailingStopPips", 299.0) \
.SetDisplay("Trailing Stop (pips)", "", "Risk")
self._use_stop_loss = self.Param("UseStopLoss", True) \
.SetDisplay("Use Stop Loss", "", "Risk")
self._use_take_profit = self.Param("UseTakeProfit", True) \
.SetDisplay("Use Take Profit", "", "Risk")
self._use_trailing_stop = self.Param("UseTrailingStop", True) \
.SetDisplay("Use Trailing Stop", "", "Risk")
self._prev_rsi = None
self._entry_price = 0.0
self._stop_loss_price = None
self._take_profit_price = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@property
def OversoldActivationLevel(self):
return float(self._oversold_activation.Value)
@property
def OversoldExtremeLevel(self):
return float(self._oversold_extreme.Value)
@property
def OverboughtActivationLevel(self):
return float(self._overbought_activation.Value)
@property
def OverboughtExtremeLevel(self):
return float(self._overbought_extreme.Value)
@property
def StopLossPips(self):
return float(self._stop_loss_pips.Value)
@property
def TakeProfitPips(self):
return float(self._take_profit_pips.Value)
@property
def TrailingStopPips(self):
return float(self._trailing_stop_pips.Value)
@property
def UseStopLoss(self):
return self._use_stop_loss.Value
@property
def UseTakeProfit(self):
return self._use_take_profit.Value
@property
def UseTrailingStop(self):
return self._use_trailing_stop.Value
def OnStarted2(self, time):
super(rsi_ma_strategy, self).OnStarted2(time)
self._prev_rsi = None
self._entry_price = 0.0
self._stop_loss_price = None
self._take_profit_price = None
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.RsiPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._rsi, self.ProcessCandle).Start()
def _get_pip_size(self):
sec = self.Security
if sec is not None:
ps = sec.PriceStep
if ps is not None and float(ps) > 0:
return float(ps)
return 0.0001
def ProcessCandle(self, candle, rsi_val):
if candle.State != CandleStates.Finished:
return
rv = float(rsi_val)
if self._prev_rsi is None:
self._prev_rsi = rv
return
close = float(candle.ClosePrice)
low = float(candle.LowPrice)
high = float(candle.HighPrice)
prev = self._prev_rsi
# manage open position
if self.Position > 0:
exit_signal = prev > self.OverboughtExtremeLevel and rv < self.OverboughtActivationLevel
if exit_signal:
self.SellMarket()
self._reset_risk()
self._prev_rsi = rv
return
self._update_trailing_long(close)
if self._should_close_long(low, high):
self.SellMarket()
self._reset_risk()
self._prev_rsi = rv
return
elif self.Position < 0:
exit_signal = prev < self.OversoldExtremeLevel and rv > self.OversoldActivationLevel
if exit_signal:
self.BuyMarket()
self._reset_risk()
self._prev_rsi = rv
return
self._update_trailing_short(close)
if self._should_close_short(low, high):
self.BuyMarket()
self._reset_risk()
self._prev_rsi = rv
return
# evaluate entries
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_rsi = rv
return
if close > 0:
if prev < self.OversoldExtremeLevel and rv > self.OversoldActivationLevel and self.Position <= 0:
self._entry_price = close
self._init_risk_long(close)
self.BuyMarket()
elif prev > self.OverboughtExtremeLevel and rv < self.OverboughtActivationLevel and self.Position >= 0:
self._entry_price = close
self._init_risk_short(close)
self.SellMarket()
self._prev_rsi = rv
def _init_risk_long(self, price):
pip = self._get_pip_size()
if self.UseStopLoss and self.StopLossPips > 0:
self._stop_loss_price = price - pip * self.StopLossPips
else:
self._stop_loss_price = None
if self.UseTakeProfit and self.TakeProfitPips > 0:
self._take_profit_price = price + pip * self.TakeProfitPips
else:
self._take_profit_price = None
def _init_risk_short(self, price):
pip = self._get_pip_size()
if self.UseStopLoss and self.StopLossPips > 0:
self._stop_loss_price = price + pip * self.StopLossPips
else:
self._stop_loss_price = None
if self.UseTakeProfit and self.TakeProfitPips > 0:
self._take_profit_price = price - pip * self.TakeProfitPips
else:
self._take_profit_price = None
def _update_trailing_long(self, close):
if not self.UseTrailingStop or self.TrailingStopPips <= 0:
return
pip = self._get_pip_size()
pip_dist = pip * self.TrailingStopPips
if pip_dist <= 0:
return
profit = close - self._entry_price
if profit <= pip_dist:
return
new_stop = close - pip_dist
if self._stop_loss_price is None or new_stop > self._stop_loss_price:
self._stop_loss_price = new_stop
def _update_trailing_short(self, close):
if not self.UseTrailingStop or self.TrailingStopPips <= 0:
return
pip = self._get_pip_size()
pip_dist = pip * self.TrailingStopPips
if pip_dist <= 0:
return
profit = self._entry_price - close
if profit <= pip_dist:
return
new_stop = close + pip_dist
if self._stop_loss_price is None or new_stop < self._stop_loss_price:
self._stop_loss_price = new_stop
def _should_close_long(self, low, high):
stop_hit = self.UseStopLoss and self._stop_loss_price is not None and low <= self._stop_loss_price
tp_hit = self.UseTakeProfit and self._take_profit_price is not None and high >= self._take_profit_price
return stop_hit or tp_hit
def _should_close_short(self, low, high):
stop_hit = self.UseStopLoss and self._stop_loss_price is not None and high >= self._stop_loss_price
tp_hit = self.UseTakeProfit and self._take_profit_price is not None and low <= self._take_profit_price
return stop_hit or tp_hit
def _reset_risk(self):
self._stop_loss_price = None
self._take_profit_price = None
self._entry_price = 0.0
def OnReseted(self):
super(rsi_ma_strategy, self).OnReseted()
self._prev_rsi = None
self._entry_price = 0.0
self._stop_loss_price = None
self._take_profit_price = None
def CreateClone(self):
return rsi_ma_strategy()