Estratégia de Inteligência Artificial Perceptron
Esta estratégia usa os valores do Accelerator Oscillator (AC) como entradas de um perceptron linear simples. Quatro leituras de AC espaçadas sete barras são ponderadas por coeficientes definidos pelo usuário. Uma saída positiva do perceptron abre uma posição comprada, e uma saída negativa abre uma posição vendida.
A estratégia sempre aplica um stop-loss. Se um sinal oposto aparecer depois que o lucro ultrapassar o dobro do stop-loss, a posição é revertida com volume aumentado. Caso contrário, o stop-loss é movido para o ponto de equilíbrio.
Detalhes
- Critérios de entrada:
- Comprado: Saída do perceptron > 0.
- Vendido: Saída do perceptron < 0.
- Comprado/Vendido: Ambos.
- Critérios de saída:
- Sinal oposto com lucro > 2 * StopLoss → reversão.
- Sinal oposto com lucro menor → stop movido para a entrada.
- Stop-loss atingido.
- Stops: Stop-loss fixo em pontos.
- Filtros: Nenhum.
Parâmetros
StopLoss– distância do stop-loss em pontos (padrão 850).Shift– deslocamento de barra para valores do indicador (padrão 1).X1,X2,X3,X4– pesos do perceptron.CandleType– período de velas.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Perceptron strategy driven by four Accelerator Oscillator samples spaced seven bars apart.
/// </summary>
public class ArtificialIntelligencePerceptronStrategy : Strategy
{
private readonly StrategyParam<decimal> _stopLoss;
private readonly StrategyParam<int> _shift;
private readonly StrategyParam<decimal> _x1;
private readonly StrategyParam<decimal> _x2;
private readonly StrategyParam<decimal> _x3;
private readonly StrategyParam<decimal> _x4;
private readonly StrategyParam<DataType> _candleType;
private readonly List<decimal> _median = [];
private readonly List<decimal> _ao = [];
private readonly List<decimal> _ac = [];
private decimal _entryPrice;
private decimal? _stopPrice;
public decimal StopLoss { get => _stopLoss.Value; set => _stopLoss.Value = value; }
public int Shift { get => _shift.Value; set => _shift.Value = value; }
public decimal X1 { get => _x1.Value; set => _x1.Value = value; }
public decimal X2 { get => _x2.Value; set => _x2.Value = value; }
public decimal X3 { get => _x3.Value; set => _x3.Value = value; }
public decimal X4 { get => _x4.Value; set => _x4.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ArtificialIntelligencePerceptronStrategy()
{
_stopLoss = Param(nameof(StopLoss), 850m).SetGreaterThanZero()
.SetDisplay("Stop Loss", "Stop distance in price steps.", "Risk");
_shift = Param(nameof(Shift), 1).SetNotNegative()
.SetDisplay("Shift", "Latest AC sample shift.", "Perceptron");
_x1 = Param(nameof(X1), 1m).SetDisplay("X1", "Weight for the newest AC sample.", "Perceptron");
_x2 = Param(nameof(X2), 1m).SetDisplay("X2", "Weight for AC sample 7 bars older.", "Perceptron");
_x3 = Param(nameof(X3), 1m).SetDisplay("X3", "Weight for AC sample 14 bars older.", "Perceptron");
_x4 = Param(nameof(X4), 1m).SetDisplay("X4", "Weight for AC sample 21 bars older.", "Perceptron");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe.", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_median.Clear();
_ao.Clear();
_ac.Clear();
_entryPrice = 0m;
_stopPrice = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
SubscribeCandles(CandleType).Bind(ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var median = (candle.HighPrice + candle.LowPrice) / 2m;
_median.Add(median);
if (_median.Count < 34)
return;
var ao = AverageTail(_median, 5) - AverageTail(_median, 34);
_ao.Add(ao);
if (_ao.Count < 5)
return;
var ac = ao - AverageTail(_ao, 5);
_ac.Add(ac);
if (ApplyStop(candle))
return;
var newest = _ac.Count - 1 - Shift;
if (newest - 21 < 0)
return;
var output =
X1 * _ac[newest] +
X2 * _ac[newest - 7] +
X3 * _ac[newest - 14] +
X4 * _ac[newest - 21];
var signal = output > 0m ? 1 : output < 0m ? -1 : 0;
if (signal == 0)
return;
var step = Security?.PriceStep ?? 1m;
if (step <= 0m)
step = 1m;
var stopDistance = StopLoss * step;
if (Position == 0)
{
Enter(signal, Volume, candle.ClosePrice, stopDistance);
return;
}
var currentDirection = Position > 0 ? 1 : -1;
if (signal == currentDirection)
return;
var profitDistance = currentDirection > 0
? candle.ClosePrice - _entryPrice
: _entryPrice - candle.ClosePrice;
if (profitDistance > stopDistance * 2m)
{
// Reverse and increase the new exposure to twice the base volume.
var orderVolume = Math.Abs(Position) + Volume * 2m;
if (signal > 0)
BuyMarket(orderVolume);
else
SellMarket(orderVolume);
_entryPrice = candle.ClosePrice;
_stopPrice = signal > 0 ? _entryPrice - stopDistance : _entryPrice + stopDistance;
}
else
{
// Opposite signal without enough profit: protect the current trade at break-even.
_stopPrice = _entryPrice;
}
}
private bool ApplyStop(ICandleMessage candle)
{
if (Position > 0 && _stopPrice is decimal longStop && candle.LowPrice <= longStop)
{
SellMarket(Math.Abs(Position));
_entryPrice = 0m;
_stopPrice = null;
return true;
}
else if (Position < 0 && _stopPrice is decimal shortStop && candle.HighPrice >= shortStop)
{
BuyMarket(Math.Abs(Position));
_entryPrice = 0m;
_stopPrice = null;
return true;
}
return false;
}
private void Enter(int signal, decimal volume, decimal price, decimal stopDistance)
{
if (signal > 0)
BuyMarket(volume);
else
SellMarket(volume);
_entryPrice = price;
_stopPrice = signal > 0 ? price - stopDistance : price + stopDistance;
}
private static decimal AverageTail(List<decimal> values, int count)
{
var start = values.Count - count;
var sum = 0m;
for (var i = start; i < values.Count; i++)
sum += values[i];
return sum / count;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Strategies import Strategy
class artificial_intelligence_perceptron_strategy(Strategy):
def __init__(self):
super(artificial_intelligence_perceptron_strategy, self).__init__()
self._stop_loss = self.Param("StopLoss", 850.0).SetGreaterThanZero()
self._shift = self.Param("Shift", 1).SetNotNegative()
self._x1 = self.Param("X1", 1.0)
self._x2 = self.Param("X2", 1.0)
self._x3 = self.Param("X3", 1.0)
self._x4 = self.Param("X4", 1.0)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4)))
self._median = []
self._ao = []
self._ac = []
self._entry_price = 0.0
self._stop_price = None
@property
def CandleType(self):
return self._candle_type.Value
def GetWorkingSecurities(self):
return [(self.Security, self.CandleType)]
def OnReseted(self):
super(artificial_intelligence_perceptron_strategy, self).OnReseted()
self._median = []
self._ao = []
self._ac = []
self._entry_price = 0.0
self._stop_price = None
def OnStarted2(self, time):
super(artificial_intelligence_perceptron_strategy, self).OnStarted2(time)
self.SubscribeCandles(self.CandleType).Bind(self._process_candle).Start()
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
median = (float(candle.HighPrice) + float(candle.LowPrice)) / 2.0
self._median.append(median)
if len(self._median) < 34:
return
ao = self._avg_tail(self._median, 5) - self._avg_tail(self._median, 34)
self._ao.append(ao)
if len(self._ao) < 5:
return
ac = ao - self._avg_tail(self._ao, 5)
self._ac.append(ac)
if self._apply_stop(candle):
return
newest = len(self._ac) - 1 - int(self._shift.Value)
if newest - 21 < 0:
return
output = (
float(self._x1.Value) * self._ac[newest] +
float(self._x2.Value) * self._ac[newest - 7] +
float(self._x3.Value) * self._ac[newest - 14] +
float(self._x4.Value) * self._ac[newest - 21]
)
signal = 1 if output > 0 else (-1 if output < 0 else 0)
if signal == 0:
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:
step = 1.0
stop_distance = float(self._stop_loss.Value) * step
close = float(candle.ClosePrice)
if self.Position == 0:
self._enter(signal, float(self.Volume), close, stop_distance)
return
current_direction = 1 if self.Position > 0 else -1
if signal == current_direction:
return
profit_distance = close - self._entry_price if current_direction > 0 else self._entry_price - close
if profit_distance > stop_distance * 2.0:
order_volume = abs(float(self.Position)) + float(self.Volume) * 2.0
if signal > 0:
self.BuyMarket(order_volume)
else:
self.SellMarket(order_volume)
self._entry_price = close
self._stop_price = close - stop_distance if signal > 0 else close + stop_distance
else:
self._stop_price = self._entry_price
def _apply_stop(self, candle):
if self.Position > 0 and self._stop_price is not None and float(candle.LowPrice) <= self._stop_price:
self.SellMarket(Math.Abs(self.Position))
self._entry_price = 0.0
self._stop_price = None
return True
elif self.Position < 0 and self._stop_price is not None and float(candle.HighPrice) >= self._stop_price:
self.BuyMarket(Math.Abs(self.Position))
self._entry_price = 0.0
self._stop_price = None
return True
return False
def _enter(self, signal, volume, price, stop_distance):
if signal > 0:
self.BuyMarket(volume)
else:
self.SellMarket(volume)
self._entry_price = price
self._stop_price = price - stop_distance if signal > 0 else price + stop_distance
@staticmethod
def _avg_tail(values, count):
return sum(values[-count:]) / float(count)
def CreateClone(self):
return artificial_intelligence_perceptron_strategy()