ASCtrend Strategy
This strategy uses the Williams %R indicator to detect rapid reversals similar to the ASCtrend approach. It sells when the indicator rises from an oversold level to an overbought level and buys when the opposite occurs.
Details
- Entry Criteria:
- Sell when Williams %R crosses from oversold (below
x2) to overbought (abovex1). - Buy when Williams %R crosses from overbought (above
x1) to oversold (belowx2).
- Sell when Williams %R crosses from oversold (below
- Long/Short: Both.
- Exit Criteria:
- Reverse signal closes and flips the position.
- Stops: No.
- Default Values:
Risk= 4CandleType= 1 hour
- Filters:
- Category: Reversal
- Direction: Both
- Indicators: Williams %R
- Stops: No
- Complexity: Low
- Timeframe: Any
- Seasonality: No
- Neural networks: No
- Divergence: No
- Risk level: Medium
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// ASCtrend strategy based on Williams %R reversals.
/// </summary>
public class ASCtrendStrategy : Strategy
{
private readonly StrategyParam<int> _risk;
private readonly StrategyParam<DataType> _candleType;
private bool _wasOversold;
private bool _wasOverbought;
/// <summary>
/// Risk factor that adjusts threshold levels.
/// </summary>
public int Risk
{
get => _risk.Value;
set => _risk.Value = value;
}
/// <summary>
/// Candle type used by the strategy.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initialize the strategy.
/// </summary>
public ASCtrendStrategy()
{
_risk = Param(nameof(Risk), 4)
.SetRange(1, 50)
.SetDisplay("Risk", "Risk parameter", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_wasOversold = false;
_wasOverbought = false;
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var wpr = new WilliamsR
{
Length = 3 + Risk * 2
};
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(wpr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, wpr);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal wpr)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var value2 = 100m - Math.Abs(wpr);
var x1 = 67m + Risk;
var x2 = 33m - Risk;
if (value2 < x2)
_wasOversold = true;
else if (value2 > x1)
_wasOverbought = true;
if (_wasOversold && value2 > x1 && Position >= 0)
{
SellMarket();
_wasOversold = false;
_wasOverbought = false;
return;
}
if (_wasOverbought && value2 < x2 && Position <= 0)
{
BuyMarket();
_wasOversold = false;
_wasOverbought = 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.Indicators import WilliamsR
from StockSharp.Algo.Strategies import Strategy
class asc_trend_strategy(Strategy):
def __init__(self):
super(asc_trend_strategy, self).__init__()
self._risk = self.Param("Risk", 4) \
.SetDisplay("Risk", "Risk parameter", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._was_oversold = False
self._was_overbought = False
@property
def risk(self):
return self._risk.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(asc_trend_strategy, self).OnReseted()
self._was_oversold = False
self._was_overbought = False
def OnStarted2(self, time):
super(asc_trend_strategy, self).OnStarted2(time)
wpr = WilliamsR()
wpr.Length = 3 + self.risk * 2
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(wpr, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, wpr)
self.DrawOwnTrades(area)
def process_candle(self, candle, wpr_val):
if candle.State != CandleStates.Finished:
return
wpr_val = float(wpr_val)
value2 = 100.0 - abs(wpr_val)
x1 = 67.0 + float(self.risk)
x2 = 33.0 - float(self.risk)
if value2 < x2:
self._was_oversold = True
elif value2 > x1:
self._was_overbought = True
if self._was_oversold and value2 > x1 and self.Position >= 0:
self.SellMarket()
self._was_oversold = False
self._was_overbought = False
return
if self._was_overbought and value2 < x2 and self.Position <= 0:
self.BuyMarket()
self._was_oversold = False
self._was_overbought = False
def CreateClone(self):
return asc_trend_strategy()