Indicator Test with Conditions Table Strategy
This strategy compares the latest closing price with user-defined levels and executes market orders when the conditions are met. Each side (long and short) has separate entry and exit rules controlled by parameters.
Details
- Entry Criteria:
- Long: Enabled long condition is true.
- Short: Enabled short condition is true.
- Long/Short: Both sides.
- Exit Criteria:
- Long: Enabled close long condition is true.
- Short: Enabled close short condition is true.
- Stops: No.
- Default Values:
LongOperator=>CloseLongOperator=<ShortOperator=<CloseShortOperator=>
- Filters:
- Category: Other
- Direction: Both
- Indicators: None
- Stops: No
- Complexity: Simple
- Timeframe: Any
- Seasonality: No
- Neural networks: No
- Divergence: No
- Risk level: Medium
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Simple condition-based strategy.
/// Compares close price with user-defined values to open or close positions.
/// </summary>
public class IndicatorTestWithConditionsTableStrategy : Strategy
{
private readonly StrategyParam<bool> _enableLongCond;
private readonly StrategyParam<string> _longOperator;
private readonly StrategyParam<decimal> _longValue;
private readonly StrategyParam<bool> _enableCloseLongCond;
private readonly StrategyParam<string> _closeLongOperator;
private readonly StrategyParam<decimal> _closeLongValue;
private readonly StrategyParam<bool> _enableShortCond;
private readonly StrategyParam<string> _shortOperator;
private readonly StrategyParam<decimal> _shortValue;
private readonly StrategyParam<bool> _enableCloseShortCond;
private readonly StrategyParam<string> _closeShortOperator;
private readonly StrategyParam<decimal> _closeShortValue;
private readonly StrategyParam<DataType> _candleType;
/// <summary>
/// The type of candles used for processing.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Enable long entry condition.
/// </summary>
public bool EnableLongCond
{
get => _enableLongCond.Value;
set => _enableLongCond.Value = value;
}
/// <summary>
/// Operator for long entry.
/// </summary>
public string LongOperator
{
get => _longOperator.Value;
set => _longOperator.Value = value;
}
/// <summary>
/// Comparison value for long entry.
/// </summary>
public decimal LongValue
{
get => _longValue.Value;
set => _longValue.Value = value;
}
/// <summary>
/// Enable close long condition.
/// </summary>
public bool EnableCloseLongCond
{
get => _enableCloseLongCond.Value;
set => _enableCloseLongCond.Value = value;
}
/// <summary>
/// Operator for closing long position.
/// </summary>
public string CloseLongOperator
{
get => _closeLongOperator.Value;
set => _closeLongOperator.Value = value;
}
/// <summary>
/// Comparison value for closing long position.
/// </summary>
public decimal CloseLongValue
{
get => _closeLongValue.Value;
set => _closeLongValue.Value = value;
}
/// <summary>
/// Enable short entry condition.
/// </summary>
public bool EnableShortCond
{
get => _enableShortCond.Value;
set => _enableShortCond.Value = value;
}
/// <summary>
/// Operator for short entry.
/// </summary>
public string ShortOperator
{
get => _shortOperator.Value;
set => _shortOperator.Value = value;
}
/// <summary>
/// Comparison value for short entry.
/// </summary>
public decimal ShortValue
{
get => _shortValue.Value;
set => _shortValue.Value = value;
}
/// <summary>
/// Enable close short condition.
/// </summary>
public bool EnableCloseShortCond
{
get => _enableCloseShortCond.Value;
set => _enableCloseShortCond.Value = value;
}
/// <summary>
/// Operator for closing short position.
/// </summary>
public string CloseShortOperator
{
get => _closeShortOperator.Value;
set => _closeShortOperator.Value = value;
}
/// <summary>
/// Comparison value for closing short position.
/// </summary>
public decimal CloseShortValue
{
get => _closeShortValue.Value;
set => _closeShortValue.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public IndicatorTestWithConditionsTableStrategy()
{
_enableLongCond = Param(nameof(EnableLongCond), true)
.SetDisplay("Enable Long Condition", "Enable long entry condition.", "Long Entry");
_longOperator = Param(nameof(LongOperator), ">")
.SetDisplay("Long Operator", "Operator for long entry.", "Long Entry");
_longValue = Param(nameof(LongValue), 0m)
.SetDisplay("Long Value", "Comparison value for long entry.", "Long Entry");
_enableCloseLongCond = Param(nameof(EnableCloseLongCond), false)
.SetDisplay("Enable Close Long", "Enable close long condition.", "Close Long");
_closeLongOperator = Param(nameof(CloseLongOperator), "<")
.SetDisplay("Close Long Operator", "Operator for closing long.", "Close Long");
_closeLongValue = Param(nameof(CloseLongValue), 0m)
.SetDisplay("Close Long Value", "Value for closing long.", "Close Long");
_enableShortCond = Param(nameof(EnableShortCond), false)
.SetDisplay("Enable Short Condition", "Enable short entry condition.", "Short Entry");
_shortOperator = Param(nameof(ShortOperator), "<")
.SetDisplay("Short Operator", "Operator for short entry.", "Short Entry");
_shortValue = Param(nameof(ShortValue), 0m)
.SetDisplay("Short Value", "Comparison value for short entry.", "Short Entry");
_enableCloseShortCond = Param(nameof(EnableCloseShortCond), false)
.SetDisplay("Enable Close Short", "Enable close short condition.", "Close Short");
_closeShortOperator = Param(nameof(CloseShortOperator), ">")
.SetDisplay("Close Short Operator", "Operator for closing short.", "Close Short");
_closeShortValue = Param(nameof(CloseShortValue), 0m)
.SetDisplay("Close Short Value", "Value for closing short.", "Close Short");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candle type for strategy.", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
var longEntry = _enableLongCond.Value && CheckCondition(close, _longOperator.Value, _longValue.Value);
var closeLong = _enableCloseLongCond.Value && CheckCondition(close, _closeLongOperator.Value, _closeLongValue.Value);
var shortEntry = _enableShortCond.Value && CheckCondition(close, _shortOperator.Value, _shortValue.Value);
var closeShort = _enableCloseShortCond.Value && CheckCondition(close, _closeShortOperator.Value, _closeShortValue.Value);
if (closeLong && Position > 0)
SellMarket();
else if (closeShort && Position < 0)
BuyMarket();
else if (longEntry && Position <= 0)
BuyMarket();
else if (shortEntry && Position >= 0)
SellMarket();
}
private static bool CheckCondition(decimal left, string op, decimal right)
{
return op switch
{
">" => left > right,
"<" => left < right,
">=" => left >= right,
"<=" => left <= right,
"=" => left == right,
"!=" => left != right,
_ => false
};
}
}
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
class indicator_test_with_conditions_table_strategy(Strategy):
def __init__(self):
super(indicator_test_with_conditions_table_strategy, self).__init__()
self._enable_long_cond = self.Param("EnableLongCond", True) \
.SetDisplay("Enable Long Condition", "Enable long entry condition", "Long Entry")
self._long_operator = self.Param("LongOperator", ">") \
.SetDisplay("Long Operator", "Operator for long entry", "Long Entry")
self._long_value = self.Param("LongValue", 0.0) \
.SetDisplay("Long Value", "Comparison value for long entry", "Long Entry")
self._enable_close_long_cond = self.Param("EnableCloseLongCond", False) \
.SetDisplay("Enable Close Long", "Enable close long condition", "Close Long")
self._close_long_operator = self.Param("CloseLongOperator", "<") \
.SetDisplay("Close Long Operator", "Operator for closing long", "Close Long")
self._close_long_value = self.Param("CloseLongValue", 0.0) \
.SetDisplay("Close Long Value", "Value for closing long", "Close Long")
self._enable_short_cond = self.Param("EnableShortCond", False) \
.SetDisplay("Enable Short Condition", "Enable short entry condition", "Short Entry")
self._short_operator = self.Param("ShortOperator", "<") \
.SetDisplay("Short Operator", "Operator for short entry", "Short Entry")
self._short_value = self.Param("ShortValue", 0.0) \
.SetDisplay("Short Value", "Comparison value for short entry", "Short Entry")
self._enable_close_short_cond = self.Param("EnableCloseShortCond", False) \
.SetDisplay("Enable Close Short", "Enable close short condition", "Close Short")
self._close_short_operator = self.Param("CloseShortOperator", ">") \
.SetDisplay("Close Short Operator", "Operator for closing short", "Close Short")
self._close_short_value = self.Param("CloseShortValue", 0.0) \
.SetDisplay("Close Short Value", "Value for closing short", "Close Short")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60))) \
.SetDisplay("Candle Type", "Candle type for strategy", "General")
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
def OnStarted2(self, time):
super(indicator_test_with_conditions_table_strategy, self).OnStarted2(time)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self.OnProcess).Start()
def _check_condition(self, left, op, right):
if op == ">":
return left > right
elif op == "<":
return left < right
elif op == ">=":
return left >= right
elif op == "<=":
return left <= right
elif op == "=":
return left == right
elif op == "!=":
return left != right
return False
def OnProcess(self, candle):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
long_entry = self._enable_long_cond.Value and self._check_condition(close, str(self._long_operator.Value), float(self._long_value.Value))
close_long = self._enable_close_long_cond.Value and self._check_condition(close, str(self._close_long_operator.Value), float(self._close_long_value.Value))
short_entry = self._enable_short_cond.Value and self._check_condition(close, str(self._short_operator.Value), float(self._short_value.Value))
close_short = self._enable_close_short_cond.Value and self._check_condition(close, str(self._close_short_operator.Value), float(self._close_short_value.Value))
if close_long and self.Position > 0:
self.SellMarket()
elif close_short and self.Position < 0:
self.BuyMarket()
elif long_entry and self.Position <= 0:
self.BuyMarket()
elif short_entry and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return indicator_test_with_conditions_table_strategy()