Pineconnector Strategy Template
This strategy demonstrates how to connect any indicator to generate trading signals. It uses two moving averages as an example and enters long when the fast average crosses above the slow average, and enters short on the opposite cross.
Parameters
- Fast Length – period of the fast moving average.
- Slow Length – period of the slow moving average.
- Candle Type – candle type for calculation.
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>
/// Template strategy demonstrating how to connect any indicator and trade on its signals.
/// Uses two exponential moving averages as an example indicator.
/// </summary>
public class PineconnectorTemplateStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<DataType> _candleType;
/// <summary>
/// Fast MA period length.
/// </summary>
public int FastLength
{
get => _fastLength.Value;
set => _fastLength.Value = value;
}
/// <summary>
/// Slow MA period length.
/// </summary>
public int SlowLength
{
get => _slowLength.Value;
set => _slowLength.Value = value;
}
/// <summary>
/// The type of candles to use for strategy calculation.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initializes a new instance of the strategy.
/// </summary>
public PineconnectorTemplateStrategy()
{
_fastLength = Param(nameof(FastLength), 14)
.SetGreaterThanZero()
.SetDisplay("Fast MA Length", "Period of the fast moving average", "MA Settings")
.SetOptimize(5, 20, 5);
_slowLength = Param(nameof(SlowLength), 40)
.SetGreaterThanZero()
.SetDisplay("Slow MA Length", "Period of the slow moving average", "MA Settings")
.SetOptimize(50, 200, 10);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastMa = new ExponentialMovingAverage { Length = FastLength };
var slowMa = new ExponentialMovingAverage { Length = SlowLength };
var prevF = 0m;
var prevS = 0m;
var init = false;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastMa, slowMa, (candle, f, s) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!fastMa.IsFormed || !slowMa.IsFormed)
return;
if (!init)
{
prevF = f;
prevS = s;
init = true;
return;
}
if (prevF <= prevS && f > s && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (prevF >= prevS && f < s && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
prevF = f;
prevS = s;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastMa);
DrawIndicator(area, slowMa);
DrawOwnTrades(area);
}
}
}
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 pineconnector_template_strategy(Strategy):
def __init__(self):
super(pineconnector_template_strategy, self).__init__()
self._fast_length = self.Param("FastLength", 14) \
.SetGreaterThanZero()
self._slow_length = self.Param("SlowLength", 40) \
.SetGreaterThanZero()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5)))
self._prev_fast = 0.0
self._prev_slow = 0.0
self._initialized = False
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(pineconnector_template_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._initialized = False
def OnStarted2(self, time):
super(pineconnector_template_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._initialized = False
self._fast = ExponentialMovingAverage()
self._fast.Length = self._fast_length.Value
self._slow = ExponentialMovingAverage()
self._slow.Length = self._slow_length.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._fast, self._slow, self.OnProcess).Start()
def OnProcess(self, candle, f, s):
if candle.State != CandleStates.Finished:
return
if not self._fast.IsFormed or not self._slow.IsFormed:
return
if not self._initialized:
self._prev_fast = f
self._prev_slow = s
self._initialized = True
return
if self._prev_fast <= self._prev_slow and f > s and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif self._prev_fast >= self._prev_slow and f < s and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
self._prev_fast = f
self._prev_slow = s
def CreateClone(self):
return pineconnector_template_strategy()