This strategy is a StockSharp port of the MetaTrader expert advisor “Mission Impossible Power Two Open”. It monitors the direction of the most recently completed candle and opens a new basket of trades in that direction. When price moves against the active basket, the strategy adds new averaging entries according to a fixed pip grid. The volume of each new entry grows with the floating loss of the basket, mimicking the power-based sizing rule from the original EA. Exit targets are recalculated after every fill so that the entire basket shares a single take-profit and stop-loss level.
Trading Logic
Signal detection – On every finished candle the strategy compares the previous candle’s close with its open.
If the previous candle closed above its open, the long signal is active.
If it closed below the open, the short signal is active.
An inside bar (close equal to open) produces no new basket.
Opening the first trade – If no grid is active in the signaled direction, the strategy places a market order with the BaseVolume size.
Averaging grid – When a basket exists, the strategy keeps measuring the distance between the last filled price and the current close.
For longs a new entry is added once price falls by at least GridStepPips * PriceStep below the last fill.
For shorts the strategy waits until price rises by the same distance above the last fill.
The grid stops adding new positions after MaxTrades fills have been reached in the respective direction.
Dynamic volume – Before sending each new order the strategy computes the unrealized loss of the basket, multiplies it by Power * 0.0001, and adds the result to BaseVolume. The final size is rounded to the exchange volume step, clamped between the security limits, and capped by MaxVolume.
Exit management – After every fill the strategy recomputes the shared targets for the whole basket:
With a single position the take-profit is TakeProfitFirstPips away from the entry and the stop-loss is StopLossPips away in the opposite direction.
With two or more positions both levels are anchored to the volume-weighted average price of the basket, using TakeProfitNextPips for the target distance and StopLossPips for protection.
When price touches either the take-profit or the stop-loss all positions in that direction are closed at market.
Independent baskets – Long and short grids are tracked independently. The strategy can hold both at the same time when alternating signals arrive.
Parameters
Name
Type
Default
Description
BaseVolume
decimal
0.01
Initial order size for a new basket before scaling.
MaxVolume
decimal
2
Hard cap for a single market order after rounding.
Power
decimal
13
Multiplier applied to the floating loss when calculating the additive volume for new entries.
StopLossPips
int
400
Distance in price steps used for the shared stop-loss.
TakeProfitFirstPips
int
15
Take-profit distance for the very first entry in a basket.
TakeProfitNextPips
int
7
Take-profit distance for averaged baskets (two or more entries).
GridStepPips
int
21
Minimum adverse move (in price steps) before another averaging entry is allowed.
MaxTrades
int
16
Maximum number of grid trades per direction.
CandleType
DataType
TimeSpan.FromMinutes(5).TimeFrame()
Candles used for signal generation and basket management.
Notes
Order volumes are always aligned to the instrument’s VolumeStep, restricted by the security’s MinVolume and MaxVolume whenever those limits are available from the trading board.
Long and short state machines are fully separated, allowing the strategy to maintain hedged baskets when market direction alternates quickly.
The protective levels are recalculated on every fill and rounded to the nearest PriceStep, matching the frequent take-profit modification routine performed in the MetaTrader version.
No indicator buffers are used; all decisions are based on raw candle data and portfolio information, just like in the source EA.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Mission Impossible Power Two Open strategy: Candle direction with EMA trend filter.
/// Buys on bullish candle when above EMA, sells on bearish candle when below EMA.
/// </summary>
public class MissionImpossiblePowerTwoOpenStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaPeriod;
private bool _wasBullishSignal;
private bool _hasPrevSignal;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public MissionImpossiblePowerTwoOpenStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_emaPeriod = Param(nameof(EmaPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA trend filter period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_wasBullishSignal = false;
_hasPrevSignal = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_wasBullishSignal = false;
_hasPrevSignal = false;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(ema, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal emaValue)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
var open = candle.OpenPrice;
var bullish = close > open;
var bearish = close < open;
var bullishSignal = bullish && close > emaValue;
var bearishSignal = bearish && close < emaValue;
var crossedUp = bullishSignal && (!_hasPrevSignal || !_wasBullishSignal);
var crossedDown = bearishSignal && (!_hasPrevSignal || _wasBullishSignal);
if (crossedUp && Position <= 0)
BuyMarket();
else if (crossedDown && Position >= 0)
SellMarket();
if (bullishSignal || bearishSignal)
{
_wasBullishSignal = bullishSignal;
_hasPrevSignal = true;
}
}
}
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.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class mission_impossible_power_two_open_strategy(Strategy):
def __init__(self):
super(mission_impossible_power_two_open_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._ema_period = self.Param("EmaPeriod", 50)
self._was_bullish_signal = False
self._has_prev_signal = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def EmaPeriod(self):
return self._ema_period.Value
@EmaPeriod.setter
def EmaPeriod(self, value):
self._ema_period.Value = value
def OnReseted(self):
super(mission_impossible_power_two_open_strategy, self).OnReseted()
self._was_bullish_signal = False
self._has_prev_signal = False
def OnStarted2(self, time):
super(mission_impossible_power_two_open_strategy, self).OnStarted2(time)
self._was_bullish_signal = False
self._has_prev_signal = False
ema = ExponentialMovingAverage()
ema.Length = self.EmaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, self._process_candle).Start()
def _process_candle(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
open_price = float(candle.OpenPrice)
ema_val = float(ema_value)
bullish = close > open_price
bearish = close < open_price
bullish_signal = bullish and close > ema_val
bearish_signal = bearish and close < ema_val
crossed_up = bullish_signal and (not self._has_prev_signal or not self._was_bullish_signal)
crossed_down = bearish_signal and (not self._has_prev_signal or self._was_bullish_signal)
if crossed_up and self.Position <= 0:
self.BuyMarket()
elif crossed_down and self.Position >= 0:
self.SellMarket()
if bullish_signal or bearish_signal:
self._was_bullish_signal = bullish_signal
self._has_prev_signal = True
def CreateClone(self):
return mission_impossible_power_two_open_strategy()