TCPivot Stop 策略
该策略交易日内枢轴线的突破。枢轴点按照经典交易员公式,用前一日的最高价、最低价和收盘价计算。当收盘价向上突破枢轴线时开多单;当收盘价向下突破枢轴线时开空单。
进场后系统将某个支撑或阻力位同时用作止盈和止损。具体使用哪个级别由 Target Level 参数决定:
- 1 – 使用
Support1/Resistance1。 - 2 – 使用
Support2/Resistance2。 - 3 – 使用
Support3/Resistance3。
如果启用 Intraday Only,所有持仓将在平台时间 23:00 被平仓。
细节
- 入场条件
- 多头:上一根收盘价 ≤ 枢轴 && 当前收盘价 > 枢轴。
- 空头:上一根收盘价 ≥ 枢轴 && 当前收盘价 < 枢轴。
- 出场条件
- 多头:收盘价 ≥ 选定阻力位或收盘价 ≤ 选定支撑位。
- 空头:收盘价 ≤ 选定支撑位或收盘价 ≥ 选定阻力位。
- 若启用 Intraday Only,所有仓位在 23:00 平仓。
- 指标:仅使用枢轴点计算。
- 时间框架:可配置,默认 5 分钟K线。
- 止损:基于所选枢轴级别的止损和止盈。
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Pivot-based breakout strategy.
/// Buys when close crosses above calculated pivot, sells when it crosses below.
/// Uses support/resistance levels for exits.
/// </summary>
public class TcpPivotStopStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private decimal _pivot;
private decimal _res1, _sup1;
private decimal _prevClose;
private decimal _prevHigh;
private decimal _prevLow;
private int _barCount;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public TcpPivotStopStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Time frame", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_pivot = _res1 = _sup1 = 0;
_prevClose = _prevHigh = _prevLow = 0;
_barCount = 0;
}
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;
_barCount++;
// Recalculate pivot every 12 bars (~2 days for 4h candles)
if (_barCount % 12 == 0 && _prevHigh > 0)
{
_pivot = (_prevHigh + _prevLow + _prevClose) / 3m;
_res1 = 2m * _pivot - _prevLow;
_sup1 = 2m * _pivot - _prevHigh;
}
_prevHigh = candle.HighPrice;
_prevLow = candle.LowPrice;
var close = candle.ClosePrice;
if (_pivot > 0 && _prevClose > 0)
{
// Cross above pivot => long
if (_prevClose <= _pivot && close > _pivot && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
// Cross below pivot => short
else if (_prevClose >= _pivot && close < _pivot && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
// Exit long at resistance or support
else if (Position > 0 && (close >= _res1 || close <= _sup1))
{
SellMarket();
}
// Exit short at support or resistance
else if (Position < 0 && (close <= _sup1 || close >= _res1))
{
BuyMarket();
}
}
_prevClose = close;
}
}
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 tcp_pivot_stop_strategy(Strategy):
"""Pivot-based breakout with support/resistance exits."""
def __init__(self):
super(tcp_pivot_stop_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).SetDisplay("Candle Type", "Time frame", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(tcp_pivot_stop_strategy, self).OnReseted()
self._pivot = 0
self._res1 = 0
self._sup1 = 0
self._prev_close = 0
self._prev_high = 0
self._prev_low = 0
self._bar_count = 0
def OnStarted2(self, time):
super(tcp_pivot_stop_strategy, self).OnStarted2(time)
self._pivot = 0
self._res1 = 0
self._sup1 = 0
self._prev_close = 0
self._prev_high = 0
self._prev_low = 0
self._bar_count = 0
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawOwnTrades(area)
def OnProcess(self, candle):
if candle.State != CandleStates.Finished:
return
self._bar_count += 1
high = float(candle.HighPrice)
low = float(candle.LowPrice)
close = float(candle.ClosePrice)
# Recalculate pivot every 12 bars
if self._bar_count % 12 == 0 and self._prev_high > 0:
self._pivot = (self._prev_high + self._prev_low + self._prev_close) / 3.0
self._res1 = 2.0 * self._pivot - self._prev_low
self._sup1 = 2.0 * self._pivot - self._prev_high
self._prev_high = high
self._prev_low = low
if self._pivot > 0 and self._prev_close > 0:
# Cross above pivot => long
if self._prev_close <= self._pivot and close > self._pivot and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Cross below pivot => short
elif self._prev_close >= self._pivot and close < self._pivot and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
# Exit long at resistance or support
elif self.Position > 0 and (close >= self._res1 or close <= self._sup1):
self.SellMarket()
# Exit short at support or resistance
elif self.Position < 0 and (close <= self._sup1 or close >= self._res1):
self.BuyMarket()
self._prev_close = close
def CreateClone(self):
return tcp_pivot_stop_strategy()