This strategy is a StockSharp conversion of the MetaTrader expert advisor N7S_AO_772012. The original robot combines perceptron-like filters of the Awesome Oscillator (AO) across several timeframes with a price pattern gate and a configurable "neuro" mode that can override the base logic. The converted version preserves the decision tree while exposing all tuning knobs as strategy parameters.
The bot operates on the primary instrument selected in the strategy and uses:
M1 candles for entry timing and the price perceptron.
H1 candles to feed multiple AO-based perceptrons.
H4 candles to compute the AO momentum delta used by the base Buy/Sell selector (BTS).
Trading logic
On each finished M1 candle the strategy updates the price pattern history, manages existing positions, and evaluates whether trading is allowed (no trading on Monday before 02:00 or on Friday from 18:00 and later, platform local time).
Hourly AO values are aggregated into five perceptrons:
Perceptron X/Y – base BTS filters that work together with the price perceptron and H4 AO delta.
Neuro X/Y – advanced long/short filters used when the neuro mode grants priority to them.
Neuro Z – gating perceptron that enables Neuro X in mode 4.
The price perceptron evaluates the weighted differences between recent M1 opens and the latest close.
The neuro mode parameter controls how the uppercase perceptrons intervene:
4: If Neuro Z > 0, only Neuro X can generate a long signal; otherwise Neuro Y can trigger a short. If neither fires, fall back to BTS.
3: Neuro Y can trigger shorts; otherwise fall back to BTS.
2: Neuro X can trigger longs; otherwise fall back to BTS.
Any other value skips the neuro layer and directly evaluates BTS.
The BTS block uses the price perceptron and H4 AO delta as gates:
Long setup: price perceptron > 0 (unless BtsMode = 0), Neuro/BTS X > 0 and H4 AO delta > 0. Stop-loss is BaseStopLossPointsLong, take-profit is BaseTakeProfitFactorLong × BaseStopLossPointsLong.
Short setup: price perceptron < 0 (unless BtsMode = 0), Neuro/BTS Y > 0 and H4 AO delta < 0. Stop-loss is BaseStopLossPointsShort, take-profit is BaseTakeProfitFactorShort × BaseStopLossPointsShort.
After a signal is accepted the strategy opens a market order (respecting the enabled direction). Protective prices are tracked internally; every finished M1 candle checks whether the stop or target was hit using candle highs/lows and closes the position when appropriate. Opposite signals first close the existing position and wait for the next candle before re-entry.
Parameters
Trading
OrderVolume – Base volume for all market orders.
AllowLongTrades / AllowShortTrades – Enable or disable long or short entries.
BtsMode – When set to 0 the price perceptron gate in BTS is ignored; otherwise its sign must align with the trade.
NeuroMode – Selects how the advanced perceptrons participate (see logic section).
Base BTS perceptrons
BaseStopLossPointsLong / BaseTakeProfitFactorLong – Stop distance (points) and multiplier for long take-profit.
BaseStopLossPointsShort / BaseTakeProfitFactorShort – Analogous settings for short trades.
PerceptronPeriodX / Y – AO shift (in H1 bars) used by the respective perceptron.
PerceptronWeightX1..4 / Y1..4 – Weights (0–100) of the perceptron inputs; internally they are centred by subtracting 50.
PerceptronThresholdX / Y – Minimum absolute perceptron output required before it is considered valid.
Price filter
PricePatternPeriod – Number of M1 candles forming each lag in the price perceptron.
PriceWeight1..4 – Weights (centred around 50) applied to price differences inside the perceptron.
Neuro perceptrons
NeuroStopLossPointsLong / NeuroTakeProfitFactorLong – Stop and TP multiplier used by Neuro X signals.
NeuroStopLossPointsShort / NeuroTakeProfitFactorShort – Stop and TP multiplier used by Neuro Y signals.
NeuroPeriodX / Y / Z – AO shift (H1 candles) for the three neuro perceptrons.
NeuroThresholdX / NeuroThresholdY / NeuroThresholdZ – Minimum absolute value for each neuro perceptron.
Data
CandleType – Timeframe used for the primary trading candles (default 1 minute).
Trade management
Stop-loss and take-profit distances are converted from points to absolute prices using the instrument price step. If a distance is set to zero, the corresponding protection is disabled.
Protective levels are monitored on completed M1 candles by comparing candle highs/lows to the stored prices.
The strategy works in netting mode: it never holds both long and short positions simultaneously. An opposite signal closes the current position first.
Notes on the conversion
High level StockSharp bindings (SubscribeCandles().Bind(...)) are used to stream AO values without direct indicator queries.
Historical buffers are kept as fixed-size lists to emulate the original shift-based indexing while avoiding direct indicator lookups.
No Python version is provided, as requested.
Tests were not modified.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Perceptron-based strategy using Awesome Oscillator values at different lookback periods.
/// Combines weighted AO signals with price pattern confirmation for entry/exit decisions.
/// </summary>
public class N7SAo772012Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _aoPeriod;
private readonly StrategyParam<int> _lookback;
private readonly List<decimal> _aoHistory = new();
private decimal _entryPrice;
public N7SAo772012Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(2).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for analysis.", "General");
_aoPeriod = Param(nameof(AoPeriod), 5)
.SetDisplay("AO Period", "Period for the Awesome Oscillator.", "Indicators");
_lookback = Param(nameof(Lookback), 3)
.SetDisplay("Lookback", "Number of AO values to look back for signal.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int AoPeriod
{
get => _aoPeriod.Value;
set => _aoPeriod.Value = value;
}
public int Lookback
{
get => _lookback.Value;
set => _lookback.Value = value;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_aoHistory.Clear();
_entryPrice = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ao = new AwesomeOscillator();
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ao, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ao);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal aoValue)
{
if (candle.State != CandleStates.Finished)
return;
_aoHistory.Add(aoValue);
if (_aoHistory.Count > 50)
_aoHistory.RemoveAt(0);
if (_aoHistory.Count < Lookback + 1)
return;
var close = candle.ClosePrice;
var current = _aoHistory[_aoHistory.Count - 1];
var prev = _aoHistory[_aoHistory.Count - 1 - Lookback];
// AO momentum: current vs lookback periods ago
var rising = current > prev && current > 0;
var falling = current < prev && current < 0;
// Manage positions
if (Position > 0)
{
// Exit long if AO turns negative or stop-loss
if (current < 0 || (_entryPrice > 0 && close < _entryPrice * 0.98m))
{
SellMarket();
}
}
else if (Position < 0)
{
// Exit short if AO turns positive or stop-loss
if (current > 0 || (_entryPrice > 0 && close > _entryPrice * 1.02m))
{
BuyMarket();
}
}
// Entry
if (Position == 0)
{
if (rising)
{
_entryPrice = close;
BuyMarket();
}
else if (falling)
{
_entryPrice = close;
SellMarket();
}
}
}
}
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 AwesomeOscillator
class n7_s_ao772012_strategy(Strategy):
def __init__(self):
super(n7_s_ao772012_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(2))) \
.SetDisplay("Candle Type", "Timeframe for analysis", "General")
self._ao_period = self.Param("AoPeriod", 5) \
.SetDisplay("AO Period", "Period for the Awesome Oscillator", "Indicators")
self._lookback = self.Param("Lookback", 3) \
.SetDisplay("Lookback", "Number of AO values to look back for signal", "Indicators")
self._ao_history = []
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@property
def AoPeriod(self):
return self._ao_period.Value
@property
def Lookback(self):
return self._lookback.Value
def OnStarted2(self, time):
super(n7_s_ao772012_strategy, self).OnStarted2(time)
self._ao_history = []
self._entry_price = 0.0
self._ao = AwesomeOscillator()
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._ao, self.ProcessCandle).Start()
def ProcessCandle(self, candle, ao_value):
if candle.State != CandleStates.Finished:
return
ao_val = float(ao_value)
self._ao_history.append(ao_val)
if len(self._ao_history) > 50:
self._ao_history.pop(0)
lookback = self.Lookback
if len(self._ao_history) < lookback + 1:
return
close = float(candle.ClosePrice)
current = self._ao_history[-1]
prev = self._ao_history[-1 - lookback]
rising = current > prev and current > 0
falling = current < prev and current < 0
# Manage positions
if self.Position > 0:
if current < 0 or (self._entry_price > 0 and close < self._entry_price * 0.98):
self.SellMarket()
elif self.Position < 0:
if current > 0 or (self._entry_price > 0 and close > self._entry_price * 1.02):
self.BuyMarket()
# Entry
if self.Position == 0:
if rising:
self._entry_price = close
self.BuyMarket()
elif falling:
self._entry_price = close
self.SellMarket()
def OnReseted(self):
super(n7_s_ao772012_strategy, self).OnReseted()
self._ao_history = []
self._entry_price = 0.0
def CreateClone(self):
return n7_s_ao772012_strategy()