Very Blondie System 是一个短线均值回归网格策略,原始版本是 MetaTrader 4 上的 "VBS - Very Blondie System" 智能交易系统。移植版完全保留了原有思想:一旦价格远离最近 PeriodX 根 K 线的区间极值,策略立即用市价单入场,并在趋势继续延伸时通过四个加倍的限价单逐级加仓。
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Mean reversion strategy that trades when price deviates from a range channel.
/// Buys at lower channel, sells at upper channel, exits at channel midpoint.
/// </summary>
public class VeryBlondieSystemStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _periodLength;
public VeryBlondieSystemStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for analysis.", "General");
_periodLength = Param(nameof(PeriodLength), 30)
.SetDisplay("Period Length", "Period for Highest/Lowest channel.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int PeriodLength
{
get => _periodLength.Value;
set => _periodLength.Value = value;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var highest = new Highest { Length = PeriodLength };
var lowest = new Lowest { Length = PeriodLength };
var sma = new SimpleMovingAverage { Length = PeriodLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(highest, lowest, sma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal highestValue, decimal lowestValue, decimal smaValue)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
var range = highestValue - lowestValue;
if (range <= 0)
return;
// Percentage position within channel
var position = (close - lowestValue) / range;
// Exit conditions: revert to mean
if (Position > 0 && close >= smaValue)
{
SellMarket();
}
else if (Position < 0 && close <= smaValue)
{
BuyMarket();
}
// Entry: at channel extremes
if (Position == 0)
{
if (position < 0.15m)
{
// Near lower channel - buy for mean reversion
BuyMarket();
}
else if (position > 0.85m)
{
// Near upper channel - sell for mean reversion
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 Highest, Lowest, SimpleMovingAverage
class very_blondie_system_strategy(Strategy):
def __init__(self):
super(very_blondie_system_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe for analysis", "General")
self._period_length = self.Param("PeriodLength", 30) \
.SetDisplay("Period Length", "Period for Highest/Lowest channel", "Indicators")
@property
def CandleType(self):
return self._candle_type.Value
@property
def PeriodLength(self):
return self._period_length.Value
def OnStarted2(self, time):
super(very_blondie_system_strategy, self).OnStarted2(time)
self._highest = Highest()
self._highest.Length = self.PeriodLength
self._lowest = Lowest()
self._lowest.Length = self.PeriodLength
self._sma = SimpleMovingAverage()
self._sma.Length = self.PeriodLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._highest, self._lowest, self._sma, self.ProcessCandle).Start()
def ProcessCandle(self, candle, highest_value, lowest_value, sma_value):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
high_val = float(highest_value)
low_val = float(lowest_value)
sma_val = float(sma_value)
rng = high_val - low_val
if rng <= 0:
return
position_pct = (close - low_val) / rng
# Exit conditions: revert to mean
if self.Position > 0 and close >= sma_val:
self.SellMarket()
elif self.Position < 0 and close <= sma_val:
self.BuyMarket()
# Entry: at channel extremes
if self.Position == 0:
if position_pct < 0.15:
self.BuyMarket()
elif position_pct > 0.85:
self.SellMarket()
def OnReseted(self):
super(very_blondie_system_strategy, self).OnReseted()
def CreateClone(self):
return very_blondie_system_strategy()